@ecoma-io/archkeep 0.26.0 → 0.27.0

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.
Files changed (56) hide show
  1. package/cli.mjs +4 -3
  2. package/package.json +1 -1
  3. package/src/architecture-intent/model.mjs +2 -2
  4. package/src/commands/analyze-capability.mjs +2 -2
  5. package/src/commands/change-intent.mjs +2 -2
  6. package/src/commands/change.mjs +6 -3
  7. package/src/commands/check-capability.mjs +2 -2
  8. package/src/commands/check.mjs +3 -5
  9. package/src/commands/compare-capability.mjs +2 -2
  10. package/src/commands/completeness.mjs +2 -2
  11. package/src/commands/delta.mjs +5 -3
  12. package/src/commands/diff.mjs +2 -2
  13. package/src/commands/evolution.mjs +10 -0
  14. package/src/commands/explain-capability.mjs +2 -2
  15. package/src/commands/fitness.mjs +2 -2
  16. package/src/commands/govern-capability.mjs +2 -2
  17. package/src/commands/inspect-capability.mjs +2 -2
  18. package/src/commands/rules-capability.mjs +2 -2
  19. package/src/corpus/goldens/adr.json +2 -2
  20. package/src/corpus/goldens/change.json +6 -5
  21. package/src/corpus/goldens/change.text +2 -2
  22. package/src/corpus/goldens/check.json +2 -2
  23. package/src/corpus/goldens/context.json +2 -2
  24. package/src/corpus/goldens/debt.json +4 -4
  25. package/src/corpus/goldens/debt.text +2 -2
  26. package/src/corpus/goldens/decisions.json +2 -2
  27. package/src/corpus/goldens/delta.json +4 -4
  28. package/src/corpus/goldens/delta.text +1 -1
  29. package/src/corpus/goldens/diff.json +4 -4
  30. package/src/corpus/goldens/diff.text +1 -1
  31. package/src/corpus/goldens/discover.json +2 -2
  32. package/src/corpus/goldens/drift.json +2 -2
  33. package/src/corpus/goldens/evolution.json +4 -2
  34. package/src/corpus/goldens/explain.json +2 -2
  35. package/src/corpus/goldens/fitness.json +2 -2
  36. package/src/corpus/goldens/graph.json +2 -2
  37. package/src/corpus/goldens/health.json +2 -2
  38. package/src/corpus/goldens/history.json +3 -3
  39. package/src/corpus/goldens/history.text +1 -1
  40. package/src/corpus/goldens/impact.json +2 -2
  41. package/src/corpus/goldens/provenance.json +2 -2
  42. package/src/corpus/goldens/reconcile.json +2 -2
  43. package/src/corpus/goldens/report.json +2 -2
  44. package/src/corpus/goldens/report.text +1 -1
  45. package/src/corpus/goldens/scenario.json +2 -2
  46. package/src/corpus/goldens/trajectory.json +3 -3
  47. package/src/corpus/goldens/trajectory.text +1 -1
  48. package/src/corpus/goldens/waivers.json +2 -2
  49. package/src/go-work.mjs +4 -5
  50. package/src/governance/debt-ledger.mjs +5 -2
  51. package/src/governance/evolution-event.mjs +1 -2
  52. package/src/intent/intent-manifest.json +8 -8
  53. package/src/providers/nx-static.mjs +4 -4
  54. package/src/rules/edge-constraints.mjs +4 -5
  55. package/src/rules/index.mjs +8 -10
  56. package/src/tsconfig-paths.mjs +4 -5
package/cli.mjs CHANGED
@@ -57,7 +57,7 @@
57
57
  * declared constraint. `check`, `fitness`, `delta` and `change` are the
58
58
  * verbs whose verdicts carry this code, plus `rules verify` — the
59
59
  * artifact-integrity fold, a bounded verification surface, not a fifth
