@antoneeo/agentic-sdlc-skill 1.48.0 → 1.50.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/CHANGELOG.md CHANGED
@@ -2,6 +2,63 @@
2
2
 
3
3
  Tutte le modifiche significative a questa skill saranno documentate in questo file.
4
4
 
5
+ ## [1.50.0] - 2026-10-31
6
+
7
+ ### What's new
8
+
9
+ **You approve the design before any code is written.** On significant work, once the independent design review passes, the agent stops and shows you a short summary of the design: what the change does, for whom and through which surfaces, which files it touches, the risks and how they are handled, and what the review found. The work starts only after your yes, which the agent records in the unit's request record. A "go ahead" given before you saw the design does not count, and in a session with nobody to answer the unit waits for you. A design that is right but not what you meant is cheapest to fix before the code exists. If you work with devPNT, your acceptance of the design proposal there is this approval, and nothing else is asked.
10
+
11
+ **The npm page tells you what is new.** This section, at the top of the package page, now summarizes each version for the people who install it.
12
+
13
+ **From 1.49.0, published without notes:**
14
+ - **Fewer regressions on significant changes.** When an analysis states what must not break, the agent is reminded of it just before it edits that file, not only at the start of the work, and the reviewer has the list to check. It is a reminder and never blocks the work; for now it works on Claude Code.
15
+ - **The process checks can no longer be bypassed by accident.** Quoting a work level inside a sentence no longer counts as declaring it, and protected parts of the project stay protected when the agent changes folder.
16
+ - **You know what the project memory has not read yet.** The agent can tell how much of the project it has never examined (automatically in projects with a corpus, on request otherwise).
17
+ - **Defects found after the merge can be recorded** without distorting the review statistics.
18
+
19
+ #### What to do
20
+
21
+ **1. Update (everyone).** The changes arrive only with the update.
22
+ 1. Run `npm install -g @antoneeo/agentic-sdlc-skill@latest`, then `agentic-sdlc-install-skill`.
23
+ 2. Close and reopen your agent sessions: the new version loads only at startup.
24
+
25
+ To check: `npm ls -g @antoneeo/agentic-sdlc-skill` shows 1.50.0.
26
+
27
+ If you do not want the constraint reminder (Claude Code only, from 1.49.0): remove the entry that contains `constraints --hook` from `~/.claude/settings.json`. Later updates will not put it back.
28
+
29
+ **2. Approving the design (significant units).**
30
+ - **This concerns you if** you use the skill for significant (L3) work. Nothing to configure: after the design review passes, the agent asks whether to proceed. Answer yes to start the code, or say what to change; the design is then revised and, where the change touches what the review judged, reviewed again before you are asked again.
31
+ - **A unit already in progress.** Units started before 2026-10-31 are not affected. If a unit started on or after 2026-10-31 with an earlier version is already in progress or finished, `sdlc_check.py validate` shows a `[note]` saying it has `no design approval in its request record`. Why: the earlier version never asked you. To clear it, tell the agent that you approve the design as it was implemented; it records your words under a label that begins `design approved` (for example `design approved after implementation`). The note never fails a check, so you can also leave it.
32
+ - **To check:** on your next significant unit, the agent stops after the design review and asks you before any code starts.
33
+
34
+ **3. Protected folders in a repository with several `ai_docs/` (only if you use them; from 1.49.0).**
35
+ - **This concerns you if** your agent settings contain `gate --hook --protected` and the repository has more than one `ai_docs/` folder, for example a package with its own.
36
+ - **Why:** protected paths are now read from the `ai_docs/` nearest to the edited file. A path written from the repository root, such as `packages/api/src/auth`, no longer matches the files inside `packages/api`, so the agent could change them without an analysis.
37
+ - **Steps:** rewrite those paths from the package: `packages/api/src/auth` becomes `src/auth`. Note that `src/auth` then protects the folder with that name in every project that has its own `ai_docs/`.
38
+ - **To check:** in a session with no open analysis, ask the agent for a small change to a protected file. It must be refused.
39
+
40
+ ### Changed
41
+ - After the design review's final PASS, an L3 unit stops: the agent presents a short summary of the design (what it does, for whom and through which surfaces, what it touches, threats, the review's verdict) and asks the owner whether to proceed. Only a yes, recorded in the request record under a label that begins `design approved`, moves the ANALYSIS to `IN_PROGRESS`. An instruction given before the design was shown is not an approval; unattended, the unit is `BLOCKED on the user`; in Hybrid the approval in devPNT counts. The rule is in `review.md`; `SKILL.md`, `elicitation.md` and `templates.md` point at it (F-087).
42
+ - The shared validator: `validate` notes an L3 ANALYSIS in implementation, started on or after 2026-10-31, whose request record holds no entry whose label begins `design approved`. It is a `[note]`: `--strict` exits as before. The `gate` refusal message adds that at L3 the ANALYSIS goes `IN_PROGRESS` only after the owner's design approval; its exit codes are unchanged (F-087).
43
+ - The package's npm page (its README) gains a "What's new in <version>" section right after the introduction, written for the people who install the package and linking the full CHANGELOG. It appears from the first version that carries one; each version's notes are the `### What's new` at the top of its CHANGELOG section (F-070). The "Shared project memory" section moves from the top of the page to just after the features, unchanged.
44
+
45
+ ## [1.49.0] - 2026-10-27
46
+
47
+ ### Added
48
+ - Shared knowledge layer (F-084, kb CHANGELOG): `inventory <path>` and orient's upper bound of never-examined project files reach this lens; `validate`/`check` refuse a malformed `audit/INVENTORY_exclusions.md` row and the new `DECLARED`/`DIVERGES` claim rules; the docs site renders them. `sdlc_core.skip_dir` is extracted from `iter_files`, behaviour unchanged.
49
+ - `sdlc_check.py constraints --unit <id>` shows the constraints an ANALYSIS states in extractable form — its `UC`/`FS`/`T` items and the rows of the new `### Preservation constraints` table — each with its line, and ends with the sections it could not extract. `constraints --file <path>` shows those of the open L3 units that bind that file.
50
+ - Constraint recall on Claude Code: before an edit of a file the open L3 unit binds, the agent receives those constraints in its context (at most 15 lines). It informs and never decides: no permission decision, silent at every other level, always exit 0. Installing wires it beside the guide-verdict check; removing that hook entry is a standing opt-out.
51
+ - ANALYSIS template: `UC<n>`/`FS<n>`/`T<n>` ids, and under `## Impact` the `### Preservation constraints` table (symbol, callers, what must stay true, evidence), which replaces the prose blast radius; a unit that changes no existing symbol writes `No existing symbol changed.` `validate` notes an open L3 that has neither — a note, never an error.
52
+ - At closure, unreleased preservation constraints are copied into the component's code guide under `## Preservation constraints`; a constraint stops binding only on the owner's own words.
53
+ - REVIEW_LOG tier `post-merge`: the owner's report of a wrong behaviour in a merged L3 change. `benefit` keeps it out of every review figure; the docs site shows it as "defect reported after merge".
54
+
55
+ ### Changed
56
+ - The uninstaller names each hook entry it removes by its own name; two hooks now share PreToolUse.
57
+
58
+ ### Fixed
59
+ - Shared claim checks (`check`, every lens): a `RULING` row on a note that names a foreign origin (`imported_from:`) is refused — relabelling an imported row is not ratifying it; the message for a row superseded by an `IMPORTED` one names the ratification act. The kb lens's `import` now makes an imported ruling arrive as `IMPORTED` on a renamed copy of its note and reopens the set it had settled (kb CHANGELOG, F-083).
60
+ - Guide-verdict check (`verdict --hook`): a level quoted inside a sentence (`Level: L1` in prose) no longer counts as a declaration: only a line that opens with the level word does, the rule the constraint recall already uses (level 1 alone, `L1` or `E1`; levels 2 and 3 with `router` on the same line). The check now judges the project, and its docs-root name, that holds the edited file, not the one around the session's working directory; after a `cd` out of the project it let every edit through. A router verdict follows the same rule: only a line that opens with `router` or declares the level with it counts, never `router: no match` quoted in a sentence; `Level: Spike · router: …` and markdown openers (`##`, `1.`, `•`) count. A quote that itself opens a line (blockquote, code fence) still counts. The protected-path gate (`gate --hook`, `gate --file`) also judges the edited file's project, falls back to the session's project when no docs root sits above the file, and stays silent instead of exiting with an error when two docs roots sit side by side. Its `--protected` prefixes are relative to the nearest docs root above the edited file: with nested docs roots (a monorepo package with its own `ai_docs/`, or a docs folder inside a protected path) rewrite them relative to that root, or the path is no longer protected.
61
+
5
62
  ## [1.48.0] - 2026-10-23
