harness-everything 0.39.0 → 0.41.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/.agents/harness-everything/project-docs.json +9 -0
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +50 -0
- package/benchmarks/results/f1-doc-path-baseline/1-source-clean.stderr.txt +0 -0
- package/benchmarks/results/f1-doc-path-baseline/1-source-clean.stdout.json +20 -0
- package/benchmarks/results/f1-doc-path-baseline/2-injected-architecture.md +229 -0
- package/benchmarks/results/f1-doc-path-baseline/2-source-injected.stderr.txt +0 -0
- package/benchmarks/results/f1-doc-path-baseline/2-source-injected.stdout.json +33 -0
- package/benchmarks/results/f1-doc-path-baseline/3-source-reverted.stderr.txt +0 -0
- package/benchmarks/results/f1-doc-path-baseline/3-source-reverted.stdout.json +20 -0
- package/benchmarks/results/f1-doc-path-baseline/4a-packaged-clean.stderr.txt +0 -0
- package/benchmarks/results/f1-doc-path-baseline/4a-packaged-clean.stdout.json +20 -0
- package/benchmarks/results/f1-doc-path-baseline/4b-packaged-injected.stderr.txt +0 -0
- package/benchmarks/results/f1-doc-path-baseline/4b-packaged-injected.stdout.json +33 -0
- package/benchmarks/results/f1-doc-path-baseline/5-source-missing-config.stderr.txt +0 -0
- package/benchmarks/results/f1-doc-path-baseline/5-source-missing-config.stdout.json +15 -0
- package/benchmarks/results/f1-doc-path-baseline/5b-packaged-missing-config.stderr.txt +0 -0
- package/benchmarks/results/f1-doc-path-baseline/5b-packaged-missing-config.stdout.json +15 -0
- package/benchmarks/results/f1-doc-path-baseline/README.md +54 -0
- package/benchmarks/results/f1-doc-path-baseline/before-fix/1-source-clean.stderr.txt +0 -0
- package/benchmarks/results/f1-doc-path-baseline/before-fix/1-source-clean.stdout.json +115 -0
- package/benchmarks/results/f1-doc-path-baseline/before-fix/2-injected-document.md +328 -0
- package/benchmarks/results/f1-doc-path-baseline/before-fix/2-source-injected.stderr.txt +0 -0
- package/benchmarks/results/f1-doc-path-baseline/before-fix/2-source-injected.stdout.json +127 -0
- package/benchmarks/results/f1-doc-path-baseline/before-fix/3-source-reverted.stderr.txt +0 -0
- package/benchmarks/results/f1-doc-path-baseline/before-fix/3-source-reverted.stdout.json +115 -0
- package/benchmarks/results/f1-doc-path-baseline/before-fix/4a-packaged-clean.stderr.txt +0 -0
- package/benchmarks/results/f1-doc-path-baseline/before-fix/4a-packaged-clean.stdout.json +115 -0
- package/benchmarks/results/f1-doc-path-baseline/before-fix/4b-packaged-injected.stderr.txt +0 -0
- package/benchmarks/results/f1-doc-path-baseline/before-fix/4b-packaged-injected.stdout.json +127 -0
- package/benchmarks/results/f1-doc-path-baseline/before-fix/5-source-missing-config.stderr.txt +0 -0
- package/benchmarks/results/f1-doc-path-baseline/before-fix/5-source-missing-config.stdout.json +15 -0
- package/benchmarks/results/f1-doc-path-baseline/before-fix/5b-packaged-missing-config.stderr.txt +0 -0
- package/benchmarks/results/f1-doc-path-baseline/before-fix/5b-packaged-missing-config.stdout.json +15 -0
- package/benchmarks/results/f1-doc-path-baseline/before-fix/6-supplementary-fixture-ok.input.md +8 -0
- package/benchmarks/results/f1-doc-path-baseline/before-fix/6-supplementary-fixture-ok.stdout.json +16 -0
- package/benchmarks/results/f1-doc-path-baseline/before-fix/README.md +34 -0
- package/benchmarks/results/f1-doc-path-baseline/probe-31-docs/after.json +248 -0
- package/benchmarks/results/f1-doc-path-baseline/probe-31-docs/before.json +254 -0
- package/benchmarks/results/f1-doc-path-baseline/probe-31-docs/probe.js +26 -0
- package/benchmarks/results/f2-doc-craft-baseline/README.md +32 -0
- package/benchmarks/results/f2-doc-craft-baseline/arm-f1-report.md +84 -0
- package/benchmarks/results/f2-doc-craft-baseline/arm-f1-task.md +21 -0
- package/benchmarks/results/f2-doc-craft-baseline/arm-f1.diff +19 -0
- package/benchmarks/results/f2-doc-craft-baseline/arm-f2-report.md +110 -0
- package/benchmarks/results/f2-doc-craft-baseline/arm-f2-task.md +21 -0
- package/benchmarks/results/f2-doc-craft-baseline/arm-f2.diff +19 -0
- package/benchmarks/results/f3-derived-views-baseline/README.md +34 -0
- package/benchmarks/results/f3-derived-views-baseline/arm-f2-report.md +43 -0
- package/benchmarks/results/f3-derived-views-baseline/arm-f2-task.md +21 -0
- package/benchmarks/results/f3-derived-views-baseline/arm-f2.diff +21 -0
- package/benchmarks/results/f3-derived-views-baseline/arm-f3-report.md +57 -0
- package/benchmarks/results/f3-derived-views-baseline/arm-f3-task.md +21 -0
- package/benchmarks/results/f3-derived-views-baseline/arm-f3.diff +21 -0
- package/benchmarks/results/live-host/claude-325-3b-s2b/README.md +99 -0
- package/benchmarks/results/live-host/claude-325-3b-s2b/capture.sanitized.jsonl +26 -0
- package/ci/archive/325-prep/README.md +71 -0
- package/ci/{prep → archive/325-prep}/doc-reconciliation-red.js +9 -7
- package/ci/archive/325-prep/f4-expected-red.json +34 -0
- package/ci/archive/325-prep/historical-qualification.test.js +143 -0
- package/ci/fixtures/doc-obligations/reconciliation-prep/cases.json +17 -4
- package/ci/fixtures/doc-obligations/reconciliation-prep/pending-red.json +8 -56
- package/ci/fixtures/doc-obligations/reconciliation-prep/trust-contract.json +2 -2
- package/ci/fixtures/doc-obligations/reconciliation-s1/cases.json +17 -5
- package/ci/fixtures/doc-obligations/reconciliation-s2b/capture/harness.js +415 -0
- package/ci/fixtures/doc-obligations/reconciliation-s2b/capture/off-handoff-golden.json +16 -0
- package/ci/fixtures/doc-obligations/reconciliation-s2b/capture/payload-post-tool-use-failure.json +11 -0
- package/ci/fixtures/doc-obligations/reconciliation-s2b/capture/payload-post-tool-use-success-minimal.json +9 -0
- package/ci/fixtures/doc-obligations/reconciliation-s2b/capture/payload-post-tool-use-success.json +13 -0
- package/ci/fixtures/doc-obligations/reconciliation-s2b/capture/payload-subagent-start.json +7 -0
- package/ci/fixtures/doc-obligations/reconciliation-s2b/capture/payload-subagent-stop-freetext-reject.json +11 -0
- package/ci/fixtures/doc-obligations/reconciliation-s2b/capture/payload-subagent-stop-reject.json +11 -0
- package/ci/fixtures/doc-obligations/reconciliation-s2b/capture/payload-subagent-stop.json +11 -0
- package/ci/fixtures/doc-obligations/reconciliation-s2b/capture/payload-task-result.json +19 -0
- package/ci/fixtures/doc-obligations/reconciliation-s2b/corpus/off-capture-only.json +99 -0
- package/ci/fixtures/doc-obligations/reconciliation-s2b/corpus/off-legacy.json +67 -0
- package/ci/fixtures/doc-obligations/reconciliation-s2b/corpus/on-concurrent-writers.json +62 -0
- package/ci/fixtures/doc-obligations/reconciliation-s2b/corpus/on-lookalikes-runtime-mutations.json +67 -0
- package/ci/fixtures/doc-obligations/reconciliation-s2b/corpus/on-malformed.json +85 -0
- package/ci/fixtures/doc-obligations/reconciliation-s2b/corpus/on-normal-session.json +74 -0
- package/ci/fixtures/doc-obligations/reconciliation-s2b/corpus/on-runtime-drift-later-npm-test.json +58 -0
- package/ci/fixtures/doc-obligations/reconciliation-s2b/corpus/on-valid-direct-quoted-review.json +85 -0
- package/ci/fixtures/doc-obligations/reconciliation-s2b/f4/cases.json +2267 -0
- package/ci/fixtures/doc-obligations/reconciliation-s2b/wiring/cases.json +1110 -0
- package/ci/fixtures/doc-obligations/reconciliation-s2b/wiring/legacy-off-golden.json +674 -0
- package/ci/lib/doc-reconciliation-file-spy.js +23 -0
- package/ci/lib/doc-reconciliation-prep-fixtures.js +136 -10
- package/ci/lib/doc-reconciliation-qualification-preload.js +37 -0
- package/ci/lib/doc-reconciliation-replay.js +104 -0
- package/ci/lib/doc-reconciliation-staged-tree.js +102 -0
- package/ci/mechanism-2p-opencode-v2-entrypoint.test.js +179 -0
- package/ci/mechanism-325-3b-preparation.test.js +27 -101
- package/ci/mechanism-325-3b-s2b-capture.test.js +561 -0
- package/ci/mechanism-325-3b-s2b-wiring.test.js +668 -0
- package/ci/mechanism-325-f1-doc-check.test.js +674 -0
- package/ci/mechanism-325-f2-doc-craft.test.js +597 -0
- package/ci/mechanism-325-f3-derived-views.test.js +798 -0
- package/ci/mechanism-325-f4-invariants.test.js +606 -0
- package/ci/mechanism-325-f4-projections.test.js +382 -0
- package/ci/mechanism-325-f4-qualification.test.js +228 -0
- package/ci/mechanism-325-f4-trust-boundary.test.js +880 -0
- package/ci/mutation-check.js +26 -3
- package/code-review/SKILL.md +3 -3
- package/code-review/references/review-playbook.md +4 -0
- package/code-review/templates/finding.template.md +6 -0
- package/docs/architecture.md +5 -0
- package/docs/doc-workflow-reconciliation.md +331 -4
- package/docs/document-lifecycle.md +11 -0
- package/docs/governed-index.md +20 -0
- package/docs/platform-capabilities.md +22 -2
- package/evals/zoom-out/tasks/negative-first-edge-case-review.yaml +16 -0
- package/evals/zoom-out/tasks/positive-repair-loop.yaml +15 -0
- package/grill-with-docs/SKILL.md +1 -1
- package/grill-with-docs/references/session-playbook.md +4 -0
- package/harness-everything/SKILL.md +1 -1
- package/harness-everything/references/doc-check.md +186 -0
- package/harness-everything/references/documentation/_shared/maintenance.md +41 -0
- package/harness-everything/references/documentation/_shared/writing-craft.md +59 -0
- package/harness-everything/references/triage-and-tiers.md +4 -0
- package/harness-everything/scripts/doc-check.js +442 -0
- package/harness-everything/scripts/doc-lifecycle.js +3 -0
- package/harness-everything/scripts/routing-keywords.json +4 -0
- package/hooks/hooks.json +46 -0
- package/hooks/scripts/lib/doc-reconciliation-capture.sanitized.jsonl +26 -0
- package/hooks/scripts/lib/doc-reconciliation-pilot.js +171 -2
- package/hooks/scripts/lib/doc-reconciliation-provider.js +1059 -0
- package/hooks/scripts/lib/doc-reconciliation-qualification.json +34 -0
- package/hooks/scripts/lib/workflow-obligations.js +7 -0
- package/hooks/scripts/state-persist.js +78 -2
- package/hooks/scripts/workflow-stop-gate.js +7 -2
- package/opencode-plugin/README.md +15 -0
- package/opencode-plugin/index.mjs +77 -0
- package/opencode-plugin/plugin.json +1 -1
- package/package.json +2 -1
- package/plugins/harness-everything/.codex-plugin/plugin.json +1 -1
- package/plugins/harness-everything/hooks/scripts/lib/doc-reconciliation-capture.sanitized.jsonl +26 -0
- package/plugins/harness-everything/hooks/scripts/lib/doc-reconciliation-pilot.js +171 -2
- package/plugins/harness-everything/hooks/scripts/lib/doc-reconciliation-provider.js +1059 -0
- package/plugins/harness-everything/hooks/scripts/lib/doc-reconciliation-qualification.json +34 -0
- package/plugins/harness-everything/hooks/scripts/lib/workflow-obligations.js +7 -0
- package/plugins/harness-everything/hooks/scripts/state-persist.js +78 -2
- package/plugins/harness-everything/hooks/scripts/workflow-stop-gate.js +7 -2
- package/plugins/harness-everything/plugin.json +1 -1
- package/plugins/harness-everything/skills/code-review/SKILL.md +3 -3
- package/plugins/harness-everything/skills/code-review/references/review-playbook.md +4 -0
- package/plugins/harness-everything/skills/code-review/templates/finding.template.md +6 -0
- package/plugins/harness-everything/skills/grill-with-docs/SKILL.md +1 -1
- package/plugins/harness-everything/skills/grill-with-docs/references/session-playbook.md +4 -0
- package/plugins/harness-everything/skills/harness-everything/SKILL.md +1 -1
- package/plugins/harness-everything/skills/harness-everything/references/doc-check.md +186 -0
- package/plugins/harness-everything/skills/harness-everything/references/documentation/_shared/maintenance.md +41 -0
- package/plugins/harness-everything/skills/harness-everything/references/documentation/_shared/writing-craft.md +59 -0
- package/plugins/harness-everything/skills/harness-everything/references/triage-and-tiers.md +4 -0
- package/plugins/harness-everything/skills/harness-everything/scripts/doc-check.js +442 -0
- package/plugins/harness-everything/skills/harness-everything/scripts/doc-lifecycle.js +3 -0
- package/plugins/harness-everything/skills/harness-everything/scripts/routing-keywords.json +4 -0
- package/plugins/harness-everything/skills/repo-docs/SKILL.md +1 -1
- package/plugins/harness-everything/skills/repo-docs/references/process-guide.md +4 -0
- package/plugins/harness-everything/skills/to-spec/SKILL.md +1 -1
- package/plugins/harness-everything/skills/to-spec/references/process.md +4 -0
- package/plugins/harness-everything/skills/to-tickets/SKILL.md +1 -1
- package/plugins/harness-everything/skills/to-tickets/references/publishing-and-templates.md +4 -0
- package/plugins/harness-everything/skills/zoom-out/SKILL.md +4 -3
- package/plugins/harness-everything/skills/zoom-out/references/circuit-breaker.md +7 -0
- package/plugins/harness-everything/skills/zoom-out/templates/zoom-out-report.template.md +4 -2
- package/repo-docs/SKILL.md +1 -1
- package/repo-docs/references/process-guide.md +4 -0
- package/sbom.cdx.json +7 -7
- package/scripts/errors-sync.js +90 -0
- package/to-spec/SKILL.md +1 -1
- package/to-spec/references/process.md +4 -0
- package/to-tickets/SKILL.md +1 -1
- package/to-tickets/references/publishing-and-templates.md +4 -0
- package/zoom-out/SKILL.md +4 -3
- package/zoom-out/references/circuit-breaker.md +7 -0
- package/zoom-out/templates/zoom-out-report.template.md +4 -2
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
{
|
|
2
|
+
"lint": {
|
|
3
|
+
"exit": 1,
|
|
4
|
+
"evidence": {
|
|
5
|
+
"immutability": "observed"
|
|
6
|
+
},
|
|
7
|
+
"diagnostics": [
|
|
8
|
+
{
|
|
9
|
+
"code": "missing-req",
|
|
10
|
+
"severity": "error",
|
|
11
|
+
"path": "docs/document-lifecycle.md",
|
|
12
|
+
"message": "requirement REQ-GRAPH-012 is referenced but is not defined in an active PRD",
|
|
13
|
+
"id": "REQ-GRAPH-012"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"code": "missing-req",
|
|
17
|
+
"severity": "error",
|
|
18
|
+
"path": "docs/document-lifecycle.md",
|
|
19
|
+
"message": "requirement REQ-GRAPH-020 is referenced but is not defined in an active PRD",
|
|
20
|
+
"id": "REQ-GRAPH-020"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"code": "missing-req",
|
|
24
|
+
"severity": "error",
|
|
25
|
+
"path": "docs/document-lifecycle.md",
|
|
26
|
+
"message": "requirement REQ-GRPH-012 is referenced but is not defined in an active PRD",
|
|
27
|
+
"id": "REQ-GRPH-012"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"code": "missing-req",
|
|
31
|
+
"severity": "error",
|
|
32
|
+
"path": "docs/document-lifecycle.md",
|
|
33
|
+
"message": "requirement REQ-GRPH-013 is referenced but is not defined in an active PRD",
|
|
34
|
+
"id": "REQ-GRPH-013"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"code": "missing-req",
|
|
38
|
+
"severity": "error",
|
|
39
|
+
"path": "docs/document-lifecycle.md",
|
|
40
|
+
"message": "requirement REQ-GRPH-020 is referenced but is not defined in an active PRD",
|
|
41
|
+
"id": "REQ-GRPH-020"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"code": "missing-req",
|
|
45
|
+
"severity": "error",
|
|
46
|
+
"path": "docs/document-lifecycle.md",
|
|
47
|
+
"message": "requirement REQ-GRPH-099 is referenced but is not defined in an active PRD",
|
|
48
|
+
"id": "REQ-GRPH-099"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"code": "unresolved-ref",
|
|
52
|
+
"severity": "error",
|
|
53
|
+
"path": "docs/document-lifecycle.md",
|
|
54
|
+
"message": "reference GRPH-007 cannot be resolved",
|
|
55
|
+
"id": "GRPH-007"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"code": "unresolved-ref",
|
|
59
|
+
"severity": "error",
|
|
60
|
+
"path": "docs/document-lifecycle.md",
|
|
61
|
+
"message": "reference PRD-GRPH-001 cannot be resolved",
|
|
62
|
+
"id": "PRD-GRPH-001"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"code": "unresolved-ref",
|
|
66
|
+
"severity": "error",
|
|
67
|
+
"path": "docs/document-lifecycle.md",
|
|
68
|
+
"message": "reference PRD-GRPH-001@r2 cannot be resolved",
|
|
69
|
+
"id": "PRD-GRPH-001@r2"
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"code": "unresolved-ref",
|
|
73
|
+
"severity": "error",
|
|
74
|
+
"path": "docs/document-lifecycle.md",
|
|
75
|
+
"message": "reference PRD-GRPH-001@r2#REQ-GRPH-012 cannot be resolved",
|
|
76
|
+
"id": "PRD-GRPH-001@r2#REQ-GRPH-012"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"code": "unresolved-ref",
|
|
80
|
+
"severity": "error",
|
|
81
|
+
"path": "docs/document-lifecycle.md",
|
|
82
|
+
"message": "reference PRD-GRPH-001@r3 cannot be resolved",
|
|
83
|
+
"id": "PRD-GRPH-001@r3"
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"code": "unresolved-ref",
|
|
87
|
+
"severity": "error",
|
|
88
|
+
"path": "docs/document-lifecycle.md",
|
|
89
|
+
"message": "reference PRD-GRPH-001@r4 cannot be resolved",
|
|
90
|
+
"id": "PRD-GRPH-001@r4"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"code": "unresolved-ref",
|
|
94
|
+
"severity": "error",
|
|
95
|
+
"path": "docs/document-lifecycle.md",
|
|
96
|
+
"message": "reference legacy:GRPH-007 cannot be resolved",
|
|
97
|
+
"id": "legacy:GRPH-007"
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"code": "unresolved-ref",
|
|
101
|
+
"severity": "error",
|
|
102
|
+
"path": "docs/document-lifecycle.md",
|
|
103
|
+
"message": "reference legacy:GRPH-007@docs/adr/legacy/v2/GRPH-007.md cannot be resolved",
|
|
104
|
+
"id": "legacy:GRPH-007@docs/adr/legacy/v2/GRPH-007.md"
|
|
105
|
+
}
|
|
106
|
+
]
|
|
107
|
+
},
|
|
108
|
+
"links": {
|
|
109
|
+
"checked": 6,
|
|
110
|
+
"broken": []
|
|
111
|
+
},
|
|
112
|
+
"coverage": {
|
|
113
|
+
"unsupported": []
|
|
114
|
+
}
|
|
115
|
+
}
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
---
|
|
2
|
+
role: reference
|
|
3
|
+
status: bogus
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Document Lifecycle Contract (#325)
|
|
7
|
+
|
|
8
|
+
Contract for the documentation family: project docs configuration (D5), document roles and revision metadata (D6.1–D6.3), domain-scoped IDs (D6.8) and the generated index. Owner decisions live in [#325](https://github.com/dyphn1/Harness-everything/issues/325); this file is the implementation contract that tests cite.
|
|
9
|
+
|
|
10
|
+
Documentation is a **consumer** of the #320 workflow/obligation abstractions. Nothing here is a second router, a standing maintenance loop or a cognitive lock: every check is a pure function that reports diagnostics.
|
|
11
|
+
|
|
12
|
+
## Scope of this slice (status as of 2026-10-20)
|
|
13
|
+
|
|
14
|
+
This table distinguishes merged mechanism code from end-to-end workflow integration. The last reviewed `main` commit is `29b1d65b398e2622af97bf067078373b7fa76b26` (v0.36.2). That release commit carries `[skip ci]` and only bumps package/distribution versions on top of `e5d22584e243d5b5e587ee0279625e97a9033160`, whose full-gate `CI` run [39374474269](https://github.com/dyphn1/Harness-everything/actions/runs/39374474269) completed with every job succeeded. The historical Windows System One resident teardown (`S1-RS15`) was observed in attempt 1 of [run 39175240370](https://github.com/dyphn1/Harness-everything/actions/runs/39175240370) on `main@75e04359ae5bf11a41739f8eb04d25a76ee8f3a7`; that run completed successfully on attempt 2 and says nothing about `29b1d65`. Treat the resident teardown as a known platform limitation only when a current run on the exact SHA reproduces it, and require an all-green full-gate run for that SHA before calling any baseline green.
|
|
15
|
+
|
|
16
|
+
| Phase / prerequisite | Verified implementation and remaining work |
|
|
17
|
+
| --- | --- |
|
|
18
|
+
| 0 — contract + RED fixtures | Agreed decisions in this document, #325 and #327; fixtures under `ci/fixtures/doc-lifecycle/`; preserve earlier design history |
|
|
19
|
+
| 1a — `project-docs.json` loader | **Merged** in #327; host-only malformed manifest protection remains a separate correction in #331 / draft PR #333 |
|
|
20
|
+
| 2 — roles, IDs, aliases, legacy, supersession, index, D6.9 PRD revisions | **Merged** in #327; do not rebuild this lifecycle logic for Phase 3 |
|
|
21
|
+
| Step-type prerequisite (#326) | **Complete:** PR #328 merged; Harness-owned `doc-change` is explicitly declared, has no implicit TDD binding, and is not auto-inserted by router/System One |
|
|
22
|
+
| 3a — document facts, obligations and evidence producer | **Merged** in #334: `harness-everything/scripts/doc-obligations.js` and `doc-evidence.js`. H3/H4 have *partial deterministic mechanism* coverage, not integrated workflow evidence. Known limitations: caller-attested envelope; `configDigest` presence-only; `candidateDigest` restricted to `docs/prd/`; missing independent task-scope binding. Deleted and old rename paths are bound to trusted per-path baseline evidence ([doc-evidence-baseline-binding.md](doc-evidence-baseline-binding.md), #335 fixed by #342), with workflow-disposition reconciliation left out of scope |
|
|
23
|
+
| 3b — pilot-local provider suggestions and workflow evidence reconciliation | **S1 runtime ships default OFF** (opt in with `HARNESS_DOC_RECONCILIATION_PILOT=1`), with trusted scope assessment and fail-closed withholding; **no positive document verification credit**. See [S1 switch, trusted scope and no-credit contract](doc-workflow-reconciliation.md#s1--switch-trusted-scope-and-fail-closed-no-credit-gate). **S3 pure advisory provider suggestions shipped in 0.37.0 (not wired); S2 trusted producer/positive reconciliation/freshness is pending; E1 has not started.** Accepted #341 E0 permits this limited reversible consumer. Current evidence is deterministic mechanism/package coverage, not live-host loading or E1 GO; preserve existing required-binding compatibility |
|
|
24
|
+
| 3c — H1–H4 and paired-task evaluation | **Not started.** Mechanism tests alone are insufficient for architecture promotion; compare frozen baseline and treatment on real bounded tasks, success/failure first, then conditional cost and latency |
|
|
25
|
+
| 1b — shared documentation craft and family metadata | **Splittable.** Shared references and thin skill consumers can proceed independently. A small optional logical-family metadata seam may be piloted; physical skill directory moves remain blocked on #320 identity/path separation |
|
|
26
|
+
| 4 — derived-view generators and `describes:` drift | **Not started.** Preserve generator authorization, deterministic regenerate-equals and scoped reminder semantics |
|
|
27
|
+
|
|
28
|
+
### Phase 3b — narrow integration contract (S1 shipped default OFF; positive reconciliation not shipped)
|
|
29
|
+
|
|
30
|
+
The preparation design, test-only provider/trust contracts, and qualified RED replay are complete:
|
|
31
|
+
[Document workflow reconciliation](doc-workflow-reconciliation.md),
|
|
32
|
+
[case corpus](../ci/fixtures/doc-obligations/reconciliation-prep/cases.json),
|
|
33
|
+
[pending-RED registry](../ci/fixtures/doc-obligations/reconciliation-prep/pending-red.json), and
|
|
34
|
+
[preparation suite](../ci/mechanism-325-3b-preparation.test.js). #341 E0 is accepted; S1 ships the
|
|
35
|
+
default-OFF no-credit gate only. Positive reconciliation (S2) remains unshipped.
|
|
36
|
+
|
|
37
|
+
- **Inputs:** explicit active `doc-change` step, D6.5 diff facts, Phase 3a obligations/evidence, available provider *metadata*, and host capabilities.
|
|
38
|
+
- **Entry and activation gates (#341):** parallel preparatory work — provider metadata, adapter/interface design and RED fixtures — may proceed while #341 Phase 0A–0C runs, but the **runtime** Evidence Reconciliation must not merge or activate until **#341 E0** is reviewed and accepted (initial evidence read/binding/outcome conformance, mutation and read-order compatibility, source/package parity, zero false MUST PASS on applicable adversarial cases, and applicable green CI including Windows). After E0, only the **bounded, opt-in, reversible** documentation consumer is eligible for runtime integration at the existing verification/disposition path (no second router, forced provider, new lock, or weakened authorization, with a documented rollback), and it supplies the observed exposure for **#341 E1** (initial target 2–3 genuine development/review cycles with sufficient case mix, not elapsed time). **#341 E1 GO / REVISE / NO-GO gates expansion beyond the limited pilot, not the pilot's own observation** (missing or unrepresentative exposure is `UNCHECKED`, never an automatic GO). The H1–H4 paired-task architectural gate below stays required for any #320 promotion in addition to E1. Shared evidence-read/binding/decision defects route to #341 (fixture-first correction, regression replay, re-observation); documentation policy and the trusted host/VCS producer remain #325 deliverables here.
|
|
39
|
+
- **Advisory provider suggestions:** `suggestDocProviders({activeStep, neededCapabilities, availableProviderMetadata, hostCapabilities})` yields candidate providers and unavailable reasons without altering the MUST/SHOULD obligation set, granting tool access, or eagerly reading unrelated `SKILL.md`. Existing binding resolution handles an explicitly chosen provider. No new automatic step selection.
|
|
40
|
+
- **Evidence reconciliation boundary and credit order:** the pilot wires Phase 3a results into the non-Fable typed-step path only. `hooks/scripts/workflow-disposition.js` delegates `step` to `updateStep()` and `binding` to `updateBinding()` in `hooks/scripts/lib/workflow-obligations.js`. Today `updateStep()` persists `step.status = 'pass'` when every required binding is `loaded` and `--evidence` is non-empty; `syncTypedAggregateObligations()` then derives aggregate `execute`/`verify` PASS from the persisted step statuses. An authored `doc-change` step is authored work, not verification: it may advance under its existing binding contract **without claiming** any doc MUST as verified. The doc-MUST reconciliation gate belongs at the authorized `verification` step and the final-completion boundary, matching D6.6 ("All events are checked at the existing workflow's `verification` step"). Phase 3b must evaluate `checkDocObligations()` for the active scope before aggregate `verify` PASS is persisted and before the workflow reports completion; an aggregate `execute` may still reflect authored step passes, but neither aggregate may stand as completion while an applicable doc MUST is unsatisfied, and `unresolvedObligations()` must surface the unsatisfied results (`pending`/`unknown`/`unavailable`/`failed`). Ordered `doc-change → review → verification` topologies stay reachable: evidence supplied by the later `review`/`verification` steps counts at its own stage, so no stage is forced to pass early and a normative doc change cannot deadlock. Non-document steps, persisted plans, existing bindings and authorization stay unchanged.
|
|
41
|
+
- **Typed aggregate writes and freshness (doc-governed scope):** aggregate PASS is not derived exclusively from persisted step passes today. `updateObligation()` accepts a direct `obligation --obligation-id execute|verify --disposition pass --evidence <text>` write for **all** non-Fable typed plans, including workflows with no applicable document MUSTs. Phase 3b's guard is scoped to typed plans/steps with an applicable, doc-governed scope: there, a direct typed `execute`/`verify` PASS must be rejected or ignored unless it was derived/reconciled from satisfied doc evidence, and the `obligation` command joins `step` in the negative tests. Non-document typed workflows and persisted plans retain today's behavior unless a separately authorized compatibility decision changes them; an already-persisted plan that gains a doc-governed scope is validated against that scope and cannot complete on a stale direct aggregate PASS. Verified doc evidence must also stay bound to the persisted candidate, task and config identity: `unresolvedObligations()` and the final completion path re-check freshness, so evidence that was valid before a later candidate edit cannot remain a completion proof solely because `status: pass` was persisted.
|
|
42
|
+
- **Minimum trusted producer (3b deliverable):** Phase 3b ships the pilot-local adapter that derives the VCS baseline and candidate identity, active task scope, parsed config bytes (`configDigest` bound rather than presence-checked), PRD root, execution/verification provenance and independent reviewer identity from host state (see *Phase 3b minimum trust boundary* below). `checkDocObligations()` only proves agreement with caller-supplied values; without this producer, a 3b PASS would promote caller-attested claims. Any input the producer cannot establish stays `unknown`/`unavailable` and MUST NOT pass. Phase 3c broadens adversarial H3 validation and adds paired architectural evaluation; it does not supply the minimum producer.
|
|
43
|
+
- **Pilot topology and unsupported paths:** the pilot is limited to non-Fable typed-step workflows (`stepBindingsEnabled === true`, set when typed steps exist and the strategy is not `fable-*`). Fable stage-contract paths (`fable-staged`, `fable-parallel`, `fable-multi-agent-workspace`) and workflows without the typed-step contract are explicitly **not integrated / unavailable** for doc-MUST reconciliation: a `stage-binding` disposition is never doc verification, and no fallback may mark a doc MUST satisfied. Unsupported paths report that state rather than silently passing.
|
|
44
|
+
- **Negative acceptance case:** for a doc-governed typed plan whose applicable MUST is failing or unknown, no boundary may report PASS: `step --disposition pass` on the verification step, `obligation --obligation-id execute|verify --disposition pass --evidence 'done'`, and final completion must all fail closed, report the unsatisfied obligation ids, and leave aggregate `verify` pending. A loaded skill plus free-text evidence is not verification. A RED fixture covers ordered `doc-change → review → verification` with reviewer/command evidence missing first and valid later: the authored `doc-change` step advances, aggregate/final PASS stays blocked until the later evidence satisfies the MUST, and neither a premature PASS nor a deadlock occurs.
|
|
45
|
+
- **Compatibility:** preserve existing non-document step bindings, authorization/Rule-of-3 semantics, old persisted plans and no new Stop/tool lock. Source and installed plugin copies must behave consistently.
|
|
46
|
+
- **Pre-integration work:** the baseline-bound tombstone/rename-pair evidence required by #335 shipped in #342; the remaining pre-integration work is the reconciliation contract above. #331 / draft PR #333 is a parallel host-config safety correction; neither requires the broad #320 migration.
|
|
47
|
+
|
|
48
|
+
### Phase 3c — architecture promotion gate for #320 (planned, not shipped)
|
|
49
|
+
|
|
50
|
+
| Hypothesis | Objective acceptance evidence |
|
|
51
|
+
| --- | --- |
|
|
52
|
+
| **H1 Provider independence** | Swap/omit suggestions without changing workflow obligations; valid alternate execution evidence can satisfy an applicable MUST; no evidence cannot |
|
|
53
|
+
| **H2 Active-step progressive disclosure** | Captured step output / provider metadata access shows only active-step relevance and no eager unrelated `SKILL.md` content or future-step loading |
|
|
54
|
+
| **H3 Evidence reconciliation** | Adversarial replay of fabricated completion, missing verifier, stale digest/base, scope substitution, forged identity, unsupported PRD roots, contradictory/failed results and unsupported waiver yields **zero false PASS** for MUSTs, with the fixture matrix below as the observable trust boundary |
|
|
55
|
+
| **H4 Task-shaped composition** | Docs-only, docs+code, REQ-citing assertions, typo-only changes, code-only uncertainty, missing independent approval and waivers produce the expected obligation union and explicit unknown/unavailable outcomes |
|
|
56
|
+
|
|
57
|
+
### Phase 3b minimum trust boundary and Phase 3c H3 validation (planned, not shipped)
|
|
58
|
+
|
|
59
|
+
Phase 3b delivers the minimum producer and identity/scope binding needed for a trustworthy PASS; Phase 3c extends the same seam with adversarial H3 validation and paired architectural evaluation.
|
|
60
|
+
|
|
61
|
+
- **Trusted producer, not the checker:** a pilot-local adapter is a **3b deliverable**; it derives the VCS baseline and candidate identity, active task scope, project-docs config identity (parsed config bytes, not presence) and execution/review provenance from host state. `checkDocObligations()` proves only that records agree with those caller-supplied values; matching a caller-provided digest is not independent validation of the input.
|
|
62
|
+
- **Identity and scope requirements:** `baseline.digest` and `baseline.artifacts[path]` come from the same recorded baseline tree; candidate artifact digests come from the candidate tree actually under review; `configDigest` is bound to the parsed config bytes rather than checked for presence; the obligation's PRD root and active task scope must match the adapter's scope, and an unsupported custom PRD root is `unavailable`.
|
|
63
|
+
- **Provenance and reviewer identity:** execution and verification records need the command, non-empty provenance and integer exit code; review approval needs an independent reviewer identity distinct from the executor/author. A free-text claim, self-review, missing verifier or replayed record never satisfies a MUST.
|
|
64
|
+
- **Dispositions:** absent, untrusted, stale, replayed, contradictory, malformed or unsupported inputs resolve to `unknown`/`unavailable`/failed, never PASS. The 3b fail-closed negative cases cover missing producer identity, scope substitution, unbound config bytes and stale candidate evidence; 3c adds the full adversarial fixture matrix below.
|
|
65
|
+
|
|
66
|
+
| H3 fixture | Expected disposition |
|
|
67
|
+
| --- | --- |
|
|
68
|
+
| Fabricated completion claim / no record | `unknown`; MUST unsatisfied |
|
|
69
|
+
| Forged baseline or candidate digest | rejected as stale/unknown; MUST unsatisfied |
|
|
70
|
+
| Scope substitution across tasks or PRD roots | `unknown`; MUST unsatisfied |
|
|
71
|
+
| Unsupported custom PRD root | `unavailable`; MUST unsatisfied |
|
|
72
|
+
| Replayed earlier-candidate record | stale; MUST unsatisfied |
|
|
73
|
+
| Missing, non-independent or mismatched reviewer identity | MUST unsatisfied |
|
|
74
|
+
| Unsupported waiver (no reason, no cited observed record, or self-bound scope) | `unsupported-waiver`; MUST unsatisfied |
|
|
75
|
+
| Contradictory or failed command results | failed; not PASS |
|
|
76
|
+
| Positive control: current, independently produced matching evidence | pass |
|
|
77
|
+
|
|
78
|
+
Two *separate* gates apply. The **functional gate** requires contract tests, negative cases, source/package parity, host/platform compatibility and an all-green applicable CI baseline. The **architectural gate** additionally requires H1–H4 and independently reviewed paired real-task outcomes. Freeze task fixtures, acceptance rubrics, model/effort, host permissions, comparison order and thresholds **after baseline measurement but before treatment outcomes**. Compare task correctness and failures first; report successful-task token/time/tool cost and failed-run overhead separately, with uncertainty. A small inconclusive sample is not approval. Broader #320 CDG/registry compilation and physical skill moves need **explicit owner sign-off on each specific validated interface**; retain the legacy path until then.
|
|
79
|
+
|
|
80
|
+
**Cross-contract acceptance assertion:** the #341 E0/E1 gates in the Phase 3b entry-gates bullet above, [#341](https://github.com/dyphn1/Harness-everything/issues/341) and #325's phase table must stay mutually consistent: a change to one gate's semantics updates the other two records, replays affected #341 fixtures first, and only then re-collects affected 3b observations. E0 enables only the bounded, reversible, doc-only runtime consumer; E1 gates expansion beyond the limited pilot; neither approves generic #320 CDG/registry promotion, which additionally requires the H1–H4 paired real-task evidence and explicit owner sign-off above.
|
|
81
|
+
|
|
82
|
+
## Configuration (D5)
|
|
83
|
+
|
|
84
|
+
| Source | Rule |
|
|
85
|
+
| --- | --- |
|
|
86
|
+
| `.agents/harness-everything/project-docs.json` | Committed, host-neutral. When present it **wholly overrides** host-manifest `projectDocs` (no field merge); warn `project-overrides-host` when a host value differs |
|
|
87
|
+
| Invalid project file | Status `invalid` with diagnostics; no fallback to host manifests; config-dependent MUSTs report unresolved |
|
|
88
|
+
| No project file, active host known and declares `projectDocs` | Status `host`; record that manifest as the source |
|
|
89
|
+
| No project file, active host known but its manifest has no `projectDocs` | **Owner decision 2026-10-17:** `none`, recording the active host; never inherit another host's config. Warn and suggest `project-docs.json` |
|
|
90
|
+
| No project file, host unknown | All declaring hosts canonically equal → `host` (all sources recorded); they differ → `ambiguous`; none → `none` |
|
|
91
|
+
| AGENTS.md | Never a configuration source |
|
|
92
|
+
|
|
93
|
+
- Canonical comparison: object keys sorted recursively, array order preserved, whitespace irrelevant.
|
|
94
|
+
- The project file may also carry the existing zone fields (`decisionLocation`, `domainLocation`, `architectureLocation` and their aliases). Zone resolution uses the project file when present, so the override is total.
|
|
95
|
+
- Host manifests that fail to parse are skipped with an `invalid-host-config` diagnostic naming the source; they never count as agreeing or disagreeing.
|
|
96
|
+
- **Generator security (MUST):** reading or validating config never executes `derived[].generator`. Execution belongs to an authorized verification step only.
|
|
97
|
+
|
|
98
|
+
```json
|
|
99
|
+
{
|
|
100
|
+
"governed": [
|
|
101
|
+
{ "path": "docs/prd/**", "role": "prd" },
|
|
102
|
+
{ "path": "docs/adr/**", "role": "adr" }
|
|
103
|
+
],
|
|
104
|
+
"domains": ["GRPH", "IFCE"],
|
|
105
|
+
"legacy": ["docs/adr/legacy/**"],
|
|
106
|
+
"derived": [{ "path": "docs/roadmap/index.md", "generator": "npm run docs:index" }],
|
|
107
|
+
"tickets": "tracker"
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
| Field | Validation |
|
|
112
|
+
| --- | --- |
|
|
113
|
+
| `governed` | Array of `{ path: glob, role }`; `role` from the fixed vocabulary below |
|
|
114
|
+
| `domains` | Array of unique `^[A-Z][A-Z0-9]{1,9}$`. Reserved for ID prefixes: a legacy string value in a host manifest is read as `domainLocation` with a `deprecated-domains-string` warning; in `project-docs.json` it is a schema error |
|
|
115
|
+
| `legacy` | Array of globs |
|
|
116
|
+
| `derived` | Array of `{ path, generator }`, both non-empty strings |
|
|
117
|
+
| `tickets` | `"tracker"` or a repo-relative path |
|
|
118
|
+
| Unknown keys | Warning, not error |
|
|
119
|
+
|
|
120
|
+
Globs are repo-relative POSIX paths supporting `*` (one segment) and `**` (any depth).
|
|
121
|
+
|
|
122
|
+
## Roles and status (D6.1, D6.3)
|
|
123
|
+
|
|
124
|
+
| Role | Status vocabulary | `id` |
|
|
125
|
+
| --- | --- | --- |
|
|
126
|
+
| `prd` | `draft` / `approved` / `effective` / `rejected` / `withdrawn` (D6.9); pre-migration `active` / `superseded` warn unchanged and error when added or changed | Required: `PRD-<DOMAIN>-NNN` plus `revision` (D6.9) |
|
|
127
|
+
| `adr` | `proposed` / `accepted` / `rejected` / `superseded` | Required: `<DOMAIN>-NNN` |
|
|
128
|
+
| `ticket` | `open` / `blocked` / `done` / `withdrawn` | Optional |
|
|
129
|
+
| `reference` | `active` / `deprecated` | Optional |
|
|
130
|
+
| `log`, `report` | `final` / `archived` | Optional |
|
|
131
|
+
|
|
132
|
+
- Role comes from the first matching `governed` entry; a frontmatter `role` must agree with it.
|
|
133
|
+
- **Legacy immutability:** Legacy files remain outside the active ID namespace. With an observed trusted base, a path is frozen only when some base source's `legacy` matches it and no base source positively governs it after that source's own legacy exclusion; parsed frontmatter stays deep-equal while body/editorial/link edits remain allowed. A surviving path is reclassified when it is no longer legacy under the same per-source rule for candidate sources and emits `legacy-frozen-modified`; deletion/move relies on existing escalation for surviving explicit `legacy:ID@path` references. Without a trusted base, legacy immutability is not-observed or unavailable.
|
|
134
|
+
- Frontmatter fields: `id`, `role`, `status`, `supersedes`, `aliases`. `superseded_by` and `amends` are not stored; `superseded_by` is derived in the index.
|
|
135
|
+
- **Ratchet:** schema checks (role/status/ID) apply to governed files named in `changedPaths`. Full mode is explicit (`--all` / `{ all: true }`); the CLI refuses to run without `--changed`, `--changed-path` or `--all`. Cross-file integrity diagnostics are errors when any involved file is changed (deleted and renamed paths count as changed), warnings otherwise. Warnings that affect resolution still appear in the index's unresolved list. CLI `--changed` entries resolve against `--workspace`, normalize to repo-relative POSIX paths, and fail as usage errors when outside the workspace; `--changed` takes one comma-separated argument and cannot represent filenames containing commas, so repeat `--changed-path <path>` (one occurrence per path, never comma-split, normalizes and resolves like the CSV form, and mutually exclusive with `--all`; may be combined with `--changed`) when a filename contains a comma. Occurrences of either changed selector accumulate: repeated `--changed` or `--changed-path` flags add to the changed set instead of overwriting earlier declarations. The CSV form trims whitespace around its comma-separated items; `--changed-path` preserves commas and outer whitespace while resolving paths and normalizing separators. Both `/` and `\` are separators on every host; literal backslashes in POSIX filenames cannot be selected through these CLI flags — use `--all` or the API `changedPaths` for those files. Relative `--config` paths also resolve from `--workspace`. Without a trusted base, escalation for deleted or renamed targets covers explicit `legacy:ID@path` selectors only; ID-only references escalate when a trusted base (`--base` or a supplied inventory, see D6.9) maps the ID to a changed path.
|
|
136
|
+
- Parsing conventions: role comes from the first matching `governed` entry; frontmatter is the leading `---` block in a YAML subset (scalars, inline `[a, b]` lists, `- a` block lists); references inside fenced code blocks are ignored.
|
|
137
|
+
|
|
138
|
+
## IDs, aliases and references (D6.2, D6.8)
|
|
139
|
+
|
|
140
|
+
- ADR: `<DOMAIN>-NNN` (three or more digits). REQ: `REQ-<DOMAIN>-NNN`, defined only in a PRD as a heading `REQ-<DOMAIN>-NNN` at the start of a Markdown heading line (`### REQ-GRPH-012: …`).
|
|
141
|
+
- **REQ aliases — owner decision 2026-10-17:** declared on the REQ heading itself, `### REQ-GRAPH-012 (aliases: REQ-GRPH-012, REQ-GRPH-099): title`. Each alias resolves directly to that REQ; collision rules match document aliases. Document-level `aliases` never rename REQs.
|
|
142
|
+
- `DOMAIN` must be declared in `domains`. Aliases keep their historical domain, which need not be declared.
|
|
143
|
+
- `aliases: [...]` lists every previous ID; each alias resolves **directly** to the declaring document. Reject duplicate canonical IDs, an alias equal to another active canonical ID or alias, and unresolved references.
|
|
144
|
+
|
|
145
|
+
| Reference | Resolution |
|
|
146
|
+
| --- | --- |
|
|
147
|
+
| `GRPH-007` | Active canonical IDs and aliases only; never falls through to legacy |
|
|
148
|
+
| `legacy:GRPH-007` | The unique legacy document with that ID. Several matches → `ambiguous-legacy-ref` listing every candidate path; never the first match |
|
|
149
|
+
| `legacy:GRPH-007@docs/adr/legacy/v2/GRPH-007.md` | **Owner decision 2026-10-17:** the repo-relative path is the archive discriminator; resolves only when that file is legacy and carries that ID |
|
|
150
|
+
|
|
151
|
+
Selector grammar: `legacy:` + ID, optionally `@` + path, split at the **first** `@`. The path is a repo-relative POSIX path compared byte-exactly with the collected path (case-sensitive on every OS). Backslashes, leading `/`, drive letters, `.` or `..` segments, and paths outside the workspace are `invalid-ref`; they are never normalized into a match. A renamed archive path leaves old selectors `unresolved-ref` until updated.
|
|
152
|
+
|
|
153
|
+
- A legacy document's ID is its frontmatter `id`, else its file stem when that matches an ID pattern. Duplicate legacy IDs are allowed; only bare references to them are ambiguous.
|
|
154
|
+
- An active alias equal to a legacy ID is allowed (the rename case).
|
|
155
|
+
- Aliases are strings matching an ADR or REQ ID pattern. The `legacy:` prefix is reserved for references and is `invalid-alias` inside `aliases`, as are self-aliases and non-strings.
|
|
156
|
+
|
|
157
|
+
## Supersession (D6.3, D6.4)
|
|
158
|
+
|
|
159
|
+
- `supersedes` is written on the new document and means real normative replacement, never an identity rename.
|
|
160
|
+
- Active target: the target must carry `status: superseded`, else `supersede-status-mismatch`. This is the only required two-file edit.
|
|
161
|
+
- **Legacy target — owner decision 2026-10-17 (external projection):** reference it with an explicit `legacy:` ref that resolves uniquely. The legacy file is never edited; the generated index projects its status as superseded by the active document. This is the explicit legacy exception to both the D6.3 two-file lint and the D6.6 "ADR superseded → old status `superseded`" event: for legacy targets the obligation is met by the projection. The index shows the stored status and the projected effective status side by side, with the source edge.
|
|
162
|
+
- A plain ref that matches only a legacy ID is `unresolved-ref` with a hint to use `legacy:`.
|
|
163
|
+
- Self-supersession and supersession cycles are errors.
|
|
164
|
+
- **Branching and eligibility — owner decision 2026-10-17:** a target may have several successors; the index lists them sorted. Only edges from an `accepted` ADR or an `active` PRD are effective: they require the active target's `superseded` status and drive legacy projection. Edges from other statuses (`draft`, `proposed`, …) are shown as pending, do not require the target's status change, and do not project.
|
|
165
|
+
- Only explicit `supersedes` or a recorded owner decision resolves a conflict.
|
|
166
|
+
- **Recorded conflicts — owner decision 2026-10-17:** semantic PRD/ADR contradictions are not detected from prose. Whoever finds one records `conflicts_with: [<ID>]` on either document; the pair stays in the unresolved list (`recorded-conflict`, both IDs and paths) until an effective `supersedes` between them exists. Owner adjudication is recorded by that `supersedes` edge or by removing the entry in the same change that updates the canonical document. Structural conflicts are detected automatically.
|
|
167
|
+
|
|
168
|
+
## Diagnostics
|
|
169
|
+
|
|
170
|
+
Each diagnostic is `{ code, severity, path, id?, message, candidates? }`, sorted by `path`, `code`, `id`, then `message`.
|
|
171
|
+
|
|
172
|
+
Anchors for cross-file diagnostics: `supersede-*`, `unresolved-ref`, `ambiguous-legacy-ref`, `invalid-ref` and `recorded-conflict` attach to the document that declares the reference or edge. `legacy-frozen-modified` attaches to the trusted-base archive path. `duplicate-id`, `alias-collision` and `duplicate-req` emit one diagnostic on **every** involved document, each listing the others in `candidates`.
|
|
173
|
+
|
|
174
|
+
| Code | Trigger |
|
|
175
|
+
| --- | --- |
|
|
176
|
+
| `malformed-frontmatter` | Unparseable frontmatter block |
|
|
177
|
+
| `role-mismatch` | Frontmatter `role` differs from path role |
|
|
178
|
+
| `missing-status` / `invalid-status` | Status absent or outside the role vocabulary |
|
|
179
|
+
| `missing-id` / `invalid-id` / `unknown-domain` | ADR ID absent, malformed, or domain undeclared |
|
|
180
|
+
| `duplicate-id` | Two active documents share a canonical ID |
|
|
181
|
+
| `alias-collision` | Alias equals another active canonical ID or alias |
|
|
182
|
+
| `duplicate-req` / `missing-req` | REQ defined twice in active PRDs, or referenced in a governed doc but never defined |
|
|
183
|
+
| `unresolved-ref` / `ambiguous-legacy-ref` / `invalid-ref` | Reference resolves to nothing, to several legacy documents, or is malformed |
|
|
184
|
+
| `legacy-frozen-modified` | With a trusted base, legacy frontmatter changed or a surviving archive was reclassified out of legacy scope (error) |
|
|
185
|
+
| `invalid-alias` | Alias is not a string ID, is self-referential, or uses the reserved `legacy:` prefix |
|
|
186
|
+
| `invalid-host-config` | A host manifest's `projectDocs` failed to parse or validate |
|
|
187
|
+
| `supersede-status-mismatch` / `supersede-cycle` | Effective edge to an active target that is not `superseded`; self or cyclic supersession |
|
|
188
|
+
| `recorded-conflict` | `conflicts_with` pair without an effective `supersedes` between them |
|
|
189
|
+
|
|
190
|
+
## Contract-style PRD revisions (D6.9)
|
|
191
|
+
|
|
192
|
+
**Owner direction 2026-10-17:** an effective PRD is a contract. A change creates a new **complete** revision copied from the current effective revision; the effective snapshot is never edited in place. This replaces the D6.1 "living PRD" model for PRDs only; ADRs, tickets and other roles are unchanged. Where this section conflicts with earlier PRD rules (optional PRD `id`, PRD status vocabulary, PRD `supersedes`), this section wins.
|
|
193
|
+
|
|
194
|
+
### Identity and graph
|
|
195
|
+
|
|
196
|
+
| Concept | Rule |
|
|
197
|
+
| --- | --- |
|
|
198
|
+
| Logical PRD | `id: PRD-<DOMAIN>-NNN`, shared by every revision; grouped by canonical identity (aliases preserved) |
|
|
199
|
+
| Revision | `revision: <N>` positive integer, no leading zeros; canonical form `PRD-GRPH-001@r3` |
|
|
200
|
+
| Parent | `previous_revision: <N>`; must name an existing revision of the same logical PRD with a smaller number. Exactly one baseline (no parent) per logical PRD |
|
|
201
|
+
| Layout | Not mandated (recommended `docs/prd/<slug>/r003.md`); identity comes from frontmatter only |
|
|
202
|
+
| Uniqueness | `(logical id, revision)` unique. Repeated logical IDs and inherited aliases across revisions are not `duplicate-id` / `alias-collision` |
|
|
203
|
+
|
|
204
|
+
### Status, approval, activation
|
|
205
|
+
|
|
206
|
+
| Stored status | Editable | Notes |
|
|
207
|
+
| --- | --- | --- |
|
|
208
|
+
| `draft` | Yes | Never authoritative; drafts may fork |
|
|
209
|
+
| `approved` | Activation fields only | Approval bound to content |
|
|
210
|
+
| `effective` | **No**, from the change that sets it | Frozen artifact |
|
|
211
|
+
| `rejected` / `withdrawn` | Not enforced in this slice | Never selectable as current |
|
|
212
|
+
|
|
213
|
+
- **Approval record (owner decision 2026-10-17):** `approval: { by, at, ref, content_digest }`. `by` is a human or an independent cold verifier, never the drafting agent. `ref` is a URL or an in-repo record path (offline-checkable). `content_digest` covers the revision body plus non-activation frontmatter; a content edit after approval invalidates it (`approval-content-mismatch`).
|
|
214
|
+
- **Activation:** sets `status: effective` and `effective_at`; only these fields may change between `approved` and `effective`. The file path must also stay the same as in the trusted approved baseline. An `approved` revision is frozen except for activation; any other edit, including rebinding `approval`, requires returning it to `draft` and re-approving (`invalid-transition`). Deleting an approved revision or moving it outside the candidate inventory is also an `invalid-transition`. Timestamps are ISO 8601 with timezone; `effective_at` must not precede `approval.at`. Activation requires the parent to be the current effective revision (`stale-draft-base`).
|
|
215
|
+
- **Current effective** is derived after validating the whole graph: a connected chain of `effective` revisions from the baseline; two effective children of one parent → `revision-fork`; no effective revision → explicit pre-activation state. Older effective revisions are derived `historical`; their files are never edited.
|
|
216
|
+
|
|
217
|
+
### Digests and evidence envelope
|
|
218
|
+
|
|
219
|
+
- **Stored bytes:** the bytes Git stores for the file (after `git add` end-of-line normalization). Base content comes from the trusted base tree; candidate content is normalized the same way. Comparisons may use Git blob object IDs; frontmatter digests are `sha256:<hex>` over stored bytes. Pure API callers pass stored bytes directly.
|
|
220
|
+
- **Artifact digest** (`previous_digest`, immutability): sha256 over the complete stored bytes of the revision file.
|
|
221
|
+
- **Approval content digest** (`approval.content_digest`): sha256 over `JSON(frontmatter without status, effective_at, approval; keys sorted; UTF-8) + "\n" + body` (body in stored bytes). Excluding `approval` avoids self-reference; excluding activation fields lets activation keep the digest valid.
|
|
222
|
+
- **Independence:** `drafted_by` (required on `approved` and `effective` revisions; missing → `approval-missing`) names the drafting author; `approval.by` equal to `drafted_by` → `approval-not-independent`. `approval.role` is `human` or `cold-verifier`. The checker verifies the record's presence, binding and independence, not that a review actually happened.
|
|
223
|
+
- **Evidence envelope:** `analyzeDocs(docs, config, opts)` returns `{ diagnostics, evidence }` with `evidence.immutability` = `observed` | `not-observed` | `unavailable`. `lintDocs` stays the diagnostics-only projection. CLI JSON prints the envelope; exit 1 only for error diagnostics, and `not-observed` is always printed, never folded into success.
|
|
224
|
+
- **Offline base inventory:** `analyzeDocs(docs, config, { baseInventory: [{ id, revision, path, status, bytes }] })` supplies stored baseline bytes for offline checks. For Git-equivalent legacy freezing, supply either per-entry boolean `legacy` classifications computed under the per-source rule or `baseConfigSources`; when both are supplied, `baseConfigSources` takes precedence and applies the source rule. The supplied historical sources also govern migration checks, REQ identity lookup, and changed-scope calculations. Without either, legacy classification is not established for unflagged rows, which are not frozen, and `evidence.legacyImmutability` reports `not-observed` while byte-based `evidence.immutability` remains `observed`. Candidate classification uses `options.configSources` when supplied, otherwise `config`; equivalent trusted bytes and authority inputs must yield the same diagnostics as `--base`.
|
|
225
|
+
- Tests isolate Git (no global/system config, hooks, templates or signing; explicit `core.autocrlf` and attributes) and compute expected digests independently of the system under test.
|
|
226
|
+
|
|
227
|
+
### Immutability evidence
|
|
228
|
+
|
|
229
|
+
- **Byte basis (owner decision 2026-10-17):** digests use the repository-stored content (Git blob bytes, or an exported snapshot of them), so checkout line-ending conversion cannot change identity.
|
|
230
|
+
- `previous_digest` in each revision is an **internal consistency** check only; editing a parent and its child's digest together stays self-consistent.
|
|
231
|
+
- **Immutability** needs a trusted baseline: CLI `--base <git-rev>` or a supplied snapshot inventory. Base and candidate inventories are compared by `(logical id, revision)` and by path: a base-effective revision must remain present with identical bytes regardless of status edits, moves, deletions or config exclusions (`immutable-revision-modified`, `immutable-revision-deleted`). Without a trusted baseline the result is `not-observed`, never pass. The immutability scope is the **union** of governed, legacy and PRD globs from the current config and from every config source in the base tree (`project-docs.json`, each host manifest's `projectDocs`, and the base copy of an explicit `--config` path); narrowing the current config never removes a base-effective revision from checking. Stored-byte normalization follows Git's text/binary decision (including NUL detection for `text=auto` and for `core.autocrlf` without attributes); content Git stores unchanged is compared unchanged. Git is read with argument arrays, never shell interpolation; missing history is never fetched.
|
|
232
|
+
|
|
233
|
+
### REQ continuity
|
|
234
|
+
|
|
235
|
+
- Every REQ of the parent appears in the child unless accounted for by `removed_reqs: [...]` or a `replaces` edge; otherwise `req-dropped`. Each REQ block needs non-empty acceptance content (`incomplete-snapshot`). ID continuity is structural evidence only; semantic completeness still needs review.
|
|
236
|
+
- Unchanged and editorial REQs keep their IDs. A REQ whose text changed is reported as changed and needs a review classification (normative vs editorial); IDs are never recycled for unrelated meaning.
|
|
237
|
+
- Heading clauses: `### REQ-GRPH-020 (replaces: REQ-GRPH-012, REQ-GRPH-013; aliases: REQ-GRAPH-020): title`. Clauses are `;`-separated, comma lists, each at most once; unknown or duplicate clauses are errors. `replaces` allows splits and merges; a REQ ID may not be both alias and replaced target; replacement cycles are errors.
|
|
238
|
+
- `duplicate-req` applies within each revision and across the current effective revisions of different logical PRDs.
|
|
239
|
+
- Plain `REQ-…` resolves only in current effective revisions; a removed or replaced REQ is `unresolved-ref` with a historical/replacement hint, never auto-followed.
|
|
240
|
+
|
|
241
|
+
### References
|
|
242
|
+
|
|
243
|
+
| Ref | Resolves to |
|
|
244
|
+
| --- | --- |
|
|
245
|
+
| `PRD-GRPH-001` | Current effective revision |
|
|
246
|
+
| `PRD-GRPH-001@r2` | Exactly revision 2, returned with status, digest and provenance |
|
|
247
|
+
| `PRD-GRPH-001@r2#REQ-GRPH-012` | That REQ inside revision 2 (aliases resolved as of r2) |
|
|
248
|
+
|
|
249
|
+
- Parse the namespace first: `legacy:` refs keep their exact path grammar; `@r<N>` and `#REQ` apply only to PRD logical IDs. Whole-token anchored parsing; a valid prefix of an invalid ref never resolves.
|
|
250
|
+
- Pins to `draft`/`approved` revisions are provisional and never satisfy governed-implementation evidence; audit evidence pins an effective revision plus its digest.
|
|
251
|
+
|
|
252
|
+
### Cross-PRD replacement and migration
|
|
253
|
+
|
|
254
|
+
- **Retirement eligibility:** only an `effective` source revision retires a target or resolves a recorded conflict; edges from `draft`/`approved`/`rejected` revisions are pending (same rule as ADR effective edges).
|
|
255
|
+
- **Retirement is a historical event (owner decision 2026-10-17):** once any revision that was effective declares the edge, the target stays retired even if later revisions of the source omit it; omission never revives a target. The index records the revision that issued the retirement.
|
|
256
|
+
- **Retirement (owner decision 2026-10-17):** `supersedes: [PRD-GRPH-001@r4]` on another logical PRD retires that contract by external projection, like legacy targets: no file is edited, splits and merges are allowed, the exact source/target revisions are recorded, and the retired PRD stays addressable.
|
|
257
|
+
- **Baseline adoption (owner decision 2026-10-17):** an existing non-legacy living PRD gets one reviewed metadata-only edit adding `revision: 1`, approval and a `migrated_from_digest` of its prior content, recorded in a migration record. The baseline frontmatter names the record with `migration_record: <repo-relative path>`; the record is JSON `{ record: "prd-baseline-migration", id, revision, source, migrated_from_digest, approved_by }` and must match the frontmatter and the base content of `source` (`migration-record-missing` / `migration-record-mismatch`). `baseline` status never exempts later edits. Legacy PRDs stay frozen outside the graph.
|
|
258
|
+
|
|
259
|
+
### Diagnostics (D6.9)
|
|
260
|
+
|
|
261
|
+
`invalid-prd-id`, `invalid-revision`, `duplicate-revision`, `missing-parent`, `multiple-baselines`, `revision-cycle`, `revision-fork`, `stale-draft-base`, `invalid-transition`, `approval-missing`, `approval-content-mismatch`, `revision-digest-mismatch`, `immutable-revision-modified`, `immutable-revision-deleted`, `req-dropped`, `incomplete-snapshot`, `invalid-req-clause`, `replacement-alias-overlap`, `replacement-cycle`. `not-observed` is an evidence disposition, not a diagnostic and not a pass.
|
|
262
|
+
|
|
263
|
+
## D6.5 — `doc-change` applicability by diff facts (Decided; revised 2026-10-16)
|
|
264
|
+
|
|
265
|
+
Not a single class enum. The diff yields **facts**; required checks are the **union** of what each fact triggers. If a fact cannot be determined, assume it is present (`unknown` never downgrades to trivial).
|
|
266
|
+
|
|
267
|
+
| Fact (from diff) | Triggers |
|
|
268
|
+
| --- | --- |
|
|
269
|
+
| Any governed file touched | Lint (role/status/ID/alias); in-repo link check |
|
|
270
|
+
| Text/format only (no fact below) | Nothing more |
|
|
271
|
+
| New governed file | Update-over-create check; outline confirmation (MUST for PRD/ADR, SHOULD otherwise) |
|
|
272
|
+
| Declared derived source affected | Regenerate + regenerate-equals |
|
|
273
|
+
| **Normative field**: frontmatter `status`/`supersedes`, PRD REQ block/acceptance, ADR *Decision* section | Quality review (MUST); D6.4 conflict check |
|
|
274
|
+
| Governed reference/guide content | Prose > 50% reminder (SHOULD) |
|
|
275
|
+
| Code or REQ-citing test touched | `requirement-sync` evaluation (D6.6) |
|
|
276
|
+
|
|
277
|
+
Decision extraction recognizes ATX boundaries with 0–3 leading spaces and ignores fenced or indented code. A suspected Setext Decision heading, or an unsupported Setext boundary within an ATX Decision section, yields `unknown`; paragraph/container context is not inferred.
|
|
278
|
+
|
|
279
|
+
- Example: a typo in an ADR's *Context* section triggers only lint + links; the same typo in its *Decision* section is normative.
|
|
280
|
+
- Claimed scope vs diff facts mismatch → claim/evidence contradiction (#320 D3), only where the diff supports it; visible, never a lock.
|
|
281
|
+
- Commit still requires existing workflow authorization; no automatic commit.
|
|
282
|
+
|
|
283
|
+
## D6.6 — Event-driven maintenance (Decided)
|
|
284
|
+
|
|
285
|
+
**`requirement-sync` detection** (builds on D6.2: tests cite REQ IDs):
|
|
286
|
+
|
|
287
|
+
| Observation | Disposition |
|
|
288
|
+
| --- | --- |
|
|
289
|
+
| A test citing `REQ-X` is added or its assertions change | **Candidate signal**, not proof → **MUST** update/supersede REQ-X in the PRD in the same change, or record a structured `no-req-change` (reason + cited evidence, e.g. unchanged acceptance, passing test result) |
|
|
290
|
+
| An existing test's cited REQ identity set is added, removed, or retargeted, or the changed call cannot be associated with its prior identity | Applicability/scope `unknown`, never N/A; retain candidate REQ identities and the test path. If removal leaves no candidate identity, retain the prior REQ ID as a removed identity. A citation-only change is not by itself a `new-test` or `assertion-change` trigger |
|
|
291
|
+
| A legacy file-level REQ tag is added, removed, or retargeted on a modified test file | Applicability/scope `unknown`, never N/A; retain the changed identity and test path, even when stripped comments leave assertion tokens unchanged |
|
|
292
|
+
| A test title changes or reorders REQ IDs while preserving the same cited identity set, or an ordinary comment changes | No trigger → `requirement-sync` N/A |
|
|
293
|
+
| Ordinary comment-only or whitespace-only edit that preserves the cited REQ identity set | Not a trigger → `requirement-sync` N/A |
|
|
294
|
+
| REQ-citing test change whose assertion change cannot be determined | `unknown`; never a fail |
|
|
295
|
+
| Triggered MUST, **attested envelope** (all of the following), cited REQ resolved, **not** revised, **no** valid `no-req-change` waiver | **Observed fail** (`req-sync-no-revision-or-waiver`). Not a Stop hook, lock, or completion policy |
|
|
296
|
+
| Triggered MUST, `complete` inventory but envelope incomplete, mismatched, or unattested | `none` with `req-sync-envelope-unattested`. Never a fail |
|
|
297
|
+
| Attested envelope = `complete` and `waiverInventoryComplete` both `true`; `baseDigest` equal to the baseline digest; `candidateDigest` equal to the digest of the candidate PRD set; `configDigest` present; non-empty cited REQ list | Caller-attested. The derivation copies it and never infers it. Not independent proof that the caller collected the inventory completely |
|
|
298
|
+
| Unsupported or stale `no-req-change` waiver | Unverified (`unsupported-waiver`). It never satisfies the MUST. It does not by itself establish the failure, and an independently attested unmet obligation may still fail |
|
|
299
|
+
| `no-req-change` without adequate evidence | `not-observed` / unverified; never an automatic pass. An invalid waiver is diagnosed and does not satisfy the MUST |
|
|
300
|
+
| Cited REQ missing, ambiguous, or unresolved | `unresolved` with `req-unresolved`; never a pass, never an observed fail. "Ambiguous" means declared in two distinct current logical PRDs. Retained revisions of one PRD resolve to the current effective revision |
|
|
301
|
+
| Incomplete execution record (no command, no provenance, non-integer `exitCode`) | `execution-record-incomplete`; never a pass |
|
|
302
|
+
| Code changes, no REQ-citing test touched | `not-observed` (#320 D3 evidence state), not a failure; diff alone never proves behavior unchanged |
|
|
303
|
+
| Agent claims REQ-X affected, no supporting evidence | Claim/evidence contradiction; reminder, no lock |
|
|
304
|
+
|
|
305
|
+
| Event | Obligation | Strength | Enforced by |
|
|
306
|
+
| --- | --- | --- | --- |
|
|
307
|
+
| REQ touched (above) | `requirement-sync` | MUST | New rule |
|
|
308
|
+
| `describes:` fingerprint drift | Reminder | SHOULD | D5 #4 |
|
|
309
|
+
| Ticket closed | In-repo tickets: `status: done`; regenerate index. `tickets: "tracker"`: no in-repo ticket status is generated or inferred offline | MUST | D5 #1 + D6.3 lint |
|
|
310
|
+
| ADR superseded | Old ADR `status: superseded` | MUST | D6.3 lint |
|
|
311
|
+
| New defect | Goes to tracker or the declared `tickets` path | MUST | Lint reminder when a ticket is added under a `done` phase |
|
|
312
|
+
| Report finished | `final`; `archived` once its work closes | SHOULD | Reminder |
|
|
313
|
+
|
|
314
|
+
- All events are checked at the existing workflow's `verification` step; no standing maintenance loop.
|
|
315
|
+
- Checks are pure and generators deterministic, so reruns are idempotent.
|
|
316
|
+
- `requirement-sync` is the only genuinely new rule; the rest reuse D5 and D6.3 checks.
|
|
317
|
+
|
|
318
|
+
## Packaging
|
|
319
|
+
|
|
320
|
+
Source checkout, Codex plugin and Claude plugin copy whole skill trees. Callers locate `doc-lifecycle.js` and the resolver relative to their own skill directory, never the source-tree root. A to-spec-only install must use the same resolver implementation (copied byte-identically and checked), and a broken shared module is an error, never a silent fallback to older host scanning.
|
|
321
|
+
|
|
322
|
+
## Generated index
|
|
323
|
+
|
|
324
|
+
`buildIndex` returns Markdown with no timestamps or environment data, so two runs over the same tree are byte-identical. Sections: active documents (sorted by ID then path, with derived `superseded by`), legacy documents (sorted by ID then path, with projected status), and the unresolved list (resolution-affecting error diagnostics).
|
|
325
|
+
|
|
326
|
+
The shared `AUTHORITY_BLOCKER_DIAGNOSTICS` taxonomy covers `invalid-prd-id`, `invalid-revision`, `invalid-status`, `invalid-alias`, `duplicate-revision`, `missing-parent`, `multiple-baselines`, `revision-cycle`, `revision-fork`, `revision-digest-mismatch`, `req-dropped`, `incomplete-snapshot`, `invalid-req-clause`, `duplicate-req`, `replacement-alias-overlap`, `replacement-cycle`, `approval-missing`, `approval-not-independent`, `approval-content-mismatch`, `invalid-transition`, `stale-draft-base`, `migration-record-missing`, `migration-record-mismatch`, `immutable-revision-modified`, `immutable-revision-deleted`, `legacy-frozen-modified`, `duplicate-id`, `alias-collision`, `unknown-domain`, `invalid-id` and `role-mismatch`. Retirement eligibility uses the validated effective prefix and blocks on these authority findings regardless of ratchet severity; this prevents a known identity, alias or REQ collision from authorizing a new retirement. Namespace and REQ collisions are computed before the final prefix and supersession/conflict projection. Index current-state display uses the same blocker taxonomy with error severity: an error on the graph-selected current revision or a required effective ancestor produces `state: invalid; current: none`, while warnings stay visible in Unresolved without revoking `valid/current`. A pending descendant cannot discard an earlier valid effective prefix or its historical retirement event. The unresolved list also includes resolution diagnostics `malformed-frontmatter`, `missing-id`, `missing-req`, `unresolved-ref`, `ambiguous-legacy-ref`, `invalid-ref`, `missing-status`, `supersede-status-mismatch`, `supersede-cycle`, `recorded-conflict` and `prd-migration-required`; these remain visible at their reported severity but do not themselves block retirement eligibility or current-state display. When `buildIndex` receives no `diagnostics`, it runs `analyzeDocs` with the supplied options (including trusted-base inputs) and renders that result; callers that provide precomputed diagnostics must provide diagnostics from the same analysis context, with its graph and validated-prefix set, for equivalent retirement and current-state output.
|
|
327
|
+
|
|
328
|
+
See [missing](./does-not-exist.md).
|
|
File without changes
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
{
|
|
2
|
+
"lint": {
|
|
3
|
+
"exit": 1,
|
|
4
|
+
"evidence": {
|
|
5
|
+
"immutability": "observed"
|
|
6
|
+
},
|
|
7
|
+
"diagnostics": [
|
|
8
|
+
{
|
|
9
|
+
"code": "invalid-status",
|
|
10
|
+
"severity": "error",
|
|
11
|
+
"path": "docs/document-lifecycle.md",
|
|
12
|
+
"message": "status bogus is not valid for reference"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"code": "missing-req",
|
|
16
|
+
"severity": "error",
|
|
17
|
+
"path": "docs/document-lifecycle.md",
|
|
18
|
+
"message": "requirement REQ-GRAPH-012 is referenced but is not defined in an active PRD",
|
|
19
|
+
"id": "REQ-GRAPH-012"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"code": "missing-req",
|
|
23
|
+
"severity": "error",
|
|
24
|
+
"path": "docs/document-lifecycle.md",
|
|
25
|
+
"message": "requirement REQ-GRAPH-020 is referenced but is not defined in an active PRD",
|
|
26
|
+
"id": "REQ-GRAPH-020"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"code": "missing-req",
|
|
30
|
+
"severity": "error",
|
|
31
|
+
"path": "docs/document-lifecycle.md",
|
|
32
|
+
"message": "requirement REQ-GRPH-012 is referenced but is not defined in an active PRD",
|
|
33
|
+
"id": "REQ-GRPH-012"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"code": "missing-req",
|
|
37
|
+
"severity": "error",
|
|
38
|
+
"path": "docs/document-lifecycle.md",
|
|
39
|
+
"message": "requirement REQ-GRPH-013 is referenced but is not defined in an active PRD",
|
|
40
|
+
"id": "REQ-GRPH-013"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"code": "missing-req",
|
|
44
|
+
"severity": "error",
|
|
45
|
+
"path": "docs/document-lifecycle.md",
|
|
46
|
+
"message": "requirement REQ-GRPH-020 is referenced but is not defined in an active PRD",
|
|
47
|
+
"id": "REQ-GRPH-020"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"code": "missing-req",
|
|
51
|
+
"severity": "error",
|
|
52
|
+
"path": "docs/document-lifecycle.md",
|
|
53
|
+
"message": "requirement REQ-GRPH-099 is referenced but is not defined in an active PRD",
|
|
54
|
+
"id": "REQ-GRPH-099"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"code": "unresolved-ref",
|
|
58
|
+
"severity": "error",
|
|
59
|
+
"path": "docs/document-lifecycle.md",
|
|
60
|
+
"message": "reference GRPH-007 cannot be resolved",
|
|
61
|
+
"id": "GRPH-007"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"code": "unresolved-ref",
|
|
65
|
+
"severity": "error",
|
|
66
|
+
"path": "docs/document-lifecycle.md",
|
|
67
|
+
"message": "reference PRD-GRPH-001 cannot be resolved",
|
|
68
|
+
"id": "PRD-GRPH-001"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"code": "unresolved-ref",
|
|
72
|
+
"severity": "error",
|
|
73
|
+
"path": "docs/document-lifecycle.md",
|
|
74
|
+
"message": "reference PRD-GRPH-001@r2 cannot be resolved",
|
|
75
|
+
"id": "PRD-GRPH-001@r2"
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"code": "unresolved-ref",
|
|
79
|
+
"severity": "error",
|
|
80
|
+
"path": "docs/document-lifecycle.md",
|
|
81
|
+
"message": "reference PRD-GRPH-001@r2#REQ-GRPH-012 cannot be resolved",
|
|
82
|
+
"id": "PRD-GRPH-001@r2#REQ-GRPH-012"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"code": "unresolved-ref",
|
|
86
|
+
"severity": "error",
|
|
87
|
+
"path": "docs/document-lifecycle.md",
|
|
88
|
+
"message": "reference PRD-GRPH-001@r3 cannot be resolved",
|
|
89
|
+
"id": "PRD-GRPH-001@r3"
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"code": "unresolved-ref",
|
|
93
|
+
"severity": "error",
|
|
94
|
+
"path": "docs/document-lifecycle.md",
|
|
95
|
+
"message": "reference PRD-GRPH-001@r4 cannot be resolved",
|
|
96
|
+
"id": "PRD-GRPH-001@r4"
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"code": "unresolved-ref",
|
|
100
|
+
"severity": "error",
|
|
101
|
+
"path": "docs/document-lifecycle.md",
|
|
102
|
+
"message": "reference legacy:GRPH-007 cannot be resolved",
|
|
103
|
+
"id": "legacy:GRPH-007"
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"code": "unresolved-ref",
|
|
107
|
+
"severity": "error",
|
|
108
|
+
"path": "docs/document-lifecycle.md",
|
|
109
|
+
"message": "reference legacy:GRPH-007@docs/adr/legacy/v2/GRPH-007.md cannot be resolved",
|
|
110
|
+
"id": "legacy:GRPH-007@docs/adr/legacy/v2/GRPH-007.md"
|
|
111
|
+
}
|
|
112
|
+
]
|
|
113
|
+
},
|
|
114
|
+
"links": {
|
|
115
|
+
"checked": 7,
|
|
116
|
+
"broken": [
|
|
117
|
+
{
|
|
118
|
+
"path": "docs/document-lifecycle.md",
|
|
119
|
+
"line": 328,
|
|
120
|
+
"target": "./does-not-exist.md"
|
|
121
|
+
}
|
|
122
|
+
]
|
|
123
|
+
},
|
|
124
|
+
"coverage": {
|
|
125
|
+
"unsupported": []
|
|
126
|
+
}
|
|
127
|
+
}
|
|
File without changes
|