60
- * architecture carrier (PD-8; `docs/reference/exit-codes.md` owns the
60
+ * architecture carrier (`docs/reference/exit-codes.md` owns the
61
61
  * roster). Every other verb only ever reads.
62
62
  * 2 usage error — unknown command, unknown flag, missing argument, path
63
63
  * outside the tree
@@ -105,7 +105,8 @@ import { containmentViolation } from "./src/containment.mjs";
105
105
  import { UsageError } from "./src/errors.mjs";
106
106
  // Verb imports route through the capability facades: each
107
107
  // `<word>-capability.mjs` module is its word's explicit verb roster — pure
108
- // re-exports, zero judgment (PD-18, docs/architecture/refactor/DECISIONS.md).
108
+ // re-exports, zero judgment. The vocabulary's roster lives in
109
+ // docs/concepts/architecture.md's "The 24 commands".
109
110
  // Non-verb helper modules keep their direct imports.
110
111
  import {
111
112
  discoverCommand,
@@ -1331,7 +1332,7 @@ async function runWaivers(options, { cwd, env }) {
1331
1332
  * (D-09). `check` folds the same `fail` into its own exit 1 by presence, so the
1332
1333
  * two faces agree; the verbs whose verdict carries that code are `check`,
1333
1334
  * `fitness`, `delta` and `change`, plus the `rules verify` artifact-integrity
1334
- * fold (PD-8; `docs/reference/exit-codes.md` owns the roster).
1335
+ * fold (`docs/reference/exit-codes.md` owns the roster).
1335
1336
  *
1336
1337
  * @param {{format: string, output: string|null, config: string|null, paths: string[]}} options
1337
1338
  * @param {{cwd: string, env: {out: Function, err: Function, readGraph?: Function, listFiles?: Function}}} runContext
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ecoma-io/archkeep",
3
- "version": "0.26.0",
3
+ "version": "0.27.0",
4
4
  "description": "Architecture authority for human and agentic software development — deterministic, evidence-backed enforcement of declared architecture.",
5
5
  "keywords": [
6
6
  "architecture",
@@ -12,8 +12,8 @@
12
12
  * is a deterministic comparison (`./judge.mjs`). NO LLM/AI anywhere in the core.
13
13
  *
14
14
  * Which "intent" this is: one of four unrelated surfaces sharing the word —
15
- * PD-13 outcome (c), four surfaces, never one type
16
- * (`../../../../docs/architecture/refactor/DECISIONS.md`). This module is
15
+ * four surfaces, never one type
16
+ * (`../../../../docs/concepts/architecture.md`, "The 24 commands"). This module is
17
17
  * the workspace-declared law: the grammar, validation, and loading of
18
18
  * `architecture-intent.json`, judged against the observed graph by `check`
19
19
  * and `drift`. The other three: the v1.0 evidence-manifest registry
@@ -7,7 +7,7 @@
7
7
  * Pure surface module: no judgment, no defaults, no logic — every export is
8
8
  * a re-export of a command module. `cli.mjs` routes its verb imports through
9
9
  * the facade so the vocabulary's code referent is visible to the import
10
- * graph, not just to a comment (PD-18,
11
- * ../../../../docs/architecture/refactor/DECISIONS.md).
10
+ * graph, not just to a comment — the vocabulary's roster lives in
11
+ * ../../../../docs/concepts/architecture.md's "The 24 commands".
12
12
  */
13
13
  export { discoverCommand, intentJsonFromProposal, intentWriteRefusal } from "./discover.mjs";
@@ -10,8 +10,8 @@
10
10
  * as the reviewable answer to "what did this change do to the architecture?".
11
11
  *
12
12
  * Which "intent" this is: one of four unrelated surfaces sharing the word —
13
- * PD-13 outcome (c), four surfaces, never one type
14
- * (`../../../../docs/architecture/refactor/DECISIONS.md`). This module is
13
+ * four surfaces, never one type
14
+ * (`../../../../docs/concepts/architecture.md`, "The 24 commands"). This module is
15
15
  * the declared-change grammar: one change's expected architectural
16
16
  * consequences, verified by the `change` command against the actual delta.
17
17
  * The other three: the workspace-declared law (`../architecture-intent/` —
@@ -480,8 +480,8 @@ function changeFoldInputProblem(reconciliation, constraints, unprovenReasons) {
480
480
  * before any list, so a malformed one reaching it unguarded can name the
481
481
  * whole run unproven or matched for reasons the counts never supported. The
482
482
  * literals stay hand-rolled per site by decision — the carrier folds are the
483
- * pinned baseline INV-2 names, not a table to be converged
484
- * (`docs/architecture/refactor/AUTHORITY-MAP.md`).
483
+ * pinned baseline, not a table to be converged
484
+ * (`docs/reference/exit-codes.md`'s fold-site statement).
485
485
  *
486
486
  * @param {{matched: object[], unexpected: object[], missingExpected: object[]}} reconciliation
487
487
  * @param {{verdict: string}[]} constraints Judged `fitnessVerdict` rows —
@@ -1000,10 +1000,11 @@ export async function changeCommand(
1000
1000
  // `findings`, never in `debt`. An unproven base (F-CHG-1) or an unjudgeable
1001
1001
  // intent is a no-verdict: no ids are emitted, an in-band note says so, and a
1002
1002
  // change run never fabricates ledger ids over evidence it cannot vouch for.
1003
- /** @type {{introduced: string[], resolved: string[], note?: string}} */
1003
+ /** @type {{judged: boolean, introduced: string[], resolved: string[], note?: string}} the marker is in-band on every shape: `false` on a fail-closed path, `true` from `debtChangeDiff` */
1004
1004
  let debt;
1005
1005
  if (baseEngineGraph === null) {
1006
1006
  debt = {
1007
+ judged: false,
1007
1008
  introduced: [],
1008
1009
  resolved: [],
1009
1010
  note: "base identity unproven — no architecture debt diff can be trusted",
@@ -1013,6 +1014,7 @@ export async function changeCommand(
1013
1014
  const archIntent = await (loadIntentOverride ?? loadIntent)(root, { tracked });
1014
1015
  if (archIntent === undefined || archIntent === null) {
1015
1016
  debt = {
1017
+ judged: false,
1016
1018
  introduced: [],
1017
1019
  resolved: [],
1018
1020
  note: `no '${INTENT_FILE}' tracked — the change event carries no architecture debt ids`,
@@ -1024,6 +1026,7 @@ export async function changeCommand(
1024
1026
  }
1025
1027
  } catch (error) {
1026
1028
  debt = {
1029
+ judged: false,
1027
1030
  introduced: [],
1028
1031
  resolved: [],
1029
1032
  note: `architecture intent could not be judged — no debt ids emitted (${error.message})`,
@@ -5,8 +5,8 @@
5
5
  * Pure surface module: no judgment, no defaults, no logic — every export is
6
6
  * a re-export of a command module. `cli.mjs` routes its verb imports through
7
7
  * the facade so the vocabulary's code referent is visible to the import
8
- * graph, not just to a comment (PD-18,
9
- * ../../../../docs/architecture/refactor/DECISIONS.md).
8
+ * graph, not just to a comment — the vocabulary's roster lives in
9
+ * ../../../../docs/concepts/architecture.md's "The 24 commands".
10
10
  */
11
11
  export { check, sortViolations } from "./check.mjs";
12
12
  export { fitness } from "./fitness.mjs";
@@ -522,14 +522,12 @@ export async function check(
522
522
  // constraint from the edge — so suppression, waiver annotation, sorting and
523
523
  // the SARIF face all treat it as the ordinary violation it is.
524
524
  //
525
- // PD-13 (2026-09-06) pins THIS fold as the documented normalization seam
526
- // (`../../../../docs/architecture/refactor/DECISIONS.md`): the one place
525
+ // This fold is the documented normalization seam — the one place
527
526
  // `judgeEdge`'s markdown-pairing verdicts are reshaped into the exact
528
527
  // `Violation` record `violationOf` (`../rules/index.mjs`) builds — the
529
528
  // families then fold into the one verdict lane as count keys into
530
- // `verdictFor` (`../verdict.mjs`). The canonical statement is the
531
- // "Finding the unowned concept" section of
532
- // `../../../../docs/architecture/refactor/SEMANTIC-MODEL.md`.
529
+ // `verdictFor` (`../verdict.mjs`). The canonical statement is
530
+ // `../../../../docs/concepts/evidence.md`'s "Four finding families".
533
531
  /** @type {object[]} */
534
532
  const markdownRaw = [];
535
533
  if (config !== null && markdownTrack !== null && config.depConstraints.length > 0) {
@@ -7,8 +7,8 @@
7
7
  * Pure surface module: no judgment, no defaults, no logic — every export is
8
8
  * a re-export of a command module. `cli.mjs` routes its verb imports through
9
9
  * the facade so the vocabulary's code referent is visible to the import
10
- * graph, not just to a comment (PD-18,
11
- * ../../../../docs/architecture/refactor/DECISIONS.md).
10
+ * graph, not just to a comment — the vocabulary's roster lives in
11
+ * ../../../../docs/concepts/architecture.md's "The 24 commands".
12
12
  */
13
13
  export { diff } from "./diff.mjs";
14
14
  export { captureBaseline, delta } from "./delta.mjs";
@@ -33,8 +33,8 @@
33
33
  * refusal contract (`./coverage-verdict.mjs`): `coverageVerdict` refuses
34
34
  * `no-verdict` (exit 3), and no status here is derived from it or folds
35
35
  * into it. Two models of "did we see everything", owned by different
36
- * waves — register R1 in `docs/architecture/refactor/SEMANTIC-MODEL.md`
37
- * keeps them separate.
36
+ * waves — register R1 in `../../../../docs/concepts/evidence.md`'s "Register
37
+ * R1" keeps them separate.
38
38
  *
39
39
  * @module
40
40
  */
@@ -479,8 +479,8 @@ function deltaFoldInputProblem(classification, custom) {
479
479
  * The input latch runs first: a bucket the fold cannot read is refused as a
480
480
  * no-verdict whose single reason names it (`refused`), never folded past as a
481
481
  * silently-empty count. The literals stay hand-rolled per site by decision —
482
- * the carrier folds are the pinned baseline INV-2 names, not a table to be
483
- * converged (`docs/architecture/refactor/AUTHORITY-MAP.md`).
482
+ * the carrier folds are the pinned baseline, not a table to be converged
483
+ * (`docs/reference/exit-codes.md`'s fold-site statement).
484
484
  *
485
485
  * Pure and exported for the fold's own tests; `deltaCommand` is its only
486
486
  * production caller.
@@ -1029,12 +1029,13 @@ export async function deltaCommand(
1029
1029
  // gate; the fail-closed branches are an absent intent and an unjudgeable
1030
1030
  // one, each emitting no ids and an in-band note rather than a fabricated
1031
1031
  // clean ledger.
1032
- /** @type {{introduced: string[], resolved: string[], note?: string}} */
1032
+ /** @type {{judged: boolean, introduced: string[], resolved: string[], note?: string}} the marker is in-band on every shape: `false` on a fail-closed path, `true` from `debtChangeDiff` */
1033
1033
  let debt;
1034
1034
  try {
1035
1035
  const archIntent = await (loadIntentOverride ?? loadIntent)(root, { tracked });
1036
1036
  if (archIntent === undefined || archIntent === null) {
1037
1037
  debt = {
1038
+ judged: false,
1038
1039
  introduced: [],
1039
1040
  resolved: [],
1040
1041
  note: `no '${INTENT_FILE}' tracked — the delta event carries no architecture debt ids`,
@@ -1046,6 +1047,7 @@ export async function deltaCommand(
1046
1047
  }
1047
1048
  } catch (error) {
1048
1049
  debt = {
1050
+ judged: false,
1049
1051
  introduced: [],
1050
1052
  resolved: [],
1051
1053
  note: `architecture intent could not be judged — no debt ids emitted (${error.message})`,
@@ -245,8 +245,8 @@ function buildHeadSnapshot(commandContext) {
245
245
  * `edgeEvolutionIdentity` (`../governance/evolution-event.mjs`), the escaped
246
246
  * `source>target:type` string evolution events carry, and the two spellings
247
247
  * are deliberately not unified — each medium keeps exactly one identity
248
- * constructor (`../../../../docs/adr/0008-snapshot-identity-per-family.md`;
249
- * INV-6 in `../../../../docs/architecture/refactor/INVARIANTS.md`). An edge
248
+ * constructor (`../../../../docs/adr/0008-snapshot-identity-per-family.md`).
249
+ * An edge
250
250
  * crosses from a structural diff into an event as its raw
251
251
  * `{source, target, type}` triple, mapped through that function at the
252
252
  * command boundary; a `\0`-joined key written into an event record would
@@ -940,6 +940,16 @@ export function buildEvolutionSummary(comparisons) {
940
940
  });
941
941
  return { verdictDeltas };
942
942
  }
943
+ if (axis === "debt") {
944
+ // The aggregate states whether the debt it unions was judged at every
945
+ // transition (`debtChangeDiff`'s marker) — a summary over a transition
946
+ // that could not judge its debt never reads as a judged clean union.
947
+ return {
948
+ judged: comparisons.every((c) => c.debt === undefined || c.debt.judged === true),
949
+ introduced: collect("introduced"),
950
+ resolved: collect("resolved"),
951
+ };
952
+ }
943
953
  return {
944
954
  introduced: collect("introduced"),
945
955
  resolved: collect("resolved"),
@@ -5,7 +5,7 @@
5
5
  * Pure surface module: no judgment, no defaults, no logic — every export is
6
6
  * a re-export of a command module. `cli.mjs` routes its verb imports through
7
7
  * the facade so the vocabulary's code referent is visible to the import
8
- * graph, not just to a comment (PD-18,
9
- * ../../../../docs/architecture/refactor/DECISIONS.md).
8
+ * graph, not just to a comment — the vocabulary's roster lives in
9
+ * ../../../../docs/concepts/architecture.md's "The 24 commands".
10
10
  */
11
11
  export { explain } from "./explain.mjs";
@@ -122,8 +122,8 @@ export function declaresFitness(config) {
122
122
  * exit over a run the fold could not read. A verdict outside the four states
123
123
  * is refused as a no-verdict whose single reason names it (`refused`), never
124
124
  * folded past. The literals stay hand-rolled per site by decision — the
125
- * carrier folds are the pinned baseline INV-2 names, not a table to be
126
- * converged (`docs/architecture/refactor/AUTHORITY-MAP.md`).
125
+ * carrier folds are the pinned baseline, not a table to be
126
+ * converged (`docs/reference/exit-codes.md`'s fold-site statement).
127
127
  *
128
128
  * `overall.decisions` is validated for the same reason the delta fold
129
129
  * validates buckets the fold itself does not count first: `result.functions`
@@ -5,8 +5,8 @@
5
5
  * Pure surface module: no judgment, no defaults, no logic — every export is
6
6
  * a re-export of a command module. `cli.mjs` routes its verb imports through
7
7
  * the facade so the vocabulary's code referent is visible to the import
8
- * graph, not just to a comment (PD-18,
9
- * ../../../../docs/architecture/refactor/DECISIONS.md).
8
+ * graph, not just to a comment — the vocabulary's roster lives in
9
+ * ../../../../docs/concepts/architecture.md's "The 24 commands".
10
10
  */
11
11
  export { waivers } from "./waivers.mjs";
12
12
  export { report } from "./report.mjs";
@@ -6,8 +6,8 @@
6
6
  * Pure surface module: no judgment, no defaults, no logic — every export is
7
7
  * a re-export of a command module. `cli.mjs` routes its verb imports through
8
8
  * the facade so the vocabulary's code referent is visible to the import
9
- * graph, not just to a comment (PD-18,
10
- * ../../../../docs/architecture/refactor/DECISIONS.md).
9
+ * graph, not just to a comment — the vocabulary's roster lives in
10
+ * ../../../../docs/concepts/architecture.md's "The 24 commands".
11
11
  */
12
12
  export { graph } from "./graph.mjs";
13
13
  export { impact } from "./impact.mjs";
@@ -5,8 +5,8 @@
5
5
  * Pure surface module: no judgment, no defaults, no logic — every export is
6
6
  * a re-export of a command module. `cli.mjs` routes its verb imports through
7
7
  * the facade so the vocabulary's code referent is visible to the import
8
- * graph, not just to a comment (PD-18,
9
- * ../../../../docs/architecture/refactor/DECISIONS.md).
8
+ * graph, not just to a comment — the vocabulary's roster lives in
9
+ * ../../../../docs/concepts/architecture.md's "The 24 commands".
10
10
  */
11
11
  export {
12
12
  rulesAddCommand,
@@ -2,11 +2,11 @@
2
2
  "schemaVersion": 2,
3
3
  "tool": {
4
4
  "name": "@ecoma-io/archkeep",
5
- "version": "0.26.0"
5
+ "version": "0.27.0"
6
6
  },
7
7
  "command": "adr",
8
8
  "workspace": {
9
- "root": "/tmp/archkeep-golden-fixture",
9
+ "root": "<fixture-root>",
10
10
  "provider": "native",
11
11
  "marker": "docs/adr",
12
12
  "provenance": null
@@ -2,11 +2,11 @@
2
2
  "schemaVersion": 2,
3
3
  "tool": {
4
4
  "name": "@ecoma-io/archkeep",
5
- "version": "0.26.0"
5
+ "version": "0.27.0"
6
6
  },
7
7
  "command": "change",
8
8
  "workspace": {
9
- "root": "/tmp/archkeep-golden-fixture",
9
+ "root": "<fixture-root>",
10
10
  "provider": "native",
11
11
  "marker": "archkeep.json",
12
12
  "provenance": {
@@ -28,7 +28,7 @@
28
28
  },
29
29
  "result": {
30
30
  "intent": {
31
- "file": "/tmp/archkeep-golden-fixture/.archkeep-change.json",
31
+ "file": "<fixture-root>/.archkeep-change.json",
32
32
  "version": "1",
33
33
  "base": {
34
34
  "commit": "1fd51709c377d99a6139891e1200291cf08aede9"
@@ -42,10 +42,10 @@
42
42
  }
43
43
  },
44
44
  "baseline": {
45
- "path": "/tmp/archkeep-golden-fixture/.archkeep-delta.json",
45
+ "path": "<fixture-root>/.archkeep-delta.json",
46
46
  "tool": {
47
47
  "name": "@ecoma-io/archkeep",
48
- "version": "0.26.0"
48
+ "version": "0.27.0"
49
49
  },
50
50
  "provider": "native",
51
51
  "provenance": {
@@ -87,6 +87,7 @@
87
87
  "decisions": []
88
88
  },
89
89
  "debt": {
90
+ "judged": true,
90
91
  "introduced": [],
91
92
  "resolved": []
92
93
  }
@@ -1,5 +1,5 @@
1
- intent /tmp/archkeep-golden-fixture/.archkeep-change.json — base 1fd51709
2
- baseline /tmp/archkeep-golden-fixture/.archkeep-delta.json — 1fd51709, 2 records, 3 projects
1
+ intent <fixture-root>/.archkeep-change.json — base 1fd51709
2
+ baseline <fixture-root>/.archkeep-delta.json — 1fd51709, 2 records, 3 projects
3
3
  head 1fd51709, 3 projects
4
4
  reconciliation ✔ MATCHED — the delta is exactly the declared change
5
5
  workspace law 0 live violations under the current law — informational; archkeep check remains the authoritative verdict
@@ -2,11 +2,11 @@
2
2
  "schemaVersion": 2,
3
3
  "tool": {
4
4
  "name": "@ecoma-io/archkeep",
5
- "version": "0.26.0"
5
+ "version": "0.27.0"
6
6
  },
7
7
  "command": "check",
8
8
  "workspace": {
9
- "root": "/tmp/archkeep-golden-fixture",
9
+ "root": "<fixture-root>",
10
10
  "provider": "native",
11
11
  "marker": "archkeep.json",
12
12
  "provenance": {
@@ -2,11 +2,11 @@
2
2
  "schemaVersion": 2,
3
3
  "tool": {
4
4
  "name": "@ecoma-io/archkeep",
5
- "version": "0.26.0"
5
+ "version": "0.27.0"
6
6
  },
7
7
  "command": "context",
8
8
  "workspace": {
9
- "root": "/tmp/archkeep-golden-fixture",
9
+ "root": "<fixture-root>",
10
10
  "provider": "native",
11
11
  "marker": "archkeep.json",
12
12
  "provenance": {
@@ -2,11 +2,11 @@
2
2
  "schemaVersion": 2,
3
3
  "tool": {
4
4
  "name": "@ecoma-io/archkeep",
5
- "version": "0.26.0"
5
+ "version": "0.27.0"
6
6
  },
7
7
  "command": "debt",
8
8
  "workspace": {
9
- "root": "/tmp/archkeep-golden-fixture",
9
+ "root": "<fixture-root>",
10
10
  "provider": "native",
11
11
  "marker": "archkeep.json",
12
12
  "provenance": {
@@ -31,10 +31,10 @@
31
31
  ]
32
32
  },
33
33
  "result": {
34
- "dir": "/tmp/archkeep-golden-fixture/.archkeep-history",
34
+ "dir": "<fixture-root>/.archkeep-history",
35
35
  "snapshots": 1,
36
36
  "agings": false,
37
- "sampleTime": "2026-09-07T06:50:29.512Z",
37
+ "sampleTime": "2026-09-08T10:33:14.692Z",
38
38
  "entries": [],
39
39
  "resolved": [],
40
40
  "total": 0,
@@ -1,7 +1,7 @@
1
- debt /tmp/archkeep-golden-fixture/.archkeep-history
1
+ debt <fixture-root>/.archkeep-history
2
2
  0 entries across 1 snapshot — ages not yet established (fewer than two snapshots)
3
3
  ✔ no architecture debt — no waivers, aspirational gaps, drift or unresolved intent
4
4
  no event store linked — lifecycle refs unavailable
5
5
  total 0 entries · byKind: waiver 0, expired-waiver 0, aspirational-gap 0, drift 0, unresolved 0 · bySeverity: high 0, medium 0, low 0
6
- sampled 2026-09-07T06:50:29.192Z
6
+ sampled 2026-09-08T10:33:14.369Z
7
7
  ✔ complete (2 imports in 3 files across 3 projects)
@@ -2,11 +2,11 @@
2
2
  "schemaVersion": 2,
3
3
  "tool": {
4
4
  "name": "@ecoma-io/archkeep",
5
- "version": "0.26.0"
5
+ "version": "0.27.0"
6
6
  },
7
7
  "command": "decisions",
8
8
  "workspace": {
9
- "root": "/tmp/archkeep-golden-fixture",
9
+ "root": "<fixture-root>",
10
10
  "provider": "native",
11
11
  "marker": "docs/adr",
12
12
  "provenance": null
@@ -2,11 +2,11 @@
2
2
  "schemaVersion": 2,
3
3
  "tool": {
4
4
  "name": "@ecoma-io/archkeep",
5
- "version": "0.26.0"
5
+ "version": "0.27.0"
6
6
  },
7
7
  "command": "delta",
8
8
  "workspace": {
9
- "root": "/tmp/archkeep-golden-fixture",
9
+ "root": "<fixture-root>",
10
10
  "provider": "native",
11
11
  "marker": "archkeep.json",
12
12
  "provenance": {
@@ -28,10 +28,10 @@
28
28
  },
29
29
  "result": {
30
30
  "baseline": {
31
- "path": "/tmp/archkeep-golden-fixture/.archkeep-delta.json",
31
+ "path": "<fixture-root>/.archkeep-delta.json",
32
32
  "tool": {
33
33
  "name": "@ecoma-io/archkeep",
34
- "version": "0.26.0"
34
+ "version": "0.27.0"
35
35
  },
36
36
  "provider": "native",
37
37
  "provenance": {
@@ -1,4 +1,4 @@
1
- baseline /tmp/archkeep-golden-fixture/.archkeep-delta.json — 1fd51709, 2 records, 3 projects
1
+ baseline <fixture-root>/.archkeep-delta.json — 1fd51709, 2 records, 3 projects
2
2
  head 1fd51709, 2 records, 3 projects
3
3
  ✔ no introduced violations — compared baseline 1fd51709 (2 records) against head 1fd51709 (2 records, 3 analyzed files, 3 projects)
4
4
  classifications none
@@ -2,11 +2,11 @@
2
2
  "schemaVersion": 2,
3
3
  "tool": {
4
4
  "name": "@ecoma-io/archkeep",
5
- "version": "0.26.0"
5
+ "version": "0.27.0"
6
6
  },
7
7
  "command": "diff",
8
8
  "workspace": {
9
- "root": "/tmp/archkeep-golden-fixture",
9
+ "root": "<fixture-root>",
10
10
  "provider": "native",
11
11
  "marker": "archkeep.json",
12
12
  "provenance": {
@@ -30,10 +30,10 @@
30
30
  },
31
31
  "result": {
32
32
  "baseline": {
33
- "path": "/tmp/archkeep-golden-fixture/.archkeep-graph.json",
33
+ "path": "<fixture-root>/.archkeep-graph.json",
34
34
  "projects": 3,
35
35
  "edges": 2,
36
- "toolVersion": "0.26.0",
36
+ "toolVersion": "0.27.0",
37
37
  "provenance": {
38
38
  "commit": "1fd51709c377d99a6139891e1200291cf08aede9",
39
39
  "remote": null,
@@ -1,4 +1,4 @@
1
- baseline /tmp/archkeep-golden-fixture/.archkeep-graph.json — 3 projects, 2 edges
1
+ baseline <fixture-root>/.archkeep-graph.json — 3 projects, 2 edges
2
2
  head 3 projects, 2 edges
3
3
  ✔ no boundary-rule impact
4
4
  ✔ no changes between baseline and head (2 imports in 3 files across 3 projects; per-edge rule-impact covers only depConstraints (3 of 15 violation types; standing edges adjacent to a tags-changed project are re-judged under both sides' tags). A dependency with no rule-impact may still violate npm-ban, circular-dependency, lazy-load, or other rules that require import-site details. Run check for the complete verdict.)
@@ -2,11 +2,11 @@
2
2
  "schemaVersion": 2,
3
3
  "tool": {
4
4
  "name": "@ecoma-io/archkeep",
5
- "version": "0.26.0"
5
+ "version": "0.27.0"
6
6
  },
7
7
  "command": "discover",
8
8
  "workspace": {
9
- "root": "/tmp/archkeep-golden-fixture",
9
+ "root": "<fixture-root>",
10
10
  "provider": "native",
11
11
  "marker": "archkeep.json",
12
12
  "provenance": {
@@ -2,11 +2,11 @@
2
2
  "schemaVersion": 2,
3
3
  "tool": {
4
4
  "name": "@ecoma-io/archkeep",
5
- "version": "0.26.0"
5
+ "version": "0.27.0"
6
6
  },
7
7
  "command": "drift",
8
8
  "workspace": {
9
- "root": "/tmp/archkeep-golden-fixture",
9
+ "root": "<fixture-root>",
10
10
  "provider": "native",
11
11
  "marker": "archkeep.json",
12
12
  "provenance": {
@@ -2,11 +2,11 @@
2
2
  "schemaVersion": 2,
3
3
  "tool": {
4
4
  "name": "@ecoma-io/archkeep",
5
- "version": "0.26.0"
5
+ "version": "0.27.0"
6
6
  },
7
7
  "command": "evolution",
8
8
  "workspace": {
9
- "root": "/tmp/archkeep-golden-fixture",
9
+ "root": "<fixture-root>",
10
10
  "provider": "native",
11
11
  "marker": "archkeep.json",
12
12
  "provenance": {
@@ -228,6 +228,7 @@
228
228
  "unknown": []
229
229
  },
230
230
  "debt": {
231
+ "judged": true,
231
232
  "introduced": [],
232
233
  "resolved": []
233
234
  },
@@ -309,6 +310,7 @@
309
310
  "unknown": []
310
311
  },
311
312
  "debt": {
313
+ "judged": true,
312
314
  "introduced": [],
313
315
  "resolved": []
314
316
  },
@@ -2,11 +2,11 @@
2
2
  "schemaVersion": 2,
3
3
  "tool": {
4
4
  "name": "@ecoma-io/archkeep",
5
- "version": "0.26.0"
5
+ "version": "0.27.0"
6
6
  },
7
7
  "command": "explain",
8
8
  "workspace": {
9
- "root": "/tmp/archkeep-golden-fixture",
9
+ "root": "<fixture-root>",
10
10
  "provider": "native",
11
11
  "marker": "archkeep.json",
12
12
  "provenance": {
@@ -2,11 +2,11 @@
2
2
  "schemaVersion": 2,
3
3
  "tool": {
4
4
  "name": "@ecoma-io/archkeep",
5
- "version": "0.26.0"
5
+ "version": "0.27.0"
6
6
  },
7
7
  "command": "fitness",
8
8
  "workspace": {
9
- "root": "/tmp/archkeep-golden-fixture",
9
+ "root": "<fixture-root>",
10
10
  "provider": "native",
11
11
  "marker": "archkeep.json",
12
12
  "provenance": {
@@ -2,11 +2,11 @@
2
2
  "schemaVersion": 2,
3
3
  "tool": {
4
4
  "name": "@ecoma-io/archkeep",
5
- "version": "0.26.0"
5
+ "version": "0.27.0"
6
6
  },
7
7
  "command": "graph",
8
8
  "workspace": {
9
- "root": "/tmp/archkeep-golden-fixture",
9
+ "root": "<fixture-root>",
10
10
  "provider": "native",
11
11
  "marker": "archkeep.json",
12
12
  "provenance": {
@@ -2,11 +2,11 @@
2
2
  "schemaVersion": 2,
3
3
  "tool": {
4
4
  "name": "@ecoma-io/archkeep",
5
- "version": "0.26.0"
5
+ "version": "0.27.0"
6
6
  },
7
7
  "command": "health",
8
8
  "workspace": {
9
- "root": "/tmp/archkeep-golden-fixture",
9
+ "root": "<fixture-root>",
10
10
  "provider": "native",
11
11
  "marker": "archkeep.json",
12
12
  "provenance": {
@@ -2,11 +2,11 @@
2
2
  "schemaVersion": 2,
3
3
  "tool": {
4
4
  "name": "@ecoma-io/archkeep",
5
- "version": "0.26.0"
5
+ "version": "0.27.0"
6
6
  },
7
7
  "command": "history",
8
8
  "workspace": {
9
- "root": "/tmp/archkeep-golden-fixture",
9
+ "root": "<fixture-root>",
10
10
  "provider": "native",
11
11
  "marker": "archkeep.json",
12
12
  "provenance": {
@@ -29,7 +29,7 @@
29
29
  ]
30
30
  },
31
31
  "result": {
32
- "dir": "/tmp/archkeep-golden-fixture/.archkeep-history",
32
+ "dir": "<fixture-root>/.archkeep-history",
33
33
  "captured": null,
34
34
  "snapshots": [
35
35
  {
@@ -1,4 +1,4 @@
1
- history /tmp/archkeep-golden-fixture/.archkeep-history
1
+ history <fixture-root>/.archkeep-history
2
2
  1 snapshot, 0 transitions (2 imports in 3 files across 3 projects)
3
3
  0 0001-71341a04.json 71341a04
4
4
  ✔ one snapshot, no transitions yet — capture again after an architectural change
@@ -2,11 +2,11 @@
2
2
  "schemaVersion": 2,
3
3
  "tool": {
4
4
  "name": "@ecoma-io/archkeep",
5
- "version": "0.26.0"
5
+ "version": "0.27.0"
6
6
  },
7
7
  "command": "impact",
8
8
  "workspace": {
9
- "root": "/tmp/archkeep-golden-fixture",
9
+ "root": "<fixture-root>",
10
10
  "provider": "native",
11
11
  "marker": "archkeep.json",
12
12
  "provenance": {
@@ -2,11 +2,11 @@
2
2
  "schemaVersion": 2,
3
3
  "tool": {
4
4
  "name": "@ecoma-io/archkeep",
5
- "version": "0.26.0"
5
+ "version": "0.27.0"
6
6
  },
7
7
  "command": "provenance",
8
8
  "workspace": {
9
- "root": "/tmp/archkeep-golden-fixture",
9
+ "root": "<fixture-root>",
10
10
  "provider": "native",
11
11
  "marker": "archkeep.json",
12
12
  "provenance": {
@@ -2,11 +2,11 @@
2
2
  "schemaVersion": 2,
3
3
  "tool": {
4
4
  "name": "@ecoma-io/archkeep",
5
- "version": "0.26.0"
5
+ "version": "0.27.0"
6
6
  },
7
7
  "command": "reconcile",
8
8
  "workspace": {
9
- "root": "/tmp/archkeep-golden-fixture",
9
+ "root": "<fixture-root>",
10
10
  "provider": "native",
11
11
  "marker": "archkeep.json",
12
12
  "provenance": {
@@ -2,11 +2,11 @@
2
2
  "schemaVersion": 2,
3
3
  "tool": {
4
4
  "name": "@ecoma-io/archkeep",
5
- "version": "0.26.0"
5
+ "version": "0.27.0"
6
6
  },
7
7
  "command": "report",
8
8
  "workspace": {
9
- "root": "/tmp/archkeep-golden-fixture",
9
+ "root": "<fixture-root>",
10
10
  "provider": "native",
11
11
  "marker": "archkeep.json",
12
12
  "provenance": {
@@ -1,7 +1,7 @@
1
1
  architecture governance report — every surface reached a verdict
2
2
 
3
3
  provenance
4
- root /tmp/archkeep-golden-fixture
4
+ root <fixture-root>
5
5
  provider native (archkeep.json)
6
6
  policy module-boundaries.config.mjs
7
7
  commit 1fd51709c377d99a6139891e1200291cf08aede9
@@ -2,11 +2,11 @@
2
2
  "schemaVersion": 2,
3
3
  "tool": {
4
4
  "name": "@ecoma-io/archkeep",
5
- "version": "0.26.0"
5
+ "version": "0.27.0"
6
6
  },
7
7
  "command": "scenario",
8
8
  "workspace": {
9
- "root": "/tmp/archkeep-golden-fixture",
9
+ "root": "<fixture-root>",
10
10
  "provider": "native",
11
11
  "marker": "archkeep.json",
12
12
  "provenance": {
@@ -2,11 +2,11 @@
2
2
  "schemaVersion": 2,
3
3
  "tool": {
4
4
  "name": "@ecoma-io/archkeep",
5
- "version": "0.26.0"
5
+ "version": "0.27.0"
6
6
  },
7
7
  "command": "trajectory",
8
8
  "workspace": {
9
- "root": "/tmp/archkeep-golden-fixture",
9
+ "root": "<fixture-root>",
10
10
  "provider": "native",
11
11
  "marker": "archkeep.json",
12
12
  "provenance": {
@@ -30,7 +30,7 @@
30
30
  ]
31
31
  },
32
32
  "result": {
33
- "dir": "/tmp/archkeep-golden-fixture/.archkeep-history",
33
+ "dir": "<fixture-root>/.archkeep-history",
34
34
  "observations": {
35
35
  "count": 1,
36
36
  "basis": "graph_snapshots",
@@ -1,4 +1,4 @@
1
- trajectory /tmp/archkeep-golden-fixture/.archkeep-history
1
+ trajectory <fixture-root>/.archkeep-history
2
2
  1 observation (graph_snapshots), 0 transitions
3
3
  ✖ insufficient_history: a trajectory needs at least two observations — derived values are unavailable, not zero
4
4
  signals architecture 0 · policy 0 · provider 0 · code drift 0 · incomparable 0 · unchanged 0
@@ -2,11 +2,11 @@
2
2
  "schemaVersion": 2,
3
3
  "tool": {
4
4
  "name": "@ecoma-io/archkeep",
5
- "version": "0.26.0"
5
+ "version": "0.27.0"
6
6
  },
7
7
  "command": "waivers",
8
8
  "workspace": {
9
- "root": "/tmp/archkeep-golden-fixture",
9
+ "root": "<fixture-root>",
10
10
  "provider": "native",
11
11
  "marker": "archkeep.json",
12
12
  "provenance": {
package/src/go-work.mjs CHANGED
@@ -276,13 +276,12 @@ function useDirectory(usePath, workspaceRoot) {
276
276
  * - **`goWorkOutsideUse`** — a `use` entry above the workspace root. Whatever
277
277
  * it builds, no run over this workspace can cover it.
278
278
  *
279
- * One of the FOUR finding families — PD-13 (2026-09-06) outcome (c): no
279
+ * One of the FOUR finding families: no
280
280
  * Finding supertype exists, and the relationship pin lives on
281
- * `./rules/index.mjs`'s `violationOf` header. These findings stay this
281
+ * `./rules/index.mjs`'s `violationOf` header (stated in
282
+ * `../../../docs/concepts/evidence.md`'s "Four finding families"). These findings stay this
282
283
  * family's own shape and fold into the one verdict lane as count keys into
283
- * `verdictFor` (`./verdict.mjs`). The canonical statement is the
284
- * "Finding — the unowned concept" section of
285
- * `../../../docs/architecture/refactor/SEMANTIC-MODEL.md`.
284
+ * `verdictFor` (`./verdict.mjs`).
286
285
  *
287
286
  * @param {{ uses: { path: string, line: number, column: number }[],
288
287
  * workspaceRoot: string,
@@ -208,7 +208,10 @@ export function driftFactOf(finding) {
208
208
  *
209
209
  * @param {object} baseVerdict A `judgeIntent` result over the base graph.
210
210
  * @param {object} headVerdict A `judgeIntent` result over the head graph.
211
- * @returns {{introduced: string[], resolved: string[]}} Stable debt ids.
211
+ * @returns {{judged: true, introduced: string[], resolved: string[]}} Stable
212
+ * debt ids, marked judged — the in-band complement of `judged: false`, so a
213
+ * consumer can always distinguish "no debt existed" from "debt could not be
214
+ * judged" (see `../../AGENTS.md`'s invariant).
212
215
  */
213
216
  export function debtChangeDiff(baseVerdict, headVerdict) {
214
217
  const driftOf = (v) => (v.findings ?? []).map((f) => debtFactId("drift", driftFactOf(f)));
@@ -218,7 +221,7 @@ export function debtChangeDiff(baseVerdict, headVerdict) {
218
221
  const headIds = new Set([...driftOf(headVerdict), ...gapOf(headVerdict)]);
219
222
  const introduced = [...headIds].filter((id) => !baseIds.has(id)).sort();
220
223
  const resolved = [...baseIds].filter((id) => !headIds.has(id)).sort();
221
- return { introduced, resolved };
224
+ return { judged: true, introduced, resolved };
222
225
  }
223
226
  /**
224
227
  * Reduces an `opts.events` value to a loaded event array, or `null` when no
@@ -198,8 +198,7 @@ export function escapeIdentityField(value) {
198
198
  * index maps, `trajectory`'s persistence sets — and is never stored. Different
199
199
  * media, one law: each family keeps exactly one identity constructor, and
200
200
  * consumers consume a constructor's output rather than re-deriving a second
201
- * spelling of it (`../../../../docs/adr/0008-snapshot-identity-per-family.md`,
202
- * INV-6 in `../../../../docs/architecture/refactor/INVARIANTS.md`). An edge
201
+ * spelling of it (`../../../../docs/adr/0008-snapshot-identity-per-family.md`). An edge
203
202
  * reaches this module only as its raw triple, never as a pre-built string
204
203
  * from either spelling (`evolutionBoundary` below refuses one), and a
205
204
  * `\0`-joined diff key written into an event would give one edge two
@@ -52,7 +52,7 @@
52
52
  "type": "source-evidence",
53
53
  "path": "cli.mjs",
54
54
  "assertion": "Exit codes 0/1/3 distinguish clean/findings/cannot-look",
55
- "sha256": "2b6590f4039464d3569727d0a73db61dd86c18648a519ee034ebcc2d845ecfc7"
55
+ "sha256": "536fef05cdf8d6ec8a5c364819d2dcbf61cdcf75b638463e98b89d6073e27851"
56
56
  }
57
57
  ],
58
58
  "status": "proven"
@@ -66,13 +66,13 @@
66
66
  "type": "behavioral-test",
67
67
  "path": "src/intent/intent.test.mjs",
68
68
  "assertion": "analysis output conforms to the frozen contract schema (no extra verdict/policy fields); analysis output is invariant under project tag changes (three workspaces differing only in project tag fields compared byte-for-byte)",
69
- "sha256": "749414363ef9991ae3697fc00ab5969751666867792d4bb4dbe528ec47ccd740"
69
+ "sha256": "8c481f1230ae8700469816018fba99017a0014920b12bebdf262ceb241cba745"
70
70
  },
71
71
  {
72
72
  "type": "architecture-test",
73
73
  "path": "src/intent/intent.test.mjs",
74
74
  "assertion": "the gate walks every production analysis module and fails when judging vocabulary (judge/forbid/permit/allow/ban) appears in code",
75
- "sha256": "749414363ef9991ae3697fc00ab5969751666867792d4bb4dbe528ec47ccd740"
75
+ "sha256": "8c481f1230ae8700469816018fba99017a0014920b12bebdf262ceb241cba745"
76
76
  },
77
77
  {
78
78
  "type": "source-evidence",
@@ -84,7 +84,7 @@
84
84
  "type": "source-evidence",
85
85
  "path": "AGENTS.md",
86
86
  "assertion": "src/graph/ is a lossy view of analysis, on purpose; src/analysis/ never judges",
87
- "sha256": "552b54c1956370f024ffeecec95c0e0941a0c66d4a14094045b444a25a27f913"
87
+ "sha256": "6ab8eef7a1ec2a8bde81393880cc6d29b1f089b01ffec403b31846c5d3a1a830"
88
88
  }
89
89
  ],
90
90
  "status": "proven"
@@ -136,7 +136,7 @@
136
136
  "type": "source-evidence",
137
137
  "path": "src/commands/diff.mjs",
138
138
  "assertion": "parseBaseline validates schemaVersion; refuses unknown versions",
139
- "sha256": "4d44eea475cd4b06122a405718203d2e0018a163c1d42b17324400e7e4de5eea"
139
+ "sha256": "59e6e8f1cb0535cbec241f6daf99c10f5a679c798e66fcc1f4afb5329bc6497a"
140
140
  }
141
141
  ],
142
142
  "status": "proven"
@@ -156,7 +156,7 @@
156
156
  "type": "source-evidence",
157
157
  "path": "src/commands/diff.mjs",
158
158
  "assertion": "computeDiff returns structural diff; policyMismatch detected via fingerprint; computeRuleImpact for depConstraints-only context",
159
- "sha256": "4d44eea475cd4b06122a405718203d2e0018a163c1d42b17324400e7e4de5eea"
159
+ "sha256": "59e6e8f1cb0535cbec241f6daf99c10f5a679c798e66fcc1f4afb5329bc6497a"
160
160
  }
161
161
  ],
162
162
  "status": "proven"
@@ -236,7 +236,7 @@
236
236
  "type": "behavioral-test",
237
237
  "path": "src/intent/intent.test.mjs",
238
238
  "assertion": "depConstraints verdicts from judgeEdge agree with evaluate in both directions (violating edge found by both, legal edge reported by neither); explain includes the same violations as evaluate at a given site",
239
- "sha256": "749414363ef9991ae3697fc00ab5969751666867792d4bb4dbe528ec47ccd740"
239
+ "sha256": "8c481f1230ae8700469816018fba99017a0014920b12bebdf262ceb241cba745"
240
240
  },
241
241
  {
242
242
  "type": "behavioral-test",
@@ -266,7 +266,7 @@
266
266
  "type": "source-evidence",
267
267
  "path": "src/commands/diff.mjs",
268
268
  "assertion": "coverage.notes warns when ruleImpact is computed (depConstraints only, 3 of 15)",
269
- "sha256": "4d44eea475cd4b06122a405718203d2e0018a163c1d42b17324400e7e4de5eea"
269
+ "sha256": "59e6e8f1cb0535cbec241f6daf99c10f5a679c798e66fcc1f4afb5329bc6497a"
270
270
  },
271
271
  {
272
272
  "type": "documentation",
@@ -2,10 +2,10 @@
2
2
  * The Nx provider's static acquisition — the graph built from the tree's own
3
3
  * tracked `project.json` files, with no Nx process asked.
4
4
  *
5
- * This is the acquisition `../lsp/workspace-index.mjs` composed inline until
6
- * the Phase 7 collapse: a language server is spawned by an editor, in a
7
- * directory, with nothing else — no `nx` binary to resolve, and a spawn per
8
- * index build would put `nx graph` on every file save. So beside
5
+ * This is the acquisition `../lsp/workspace-index.mjs` composes: a language
6
+ * server is spawned by an editor, in a directory, with nothing else — no `nx`
7
+ * binary to resolve, and a spawn per index build would put `nx graph` on
8
+ * every file save. So beside
9
9
  * `./nx.mjs`'s `readProjectGraph` (which asks Nx itself and is what
10
10
  * `../../cli.mjs`'s `check` runs) this module builds the same `{nodes,
11
11
  * dependencies}`-shaped starting point — here just the nodes; the caller
@@ -66,14 +66,13 @@ import {
66
66
  * table — it does NOT mean the edge is free of all boundary violations (see
67
67
  * this module's header for what is not checked).
68
68
  *
69
- * One of the FOUR finding families — PD-13 (2026-09-06) outcome (c): no
69
+ * One of the FOUR finding families: no
70
70
  * Finding supertype exists, and the relationship pin lives on `./index.mjs`'s
71
- * `violationOf` header. These verdicts are NOT `Violation` records: the
71
+ * `violationOf` header (stated in `../../../../docs/concepts/evidence.md`'s
72
+ * "Four finding families"). These verdicts are NOT `Violation` records: the
72
73
  * markdown-pairing fold in `../commands/check.mjs` reshapes each into the
73
74
  * exact record `violationOf` builds, and the families fold into the one
74
- * verdict lane as count keys into `verdictFor` (`../verdict.mjs`). The
75
- * canonical statement is the "Finding — the unowned concept" section of
76
- * `../../../../docs/architecture/refactor/SEMANTIC-MODEL.md`.
75
+ * verdict lane as count keys into `verdictFor` (`../verdict.mjs`).
77
76
  *
78
77
  * @param {{source: string, target: string}} edge The graph edge to judge.
79
78
  * @param {object} nodes The project graph's `nodes` map (carries `data.tags`).
@@ -425,20 +425,18 @@ export function exemptResolvedFile(site, exemptedFiles) {
425
425
  }
426
426
 
427
427
  /**
428
- * Builds one `Violation` — the rules lane's canonical violation record (PD-13
429
- * (2026-09-06) in `../../../../docs/architecture/refactor/DECISIONS.md`: the
430
- * Violation concept ruled outcome (a), this constructor its one home).
428
+ * Builds one `Violation` — the rules lane's canonical violation record (the
429
+ * relationship pin below, stated in `docs/concepts/evidence.md`).
431
430
  *
432
431
  * This is also one of the FOUR finding families — `violationOf` here,
433
432
  * `judgeEdge` (`./edge-constraints.mjs`), `compareGoWork` (`../go-work.mjs`)
434
433
  * and `judgeTsconfigPaths` (`../tsconfig-paths.mjs`) — and no Finding
435
- * supertype exists (PD-13 outcome (c)): what binds the four is the
436
- * relationship pin. Each family folds into the one verdict lane as count
437
- * keys into `verdictFor` (`../verdict.mjs`), and `../commands/check.mjs`'s
438
- * markdown fold is the documented seam where `judgeEdge`'s verdicts are
439
- * reshaped into the exact record this function builds. The canonical
440
- * statement is the "Finding — the unowned concept" section of
441
- * `../../../../docs/architecture/refactor/SEMANTIC-MODEL.md`.
434
+ * supertype exists: what binds the four is the relationship pin, stated in
435
+ * `../../../../docs/concepts/evidence.md`'s "Four finding families". Each
436
+ * family folds into the one verdict lane as count keys into `verdictFor`
437
+ * (`../verdict.mjs`), and `../commands/check.mjs`'s markdown fold is the
438
+ * documented seam where `judgeEdge`'s verdicts are reshaped into the exact
439
+ * record this function builds.
442
440
  */
443
441
  function violationOf(site, sourceProject, targetProject, messageId, data = {}, constraint = null) {
444
442
  return {
@@ -114,13 +114,12 @@ function probeDirectory(target, base, root) {
114
114
  * need no filesystem: the table and its base come from the resolver's own
115
115
  * parsed context, and existence arrives as a predicate.
116
116
  *
117
- * One of the FOUR finding families — PD-13 (2026-09-06) outcome (c): no
117
+ * One of the FOUR finding families: no
118
118
  * Finding supertype exists, and the relationship pin lives on
119
- * `./rules/index.mjs`'s `violationOf` header. These findings stay this
119
+ * `./rules/index.mjs`'s `violationOf` header (stated in
120
+ * `../../../docs/concepts/evidence.md`'s "Four finding families"). These findings stay this
120
121
  * family's own shape and fold into the one verdict lane as count keys into
121
- * `verdictFor` (`./verdict.mjs`). The canonical statement is the
122
- * "Finding — the unowned concept" section of
123
- * `../../../docs/architecture/refactor/SEMANTIC-MODEL.md`.
122
+ * `verdictFor` (`./verdict.mjs`).
124
123
  *
125
124
  * @param {{ paths: Record<string, unknown>,
126
125
  * base: string,