6
63
 
7
64
  ### Changed
package/README.md CHANGED
@@ -1,22 +1,44 @@
1
1
  # Agentic SDLC Skill for Claude Code, Gemini CLI, Google Antigravity & Codex
2
2
 
3
- ## Shared project memory
3
+ `agentic-sdlc` is a Documentation-First SDLC protocol for AI coding agents. It supports Claude Code, Codex, Gemini CLI, Google Antigravity 2.0, Cursor/Windsurf-style project instructions, and optional devPNT governance.
4
4
 
5
- All four lenses include project memory by default; install the lens you need,
6
- not a second skill just for recall. `index` registers guides, decisions and plans
7
- in the docs root's `memory/INDEX.md`, linking originals without copying them.
8
- `recall "onboarding"` finds related metadata across domains; optional
9
- `topics: [onboarding]` links documents by subject. Read the originals for authority,
10
- status and evidence: discovery is not approval or proof of implementation.
5
+ <!-- whats-new:begin -->
6
+ <!-- generated by scripts/whats_new.js from CHANGELOG.md: edit the CHANGELOG, then run node scripts/whats_new.js --write -->
7
+ ## What's new in 1.50.0
11
8
 
12
- Registration happens at `index`/documentation closure, not through a background
13
- watcher. Existing projects acquire the catalog on their next `index`; `recall`
14
- also sees live metadata. The KB lens remains the specialist for ingestion and
15
- taxonomy. Marketing retains its numerical validators. See the skill's `memory.md`.
16
- Vendoring requires all three files: the entry point, `sdlc_core.py`, `knowledge.py`.
9
+ **You approve the design before any code is written.** On significant work, once the independent design review passes, the agent stops and shows you a short summary of the design: what the change does, for whom and through which surfaces, which files it touches, the risks and how they are handled, and what the review found. The work starts only after your yes, which the agent records in the unit's request record. A "go ahead" given before you saw the design does not count, and in a session with nobody to answer the unit waits for you. A design that is right but not what you meant is cheapest to fix before the code exists. If you work with devPNT, your acceptance of the design proposal there is this approval, and nothing else is asked.
17
10
 
11
+ **The npm page tells you what is new.** This section, at the top of the package page, now summarizes each version for the people who install it.
18
12
 
