@ybotok/loam 0.2.0-alpha.6 → 0.2.0-alpha.7
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 +162 -0
- package/README.md +4 -4
- package/ROADMAP.md +27 -6
- package/SCHEMA.md +152 -32
- package/dist/commands/archive/run.js +49 -22
- package/dist/commands/archive/run.js.map +1 -1
- package/dist/commands/seed/commit.js +34 -1
- package/dist/commands/seed/commit.js.map +1 -1
- package/dist/commands/seed/plan.js +64 -13
- package/dist/commands/seed/plan.js.map +1 -1
- package/dist/commands/subsystem/edit.js +4 -2
- package/dist/commands/subsystem/edit.js.map +1 -1
- package/dist/commands/subsystem/move.js +55 -17
- package/dist/commands/subsystem/move.js.map +1 -1
- package/dist/commands/subsystem/sync.js +142 -45
- package/dist/commands/subsystem/sync.js.map +1 -1
- package/dist/commands/subsystem/txn/report.js +55 -5
- package/dist/commands/subsystem/txn/report.js.map +1 -1
- package/dist/commands/subsystem/txn/txn.js +118 -21
- package/dist/commands/subsystem/txn/txn.js.map +1 -1
- package/dist/commands/subsystem/txn/views.js +51 -8
- package/dist/commands/subsystem/txn/views.js.map +1 -1
- package/dist/commands/validate/checks/health-deps.js +9 -6
- package/dist/commands/validate/checks/health-deps.js.map +1 -1
- package/dist/commands/validate/fleet/census.js +26 -3
- package/dist/commands/validate/fleet/census.js.map +1 -1
- package/dist/commands/validate/fleet/landscape.js +12 -9
- package/dist/commands/validate/fleet/landscape.js.map +1 -1
- package/dist/commands/validate/fleet/map/attest.js +4 -5
- package/dist/commands/validate/fleet/map/attest.js.map +1 -1
- package/dist/commands/validate/fleet/map/bindings.js +15 -2
- package/dist/commands/validate/fleet/map/bindings.js.map +1 -1
- package/dist/commands/validate/fleet/map/consumers.js +43 -122
- package/dist/commands/validate/fleet/map/consumers.js.map +1 -1
- package/dist/commands/validate/fleet/scorecard/scorecard.js.map +1 -1
- package/dist/commands/validate/fleet/views/fleet-project.js +1 -1
- package/dist/commands/validate/fleet/views/fleet-project.js.map +1 -1
- package/dist/commands/validate/fleet/views/ids.js +33 -7
- package/dist/commands/validate/fleet/views/ids.js.map +1 -1
- package/dist/commands/validate/fleet/views/root-documents.js +9 -7
- package/dist/commands/validate/fleet/views/root-documents.js.map +1 -1
- package/dist/commands/validate/fleet/views/stale.js +31 -14
- package/dist/commands/validate/fleet/views/stale.js.map +1 -1
- package/dist/core/agent/agents-md/command-map.js +1 -1
- package/dist/core/agent/agents-md/command-map.js.map +1 -1
- package/dist/core/agent/agents-md/map/subsystem.js +27 -14
- package/dist/core/agent/agents-md/map/subsystem.js.map +1 -1
- package/dist/core/agent/agents-md/refusals.js +5 -3
- package/dist/core/agent/agents-md/refusals.js.map +1 -1
- package/dist/core/agent/agents-md.js +16 -7
- package/dist/core/agent/agents-md.js.map +1 -1
- package/dist/core/agent/workflows/check.js +5 -6
- package/dist/core/agent/workflows/check.js.map +1 -1
- package/dist/core/agent/workflows/reference/spine.js +12 -6
- package/dist/core/agent/workflows/reference/spine.js.map +1 -1
- package/dist/core/brief/brief.js +25 -8
- package/dist/core/brief/brief.js.map +1 -1
- package/dist/core/brief/targets.js +64 -0
- 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/c4/project/architecture.js +31 -9
- package/dist/core/c4/project/architecture.js.map +1 -1
- package/dist/core/c4/project/documents.js +5 -4
- package/dist/core/c4/project/documents.js.map +1 -1
- package/dist/core/c4/project/load.js +8 -4
- package/dist/core/c4/project/load.js.map +1 -1
- package/dist/core/c4/project/staged.js +7 -3
- package/dist/core/c4/project/staged.js.map +1 -1
- package/dist/core/deployment/delta.js +12 -10
- package/dist/core/deployment/delta.js.map +1 -1
- package/dist/core/gate/checks.js +5 -1
- package/dist/core/gate/checks.js.map +1 -1
- package/dist/core/gate/partners.js +60 -17
- package/dist/core/gate/partners.js.map +1 -1
- package/dist/core/repo/paths.js +34 -29
- package/dist/core/repo/paths.js.map +1 -1
- package/dist/core/repo/tree/render/body.js +45 -6
- package/dist/core/repo/tree/render/body.js.map +1 -1
- package/dist/core/repo/tree/render/service/header.js +125 -0
- package/dist/core/repo/tree/render/service/header.js.map +1 -0
- package/dist/core/repo/tree/render/service/peers.js +28 -0
- package/dist/core/repo/tree/render/service/peers.js.map +1 -0
- package/dist/core/repo/tree/render/service/view-id.js +67 -0
- package/dist/core/repo/tree/render/service/view-id.js.map +1 -0
- package/dist/core/repo/tree/render/service/views.js +78 -0
- package/dist/core/repo/tree/render/service/views.js.map +1 -0
- package/dist/core/repo/tree/render/stale.js +19 -2
- package/dist/core/repo/tree/render/stale.js.map +1 -1
- package/dist/core/repo/tree/render/views.js +102 -33
- package/dist/core/repo/tree/render/views.js.map +1 -1
- package/dist/core/verify/checklist.js +42 -10
- package/dist/core/verify/checklist.js.map +1 -1
- package/dist/core/vocabulary/issue.js.map +1 -1
- package/dist/core/vocabulary/maturity.js +41 -1
- package/dist/core/vocabulary/maturity.js.map +1 -1
- package/examples/README.md +7 -3
- package/examples/docs/architecture/landscape.likec4 +13 -7
- package/examples/docs/architecture/services.likec4 +70 -0
- package/examples/docs/architecture/subsystems.likec4 +3 -0
- package/examples/docs/services/order-service/model.likec4 +10 -8
- package/examples/docs/services/payment-service/model.likec4 +6 -4
- package/examples/docs/services/platform/identity-service/model.likec4 +9 -7
- package/examples/docs/services/platform/notification-service/model.likec4 +4 -5
- package/package.json +1 -1
|
@@ -1,19 +1,37 @@
|
|
|
1
|
-
import { subsystemViewsPath } from "../../../../core/repo/paths.js";
|
|
2
|
-
import { viewsState } from "../../../../core/repo/tree/render/stale.js";
|
|
1
|
+
import { serviceViewsPath, subsystemViewsPath } from "../../../../core/repo/paths.js";
|
|
2
|
+
import { serviceViewsState, viewsState } from "../../../../core/repo/tree/render/stale.js";
|
|
3
3
|
export async function viewsStaleFindings(docsDir, tree, map) {
|
|
4
|
-
const
|
|
5
|
-
|
|
4
|
+
const subsystems = await viewsState(subsystemViewsPath(docsDir), tree, map);
|
|
5
|
+
const services = await serviceViewsState(serviceViewsPath(docsDir), tree, map);
|
|
6
|
+
return [
|
|
7
|
+
...staleFinding(subsystems, {
|
|
8
|
+
file: "architecture/subsystems.likec4",
|
|
9
|
+
absent: "does not exist, but the tree has subsystems to mirror",
|
|
10
|
+
leftover: "exists, but the tree has no subsystems — the generated file must be absent",
|
|
11
|
+
what: "one view per subsystem, and every derived scope drawn from it is wrong until it agrees",
|
|
12
|
+
}),
|
|
13
|
+
...staleFinding(services, {
|
|
14
|
+
file: "architecture/services.likec4",
|
|
15
|
+
absent: "does not exist, but the fleet map draws services this file must mirror",
|
|
16
|
+
leftover: "exists, but the fleet map draws none of the services under services/ — the generated file must be absent",
|
|
17
|
+
what: "one overview view per service the map draws, and every drill-down into a service goes through it, so a " +
|
|
18
|
+
"reader following the map lands on a picture that is wrong until it agrees",
|
|
19
|
+
}),
|
|
20
|
+
];
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* One finding, or none — the shape both generated files share, spelled once so
|
|
24
|
+
* they cannot drift into two dialects of the same sentence.
|
|
25
|
+
*/
|
|
26
|
+
function staleFinding(state, file) {
|
|
27
|
+
if (state.agrees)
|
|
6
28
|
return [];
|
|
7
|
-
const
|
|
8
|
-
? "does not exist, but the tree has subsystems to mirror"
|
|
9
|
-
: expected === null
|
|
10
|
-
? "exists, but the tree has no subsystems — the generated file must be absent"
|
|
11
|
-
: "does not match the tree";
|
|
29
|
+
const said = state.actual === null ? file.absent : state.expected === null ? file.leftover : "does not match the tree and the map";
|
|
12
30
|
return [
|
|
13
31
|
{
|
|
14
32
|
severity: "error",
|
|
15
33
|
code: "subsystem.views-stale",
|
|
16
|
-
subject:
|
|
34
|
+
subject: file.file,
|
|
17
35
|
// The file the message names, so an editor jumping to the finding lands
|
|
18
36
|
// on it. Without a location the report's fallback files this under the
|
|
19
37
|
// TARGET, which is the landscape — a reader was sent to
|
|
@@ -22,12 +40,11 @@ export async function viewsStaleFindings(docsDir, tree, map) {
|
|
|
22
40
|
// yet cannot be `primary`: the actionable place is then the directory
|
|
23
41
|
// the regenerator will write into.
|
|
24
42
|
locations: [
|
|
25
|
-
actual === null
|
|
43
|
+
state.actual === null
|
|
26
44
|
? { path: "architecture", role: "scope" }
|
|
27
|
-
: { path:
|
|
45
|
+
: { path: file.file, role: "primary" },
|
|
28
46
|
],
|
|
29
|
-
message: `subsystems:
|
|
30
|
-
`it is generated, one view per subsystem, and every derived scope drawn from it is wrong until it agrees. ` +
|
|
47
|
+
message: `subsystems: ${file.file} ${said} — it is generated, ${file.what}. ` +
|
|
31
48
|
"Run `loam subsystem sync` to regenerate it; never edit it by hand.",
|
|
32
49
|
},
|
|
33
50
|
];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stale.js","sourceRoot":"","sources":["../../../../../src/commands/validate/fleet/views/stale.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"stale.js","sourceRoot":"","sources":["../../../../../src/commands/validate/fleet/views/stale.ts"],"names":[],"mappings":"AAmDA,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AACtF,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAmB,MAAM,4CAA4C,CAAC;AAK5G,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,OAAgB,EAAE,IAAe,EAAE,GAAa;IACvF,MAAM,UAAU,GAAG,MAAM,UAAU,CAAC,kBAAkB,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;IAC5E,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,gBAAgB,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;IAC/E,OAAO;QACL,GAAG,YAAY,CAAC,UAAU,EAAE;YAC1B,IAAI,EAAE,gCAAgC;YACtC,MAAM,EAAE,uDAAuD;YAC/D,QAAQ,EAAE,4EAA4E;YACtF,IAAI,EAAE,wFAAwF;SAC/F,CAAC;QACF,GAAG,YAAY,CAAC,QAAQ,EAAE;YACxB,IAAI,EAAE,8BAA8B;YACpC,MAAM,EAAE,wEAAwE;YAChF,QAAQ,EACN,0GAA0G;YAC5G,IAAI,EACF,yGAAyG;gBACzG,2EAA2E;SAC9E,CAAC;KACH,CAAC;AACJ,CAAC;AAcD;;;GAGG;AACH,SAAS,YAAY,CAAC,KAAiB,EAAE,IAAe;IACtD,IAAI,KAAK,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IAC5B,MAAM,IAAI,GACR,KAAK,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,qCAAqC,CAAC;IACxH,OAAO;QACL;YACE,QAAQ,EAAE,OAAO;YACjB,IAAI,EAAE,uBAAuB;YAC7B,OAAO,EAAE,IAAI,CAAC,IAAI;YAClB,wEAAwE;YACxE,uEAAuE;YACvE,wDAAwD;YACxD,qEAAqE;YACrE,sEAAsE;YACtE,sEAAsE;YACtE,mCAAmC;YACnC,SAAS,EAAE;gBACT,KAAK,CAAC,MAAM,KAAK,IAAI;oBACnB,CAAC,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,OAAgB,EAAE;oBAClD,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,SAAkB,EAAE;aAClD;YACD,OAAO,EACL,eAAe,IAAI,CAAC,IAAI,IAAI,IAAI,uBAAuB,IAAI,CAAC,IAAI,IAAI;gBACpE,oEAAoE;SACvE;KACF,CAAC;AACJ,CAAC","sourcesContent":["/**\n * Staleness of the GENERATED documents under `architecture/` against the tree\n * and the map: ONE error per stale file, naming that file, repaired by exactly\n * one command (`loam subsystem sync`).\n *\n * TWO FILES, ONE CODE, and that is a decision rather than an omission.\n * `subsystems.likec4` (one view per subsystem) and `services.likec4` (one\n * overview view per service the map draws) are written by the same command in\n * the same commit, drift for overlapping reasons — a `subsystem move` restales\n * both, because a per-service view's title is `<subsystem path> / <service\n * id>` — and are repaired by the same run. A second code would buy a reader\n * nothing the `subject` and the message do not already say, and every code costs\n * a row in `core/agent/workflows/check.ts`, a `loam explain` entry and a place in\n * the vocabulary. What DOES have to stay apart is which file drifted, so the two\n * are graded separately and each finding carries its own path — folding them\n * into one finding would lose the only thing the message has to say.\n *\n * A content compare, deliberately — never a parse. A views-only document does\n * not parse standalone (its `include` lines reference elements the landscape\n * defines; the spike in `core/repo/tree/render/views.ts` records it), and no check\n * anywhere reads the file's MEANING: the file is a scoping convenience for\n * the LikeC4 renderer, so the only question loam owes it is \"is this what the\n * tree renders to\". Rule 26 leaves this untouched: what loam may\n * read is a `dynamic view`'s declared steps out of a document it already\n * parses — never a static view's `include` predicates, and never this\n * generated file at all. Absent counts as a state of its own: a fleet\n * with subsystems and no file is stale, and a fleet with NO subsystems and a\n * leftover file is stale too — the render contract says the file must then\n * not exist, or a group deleted months ago keeps a view forever.\n *\n * The compare is over CONTENT, not BYTES, and `viewsAgree` in\n * `core/repo/tree/render/views.ts` both performs it and records why: an ordinary\n * Windows clone hands this file back with CRLF and not one fact in it changed,\n * and under a byte compare the advertised repair is a loop rather than a\n * diagnosis. The rule lives beside the generator because the module that mints\n * the bytes is the one that owes an answer about them.\n *\n * Graded only when the landscape PARSED (the caller holds that gate): the\n * expected bytes resolve members through the landscape's element→service\n * join, and grading them against a map that is missing or unreadable would\n * cascade a second error behind `landscape.missing`/`landscape.invalid`,\n * pointing at a file whose repair command would only re-derive the same\n * incomplete answer.\n *\n * The map arrives as the parsed document's facts — its elements AND the\n * global style ids it declares — because the expected bytes now depend on\n * both: a view references `global style subsystems` exactly when the project\n * declares that id, so a fleet that declares it sees this finding once, until\n * the next `sync` writes the line.\n */\nimport type { DocsDir } from \"../../../../core/kernel/ids/dirs.js\";\nimport { serviceViewsPath, subsystemViewsPath } from \"../../../../core/repo/paths.js\";\nimport { serviceViewsState, viewsState, type ViewsState } from \"../../../../core/repo/tree/render/stale.js\";\nimport type { MapFacts } from \"../../../../core/repo/tree/render/views.js\";\nimport type { FleetTree } from \"../../../../core/repo/tree/walk.js\";\nimport type { Finding } from \"../../../../core/vocabulary/report.js\";\n\nexport async function viewsStaleFindings(docsDir: DocsDir, tree: FleetTree, map: MapFacts): Promise<Finding[]> {\n const subsystems = await viewsState(subsystemViewsPath(docsDir), tree, map);\n const services = await serviceViewsState(serviceViewsPath(docsDir), tree, map);\n return [\n ...staleFinding(subsystems, {\n file: \"architecture/subsystems.likec4\",\n absent: \"does not exist, but the tree has subsystems to mirror\",\n leftover: \"exists, but the tree has no subsystems — the generated file must be absent\",\n what: \"one view per subsystem, and every derived scope drawn from it is wrong until it agrees\",\n }),\n ...staleFinding(services, {\n file: \"architecture/services.likec4\",\n absent: \"does not exist, but the fleet map draws services this file must mirror\",\n leftover:\n \"exists, but the fleet map draws none of the services under services/ — the generated file must be absent\",\n what:\n \"one overview view per service the map draws, and every drill-down into a service goes through it, so a \" +\n \"reader following the map lands on a picture that is wrong until it agrees\",\n }),\n ];\n}\n\n/** The four sentences one file's finding differs by — the rest of it is shared. */\ninterface StaleFile {\n /** The docs-relative path, which is the subject, the location and the head of the message. */\n file: string;\n /** Why an absent file is stale. */\n absent: string;\n /** Why a present file that must not exist is stale. */\n leftover: string;\n /** What the file holds, and what is wrong while it disagrees. */\n what: string;\n}\n\n/**\n * One finding, or none — the shape both generated files share, spelled once so\n * they cannot drift into two dialects of the same sentence.\n */\nfunction staleFinding(state: ViewsState, file: StaleFile): Finding[] {\n if (state.agrees) return [];\n const said =\n state.actual === null ? file.absent : state.expected === null ? file.leftover : \"does not match the tree and the map\";\n return [\n {\n severity: \"error\",\n code: \"subsystem.views-stale\",\n subject: file.file,\n // The file the message names, so an editor jumping to the finding lands\n // on it. Without a location the report's fallback files this under the\n // TARGET, which is the landscape — a reader was sent to\n // architecture/landscape.likec4 to fix a file the sentence beside it\n // named as architecture/subsystems.likec4. A file that does not exist\n // yet cannot be `primary`: the actionable place is then the directory\n // the regenerator will write into.\n locations: [\n state.actual === null\n ? { path: \"architecture\", role: \"scope\" as const }\n : { path: file.file, role: \"primary\" as const },\n ],\n message:\n `subsystems: ${file.file} ${said} — it is generated, ${file.what}. ` +\n \"Run `loam subsystem sync` to regenerate it; never edit it by hand.\",\n },\n ];\n}\n"]}
|
|
@@ -218,7 +218,7 @@ const MAP_REST = `- \`loam validate --service <id>\` grades one service's own ax
|
|
|
218
218
|
\`landscape.merge-conflict\`, \`landscape.service-unmodelled\`,
|
|
219
219
|
\`landscape.service-undocumented\`, \`landscape.binding-unknown\`,
|
|
220
220
|
\`landscape.binding-duplicate\`, the fleet-shape advisories
|
|
221
|
-
\`landscape.platform-candidate
|
|
221
|
+
\`landscape.platform-candidate\` and
|
|
222
222
|
\`landscape.datastore-shared\`, \`service.id-invalid\` (fleet scope only, and
|
|
223
223
|
graded before the map is opened, so it stands even when the landscape is
|
|
224
224
|
missing or unreadable), the four renderer-wiring warnings a
|
|
@@ -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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyKhB,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.declaration-diverged\\`, \\`c4.element-unowned\\`,\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), the four renderer-wiring warnings a\n \\`loam subsystem sync\\` repairs — \\`service.likec4-config-missing\\` (a model that\n STANDS ALONE, declaring its own \\`specification\\`, with no\n \\`likec4.config.json\\` beside it: it renders nowhere from the docs root),\n \\`service.likec4-config-stray\\` (that file beside a model that EXTENDS the map,\n where it registers a project that CLAIMS the model, out of the root project\n where the map's kinds are),\n \\`service.model-excluded\\` (the root \\`likec4.config.json\\` excludes an extending\n model's directory, so the renderer never loads it) and\n \\`service.model-unexcluded\\` (it does NOT exclude a standalone model's, so the\n renderer merges that model into the map and calls every declaration a\n duplicate) — plus \\`c4.fleet-project-invalid\\` (warn: every document reads clean\n where loam grades it and the ONE project the renderer builds out of the map and\n every extending model does not, because something is declared in two of them),\n 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 anywhere in the file, including above the stub, makes it yours — seed\n 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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyKhB,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.declaration-diverged\\`, \\`c4.element-unowned\\`,\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\\` 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), the four renderer-wiring warnings a\n \\`loam subsystem sync\\` repairs — \\`service.likec4-config-missing\\` (a model that\n STANDS ALONE, declaring its own \\`specification\\`, with no\n \\`likec4.config.json\\` beside it: it renders nowhere from the docs root),\n \\`service.likec4-config-stray\\` (that file beside a model that EXTENDS the map,\n where it registers a project that CLAIMS the model, out of the root project\n where the map's kinds are),\n \\`service.model-excluded\\` (the root \\`likec4.config.json\\` excludes an extending\n model's directory, so the renderer never loads it) and\n \\`service.model-unexcluded\\` (it does NOT exclude a standalone model's, so the\n renderer merges that model into the map and calls every declaration a\n duplicate) — plus \\`c4.fleet-project-invalid\\` (warn: every document reads clean\n where loam grades it and the ONE project the renderer builds out of the map and\n every extending model does not, because something is declared in two of them),\n 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 anywhere in the file, including above the stub, makes it yours — seed\n 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"]}
|
|
@@ -15,8 +15,8 @@ export const SUBSYSTEM_COMMANDS = `- \`loam subsystem <verb>\` manages the group
|
|
|
15
15
|
[--owner]\` creates a group (an empty one is legal — its \`subsystem.yaml\` is a
|
|
16
16
|
marker, never a member list); \`move <name>... --into <sub|.>\` relocates
|
|
17
17
|
services and whole subtrees in ONE journaled transaction over the renames
|
|
18
|
-
plus
|
|
19
|
-
regenerated views
|
|
18
|
+
plus BOTH regenerated views files (\`--into .\` unfiles; the renames and the
|
|
19
|
+
regenerated views files are staged in git without committing, where git answers); \`rename <old> <new>\` renames a
|
|
20
20
|
group through the same transaction (services are never renamed — the id is
|
|
21
21
|
the identity); \`rm <name>\` removes an EMPTY group; \`list\` shows the tree
|
|
22
22
|
with member counts and the unfiled count (unfiled is permanent and normal —
|
|
@@ -24,9 +24,12 @@ export const SUBSYSTEM_COMMANDS = `- \`loam subsystem <verb>\` manages the group
|
|
|
24
24
|
additive keys \`services[].subsystem\`, \`subsystems[]\` and
|
|
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
|
-
\`sync\` regenerates
|
|
28
|
-
\`
|
|
29
|
-
|
|
27
|
+
\`sync\` regenerates BOTH generated views files —
|
|
28
|
+
\`architecture/subsystems.likec4\` (one view per subsystem) and
|
|
29
|
+
\`architecture/services.likec4\` (one overview view per service the fleet map
|
|
30
|
+
draws) — the one repair for \`subsystem.views-stale\`, which grades each file
|
|
31
|
+
separately and names the one that drifted. It also maintains the RENDERER's
|
|
32
|
+
wiring for the service models. Which wiring a model needs is decided by the file's own
|
|
30
33
|
grammar, never by a config key: a model that declares its own
|
|
31
34
|
\`specification { element … }\` block STANDS ALONE — it cannot share a project
|
|
32
35
|
with the fleet map, since every kind it declares would be a duplicate there —
|
|
@@ -58,16 +61,24 @@ export const SUBSYSTEM_COMMANDS = `- \`loam subsystem <verb>\` manages the group
|
|
|
58
61
|
(\`build\` and \`export\` take every project). A view id claimed twice inside one
|
|
59
62
|
project — the landscape and an extending model both minting it, or either
|
|
60
63
|
claiming a generated one — is
|
|
61
|
-
\`subsystem.view-id-collision
|
|
64
|
+
\`subsystem.view-id-collision\` — ids beginning \`subsystem_\` or \`service_\` are
|
|
65
|
+
loam's to mint. Each generated view is titled by its PATH —
|
|
62
66
|
every marked ancestor's label and its own, which the renderer reads as
|
|
63
67
|
folders — where a label is the marker's \`title\` or the directory name; the
|
|
64
|
-
marker's \`description\` rides along.
|
|
68
|
+
marker's \`description\` rides along. A per-service view is titled
|
|
69
|
+
\`<subsystem path> / <service id>\`, so it lands in the same folder as its
|
|
70
|
+
group, and a \`dynamic view\` you write under
|
|
71
|
+
\`services/<…>/<id>/usecases/\` titled \`<subsystem path> / <service id> / <use
|
|
72
|
+
case>\` lands beside it. So editing \`subsystem.yaml\` changes
|
|
65
73
|
what the renderer LABELS the group, a parent's title changes every view
|
|
66
|
-
beneath it, and either makes
|
|
67
|
-
generated file is
|
|
74
|
+
beneath it, and either makes both files stale until the next \`sync\`. Neither
|
|
75
|
+
generated file is part of the fleet-project load
|
|
68
76
|
(\`c4.fleet-project-invalid\` reads every other \`.likec4\` the root project holds);
|
|
69
|
-
\`subsystem.views-stale\` is the only check that reads
|
|
70
|
-
|
|
77
|
+
\`subsystem.views-stale\` is the only check that reads them, by content
|
|
78
|
+
comparison against the deterministic re-render, never by reading what a view
|
|
79
|
+
shows. Each per-service view is declared \`of\` its service's element, which is
|
|
80
|
+
what makes every other view — the fleet map, its subsystem view, its peers'
|
|
81
|
+
views — drill into it with no authored link. Each subsystem view
|
|
71
82
|
carries \`global style subsystems\` — written after its title, the one line
|
|
72
83
|
LikeC4 gives a view for borrowing a palette — exactly when the \`architecture/\`
|
|
73
84
|
project declares a global style with that id (\`global { styleGroup subsystems
|
|
@@ -79,10 +90,12 @@ export const SUBSYSTEM_COMMANDS = `- \`loam subsystem <verb>\` manages the group
|
|
|
79
90
|
names only, the file opens with one comment line naming them and saying none is
|
|
80
91
|
\`subsystems\`, and the views carry the renderer's defaults — so declaring a group
|
|
81
92
|
under ANY name restales the file, because that comment is part of the bytes.
|
|
82
|
-
\`
|
|
83
|
-
|
|
93
|
+
\`architecture/services.likec4\` reads a group named \`services\` the same way.
|
|
94
|
+
\`sync\` refuses to rewrite either file while \`architecture/\` does not parse
|
|
95
|
+
(\`action: "blocked"\`): fix the map first. Both are generated wholesale:
|
|
84
96
|
an authored diagram of the same services belongs in the landscape or in a
|
|
85
|
-
file of your own name, never here. \`
|
|
97
|
+
file of your own name, never here. \`--json\` reports the subsystem file as
|
|
98
|
+
\`path\`/\`action\` and the per-service one as \`serviceViews\`. \`loam adopt --subsystem <name>\` briefs a new
|
|
86
99
|
service's baseline directly into a group, so adoption need not land unfiled.
|
|
87
100
|
`;
|
|
88
101
|
//# 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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyFjC,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 BOTH regenerated views files (\\`--into .\\` unfiles; the renames and the\n regenerated views files 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 BOTH generated views files —\n \\`architecture/subsystems.likec4\\` (one view per subsystem) and\n \\`architecture/services.likec4\\` (one overview view per service the fleet map\n draws) — the one repair for \\`subsystem.views-stale\\`, which grades each file\n separately and names the one that drifted. It also maintains the RENDERER's\n wiring for the service models. Which wiring a model needs is decided by the file's own\n grammar, never by a config key: a model that declares its own\n \\`specification { element … }\\` block STANDS ALONE — it cannot share a project\n with the fleet map, since every kind it declares would be a duplicate there —\n and a model with no such block EXTENDS the map with\n \\`extend <fully-qualified id> { … }\\` and parses only INSIDE the root project.\n So \\`sync\\` writes one create-only \\`services/<…>/<id>/likec4.config.json\\` per\n STANDALONE model (never rewritten; the team may edit it; commit\n the new files before a \\`move\\`, which refuses over untracked paths), DELETES one\n sitting beside an EXTENDING model (that nested project claims the model out of\n the root project, so \\`likec4 validate .\\` refuses without \\`--project\\` and,\n wherever that project claims the model, \\`export json --project fleet\\` loses\n the service's containers; \\`--json\\` lists what it removed as \\`projects.removed\\`), and rewrites\n the root \\`likec4.config.json\\`'s \\`exclude\\` to hold \\`services/<tree>/**\\` for\n exactly those models, keeping every entry that is not about \\`services/\\` in the\n order the team wrote it. It rewrites that list when at least one extending model\n exists, or when a standalone model's directory is not covered — an older repo\n whose models all stand alone behind \\`services/**\\` is never touched. \\`--json\\`\n carries the result as \\`projects.exclude\\`, and the text view prints one line when\n it rewrote. Between them these repair four warnings:\n \\`service.likec4-config-missing\\` (a standalone model with no project file),\n \\`service.likec4-config-stray\\` (a project file beside an extending model),\n \\`service.model-excluded\\` (an extending model the root \\`exclude\\` hides from the\n renderer) and \\`service.model-unexcluded\\` (a standalone model it does not hide,\n which blanks the whole root project). A flat fleet with no subsystems still owes\n this run: the verb is the tree's, the files are the renderer's. A fleet whose\n models all extend the map ends with ONE project and one picker entry, and\n \\`likec4 validate\\` at the docs root needs no flag; each standalone model adds a\n project, and with more than one \\`likec4 validate\\` needs \\`--project <name>\\`\n (\\`build\\` and \\`export\\` take every project). A view id claimed twice inside one\n project — the landscape and an extending model both minting it, or either\n claiming a generated one — is\n \\`subsystem.view-id-collision\\` — ids beginning \\`subsystem_\\` or \\`service_\\` are\n loam's to mint. 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. A per-service view is titled\n \\`<subsystem path> / <service id>\\`, so it lands in the same folder as its\n group, and a \\`dynamic view\\` you write under\n \\`services/<…>/<id>/usecases/\\` titled \\`<subsystem path> / <service id> / <use\n case>\\` lands beside it. 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 both files stale until the next \\`sync\\`. Neither\n generated file is part of the fleet-project load\n (\\`c4.fleet-project-invalid\\` reads every other \\`.likec4\\` the root project holds);\n \\`subsystem.views-stale\\` is the only check that reads them, by content\n comparison against the deterministic re-render, never by reading what a view\n shows. Each per-service view is declared \\`of\\` its service's element, which is\n what makes every other view — the fleet map, its subsystem view, its peers'\n views — drill into it with no authored link. Each subsystem view\n carries \\`global style subsystems\\` — written after its title, the one line\n LikeC4 gives a view for borrowing a palette — exactly when the \\`architecture/\\`\n project declares a global style with that id (\\`global { styleGroup subsystems\n { style element.tag = #external { color gray } } }\\`, in the landscape or in\n ANY \\`.likec4\\` under \\`architecture/\\` the root \\`exclude\\` does not cover — a\n \\`palette.likec4\\` beside the map counts); nothing otherwise, and loam never reads\n what the group says. Declaring it is the whole opt-in and makes the file stale\n once, until the next \\`sync\\`. When the project declares style groups under other\n names only, the file opens with one comment line naming them and saying none is\n \\`subsystems\\`, and the views carry the renderer's defaults — so declaring a group\n under ANY name restales the file, because that comment is part of the bytes.\n \\`architecture/services.likec4\\` reads a group named \\`services\\` the same way.\n \\`sync\\` refuses to rewrite either file while \\`architecture/\\` does not parse\n (\\`action: \"blocked\"\\`): fix the map first. Both are 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. \\`--json\\` reports the subsystem file as\n \\`path\\`/\\`action\\` and the per-service one as \\`serviceViews\\`. \\`loam adopt --subsystem <name>\\` briefs a new\n service's baseline directly into a group, so adoption need not land unfiled.\n`;\n"]}
|
|
@@ -227,9 +227,11 @@ follows is the other half — which command raises which:
|
|
|
227
227
|
workspace file, which loam never silently overwrites — pass \`--out\` or
|
|
228
228
|
\`--force\`) and \`invalid-option\`.
|
|
229
229
|
- \`loam seed --from fleet.yaml\`: \`seed-file-invalid\`, \`seed-duplicate-service\`,
|
|
230
|
-
\`seed-unknown-subsystem\`, \`seed-landscape-edited\`,
|
|
231
|
-
|
|
232
|
-
|
|
230
|
+
\`seed-unknown-subsystem\`, \`seed-landscape-edited\`, \`already-exists\` when a
|
|
231
|
+
generated views file in \`architecture/\` was written by somebody rather than by
|
|
232
|
+
loam (no \`// generated by loam\` first line — seed writes nothing at all in that
|
|
233
|
+
case), and \`unknown-service\` for a call endpoint nothing declares. An existing
|
|
234
|
+
service directory is never moved, and nothing is ever deleted.
|
|
233
235
|
- \`internal\` — an unexpected throw, the one code with no stable meaning.
|
|
234
236
|
|
|
235
237
|
\`--all\` reports a target per service, a target per feature in flight, and one target
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"refusals.js","sourceRoot":"","sources":["../../../../src/core/agent/agents-md/refusals.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqNvB,CAAC;AAEF;;2DAE2D","sourcesContent":["/**\n * What loam REFUSES: the OpenSpec migration surface, the containment and\n * unreadable-file findings, and the error-envelope codes. What happens to a\n * SHIPPED change — the archive gate, unarchive, and dropping a feature — is\n * the continuation section in ./shipped/archive-gate.ts, split there because\n * the two subjects had grown past one file's ceiling.\n *\n * Codes here are LISTED by the command that raises them, not glossed; the\n * meanings come from `loam explain <code>`, out of the running binary. See\n * ./command-map.ts's header for why the duplicated gloss left.\n *\n * THE ONE EXCEPTION IS THE FIRST BULLET. `loam explain` cannot answer\n * `openspec.*` or `mapping.*` — those commands grade a repository still in\n * another tool's shape, before it has a governed loop to look a code up from,\n * and the catalogue leaves them unanswered for that reason. Pointing this\n * section's reader at an explanation that does not exist is the exact failure\n * the pointer exists to prevent, so the migration notes stay written out here\n * until the catalogue reaches them. test/agent-contract.test.ts enforces the\n * boundary from the other side: every OTHER code backticked in AGENTS_MD must\n * resolve, so a family can never quietly lose its gloss and its explanation\n * at once.\n *\n * One section of the AGENTS.md template. ../agents-md.ts assembles the\n * document by PLAIN CONCATENATION — no join separator — so every section\n * starts at the first character of its opening line and ends with the newline\n * that closes its last one. Keep that shape when editing, or two sections glue\n * onto one line in every docs repo loam scaffolds from now on.\n */\nexport const REFUSALS = `- \\`loam audit-openspec <root>\\` is the read-only OpenSpec inventory; an explicit\n \\`--write-mapping\\` writes a non-overwriting, digest-bound decision skeleton\n outside the source tree. \\`loam migrate-openspec <root> --map <file>\\` validates\n that mapping and stays dry-run unless both \\`--apply\\` and an empty \\`--target\\`\n are supplied. Living/active shape diagnostics are \\`openspec.workspace-empty\\`\n (the audited root holds no living spec and no active change, so there is\n nothing to migrate and no verdict over it can be \\`ready\\`),\n \\`openspec.specs-missing\\`,\n \\`openspec.config-invalid\\`, \\`openspec.external-store-pointer\\`,\n \\`openspec.living-empty\\`, \\`openspec.living-requirements-outside-section\\`,\n \\`openspec.living-delta-section\\`, \\`openspec.nonstandard-living-spec\\` (markdown\n under \\`specs/\\` named neither spec.md nor design.md, so no capability reads\n it), \\`openspec.change-metadata-invalid\\`,\n \\`openspec.change-schema-unresolved\\`, \\`openspec.skip-specs-with-specs\\`,\n \\`openspec.change-no-specs\\`, \\`openspec.change-empty\\`,\n \\`openspec.change-without-delta-sections\\`,\n \\`openspec.change-requirements-outside-delta-sections\\`,\n \\`openspec.change-quoted-requirements\\` (requirements under a \\`## Requirements\\`\n heading INSIDE a change delta — the shape OpenSpec's own living-spec template\n mandates, and one that stages nothing, so loam refuses it rather than counting\n requirements it cannot route),\n \\`openspec.hidden-change-directory\\` (a dot-prefixed directory under\n \\`changes/\\` is not enumerated as a change, so nothing under it migrates —\n rename it or move it out; under \\`changes/archive/\\` the same code is an archive\n diagnostic and does not gate, because frozen history never blocks),\n \\`openspec.nonstandard-change-spec\\`, \\`openspec.renamed-malformed\\`,\n \\`openspec.requirement-id-invalid\\`, \\`openspec.requirement-id-repeated\\`,\n \\`openspec.requirement-id-duplicate\\` (a stable \\`Requirement-ID\\` that is\n malformed, declared twice, or shared by two requirements — identity is never\n inferred from an invalid declaration, so the RENAMED chain cannot be followed\n through it), \\`openspec.symlink-unsupported\\`, and \\`openspec.non-utf8-artifact\\`;\n the same shapes in frozen history are non-blocking archive diagnostics.\n Mapping refuses stale or incomplete decisions under \\`mapping.source-missing\\`,\n \\`mapping.source-root-mismatch\\`, \\`mapping.source-digest-mismatch\\`,\n \\`mapping.unknown-capability\\`, \\`mapping.unknown-requirement\\`,\n \\`mapping.requirement-allocation-missing\\`,\n \\`mapping.requirement-service-unknown\\`, \\`mapping.service-allocation-empty\\`,\n \\`mapping.unknown-change\\`, \\`mapping.change-title-missing\\`,\n \\`mapping.feature-id-invalid\\`, \\`mapping.feature-id-duplicate\\`,\n \\`mapping.unknown-rename\\`, \\`mapping.invalid-requirement-id\\`,\n \\`mapping.rename-source-missing\\`, \\`mapping.rename-source-ambiguous\\`,\n \\`mapping.rename-source-id-invalid\\`, \\`mapping.rename-target-conflict\\`,\n \\`mapping.rename-existing-id-conflict\\`, \\`mapping.rename-id-conflict\\`,\n \\`mapping.rename-double-source\\`, \\`mapping.rename-double-target\\`,\n \\`mapping.rename-chain\\`,\n \\`mapping.unknown-artifact\\`, and \\`mapping.invalid-artifact-disposition\\`.\n- Repository containment failures are explicit: \\`sources.path-outside\\` rejects a\n provenance source outside the service repo and \\`gherkin.path-outside\\` rejects a\n generated-suite target outside it. Federated verify recording refuses under\n \\`service-mismatch\\`, \\`unknown-service\\` or \\`repository-unavailable\\` when the\n selected service, fleet identity and repository commit cannot be bound safely,\n and under \\`record-federated\\` when the legacy all-at-once form would erase other\n repositories' attestations. \\`loam gherkin --service <id>\\` and\n \\`loam vouch --service <id>\\` answer that same wrong-repo pair\n (\\`repository-unavailable\\`, \\`service-mismatch\\`) for the same reason. Neither is\n \\`invalid-option\\`: the flags were right and the directory was wrong, so the fix\n is to re-run in the service's own checkout, never to re-read the invocation.\n- A file loam cannot read is reported, never skipped: \\`service.unreadable\\` and\n \\`feature.unreadable\\` (both errors) name the path and say that nothing about\n that target was checked while the rest of the fleet still was. The whole docs\n repo being unreachable is a refusal instead: \\`docs-missing\\` or\n \\`services-missing\\`.\n- Both modes read frontmatter (\\`frontmatter.missing\\`, \\`frontmatter.malformed\\`,\n \\`frontmatter.field-mismatch\\`,\n \\`frontmatter.status-unknown\\`, \\`frontmatter.field-missing\\`); a service's spec.md —\n and its arch.spec.md, same conventions — additionally carries the sources chain\n (\\`sources.absent\\`, \\`sources.path-missing\\`, \\`sources.empty\\`, \\`sources.skipped\\`,\n \\`sources.unvouched\\`, \\`sources.stale\\`) plus the two doc-side checks,\n \\`content.stale\\` and \\`sources.sampled-vouch\\`, which need no service repo and so\n fire from the docs repo too.\n- A service target run from the service's own repository also re-checks the\n \\`evidence_pins\\` its federated verification records carry, against the working\n tree: \\`evidence.checked\\` and \\`evidence.unpinned\\` are the confirmations,\n \\`evidence.unresolved\\`, \\`evidence.moved\\`, \\`evidence.line-changed\\`,\n \\`evidence.token-missing\\` and \\`evidence.record-unreadable\\` the warnings.\n Demote-only, by doctrine: a warn here is a reading priority for a reviewer,\n never a verdict change — no pin state moves \\`attested\\` or \\`verified\\` in\n either direction. From the docs repo the family is silent;\n \\`sources.unverifiable-from-here\\` already names that blind spot.\n- \\`loam archive\\` alone reports the breaches only the merge computation can see:\n \\`living.requirement-outside-requirements\\`, \\`openapi.op-modified\\`,\n \\`openapi.path-item-modified\\`, \\`openapi.component-modified\\`,\n \\`openapi.ref-unresolved\\`, \\`openapi.remove-marker-path-level\\`, the event\n axis's own trio \\`asyncapi.message-modified\\` / \\`asyncapi.channel-modified\\` /\n \\`asyncapi.operation-modified\\`, \\`asyncapi.ref-unresolved\\`,\n \\`asyncapi.remove-marker-inline\\` and \\`service.no-model\\`. Two of those are\n graded at validate time as well and are STRICTER here —\n \\`openapi.ref-unresolved\\` and \\`asyncapi.ref-unresolved\\` are warnings there and\n errors here, because the merged document is what would carry the dangling\n reference — so \\`loam explain\\` on either prints both contexts.\n\n\\`loam validate <target>\\` is the positional spelling of the first two: a feature id\nor a service id, tried in that order, so the feature wins when one name could be\nboth and \\`--service\\`/\\`--feature\\` force the reading. When the name really is both,\nthe run says so — \\`target.ambiguous\\` (warn) names the reading it took and the\nflag that forces the other, and \\`--json\\` carries \\`resolvedKind\\` — because a\nsilent precedence rule is a report about a target nobody asked for. The\npositional together with \\`--all\\`, \\`--service\\` or \\`--feature\\` is refused\n(\\`invalid-option\\`).\n\nTwo rendering levers change nothing else: \\`loam validate --errors-only\\` drops\nthe confirmations from the TEXT view (the \\`--json\\` payload is byte-identical),\nand \\`loam list --needs-work\\` narrows the service list to the ones with\nsomething missing — the adoption worklist. \\`loam list --needs-work --review-order\\`\norders that worklist by fan-in — the services the most other services depend on\nfirst: drawn call edges into each, plus event subscriptions (a drawn \\`consumes\\`\nedge, or a living \\`Consumes:\\` line naming a message it sends) — a count, never\na priority judgement — and its \\`--json\\` rows then additionally carry \\`fanIn\\`\nand \\`reviewRank\\`; without \\`--needs-work\\` the flag is refused (\\`invalid-option\\`).\n\nTwo campaign flags slice that same services section and change nothing about\nany row. \\`loam list --subsystem <name>\\` limits the listing to the services\nfiled under one subsystem, at any depth: \\`services[]\\`, the \\`maturity\\` rollup\nand \\`subsystems[]\\` reflect the slice (\\`unfiledServices\\` is omitted — it is a\nfleet-root fact), while every per-row fact — \\`fanIn\\`, \\`apiExpected\\`,\n\\`missing\\` — is still computed fleet-wide, so filtering changes which rows\nappear, never what a row says; with \\`--review-order\\` the filter applies first\nand \\`reviewRank\\` stays contiguous within the filtered worklist. The name\n\\`unfiled\\` selects the services filed under no subsystem while nothing in the\ntree claims that name (a real subsystem or service spelled \\`unfiled\\` wins).\nAn unknown name refuses \\`unknown-target\\` with close-name hints; a service\nname refuses \\`invalid-option\\`. \\`loam list --owners <path>\\` joins each listed\nservice's directory to the owning teams in the named CODEOWNERS file —\ndirectory-pattern rules only, last match wins, an owner-less directory rule\nCLEARING ownership for what it matches exactly as the forge reads it; a\nrecognised rule outside that subset (any other wildcard use, \\`*\\` included)\nis reported under \\`skippedRules\\`, never guessed at — and \\`--json\\` gains the additive \\`owners\\`\nkey (\\`path\\`, \\`teams[]\\` with each team's services in the listing's own\nfiltered-and-ordered row order, \\`unowned[]\\` listing the rows no rule matched,\n\\`skippedRules[]\\`), so the per-team arrays are the per-team campaign\nworklists. A CODEOWNERS path that cannot be read, or a line that cannot be\nparsed as \\`pattern owner…\\`, refuses \\`owners-unreadable\\` naming the path and\nline — fail-closed, exactly as \\`answers-unreadable\\` treats the other\nuser-named file. Either flag with the \\`features\\` or \\`capabilities\\` section\nis refused (\\`invalid-option\\`).\n\n\\`--strict\\` (every targeting mode, \\`--all\\` included) exits 1 when any error\nor warning exists — \\`ok\\`-severity findings are confirmations and never trip\nit. It changes the exit code and nothing else:\n\\`valid\\` still means \"no errors\", and the \\`--json\\` payload stays byte-for-byte\nwhat it was. The stricter grade is a per-invocation lever, visible in the CI\npipeline that passes the flag — deliberately not a per-repo profile.\n\n\\`loam delta <FEAT> --json\\` exits 1 when either authored document behind the brief\nfailed to parse — \\`architecture.errors\\` non-empty, or \\`openapi.unreadable\\` true —\nwith \\`ok: true\\` and the full payload intact: the empty C4 slice means the delta\ndid not parse, and an empty \\`api\\` beside \\`openapi.unreadable\\` means the contract\ndelta did not parse, neither of them \"this feature changes nothing there\". Branch\non the exit code before consuming either slice as a task brief.\n\nFindings with severity \\`ok\\` are confirmations, not work: \\`c4.valid\\`, \\`delta.valid\\`,\n\\`requirements.covered\\`, \\`api.covered\\`, \\`spine.resolved\\`, \\`event.covered\\`, \\`coherence.ok\\`,\n\\`landscape.matched\\`, \\`archedge.covered\\`, \\`sources.resolved\\`, \\`sources.current\\`,\n\\`sources.walked\\`, \\`gherkin.current\\`.\n\nA finding's \\`subject\\` names the service it is about. The envelope separates \\`ok\\` (the\ncommand ran) from \\`valid\\` (the docs pass). A refusal is \\`ok: false\\` with a stable\n\\`error.code\\`, and \\`loam explain <code>\\` has the meaning of every one of them. What\nfollows is the other half — which command raises which:\n\n- Before any command can read anything: \\`no-config\\`, \\`config-invalid\\`,\n \\`docs-missing\\`, \\`services-missing\\`, \\`unknown-target\\`, \\`invalid-option\\`.\n \\`invalid-option\\` covers flags that contradict each other AND a value that\n cannot be right — a \\`loam list\\` section that is not services or features, or a\n service id that is not a legal \\`services/<id>/\\` directory name.\n- Every JOURNALED writer — \\`archive\\`, \\`unarchive\\`, \\`rebase\\`, \\`vouch\\`, \\`new\\`,\n \\`gherkin\\`, \\`seed\\`, \\`subsystem\\` and \\`verify --record\\` — shares one transaction\n and therefore one set of refusals: \\`docs-busy\\`, \\`commit-interrupted\\`,\n \\`merge-failed\\` and \\`rollback-incomplete\\`. Learn them once and you have read\n them for all nine. \\`loam doctor\\` names the interrupted state as\n \\`doctor.commit-interrupted\\` and \\`loam validate\\` leads every mode with\n \\`docs.commit-interrupted\\` while the journal sits there; every journaled writer\n recovers a finished predecessor's journal on its next run and reports it as\n \\`recovered\\` in \\`--json\\`.\n- \\`loam new\\`: \\`already-exists\\` — also the answer when a concurrent \\`new\\` for the\n same id wins the race.\n- \\`loam vouch\\`: \\`sources-absent\\`, \\`sources-path-missing\\`, \\`vouch-raced\\`, and the\n wrong-repo pair \\`repository-unavailable\\` / \\`service-mismatch\\`, because\n \\`sources\\` resolve against the service's own checkout and from anywhere else\n those paths are somebody else's.\n- \\`loam archive\\`: \\`not-coherent\\`, \\`living-outside-requirements\\`,\n \\`archive-exists\\` — see the archive gate below.\n- \\`loam unarchive\\`: \\`feature-active\\`, \\`snapshot-missing\\`, \\`snapshot-stale\\`,\n \\`snapshot-corrupt\\`, \\`restore-failed\\` — see \"Taking an archive back\".\n- \\`loam gherkin\\`: \\`gherkin-conflict\\`, plus the same wrong-repo pair, refused\n before anything is written because the generated files land in the repo loam\n is standing in.\n- \\`loam subsystem\\`: \\`subsystem-not-empty\\`, \\`move-uncommitted\\`, \\`move-failed\\`,\n and \\`unknown-target\\` / \\`already-exists\\` / \\`invalid-option\\` for names that\n resolve to nothing, collide in the flat namespace, or break the grammar.\n \\`move-failed\\` is deliberately distinct from \\`merge-failed\\`: the move's own\n transaction rolled back cleanly, nothing changed, and re-running can work.\n- \\`loam verify --record\\` / \\`--results\\` / \\`--contract-results\\`:\n \\`answers-unreadable\\`, \\`answers-mismatch\\`, \\`answers-unevidenced\\`,\n \\`record-federated\\`, \\`record-unreadable\\` and \\`record-raced\\`. Two records for\n different services land in either order — the later one waits, then merges,\n and both attestations survive.\n- \\`loam open\\`: \\`no-members\\`, \\`binding-duplicate\\`, \\`already-exists\\` (the\n workspace file, which loam never silently overwrites — pass \\`--out\\` or\n \\`--force\\`) and \\`invalid-option\\`.\n- \\`loam seed --from fleet.yaml\\`: \\`seed-file-invalid\\`, \\`seed-duplicate-service\\`,\n \\`seed-unknown-subsystem\\`, \\`seed-landscape-edited\\`, and \\`unknown-service\\` for a\n call endpoint nothing declares. An existing service directory is never moved,\n and nothing is ever deleted.\n- \\`internal\\` — an unexpected throw, the one code with no stable meaning.\n\n\\`--all\\` reports a target per service, a target per feature in flight, and one target\nof kind \\`landscape\\` for the fleet-level checks that belong to no single service.\n\nThree different words for three different questions, and no command conflates them:\n\\`ok\\` — the command ran; \\`valid\\` — the documents pass (\\`validate\\`); \\`verified\\` —\nsomebody says the code was built and showed evidence (\\`verify\\`). A feature can be\nvalid and unverified, or verified and incoherent. Read the one you meant.\n`;\n\n/* The archive gate, unarchive, and dropping a feature continue in\n * ./shipped/archive-gate.ts — one document section split at its own subject\n * seam, concatenated after this one by ../agents-md.ts. */\n"]}
|
|
1
|
+
{"version":3,"file":"refusals.js","sourceRoot":"","sources":["../../../../src/core/agent/agents-md/refusals.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuNvB,CAAC;AAEF;;2DAE2D","sourcesContent":["/**\n * What loam REFUSES: the OpenSpec migration surface, the containment and\n * unreadable-file findings, and the error-envelope codes. What happens to a\n * SHIPPED change — the archive gate, unarchive, and dropping a feature — is\n * the continuation section in ./shipped/archive-gate.ts, split there because\n * the two subjects had grown past one file's ceiling.\n *\n * Codes here are LISTED by the command that raises them, not glossed; the\n * meanings come from `loam explain <code>`, out of the running binary. See\n * ./command-map.ts's header for why the duplicated gloss left.\n *\n * THE ONE EXCEPTION IS THE FIRST BULLET. `loam explain` cannot answer\n * `openspec.*` or `mapping.*` — those commands grade a repository still in\n * another tool's shape, before it has a governed loop to look a code up from,\n * and the catalogue leaves them unanswered for that reason. Pointing this\n * section's reader at an explanation that does not exist is the exact failure\n * the pointer exists to prevent, so the migration notes stay written out here\n * until the catalogue reaches them. test/agent-contract.test.ts enforces the\n * boundary from the other side: every OTHER code backticked in AGENTS_MD must\n * resolve, so a family can never quietly lose its gloss and its explanation\n * at once.\n *\n * One section of the AGENTS.md template. ../agents-md.ts assembles the\n * document by PLAIN CONCATENATION — no join separator — so every section\n * starts at the first character of its opening line and ends with the newline\n * that closes its last one. Keep that shape when editing, or two sections glue\n * onto one line in every docs repo loam scaffolds from now on.\n */\nexport const REFUSALS = `- \\`loam audit-openspec <root>\\` is the read-only OpenSpec inventory; an explicit\n \\`--write-mapping\\` writes a non-overwriting, digest-bound decision skeleton\n outside the source tree. \\`loam migrate-openspec <root> --map <file>\\` validates\n that mapping and stays dry-run unless both \\`--apply\\` and an empty \\`--target\\`\n are supplied. Living/active shape diagnostics are \\`openspec.workspace-empty\\`\n (the audited root holds no living spec and no active change, so there is\n nothing to migrate and no verdict over it can be \\`ready\\`),\n \\`openspec.specs-missing\\`,\n \\`openspec.config-invalid\\`, \\`openspec.external-store-pointer\\`,\n \\`openspec.living-empty\\`, \\`openspec.living-requirements-outside-section\\`,\n \\`openspec.living-delta-section\\`, \\`openspec.nonstandard-living-spec\\` (markdown\n under \\`specs/\\` named neither spec.md nor design.md, so no capability reads\n it), \\`openspec.change-metadata-invalid\\`,\n \\`openspec.change-schema-unresolved\\`, \\`openspec.skip-specs-with-specs\\`,\n \\`openspec.change-no-specs\\`, \\`openspec.change-empty\\`,\n \\`openspec.change-without-delta-sections\\`,\n \\`openspec.change-requirements-outside-delta-sections\\`,\n \\`openspec.change-quoted-requirements\\` (requirements under a \\`## Requirements\\`\n heading INSIDE a change delta — the shape OpenSpec's own living-spec template\n mandates, and one that stages nothing, so loam refuses it rather than counting\n requirements it cannot route),\n \\`openspec.hidden-change-directory\\` (a dot-prefixed directory under\n \\`changes/\\` is not enumerated as a change, so nothing under it migrates —\n rename it or move it out; under \\`changes/archive/\\` the same code is an archive\n diagnostic and does not gate, because frozen history never blocks),\n \\`openspec.nonstandard-change-spec\\`, \\`openspec.renamed-malformed\\`,\n \\`openspec.requirement-id-invalid\\`, \\`openspec.requirement-id-repeated\\`,\n \\`openspec.requirement-id-duplicate\\` (a stable \\`Requirement-ID\\` that is\n malformed, declared twice, or shared by two requirements — identity is never\n inferred from an invalid declaration, so the RENAMED chain cannot be followed\n through it), \\`openspec.symlink-unsupported\\`, and \\`openspec.non-utf8-artifact\\`;\n the same shapes in frozen history are non-blocking archive diagnostics.\n Mapping refuses stale or incomplete decisions under \\`mapping.source-missing\\`,\n \\`mapping.source-root-mismatch\\`, \\`mapping.source-digest-mismatch\\`,\n \\`mapping.unknown-capability\\`, \\`mapping.unknown-requirement\\`,\n \\`mapping.requirement-allocation-missing\\`,\n \\`mapping.requirement-service-unknown\\`, \\`mapping.service-allocation-empty\\`,\n \\`mapping.unknown-change\\`, \\`mapping.change-title-missing\\`,\n \\`mapping.feature-id-invalid\\`, \\`mapping.feature-id-duplicate\\`,\n \\`mapping.unknown-rename\\`, \\`mapping.invalid-requirement-id\\`,\n \\`mapping.rename-source-missing\\`, \\`mapping.rename-source-ambiguous\\`,\n \\`mapping.rename-source-id-invalid\\`, \\`mapping.rename-target-conflict\\`,\n \\`mapping.rename-existing-id-conflict\\`, \\`mapping.rename-id-conflict\\`,\n \\`mapping.rename-double-source\\`, \\`mapping.rename-double-target\\`,\n \\`mapping.rename-chain\\`,\n \\`mapping.unknown-artifact\\`, and \\`mapping.invalid-artifact-disposition\\`.\n- Repository containment failures are explicit: \\`sources.path-outside\\` rejects a\n provenance source outside the service repo and \\`gherkin.path-outside\\` rejects a\n generated-suite target outside it. Federated verify recording refuses under\n \\`service-mismatch\\`, \\`unknown-service\\` or \\`repository-unavailable\\` when the\n selected service, fleet identity and repository commit cannot be bound safely,\n and under \\`record-federated\\` when the legacy all-at-once form would erase other\n repositories' attestations. \\`loam gherkin --service <id>\\` and\n \\`loam vouch --service <id>\\` answer that same wrong-repo pair\n (\\`repository-unavailable\\`, \\`service-mismatch\\`) for the same reason. Neither is\n \\`invalid-option\\`: the flags were right and the directory was wrong, so the fix\n is to re-run in the service's own checkout, never to re-read the invocation.\n- A file loam cannot read is reported, never skipped: \\`service.unreadable\\` and\n \\`feature.unreadable\\` (both errors) name the path and say that nothing about\n that target was checked while the rest of the fleet still was. The whole docs\n repo being unreachable is a refusal instead: \\`docs-missing\\` or\n \\`services-missing\\`.\n- Both modes read frontmatter (\\`frontmatter.missing\\`, \\`frontmatter.malformed\\`,\n \\`frontmatter.field-mismatch\\`,\n \\`frontmatter.status-unknown\\`, \\`frontmatter.field-missing\\`); a service's spec.md —\n and its arch.spec.md, same conventions — additionally carries the sources chain\n (\\`sources.absent\\`, \\`sources.path-missing\\`, \\`sources.empty\\`, \\`sources.skipped\\`,\n \\`sources.unvouched\\`, \\`sources.stale\\`) plus the two doc-side checks,\n \\`content.stale\\` and \\`sources.sampled-vouch\\`, which need no service repo and so\n fire from the docs repo too.\n- A service target run from the service's own repository also re-checks the\n \\`evidence_pins\\` its federated verification records carry, against the working\n tree: \\`evidence.checked\\` and \\`evidence.unpinned\\` are the confirmations,\n \\`evidence.unresolved\\`, \\`evidence.moved\\`, \\`evidence.line-changed\\`,\n \\`evidence.token-missing\\` and \\`evidence.record-unreadable\\` the warnings.\n Demote-only, by doctrine: a warn here is a reading priority for a reviewer,\n never a verdict change — no pin state moves \\`attested\\` or \\`verified\\` in\n either direction. From the docs repo the family is silent;\n \\`sources.unverifiable-from-here\\` already names that blind spot.\n- \\`loam archive\\` alone reports the breaches only the merge computation can see:\n \\`living.requirement-outside-requirements\\`, \\`openapi.op-modified\\`,\n \\`openapi.path-item-modified\\`, \\`openapi.component-modified\\`,\n \\`openapi.ref-unresolved\\`, \\`openapi.remove-marker-path-level\\`, the event\n axis's own trio \\`asyncapi.message-modified\\` / \\`asyncapi.channel-modified\\` /\n \\`asyncapi.operation-modified\\`, \\`asyncapi.ref-unresolved\\`,\n \\`asyncapi.remove-marker-inline\\` and \\`service.no-model\\`. Two of those are\n graded at validate time as well and are STRICTER here —\n \\`openapi.ref-unresolved\\` and \\`asyncapi.ref-unresolved\\` are warnings there and\n errors here, because the merged document is what would carry the dangling\n reference — so \\`loam explain\\` on either prints both contexts.\n\n\\`loam validate <target>\\` is the positional spelling of the first two: a feature id\nor a service id, tried in that order, so the feature wins when one name could be\nboth and \\`--service\\`/\\`--feature\\` force the reading. When the name really is both,\nthe run says so — \\`target.ambiguous\\` (warn) names the reading it took and the\nflag that forces the other, and \\`--json\\` carries \\`resolvedKind\\` — because a\nsilent precedence rule is a report about a target nobody asked for. The\npositional together with \\`--all\\`, \\`--service\\` or \\`--feature\\` is refused\n(\\`invalid-option\\`).\n\nTwo rendering levers change nothing else: \\`loam validate --errors-only\\` drops\nthe confirmations from the TEXT view (the \\`--json\\` payload is byte-identical),\nand \\`loam list --needs-work\\` narrows the service list to the ones with\nsomething missing — the adoption worklist. \\`loam list --needs-work --review-order\\`\norders that worklist by fan-in — the services the most other services depend on\nfirst: drawn call edges into each, plus event subscriptions (a drawn \\`consumes\\`\nedge, or a living \\`Consumes:\\` line naming a message it sends) — a count, never\na priority judgement — and its \\`--json\\` rows then additionally carry \\`fanIn\\`\nand \\`reviewRank\\`; without \\`--needs-work\\` the flag is refused (\\`invalid-option\\`).\n\nTwo campaign flags slice that same services section and change nothing about\nany row. \\`loam list --subsystem <name>\\` limits the listing to the services\nfiled under one subsystem, at any depth: \\`services[]\\`, the \\`maturity\\` rollup\nand \\`subsystems[]\\` reflect the slice (\\`unfiledServices\\` is omitted — it is a\nfleet-root fact), while every per-row fact — \\`fanIn\\`, \\`apiExpected\\`,\n\\`missing\\` — is still computed fleet-wide, so filtering changes which rows\nappear, never what a row says; with \\`--review-order\\` the filter applies first\nand \\`reviewRank\\` stays contiguous within the filtered worklist. The name\n\\`unfiled\\` selects the services filed under no subsystem while nothing in the\ntree claims that name (a real subsystem or service spelled \\`unfiled\\` wins).\nAn unknown name refuses \\`unknown-target\\` with close-name hints; a service\nname refuses \\`invalid-option\\`. \\`loam list --owners <path>\\` joins each listed\nservice's directory to the owning teams in the named CODEOWNERS file —\ndirectory-pattern rules only, last match wins, an owner-less directory rule\nCLEARING ownership for what it matches exactly as the forge reads it; a\nrecognised rule outside that subset (any other wildcard use, \\`*\\` included)\nis reported under \\`skippedRules\\`, never guessed at — and \\`--json\\` gains the additive \\`owners\\`\nkey (\\`path\\`, \\`teams[]\\` with each team's services in the listing's own\nfiltered-and-ordered row order, \\`unowned[]\\` listing the rows no rule matched,\n\\`skippedRules[]\\`), so the per-team arrays are the per-team campaign\nworklists. A CODEOWNERS path that cannot be read, or a line that cannot be\nparsed as \\`pattern owner…\\`, refuses \\`owners-unreadable\\` naming the path and\nline — fail-closed, exactly as \\`answers-unreadable\\` treats the other\nuser-named file. Either flag with the \\`features\\` or \\`capabilities\\` section\nis refused (\\`invalid-option\\`).\n\n\\`--strict\\` (every targeting mode, \\`--all\\` included) exits 1 when any error\nor warning exists — \\`ok\\`-severity findings are confirmations and never trip\nit. It changes the exit code and nothing else:\n\\`valid\\` still means \"no errors\", and the \\`--json\\` payload stays byte-for-byte\nwhat it was. The stricter grade is a per-invocation lever, visible in the CI\npipeline that passes the flag — deliberately not a per-repo profile.\n\n\\`loam delta <FEAT> --json\\` exits 1 when either authored document behind the brief\nfailed to parse — \\`architecture.errors\\` non-empty, or \\`openapi.unreadable\\` true —\nwith \\`ok: true\\` and the full payload intact: the empty C4 slice means the delta\ndid not parse, and an empty \\`api\\` beside \\`openapi.unreadable\\` means the contract\ndelta did not parse, neither of them \"this feature changes nothing there\". Branch\non the exit code before consuming either slice as a task brief.\n\nFindings with severity \\`ok\\` are confirmations, not work: \\`c4.valid\\`, \\`delta.valid\\`,\n\\`requirements.covered\\`, \\`api.covered\\`, \\`spine.resolved\\`, \\`event.covered\\`, \\`coherence.ok\\`,\n\\`landscape.matched\\`, \\`archedge.covered\\`, \\`sources.resolved\\`, \\`sources.current\\`,\n\\`sources.walked\\`, \\`gherkin.current\\`.\n\nA finding's \\`subject\\` names the service it is about. The envelope separates \\`ok\\` (the\ncommand ran) from \\`valid\\` (the docs pass). A refusal is \\`ok: false\\` with a stable\n\\`error.code\\`, and \\`loam explain <code>\\` has the meaning of every one of them. What\nfollows is the other half — which command raises which:\n\n- Before any command can read anything: \\`no-config\\`, \\`config-invalid\\`,\n \\`docs-missing\\`, \\`services-missing\\`, \\`unknown-target\\`, \\`invalid-option\\`.\n \\`invalid-option\\` covers flags that contradict each other AND a value that\n cannot be right — a \\`loam list\\` section that is not services or features, or a\n service id that is not a legal \\`services/<id>/\\` directory name.\n- Every JOURNALED writer — \\`archive\\`, \\`unarchive\\`, \\`rebase\\`, \\`vouch\\`, \\`new\\`,\n \\`gherkin\\`, \\`seed\\`, \\`subsystem\\` and \\`verify --record\\` — shares one transaction\n and therefore one set of refusals: \\`docs-busy\\`, \\`commit-interrupted\\`,\n \\`merge-failed\\` and \\`rollback-incomplete\\`. Learn them once and you have read\n them for all nine. \\`loam doctor\\` names the interrupted state as\n \\`doctor.commit-interrupted\\` and \\`loam validate\\` leads every mode with\n \\`docs.commit-interrupted\\` while the journal sits there; every journaled writer\n recovers a finished predecessor's journal on its next run and reports it as\n \\`recovered\\` in \\`--json\\`.\n- \\`loam new\\`: \\`already-exists\\` — also the answer when a concurrent \\`new\\` for the\n same id wins the race.\n- \\`loam vouch\\`: \\`sources-absent\\`, \\`sources-path-missing\\`, \\`vouch-raced\\`, and the\n wrong-repo pair \\`repository-unavailable\\` / \\`service-mismatch\\`, because\n \\`sources\\` resolve against the service's own checkout and from anywhere else\n those paths are somebody else's.\n- \\`loam archive\\`: \\`not-coherent\\`, \\`living-outside-requirements\\`,\n \\`archive-exists\\` — see the archive gate below.\n- \\`loam unarchive\\`: \\`feature-active\\`, \\`snapshot-missing\\`, \\`snapshot-stale\\`,\n \\`snapshot-corrupt\\`, \\`restore-failed\\` — see \"Taking an archive back\".\n- \\`loam gherkin\\`: \\`gherkin-conflict\\`, plus the same wrong-repo pair, refused\n before anything is written because the generated files land in the repo loam\n is standing in.\n- \\`loam subsystem\\`: \\`subsystem-not-empty\\`, \\`move-uncommitted\\`, \\`move-failed\\`,\n and \\`unknown-target\\` / \\`already-exists\\` / \\`invalid-option\\` for names that\n resolve to nothing, collide in the flat namespace, or break the grammar.\n \\`move-failed\\` is deliberately distinct from \\`merge-failed\\`: the move's own\n transaction rolled back cleanly, nothing changed, and re-running can work.\n- \\`loam verify --record\\` / \\`--results\\` / \\`--contract-results\\`:\n \\`answers-unreadable\\`, \\`answers-mismatch\\`, \\`answers-unevidenced\\`,\n \\`record-federated\\`, \\`record-unreadable\\` and \\`record-raced\\`. Two records for\n different services land in either order — the later one waits, then merges,\n and both attestations survive.\n- \\`loam open\\`: \\`no-members\\`, \\`binding-duplicate\\`, \\`already-exists\\` (the\n workspace file, which loam never silently overwrites — pass \\`--out\\` or\n \\`--force\\`) and \\`invalid-option\\`.\n- \\`loam seed --from fleet.yaml\\`: \\`seed-file-invalid\\`, \\`seed-duplicate-service\\`,\n \\`seed-unknown-subsystem\\`, \\`seed-landscape-edited\\`, \\`already-exists\\` when a\n generated views file in \\`architecture/\\` was written by somebody rather than by\n loam (no \\`// generated by loam\\` first line — seed writes nothing at all in that\n case), and \\`unknown-service\\` for a call endpoint nothing declares. An existing\n service directory is never moved, and nothing is ever deleted.\n- \\`internal\\` — an unexpected throw, the one code with no stable meaning.\n\n\\`--all\\` reports a target per service, a target per feature in flight, and one target\nof kind \\`landscape\\` for the fleet-level checks that belong to no single service.\n\nThree different words for three different questions, and no command conflates them:\n\\`ok\\` — the command ran; \\`valid\\` — the documents pass (\\`validate\\`); \\`verified\\` —\nsomebody says the code was built and showed evidence (\\`verify\\`). A feature can be\nvalid and unverified, or verified and incoherent. Read the one you meant.\n`;\n\n/* The archive gate, unarchive, and dropping a feature continue in\n * ./shipped/archive-gate.ts — one document section split at its own subject\n * seam, concatenated after this one by ../agents-md.ts. */\n"]}
|
|
@@ -18,17 +18,26 @@ 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\`
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
\`
|
|
26
|
-
|
|
21
|
+
\`architecture/subsystems.likec4\` and \`architecture/services.likec4\` are both
|
|
22
|
+
GENERATED by \`loam subsystem sync\` — one view per subsystem from the directory
|
|
23
|
+
tree under \`services/\`, and one overview view per service the fleet map draws.
|
|
24
|
+
Scoping aids, never hand-edited and never a second fleet map; each is stale
|
|
25
|
+
(\`subsystem.views-stale\`, one finding per file) until the next \`sync\`. Their one
|
|
26
|
+
styling opt-in is a \`global { styleGroup subsystems { … } }\` — or
|
|
27
|
+
\`styleGroup services\` — declared in any \`.likec4\` under \`architecture/\`, which
|
|
28
|
+
\`sync\` then references. A diagram you author belongs in the landscape or in a
|
|
29
|
+
file of your own name beside it; an authored view \`of\` an element the generated
|
|
30
|
+
file also draws is legal, and the file that sorts first wins the default
|
|
31
|
+
drill-down target while both stay reachable.
|
|
27
32
|
\`services/<id>/\` holds a boundary's living \`model.likec4\`, \`spec.md\`,
|
|
28
33
|
\`arch.spec.md\`, OpenAPI, AsyncAPI, runbook and health facts — and
|
|
29
34
|
\`services/<…>/<id>/usecases/*.likec4\`, the slot for a \`dynamic view\` over that
|
|
30
35
|
service's OWN containers, tagged \`#req-<Requirement-ID>\`; a flow that crosses
|
|
31
|
-
services lives in \`architecture/usecases/\` and is tagged \`#cap-\` instead.
|
|
36
|
+
services lives in \`architecture/usecases/\` and is tagged \`#cap-\` instead. Title
|
|
37
|
+
a service use case \`'<subsystem path> / <service id> / <use case>'\` — LikeC4
|
|
38
|
+
splits a view title on \`/\` into browser folders, so that convention lands the
|
|
39
|
+
flow in the same folder as the generated overview of its service. Nothing grades
|
|
40
|
+
the title, and nothing grades the slot's absence: presence is never owed.
|
|
32
41
|
\`features/<FEAT>/\` holds a change in flight: \`intent.md\`, \`delta.likec4\`,
|
|
33
42
|
per-service requirement and contract deltas, and \`verification.yaml\`.
|
|
34
43
|
\`features/archive/\` is shipped history.
|
|
@@ -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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2KnB,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; its one styling opt-in is a\n\\`global { styleGroup subsystems { … } }\\` declared in any \\`.likec4\\` under\n\\`architecture/\\`, which \\`sync\\` then references. 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 — and\n\\`services/<…>/<id>/usecases/*.likec4\\`, the slot for a \\`dynamic view\\` over that\nservice's OWN containers, tagged \\`#req-<Requirement-ID>\\`; a flow that crosses\nservices lives in \\`architecture/usecases/\\` and is tagged \\`#cap-\\` instead.\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. Reports are numbered — \\`loam-reports/NNN-YYYY-MM-DD-<slug>.md\\`,\ncited by ordinal — and carry a \\`Status:\\` line, so \\`loam doctor\\` counts the\ndirectory and says which ordinal the next report takes. This is support, not a\nseventh 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. Draw the map's edges in the same pass:\n the brief's \\`landscape.touched\\` is the only place an edgeless element is named,\n and \\`landscape.service-isolated\\` (fleet scope) goes quiet on the first edge.\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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoLnB,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\\` and \\`architecture/services.likec4\\` are both\nGENERATED by \\`loam subsystem sync\\` — one view per subsystem from the directory\ntree under \\`services/\\`, and one overview view per service the fleet map draws.\nScoping aids, never hand-edited and never a second fleet map; each is stale\n(\\`subsystem.views-stale\\`, one finding per file) until the next \\`sync\\`. Their one\nstyling opt-in is a \\`global { styleGroup subsystems { … } }\\` — or\n\\`styleGroup services\\` — declared in any \\`.likec4\\` under \\`architecture/\\`, which\n\\`sync\\` then references. A diagram you author belongs in the landscape or in a\nfile of your own name beside it; an authored view \\`of\\` an element the generated\nfile also draws is legal, and the file that sorts first wins the default\ndrill-down target while both stay reachable.\n\\`services/<id>/\\` holds a boundary's living \\`model.likec4\\`, \\`spec.md\\`,\n\\`arch.spec.md\\`, OpenAPI, AsyncAPI, runbook and health facts — and\n\\`services/<…>/<id>/usecases/*.likec4\\`, the slot for a \\`dynamic view\\` over that\nservice's OWN containers, tagged \\`#req-<Requirement-ID>\\`; a flow that crosses\nservices lives in \\`architecture/usecases/\\` and is tagged \\`#cap-\\` instead. Title\na service use case \\`'<subsystem path> / <service id> / <use case>'\\` — LikeC4\nsplits a view title on \\`/\\` into browser folders, so that convention lands the\nflow in the same folder as the generated overview of its service. Nothing grades\nthe title, and nothing grades the slot's absence: presence is never owed.\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. Reports are numbered — \\`loam-reports/NNN-YYYY-MM-DD-<slug>.md\\`,\ncited by ordinal — and carry a \\`Status:\\` line, so \\`loam doctor\\` counts the\ndirectory and says which ordinal the next report takes. This is support, not a\nseventh 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. Draw the map's edges in the same pass:\n the brief's \\`landscape.touched\\` is the only place an edgeless element is named,\n and \\`landscape.service-isolated\\` (fleet scope) goes quiet on the first edge.\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"]}
|