@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.
- package/cli.mjs +4 -3
- package/package.json +1 -1
- package/src/architecture-intent/model.mjs +2 -2
- package/src/commands/analyze-capability.mjs +2 -2
- package/src/commands/change-intent.mjs +2 -2
- package/src/commands/change.mjs +6 -3
- package/src/commands/check-capability.mjs +2 -2
- package/src/commands/check.mjs +3 -5
- package/src/commands/compare-capability.mjs +2 -2
- package/src/commands/completeness.mjs +2 -2
- package/src/commands/delta.mjs +5 -3
- package/src/commands/diff.mjs +2 -2
- package/src/commands/evolution.mjs +10 -0
- package/src/commands/explain-capability.mjs +2 -2
- package/src/commands/fitness.mjs +2 -2
- package/src/commands/govern-capability.mjs +2 -2
- package/src/commands/inspect-capability.mjs +2 -2
- package/src/commands/rules-capability.mjs +2 -2
- package/src/corpus/goldens/adr.json +2 -2
- package/src/corpus/goldens/change.json +6 -5
- package/src/corpus/goldens/change.text +2 -2
- package/src/corpus/goldens/check.json +2 -2
- package/src/corpus/goldens/context.json +2 -2
- package/src/corpus/goldens/debt.json +4 -4
- package/src/corpus/goldens/debt.text +2 -2
- package/src/corpus/goldens/decisions.json +2 -2
- package/src/corpus/goldens/delta.json +4 -4
- package/src/corpus/goldens/delta.text +1 -1
- package/src/corpus/goldens/diff.json +4 -4
- package/src/corpus/goldens/diff.text +1 -1
- package/src/corpus/goldens/discover.json +2 -2
- package/src/corpus/goldens/drift.json +2 -2
- package/src/corpus/goldens/evolution.json +4 -2
- package/src/corpus/goldens/explain.json +2 -2
- package/src/corpus/goldens/fitness.json +2 -2
- package/src/corpus/goldens/graph.json +2 -2
- package/src/corpus/goldens/health.json +2 -2
- package/src/corpus/goldens/history.json +3 -3
- package/src/corpus/goldens/history.text +1 -1
- package/src/corpus/goldens/impact.json +2 -2
- package/src/corpus/goldens/provenance.json +2 -2
- package/src/corpus/goldens/reconcile.json +2 -2
- package/src/corpus/goldens/report.json +2 -2
- package/src/corpus/goldens/report.text +1 -1
- package/src/corpus/goldens/scenario.json +2 -2
- package/src/corpus/goldens/trajectory.json +3 -3
- package/src/corpus/goldens/trajectory.text +1 -1
- package/src/corpus/goldens/waivers.json +2 -2
- package/src/go-work.mjs +4 -5
- package/src/governance/debt-ledger.mjs +5 -2
- package/src/governance/evolution-event.mjs +1 -2
- package/src/intent/intent-manifest.json +8 -8
- package/src/providers/nx-static.mjs +4 -4
- package/src/rules/edge-constraints.mjs +4 -5
- package/src/rules/index.mjs +8 -10
- 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 (
|
|
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
|
|
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 (
|
|
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.
|
|
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
|
-
*
|
|
16
|
-
* (`../../../../docs/architecture
|
|
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
|
|
11
|
-
* ../../../../docs/architecture
|
|
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
|
-
*
|
|
14
|
-
* (`../../../../docs/architecture
|
|
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/` —
|
package/src/commands/change.mjs
CHANGED
|
@@ -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
|
|
484
|
-
* (`docs/
|
|
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
|
|
9
|
-
* ../../../../docs/architecture
|
|
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";
|
package/src/commands/check.mjs
CHANGED
|
@@ -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
|
-
//
|
|
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
|
|
531
|
-
// "
|
|
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
|
|
11
|
-
* ../../../../docs/architecture
|
|
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
|
|
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
|
*/
|
package/src/commands/delta.mjs
CHANGED
|
@@ -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
|
|
483
|
-
*
|
|
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})`,
|
package/src/commands/diff.mjs
CHANGED
|
@@ -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
|
-
*
|
|
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
|
|
9
|
-
* ../../../../docs/architecture
|
|
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";
|
package/src/commands/fitness.mjs
CHANGED
|
@@ -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
|
|
126
|
-
* converged (`docs/
|
|
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
|
|
9
|
-
* ../../../../docs/architecture
|
|
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
|
|
10
|
-
* ../../../../docs/architecture
|
|
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
|
|
9
|
-
* ../../../../docs/architecture
|
|
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.
|
|
5
|
+
"version": "0.27.0"
|
|
6
6
|
},
|
|
7
7
|
"command": "adr",
|
|
8
8
|
"workspace": {
|
|
9
|
-
"root": "
|
|
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.
|
|
5
|
+
"version": "0.27.0"
|
|
6
6
|
},
|
|
7
7
|
"command": "change",
|
|
8
8
|
"workspace": {
|
|
9
|
-
"root": "
|
|
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": "
|
|
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": "
|
|
45
|
+
"path": "<fixture-root>/.archkeep-delta.json",
|
|
46
46
|
"tool": {
|
|
47
47
|
"name": "@ecoma-io/archkeep",
|
|
48
|
-
"version": "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
|
|
2
|
-
baseline
|
|
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.
|
|
5
|
+
"version": "0.27.0"
|
|
6
6
|
},
|
|
7
7
|
"command": "check",
|
|
8
8
|
"workspace": {
|
|
9
|
-
"root": "
|
|
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.
|
|
5
|
+
"version": "0.27.0"
|
|
6
6
|
},
|
|
7
7
|
"command": "context",
|
|
8
8
|
"workspace": {
|
|
9
|
-
"root": "
|
|
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.
|
|
5
|
+
"version": "0.27.0"
|
|
6
6
|
},
|
|
7
7
|
"command": "debt",
|
|
8
8
|
"workspace": {
|
|
9
|
-
"root": "
|
|
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": "
|
|
34
|
+
"dir": "<fixture-root>/.archkeep-history",
|
|
35
35
|
"snapshots": 1,
|
|
36
36
|
"agings": false,
|
|
37
|
-
"sampleTime": "2026-09-
|
|
37
|
+
"sampleTime": "2026-09-08T10:33:14.692Z",
|
|
38
38
|
"entries": [],
|
|
39
39
|
"resolved": [],
|
|
40
40
|
"total": 0,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
debt
|
|
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-
|
|
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.
|
|
5
|
+
"version": "0.27.0"
|
|
6
6
|
},
|
|
7
7
|
"command": "decisions",
|
|
8
8
|
"workspace": {
|
|
9
|
-
"root": "
|
|
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.
|
|
5
|
+
"version": "0.27.0"
|
|
6
6
|
},
|
|
7
7
|
"command": "delta",
|
|
8
8
|
"workspace": {
|
|
9
|
-
"root": "
|
|
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": "
|
|
31
|
+
"path": "<fixture-root>/.archkeep-delta.json",
|
|
32
32
|
"tool": {
|
|
33
33
|
"name": "@ecoma-io/archkeep",
|
|
34
|
-
"version": "0.
|
|
34
|
+
"version": "0.27.0"
|
|
35
35
|
},
|
|
36
36
|
"provider": "native",
|
|
37
37
|
"provenance": {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
baseline
|
|
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.
|
|
5
|
+
"version": "0.27.0"
|
|
6
6
|
},
|
|
7
7
|
"command": "diff",
|
|
8
8
|
"workspace": {
|
|
9
|
-
"root": "
|
|
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": "
|
|
33
|
+
"path": "<fixture-root>/.archkeep-graph.json",
|
|
34
34
|
"projects": 3,
|
|
35
35
|
"edges": 2,
|
|
36
|
-
"toolVersion": "0.
|
|
36
|
+
"toolVersion": "0.27.0",
|
|
37
37
|
"provenance": {
|
|
38
38
|
"commit": "1fd51709c377d99a6139891e1200291cf08aede9",
|
|
39
39
|
"remote": null,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
baseline
|
|
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.
|
|
5
|
+
"version": "0.27.0"
|
|
6
6
|
},
|
|
7
7
|
"command": "discover",
|
|
8
8
|
"workspace": {
|
|
9
|
-
"root": "
|
|
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.
|
|
5
|
+
"version": "0.27.0"
|
|
6
6
|
},
|
|
7
7
|
"command": "drift",
|
|
8
8
|
"workspace": {
|
|
9
|
-
"root": "
|
|
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.
|
|
5
|
+
"version": "0.27.0"
|
|
6
6
|
},
|
|
7
7
|
"command": "evolution",
|
|
8
8
|
"workspace": {
|
|
9
|
-
"root": "
|
|
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.
|
|
5
|
+
"version": "0.27.0"
|
|
6
6
|
},
|
|
7
7
|
"command": "explain",
|
|
8
8
|
"workspace": {
|
|
9
|
-
"root": "
|
|
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.
|
|
5
|
+
"version": "0.27.0"
|
|
6
6
|
},
|
|
7
7
|
"command": "fitness",
|
|
8
8
|
"workspace": {
|
|
9
|
-
"root": "
|
|
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.
|
|
5
|
+
"version": "0.27.0"
|
|
6
6
|
},
|
|
7
7
|
"command": "graph",
|
|
8
8
|
"workspace": {
|
|
9
|
-
"root": "
|
|
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.
|
|
5
|
+
"version": "0.27.0"
|
|
6
6
|
},
|
|
7
7
|
"command": "health",
|
|
8
8
|
"workspace": {
|
|
9
|
-
"root": "
|
|
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.
|
|
5
|
+
"version": "0.27.0"
|
|
6
6
|
},
|
|
7
7
|
"command": "history",
|
|
8
8
|
"workspace": {
|
|
9
|
-
"root": "
|
|
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": "
|
|
32
|
+
"dir": "<fixture-root>/.archkeep-history",
|
|
33
33
|
"captured": null,
|
|
34
34
|
"snapshots": [
|
|
35
35
|
{
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
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.
|
|
5
|
+
"version": "0.27.0"
|
|
6
6
|
},
|
|
7
7
|
"command": "impact",
|
|
8
8
|
"workspace": {
|
|
9
|
-
"root": "
|
|
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.
|
|
5
|
+
"version": "0.27.0"
|
|
6
6
|
},
|
|
7
7
|
"command": "provenance",
|
|
8
8
|
"workspace": {
|
|
9
|
-
"root": "
|
|
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.
|
|
5
|
+
"version": "0.27.0"
|
|
6
6
|
},
|
|
7
7
|
"command": "reconcile",
|
|
8
8
|
"workspace": {
|
|
9
|
-
"root": "
|
|
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.
|
|
5
|
+
"version": "0.27.0"
|
|
6
6
|
},
|
|
7
7
|
"command": "report",
|
|
8
8
|
"workspace": {
|
|
9
|
-
"root": "
|
|
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.
|
|
5
|
+
"version": "0.27.0"
|
|
6
6
|
},
|
|
7
7
|
"command": "scenario",
|
|
8
8
|
"workspace": {
|
|
9
|
-
"root": "
|
|
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.
|
|
5
|
+
"version": "0.27.0"
|
|
6
6
|
},
|
|
7
7
|
"command": "trajectory",
|
|
8
8
|
"workspace": {
|
|
9
|
-
"root": "
|
|
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": "
|
|
33
|
+
"dir": "<fixture-root>/.archkeep-history",
|
|
34
34
|
"observations": {
|
|
35
35
|
"count": 1,
|
|
36
36
|
"basis": "graph_snapshots",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
trajectory
|
|
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.
|
|
5
|
+
"version": "0.27.0"
|
|
6
6
|
},
|
|
7
7
|
"command": "waivers",
|
|
8
8
|
"workspace": {
|
|
9
|
-
"root": "
|
|
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
|
|
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
|
|
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`).
|
|
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
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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`
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
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
|
|
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
|
|
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`).
|
|
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`).
|
package/src/rules/index.mjs
CHANGED
|
@@ -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 (
|
|
429
|
-
*
|
|
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
|
|
436
|
-
*
|
|
437
|
-
*
|
|
438
|
-
* markdown fold is the
|
|
439
|
-
*
|
|
440
|
-
*
|
|
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 {
|
package/src/tsconfig-paths.mjs
CHANGED
|
@@ -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
|
|
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
|
|
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`).
|
|
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,
|