ADR 0189 collects again; issue 244: a verb with an empty schema cannot be called
The nightly collector is back on the store (mesh-catalog#57). It was out for a day because while-stopped named the module-local id and the host refuses a declaration naming a container it does not have, whole; the namespacing was fixed the same night and the composition was read before anything was sent this time — plan's distribution.collect shows while-stopped as distribution.store. novox applied it with no refusal and the registry was untouched. The store is 40G at 14:37, the filesystem 56% full; the collector first fires at 03:30. Deleting a manifest frees no bytes until then, so that is the number to read against. 244: mesh-controller.plan and .node publish an empty schema and then refuse with 'needs node', including when node is passed — the console drops what the schema does not declare. A tool that cannot be called is worse than one that is absent, because it is listed. Worked around through the login shell, which is the path the console exists to replace.
This commit is contained in:
@@ -132,6 +132,34 @@ unreferenced.
|
||||
asserted is the decision and not the registry's behaviour.
|
||||
- Live: the store's size before and after the first nightly collection, read from the machine.
|
||||
|
||||
## Built, withdrawn, and collecting again — 2026-10-04 and 05
|
||||
|
||||
**Both halves are live.** The mesh has been deciding since 2026-10-04: the sweep deletes the
|
||||
manifests no record names, after each build it recorded, bounded to two hundred artifacts and
|
||||
sixty seconds so no one waits on it. Its first run let go of two hundred and reported one thousand
|
||||
one hundred and twenty-six left.
|
||||
|
||||
**The nightly collector was withdrawn for a day, and this is why.** `while-stopped` named the
|
||||
module-local id, `store`, while the machine's container is `distribution.store` — a module names
|
||||
its own resources locally and a declaration names them under the module, which `restart-on` and
|
||||
`reload-on` are rewritten for and this field was not. The host refuses a declaration naming a
|
||||
container it does not have **whole**, so the control machine took nothing at all until the step
|
||||
came out. The namespacing was fixed the same night (mesh-controller#259) and the step is back
|
||||
(mesh-catalog#57).
|
||||
|
||||
**The lesson is about where a test stands, not about the field.** Both sides passed throughout:
|
||||
the controller's tests read manifests, the host's read hand-written declarations with bare ids,
|
||||
and nothing composed one and judged the result against what the host accepts. The test that does
|
||||
now exists, and it is the one that would have caught this in a second.
|
||||
|
||||
**And this time the composition was read before anything was sent** — `plan`'s
|
||||
`distribution.collect` showing `while-stopped: ["distribution.store"]` — which is the check whose
|
||||
absence caused the outage.
|
||||
|
||||
*Where it stands for the live measurement:* at 2026-10-05 14:37 CEST the store is **40G**, the
|
||||
machine's filesystem 1.1T used of 2.0T, 56%. The collector first fires at 03:30 the following
|
||||
morning. Deleting a manifest frees no bytes until it does, so that is the number to read against.
|
||||
|
||||
## References
|
||||
|
||||
- [issue 108 — the registry has no garbage collection](../04-ISSUES/108-the-registry-has-no-garbage-collection-once-it-has-two-doors/00-report.md)
|
||||
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
---
|
||||
status: open
|
||||
opened: 2026-10-05
|
||||
located-in: [mesh-tools, mesh-controller]
|
||||
fixed-by:
|
||||
amended-design:
|
||||
---
|
||||
|
||||
# 244 — A verb whose published schema is empty cannot be called through the console, and says only that it needs the argument it will not take
|
||||
|
||||
## What was observed
|
||||
|
||||
Through the console, 2026-10-05, composing one machine's declaration before pushing it:
|
||||
|
||||
```
|
||||
mesh_describe mesh-controller.plan
|
||||
→ {"properties": {}, "type": "object"} ... it takes nothing
|
||||
|
||||
mesh_call mesh-controller.plan {}
|
||||
→ plan failed: plan needs "node" ... it takes something
|
||||
|
||||
mesh_call mesh-controller.plan {"node": "novox"}
|
||||
→ plan failed: plan needs "node" ... and not that
|
||||
```
|
||||
|
||||
`mesh-controller.node` describes the same way and behaves the same way. Both are listed in the
|
||||
node's own instructions as the mesh's verbs, so they are the first thing a session reaches for.
|
||||
|
||||
The verb is not broken where it runs: the same `plan novox --json` through the machine's login
|
||||
shell answers in full. What cannot be done is calling it **through the console**, which the
|
||||
node's instructions say is the only way to the mesh.
|
||||
|
||||
## Why
|
||||
|
||||
Not diagnosed past the symptom, and the symptom is specific enough to place it: the published
|
||||
schema declares no properties, and an argument that is not in the schema does not reach the verb.
|
||||
So the verb reports a missing argument that the console has dropped, every time, whatever is
|
||||
sent. The two halves are each defensible — publish a schema, honour it — and together they make
|
||||
a verb that can only refuse.
|
||||
|
||||
## Why it matters beyond this instance
|
||||
|
||||
**A tool that cannot be called is worse than one that is absent**, because it is listed. It
|
||||
appears in `mesh_overview`, it describes itself, and the only thing it will say is that it wants
|
||||
something it will not accept. A reader has no way to tell that from their own mistake, and the
|
||||
obvious next move — pass the argument it names — is the one that does not work.
|
||||
|
||||
It also marks what the console does not check. Nothing compares a verb's published schema against
|
||||
the arguments the verb actually requires, so a verb can be published in a shape that makes it
|
||||
uncallable and nothing says so. That is the shape of an unenforced rule: the schema is believed,
|
||||
and it is wrong.
|
||||
|
||||
## What a fix has to settle
|
||||
|
||||
- Where the schema for a seat's verbs comes from, and why these two publish an empty one while
|
||||
the verbs beside them (`status`, `builds`, `push`) take their arguments and answer.
|
||||
- Whether the console should refuse to publish a verb whose schema cannot satisfy it, rather than
|
||||
listing one that can only fail.
|
||||
- **How it is checked:** every verb the console lists is callable with the arguments its own
|
||||
schema describes — a test that calls each with its schema's required set and asserts the answer
|
||||
is not "needs" an argument the schema does not have.
|
||||
|
||||
## Worked around, for now
|
||||
|
||||
Through `<node>/node-login-shell.execute`, running the controller's own command line on the
|
||||
machine. That is the path the console exists to replace, so it is a workaround and not an answer.
|
||||
Reference in New Issue
Block a user