@antoneeo/kb-agentic-skill 1.31.0 → 1.33.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,69 @@
2
2
 
3
3
  Every significant change to this skill is recorded here.
4
4
 
5
+ ## [1.33.0] - 2026-10-31
6
+
7
+ ### What's new
8
+
9
+ **You approve the design before any drafting.** On significant work, once the independent design review passes, the agent stops and shows you a short summary of the design: what it will produce, for whom, what it touches, the risks and how they are handled, and what the review found. Drafting 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.
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.32.0, published without notes:**
14
+ - **You know what the knowledge base has not read yet.** It tells you how much of the project remains to be examined, and before answering "no information" it checks where the answer could be.
15
+ - **What you told others stays a statement.** What you wrote to a client or a partner does not become a fact about the product. If it contradicts what the knowledge base holds, it is flagged.
16
+ - **Decisions from other projects no longer apply by themselves.** Importing a topic from another project brings the knowledge whole, but the decisions taken there stay pending until one of you approves them.
17
+ - **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.
18
+
19
+ #### What to do
20
+
21
+ **1. Update (everyone).** The changes arrive only with the update.
22
+ 1. Run `npm install -g @antoneeo/kb-agentic-skill@latest`, then `kb-agentic-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/kb-agentic-skill` shows 1.33.0.
26
+
27
+ **2. Approving the design (significant units).**
28
+ - **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 drafting, 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.
29
+ - **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.
30
+ - **To check:** on your next significant unit, the agent stops after the design review and asks you before any drafting starts.
31
+
32
+ **3. Decisions imported from another project (only if you used `import` before 1.32.0).**
33
+ - **This concerns you if** you used the knowledge base's `import` command to bring topics from another project with version 1.31.0 or earlier. If you never did, skip this point.
34
+ - **Why:** the knowledge base leaves open the questions on which sources disagree, and only a reasoned decision of yours closes them. The earlier version brought another project's decisions in already in force. For example, if someone in project A had settled "the right price is 49 €", importing into B made that price the truth in B too, without anyone in B deciding it. The update corrects future imports only; past ones stay as they are.
35
+ - **Steps:** the simplest way is to ask the agent: "convert the imported decisions as described in portability.md §4". Or by hand: delete the imported topic together with the files that came with it, then run `import` again on the same bundle with the new version; you can try it first with `--dry-run`.
36
+ - **To check:** `sdlc_check.py check` is clean; the other project's decisions appear as imported, and the questions they closed are open again. To make one yours, write your own decision with your own reasoning.
37
+
38
+ **4. Protected folders in a repository with several `ai_docs/` (only if you use them; from 1.32.0).**
39
+ - **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.
40
+ - **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.
41
+ - **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/`.
42
+ - **To check:** in a session with no open analysis, ask the agent for a small change to a protected file. It must be refused.
43
+
44
+ ### Changed
45
+ - After the design review's final PASS, an L3 unit stops: the agent presents a short summary of the design and asks the owner whether to proceed; drafting starts only after a yes, recorded in the request record under a label that begins `design approved`. Unattended, the unit is `BLOCKED on the user`; in Hybrid the approval in devPNT counts. The rule is in the shared `review.md`; `SKILL.md` and `templates.md` point at it (F-087).
46
+ - 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).
47
+ - 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.
48
+
49
+ ## [1.32.0] - 2026-10-27
50
+
51
+ ### Added
52
+ - `inventory <path>`: every project file under a path (`.` for all), each with its state against the corpus, compared by content — `INGESTED` (its bytes are a sidecar's digest, wherever it lives, or its `original_path:` with no digest kept), `INGESTED_EARLIER` (the original changed since ingest), `EXCLUDED` (a row of the approved registry `audit/INVENTORY_exclusions.md`; never read), `NOT_EXAMINED` (the default; links, junctions and cloud-only files are never read), and once per built-in skipped directory `SKIPPED`. No totals, no filter by state; it writes nothing (`vision/rulings.md` r37).
53
+ - Orient prints, in a project with a corpus, an upper bound of the project files never examined (`Corpus reach: <= N …`); Topic Recall runs `inventory` on the plausible path before answering `kb: no coverage` and says what it found there. `stale` names an ingested artifact whose local original changed since ingest, until a successor supersedes it.
54
+ - Documents the project sends out: the version sent enters `corpus/given/` with `provenance: DECLARED`, `recipient:` and the send date; its claims are `DECLARED` ("declared to X on D"), never evidence about the product. A declaration that contradicts the ledger is held as `DIVERGES <id>` on the declaration only; the ledger row is untouched. `export` leaves declarations behind and says so; `import` refuses them (r38).
55
+ - `check` (every lens) now refuses a non-DECLARED row citing a sent document in any source position, a DECLARED row without `recipient:`, `SUPERSEDED`/`CONTESTED` across a declaration, a malformed exclusion-registry row, and a `DIVERGES` on a non-DECLARED row or at a missing, DECLARED or superseded target. A GIVEN row on a `provenance: DECLARED` sidecar used to warn; it is now an error. The docs site shows the `declared` origin, the `diverges` state, ground resting on a sent document, and "document sent" in the chronology.
56
+ - `constraints --unit <id>` and `constraints --file <path>` (shared core): the constraints an ANALYSIS states in extractable form, each with its line, ending with the sections they could not extract.
57
+ - `benefit` and the docs site recognize a REVIEW_LOG row with tier `post-merge` (written by the code lens: the owner's report of a wrong behaviour in a merged change): `benefit` keeps it out of every review figure, the docs site shows it as "defect reported after merge". `review.md`: a reviewer derives callers and behaviours before comparing with the constraint view.
58
+ - `guides.md`: a code guide may carry a `## Preservation constraints` section copied from a closed unit; it survives regeneration. Nothing else changes in this lens: `validate` adds no note.
59
+
60
+ ### Fixed
61
+ - `import` now does what `portability.md` §4 promised: a ruling from another project arrives as `prov: IMPORTED` and settles nothing until you ratify it. It used to arrive unchanged as `RULING`, so another project's decision was in force here with `check` clean. Its note arrives as a renamed copy, `corpus/notes/imported_<project>_<name>`, carrying `imported_from:` and `origin: imported`; the note is never edited under its own name, because an inserted line would move the line every locator cites. The rows the ruling superseded and the ruling itself arrive as one `CONTESTED` set. Ratifying is an ordinary ruling: your own note with your own `basis:`, a `RULING` row on it, and the contested rows `SUPERSEDED` by it. `--dry-run` reports the conversions too.
62
+ - `import` refuses, writing nothing and naming the row, a bundle whose conflict sets would arrive incomplete (a pointer resolving to no row, or to a row of this project that does not name it back), a row settled by a ruling the import does not write or by a row held as `IMPORTED`, and a ruling it cannot carry foreign (not on a note cited by line; on a note with no frontmatter or one already naming a foreign origin; superseded both by a ruling and by another row). `portability.md` §3 already listed an incomplete conflict set as a refusal; it is now enforced. §3 no longer lists a dangling `supersedes:` as a refusal: the import never checked it, and `check` reports it after the import.
63
+ - Any bundle note that declares a `basis:` lands as the renamed foreign copy, even when no ruling row travels with it, so a later import of its ruling cannot find it under its own name. A note in UTF-8 with a BOM (Windows editors) converts and keeps its BOM.
64
+ - `check` refuses a `RULING` row on a note that names a foreign origin (`imported_from:`): relabelling an imported row is not ratifying it.
65
+ - A project imported with kb 1.31.0 or earlier holds a foreign ruling as `RULING`: delete the imported topic and its files and import again, or convert it by hand (`portability.md` §4).
66
+ - Guide-verdict check (`verdict --hook`, shared core): 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.
67
+
5
68
  ## [1.31.0] - 2026-10-23
