@ybotok/loam 0.2.0-alpha.2 → 0.2.0-alpha.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +124 -0
- package/MIGRATING-from-OpenSpec.md +4 -1
- package/README.md +11 -10
- package/ROADMAP.md +103 -17
- package/SCHEMA.md +86 -7
- package/dist/commands/archive/run.js +46 -2
- package/dist/commands/archive/run.js.map +1 -1
- package/dist/commands/seed/plan.js +1 -1
- package/dist/commands/seed/plan.js.map +1 -1
- package/dist/commands/subsystem/sync.js +111 -20
- package/dist/commands/subsystem/sync.js.map +1 -1
- package/dist/commands/subsystem/txn/txn.js +20 -1
- package/dist/commands/subsystem/txn/txn.js.map +1 -1
- package/dist/commands/subsystem/txn/views.js +23 -11
- package/dist/commands/subsystem/txn/views.js.map +1 -1
- package/dist/commands/validate/fleet/landscape.js +6 -0
- package/dist/commands/validate/fleet/landscape.js.map +1 -1
- package/dist/commands/validate/fleet/views/ids.js +6 -1
- package/dist/commands/validate/fleet/views/ids.js.map +1 -1
- package/dist/commands/validate/fleet/views/projects.js +90 -0
- package/dist/commands/validate/fleet/views/projects.js.map +1 -0
- package/dist/commands/validate/fleet/views/stale.js +15 -39
- package/dist/commands/validate/fleet/views/stale.js.map +1 -1
- package/dist/core/agent/agents-md/command-map.js +3 -1
- package/dist/core/agent/agents-md/command-map.js.map +1 -1
- package/dist/core/agent/agents-md/map/subsystem.js +18 -2
- package/dist/core/agent/agents-md/map/subsystem.js.map +1 -1
- package/dist/core/agent/agents-md.js +4 -0
- package/dist/core/agent/agents-md.js.map +1 -1
- package/dist/core/agent/workflows/adopt.js +13 -3
- package/dist/core/agent/workflows/adopt.js.map +1 -1
- package/dist/core/agent/workflows/check.js +1 -0
- package/dist/core/agent/workflows/check.js.map +1 -1
- package/dist/core/brief/checks.js +9 -0
- package/dist/core/brief/checks.js.map +1 -1
- package/dist/core/brief/targets.js +7 -4
- package/dist/core/brief/targets.js.map +1 -1
- package/dist/core/brief/unchecked.js +1 -1
- package/dist/core/brief/unchecked.js.map +1 -1
- package/dist/core/docs.js +11 -7
- package/dist/core/docs.js.map +1 -1
- package/dist/core/doctor/doctor.js +17 -6
- package/dist/core/doctor/doctor.js.map +1 -1
- package/dist/core/explain/families.js +1 -1
- package/dist/core/explain/families.js.map +1 -1
- package/dist/core/repo/paths.js +39 -1
- package/dist/core/repo/paths.js.map +1 -1
- package/dist/core/repo/tree/render/body.js +219 -0
- package/dist/core/repo/tree/render/body.js.map +1 -0
- package/dist/core/repo/tree/render/projects.js +124 -0
- package/dist/core/repo/tree/render/projects.js.map +1 -0
- package/dist/core/repo/tree/render/stale.js +26 -0
- package/dist/core/repo/tree/render/stale.js.map +1 -0
- package/dist/core/repo/tree/render/text.js +84 -0
- package/dist/core/repo/tree/render/text.js.map +1 -0
- package/dist/core/repo/tree/{views.js → render/views.js} +38 -34
- package/dist/core/repo/tree/render/views.js.map +1 -0
- package/examples/README.md +6 -1
- package/examples/docs/architecture/subsystems.likec4 +4 -0
- package/examples/docs/services/checkout-web/likec4.config.json +4 -0
- package/examples/docs/services/order-service/likec4.config.json +4 -0
- package/examples/docs/services/payment-service/likec4.config.json +4 -0
- package/examples/docs/services/payment-service/model.likec4 +4 -2
- package/examples/docs/services/platform/identity-service/likec4.config.json +4 -0
- package/examples/docs/services/platform/notification-service/likec4.config.json +4 -0
- package/package.json +1 -1
- package/dist/core/repo/tree/views.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command-map.js","sourceRoot":"","sources":["../../../../src/core/agent/agents-md/command-map.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;;;;;;;;;CAuB7B,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+B9B,CAAC;AAEF;;;GAGG;AACH,MAAM,SAAS,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BjB,CAAC;AAEF,MAAM,QAAQ,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyJhB,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,SAAS,GAAG,cAAc,GAAG,QAAQ,CAAC","sourcesContent":["/**\n * Reading loam's output, in its two deliveries.\n *\n * {@link READING_OUTPUT} and {@link REFERENCE_PAGES} are what AGENTS.md keeps:\n * the `--json` envelope, the rule to branch on codes rather than prose, and the\n * index of the pages this file no longer carries. {@link CODE_MAP} is the\n * code-by-code map of `status`, `validate`, `doctor`, `rebase`, `dependencies`,\n * `explore`, `seed` and `instructions` — the part `loam instructions loam-codes`\n * prints. ../workflows/reference/codes.ts composes it with `./map/`,\n * `./map/lenses/` and `./refusals.ts`, in exactly the order ../agents-md.ts used\n * to concatenate them, so the assembled page is the section byte for byte.\n *\n * WHY THE MAP LEFT THE FILE, given that this package's whole subject is a file.\n * AGENTS.md is auto-loaded from the working directory by every agents.md-aware\n * host, on every session, and `loam init` writes it once and never refreshes it.\n * It reached 109,399 bytes; Codex truncates the AGENTS.md chain at 32,768 bytes\n * and Windsurf caps a workspace rule file at 12,000 characters, both silently.\n * Roughly seventy percent of the document was being dropped with no error and no\n * way for the reader to tell which half it held — and this section alone was\n * 44,433 of those bytes, 41% of the file. It is also the half a reader consults\n * at a moment it can name (a run reported something) rather than the half it\n * needs to form a question at all, which is what decided which side of the split\n * it went. ../workflows/reference/reference.ts carries the rest of that argument.\n *\n * The move is a move and not a deletion: every byte is still shipped, still in\n * the same corpus test/codes-drift.test.ts reads (AGENTS_MD + PROTOCOLS), and\n * still one command away rather than one file away.\n *\n * WHAT THE MAP IS, AND WHAT IT DELIBERATELY IS NOT. The unique content is which\n * codes which INVOCATION can raise: nothing else in the corpus says that, and an\n * agent choosing what to run needs it. What it does not carry is a per-code\n * gloss of what each code MEANS. That half used to be written twice — once here,\n * once in the /loam-check fix tables — in two independently worded places, in a\n * file `loam init` writes once and never refreshes, so the two drifted with\n * nothing able to say which had rotted. `loam explain <code>` now answers\n * meaning, severity and fix for every code named below, out of the running\n * binary. test/agent-contract.test.ts holds that pointer honest: every code\n * backticked in the corpus must resolve through `explainSubject`, so a family\n * added here without an explanation fails by name. Keep the code list; add the\n * gloss only where it says something `explain` cannot — a condition on when the\n * invocation raises it at all, or a cross-reference between two codes.\n *\n * ONE PARAGRAPH THE MOVE MADE FALSE, and the reason to look for others like it.\n * The `agents.stale` entry read \"one check on this very file … the reason to\n * distrust what you are reading\", which was true while these bytes WERE the\n * scaffolded AGENTS.md. On a page printed by the binary it is exactly backwards\n * — this page cannot be stale, and the file it warns about is somewhere else —\n * so the entry names AGENTS.md instead. A section that talks about its own\n * document does not survive being moved to another one; that is the class to\n * check for whenever anything else leaves this file.\n *\n * READING_OUTPUT and REFERENCE_PAGES are sections of the AGENTS.md template.\n * ../agents-md.ts assembles the document by PLAIN CONCATENATION — no join\n * separator — so every section starts at the first character of its opening line\n * and ends with the newline that closes its last one. Keep that shape when\n * editing, or two sections glue onto one line in every docs repo loam scaffolds\n * from now on. CODE_MAP owes the same shape for the same reason, one level up:\n * reference/codes.ts concatenates it with the modules listed above.\n */\nimport { STATUS_COMMAND } from \"./map/status.js\";\n\n/**\n * The section AGENTS.md keeps. Three facts an agent needs BEFORE it can form a\n * question — that every command speaks JSON, that the envelope survives a bad\n * invocation, and that codes are the contract and prose is not — plus the two\n * places the detail went.\n */\nexport const READING_OUTPUT = `## Reading loam's output\n\nEvery command takes \\`--json\\`, and the envelope holds even when the INVOCATION\nis wrong: with \\`--json\\` anywhere in the arguments, an unknown flag, unknown\ncommand or missing argument still yields \\`{ ok: false, error: { code:\n\"invalid-option\" } }\\` on stdout with exit 1 (commander's own diagnostic goes\nto stderr; \\`--help\\` and \\`--version\\` output pass through untouched). Without\n\\`--json\\` the same refusal is plain text on stderr with nothing on stdout.\n\nBranch on \\`findings[].code\\`, never on the prose — the wording changes, the codes do\nnot.\n\n**What a code MEANS is one command away**, and the answer describes the loam you\nare running rather than the one that scaffolded this repo. \\`loam explain <code>\\`\ngives one code's meaning, its severity in each scope that grades it, and its fix;\n\\`loam explain --codes\\` lists the whole vocabulary and \\`loam explain --codes --json\\`\nis the machine-readable form. Reach for it rather than for a generated pointer:\nthis page is printed by the binary that defines the codes.\n\n**Which codes an INVOCATION can raise** is the other half, and it is the one\nthing nothing else carries. It is a reference page rather than a section here:\n\\`loam instructions loam-codes\\`.\n\n`;\n\n/**\n * The index. A reference nobody can find is content deleted with extra steps,\n * so the exact command is spelled per page rather than described — and\n * test/agents.test.ts asserts that every name in REFERENCES appears here inside\n * its own `loam instructions` line, which is what makes a renamed page fail\n * loudly instead of leaving a pointer at nothing.\n */\nexport const REFERENCE_PAGES = `## The reference pages\n\nThis file is the orientation: the layout, the cycle, what gates and what only\nadvises, and what the words mean. Four things it does NOT carry — the grammars\nyou consult while writing ONE document, and the inventory of what each command\ncan report — are **reference pages**, printed by the binary rather than written\nhere. That is why: this file is auto-loaded on every session and never\nrefreshed, while a page out of the binary describes the loam you are actually\nrunning, and is read at the one moment it is needed.\n\n- \\`loam instructions loam-codes\\` — which codes each invocation can raise:\n \\`validate --service\\` / \\`--feature\\` / \\`--all\\`, \\`status\\`, \\`doctor\\`, \\`gate\\`,\n \\`context\\`, \\`diff\\`, \\`explore\\`, \\`dependencies\\`, \\`rebase\\`, \\`seed\\`, \\`subsystem\\`,\n \\`mcp\\`, the use-case views, the containment refusals, the error envelope, and\n the OpenSpec migration surface.\n- \\`loam instructions loam-spine\\` — the ID spine: every join between the\n artifacts (\\`operationId\\`, message name, \\`Covers:\\`, \\`Requires:\\`,\n \\`Capability:\\`, \\`Realizes:\\`), the \\`Based-On:\\` baseline pins on both the\n requirement and the contract axis, how to draw a shared broker, and how to\n declare a message produced outside the fleet.\n- \\`loam instructions loam-authoring\\` — the grammars you author against:\n the architecture spec axis (\\`arch.spec.md\\` and its \\`Covers:\\` line), the\n generated Gherkin suite, and frontmatter with the vouch chain behind it.\n- \\`loam instructions loam-done-check\\` — the done-check: how \\`loam verify\\`\n derives its claims, the three channels that may answer them, the federated\n recording form, and what separates **verified** from **attested**.\n\nEach takes no arguments and prints whole. \\`loam instructions\\` with no argument\nlists them beside the six workflow protocols; \\`loam explain <code>\\` answers any\nsingle code without opening a page at all.\n\n`;\n\n/**\n * The reference page's own opening: what the map is, where the /loam-check fix\n * tables sit beside it, and the one family `loam explain` cannot answer.\n */\nconst MAP_INTRO = `**What this page is.** It says which codes an INVOCATION can raise. It does\nNOT say what they mean: that half is one command away and describes the loam you\nare running rather than the one that scaffolded this repo. \\`loam explain <code>\\`\ngives one code's meaning, its severity in each scope that grades it, and its fix;\n\\`loam explain --codes\\` lists the whole vocabulary and \\`loam explain --codes --json\\`\nis the machine-readable form. The one family \\`explain\\` does not answer\nis the OpenSpec migration surface (\\`openspec.*\\`, \\`mapping.*\\`) — those commands run\nbefore a repository has a governed loop to look a code up from — so those entries\nalone keep their notes here.\n\nThe code-by-code fix table is a different document again: it lives in the\n\\`/loam-check\\` command \\`loam init\\` lays\ndown. \\`init\\` writes that body twice for every tool it configures: once as a slash\ncommand in the tool's own command directory (you type it), and once as an Agent\nSkill at \\`<tool-dir>/skills/loam-check/SKILL.md\\` (the model loads it by itself when\nthe task matches the skill's description). Same body, two ways in.\n\nWhich tools get them is detected from the repo: \\`loam init\\` scans for the\ndot-directories of the tools it knows (\\`.claude\\`, \\`.cursor\\`, \\`.gemini\\`, …) and\nwrites for the ones it finds, falling back to Claude Code when it finds none.\n\\`loam init --tools <ids|all>\\` overrides the scan — an unknown id is refused\n(\\`invalid-option\\`) rather than skipped — and \\`--no-commands\\` / \\`--no-skills\\`\neach suppress one delivery. The tools written for are recorded in\n\\`loam.json\\` as \\`agentTools\\`, which is how \\`loam doctor\\` tells a file missing\nbecause the binary grew a new command from one missing because nobody ever\nselected that tool.\n\nThe map:\n\n`;\n\nconst MAP_REST = `- \\`loam validate --service <id>\\` grades one service's own axes: \\`service.unknown\\`,\n \\`service.no-model\\`, \\`service.no-spec\\`, \\`service.no-openapi\\`, \\`c4.invalid\\`,\n \\`c4.no-relationships\\`, \\`requirements.missing-scenarios\\`,\n \\`requirements.stepless-scenario\\`, \\`requirements.assertionless-scenario\\`,\n \\`requirements.examples-unbound\\`, \\`requirements.examples-unreferenced\\`,\n \\`spec.merge-conflict\\`, \\`spec.duplicate-requirement\\`, \\`spec.no-requirements\\`,\n \\`spec.repeated-operations\\`, \\`spec.repeated-covers\\`, \\`openapi.invalid\\`,\n \\`openapi.duplicate-operationid\\`, \\`openapi.response-undescribed\\`,\n \\`openapi.ref-unresolved\\`, \\`api.ungoverned\\`, \\`api.ops-unlinked\\`,\n \\`api.requirement-deprecated\\`, \\`spec-api.op-undefined\\`,\n \\`spine.landscape-invalid\\`, \\`spine.op-undefined\\`, \\`spine.op-link-missing\\`,\n \\`spine.op-deprecated\\`; the async contract axis (AsyncAPI 3):\n \\`service.no-asyncapi\\`, \\`asyncapi.invalid\\`, \\`asyncapi.duplicate-message\\`,\n \\`asyncapi.payload-undescribed\\`, \\`asyncapi.ref-unresolved\\`,\n \\`spine.message-undefined\\`, \\`spec-event.message-undefined\\`,\n \\`spine.message-unproduced\\`, \\`spine.message-external\\`,\n \\`asyncapi.message-contested\\`, \\`event.messages-unlinked\\`, \\`event.ungoverned\\`,\n \\`event.covered\\`; and the architecture spec axis: \\`covers.unknown\\`,\n \\`health.invalid\\`, \\`health.uncovered\\`, \\`health.dependency-unmodelled\\`.\n Run inside the service's own repo, once a generated suite exists under\n \\`<gherkinDir>/loam/\\`, it also grades that suite against the living specs:\n \\`gherkin.missing\\`, \\`gherkin.stale\\`, \\`gherkin.orphaned\\`. A service that never\n ran \\`loam gherkin\\` stays quiet — that whole trio is conditional on the suite\n existing here — and a file tagged with a feature still in flight answers to\n that feature, not to the living spec it has not merged into yet.\n- \\`loam validate --feature <id>\\` grades a change's three axes against each other and\n against the fleet in flight: \\`delta.invalid\\`, \\`delta.nothing-tagged\\`,\n \\`delta.service-unknown\\`, \\`delta.service-id-invalid\\`, \\`spec-api.op-undefined\\`,\n \\`spec-api.op-pending\\`, \\`c4-api.op-undefined\\`, \\`c4-api.op-pending\\`,\n \\`c4-api.op-deprecated\\`, \\`c4.op-ungoverned\\`, \\`c4.op-link-missing\\`,\n \\`c4.service-binding-invalid\\`, \\`api.op-unconsumed\\`,\n \\`service.no-requirement-delta\\`, \\`archedge.uncovered\\`, and — the same four\n codes service scope raises, graded here on the feature's own spec.md and\n arch.spec.md deltas, because every one of those breaches merges into the\n living document — \\`spec.repeated-operations\\`, \\`spec.repeated-covers\\`,\n \\`spec.merge-conflict\\` and \\`requirements.stepless-scenario\\`. Then the\n architecture spec axis (\\`c4.uncovered\\`, plus \\`covers.unknown\\` on the\n feature's arch.spec.md deltas), the delta-shape group:\n \\`delta.unknown-section\\`, \\`delta.no-delta-sections\\`,\n \\`delta.requirement-not-merged\\`, \\`delta.modified-unknown\\`, \\`delta.removed-unknown\\`,\n \\`delta.added-duplicate\\`, \\`delta.added-near-duplicate\\`, \\`delta.modified-pending\\`,\n \\`delta.removed-pending\\`, \\`delta.added-conflict\\`, \\`delta.modified-conflict\\`,\n \\`delta.living-duplicate-requirement\\`, and the API-removal group:\n \\`openapi.remove-marker-anonymous\\`, \\`openapi.remove-op-consumed\\`.\n The event axis is graded in feature scope too — the \\`asyncapi.*\\`\n baseline/removal/conflict codes plus \\`c4-event.*\\` and \\`spec-event.*\\`.\n Where a finding names another feature in flight (\\`delta.*-pending\\`,\n \\`delta.added-conflict\\`, \\`delta.modified-conflict\\`, \\`spec-api.op-pending\\`,\n \\`c4-api.op-pending\\`) the ORDER is the answer, and \\`loam dependencies --json\\`\n is what computes it: \\`order\\` is a dependency-first sequence, \\`conflicts\\`\n the pairs no ordering fixes, \\`cycles\\` the ones that need a human.\n- \\`loam validate --all\\` runs both of those for everything and adds the fleet\n cross-check: \\`landscape.missing\\`, \\`landscape.invalid\\`,\n \\`landscape.merge-conflict\\`, \\`landscape.service-unmodelled\\`,\n \\`landscape.service-undocumented\\`, \\`landscape.binding-unknown\\`,\n \\`landscape.binding-duplicate\\`, the fleet-shape advisories\n \\`landscape.platform-candidate\\`, \\`landscape.datastore-private\\` and\n \\`landscape.datastore-shared\\`, \\`service.id-invalid\\` (fleet scope only, and\n graded before the map is opened, so it stands even when the landscape is\n missing or unreadable), a per-service \\`sources.unverifiable-from-here\\`, and\n one check on the docs repo's own AGENTS.md, \\`agents.stale\\`. That last one is\n the reason to distrust THAT file rather than this page: it fires when its\n version stamp on line 1 (\\`<!-- generated by loam vX.Y.Z -->\\`) is missing or\n older than the running binary, which is exactly when what it says may name a\n loam that no longer exists. It is never refreshed automatically — your edits\n outrank the template, so detection is all loam does, and a hand-curated file\n silences it the same way, by keeping the stamp current. This page has no such\n failure mode: it is printed by the binary it describes.\n \\`loam validate --all\\`'s \\`--json\\` payload also carries the additive \\`scorecard\\` key — per-axis ceiling-vs-actual fleet\n aggregates, the text report appending the same table; derived per run and never stored, so week-over-week is the pipeline's job: capture the key per run into a metrics store.\n \\`scorecard.adoption\\` counts the services PARTICIPATING in each contract axis\n (requirements, arch, openapi, asyncapi, permissions, capabilities; the\n denominator is \\`scorecard.services\\`) — an axis at 0 of N reads \"not started\",\n which is expected during staged adoption and distinct from partially adopted.\n Text mode folds the warnings such an axis alone causes under one banner per\n axis and says so; \\`--json\\` carries every finding unchanged, and the summary\n counts, exit codes and \\`--strict\\` are identical either way.\n- \\`loam doctor\\` is read-only local/fleet preflight — the first thing to run in a\n repo that behaves as though the fleet were empty. Every finding carries a\n \\`fix\\` field naming the exact command or edit, so this is the one family you\n rarely need \\`loam explain\\` for. Its blockers are \\`doctor.config-missing\\`,\n \\`doctor.config-invalid\\`, \\`doctor.docs-missing\\`, \\`doctor.services-missing\\`, and\n the three that say the fleet map cannot be read at all —\n \\`doctor.landscape-merge-conflict\\`, \\`doctor.landscape-invalid\\` and\n \\`doctor.landscape-unreadable\\`. It also grades what a WRITE that did not finish\n left in the docs repo, reported as \\`writePath\\` beside the findings:\n \\`doctor.docs-locked\\`, \\`doctor.commit-interrupted\\`, \\`doctor.commit-unreadable\\`\n and \\`doctor.staging-temps\\`. When this repo is a service repo that same scan\n covers \\`<gherkinDir>/loam/\\`, the root \\`loam gherkin\\` commits into.\n Accessibility, portability and incomplete binding stay warnings:\n \\`doctor.docs-unreadable\\`, \\`doctor.docs-readonly\\`, \\`doctor.docs-absolute\\`,\n \\`doctor.inventory-unreadable\\`, \\`doctor.landscape-missing\\`,\n \\`doctor.service-unbound\\` (never raised inside the docs repo itself, where\n having no service binding is the correct state), \\`doctor.service-unknown\\`\n (the same state \\`loam status\\` reports as \\`next.adopt-bound\\`),\n \\`doctor.likec4-config-missing\\`, and the two about this repo's own generated\n command and skill files: \\`doctor.agent-files-missing\\` and\n \\`doctor.agent-files-stale\\`.\n EXPECT the second one on the first \\`loam doctor\\` after an upgrade. It is not\n evidence that anything was edited or broken: staleness reads the version\n stamp only. Re-running \\`loam init\\` refreshes an unchanged pointer only when\n its current bytes still match the digest recorded in \\`loam.json\\`; an\n unrecorded or customized file stays in place for a human to review.\n- \\`loam rebase <FEAT>\\` writes the baseline pins: \\`Based-On:\\` under every\n MODIFIED/REMOVED requirement in the feature's spec deltas, and\n \\`x-loam-based-on\\` on every operation in its openapi.yaml, from the living text\n as it stands right now. Run it when you finish authoring a delta and again\n after you resolve a collision — it is the one mechanism standing between two\n features in flight and silently reverting each other's landed work. It refuses\n rather than inventing a pin, and re-pinning is not resolving: see\n \"The requirement baseline\".\n- \\`loam dependencies [<FEAT>]\\` derives the ordering of the features in flight\n from the artifacts themselves — requirement identities and OpenAPI\n operationIds, never from validator prose. It is the answer to every\n \"another feature in flight does this first\" finding, and to\n \\`delta.added-conflict\\` / \\`delta.modified-conflict\\`, which no ordering fixes.\n- \\`loam explore [<service>...]\\` reads the fleet around a change nobody has\n written down yet, and writes nothing. It exists because \\`loam new\\`'s\n \\`--touches\\` list is the hardest call in the cycle and the only one nothing\n downstream catches: a list short by one service produces a feature that\n validates, archives and ships with a consumer nobody updated. What it derives\n is mechanical — the one-hop ring, each service's rung, its living operations,\n who already calls whom, and which active features cover the same services. It\n does NOT decide which of those neighbours you actually change; that is a\n judgement about intent, and loam does not make those. \\`--op <operationId>\\`\n seeds from the operation's defining service; \\`--capability <id>\\` (repeatable)\n seeds from a declared capability's realizing services, and an id that seeds\n nothing lands in the additive \\`unresolvedCapabilities\\` — beside\n \\`loam list capabilities\\`, the rollup those seeds are read from.\n- \\`loam seed --from fleet.yaml\\` is the onboarding entry point for an empty\n fleet: a tiny human-authored YAML — a \\`services:\\` list of ids, optional\n \\`subsystems:\\`, \\`externals:\\` and \\`calls:\\` lines like\n \\`checkout -> payments\\` — templated mechanically into\n architecture/landscape.likec4 (one bound element per service, plain edges, no\n guessed operationIds) plus one services/<id>/ directory per service, in one\n journaled transaction. Not an extractor: the human stated every fact, and\n \"who calls whom\" is the one thing no generator can read off a repository.\n The seeded landscape carries a line-1 stamp; while it stands unedited,\n editing fleet.yaml and re-running regenerates the map, and the first hand\n edit makes the file yours — seed then refuses \\`seed-landscape-edited\\`\n rather than overwrite. Then adopt each service: \\`loam adopt --service <id>\\`.\n- \\`loam instructions [<page>] [args...]\\` prints one of the six workflow\n protocols — \\`loam-adopt\\`, \\`loam-feature\\`, \\`loam-implement\\`, \\`loam-check\\`,\n \\`loam-verify\\`, \\`loam-ship\\` — with \\`$1\\`, \\`$2\\` filled in from the arguments you\n pass, or one of the four reference pages — \\`loam-codes\\`, \\`loam-spine\\`,\n \\`loam-authoring\\`, \\`loam-done-check\\` — which take no arguments. With no\n argument at all it lists both sets. The pages ship inside the binary, so they\n describe the loam you are about to run rather than the one that scaffolded the\n repository; the command and skill files \\`loam init\\` writes are pointers at it,\n and so is AGENTS.md's own \"The reference pages\" section. It reads no\n \\`loam.json\\` and no docs repo, deliberately: \\`loam-adopt\\`'s own first step is\n to run \\`loam init\\` when there is no config, so it cannot be the step that\n requires one.\n`;\n\n/**\n * The reference page's body, up to the modules that continue it. The bullets\n * are ordered so `status` — the orientation command, the one to run when you\n * have lost the session — is read first.\n */\nexport const CODE_MAP = MAP_INTRO + STATUS_COMMAND + MAP_REST;\n"]}
|
|
1
|
+
{"version":3,"file":"command-map.js","sourceRoot":"","sources":["../../../../src/core/agent/agents-md/command-map.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;;;;;;;;;CAuB7B,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+B9B,CAAC;AAEF;;;GAGG;AACH,MAAM,SAAS,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BjB,CAAC;AAEF,MAAM,QAAQ,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2JhB,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,SAAS,GAAG,cAAc,GAAG,QAAQ,CAAC","sourcesContent":["/**\n * Reading loam's output, in its two deliveries.\n *\n * {@link READING_OUTPUT} and {@link REFERENCE_PAGES} are what AGENTS.md keeps:\n * the `--json` envelope, the rule to branch on codes rather than prose, and the\n * index of the pages this file no longer carries. {@link CODE_MAP} is the\n * code-by-code map of `status`, `validate`, `doctor`, `rebase`, `dependencies`,\n * `explore`, `seed` and `instructions` — the part `loam instructions loam-codes`\n * prints. ../workflows/reference/codes.ts composes it with `./map/`,\n * `./map/lenses/` and `./refusals.ts`, in exactly the order ../agents-md.ts used\n * to concatenate them, so the assembled page is the section byte for byte.\n *\n * WHY THE MAP LEFT THE FILE, given that this package's whole subject is a file.\n * AGENTS.md is auto-loaded from the working directory by every agents.md-aware\n * host, on every session, and `loam init` writes it once and never refreshes it.\n * It reached 109,399 bytes; Codex truncates the AGENTS.md chain at 32,768 bytes\n * and Windsurf caps a workspace rule file at 12,000 characters, both silently.\n * Roughly seventy percent of the document was being dropped with no error and no\n * way for the reader to tell which half it held — and this section alone was\n * 44,433 of those bytes, 41% of the file. It is also the half a reader consults\n * at a moment it can name (a run reported something) rather than the half it\n * needs to form a question at all, which is what decided which side of the split\n * it went. ../workflows/reference/reference.ts carries the rest of that argument.\n *\n * The move is a move and not a deletion: every byte is still shipped, still in\n * the same corpus test/codes-drift.test.ts reads (AGENTS_MD + PROTOCOLS), and\n * still one command away rather than one file away.\n *\n * WHAT THE MAP IS, AND WHAT IT DELIBERATELY IS NOT. The unique content is which\n * codes which INVOCATION can raise: nothing else in the corpus says that, and an\n * agent choosing what to run needs it. What it does not carry is a per-code\n * gloss of what each code MEANS. That half used to be written twice — once here,\n * once in the /loam-check fix tables — in two independently worded places, in a\n * file `loam init` writes once and never refreshes, so the two drifted with\n * nothing able to say which had rotted. `loam explain <code>` now answers\n * meaning, severity and fix for every code named below, out of the running\n * binary. test/agent-contract.test.ts holds that pointer honest: every code\n * backticked in the corpus must resolve through `explainSubject`, so a family\n * added here without an explanation fails by name. Keep the code list; add the\n * gloss only where it says something `explain` cannot — a condition on when the\n * invocation raises it at all, or a cross-reference between two codes.\n *\n * ONE PARAGRAPH THE MOVE MADE FALSE, and the reason to look for others like it.\n * The `agents.stale` entry read \"one check on this very file … the reason to\n * distrust what you are reading\", which was true while these bytes WERE the\n * scaffolded AGENTS.md. On a page printed by the binary it is exactly backwards\n * — this page cannot be stale, and the file it warns about is somewhere else —\n * so the entry names AGENTS.md instead. A section that talks about its own\n * document does not survive being moved to another one; that is the class to\n * check for whenever anything else leaves this file.\n *\n * READING_OUTPUT and REFERENCE_PAGES are sections of the AGENTS.md template.\n * ../agents-md.ts assembles the document by PLAIN CONCATENATION — no join\n * separator — so every section starts at the first character of its opening line\n * and ends with the newline that closes its last one. Keep that shape when\n * editing, or two sections glue onto one line in every docs repo loam scaffolds\n * from now on. CODE_MAP owes the same shape for the same reason, one level up:\n * reference/codes.ts concatenates it with the modules listed above.\n */\nimport { STATUS_COMMAND } from \"./map/status.js\";\n\n/**\n * The section AGENTS.md keeps. Three facts an agent needs BEFORE it can form a\n * question — that every command speaks JSON, that the envelope survives a bad\n * invocation, and that codes are the contract and prose is not — plus the two\n * places the detail went.\n */\nexport const READING_OUTPUT = `## Reading loam's output\n\nEvery command takes \\`--json\\`, and the envelope holds even when the INVOCATION\nis wrong: with \\`--json\\` anywhere in the arguments, an unknown flag, unknown\ncommand or missing argument still yields \\`{ ok: false, error: { code:\n\"invalid-option\" } }\\` on stdout with exit 1 (commander's own diagnostic goes\nto stderr; \\`--help\\` and \\`--version\\` output pass through untouched). Without\n\\`--json\\` the same refusal is plain text on stderr with nothing on stdout.\n\nBranch on \\`findings[].code\\`, never on the prose — the wording changes, the codes do\nnot.\n\n**What a code MEANS is one command away**, and the answer describes the loam you\nare running rather than the one that scaffolded this repo. \\`loam explain <code>\\`\ngives one code's meaning, its severity in each scope that grades it, and its fix;\n\\`loam explain --codes\\` lists the whole vocabulary and \\`loam explain --codes --json\\`\nis the machine-readable form. Reach for it rather than for a generated pointer:\nthis page is printed by the binary that defines the codes.\n\n**Which codes an INVOCATION can raise** is the other half, and it is the one\nthing nothing else carries. It is a reference page rather than a section here:\n\\`loam instructions loam-codes\\`.\n\n`;\n\n/**\n * The index. A reference nobody can find is content deleted with extra steps,\n * so the exact command is spelled per page rather than described — and\n * test/agents.test.ts asserts that every name in REFERENCES appears here inside\n * its own `loam instructions` line, which is what makes a renamed page fail\n * loudly instead of leaving a pointer at nothing.\n */\nexport const REFERENCE_PAGES = `## The reference pages\n\nThis file is the orientation: the layout, the cycle, what gates and what only\nadvises, and what the words mean. Four things it does NOT carry — the grammars\nyou consult while writing ONE document, and the inventory of what each command\ncan report — are **reference pages**, printed by the binary rather than written\nhere. That is why: this file is auto-loaded on every session and never\nrefreshed, while a page out of the binary describes the loam you are actually\nrunning, and is read at the one moment it is needed.\n\n- \\`loam instructions loam-codes\\` — which codes each invocation can raise:\n \\`validate --service\\` / \\`--feature\\` / \\`--all\\`, \\`status\\`, \\`doctor\\`, \\`gate\\`,\n \\`context\\`, \\`diff\\`, \\`explore\\`, \\`dependencies\\`, \\`rebase\\`, \\`seed\\`, \\`subsystem\\`,\n \\`mcp\\`, the use-case views, the containment refusals, the error envelope, and\n the OpenSpec migration surface.\n- \\`loam instructions loam-spine\\` — the ID spine: every join between the\n artifacts (\\`operationId\\`, message name, \\`Covers:\\`, \\`Requires:\\`,\n \\`Capability:\\`, \\`Realizes:\\`), the \\`Based-On:\\` baseline pins on both the\n requirement and the contract axis, how to draw a shared broker, and how to\n declare a message produced outside the fleet.\n- \\`loam instructions loam-authoring\\` — the grammars you author against:\n the architecture spec axis (\\`arch.spec.md\\` and its \\`Covers:\\` line), the\n generated Gherkin suite, and frontmatter with the vouch chain behind it.\n- \\`loam instructions loam-done-check\\` — the done-check: how \\`loam verify\\`\n derives its claims, the three channels that may answer them, the federated\n recording form, and what separates **verified** from **attested**.\n\nEach takes no arguments and prints whole. \\`loam instructions\\` with no argument\nlists them beside the six workflow protocols; \\`loam explain <code>\\` answers any\nsingle code without opening a page at all.\n\n`;\n\n/**\n * The reference page's own opening: what the map is, where the /loam-check fix\n * tables sit beside it, and the one family `loam explain` cannot answer.\n */\nconst MAP_INTRO = `**What this page is.** It says which codes an INVOCATION can raise. It does\nNOT say what they mean: that half is one command away and describes the loam you\nare running rather than the one that scaffolded this repo. \\`loam explain <code>\\`\ngives one code's meaning, its severity in each scope that grades it, and its fix;\n\\`loam explain --codes\\` lists the whole vocabulary and \\`loam explain --codes --json\\`\nis the machine-readable form. The one family \\`explain\\` does not answer\nis the OpenSpec migration surface (\\`openspec.*\\`, \\`mapping.*\\`) — those commands run\nbefore a repository has a governed loop to look a code up from — so those entries\nalone keep their notes here.\n\nThe code-by-code fix table is a different document again: it lives in the\n\\`/loam-check\\` command \\`loam init\\` lays\ndown. \\`init\\` writes that body twice for every tool it configures: once as a slash\ncommand in the tool's own command directory (you type it), and once as an Agent\nSkill at \\`<tool-dir>/skills/loam-check/SKILL.md\\` (the model loads it by itself when\nthe task matches the skill's description). Same body, two ways in.\n\nWhich tools get them is detected from the repo: \\`loam init\\` scans for the\ndot-directories of the tools it knows (\\`.claude\\`, \\`.cursor\\`, \\`.gemini\\`, …) and\nwrites for the ones it finds, falling back to Claude Code when it finds none.\n\\`loam init --tools <ids|all>\\` overrides the scan — an unknown id is refused\n(\\`invalid-option\\`) rather than skipped — and \\`--no-commands\\` / \\`--no-skills\\`\neach suppress one delivery. The tools written for are recorded in\n\\`loam.json\\` as \\`agentTools\\`, which is how \\`loam doctor\\` tells a file missing\nbecause the binary grew a new command from one missing because nobody ever\nselected that tool.\n\nThe map:\n\n`;\n\nconst MAP_REST = `- \\`loam validate --service <id>\\` grades one service's own axes: \\`service.unknown\\`,\n \\`service.no-model\\`, \\`service.no-spec\\`, \\`service.no-openapi\\`, \\`c4.invalid\\`,\n \\`c4.no-relationships\\`, \\`requirements.missing-scenarios\\`,\n \\`requirements.stepless-scenario\\`, \\`requirements.assertionless-scenario\\`,\n \\`requirements.examples-unbound\\`, \\`requirements.examples-unreferenced\\`,\n \\`spec.merge-conflict\\`, \\`spec.duplicate-requirement\\`, \\`spec.no-requirements\\`,\n \\`spec.repeated-operations\\`, \\`spec.repeated-covers\\`, \\`openapi.invalid\\`,\n \\`openapi.duplicate-operationid\\`, \\`openapi.response-undescribed\\`,\n \\`openapi.ref-unresolved\\`, \\`api.ungoverned\\`, \\`api.ops-unlinked\\`,\n \\`api.requirement-deprecated\\`, \\`spec-api.op-undefined\\`,\n \\`spine.landscape-invalid\\`, \\`spine.op-undefined\\`, \\`spine.op-link-missing\\`,\n \\`spine.op-deprecated\\`; the async contract axis (AsyncAPI 3):\n \\`service.no-asyncapi\\`, \\`asyncapi.invalid\\`, \\`asyncapi.duplicate-message\\`,\n \\`asyncapi.payload-undescribed\\`, \\`asyncapi.ref-unresolved\\`,\n \\`spine.message-undefined\\`, \\`spec-event.message-undefined\\`,\n \\`spine.message-unproduced\\`, \\`spine.message-external\\`,\n \\`asyncapi.message-contested\\`, \\`event.messages-unlinked\\`, \\`event.ungoverned\\`,\n \\`event.covered\\`; and the architecture spec axis: \\`covers.unknown\\`,\n \\`health.invalid\\`, \\`health.uncovered\\`, \\`health.dependency-unmodelled\\`.\n Run inside the service's own repo, once a generated suite exists under\n \\`<gherkinDir>/loam/\\`, it also grades that suite against the living specs:\n \\`gherkin.missing\\`, \\`gherkin.stale\\`, \\`gherkin.orphaned\\`. A service that never\n ran \\`loam gherkin\\` stays quiet — that whole trio is conditional on the suite\n existing here — and a file tagged with a feature still in flight answers to\n that feature, not to the living spec it has not merged into yet.\n- \\`loam validate --feature <id>\\` grades a change's three axes against each other and\n against the fleet in flight: \\`delta.invalid\\`, \\`delta.nothing-tagged\\`,\n \\`delta.service-unknown\\`, \\`delta.service-id-invalid\\`, \\`spec-api.op-undefined\\`,\n \\`spec-api.op-pending\\`, \\`c4-api.op-undefined\\`, \\`c4-api.op-pending\\`,\n \\`c4-api.op-deprecated\\`, \\`c4.op-ungoverned\\`, \\`c4.op-link-missing\\`,\n \\`c4.service-binding-invalid\\`, \\`api.op-unconsumed\\`,\n \\`service.no-requirement-delta\\`, \\`archedge.uncovered\\`, and — the same four\n codes service scope raises, graded here on the feature's own spec.md and\n arch.spec.md deltas, because every one of those breaches merges into the\n living document — \\`spec.repeated-operations\\`, \\`spec.repeated-covers\\`,\n \\`spec.merge-conflict\\` and \\`requirements.stepless-scenario\\`. Then the\n architecture spec axis (\\`c4.uncovered\\`, plus \\`covers.unknown\\` on the\n feature's arch.spec.md deltas), the delta-shape group:\n \\`delta.unknown-section\\`, \\`delta.no-delta-sections\\`,\n \\`delta.requirement-not-merged\\`, \\`delta.modified-unknown\\`, \\`delta.removed-unknown\\`,\n \\`delta.added-duplicate\\`, \\`delta.added-near-duplicate\\`, \\`delta.modified-pending\\`,\n \\`delta.removed-pending\\`, \\`delta.added-conflict\\`, \\`delta.modified-conflict\\`,\n \\`delta.living-duplicate-requirement\\`, and the API-removal group:\n \\`openapi.remove-marker-anonymous\\`, \\`openapi.remove-op-consumed\\`.\n The event axis is graded in feature scope too — the \\`asyncapi.*\\`\n baseline/removal/conflict codes plus \\`c4-event.*\\` and \\`spec-event.*\\`.\n Where a finding names another feature in flight (\\`delta.*-pending\\`,\n \\`delta.added-conflict\\`, \\`delta.modified-conflict\\`, \\`spec-api.op-pending\\`,\n \\`c4-api.op-pending\\`) the ORDER is the answer, and \\`loam dependencies --json\\`\n is what computes it: \\`order\\` is a dependency-first sequence, \\`conflicts\\`\n the pairs no ordering fixes, \\`cycles\\` the ones that need a human.\n- \\`loam validate --all\\` runs both of those for everything and adds the fleet\n cross-check: \\`landscape.missing\\`, \\`landscape.invalid\\`,\n \\`landscape.merge-conflict\\`, \\`landscape.service-unmodelled\\`,\n \\`landscape.service-undocumented\\`, \\`landscape.binding-unknown\\`,\n \\`landscape.binding-duplicate\\`, the fleet-shape advisories\n \\`landscape.platform-candidate\\`, \\`landscape.datastore-private\\` and\n \\`landscape.datastore-shared\\`, \\`service.id-invalid\\` (fleet scope only, and\n graded before the map is opened, so it stands even when the landscape is\n missing or unreadable), \\`service.likec4-config-missing\\` (warn, per\n service: a model with no \\`likec4.config.json\\` beside it renders nowhere from\n the docs root — \\`loam subsystem sync\\` writes the file), a per-service \\`sources.unverifiable-from-here\\`, and\n one check on the docs repo's own AGENTS.md, \\`agents.stale\\`. That last one is\n the reason to distrust THAT file rather than this page: it fires when its\n version stamp on line 1 (\\`<!-- generated by loam vX.Y.Z -->\\`) is missing or\n older than the running binary, which is exactly when what it says may name a\n loam that no longer exists. It is never refreshed automatically — your edits\n outrank the template, so detection is all loam does, and a hand-curated file\n silences it the same way, by keeping the stamp current. This page has no such\n failure mode: it is printed by the binary it describes.\n \\`loam validate --all\\`'s \\`--json\\` payload also carries the additive \\`scorecard\\` key — per-axis ceiling-vs-actual fleet\n aggregates, the text report appending the same table; derived per run and never stored, so week-over-week is the pipeline's job: capture the key per run into a metrics store.\n \\`scorecard.adoption\\` counts the services PARTICIPATING in each contract axis\n (requirements, arch, openapi, asyncapi, permissions, capabilities; the\n denominator is \\`scorecard.services\\`) — an axis at 0 of N reads \"not started\",\n which is expected during staged adoption and distinct from partially adopted.\n Text mode folds the warnings such an axis alone causes under one banner per\n axis and says so; \\`--json\\` carries every finding unchanged, and the summary\n counts, exit codes and \\`--strict\\` are identical either way.\n- \\`loam doctor\\` is read-only local/fleet preflight — the first thing to run in a\n repo that behaves as though the fleet were empty. Every finding carries a\n \\`fix\\` field naming the exact command or edit, so this is the one family you\n rarely need \\`loam explain\\` for. Its blockers are \\`doctor.config-missing\\`,\n \\`doctor.config-invalid\\`, \\`doctor.docs-missing\\`, \\`doctor.services-missing\\`, and\n the three that say the fleet map cannot be read at all —\n \\`doctor.landscape-merge-conflict\\`, \\`doctor.landscape-invalid\\` and\n \\`doctor.landscape-unreadable\\`. It also grades what a WRITE that did not finish\n left in the docs repo, reported as \\`writePath\\` beside the findings:\n \\`doctor.docs-locked\\`, \\`doctor.commit-interrupted\\`, \\`doctor.commit-unreadable\\`\n and \\`doctor.staging-temps\\`. When this repo is a service repo that same scan\n covers \\`<gherkinDir>/loam/\\`, the root \\`loam gherkin\\` commits into.\n Accessibility, portability and incomplete binding stay warnings:\n \\`doctor.docs-unreadable\\`, \\`doctor.docs-readonly\\`, \\`doctor.docs-absolute\\`,\n \\`doctor.inventory-unreadable\\`, \\`doctor.landscape-missing\\`,\n \\`doctor.service-unbound\\` (never raised inside the docs repo itself, where\n having no service binding is the correct state), \\`doctor.service-unknown\\`\n (the same state \\`loam status\\` reports as \\`next.adopt-bound\\`),\n \\`doctor.likec4-config-missing\\`, and the two about this repo's own generated\n command and skill files: \\`doctor.agent-files-missing\\` and\n \\`doctor.agent-files-stale\\`.\n EXPECT the second one on the first \\`loam doctor\\` after an upgrade. It is not\n evidence that anything was edited or broken: staleness reads the version\n stamp only. Re-running \\`loam init\\` refreshes an unchanged pointer only when\n its current bytes still match the digest recorded in \\`loam.json\\`; an\n unrecorded or customized file stays in place for a human to review.\n- \\`loam rebase <FEAT>\\` writes the baseline pins: \\`Based-On:\\` under every\n MODIFIED/REMOVED requirement in the feature's spec deltas, and\n \\`x-loam-based-on\\` on every operation in its openapi.yaml, from the living text\n as it stands right now. Run it when you finish authoring a delta and again\n after you resolve a collision — it is the one mechanism standing between two\n features in flight and silently reverting each other's landed work. It refuses\n rather than inventing a pin, and re-pinning is not resolving: see\n \"The requirement baseline\".\n- \\`loam dependencies [<FEAT>]\\` derives the ordering of the features in flight\n from the artifacts themselves — requirement identities and OpenAPI\n operationIds, never from validator prose. It is the answer to every\n \"another feature in flight does this first\" finding, and to\n \\`delta.added-conflict\\` / \\`delta.modified-conflict\\`, which no ordering fixes.\n- \\`loam explore [<service>...]\\` reads the fleet around a change nobody has\n written down yet, and writes nothing. It exists because \\`loam new\\`'s\n \\`--touches\\` list is the hardest call in the cycle and the only one nothing\n downstream catches: a list short by one service produces a feature that\n validates, archives and ships with a consumer nobody updated. What it derives\n is mechanical — the one-hop ring, each service's rung, its living operations,\n who already calls whom, and which active features cover the same services. It\n does NOT decide which of those neighbours you actually change; that is a\n judgement about intent, and loam does not make those. \\`--op <operationId>\\`\n seeds from the operation's defining service; \\`--capability <id>\\` (repeatable)\n seeds from a declared capability's realizing services, and an id that seeds\n nothing lands in the additive \\`unresolvedCapabilities\\` — beside\n \\`loam list capabilities\\`, the rollup those seeds are read from.\n- \\`loam seed --from fleet.yaml\\` is the onboarding entry point for an empty\n fleet: a tiny human-authored YAML — a \\`services:\\` list of ids, optional\n \\`subsystems:\\`, \\`externals:\\` and \\`calls:\\` lines like\n \\`checkout -> payments\\` — templated mechanically into\n architecture/landscape.likec4 (one bound element per service, plain edges, no\n guessed operationIds) plus one services/<id>/ directory per service, in one\n journaled transaction. Not an extractor: the human stated every fact, and\n \"who calls whom\" is the one thing no generator can read off a repository.\n The seeded landscape carries a line-1 stamp; while it stands unedited,\n editing fleet.yaml and re-running regenerates the map, and the first hand\n edit makes the file yours — seed then refuses \\`seed-landscape-edited\\`\n rather than overwrite. Then adopt each service: \\`loam adopt --service <id>\\`.\n- \\`loam instructions [<page>] [args...]\\` prints one of the six workflow\n protocols — \\`loam-adopt\\`, \\`loam-feature\\`, \\`loam-implement\\`, \\`loam-check\\`,\n \\`loam-verify\\`, \\`loam-ship\\` — with \\`$1\\`, \\`$2\\` filled in from the arguments you\n pass, or one of the four reference pages — \\`loam-codes\\`, \\`loam-spine\\`,\n \\`loam-authoring\\`, \\`loam-done-check\\` — which take no arguments. With no\n argument at all it lists both sets. The pages ship inside the binary, so they\n describe the loam you are about to run rather than the one that scaffolded the\n repository; the command and skill files \\`loam init\\` writes are pointers at it,\n and so is AGENTS.md's own \"The reference pages\" section. It reads no\n \\`loam.json\\` and no docs repo, deliberately: \\`loam-adopt\\`'s own first step is\n to run \\`loam init\\` when there is no config, so it cannot be the step that\n requires one.\n`;\n\n/**\n * The reference page's body, up to the modules that continue it. The bullets\n * are ordered so `status` — the orientation command, the one to run when you\n * have lost the session — is read first.\n */\nexport const CODE_MAP = MAP_INTRO + STATUS_COMMAND + MAP_REST;\n"]}
|
|
@@ -25,8 +25,24 @@ export const SUBSYSTEM_COMMANDS = `- \`loam subsystem <verb>\` manages the group
|
|
|
25
25
|
\`unfiledServices\`); \`history <name>\` asks git how a service or subsystem
|
|
26
26
|
moved and answers nothing — exit 0, no finding — when git will not say;
|
|
27
27
|
\`sync\` regenerates \`architecture/subsystems.likec4\`, the one repair for
|
|
28
|
-
\`subsystem.views-stale
|
|
29
|
-
\`
|
|
28
|
+
\`subsystem.views-stale\`, and also writes one create-only
|
|
29
|
+
\`services/<…>/<id>/likec4.config.json\` per service model (never rewritten, never
|
|
30
|
+
removed; the team may edit it; commit the new files before a \`move\`, which
|
|
31
|
+
refuses over untracked paths) — the one thing that makes a model renderable
|
|
32
|
+
from the docs root beside the fleet map, and the repair for
|
|
33
|
+
\`service.likec4-config-missing\`. A flat fleet with no subsystems still owes
|
|
34
|
+
this run: the verb is the tree's, the file is the renderer's. With more than
|
|
35
|
+
one project \`likec4 validate\` at the docs root needs \`--project <name>\`
|
|
36
|
+
(\`build\` and \`export\` take every project); a
|
|
37
|
+
landscape view claiming a generated id is
|
|
38
|
+
\`subsystem.view-id-collision\`. Each generated view is titled by its PATH —
|
|
39
|
+
every marked ancestor's label and its own, which the renderer reads as
|
|
40
|
+
folders — where a label is the marker's \`title\` or the directory name; the
|
|
41
|
+
marker's \`description\` rides along. So editing \`subsystem.yaml\` changes
|
|
42
|
+
what the renderer LABELS the group, a parent's title changes every view
|
|
43
|
+
beneath it, and either makes the file stale until the next \`sync\`. It is generated wholesale:
|
|
44
|
+
an authored diagram of the same services belongs in the landscape or in a
|
|
45
|
+
file of your own name, never here. \`loam adopt --subsystem <name>\` briefs a new
|
|
30
46
|
service's baseline directly into a group, so adoption need not land unfiled.
|
|
31
47
|
`;
|
|
32
48
|
//# sourceMappingURL=subsystem.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subsystem.js","sourceRoot":"","sources":["../../../../../src/core/agent/agents-md/map/subsystem.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG
|
|
1
|
+
{"version":3,"file":"subsystem.js","sourceRoot":"","sources":["../../../../../src/core/agent/agents-md/map/subsystem.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoCjC,CAAC","sourcesContent":["/**\n * The `loam subsystem` half of the command map — its own section module\n * because command-map.ts sat against the file-line limit and the agents-md\n * package against the five-file cap, so the tree surface's documentation\n * lives one package down and is concatenated after the map.\n *\n * Same assembly contract as every section: ../agents-md.ts concatenates with\n * NO join separator, so this string starts at the first character of its\n * opening line and ends with the newline that closes its last one.\n */\nexport const SUBSYSTEM_COMMANDS = `- \\`loam subsystem <verb>\\` manages the grouping tree under \\`services/\\` — the\n navigable tree no identity depends on: a service id stays its leaf directory\n name, every join key is byte-identical before and after a move, and the tree\n carries no policy. Verbs: \\`new <name> [--under <sub>] [--title] [--description]\n [--owner]\\` creates a group (an empty one is legal — its \\`subsystem.yaml\\` is a\n marker, never a member list); \\`move <name>... --into <sub|.>\\` relocates\n services and whole subtrees in ONE journaled transaction over the renames\n plus the regenerated views file (\\`--into .\\` unfiles; the renames and the\n regenerated views file are staged in git without committing, where git answers); \\`rename <old> <new>\\` renames a\n group through the same transaction (services are never renamed — the id is\n the identity); \\`rm <name>\\` removes an EMPTY group; \\`list\\` shows the tree\n with member counts and the unfiled count (unfiled is permanent and normal —\n a count, never a finding; \\`loam list --json\\` carries the same facts as\n additive keys \\`services[].subsystem\\`, \\`subsystems[]\\` and\n \\`unfiledServices\\`); \\`history <name>\\` asks git how a service or subsystem\n moved and answers nothing — exit 0, no finding — when git will not say;\n \\`sync\\` regenerates \\`architecture/subsystems.likec4\\`, the one repair for\n \\`subsystem.views-stale\\`, and also writes one create-only\n \\`services/<…>/<id>/likec4.config.json\\` per service model (never rewritten, never\n removed; the team may edit it; commit the new files before a \\`move\\`, which\n refuses over untracked paths) — the one thing that makes a model renderable\n from the docs root beside the fleet map, and the repair for\n \\`service.likec4-config-missing\\`. A flat fleet with no subsystems still owes\n this run: the verb is the tree's, the file is the renderer's. With more than\n one project \\`likec4 validate\\` at the docs root needs \\`--project <name>\\`\n (\\`build\\` and \\`export\\` take every project); a\n landscape view claiming a generated id is\n \\`subsystem.view-id-collision\\`. Each generated view is titled by its PATH —\n every marked ancestor's label and its own, which the renderer reads as\n folders — where a label is the marker's \\`title\\` or the directory name; the\n marker's \\`description\\` rides along. So editing \\`subsystem.yaml\\` changes\n what the renderer LABELS the group, a parent's title changes every view\n beneath it, and either makes the file stale until the next \\`sync\\`. It is generated wholesale:\n an authored diagram of the same services belongs in the landscape or in a\n file of your own name, never here. \\`loam adopt --subsystem <name>\\` briefs a new\n service's baseline directly into a group, so adoption need not land unfiled.\n`;\n"]}
|
|
@@ -18,6 +18,10 @@ loam has no server or database. Delete it and the documents still make sense.
|
|
|
18
18
|
|
|
19
19
|
\`architecture/landscape.likec4\` is the fleet map, and
|
|
20
20
|
\`architecture/adrs/\` optional system-level decisions — only their links are graded.
|
|
21
|
+
\`architecture/subsystems.likec4\` is GENERATED by \`loam subsystem sync\` from the
|
|
22
|
+
directory tree under \`services/\` — one view per subsystem, a scoping aid, never
|
|
23
|
+
hand-edited and never a second fleet map. A diagram you author belongs in the
|
|
24
|
+
landscape or in a file of your own name beside it.
|
|
21
25
|
\`services/<id>/\` holds a boundary's living \`model.likec4\`, \`spec.md\`,
|
|
22
26
|
\`arch.spec.md\`, OpenAPI, AsyncAPI, runbook and health facts.
|
|
23
27
|
\`features/<FEAT>/\` holds a change in flight: \`intent.md\`, \`delta.likec4\`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents-md.js","sourceRoot":"","sources":["../../../src/core/agent/agents-md.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEtD,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6JnB,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG,GAAG,eAAe,CAAC,YAAY,CAAC,KAAK,WAAW,EAAE,CAAC","sourcesContent":["/**\n * The small, always-loaded orientation contract for a loam docs repository.\n *\n * Detailed grammars and workflows live behind `loam instructions`: those pages\n * describe the binary that is about to run, while this file is written once and\n * may be loaded into every agent turn for years. Keep only enough here to form\n * the next question, find the relevant page, and avoid an unsafe write.\n */\nimport { agentsStampLine } from \"./agents-stamp.js\";\nimport { LOAM_VERSION } from \"../envelope/version.js\";\n\nconst ORIENTATION = `# Working in this docs repo\n\nThis is a **loam** docs repo: plain files are the shared source of truth for a governed software\nfleet's architecture, requirements, contracts and verification evidence. A service may be a modular monolith, a network service, a CLI or a worker.\nloam has no server or database. Delete it and the documents still make sense.\n\n## What is where\n\n\\`architecture/landscape.likec4\\` is the fleet map, and\n\\`architecture/adrs/\\` optional system-level decisions — only their links are graded.\n\\`services/<id>/\\` holds a boundary's living \\`model.likec4\\`, \\`spec.md\\`,\n\\`arch.spec.md\\`, OpenAPI, AsyncAPI, runbook and health facts.\n\\`features/<FEAT>/\\` holds a change in flight: \\`intent.md\\`, \\`delta.likec4\\`,\nper-service requirement and contract deltas, and \\`verification.yaml\\`.\n\\`features/archive/\\` is shipped history.\n\nLiving documents are the complete current state. A feature document is a diff\nagainst them, reviewed as a diff; \\`loam archive\\` folds it into living state.\nDo not hand-edit the living landscape to add a feature change.\n\n## Linking between documents\n\nDocuments join with **standard markdown links** whose targets are real relative\npaths, for example \\`[decision](../adrs/ADR-001.md)\\`. They render in pull-request\nreview instead of showing literal brackets,\nand make “does this link resolve” a filesystem question; \\`[[Wikilinks]]\\` would\nrequire shortest-unique-path guessing.\nObsidian supports markdown links, autocomplete and rename-tracking when its\nwikilink setting is off. \\`link.unresolved\\` grades missing targets and CASE\n**is** graded; links outside this repository, \\`#section\\` targets, a fenced code\nblock or an inline code span are deliberately not graded.\n\n## \\`loam.json\\` — the wiring\n\nEvery repository commits its own \\`loam.json\\`:\n\n\\`{ \"docsDir\": \"../docs\", \"service\": \"payment-service\", \"gherkinDir\": \"features\" }\\`\n\n\\`docsDir\\` is stored exactly as it was passed and resolved against the directory\nholding the \\`loam.json\\`, so a relative path survives a clone; an absolute one\nraises \\`doctor.docs-absolute\\`. \\`service\\` binds a service checkout to the one boundary\nit may write evidence for. \\`gherkinDir\\` is optional. \\`agentTools\\` and\n\\`agentProfile\\` record which agent surfaces and workflow subset init manages;\n\\`agentFiles\\` records digests so unchanged generated pointers can refresh while\ncustomized ones remain untouched. With no config, loam refuses with \\`no-config\\`\nrather than guessing.\n\n\\`loam init --docs <dir>\\` **joins** an existing docs repo. Add \\`--create\\` only\nwhen creating a new one; a typo must not scaffold a second source of truth.\n\n## Starting from chat\n\nThere are two equivalent entry points into the same version-matched protocol.\nPrefer the explicit one when a user wants a predictable lifecycle: invoke\n\\`/loam-feature <FEAT> \"<title>\"\\` to propose, \\`/loam-implement <FEAT> [service]\\`\nto build, \\`/loam-check\\` and \\`/loam-verify <FEAT>\\` to grade it, and\n\\`/loam-ship <FEAT>\\` to finish. Most hosts use that flat slash\nspelling; Gemini uses \\`/loam:feature\\`, Amazon Q uses \\`@loam-feature\\`, and a\nskills-only host can invoke \\`$loam-feature\\`. Natural-language requests may load\nthe matching Agent Skill instead. Once either entry point is selected, the agent\ndrives the internal status/edit/validate loop and asks the user only for a real\ndecision or human-only act; the user does not have to type every loam command.\n\nIf loam or an agent integration behaves unexpectedly, invoke \\`/loam-report\\` (or\nload \\`$loam-report\\` on a skills-only host). It collects a sanitized, reproducible\nMarkdown report under \\`loam-reports/\\` without repairing the repository, retrying a\nwriter or uploading anything. This is support, not a seventh lifecycle step.\n\n## The cycle\n\n0. **Wire the repo** — in each service checkout run\n \\`loam init --docs <path-to-docs-repo> --service <id>\\`, then \\`loam doctor\\`.\n1. **Adopt** — for an undocumented boundary load \\`loam instructions loam-adopt\n <id>\\`, then use \\`loam adopt --service <id> --json\\`. Write drafts; a person,\n never an agent, later vouches for them.\n2. **Understand** — start or resume with \\`loam status --json\\`; its ordered\n \\`next[]\\` is the work queue. Read \\`next[0].execution\\`: run it only when\n \\`runnable\\` is true; otherwise use \\`kind\\`, \\`cwd\\`, \\`needs\\` and \\`after\\`\n to complete the edit or external-repo step. Use \\`loam list --json\\`, \\`loam show <id> --json\\`\n and \\`loam explore <id> --json\\` before proposing a change. Never propose a\n change to a service you have not read.\n3. **Scaffold** — load \\`loam instructions loam-feature <FEAT>\\`, then run\n \\`loam new <FEAT> --title \"...\" --touches <service>\\`.\n4. **Author** — fill the scaffolded TODOs and run \\`loam rebase <FEAT>\\` after\n reading the living baselines. The exact joins and authoring grammars are in\n the reference pages below.\n5. **Check** — load \\`loam instructions loam-check --no-fix-tables\\`, run\n \\`loam validate <FEAT> --json\\`, and use \\`loam explain <code>\\` for reported\n codes. \\`loam dependencies --json\\` names features that must archive first.\n6. **Build** — load \\`loam instructions loam-implement <FEAT>\\`.\n \\`loam delta <FEAT> --service <id> --json\\` is one service's task; in that\n service checkout, \\`loam gherkin <FEAT>\\` emits its executable scenarios.\n7. **Verify** — \\`loam verify <FEAT> --json\\` is the checklist. Record evidence\n from each affected service's own checkout. Read\n \\`loam instructions loam-done-check\\` before recording anything.\n8. **Ship** — load \\`loam instructions loam-ship <FEAT>\\`; begin with\n \\`loam archive <FEAT> --dry-run --json\\`, then archive only after the code is\n merged and the plan is the one reviewed.\n\n## Reading loam's output\n\nEvery command takes \\`--json\\`. The envelope has \\`contractVersion\\`, \\`ok\\` and,\non refusal, \\`error.code\\`. Unknown flags are \\`invalid-option\\`; \\`--help\\` and\n\\`--version\\` pass through. Branch on stable codes, never message prose.\n\nValidation \\`findings[]\\` carry \\`severity\\`; archive-related findings also carry\n\\`gates\\`. Severity and gating are two different questions: errors invalidate,\nwhile \\`gates: true\\` makes archive refuse — archive is gated on coherence, so a\ngating finding stops it whatever its severity. Advisory warnings never block.\n\\`--approve\\` overrides the gating issues — only those that are judgement calls —\nand never a mechanical loss. For example \\`delta.requirement-not-merged\\` warns but gates;\n\\`living.requirement-outside-requirements\\` cannot be approved, while\n\\`openapi.op-modified\\` is reviewable.\n\n\\`loam status --json\\` orders executable next actions. Findings include structured\n\\`locations[]\\`; use their paths instead of extracting filenames from prose.\n\\`loam show <FEAT> --json\\` includes a \\`review\\` pack with intent, architecture,\ncontracts, dependencies, verification, blockers and the same next actions.\n\\`loam explain <code> --json\\`\nreturns one code's meaning and fix; \\`loam explain --codes --json\\` lists them.\nWhich codes an INVOCATION can raise is in \\`loam instructions loam-codes\\`.\n\n## The identity rule\n\nA service is the element whose \\`metadata { service '<id>' }\\` matches its\n\\`services/<id>/\\` directory. An exact element id is the legacy fallback. Never\ninfer identity from display names or containment. Relationships join to contracts\nthrough exact ids: OpenAPI \\`operationId\\`, requirement \\`Operations:\\`, and C4\n\\`metadata { op '...' }\\`. Consult \\`loam instructions loam-spine\\` before editing\na join.\n\n## Reference pages — fetch when needed\n\n- \\`loam instructions loam-codes\\` — finding/refusal inventory and fixes.\n- \\`loam instructions loam-spine\\` — operation, message, coverage, permission,\n capability and baseline joins.\n- \\`loam instructions loam-authoring\\` — arch requirements, generated Gherkin\n and frontmatter/vouch grammar.\n- \\`loam instructions loam-done-check\\` — verification evidence and verdicts.\n\nBare \\`loam instructions\\` lists the six workflows, the separate \\`loam-report\\`\nsupport protocol and these references. Generated agent command/skill files are\nsmall pointers to them, so the runtime page wins if an old pointer disagrees with\nthe installed binary. MCP clients can read the same pages as\n\\`loam://orientation\\` and \\`loam://instructions/<name>\\` resources.\n\n## Safety and hand-back\n\nloam's writers are journaled, but the lifecycle still matters. Do not run\n\\`loam vouch\\` for a human, do not invent evidence, do not archive before code is\nmerged, and do not edit generated files under \\`<gherkinDir>/loam/\\` by hand.\n\\`loam unarchive <FEAT>\\` is the supported undo. To abandon a feature that was\nnever archived, review it and use \\`git rm -r features/<FEAT>\\`; loam deliberately\nhas no destructive drop command.\n\nFinish by reporting remaining warnings, unverifiable claims, files or directories\nyou did not inspect, and the exact human action still owed.\n`;\n\nexport const AGENTS_MD = `${agentsStampLine(LOAM_VERSION)}\\n${ORIENTATION}`;\n"]}
|
|
1
|
+
{"version":3,"file":"agents-md.js","sourceRoot":"","sources":["../../../src/core/agent/agents-md.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEtD,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiKnB,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG,GAAG,eAAe,CAAC,YAAY,CAAC,KAAK,WAAW,EAAE,CAAC","sourcesContent":["/**\n * The small, always-loaded orientation contract for a loam docs repository.\n *\n * Detailed grammars and workflows live behind `loam instructions`: those pages\n * describe the binary that is about to run, while this file is written once and\n * may be loaded into every agent turn for years. Keep only enough here to form\n * the next question, find the relevant page, and avoid an unsafe write.\n */\nimport { agentsStampLine } from \"./agents-stamp.js\";\nimport { LOAM_VERSION } from \"../envelope/version.js\";\n\nconst ORIENTATION = `# Working in this docs repo\n\nThis is a **loam** docs repo: plain files are the shared source of truth for a governed software\nfleet's architecture, requirements, contracts and verification evidence. A service may be a modular monolith, a network service, a CLI or a worker.\nloam has no server or database. Delete it and the documents still make sense.\n\n## What is where\n\n\\`architecture/landscape.likec4\\` is the fleet map, and\n\\`architecture/adrs/\\` optional system-level decisions — only their links are graded.\n\\`architecture/subsystems.likec4\\` is GENERATED by \\`loam subsystem sync\\` from the\ndirectory tree under \\`services/\\` — one view per subsystem, a scoping aid, never\nhand-edited and never a second fleet map. A diagram you author belongs in the\nlandscape or in a file of your own name beside it.\n\\`services/<id>/\\` holds a boundary's living \\`model.likec4\\`, \\`spec.md\\`,\n\\`arch.spec.md\\`, OpenAPI, AsyncAPI, runbook and health facts.\n\\`features/<FEAT>/\\` holds a change in flight: \\`intent.md\\`, \\`delta.likec4\\`,\nper-service requirement and contract deltas, and \\`verification.yaml\\`.\n\\`features/archive/\\` is shipped history.\n\nLiving documents are the complete current state. A feature document is a diff\nagainst them, reviewed as a diff; \\`loam archive\\` folds it into living state.\nDo not hand-edit the living landscape to add a feature change.\n\n## Linking between documents\n\nDocuments join with **standard markdown links** whose targets are real relative\npaths, for example \\`[decision](../adrs/ADR-001.md)\\`. They render in pull-request\nreview instead of showing literal brackets,\nand make “does this link resolve” a filesystem question; \\`[[Wikilinks]]\\` would\nrequire shortest-unique-path guessing.\nObsidian supports markdown links, autocomplete and rename-tracking when its\nwikilink setting is off. \\`link.unresolved\\` grades missing targets and CASE\n**is** graded; links outside this repository, \\`#section\\` targets, a fenced code\nblock or an inline code span are deliberately not graded.\n\n## \\`loam.json\\` — the wiring\n\nEvery repository commits its own \\`loam.json\\`:\n\n\\`{ \"docsDir\": \"../docs\", \"service\": \"payment-service\", \"gherkinDir\": \"features\" }\\`\n\n\\`docsDir\\` is stored exactly as it was passed and resolved against the directory\nholding the \\`loam.json\\`, so a relative path survives a clone; an absolute one\nraises \\`doctor.docs-absolute\\`. \\`service\\` binds a service checkout to the one boundary\nit may write evidence for. \\`gherkinDir\\` is optional. \\`agentTools\\` and\n\\`agentProfile\\` record which agent surfaces and workflow subset init manages;\n\\`agentFiles\\` records digests so unchanged generated pointers can refresh while\ncustomized ones remain untouched. With no config, loam refuses with \\`no-config\\`\nrather than guessing.\n\n\\`loam init --docs <dir>\\` **joins** an existing docs repo. Add \\`--create\\` only\nwhen creating a new one; a typo must not scaffold a second source of truth.\n\n## Starting from chat\n\nThere are two equivalent entry points into the same version-matched protocol.\nPrefer the explicit one when a user wants a predictable lifecycle: invoke\n\\`/loam-feature <FEAT> \"<title>\"\\` to propose, \\`/loam-implement <FEAT> [service]\\`\nto build, \\`/loam-check\\` and \\`/loam-verify <FEAT>\\` to grade it, and\n\\`/loam-ship <FEAT>\\` to finish. Most hosts use that flat slash\nspelling; Gemini uses \\`/loam:feature\\`, Amazon Q uses \\`@loam-feature\\`, and a\nskills-only host can invoke \\`$loam-feature\\`. Natural-language requests may load\nthe matching Agent Skill instead. Once either entry point is selected, the agent\ndrives the internal status/edit/validate loop and asks the user only for a real\ndecision or human-only act; the user does not have to type every loam command.\n\nIf loam or an agent integration behaves unexpectedly, invoke \\`/loam-report\\` (or\nload \\`$loam-report\\` on a skills-only host). It collects a sanitized, reproducible\nMarkdown report under \\`loam-reports/\\` without repairing the repository, retrying a\nwriter or uploading anything. This is support, not a seventh lifecycle step.\n\n## The cycle\n\n0. **Wire the repo** — in each service checkout run\n \\`loam init --docs <path-to-docs-repo> --service <id>\\`, then \\`loam doctor\\`.\n1. **Adopt** — for an undocumented boundary load \\`loam instructions loam-adopt\n <id>\\`, then use \\`loam adopt --service <id> --json\\`. Write drafts; a person,\n never an agent, later vouches for them.\n2. **Understand** — start or resume with \\`loam status --json\\`; its ordered\n \\`next[]\\` is the work queue. Read \\`next[0].execution\\`: run it only when\n \\`runnable\\` is true; otherwise use \\`kind\\`, \\`cwd\\`, \\`needs\\` and \\`after\\`\n to complete the edit or external-repo step. Use \\`loam list --json\\`, \\`loam show <id> --json\\`\n and \\`loam explore <id> --json\\` before proposing a change. Never propose a\n change to a service you have not read.\n3. **Scaffold** — load \\`loam instructions loam-feature <FEAT>\\`, then run\n \\`loam new <FEAT> --title \"...\" --touches <service>\\`.\n4. **Author** — fill the scaffolded TODOs and run \\`loam rebase <FEAT>\\` after\n reading the living baselines. The exact joins and authoring grammars are in\n the reference pages below.\n5. **Check** — load \\`loam instructions loam-check --no-fix-tables\\`, run\n \\`loam validate <FEAT> --json\\`, and use \\`loam explain <code>\\` for reported\n codes. \\`loam dependencies --json\\` names features that must archive first.\n6. **Build** — load \\`loam instructions loam-implement <FEAT>\\`.\n \\`loam delta <FEAT> --service <id> --json\\` is one service's task; in that\n service checkout, \\`loam gherkin <FEAT>\\` emits its executable scenarios.\n7. **Verify** — \\`loam verify <FEAT> --json\\` is the checklist. Record evidence\n from each affected service's own checkout. Read\n \\`loam instructions loam-done-check\\` before recording anything.\n8. **Ship** — load \\`loam instructions loam-ship <FEAT>\\`; begin with\n \\`loam archive <FEAT> --dry-run --json\\`, then archive only after the code is\n merged and the plan is the one reviewed.\n\n## Reading loam's output\n\nEvery command takes \\`--json\\`. The envelope has \\`contractVersion\\`, \\`ok\\` and,\non refusal, \\`error.code\\`. Unknown flags are \\`invalid-option\\`; \\`--help\\` and\n\\`--version\\` pass through. Branch on stable codes, never message prose.\n\nValidation \\`findings[]\\` carry \\`severity\\`; archive-related findings also carry\n\\`gates\\`. Severity and gating are two different questions: errors invalidate,\nwhile \\`gates: true\\` makes archive refuse — archive is gated on coherence, so a\ngating finding stops it whatever its severity. Advisory warnings never block.\n\\`--approve\\` overrides the gating issues — only those that are judgement calls —\nand never a mechanical loss. For example \\`delta.requirement-not-merged\\` warns but gates;\n\\`living.requirement-outside-requirements\\` cannot be approved, while\n\\`openapi.op-modified\\` is reviewable.\n\n\\`loam status --json\\` orders executable next actions. Findings include structured\n\\`locations[]\\`; use their paths instead of extracting filenames from prose.\n\\`loam show <FEAT> --json\\` includes a \\`review\\` pack with intent, architecture,\ncontracts, dependencies, verification, blockers and the same next actions.\n\\`loam explain <code> --json\\`\nreturns one code's meaning and fix; \\`loam explain --codes --json\\` lists them.\nWhich codes an INVOCATION can raise is in \\`loam instructions loam-codes\\`.\n\n## The identity rule\n\nA service is the element whose \\`metadata { service '<id>' }\\` matches its\n\\`services/<id>/\\` directory. An exact element id is the legacy fallback. Never\ninfer identity from display names or containment. Relationships join to contracts\nthrough exact ids: OpenAPI \\`operationId\\`, requirement \\`Operations:\\`, and C4\n\\`metadata { op '...' }\\`. Consult \\`loam instructions loam-spine\\` before editing\na join.\n\n## Reference pages — fetch when needed\n\n- \\`loam instructions loam-codes\\` — finding/refusal inventory and fixes.\n- \\`loam instructions loam-spine\\` — operation, message, coverage, permission,\n capability and baseline joins.\n- \\`loam instructions loam-authoring\\` — arch requirements, generated Gherkin\n and frontmatter/vouch grammar.\n- \\`loam instructions loam-done-check\\` — verification evidence and verdicts.\n\nBare \\`loam instructions\\` lists the six workflows, the separate \\`loam-report\\`\nsupport protocol and these references. Generated agent command/skill files are\nsmall pointers to them, so the runtime page wins if an old pointer disagrees with\nthe installed binary. MCP clients can read the same pages as\n\\`loam://orientation\\` and \\`loam://instructions/<name>\\` resources.\n\n## Safety and hand-back\n\nloam's writers are journaled, but the lifecycle still matters. Do not run\n\\`loam vouch\\` for a human, do not invent evidence, do not archive before code is\nmerged, and do not edit generated files under \\`<gherkinDir>/loam/\\` by hand.\n\\`loam unarchive <FEAT>\\` is the supported undo. To abandon a feature that was\nnever archived, review it and use \\`git rm -r features/<FEAT>\\`; loam deliberately\nhas no destructive drop command.\n\nFinish by reporting remaining warnings, unverifiable claims, files or directories\nyou did not inspect, and the exact human action still owed.\n`;\n\nexport const AGENTS_MD = `${agentsStampLine(LOAM_VERSION)}\\n${ORIENTATION}`;\n"]}
|
|
@@ -10,7 +10,7 @@ export const LOAM_ADOPT = {
|
|
|
10
10
|
"wire this repo (`loam init`, then `loam doctor`) if it has no ./loam.json yet",
|
|
11
11
|
"`loam adopt` — the brief: the order to read the service in, every file to write, the grammar of each, and what the fleet map already says",
|
|
12
12
|
"walk the service in the brief's order — shape first, then one surface at a time — keeping the list of every path you open, because that list becomes `sources`",
|
|
13
|
-
"write the artifacts, everything `status: draft`",
|
|
13
|
+
"write the artifacts, everything `status: draft`, then `loam subsystem sync` for the per-service LikeC4 project file — loam's, never yours",
|
|
14
14
|
"validate the service, then validate the whole fleet — a baseline that passes one and fails the other is documented and invisible",
|
|
15
15
|
"hand back with what you could not determine from the code, which directories you never opened, the branch-to-scenario count per operation, and three behaviours your documents do not describe — then let a human vouch",
|
|
16
16
|
],
|
|
@@ -70,7 +70,14 @@ thin baseline that validates is thin, not done.
|
|
|
70
70
|
tying the document to the repository. Never pad it with paths you did not read:
|
|
71
71
|
it is a record, and \`loam vouch\` hashes exactly what it names.
|
|
72
72
|
3. Write the artifacts under \`services/$1/\`, in the order the brief lists them, and
|
|
73
|
-
make the landscape edit the brief asks for.
|
|
73
|
+
make the landscape edit the brief asks for. Then run \`loam subsystem sync\` (from
|
|
74
|
+
this repo or the docs repo — it resolves \`docsDir\`): once the docs root carries
|
|
75
|
+
the \`likec4.config.json\` step 0's doctor asks for, it writes
|
|
76
|
+
\`services/$1/likec4.config.json\` — and the same file beside any other service
|
|
77
|
+
model in the docs repo still missing one — the LikeC4 project that makes a
|
|
78
|
+
model.likec4 renderable beside the fleet map from the docs root. Those files are
|
|
79
|
+
loam's — never write one yourself, never list it in \`sources\`, never diff it —
|
|
80
|
+
and \`sync\` leaves them untracked for you to commit.
|
|
74
81
|
Everything \`status: draft\`. Never write \`last_verified\`, \`sources_digest\`,
|
|
75
82
|
\`content_digest\` or \`sources_files\`.
|
|
76
83
|
4. \`loam validate --service $1 --json\`. Fix every error. \`sources.unvouched\` is
|
|
@@ -84,8 +91,11 @@ thin baseline that validates is thin, not done.
|
|
|
84
91
|
\`landscape.binding-unknown\` / \`landscape.binding-duplicate\` mean it landed wrong,
|
|
85
92
|
and \`landscape.missing\` means there is no map at all. A baseline that passes step 4
|
|
86
93
|
and fails this one is documented and invisible.
|
|
94
|
+
\`service.likec4-config-missing\` (a warning) means step 3's sync did not run; the
|
|
95
|
+
fix is that command.
|
|
87
96
|
Done, stated once: step 4 clean when run from inside the service's own repo, and
|
|
88
|
-
this run reporting no \`landscape.*\` finding
|
|
97
|
+
this run reporting no \`landscape.*\` finding and no \`service.likec4-config-missing\`.
|
|
98
|
+
The fleet run is never SILENT —
|
|
89
99
|
\`sources.unverifiable-from-here\` (severity ok) appears per service as a
|
|
90
100
|
confirmation, not work — so "keep going until validation is quiet" is the wrong
|
|
91
101
|
loop; the two runs are the test.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adopt.js","sourceRoot":"","sources":["../../../../src/core/agent/workflows/adopt.ts"],"names":[],"mappings":"AAEA,wFAAwF;AACxF,MAAM,CAAC,MAAM,UAAU,GAAmB;IACxC,IAAI,EAAE,YAAY;IAClB,WAAW,EACT,kFAAkF;IACpF,YAAY,EAAE,cAAc;IAC5B,OAAO,EACL,iOAAiO;IACnO,UAAU,EAAE,iCAAiC;IAC7C,YAAY,EAAE,CAAC,SAAS,CAAC;IACzB,KAAK,EAAE;QACL,+EAA+E;QAC/E,2IAA2I;QAC3I,gKAAgK;QAChK,iDAAiD;QACjD,kIAAkI;QAClI,yNAAyN;KAC1N;IACD,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkHP;CACA,CAAC","sourcesContent":["import type { CommandContent } from \"../contract.js\";\n\n/** The adoption protocol: write one service's baseline docs from its code, as draft. */\nexport const LOAM_ADOPT: CommandContent = {\n name: \"loam-adopt\",\n description:\n \"Adopt a service — write its baseline docs from its code, as draft, then validate\",\n argumentHint: \"<service-id>\",\n purpose:\n \"Write one service's baseline documentation into the docs repo from its code, as `draft`. You read the code; loam states the work and checks the result — it never reads the service, so anything you cannot show, do not write.\",\n invocation: \"loam instructions loam-adopt $1\",\n placeholders: [\"service\"],\n spine: [\n \"wire this repo (`loam init`, then `loam doctor`) if it has no ./loam.json yet\",\n \"`loam adopt` — the brief: the order to read the service in, every file to write, the grammar of each, and what the fleet map already says\",\n \"walk the service in the brief's order — shape first, then one surface at a time — keeping the list of every path you open, because that list becomes `sources`\",\n \"write the artifacts, everything `status: draft`\",\n \"validate the service, then validate the whole fleet — a baseline that passes one and fails the other is documented and invisible\",\n \"hand back with what you could not determine from the code, which directories you never opened, the branch-to-scenario count per operation, and three behaviours your documents do not describe — then let a human vouch\",\n ],\n body: `Write one service's baseline documentation into the loam docs repo (its path is\n\\`docsDir\\` in ./loam.json). You read the code; loam states the work and checks the\nresult. It never reads the service — so anything you cannot show, do not write.\n\n**The bar this artifact set aims at is reproducibility**: a reader should be able\nto answer, from these files alone — what this boundary exposes, what it reaches,\nwhat shapes it exchanges, how it is run, and what pages whom — without opening\nthe code. \\`loam validate\\` grades form and joins, never depth: green means the\nfiles agree with each other, and the bar is what \"done\" is measured against — a\nthin baseline that validates is thin, not done.\n\n0. If there is no ./loam.json here, wire the repo first:\n \\`loam init --docs <path-to-docs-repo> --service $1\\` (add \\`--create\\` ONLY if the\n docs repo does not exist yet), then \\`loam doctor\\` — it resolves \\`docsDir\\`,\n checks the docs repo is one, and reports the service binding. Do not go on with\n \\`docs-missing\\`, \\`services-missing\\` or any \\`doctor.*\\` blocker standing.\n Every \\`doctor\\` finding carries a \\`fix\\` field spelling the exact command —\n type that, not an approximation of it.\n If this repo is already wired, \\`loam status --json\\` in the docs repo is the\n fastest way to see whether $1 is even the service that owes work next: its\n \\`next.adopt\\` entries name the services with nothing written down yet.\n1. \\`loam adopt --service $1 --json\\`. That output IS the brief:\n - \\`warnings[]\\` — read these FIRST. A near-miss against an existing service id\n usually means \\`$1\\` is a typo, and a brief followed to the letter then produces\n a complete, validating baseline for a service that does not exist.\n - \\`targets[]\\` — every file to write. \\`action: \"diff\"\\` means the file ALREADY EXISTS:\n read it, diff your findings against it, report what disagrees. Do not replace it.\n \\`action: \"edit\"\\` appears on exactly one target — \\`architecture/landscape.likec4\\`,\n the WHOLE FLEET's map: add this service's element and edges to it, never rewrite it.\n - \\`targets[].shape\\` — the grammar of each artifact, and \\`example\\` where one is\n shorter than a description. Every rule there is one a later check depends on;\n rules nothing checks are in \\`unchecked[]\\` instead, and are still worth following.\n - \\`landscape\\` — the elements and edges the fleet already has for this service.\n Bind to them; do not draw a second version of the same box. \\`landscape.expects\\`\n lists operations other services already call — your openapi.yaml owes them.\n \\`landscape.instruction\\` is the write the fleet map still owes this service; it\n is \\`null\\` once an element resolves to it, and only then.\n - \\`frontmatter\\` — what to put in the header of every markdown artifact.\n - \\`checks[]\\` — what \\`loam validate\\` will run. \\`unchecked[]\\` — what it will not.\n2. Read \\`AGENTS.md\\` at the docs repo root, then walk the service — \\`walk[]\\` in the\n same \\`adopt\\` output is the order, and it is an order, not a menu. Each stop\n names what to open, what to take from it, and which artifacts it feeds\n (\\`lands\\`). The first two stops fix what the service IS — how many processes,\n built from what — before any surface is enumerated: an agent that opens the\n HTTP routes first has already decided the service is an API by the time it\n meets the scheduler, and the consumer group and the outbox never get written\n down. Do not stop at the surface you recognise fastest.\n \\`walkClose\\` is the question that ends it: **list the directories you did not\n open.** Nothing downstream can find a service you documented a third of —\n \\`api.ungoverned\\` grades the operations you WROTE, and is silent about the twelve\n you never did.\n **Keep a list of every path you actually open.** That list becomes \\`sources\\` —\n written as files and directories, never glob patterns — and it is the only line\n tying the document to the repository. Never pad it with paths you did not read:\n it is a record, and \\`loam vouch\\` hashes exactly what it names.\n3. Write the artifacts under \\`services/$1/\\`, in the order the brief lists them, and\n make the landscape edit the brief asks for.\n Everything \\`status: draft\\`. Never write \\`last_verified\\`, \\`sources_digest\\`,\n \\`content_digest\\` or \\`sources_files\\`.\n4. \\`loam validate --service $1 --json\\`. Fix every error. \\`sources.unvouched\\` is\n expected on a fresh baseline — it closes when a person vouches, not when you do.\n \\`sources.unwalked\\` is the walk graded against the repository: its \\`details\\` name\n the top-level paths git tracks and \\`sources\\` never reached into. Treat each one\n as a place to go back to, not as a line to silence — the fix is reading it, or\n one sentence in step 6 saying why this document does not owe it.\n5. \\`loam validate --all --json\\` in the docs repo. This is the run that grades the\n fleet map: \\`landscape.service-unmodelled\\` means the element never landed,\n \\`landscape.binding-unknown\\` / \\`landscape.binding-duplicate\\` mean it landed wrong,\n and \\`landscape.missing\\` means there is no map at all. A baseline that passes step 4\n and fails this one is documented and invisible.\n Done, stated once: step 4 clean when run from inside the service's own repo, and\n this run reporting no \\`landscape.*\\` finding. The fleet run is never SILENT —\n \\`sources.unverifiable-from-here\\` (severity ok) appears per service as a\n confirmation, not work — so \"keep going until validation is quiet\" is the wrong\n loop; the two runs are the test.\n6. Hand back, and say seven things:\n - what you could not determine from the code;\n - what the existing artifacts disagreed with;\n - which parts you are least sure of;\n - what you did not open — every path \\`sources.unwalked\\` named, with one line\n each on why the baseline does not owe it. That list is the only account\n anybody gets of how much of the service was actually read; loam can name the\n paths, and it can never say whether skipping one was right;\n - **two counts per operation**: how many decisions its code makes — permission\n checks, conditionally required fields, defaults and normalisations, refused\n transitions — and how many scenarios you wrote for it.\n \\`12 branches / 3 scenarios\\` is a fact a reader can act on; \"the\n requirements look complete\" is not, and no check loam has can tell the two\n apart;\n - **how well this service is covered by its own tests**, and how many of them\n became scenarios. Say the number the service's own coverage tooling\n reports, and where you read it. This is the ceiling on the whole baseline:\n a well-covered service can be documented from evidence, and a service with\n almost no tests can only be documented from a reading of its code, which is\n a weaker document however carefully it is written. Nothing in loam can\n compute this — say it, or nobody ever knows which kind they are holding;\n - **three behaviours this service has that your documents do not describe.**\n Not \"is this enough\" — that question is answered yes by every agent that\n ever wrote a baseline, including the ones that documented a third of a\n service, because the only thing it can be answered against is the document\n itself. Name three. If you looked for three and found none, say exactly\n that: it is a claim a reviewer can go and check, which \"it is complete\"\n is not.\n Then a human runs \\`loam vouch --service $1\\` in the service's own repo.\n\nAn empty docs repo's \\`loam status --json\\` names this recipe's own states as its\nfirst-hour ladder: \\`next.author-landscape\\` (the fleet map is missing, or still the\nscaffold's untouched bytes — step 3's landscape edit is what discharges it),\n\\`next.bind-service\\` (no service repository is wired to the fleet yet — step 0) and\n\\`next.adopt-first\\` (services/ is empty — this protocol, from step 1). Landing on\none of those codes means: run this recipe, starting at the step it points at.\n\nWhere the code does not say, write that it does not say. A confident sentence about\nbehaviour nobody can find is the one failure mode none of loam's checks can catch.\n`,\n};\n"]}
|
|
1
|
+
{"version":3,"file":"adopt.js","sourceRoot":"","sources":["../../../../src/core/agent/workflows/adopt.ts"],"names":[],"mappings":"AAEA,wFAAwF;AACxF,MAAM,CAAC,MAAM,UAAU,GAAmB;IACxC,IAAI,EAAE,YAAY;IAClB,WAAW,EACT,kFAAkF;IACpF,YAAY,EAAE,cAAc;IAC5B,OAAO,EACL,iOAAiO;IACnO,UAAU,EAAE,iCAAiC;IAC7C,YAAY,EAAE,CAAC,SAAS,CAAC;IACzB,KAAK,EAAE;QACL,+EAA+E;QAC/E,2IAA2I;QAC3I,gKAAgK;QAChK,2IAA2I;QAC3I,kIAAkI;QAClI,yNAAyN;KAC1N;IACD,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4HP;CACA,CAAC","sourcesContent":["import type { CommandContent } from \"../contract.js\";\n\n/** The adoption protocol: write one service's baseline docs from its code, as draft. */\nexport const LOAM_ADOPT: CommandContent = {\n name: \"loam-adopt\",\n description:\n \"Adopt a service — write its baseline docs from its code, as draft, then validate\",\n argumentHint: \"<service-id>\",\n purpose:\n \"Write one service's baseline documentation into the docs repo from its code, as `draft`. You read the code; loam states the work and checks the result — it never reads the service, so anything you cannot show, do not write.\",\n invocation: \"loam instructions loam-adopt $1\",\n placeholders: [\"service\"],\n spine: [\n \"wire this repo (`loam init`, then `loam doctor`) if it has no ./loam.json yet\",\n \"`loam adopt` — the brief: the order to read the service in, every file to write, the grammar of each, and what the fleet map already says\",\n \"walk the service in the brief's order — shape first, then one surface at a time — keeping the list of every path you open, because that list becomes `sources`\",\n \"write the artifacts, everything `status: draft`, then `loam subsystem sync` for the per-service LikeC4 project file — loam's, never yours\",\n \"validate the service, then validate the whole fleet — a baseline that passes one and fails the other is documented and invisible\",\n \"hand back with what you could not determine from the code, which directories you never opened, the branch-to-scenario count per operation, and three behaviours your documents do not describe — then let a human vouch\",\n ],\n body: `Write one service's baseline documentation into the loam docs repo (its path is\n\\`docsDir\\` in ./loam.json). You read the code; loam states the work and checks the\nresult. It never reads the service — so anything you cannot show, do not write.\n\n**The bar this artifact set aims at is reproducibility**: a reader should be able\nto answer, from these files alone — what this boundary exposes, what it reaches,\nwhat shapes it exchanges, how it is run, and what pages whom — without opening\nthe code. \\`loam validate\\` grades form and joins, never depth: green means the\nfiles agree with each other, and the bar is what \"done\" is measured against — a\nthin baseline that validates is thin, not done.\n\n0. If there is no ./loam.json here, wire the repo first:\n \\`loam init --docs <path-to-docs-repo> --service $1\\` (add \\`--create\\` ONLY if the\n docs repo does not exist yet), then \\`loam doctor\\` — it resolves \\`docsDir\\`,\n checks the docs repo is one, and reports the service binding. Do not go on with\n \\`docs-missing\\`, \\`services-missing\\` or any \\`doctor.*\\` blocker standing.\n Every \\`doctor\\` finding carries a \\`fix\\` field spelling the exact command —\n type that, not an approximation of it.\n If this repo is already wired, \\`loam status --json\\` in the docs repo is the\n fastest way to see whether $1 is even the service that owes work next: its\n \\`next.adopt\\` entries name the services with nothing written down yet.\n1. \\`loam adopt --service $1 --json\\`. That output IS the brief:\n - \\`warnings[]\\` — read these FIRST. A near-miss against an existing service id\n usually means \\`$1\\` is a typo, and a brief followed to the letter then produces\n a complete, validating baseline for a service that does not exist.\n - \\`targets[]\\` — every file to write. \\`action: \"diff\"\\` means the file ALREADY EXISTS:\n read it, diff your findings against it, report what disagrees. Do not replace it.\n \\`action: \"edit\"\\` appears on exactly one target — \\`architecture/landscape.likec4\\`,\n the WHOLE FLEET's map: add this service's element and edges to it, never rewrite it.\n - \\`targets[].shape\\` — the grammar of each artifact, and \\`example\\` where one is\n shorter than a description. Every rule there is one a later check depends on;\n rules nothing checks are in \\`unchecked[]\\` instead, and are still worth following.\n - \\`landscape\\` — the elements and edges the fleet already has for this service.\n Bind to them; do not draw a second version of the same box. \\`landscape.expects\\`\n lists operations other services already call — your openapi.yaml owes them.\n \\`landscape.instruction\\` is the write the fleet map still owes this service; it\n is \\`null\\` once an element resolves to it, and only then.\n - \\`frontmatter\\` — what to put in the header of every markdown artifact.\n - \\`checks[]\\` — what \\`loam validate\\` will run. \\`unchecked[]\\` — what it will not.\n2. Read \\`AGENTS.md\\` at the docs repo root, then walk the service — \\`walk[]\\` in the\n same \\`adopt\\` output is the order, and it is an order, not a menu. Each stop\n names what to open, what to take from it, and which artifacts it feeds\n (\\`lands\\`). The first two stops fix what the service IS — how many processes,\n built from what — before any surface is enumerated: an agent that opens the\n HTTP routes first has already decided the service is an API by the time it\n meets the scheduler, and the consumer group and the outbox never get written\n down. Do not stop at the surface you recognise fastest.\n \\`walkClose\\` is the question that ends it: **list the directories you did not\n open.** Nothing downstream can find a service you documented a third of —\n \\`api.ungoverned\\` grades the operations you WROTE, and is silent about the twelve\n you never did.\n **Keep a list of every path you actually open.** That list becomes \\`sources\\` —\n written as files and directories, never glob patterns — and it is the only line\n tying the document to the repository. Never pad it with paths you did not read:\n it is a record, and \\`loam vouch\\` hashes exactly what it names.\n3. Write the artifacts under \\`services/$1/\\`, in the order the brief lists them, and\n make the landscape edit the brief asks for. Then run \\`loam subsystem sync\\` (from\n this repo or the docs repo — it resolves \\`docsDir\\`): once the docs root carries\n the \\`likec4.config.json\\` step 0's doctor asks for, it writes\n \\`services/$1/likec4.config.json\\` — and the same file beside any other service\n model in the docs repo still missing one — the LikeC4 project that makes a\n model.likec4 renderable beside the fleet map from the docs root. Those files are\n loam's — never write one yourself, never list it in \\`sources\\`, never diff it —\n and \\`sync\\` leaves them untracked for you to commit.\n Everything \\`status: draft\\`. Never write \\`last_verified\\`, \\`sources_digest\\`,\n \\`content_digest\\` or \\`sources_files\\`.\n4. \\`loam validate --service $1 --json\\`. Fix every error. \\`sources.unvouched\\` is\n expected on a fresh baseline — it closes when a person vouches, not when you do.\n \\`sources.unwalked\\` is the walk graded against the repository: its \\`details\\` name\n the top-level paths git tracks and \\`sources\\` never reached into. Treat each one\n as a place to go back to, not as a line to silence — the fix is reading it, or\n one sentence in step 6 saying why this document does not owe it.\n5. \\`loam validate --all --json\\` in the docs repo. This is the run that grades the\n fleet map: \\`landscape.service-unmodelled\\` means the element never landed,\n \\`landscape.binding-unknown\\` / \\`landscape.binding-duplicate\\` mean it landed wrong,\n and \\`landscape.missing\\` means there is no map at all. A baseline that passes step 4\n and fails this one is documented and invisible.\n \\`service.likec4-config-missing\\` (a warning) means step 3's sync did not run; the\n fix is that command.\n Done, stated once: step 4 clean when run from inside the service's own repo, and\n this run reporting no \\`landscape.*\\` finding and no \\`service.likec4-config-missing\\`.\n The fleet run is never SILENT —\n \\`sources.unverifiable-from-here\\` (severity ok) appears per service as a\n confirmation, not work — so \"keep going until validation is quiet\" is the wrong\n loop; the two runs are the test.\n6. Hand back, and say seven things:\n - what you could not determine from the code;\n - what the existing artifacts disagreed with;\n - which parts you are least sure of;\n - what you did not open — every path \\`sources.unwalked\\` named, with one line\n each on why the baseline does not owe it. That list is the only account\n anybody gets of how much of the service was actually read; loam can name the\n paths, and it can never say whether skipping one was right;\n - **two counts per operation**: how many decisions its code makes — permission\n checks, conditionally required fields, defaults and normalisations, refused\n transitions — and how many scenarios you wrote for it.\n \\`12 branches / 3 scenarios\\` is a fact a reader can act on; \"the\n requirements look complete\" is not, and no check loam has can tell the two\n apart;\n - **how well this service is covered by its own tests**, and how many of them\n became scenarios. Say the number the service's own coverage tooling\n reports, and where you read it. This is the ceiling on the whole baseline:\n a well-covered service can be documented from evidence, and a service with\n almost no tests can only be documented from a reading of its code, which is\n a weaker document however carefully it is written. Nothing in loam can\n compute this — say it, or nobody ever knows which kind they are holding;\n - **three behaviours this service has that your documents do not describe.**\n Not \"is this enough\" — that question is answered yes by every agent that\n ever wrote a baseline, including the ones that documented a third of a\n service, because the only thing it can be answered against is the document\n itself. Name three. If you looked for three and found none, say exactly\n that: it is a claim a reviewer can go and check, which \"it is complete\"\n is not.\n Then a human runs \\`loam vouch --service $1\\` in the service's own repo.\n\nAn empty docs repo's \\`loam status --json\\` names this recipe's own states as its\nfirst-hour ladder: \\`next.author-landscape\\` (the fleet map is missing, or still the\nscaffold's untouched bytes — step 3's landscape edit is what discharges it),\n\\`next.bind-service\\` (no service repository is wired to the fleet yet — step 0) and\n\\`next.adopt-first\\` (services/ is empty — this protocol, from step 1). Landing on\none of those codes means: run this recipe, starting at the step it points at.\n\nWhere the code does not say, write that it does not say. A confident sentence about\nbehaviour nobody can find is the one failure mode none of loam's checks can catch.\n`,\n};\n"]}
|
|
@@ -240,6 +240,7 @@ what lets a feature ship:
|
|
|
240
240
|
| \`subsystem.name-invalid\` | a subsystem directory name that breaks the id grammar (a space, a \`..\`, a Windows-reserved stem, a trailing dot) — subsystem names take the service-id grammar because both become directory names in one shared tree. Its services stay enumerated meanwhile | rename the directory to a legal name |
|
|
241
241
|
| \`subsystem.invalid\` | a \`subsystem.yaml\` that exists but cannot be read as subsystem metadata — presence still classifies the directory as a subsystem (content is metadata, never identity), and exactly one finding is emitted per file | fix the file: a YAML mapping with optional \`title\`, \`description\` and \`owner\`; never \`members\` — the directory itself is the membership record. An empty file is also a valid marker |
|
|
242
242
|
| \`subsystem.views-stale\` | \`architecture/subsystems.likec4\` — the GENERATED file holding one LikeC4 view per subsystem — does not match the tree: it drifted after a move, it is absent while subsystems exist, or it lingers after the last subsystem was removed. One error on one file, graded by byte comparison against the deterministic re-render (no check ever reads the file's content) | run \`loam subsystem sync\` — the single regenerator. Never edit the file by hand; authored views belong in the landscape or a file of your own |
|
|
243
|
+
| \`service.likec4-config-missing\` (warn) | a \`services/<…>/<id>/model.likec4\` with no \`likec4.config.json\` beside it — the root LikeC4 project excludes \`services/**\`, so a model renders only as a project of its own, and this one has none: a box on the fleet map with nothing renderable inside it. One warning per service, on the fleet target, only when the root \`likec4.config.json\` exists (\`loam doctor\` prints that one); never gating, because no loam check reads the model any differently | run \`loam subsystem sync\` — it creates the file (create-only: a file that already exists is yours and is never touched). Never hand-write it; the bytes are a function of the service id, and the writer spells them once |
|
|
243
244
|
| \`subsystem.view-id-collision\` | \`architecture/landscape.likec4\` declares a view whose id is one loam GENERATES into \`architecture/subsystems.likec4\`. LikeC4 merges every file in \`architecture/\` into one project and view ids are a flat namespace there, so the renderer refuses the WHOLE project and draws nothing — while every other check here stays green. Only a real collision is reported: a \`subsystem_\`-looking id matching no current subsystem breaks nothing yet, and fires on the run after somebody creates that subsystem | rename the view in \`architecture/landscape.likec4\`. Ids beginning \`subsystem_\` are loam's to mint; \`architecture/subsystems.likec4\` is generated (\`loam subsystem sync\`) and is never hand-edited |
|
|
244
245
|
| \`landscape.merge-conflict\` | the fleet map still holds conflict markers — it is two halves of two different maps, and every cross-service check reads it. Checked BEFORE the parse and returns like \`landscape.invalid\`: nothing is concluded from the file, so no \`landscape.service-unmodelled\` fires behind it | resolve it keeping BOTH sides' elements and edges; ten people adopting ten services into one landscape.likec4 in the same week is how it happens. \`loam archive\` refuses on it too (\`merge-failed\`, not overridable with \`--approve\`) |
|
|
245
246
|
| \`landscape.service-unmodelled\` | a \`services/<svc>/\` no element in the landscape resolves to | draw it, or bind an existing element with \`metadata { service '<svc>' }\` — the fleet map is incomplete until you do |
|