19
- `agentic-sdlc` is a Documentation-First SDLC protocol for AI coding agents. It supports Claude Code, Codex, Gemini CLI, Google Antigravity 2.0, Cursor/Windsurf-style project instructions, and optional devPNT governance.
13
+ **From 1.49.0, published without notes:**
14
+ - **Fewer regressions on significant changes.** When an analysis states what must not break, the agent is reminded of it just before it edits that file, not only at the start of the work, and the reviewer has the list to check. It is a reminder and never blocks the work; for now it works on Claude Code.
15
+ - **The process checks can no longer be bypassed by accident.** Quoting a work level inside a sentence no longer counts as declaring it, and protected parts of the project stay protected when the agent changes folder.
16
+ - **You know what the project memory has not read yet.** The agent can tell how much of the project it has never examined (automatically in projects with a corpus, on request otherwise).
17
+ - **Defects found after the merge can be recorded** without distorting the review statistics.
18
+
19
+ #### What to do
20
+
21
+ **1. Update (everyone).** The changes arrive only with the update.
22
+ 1. Run `npm install -g @antoneeo/agentic-sdlc-skill@latest`, then `agentic-sdlc-install-skill`.
23
+ 2. Close and reopen your agent sessions: the new version loads only at startup.
24
+
25
+ To check: `npm ls -g @antoneeo/agentic-sdlc-skill` shows 1.50.0.
26
+
27
+ If you do not want the constraint reminder (Claude Code only, from 1.49.0): remove the entry that contains `constraints --hook` from `~/.claude/settings.json`. Later updates will not put it back.
28
+
29
+ **2. Approving the design (significant units).**
30
+ - **This concerns you if** you use the skill for significant (L3) work. Nothing to configure: after the design review passes, the agent asks whether to proceed. Answer yes to start the code, or say what to change; the design is then revised and, where the change touches what the review judged, reviewed again before you are asked again.
31
+ - **A unit already in progress.** Units started before 2026-10-31 are not affected. If a unit started on or after 2026-10-31 with an earlier version is already in progress or finished, `sdlc_check.py validate` shows a `[note]` saying it has `no design approval in its request record`. Why: the earlier version never asked you. To clear it, tell the agent that you approve the design as it was implemented; it records your words under a label that begins `design approved` (for example `design approved after implementation`). The note never fails a check, so you can also leave it.
32
+ - **To check:** on your next significant unit, the agent stops after the design review and asks you before any code starts.
33
+
34
+ **3. Protected folders in a repository with several `ai_docs/` (only if you use them; from 1.49.0).**
35
+ - **This concerns you if** your agent settings contain `gate --hook --protected` and the repository has more than one `ai_docs/` folder, for example a package with its own.
36
+ - **Why:** protected paths are now read from the `ai_docs/` nearest to the edited file. A path written from the repository root, such as `packages/api/src/auth`, no longer matches the files inside `packages/api`, so the agent could change them without an analysis.
37
+ - **Steps:** rewrite those paths from the package: `packages/api/src/auth` becomes `src/auth`. Note that `src/auth` then protects the folder with that name in every project that has its own `ai_docs/`.
38
+ - **To check:** in a session with no open analysis, ask the agent for a small change to a protected file. It must be refused.
39
+
40
+ Full history: [CHANGELOG](https://github.com/Antoneeo/agentic-sdlc-skill/blob/main/CHANGELOG.md)
41
+ <!-- whats-new:end -->
20
42
 
21
43
  ## Key Features
22
44
 
@@ -28,15 +50,31 @@ Vendoring requires all three files: the entry point, `sdlc_core.py`, `knowledge.
28
50
  - **Several people, one project**: the workstream registry (`audit/handoff.md`) is **generated** from one file per open workstream, so two people opening or closing two workstreams on two branches edit two different files and their merge is clean. Row-per-workstream alone was not enough — a file-global `Date:` header defeats row-level ownership — so the header is derived from the sources and no writer touches it. The generated view can still conflict; that conflict is resolved by re-running `index`, never by hand, and `validate` refuses CLEAN until the file matches its sources. The append-only review log gets `merge=union` (a built-in driver, no per-clone configuration). It all works with no VCS at all: it is files and a generator.
29
51
  - **Merge review brief and E2E script**: every L3 closure ships `MERGE_REVIEW_[feature].md` for the integrator — what to review, what was verified by which gate, what only a human can judge — with a map from `sdlc_check.py review-map` that classes each changed file REVIEW / DESIGN / EVIDENCE / GENERATED (generated indexes are skipped, `check` proves them), and `E2E_TEST_[feature].md` for human testers after the merge: regression scenarios always, new-behavior scenarios when behavior changed.
30
52
  - **Verbatim request record**: every L3 starts `audit/requests/REQUEST_[feature].md` before the Vision Gate — the owner's own words and every later decision (answers, approvals, costs, rulings), append-only and redacted for secrets — so analyses cite what was asked instead of paraphrasing it, and reviewers can verify owner statements instead of trusting the author.
53
+ - **Constraints at the moment of action**: at L3 the use cases, spec items and threats carry ids and the blast radius is a `### Preservation constraints` table (symbol, callers, what must stay true, evidence). `sdlc_check.py constraints --unit <id>` shows a unit's constraints and `--file <path>` those binding a file; on Claude Code a context-only hook recalls them just before the agent edits a bound file in an L3 session — it never makes a permission decision. At closure the preservation rows move to the component's code guide.
31
54
  - **Opt-in subagent execution**: an approved design projects into a validated executable plan an orchestrator can drive through subagents.
32
55
  - **Self-activating**: a SessionStart hook emits repo-sourced orientation; a deterministic self-eval battery guards the skill's own doctrine as the release gate.
33
56
  - **Standalone complete**: works fully with local `ai_docs/` without requiring devPNT.
34
57
  - **devPNT symbiosis**: when devPNT is available, Master Plan, Action Plan, M-VISION, and governed artifacts become the authoritative planning layer, and every governed artifact passes an independent agent review before it is proposed; devPNT itself performs no review — it is where you review and approve.
35
- - **Independent review, twice**: the design is reviewed before it is implemented and the diff before the work is declared done — by somebody other than its author, who receives the whole review mandate in a fixed block copied verbatim, never a paraphrase of it. Three rungs of independence (fresh-context subagent > one-shot run > a declared self-pass, legal only when no higher rung is usable: absent, or permission-gated and declined — a gated rung is asked about, never silently skipped, and the log says which), capped at 3 rounds, one log line per review, and a PASS is invalid on "found nothing" — it must state where each constraint is satisfied.
58
+ - **Independent review, twice**: the design is reviewed before it is implemented and the diff before the work is declared done — by somebody other than its author, who receives the whole review mandate in a fixed block copied verbatim, never a paraphrase of it. Three rungs of independence (fresh-context subagent > one-shot run > a declared self-pass, legal only when no higher rung is usable: absent, or permission-gated and declined — a gated rung is asked about, never silently skipped, and the log says which), capped at 3 rounds, one log line per review, and a PASS is invalid on "found nothing" — it must state where each constraint is satisfied. After the design review passes, the owner approves the design before any code is written.
36
59
  - **Question discipline**: a real doubt is asked when it emerges, before its answer is written into any document — grouped, with the pros and cons of each option. A choice whose pros clearly win is taken without asking, and the weighing is written next to it; a fact is settled by evidence or asked, never weighed. A question is legal only when the agent searched first, names the search with its result, and names the decision it unblocks — never a stream of "shall I proceed?".
37
60
  - **Installed support files**: Claude, Codex, Gemini, and Google Antigravity receive the full skill folder, including `templates.md`, `architect.md`, `guides.md`, `vision.md`, `tdd.md`, `debugging.md`, `elicitation.md`, `review.md`, `dispatch.md`, `routing.md`, `hybrid.md`, `ENFORCEMENT.md`, `memory.md`, and the validator's three files, `scripts/sdlc_check.py` + `scripts/sdlc_core.py` + `scripts/knowledge.py` — plus the docs site generator `scripts/docs_site.py` and its page `docs_site/`, and the `LICENSE` and `NOTICE` it ships under.
38
61
  - **Docs site** (`scripts/docs_site.py --root <project> [--open] [--zip <file>]`): a static, offline, read-only website of what the agent reads in the project — reading guide, Vision, rules, documents, open work with each next step, analyses and, with a knowledge base, the topic map, each fact with its exact source passage, and the source documents. Written to `.docs-site/` (added to `.gitignore` on the first run), outside `ai_docs/`; nothing is ranked or recommended.
39
- - **Mechanical checks**: optional validator for document structure, generated feature history, stale audit areas, and protected-path gates — `check`, `validate`, `index`, `stale`, `mark`, `benefit`, `gate`, `plan`, `orient`, `migrate`, `review-map` (code lens: classes the files of a change for the merge review brief). `benefit` reports what the review gates have already caught, beside what the doctrine costs to read — it always exits 0 and carries no verdict, because a measurement that can fail a build becomes a target.
62
+ - **Mechanical checks**: optional validator for document structure, generated feature history, stale audit areas, and protected-path gates — `check`, `validate`, `index`, `stale`, `mark`, `benefit`, `gate`, `plan`, `orient`, `migrate`, `review-map` (code lens: classes the files of a change for the merge review brief), `constraints` (code lens: a unit's constraints, or those binding a file). `benefit` reports what the review gates have already caught, beside what the doctrine costs to read — it always exits 0 and carries no verdict, because a measurement that can fail a build becomes a target.
63
+
64
+ ## Shared project memory
65
+
66
+ All four lenses include project memory by default; install the lens you need,
67
+ not a second skill just for recall. `index` registers guides, decisions and plans
68
+ in the docs root's `memory/INDEX.md`, linking originals without copying them.
69
+ `recall "onboarding"` finds related metadata across domains; optional
70
+ `topics: [onboarding]` links documents by subject. Read the originals for authority,
71
+ status and evidence: discovery is not approval or proof of implementation.
72
+
73
+ Registration happens at `index`/documentation closure, not through a background
74
+ watcher. Existing projects acquire the catalog on their next `index`; `recall`
75
+ also sees live metadata. The KB lens remains the specialist for ingestion and
76
+ taxonomy. Marketing retains its numerical validators. See the skill's `memory.md`.
77
+ Vendoring requires all three files: the entry point, `sdlc_core.py`, `knowledge.py`.
40
78
 
41
79
  ## Installation
42
80
 
@@ -127,6 +165,9 @@ The validator is **three files**: `sdlc_check.py` selects the lens, `sdlc_core.p
127
165
  Installing or updating the npm package wires the session-orientation hook
128
166
  machine-wide (user-level Claude Code settings; removal is a standing opt-out
129
167
  that no update overrides -- ENFORCEMENT.md par.4).
168
+ It also wires, the same way, the per-turn reminder, the guide-verdict check and
169
+ the constraint recall (ENFORCEMENT.md par.3); the recall costs about 0.25 s per
170
+ edit and adds context only at L3 on a bound file.
130
171
 
131
172
  ## The family: four lenses, one spine
132
173
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-sdlc-skill",
3
- "version": "1.48.0",
3
+ "version": "1.50.0",
4
4
  "description": "Documentation-First SDLC protocol with triage, Vision governance and optional devPNT integration.",
5
5
  "author": "Antonio Pinto (https://github.com/Antoneeo)"
6
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antoneeo/agentic-sdlc-skill",
3
- "version": "1.48.0",
3
+ "version": "1.50.0",
4
4
  "description": "Documentation-First SDLC protocol for Claude Code, Gemini CLI, Google Antigravity and Codex with risk triage, Vision governance, installed support files and optional devPNT integration.",
5
5
  "keywords": [
6
6
  "claude-code",
package/scripts/init.js CHANGED
@@ -203,16 +203,16 @@ in the skill's \`routing.md\`: it decides which lens's method and validation rul
203
203
  that unit. L1 never reaches it. Never refer to a document whose meaning differs by lens
204
204
  ("threat model", "vision", \`principles.md\`, \`handoff.md\`) by its bare name.
205
205
 
206
- Select the owning lens by the unit's purpose, then apply only its risk scale.
207
- The project's always-on pointer stays intact: consult the selected skill rather than
208
- merging multiple mandatory ladders. All lenses already carry shared project memory
209
- (\`memory.md\`); another installation is not needed for cross-domain recall.
206
+ Select the owning lens by the unit's purpose, then apply only its risk scale.
207
+ The project's always-on pointer stays intact: consult the selected skill rather than
208
+ merging multiple mandatory ladders. All lenses already carry shared project memory
209
+ (\`memory.md\`); another installation is not needed for cross-domain recall.
210
210
  This file is NOT auto-loaded by any client: it is a note for you, deliberately additive.
211
- Delete this note once the routing pointer is integrated.
211
+ Delete this note once the routing pointer is integrated.
212
212
  `, 'multi-lens routing note');
213
213
  if (wrote && protocolPreexisting) {
214
214
  console.log(' ⚠️ A protocol pointer already existed and was NOT overwritten.');
215
- console.log(' Integrate the routing pointer from AGENTIC_MULTI_LENS.md; keep one risk scale per unit.');
215
+ console.log(' Integrate the routing pointer from AGENTIC_MULTI_LENS.md; keep one risk scale per unit.');
216
216
  }
217
217
  }