6
69
 
7
70
  ### Changed
package/README.md CHANGED
@@ -1,24 +1,50 @@
1
1
  # KB Agentic Skill for Claude Code, Gemini CLI, Google Antigravity & Codex
2
2
 
3
- ## Shared project memory
3
+ `kb-agentic` turns an AI agent into the keeper of a second brain built **on the documents you supply** — not on what the model remembers. 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
+ The sibling of [`@antoneeo/agentic-sdlc-skill`](https://www.npmjs.com/package/@antoneeo/agentic-sdlc-skill), transplanted from source code to knowledge: same process, one different fidelity discipline.
11
6
 
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`.
7
+ <!-- whats-new:begin -->
8
+ <!-- generated by scripts/whats_new.js from distributions/kb-agentic-skill/CHANGELOG.md: edit the CHANGELOG, then run node scripts/whats_new.js --write -->
9
+ ## What's new in 1.33.0
17
10
 
11
+ **You approve the design before any drafting.** On significant work, once the independent design review passes, the agent stops and shows you a short summary of the design: what it will produce, for whom, what it touches, the risks and how they are handled, and what the review found. Drafting 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.
18
12
 
19
- `kb-agentic` turns an AI agent into the keeper of a second brain built **on the documents you supply** — not on what the model remembers. It supports Claude Code, Codex, Gemini CLI, Google Antigravity 2.0, Cursor/Windsurf-style project instructions, and optional devPNT governance.
13
+ **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.
20
14
 
21
- The sibling of [`@antoneeo/agentic-sdlc-skill`](https://www.npmjs.com/package/@antoneeo/agentic-sdlc-skill), transplanted from source code to knowledge: same process, one different fidelity discipline.
15
+ **From 1.32.0, published without notes:**
16
+ - **You know what the knowledge base has not read yet.** It tells you how much of the project remains to be examined, and before answering "no information" it checks where the answer could be.
17
+ - **What you told others stays a statement.** What you wrote to a client or a partner does not become a fact about the product. If it contradicts what the knowledge base holds, it is flagged.
18
+ - **Decisions from other projects no longer apply by themselves.** Importing a topic from another project brings the knowledge whole, but the decisions taken there stay pending until one of you approves them.
19
+ - **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.
20
+
21
+ #### What to do
22
+
23
+ **1. Update (everyone).** The changes arrive only with the update.
24
+ 1. Run `npm install -g @antoneeo/kb-agentic-skill@latest`, then `kb-agentic-install-skill`.
25
+ 2. Close and reopen your agent sessions: the new version loads only at startup.
26
+
27
+ To check: `npm ls -g @antoneeo/kb-agentic-skill` shows 1.33.0.
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 drafting, 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 drafting starts.
33
+
34
+ **3. Decisions imported from another project (only if you used `import` before 1.32.0).**
35
+ - **This concerns you if** you used the knowledge base's `import` command to bring topics from another project with version 1.31.0 or earlier. If you never did, skip this point.
36
+ - **Why:** the knowledge base leaves open the questions on which sources disagree, and only a reasoned decision of yours closes them. The earlier version brought another project's decisions in already in force. For example, if someone in project A had settled "the right price is 49 €", importing into B made that price the truth in B too, without anyone in B deciding it. The update corrects future imports only; past ones stay as they are.
37
+ - **Steps:** the simplest way is to ask the agent: "convert the imported decisions as described in portability.md §4". Or by hand: delete the imported topic together with the files that came with it, then run `import` again on the same bundle with the new version; you can try it first with `--dry-run`.
38
+ - **To check:** `sdlc_check.py check` is clean; the other project's decisions appear as imported, and the questions they closed are open again. To make one yours, write your own decision with your own reasoning.
39
+
40
+ **4. Protected folders in a repository with several `ai_docs/` (only if you use them; from 1.32.0).**
41
+ - **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.
42
+ - **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.
43
+ - **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/`.
44
+ - **To check:** in a session with no open analysis, ask the agent for a small change to a protected file. It must be refused.
45
+
46
+ Full history: [CHANGELOG](https://github.com/Antoneeo/agentic-sdlc-skill/blob/main/distributions/kb-agentic-skill/CHANGELOG.md)
47
+ <!-- whats-new:end -->
22
48
 
23
49
  ## What it does
24
50
 
@@ -47,17 +73,32 @@ Deliberately absent: any per-node coverage or completion state. `gaps:` says wha
47
73
  ## Key features
48
74
 
49
75
  - **Risk-proportional triage, measured in knowledge and never in files**: one claim row → propagating a fact already settled → a new knowledge unit (a source ingested, a node created or superseded, the hierarchy moved). Carrying one settled fact into eight documents is small; one claim that re-parents a node is not. On a live front, a new source or statement within an open unit's declared scope is an **ingestion step** of that unit — recorded on the ledger at once — while the rewrite of dependent documents, the registry and the full check run once, at a closure the practitioner calls. A **Write Triggers** table maps each knowledge event to exactly one destination.
50
- - **Portable knowledge**: `export` bundles a subgraph together with the bytes its claims cite — a closure, not a selection, because a claim whose source cannot be reopened is model knowledge arriving by another route. `import` merges it into another project **additively**: it never overwrites a node and never deletes, and claims already present are recognised by id rather than by comparing text, since the same artifact cited at the same span mints the same id in every project. Knowledge crosses the project boundary; **authority does not** — an imported ruling arrives as `prov: IMPORTED`, keeps its original `basis:`, and cannot settle a local disagreement until you re-ratify it.
76
+ - **Portable knowledge**: `export` bundles a subgraph together with the bytes its claims cite — a closure, not a selection, because a claim whose source cannot be reopened is model knowledge arriving by another route. `import` merges it into another project **additively**: it never overwrites a node and never deletes, and claims already present are recognised by id rather than by comparing text, since the same artifact cited at the same span mints the same id in every project. Knowledge crosses the project boundary; **authority does not** — an imported ruling arrives as `prov: IMPORTED` on a renamed copy of its note that names its origin, keeps its original `basis:`, and the question it had closed is open again (`CONTESTED`) until you ratify it with a ruling of your own.
51
77
  - **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.
52
78
  - **Vision-guided governance**: Standalone projects use `ai_docs/vision/`; Hybrid projects use devPNT `M-VISION` as the milestone north star. `DRAFT` informs, `APPROVED` binds, promotion is the user's alone. Every Vision, the M-VISION included, is written only after a six-question **owner interview** and your explicit approval of a one- or two-sentence north star in your own words — the agent never writes one alone.
53
- - **Independent review, twice**: the design before it is implemented, the result before it is declared done — fresh-context subagent > one-shot run > a declared self-pass, 3 rounds max, one log line each, and a PASS is invalid on "found nothing".
79
+ - **Independent review, twice**: the design before it is implemented, the result before it is declared done — fresh-context subagent > one-shot run > a declared self-pass, 3 rounds max, one log line each, and a PASS is invalid on "found nothing". After the design review passes, the owner approves the design before any drafting.
54
80
  - **Question discipline**: a real doubt is asked when it emerges, before its answer is written, with the pros and cons of each option; a choice whose pros clearly win is taken with the weighing written next to it. A question is legal only when the agent searched first, names the search with its result, and names the decision it unblocks.
55
81
  - **Verbatim request record**: every L3 starts `audit/requests/REQUEST_[topic].md` before the Vision Gate — the practitioner'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 reviews check owner statements against it.
56
82
  - **Operative guides + agent-global KB**: distil user-provided indications into source-faithful `GUIDE_*.md` (`source_kind: document`) — verbatim snapshot plus hash, so drift is detected mechanically.
57
- - **Mechanical checks**: `check`, `validate`, `index`, `graph`, `corpus`, `claim-id`, `anchor`, `export`, `import`, `adopt` (dry run: document guides on snapshots and what moving them into the corpus involves), `stale` (spine staleness plus `## claims` -- superseded-cited documents, expired `valid` windows, superseded derivation chains), plus the spine's `mark`/`benefit`/`gate`/`plan`/`orient`/`migrate`. `benefit` reports what the review gates have already caught, beside what the doctrine costs to read; it always exits 0 and carries no verdict. The graph and corpus checks verify spans against the stored extraction, recompute every id, refuse cycles and unreachable nodes, and enforce `CONTESTED` symmetry.
83
+ - **Mechanical checks**: `check`, `validate`, `index`, `graph`, `corpus`, `claim-id`, `anchor`, `export`, `import`, `adopt` (dry run: document guides on snapshots and what moving them into the corpus involves), `inventory <path>` (each project file under a path against the corpus: `INGESTED`, `INGESTED_EARLIER`, `EXCLUDED`, `NOT_EXAMINED`, `SKIPPED`; orient prints an upper bound of the files never examined), `stale` (spine staleness plus `## claims` -- superseded-cited documents, expired `valid` windows, superseded derivation chains), plus the spine's `mark`/`benefit`/`gate`/`plan`/`orient`/`migrate`. `benefit` reports what the review gates have already caught, beside what the doctrine costs to read; it always exits 0 and carries no verdict. The graph and corpus checks verify spans against the stored extraction, recompute every id, refuse cycles and unreachable nodes, and enforce `CONTESTED` symmetry.
58
84
  - **Installed support files**: Claude, Codex, Gemini and Google Antigravity receive the full skill folder — `SKILL.md`, `templates.md`, `taxonomy.md`, `distillation.md`, `reconciliation.md`, `guides.md`, `vision.md`, `elicitation.md`, `review.md`, `dispatch.md`, `routing.md`, `ENFORCEMENT.md`, `memory.md`, and the validator's three files, `scripts/sdlc_check.py` + `scripts/sdlc_core.py` + `scripts/knowledge.py` (copy all three) — plus the docs site generator `scripts/docs_site.py` and its page `docs_site/`, and the `LICENSE` and `NOTICE` it ships under.
59
85
  - **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.
60
86
 
87
+ ## Shared project memory
88
+
89
+ All four lenses include project memory by default; install the lens you need,
90
+ not a second skill just for recall. `index` registers guides, decisions and plans
91
+ in the docs root's `memory/INDEX.md`, linking originals without copying them.
92
+ `recall "onboarding"` finds related metadata across domains; optional
93
+ `topics: [onboarding]` links documents by subject. Read the originals for authority,
94
+ status and evidence: discovery is not approval or proof of implementation.
95
+
96
+ Registration happens at `index`/documentation closure, not through a background
97
+ watcher. Existing projects acquire the catalog on their next `index`; `recall`
98
+ also sees live metadata. The KB lens remains the specialist for ingestion and
99
+ taxonomy. Marketing retains its numerical validators. See the skill's `memory.md`.
100
+ Vendoring requires all three files: the entry point, `sdlc_core.py`, `knowledge.py`.
101
+
61
102
  ## Installation
62
103
 
63
104
  ```bash
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kb-agentic-skill",
3
- "version": "1.31.0",
3
+ "version": "1.33.0",
4
4
  "description": "Knowledge-Base & Document-First protocol with risk triage, Vision governance, signal distillation 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/kb-agentic-skill",
3
- "version": "1.31.0",
3
+ "version": "1.33.0",
4
4
  "description": "Knowledge-Base & Document-First protocol for Claude Code, Gemini CLI, Google Antigravity and Codex with risk triage, Vision governance, signal distillation and optional devPNT integration.",
5
5
  "keywords": [
6
6
  "claude-code",
package/scripts/init.js CHANGED
@@ -196,16 +196,16 @@ in the skill's \`routing.md\`: it decides which lens's method and validation rul
196
196
  that unit. L1 never reaches it. Never refer to a document whose meaning differs by lens
197
197
  ("threat model", "vision", \`principles.md\`, \`handoff.md\`) by its bare name.
198
198
 
199
- Select the owning lens by the unit's purpose, then apply only its risk scale.
200
- The project's always-on pointer stays intact: consult the selected skill rather than
201
- merging multiple mandatory ladders. All lenses already carry shared project memory
202
- (\`memory.md\`); another installation is not needed for cross-domain recall.
199
+ Select the owning lens by the unit's purpose, then apply only its risk scale.
200
+ The project's always-on pointer stays intact: consult the selected skill rather than
201
+ merging multiple mandatory ladders. All lenses already carry shared project memory
202
+ (\`memory.md\`); another installation is not needed for cross-domain recall.
203
203
  This file is NOT auto-loaded by any client: it is a note for you, deliberately additive.
204
- Delete this note once the routing pointer is integrated.
204
+ Delete this note once the routing pointer is integrated.
205
205
  `, 'multi-lens routing note');
206
206
  if (wrote && protocolPreexisting) {
207
207
  console.log(' ⚠️ A protocol pointer already existed and was NOT overwritten.');
208
- console.log(' Integrate the routing pointer from AGENTIC_MULTI_LENS.md; keep one risk scale per unit.');
208
+ console.log(' Integrate the routing pointer from AGENTIC_MULTI_LENS.md; keep one risk scale per unit.');
209
209
  }
210
210
  }
