diff --git a/02-DECISIONS/0189-the-store-keeps-what-the-records-name.md b/02-DECISIONS/0189-the-store-keeps-what-the-records-name.md index 51b7bdf..5b7b6da 100644 --- a/02-DECISIONS/0189-the-store-keeps-what-the-records-name.md +++ b/02-DECISIONS/0189-the-store-keeps-what-the-records-name.md @@ -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) diff --git a/04-ISSUES/244-a-verb-whose-schema-is-empty-cannot-be-called-through-the-console/00-report.md b/04-ISSUES/244-a-verb-whose-schema-is-empty-cannot-be-called-through-the-console/00-report.md new file mode 100644 index 0000000..862939b --- /dev/null +++ b/04-ISSUES/244-a-verb-whose-schema-is-empty-cannot-be-called-through-the-console/00-report.md @@ -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-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.