218
218
 
package/scripts/lib.js CHANGED
@@ -662,9 +662,11 @@ function removeGlobalHookEntries(removedRoots, spec) {
662
662
 
663
663
  // F-076 generalized the pair below to every constant-command hook this
664
664
  // installer wires: one spec per hook, the remind names kept as wrappers.
665
+ // `name` is what the uninstaller says it removed: two hooks share PreToolUse,
666
+ // so the event cannot name them (F-085).
665
667
  const REMIND_HOOK = {
666
668
  event: 'UserPromptSubmit', sub: 'remind', re: / remind(\s|$)/,
667
- marker: 'remind-hook-wired', timeout: 5,
669
+ marker: 'remind-hook-wired', timeout: 5, name: 'per-turn reminder',
668
670
  };
669
671
  // F-076: the guide-verdict check. `; exit 0` because a validator that cannot
670
672
  // run `verdict` -- missing (npm 7+ may never run the uninstaller) or older than
@@ -673,6 +675,17 @@ const REMIND_HOOK = {
673
675
  const VERDICT_HOOK = {
674
676
  event: 'PreToolUse', sub: 'verdict --hook', suffix: '; exit 0', re: / verdict(\s|$)/,
675
677
  marker: 'verdict-hook-wired', timeout: 10, matcher: 'Edit|Write|MultiEdit|NotebookEdit',
678
+ name: 'guide-verdict check',
679
+ };
680
+ // F-085: the constraint recall -- before an edit of a file its open L3 unit's
681
+ // constraints bind, it adds them to the agent's context. Context only, never a
682
+ // permission decision; `; exit 0` for the same reason as the verdict check.
683
+ // Per-edit cost: the lines, owner-accepted in REQUEST_working_model.md R12 (b);
684
+ // ~0.25 s per edit in every project, owner-accepted in R15.
685
+ const RECALL_HOOK = {
686
+ event: 'PreToolUse', sub: 'constraints --hook', suffix: '; exit 0', re: / constraints(\s|$)/,
687
+ marker: 'recall-hook-wired', timeout: 10, matcher: 'Edit|Write|MultiEdit|NotebookEdit',
688
+ name: 'constraint recall',
676
689
  };
677
690
 
678
691
  function commandHookCommand(spec, python, validator) {
@@ -781,19 +794,20 @@ function wireGlobalCommandHook(spec, options) {
781
794
  }
782
795
  function wireGlobalRemindHook(options) { return wireGlobalCommandHook(REMIND_HOOK, options); }
783
796
  function wireGlobalVerdictHook(options) { return wireGlobalCommandHook(VERDICT_HOOK, options); }
797
+ function wireGlobalRecallHook(options) { return wireGlobalCommandHook(RECALL_HOOK, options); }
784
798
 
785
- // Uninstall twin for the constant-command hooks: one {target, event} per
799
+ // Uninstall twin for the constant-command hooks: one {target, event, name} per
786
800
  // removal, so the uninstaller can say what it removed.
787
801
  function removeGlobalCommandHooks(removedRoots) {
788
802
  const removed = [];
789
- for (const spec of [REMIND_HOOK, VERDICT_HOOK]) {
803
+ for (const spec of [REMIND_HOOK, VERDICT_HOOK, RECALL_HOOK]) {
790
804
  const targets = removeGlobalHookEntries(removedRoots, {
791
805
  event: spec.event,
792
806
  re: spec.re,
793
807
  markerTargets: () => markerTargetsOf(spec),
794
808
  markerRemove: (target) => markerRemoveOf(spec, target),
795
809
  });
796
- for (const target of targets) removed.push({ target, event: spec.event });
810
+ for (const target of targets) removed.push({ target, event: spec.event, name: spec.name });
797
811
  }
798
812
  return removed;
799
813
  }
@@ -812,6 +826,7 @@ module.exports = {
812
826
  wireRemindHookInto,
813
827
  wireGlobalRemindHook,
814
828
  wireGlobalVerdictHook,
829
+ wireGlobalRecallHook,
815
830
  removeGlobalCommandHooks,
816
831
  remindMarkerHas,
817
832
  remindMarkerAdd,
@@ -3,7 +3,8 @@
3
3
  const fs = require('fs');
4
4
  const {
5
5
  SKILL_SOURCE, CLIENTS, clientDetected, skillTarget, copyRecursive,
6
- wireGlobalOrientHook, wireGlobalRemindHook, wireGlobalVerdictHook, detectPython,
6
+ wireGlobalOrientHook, wireGlobalRemindHook, wireGlobalVerdictHook, wireGlobalRecallHook,
7
+ detectPython,
7
8
  } = require('./lib');
8
9
 
9
10
  function installSkill(client) {
@@ -61,6 +62,17 @@ for (const client of CLIENTS) {
61
62
  console.log(` (${rv.target}). Edits wait for the Rule-Zero router verdict in projects`);
62
63
  console.log(' with guides; remove that hook entry to opt out — it will not be re-added.');
63
64
  }
65
+ // F-085: the constraint recall -- before an edit of a file bound by a
66
+ // constraint of the open L3 unit the session works on, the agent gets
67
+ // those constraints in its context. Context only, never a decision;
68
+ // silent everywhere else. Per-edit cost: the lines, owner-accepted in
69
+ // REQUEST_working_model.md R12 (b); ~0.25 s per edit, R15.
70
+ const rc = wireGlobalRecallHook({ client, python: detectPython() });
71
+ if (rc.code === 'wired') {
72
+ console.log('🔗 Constraint recall wired for every project on this machine');
73
+ console.log(` (${rc.target}). In an L3 unit, an edit of a file its constraints bind`);
74
+ console.log(' shows them first; remove that hook entry to opt out — it will not be re-added.');
75
+ }
64
76
  const r = wireGlobalOrientHook({ client, python: detectPython() });
65
77
  if (r.code === 'wired') {
66
78
  console.log('🔗 Session orientation wired for every project on this machine');
@@ -32,14 +32,11 @@ try {
32
32
  // F-076: the per-turn reminder and the guide-verdict check name the same skill
33
33
  // dirs; left behind they exit 2 (Python cannot open the file), which blocks the
34
34
  // prompt or the edit. The verdict entry is also wired `; exit 0`, because npm 7+
35
- // may not run this script at all.
36
- const COMMAND_HOOK_NAMES = {
37
- UserPromptSubmit: 'per-turn reminder',
38
- PreToolUse: 'guide-verdict check',
39
- };
35
+ // may not run this script at all. F-085: the constraint recall shares
36
+ // PreToolUse with the verdict check, so each entry is named by its spec.
40
37
  try {
41
- for (const { target, event } of removeGlobalCommandHooks(CLIENTS.map(skillTarget))) {
42
- console.log(`🧹 Removed the ${COMMAND_HOOK_NAMES[event] || event} hook entry (${target}).`);
38
+ for (const { target, event, name } of removeGlobalCommandHooks(CLIENTS.map(skillTarget))) {
39
+ console.log(`🧹 Removed the ${name || event} hook entry (${target}).`);
43
40
  }
44
41
  } catch (e) { /* never abort an uninstall for a convenience */ }
45
42
 
@@ -54,9 +54,9 @@ Semantics: exit code 2 + message on stderr ⇒ the write is blocked and the mess
54
54
 
55
55
  **Usage warnings:**
56
56
  - The gate is deliberately coarse: applied to all of `src/` it would also block the legitimate L1/L2 tasks foreseen by the Triage. Use it **only on security-critical directories** (`--protected "src/auth;src/crypto"`), where "never without analysis" is the desired policy.
57
- - The paths in `--protected` are prefixes relative to the project root, separated by `;`.
57
+ - The paths in `--protected` are prefixes relative to the root of the project the hook judges (below), separated by `;`. With nested docs roots (a monorepo whose package has its own), that is the nearest one above the edited file: write the prefixes relative to it.
58
58
  - `ai_docs/`, `tests/` and `test/` are always excluded from blocking.
59
- - The hook assumes the working directory is the project root (standard behavior of Claude Code hooks).
59
+ - The hook judges the project, and the docs root, holding the edited file: the session's working directory can move with a `cd`, so it is never the reference. With no docs root above the file, it is the session's own project, as before. `--root <path>` overrides it; `gate --file` resolves the same way, and two docs roots side by side leave the gate silent.
60
60
  - **Hybrid/devPNT projects**: add `--hybrid` to the gate command. Governed designs live in the devPNT DB, so the gate also unlocks when an approved E-TDD shadow (`ai_docs/solutions/SHADOW_*tdd*.md`, exported before implementation — see `hybrid.md` §Shadow discipline) is present. Without the flag the gate would block legitimate governed work. The flag is deliberately explicit: never auto-detected.
61
61
 
62
62
  ### Verdict check: `verdict` (PreToolUse -- wired by default)
@@ -66,13 +66,17 @@ guide it names before acting. A field agent edited without doing either and said
66
66
  had stopped it (F-076). `sdlc_check.py verdict --hook` reads the session transcript
67
67
  Claude Code hands every hook and refuses an Edit, Write, MultiEdit or NotebookEdit when:
68
68
 
69
- - the session shows no line of the agent's own text with `router:` (the verdict) and no
70
- `Level: L1` (or another lens's level 1), or
69
+ - the session shows no line of the agent's own text that opens with `router:` or declares
70
+ the level with it on the same line (`Level: L2 · router: …`, `Level: Spike · router: …`;
71
+ a markdown opener such as `##`, `-`, `•` or `1.` is allowed; inside a sentence it is none), and no
72
+ line that opens with a level-1 declaration (`Level: L1`, or another lens's level 1 such
73
+ as `E1`; a level quoted inside a sentence declares nothing), or
71
74
  - a guide the verdict names, present in `reference/`, never appeared in the input of a
72
75
  tool call other than an edit (Read, Bash `cat`, Grep, a subagent brief all count).
73
76
 
74
77
  A verdict whose text after `router:` begins with `no match` or `absent` names no guide.
75
- The refusal is one line, shown to the agent, saying how to unblock. It is silent — the
78
+ The project judged, and its docs root, are the ones holding the edited file, wherever the
79
+ session's working directory has moved. The refusal is one line, shown to the agent, saying how to unblock. It is silent — the
76
80
  edit proceeds — in a project without guides, for a file outside the project, for a
77
81
  subagent's edit (one the client marks with `agent_id`, or one whose transcript is the
78
82
  subagent's own), and whenever it cannot tell (no or oversized transcript, unknown format,
@@ -84,7 +88,9 @@ Non-Goal on r19's precedent): ~0.2–0.5 s per edit and zero tokens when complia
84
88
  refusal of at most 250 characters and one retry when not. L1 pays nothing beyond writing
85
89
  `Level: L1`, which Rule Zero already asks for. Residuals: edits through a subagent and
86
90
  writes made with Bash are not checked (a subagent's edit the client does not mark is judged
87
- on the orchestrator's verdict); a verdict anywhere earlier in the session counts.
91
+ on the orchestrator's verdict); a verdict anywhere earlier in the session counts; a quote
92
+ that itself opens a line (a blockquote, a backticked form, a line in a code fence) still
93
+ counts as a declaration.
88
94
 
89
95
  Installing the package wires it machine-wide on Claude Code; **removing that hook entry
90
96
  is a standing opt-out.** The command ends in `; exit 0`: a validator that cannot run
@@ -110,6 +116,38 @@ is a standing opt-out.** The command ends in `; exit 0`: a validator that cannot
110
116
  }
111
117
  ```
112
118
 
119
+ ### Constraint recall: `constraints --hook` (PreToolUse -- wired by default)
120
+
121
+ Before an Edit, Write, MultiEdit or NotebookEdit, `sdlc_check.py constraints --hook`
122
+ adds to the agent's context the constraints that bind the file: the UC/FS/T items and
123
+ the `### Preservation constraints` rows of an open L3 unit of the code domain, at most
124
+ 15 lines, then the command for the rest and the sentence naming what the view could not
125
+ extract. It fires only when the session read or wrote that unit's ANALYSIS, request
126
+ record or handoff and the last level it declared (a line opening with the level word)
127
+ is L3; editing the unit's own ANALYSIS with a path a P row binds counts too. The project
128
+ is the one holding the edited file, never the hook's working directory.
129
+
130
+ It informs and never decides: its JSON carries `additionalContext` only, never a
131
+ `permissionDecision`, so the user's permission flow is the one without it. It is silent
132
+ everywhere else and whenever it cannot tell (subagent, oversized or unreadable
133
+ transcript, any error), and always exits 0.
134
+
135
+ Cost: up to 15 lines of context on a bound edit at L3 (owner-accepted,
136
+ `REQUEST_working_model.md` R12 (b)), zero tokens at any other level; and about 0.25 s
137
+ per edit in every project, the hook's own process (owner-accepted, R15). Installing the package wires it machine-wide on
138
+ Claude Code beside the verdict check; **removing that hook entry is a standing
139
+ opt-out.** The command ends in `; exit 0` for the verdict check's reason. To wire it by
140
+ hand, add this entry under `PreToolUse`, in its own group with the verdict check's
141
+ matcher (the installer writes a separate group):
142
+
143
+ ```json
144
+ {
145
+ "type": "command",
146
+ "command": "python \"C:\\Users\\<user>\\.claude\\skills\\agentic-sdlc\\scripts\\sdlc_check.py\" constraints --hook; exit 0",
147
+ "timeout": 10
148
+ }
149
+ ```
150
+
113
151
  ## 4. SessionStart hook (orientation, recommended default)
114
152
 
115
153
  Emits the `ai_docs/` orientation to stdout at session start, in the order an arriving agent needs it: the Rule-Zero triage line, the lens choice when sibling lenses are installed, the guide router (`reference/INDEX.md`, one line per guide), the workstream registry (`audit/handoff.md`, one line per workstream, then the project-wide notes), the reading guide (`README.md`), then pointers to the manifest (`INDEX.md`) and to the full files — so the agent begins already oriented instead of reading them only if it remembers to. The whole output stays under 9,500 characters: Claude Code injects a hook's output up to 10,000 and, above that, only a 2,000-character preview, which is how the router once never reached a session (F-075). A section that does not fit is cut at a line with a pointer to its file, and a note says when one client runs the hook from two settings entries. It is **fail-open**: a missing or unreadable doc is skipped, and it always exits 0 — a broken or empty `ai_docs/` never blocks the session. It is **zero-execution** (it reads and prints, never runs anything).
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: agentic-sdlc
3
- version: 1.48.0
3
+ version: 1.50.0
4
4
  description: Documentation-First SDLC protocol with risk-proportional triage, Vision as a guide, a complete Standalone mode and optional symbiosis with devPNT. Use for features, significant bugs, refactors, audits and documented maintenance.
5
5
  author: Antonio Pinto (https://github.com/Antoneeo)
6
6
  copyright: (c) 2026 Antonio Pinto
@@ -182,7 +182,7 @@ For any L3, run the spec elicitation round in `elicitation.md` BEFORE drafting t
182
182
 
183
183
  **Would a guide be worth writing here?** Ask it while you analyze — this is when you are paying to build the model, and the answer decides whether the next session inherits it or re-derives it. Two questions, one line each in the ANALYSIS `## Guide check` (`validate` notes an L3 that leaves it unanswered): does a CURRENT guide already cover what I am about to touch, and did understanding this force a model of a high-complexity component that none covers (then writing it is a duty, `guides.md` §1)?
184
184
 
185
- **Blast-radius enumeration is an authoring duty, not a review finding.** Before writing the Impact (the list of what changes), for every symbol whose signature you change, thread a new field through, or that has more than one caller: mechanically enumerate EVERY consumer with the best symbol-graph tool your toolchain offers — an LSP/IDE call hierarchy or a find-usages / call-graph capability — with `grep` only as a last-resort fallback, and list the full set in the Impact. Anchor to symbol identity, not line numbers (they rot). This is deterministic and cheap: doing it up-front collapses the review into one pass, instead of the reviewer returning "you missed a consumer" one round at a time. Leaving completeness to the closure review is the myopia failure this whole workflow exists to prevent.
185
+ **Blast-radius enumeration is an authoring duty, not a review finding.** Before writing the Impact (the list of what changes), for every symbol whose signature you change, thread a new field through, or that has more than one caller: mechanically enumerate EVERY consumer with the best symbol-graph tool your toolchain offers — an LSP/IDE call hierarchy or a find-usages / call-graph capability — with `grep` only as a last-resort fallback, and write the full set in the Impact's `### Preservation constraints` table: per symbol, its callers and what must stay true (`templates.md`). Anchor to symbol identity, not line numbers (they rot). This is deterministic and cheap: doing it up-front collapses the review into one pass, instead of the reviewer returning "you missed a consumer" one round at a time. Leaving completeness to the closure review is the myopia failure this whole workflow exists to prevent.
186
186
 
187
187
  **Execute-Before-Specify — behavioural claims about existing code are probed, not read.** Every claim in an L3 design artifact of the form "the code today does X" MUST derive from an executed probe (a small script or assertion harness run against the real system in its real states) before the prose is written, never from reading the source alone. The duty is proportional: it covers the claims the design RESTS on — where a wrong answer changes the design — never every mention of existing code; structural facts (a file exists, a symbol's signature, who calls it) belong to the blast-radius enumeration above, not to a probe. A deliverable that is itself text — doctrine, a schema, a prompt, a reviewer definition — is probed the same way: replay it against the recorded case that motivated it (the incident artifact, the tool-usage transcript, the review that missed the defect), red under the old text, green under the new. The claim the unit exists to make true is probed too: where the owner's words for an outcome (request record, approved north star) name a comparative effect — an agent understands better, a task gets faster — the probe that would show it is built before code, asks the question the outcome names, and is shown red on the baseline; the candidate is measured after. How the author frames the unit (a new capability, a fix) does not exempt it. "No probe is possible" is shown, never declared. And a probe must be able to FAIL: show it red first — negate the condition or the state it asserts — then green against the real system (the RED gesture of `tdd.md`, applied to the experiment); a probe you cannot make fail establishes nothing. Keep the probes as an assertion harness that ships WITH the artifact, in the repo (e.g. `ai_docs/solutions/harness_[feature]/` — a scratchpad dies with the session): the reviewer re-runs assertions instead of re-deriving claims, and every later revision re-verifies them for free. Field measurement (2026-08): eight consecutive design-review FAILs, every finding the class "the design describes intent, not behaviour", converged to a PASS in one round once each behavioural claim was executed first — probed claims held in every subsequent round; read claims failed in every one.
188
188
 
@@ -195,7 +195,7 @@ Standalone L3:
195
195
  - Build the Impact/solution **on** the Vision, the use-cases/user-needs and the Security & Threat Model — read and trace to them first, and state the trace (which actor / use-case / threat / benefit each part serves) so the closure review (`review.md`) can verify conformance. Do not draft the Impact in isolation.
196
196
  - For a feature known to span multiple milestones, also create `ai_docs/vision/features/VISION_[feature].md`; the retroactive case (extract it when the SECOND `ANALYSIS_*` on a theme appears) is in Write Triggers.
197
197
 
198
- **Design review gate — the design is reviewed BEFORE any code (L3).** Close Phase 3 by handing the finished ANALYSIS to an *independent* reviewer: the procedure, the independence ladder, the round cap and the log row are `review.md` §When a review is due, moment 1 — follow it there, it is not restated here. Why the moment exists: the closure review can prove the code matches the design, never that the design was right, and the author is structurally blind to what their own design omitted. In Hybrid the same review runs on the `E-ISP`/`E-TDD`, by the client's agent, and its PASS precedes the proposal to devPNT, where the human reviews — `review.md` §When a review is due owns the order.
198
+ **Design review gate — the design is reviewed BEFORE any code (L3).** Close Phase 3 by handing the finished ANALYSIS to an *independent* reviewer: the procedure, the independence ladder, the round cap and the log row are `review.md` §When a review is due, moment 1 — follow it there, it is not restated here. Why the moment exists: the closure review can prove the code matches the design, never that the design was right, and the author is structurally blind to what their own design omitted. In Hybrid the same review runs on the `E-ISP`/`E-TDD`, by the client's agent, and its PASS precedes the proposal to devPNT, where the human reviews — `review.md` §When a review is due owns the order. In Standalone the final PASS is followed by the owner's approval of the design, asked and recorded before any code (same section).
199
199
 
200
200
  Hybrid L3:
201
201
  - Restore the Master Plan, Action Plan and linked documents.
@@ -206,12 +206,13 @@ Hybrid L3:
206
206
 
207
207
  ### 4. Development and Testing
208
208
 
209
- - Implement only after the documentation gate required by the level. **Flip the ANALYSIS frontmatter `PLANNED` → `IN_PROGRESS` when implementation starts** — that flip is what `gate` and the handoff registry key on, and nothing else performs it.
209
+ - Implement only after the documentation gate required by the level; at L3 it ends with the owner's design approval (`review.md` §When a review is due). **Flip the ANALYSIS frontmatter `PLANNED` → `IN_PROGRESS` when implementation starts** — that flip is what `gate` and the handoff registry key on, and nothing else performs it.
210
210
  - Isolate the work: run an L3 change on its own branch. In Hybrid, prefer a git worktree from the start — a running devPNT server locks `.devpnt/*.db` and blocks in-place branch switches/merges in the primary worktree. A session that may run while another session uses the same checkout works in its **own git worktree**, and never switches branch, stashes, resets or runs `index` in a checkout another session may be using. Parallel work also shares ids: choose a new unit's id **after fetching**, as the first id free on every branch and tag the checkout can see (`check` names a collision while the unit is open).
211
211
  - Modify surgically, consistently with the plan.
212
212
  - Implementation work follows the TDD discipline in `tdd.md` (RED/GREEN/REFACTOR — the L2/L3 default; record the reason when it does not apply).
213
213
  - Before implementing (L2/L3; L1 exempt), **consult the guide router** — the verdict already declared with the triage level (`## Operative Guides`). Re-run the lookup here only if the work has moved to a topic the first one did not cover, and say so if the verdict changes.
214
214
  - If the environment does not allow automated tests, declare the alternative verification and the reason.
215
+ - **Constraint recall (L3).** Where the recall hook is wired (`ENFORCEMENT.md` §3), an edit of a file the open unit's constraints bind shows them first. Without it, run `sdlc_check.py constraints --file <path>` before its first edit of a file in a session.
215
216
  - For bugs (L2/L3), continue the investigation and design-verification method in `debugging.md`; implementation follows the `tdd.md` discipline above.
216
217
  - Circuit breaker: after 3 consecutive runs without progress on the tests, stop, switch to the systematic method in `debugging.md`, and ask for instructions if still stuck. `debugging.md` also covers **chronic fragility** — a component that breaks repeatedly across sessions is a comprehension + complexity signal (write the `source_kind: code` guide AND escalate a refactor), not a fourth patch.
217
218
  - Update the ANALYSIS Diary or the Action Plan when you complete milestones, hit blockers, change decisions, or a session ends with work unfinished.
@@ -226,6 +227,7 @@ Hybrid L3:
226
227
  - If the work was governed by user-provided indications and is reusable, **PROPOSE distilling a guide** (proactive trigger, `guides.md` §1) — a proposal for the user, never a silent write, never from model knowledge.
227
228
  - **Comprehension checkpoint** — the backstop for the Phase-3 question, when the signal only became visible while implementing: did this session force a model of a high-complexity component no CURRENT guide covers? If yes, WRITE the `source_kind: code` guide now (a duty, not a proposal) and say so in the closure. One closure later that model is gone.
228
229
  - Update only the documents actually impacted.
230
+ - **Give the preservation constraints back (L3).** Copy each unreleased P row into the existing `source_kind: code` guide of the component it binds, under `## Preservation constraints`, marked `[source: solutions/ANALYSIS_<name>.md#P<n>]`; the ANALYSIS keeps its table. No guide: the component's Component Map row (`strategic/architecture.md`) names the closed ANALYSIS's table. A P row stops binding only on the owner's own words in the request record: the row stays, its *must stay true* cell prefixed `RELEASED (REQUEST_<name>.md#R<n>)`.
229
231
  - **Update the workstream registry (`audit/handoff.md`)** — mandatory at every L3 closure: DELETE the closed workstream's `audit/HANDOFF_[feature].md` (history lives in git and in the Diary) and re-run `sdlc_check.py index`. Deleting the file *is* removing the row, and no other workstream's file is touched — that is the parallel-safety the registry exists for. Never edit the generated file: `validate` errors when it disagrees with its sources. The session-end rule and the L2 case: Write Triggers.
230
232
  - **Aligned indexes (Poka-Yoke)**: if you created, moved or removed canonical documents (`vision/`, `reference/`, `architecture/`, `functional/`, `strategic/`):
231
233
  - regenerate the manifest with `sdlc_check.py index` (writes `ai_docs/INDEX.md`) — never write it by hand;
@@ -34,11 +34,11 @@ proof that it caused this incident.
34
34
  Do not repeat an invalidated hypothesis unless new evidence reopens it.
35
35
 
36
36
  3. **Test and trace the mechanism.** Reproduce and isolate the smallest faithful
37
- failing case when feasible; bisect inputs, paths or changes when informative.
38
- Skip a reproduction already known to omit the incident's causal conditions;
39
- choose a faithful alternative or disclose the gap. Stop diagnostic checks when
40
- further results cannot change the causal or fix decision; this does not replace
41
- the regression and recovery verification in step 5.
37
+ failing case when feasible; bisect inputs, paths or changes when informative.
38
+ Skip a reproduction already known to omit the incident's causal conditions;
39
+ choose a faithful alternative or disclose the gap. Stop diagnostic checks when
40
+ further results cannot change the causal or fix decision; this does not replace
41
+ the regression and recovery verification in step 5.
42
42
  If the incident is intermittent or inaccessible, use captured traces and
43
43
  targeted diagnostic observations instead of declaring investigation impossible.
44
44
  Add minimal instrumentation when evidence is insufficient. Prefer read-only
@@ -12,7 +12,7 @@
12
12
  var D = null; // documents, loaded on first use
13
13
  var K = null; // knowledge base, loaded on first use
14
14
  var app = document.getElementById("app");
15
- var ORIGINS = ["given", "elicited", "derived", "ruling", "imported"];
15
+ var ORIGINS = ["given", "elicited", "derived", "ruling", "imported", "declared"];
16
16
 
17
17
  // ------------------------------------------------------------- helpers
18
18
 
@@ -483,6 +483,7 @@
483
483
  if (f.statement) marks.push(el("span", { "class": "tag statement", title: t("statement_notice"), text: t("statement_mark") }));
484
484
  if (f.state === "superseded") marks.push(el("span", { "class": "tag replaced", title: t("state_superseded_why"), text: t("state_superseded") }));
485
485
  if (f.state === "contested") marks.push(el("span", { "class": "tag conflict", title: t("state_contested_why"), text: t("state_contested") }));
486
+ if (f.state === "diverges") marks.push(el("span", { "class": "tag conflict", title: t("state_diverges_why"), text: t("state_diverges") }));
486
487
  if (opts && opts.topic) marks.push(link("#/topic/" + encodeURIComponent(f.topic), f.topic, "chip"));
487
488
  return el("li", { "class": "fact" + (f.state === "superseded" ? " replaced" : ""), onclick: function () { location.hash = "#/fact/" + encodeURIComponent(id); } },
488
489
  el("span", { "class": "dot bg-" + oc }),
@@ -597,6 +598,11 @@
597
598
  el("p", { "class": "why-line", text: t("state_contested_why") }),
598
599
  el("ul", { "class": "facts" }, (f.with || []).map(function (s) { return factLine(s, { topic: true }); })));
599
600
  }
601
+ if (f.state === "diverges") {
602
+ parts.push(el("h3", null, el("span", { "class": "tag conflict", text: t("state_diverges") }), " ", t("fact_diverges_from")),
603
+ el("p", { "class": "why-line", text: t("state_diverges_why") }),
604
+ el("ul", { "class": "facts" }, (f.diverges_from || []).map(function (s) { return factLine(s, { topic: true }); })));
605
+ }
600
606
  if (f.grounds) {
601
607
  parts.push(el("h3", { text: t("fact_rests_on") }),
602
608
  el("p", { "class": "why-line", text: t("ground_class_" + f.ground_class) }),
@@ -56,7 +56,9 @@ window.DOCS_SITE_STRINGS = {
56
56
  event_request: "request record",
57
57
  event_note: "note",
58
58
  event_source: "source document received",
59
+ event_sent: "document sent",
59
60
  event_review: "review",
61
+ event_defect: "defect reported after merge",
60
62
  event_decision: "decision record",
61
63
  event_project_note: "project note",
62
64
  event_spike: "exploration outcome",
@@ -231,6 +233,8 @@ window.DOCS_SITE_STRINGS = {
231
233
  origin_ruling_why: "Taken to settle a conflict.",
232
234
  origin_imported: "from another knowledge base",
233
235
  origin_imported_why: "Brought in from another knowledge base, where its own sources are.",
236
+ origin_declared: "declared by this project",
237
+ origin_declared_why: "What this project told a recipient, on the day it was sent: a statement of ours, not a fact about the product.",
234
238
  origin_other: "origin as written: {v}",
235
239
  origin_other_why: "An origin this site does not know.",
236
240
 
@@ -239,6 +243,8 @@ window.DOCS_SITE_STRINGS = {
239
243
  state_superseded_why: "A newer fact takes its place.",
240
244
  state_contested: "in conflict",
241
245
  state_contested_why: "Facts that disagree, not yet settled.",
246
+ state_diverges: "diverges",
247
+ state_diverges_why: "What we declared contradicts what the project decided. It is corrected by a new send, or the decision changes.",
242
248
 
243
249
  statement_mark: "statement",
244
250
  statement_prefix: "[statement] {text}",
@@ -254,6 +260,7 @@ window.DOCS_SITE_STRINGS = {
254
260
  fact_replaced_by: "Replaced by",
255
261
  fact_current_at_end: "Current fact at the end of each chain",
256
262
  fact_in_conflict_with: "In conflict with",
263
+ fact_diverges_from: "Diverges from",
257
264
  fact_rests_on: "What it rests on",
258
265
  fact_untraced: "This part could not be traced.",
259
266
  fact_sources: "Sources",
@@ -266,6 +273,7 @@ window.DOCS_SITE_STRINGS = {
266
273
  fact_unknown: "This fact is not in this knowledge base.",
267
274
 
268
275
  ground_document: "a document",
276
+ ground_declared: "a document this project sent",
269
277
  ground_statement: "a person's statement",
270
278
  ground_decision: "a decision",
271
279
  ground_kb: "another knowledge base",
@@ -273,6 +281,7 @@ window.DOCS_SITE_STRINGS = {
273
281
  ground_class_statement: "Rests, at least in part, on a person's statement.",
274
282
  ground_class_untraceable: "Part of what it rests on could not be traced.",
275
283
  ground_class_imported: "Rests on another knowledge base.",
284
+ ground_class_declared: "Rests on our own declaration to a recipient, not on evidence.",
276
285
  ground_class_documents: "Rests on documents or decisions only.",
277
286
 
278
287
  chain_loop: "The chain of replacements loops back to {id}: it stops here.",
@@ -18,6 +18,7 @@
18
18
  --o-derived: #a99be0;
19
19
  --o-ruling: #7fa7e6;
20
20
  --o-imported: #9cc96b;
21
+ --o-declared: #d98fb0;
21
22
  --conflict: #e0605a;
22
23
  --display: "Iowan Old Style", "Palatino Linotype", Palatino, "Book Antiqua", Charter, Georgia, serif;
23
24
  --body: "Segoe UI Variable Text", "Avenir Next", Avenir, "Gill Sans Nova", "Gill Sans", "Trebuchet MS", sans-serif;
@@ -179,6 +180,7 @@ a.factid code { color: var(--link); }
179
180
  .o-derived { color: var(--o-derived); } .bg-derived { background: var(--o-derived); }
180
181
  .o-ruling { color: var(--o-ruling); } .bg-ruling { background: var(--o-ruling); }
181
182
  .o-imported { color: var(--o-imported); } .bg-imported { background: var(--o-imported); }
183
+ .o-declared { color: var(--o-declared); } .bg-declared { background: var(--o-declared); }
182
184
  .o-other { color: var(--paper-3); } .bg-other { background: var(--paper-3); }
183
185
 
184
186
  .panel {