211
211
 
@@ -99,15 +99,15 @@ Semantics: exit code 2 + message on stderr ⇒ the write is blocked and the mess
99
99
 
100
100
  **Usage warnings:**
101
101
  - 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.
102
- - The paths in `--protected` are prefixes relative to the project root, separated by `;`.
102
+ - 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.
103
103
  - `ai_docs/`, `tests/` and `test/` are always excluded from blocking.
104
- - The hook assumes the working directory is the project root (standard behavior of Claude Code hooks).
104
+ - 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.
105
105
  - **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 — in this package that clause is the whole statement of the duty; the sibling lenses keep it in their `hybrid.md`, which kb does not have) is present. Without the flag the gate would block legitimate governed work. The flag is deliberately explicit: never auto-detected.
106
106
 
107
107
  ### Verdict check: `verdict` (PreToolUse -- manual for this lens)
108
108
 
109
109
  `sdlc_check.py verdict --hook` refuses an Edit, Write, MultiEdit or NotebookEdit when the
110
- session transcript shows no guide-router verdict (`router: …`, or a level-1 declaration)
110
+ session transcript shows no guide-router verdict (a line that opens with `router: …` or with the level, `Level: L2 · router: …`, `Level: Spike · router: …`; or one that opens with a level-1 declaration)
111
111
  or a guide the verdict names was never read; it is silent in projects without guides and
112
112
  whenever it cannot tell. The code package (`agentic-sdlc`) wires it machine-wide on
113
113
  Claude Code; this package does not. To wire it by hand, add a `PreToolUse` entry with
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: kb-agentic
3
- version: 1.31.0
3
+ version: 1.33.0
4
4
  description: Knowledge-Base & Document-First protocol with risk-proportional triage, Vision as a guide, Signal Distillation, a complete Standalone mode and optional symbiosis with devPNT. Use for user documentation, knowledge extraction, SOPs, research notes, decision logs, knowledge management — and for answering project questions from the claim ledger and topic graph.
5
5
  author: Antonio Pinto (https://github.com/Antoneeo)
6
6
  copyright: (c) 2026 Antonio Pinto
@@ -24,7 +24,7 @@ Support files in the skill directory:
24
24
  - `review.md`: the review discipline — when a review is due, how to request one, how to receive findings, how to review.
25
25
  - `dispatch.md`: opt-in subagent execution of an approved plan, plus the family-wide delegation boundary (what may be delegated at all) — that part applies at any level.
26
26
  - `routing.md`: which lens owns this unit of work. Read ONLY when a sibling lens skill is installed alongside this one; a single-lens install never reads it.
27
- - `scripts/sdlc_check.py` + `scripts/sdlc_core.py`: the mechanical validator for the docs root (`check`, `validate`, `index`, `mark`, `benefit`, `gate`, `plan`, `orient`, `migrate`, and the knowledge overlay: `graph`, `corpus`, `claim-id`, `anchor`, `export`, `import`, `adopt` (dry run of an adoption), `stale` (spine staleness plus `## claims` -- the time cycle's consolidated view), plus `remind` — the opt-in per-turn one-line reminder, ENFORCEMENT §4). Keep the entry point, `scripts/sdlc_core.py` and `scripts/knowledge.py` together; the last supplies common memory and KB integrity.
27
+ - `scripts/sdlc_check.py` + `scripts/sdlc_core.py`: the mechanical validator for the docs root (`check`, `validate`, `index`, `mark`, `benefit`, `gate`, `plan`, `orient`, `migrate`, and the knowledge overlay: `graph`, `corpus`, `claim-id`, `anchor`, `export`, `import`, `adopt` (dry run of an adoption), `inventory <path>` (the project files under a path, each with its state against the corpus), `stale` (spine staleness plus `## claims` -- the time cycle's consolidated view), plus `remind` — the opt-in per-turn one-line reminder, ENFORCEMENT §4). Keep the entry point, `scripts/sdlc_core.py` and `scripts/knowledge.py` together; the last supplies common memory and KB integrity.
28
28
  - `scripts/docs_site.py --root <project> --open` (`--zip <file>` to share): opens in the user's browser a read-only site of what the agent reads; use it to show the project state.
29
29
  It is what users mean by "docs site", "minisito", "documentation site" or "project site": run it, never build a page by hand.
30
30
  - `ENFORCEMENT.md`: optional setup for CI and hooks.
@@ -102,7 +102,9 @@ Triage decides IF documentation is due; this table decides WHICH document each e
102
102
  | `topics/<slug>.md` | A placement verdict creates it (MISSING/INADEQUATE-child, `taxonomy.md`); reconciliation updates its claim rows. One node per topic — a similar-but-distinct concept is a sibling with `related:` + a written distinction, never a merge and never a duplicate. Merged/renamed nodes become tombstones (`status: SUPERSEDED` + `redirect_to:`), never deleted. | 4 |
103
103
  | a KB bundle (`export`) | Knowledge must leave this project. Export is L1 — it writes nothing into the corpus. **Importing one is L3**: a source enters the corpus and nodes are created, and a bundle is external input, so never L1 whatever its size (`portability.md`). | — |
104
104
  | `corpus/given/*` + sidecar | A source arrives: it becomes a content-addressed artifact with a sidecar carrying digest/date/`supersedes:`. A text source is copied verbatim, except that credentials and unneeded personal or confidential data are redacted first (`redacted_at_intake:`). A non-text source yields its stored canonical extraction — copied **beside** the original when that is small enough to keep, or **instead of it** on a large binary corpus, where the original stays where it lives and is recorded as `original_path:`/`original_sha256:` (`distillation.md` §1, which owns this rule) — never copied beside, and no `original_sha256:`, when it was redacted. Never edited after ingest — the digest check on whatever `given/` holds is what enforces it; the one removal is withdrawing an artifact that holds a secret (`distillation.md` §1). | 4 |
105
+ | `corpus/given/*` + sidecar `provenance: DECLARED` | A document leaves the project — to a client, a supplier, another function: the version sent is ingested like any source (redaction included), its sidecar carrying `provenance: DECLARED`, `recipient:` (an organization or role) and `date:` = the day it was sent; its claims are `DECLARED`. A resend is a new artifact that `supersedes:` the earlier one. Drafts, internal working documents and the files a sent document is generated from do not enter (`distillation.md` §1). | 4 |
105
106
  | `corpus/notes/*` | Something is said (`origin: elicited`), synthesised (`derived_from:`), or ruled (`basis:`). A note with none of the three is refused by the validator. | 4 / 5 |
107
+ | `audit/INVENTORY_exclusions.md` | The practitioner approves that some project files never enter the corpus (code, copies, generated files): one row `pattern \| reason \| approved`, written only after the approval, dated that day. `validate`/`check` refuse a malformed row. Read by `inventory`; never a list of what to ingest next (`vision/rulings.md` r37). | 4 |
106
108
  | the day's decisions, at a user-signed closing (the Capture Moment sweep) | Verification that the phase-4 notes/claims exist; NEW `corpus/notes/*` + claim rows only for what the sweep surfaces un-captured. The event is the CLOSING, disjoint from the row above (which fires when something is SAID). | 5 / session end |
107
109
  | `solutions/PLAN_[topic].md` + its ledger | A source too long for one context is ingested: **one task per reading window** (30 pages by default; the plan states the window used), each ending at a declared `extracted_through:`. That ledger is the register the ingestion resumes from across sessions — ingestion never builds a second one (`distillation.md` §3, `templates.md`). | 4 |
108
110
  | `corpus/given/*.meta.md` — `extracted_through:` | Every reading window closes by advancing it (`p=<n>`, `L<n>`, `complete`). Required once any claim cites the artifact: unstated, "I am finished" cannot be falsified, which is how a sampled 200-page manual passes for an ingested one. | 4 |
@@ -141,7 +143,7 @@ Use this mode when `devpnt_*` tools are available and point at the current proje
141
143
  - Run spec elicitation round (`elicitation.md`) before drafting analysis.
142
144
  - Run taxonomy pass (`taxonomy.md`): verify whether topics, categories, or SOPs already exist in `ai_docs/`. Avoid duplication.
143
145
  - Create or update `ai_docs/solutions/ANALYSIS_[topic].md`.
144
- - **Design review gate (end of Phase 3, before any drafting):** the analysis is reviewed by somebody other than its author — a subagent with fresh context, or a declared self-pass when no higher rung is usable — a permission-gated rung is asked about, never silently skipped (`review.md`). Follow `review.md`; log the outcome in `audit/reviews/REVIEW_LOG.md`. A knowledge structure reviewed only by the person who chose it is not reviewed.
146
+ - **Design review gate (end of Phase 3, before any drafting):** the analysis is reviewed by somebody other than its author — a subagent with fresh context, or a declared self-pass when no higher rung is usable — a permission-gated rung is asked about, never silently skipped (`review.md`). Follow `review.md`; log the outcome in `audit/reviews/REVIEW_LOG.md`. A knowledge structure reviewed only by the person who chose it is not reviewed. Then the owner approves the design before any drafting (`review.md` §When a review is due).
145
147
 
146
148
  ### 4. Knowledge Processing & Distillation
147
149
  - **Isolate the work (Branch/worktree hygiene).** Distillation rewrites existing notes — full re-read per `## Revision` — and does it on a branch or a worktree, never directly on the shared corpus, so a half-finished reconciliation is never what the next reader finds. Where a project does not isolate (one shared checkout), that is a departure from this rule, not a second mode: Rule Zero's step save commit and its declared residual apply. 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).
@@ -201,6 +203,14 @@ twin of the guide consult above.
201
203
  - `kb: <slug>[, <slug> …] → node matched, no claims` — surface the node's `gaps:` when
202
204
  it answers the question: "the KB knows it doesn't know" is a first-class answer.
203
205
  - `kb: no coverage` — index read, nothing fits.
206
+ Before declaring `no coverage` or `node matched, no claims`, look where the KB has
207
+ not: run `inventory <path>` on the project paths whose names plausibly hold the
208
+ subject, count its `NOT_EXAMINED` lines, and say it in the verdict —
209
+ `kb: no coverage; not examined under <path>: N` (N = 0 stated), naming the file when
210
+ one plainly holds the subject. When no path plausibly holds it, never run
211
+ `inventory .`: cite orient's bound (`not examined in the project: <= N`). When
212
+ `inventory` fails, the clause says so. A corpus is a subset of the project; a
213
+ verdict that hides the residue certifies a lookup over what was never read.
204
214
  - `kb: index absent — regenerate (sdlc_check.py index)` — the INDEX is missing, not
205
215
  necessarily the graph (nodes routinely exist while the index lags); regenerate and
206
216
  rescan.
@@ -216,7 +226,11 @@ twin of the guide consult above.
216
226
  decision-grounding** — surfaced, never silently cited. Per-provenance stance: GIVEN's
217
227
  source column is already the direct citation; ELICITED/RULING carry the practitioner's
218
228
  own authority; an IMPORTED claim grounding a decision is named as un-re-ratified
219
- foreign authority.
229
+ foreign authority. A **DECLARED** claim is what this project told a recipient: cite it
230
+ as "declared to <recipient> on <date>", never as a fact about the product, and a
231
+ `DIVERGES` row together with the ledger row it diverges from. A DECLARED artifact is
232
+ **not ground** for a product decision — a chain that ends on one rests on our own
233
+ statement: say so and treat the claim as unverified for decision-grounding.
220
234
  - **Citation scope — the row's test is scope, not fidelity.** Before citing a claim in
221
235
  an answer or a document, verify every part of the row belongs to the question: a row
222
236
  can be atomic as provenance and plural as meaning (`distillation.md` §3), and a
@@ -29,6 +29,7 @@ from the corpus, so everything is re-derivable when the rules improve.
29
29
  | a file from the practitioner | `corpus/given/<name>-<hash8>.<ext>` — verbatim, **content-addressed with a raw-byte sha256**; a newer version is a new file whose sidecar says `supersedes: <old>` — never an overwrite |
30
30
  | a non-text original (PDF, docx, xlsx) | its **canonical extraction**: `corpus/given/<name>-<hash8>.txt`, pages separated by form-feed; extractor id, version and normalization recorded in the sidecar. Offsets address THIS file — stored bytes, not a runtime step. The original is copied beside it when it is small enough to be worth keeping; **on a large or binary-heavy corpus the extraction is the artifact and the original stays where it is** (below) |
31
31
  | something the practitioner says | a transcription in `corpus/notes/`, frontmatter `origin: elicited`, dated |
32
+ | a document the project sends out | the version sent, in `corpus/given/` like any source (redacted at intake), sidecar `provenance: DECLARED`, `recipient:` (an organization or role, never a private person's name) and `date:` = the day sent; when the file also lives in the project, `original_path:` names it. Its claims are `DECLARED`: what we said, to whom, when — not facts about the product. A resend `supersedes:` the earlier send; drafts and the files a document is generated from never enter |
32
33
  | an agent synthesis | a note in `corpus/notes/` with `derived_from:` listing its sources — a note with neither `origin:` nor `derived_from:` nor `basis:` is **model knowledge disguised as a source**, and the validator refuses it |
33
34
  | a practitioner ruling | a note with `basis:` (`reconciliation.md`) |
34
35
 
@@ -88,8 +89,13 @@ Say the limit out loud, because a field that looks like a guarantee and is not i
88
89
  than an absent one — and say it **per field**, because the two are not in the same
89
90
  position:
90
91
 
91
- - **`original_sha256` is never checked.** We do not hold the bytes, so nothing can. It
92
- lets a human re-verify by hand and it dates the ingest; it detects nothing on its own.
92
+ - **`original_sha256` is checked only where the original is local.** `stale` and
93
+ `inventory` hash the file `original_path:` resolves to, when it is a local regular
94
+ file, and report an original that changed since ingest (`stale`'s `## claims`, until
95
+ a successor sidecar `supersedes:` this one). `check` never does: it runs on every
96
+ change, and re-reading gigabytes there is not proportional. Elsewhere — a remote, a
97
+ cloud-only file, no path — it detects nothing; it lets a human re-verify by hand and
98
+ it dates the ingest.
93
99
  Same honesty as a guide's `source_hash`, which proves the source is unchanged and
94
100
  never that the guide described it correctly.
95
101
  - **`original_path` IS checked — for resolution only.** "We do not hold it" was never a
@@ -167,10 +173,14 @@ Claims live in the owning topic's `## Claims` table (`templates.md` has the temp
167
173
  `p=<n>@<start>-<end>` (character offsets into page n of the stored extraction),
168
174
  `L<a>-<b>` (line files), `Sheet<s>!<cell>`. The span must exist — the validator opens
169
175
  the file and checks.
170
- - **prov** — `GIVEN | ELICITED | DERIVED | RULING | IMPORTED`. `IMPORTED` is a ruling that came from another project (`portability.md`): it keeps its text and original `basis:`, its note must say `imported_from:`, and it may not supersede a local row until you re-ratify it. Information for whoever resolves a
176
+ - **prov** — `GIVEN | ELICITED | DERIVED | RULING | IMPORTED | DECLARED`. `DECLARED`
177
+ rests only on a document this project sent (its sidecar says so and names the
178
+ `recipient:`), and no other provenance may cite one, in any source position — a
179
+ declaration is never corroboration (`reconciliation.md` §1). `IMPORTED` is a ruling that came from another project (`portability.md`): it keeps its text and original `basis:`, it rests on a renamed copy of its note that says `imported_from:`, `import` reopens the set it had settled, and nothing is settled by it until you ratify it with a ruling of your own. Information for whoever resolves a
171
180
  conflict; never a rank.
172
- - **state** — `OK`, `CONTESTED <id>[,..]`, `SUPERSEDED <id>[,..]` (`reconciliation.md`
173
- owns the transitions; a split bundle names ALL its successors).
181
+ - **state** — `OK`, `CONTESTED <id>[,..]`, `SUPERSEDED <id>[,..]`, and on a DECLARED row
182
+ only `DIVERGES <id>[,..]` (`reconciliation.md` owns the transitions; a split bundle
183
+ names ALL its successors).
174
184
 
175
185
  ## 3. Extraction discipline
176
186
 
@@ -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 {
@@ -262,6 +262,12 @@ in the snapshot, never to your assumption about what the code does.
262
262
  (source-anchored), not an elaborated version of it.
263
263
  - When in doubt about whether something is "supported" by the source, treat it
264
264
  as not covered rather than stretching the marker to fit.
265
+ - **Declared exception: `## Preservation constraints`.** A code guide may carry
266
+ this section, copied at an L3 closure from the ANALYSIS's table (code lens,
267
+ `SKILL.md` Phase 5). The section's marker cites each row it holds as
268
+ `[source: solutions/ANALYSIS_<name>.md#P<n>]` instead of a snapshot anchor: each
269
+ row records what the code must keep doing, as that unit enumerated and probed it,
270
+ not an excerpt of the code.
265
271
 
266
272
  ## 4. Ingestion bound (T9)
267
273
 
@@ -293,5 +299,7 @@ state it explicitly when handing off a newly created guide.
293
299
  closure (docs travel with the code); when you merely READ one, check it against
294
300
  the code before trusting it. Too large to absorb → mark it `SUPERSEDED` rather
295
301
  than leave a confident-wrong map badged CURRENT, which is worse than none.
302
+ - **A regenerated guide keeps `## Preservation constraints` unchanged**: the
303
+ section does not come from the snapshot (§3), so regeneration carries it over.
296
304
  - **Agent-global KB guides** use the same pipeline and validator via
297
305
  `--root ~/.agentic-sdlc`; freshness via the same `stale` engine.