@antoneeo/kb-agentic-skill 1.0.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 +332 -0
- package/README.md +85 -0
- package/gemini-extension.json +6 -0
- package/package.json +50 -0
- package/scripts/init.js +216 -0
- package/scripts/lib.js +152 -0
- package/scripts/postinstall.js +42 -0
- package/scripts/preuninstall.js +17 -0
- package/skills/kb-agentic-skill/ENFORCEMENT.md +123 -0
- package/skills/kb-agentic-skill/SKILL.md +134 -0
- package/skills/kb-agentic-skill/dispatch.md +87 -0
- package/skills/kb-agentic-skill/distillation.md +79 -0
- package/skills/kb-agentic-skill/elicitation.md +131 -0
- package/skills/kb-agentic-skill/guides.md +287 -0
- package/skills/kb-agentic-skill/reconciliation.md +79 -0
- package/skills/kb-agentic-skill/review.md +168 -0
- package/skills/kb-agentic-skill/routing.md +100 -0
- package/skills/kb-agentic-skill/scripts/sdlc_check.py +846 -0
- package/skills/kb-agentic-skill/scripts/sdlc_core.py +1996 -0
- package/skills/kb-agentic-skill/taxonomy.md +80 -0
- package/skills/kb-agentic-skill/templates.md +579 -0
- package/skills/kb-agentic-skill/vision.md +245 -0
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
# Operative Guides — pipeline
|
|
2
|
+
|
|
3
|
+
Support file for `ai_docs/reference/GUIDE_[topic].md`. Read this only when the
|
|
4
|
+
trigger below fires; the template lives in `templates.md`.
|
|
5
|
+
|
|
6
|
+
**The training model (what a guide IS).** A guide TRAINS the agent on a topic
|
|
7
|
+
the user cares about, the way training works for a person: you study the
|
|
8
|
+
material once, you carry a SYNTHESIS in your head, and you go back to the book
|
|
9
|
+
when a task needs detail. Two levels, both produced by this pipeline:
|
|
10
|
+
- **The guide = the synthesis** — compact and dense: core principles, decision
|
|
11
|
+
rules, the map of what exists, where people go wrong. Small enough that a
|
|
12
|
+
reader takes it in WHOLE before acting (that is the "preparation").
|
|
13
|
+
- **The snapshot = the book** (`.sources/`, verbatim) — the details live here,
|
|
14
|
+
reachable on demand.
|
|
15
|
+
- **The fidelity markers are the bridge**: `[source: <snapshot>#anchor]` both
|
|
16
|
+
proves provenance AND tells the reader where in the book the full detail is.
|
|
17
|
+
A guide that restates the source at length is as wrong as a fragmented one:
|
|
18
|
+
completeness is guaranteed by the book level, economy by the synthesis level.
|
|
19
|
+
|
|
20
|
+
**Two source kinds.** A guide's `source_kind` is either `document` (the default —
|
|
21
|
+
distilled from USER-PROVIDED indications; operative, "how to act") or `code`
|
|
22
|
+
(distilled from the project's own code; a comprehension map of a complex component,
|
|
23
|
+
"how it works"). Both are **source-faithful and snapshot-anchored** — the machinery
|
|
24
|
+
below (snapshot, `source_hash`, fidelity markers, router, `stale`) is identical; only
|
|
25
|
+
what is gathered into `.sources/` differs (a handed document vs verbatim code
|
|
26
|
+
excerpts). Where a rule applies to only one kind, it says so.
|
|
27
|
+
|
|
28
|
+
## 0. Consuming a guide (consult before acting)
|
|
29
|
+
|
|
30
|
+
Guides only pay off if they reach the work they govern. **Before operative work,
|
|
31
|
+
proportional to triage** — L1 is exempt; engaged for L2/L3 — ask: *does a guide
|
|
32
|
+
already cover how to do this well?*
|
|
33
|
+
|
|
34
|
+
- **Scan the router, not the guides.** Read the when-to-consult descriptions in
|
|
35
|
+
the guide router `ai_docs/reference/INDEX.md` **and** the agent-KB router
|
|
36
|
+
`~/.agentic-sdlc/ai_docs/reference/INDEX.md` (if present). Match by topic.
|
|
37
|
+
- **On a match, read that guide's synthesis whole** before acting (the snapshot
|
|
38
|
+
stays on demand via the section markers). No match → proceed normally.
|
|
39
|
+
- **Targeted match, never blanket.** Open only the guide whose description fits
|
|
40
|
+
the task — never load every guide, which would reintroduce the exact token
|
|
41
|
+
cost the "point to them" model exists to avoid. The two-level model (compact
|
|
42
|
+
synthesis / verbatim snapshot) already bounds a single guide's cost.
|
|
43
|
+
- **Declare the router verdict.** The lookup result travels with the triage
|
|
44
|
+
level (`SKILL.md` Rule Zero) as one line — `router: no match`, or
|
|
45
|
+
`router: GUIDE_x.md → read`. This is what makes the consult reliable: an
|
|
46
|
+
undeclared lookup is indistinguishable from a skipped one, to the user, to a
|
|
47
|
+
later reviewer, and to you in the next session. Declaring `no match` on a repo
|
|
48
|
+
with no matching guide is the correct, expected output — not noise.
|
|
49
|
+
- **Three legal verdicts, not two.** `GUIDE_x.md → read`, `no match` (the router
|
|
50
|
+
was read; nothing fitted — including a project whose router is an empty stub,
|
|
51
|
+
which is the normal state before the first guide exists), and
|
|
52
|
+
`router: absent (no router file)` for the case where `ai_docs/reference/INDEX.md`
|
|
53
|
+
does not exist at all. That third value exists so the honest answer is always
|
|
54
|
+
available: a required declaration with no truthful value gets faked or dropped,
|
|
55
|
+
and it takes the rest of Rule Zero with it. Regenerate the router
|
|
56
|
+
(`sdlc_check.py index`) when you report `absent`.
|
|
57
|
+
- **Never fake the verdict.** `no match` means the router was read and nothing
|
|
58
|
+
fitted. A verdict that is always `no match` certifies a lookup that did not
|
|
59
|
+
happen and is worse than silence; a verdict listing the catalogue means the
|
|
60
|
+
match was not targeted (T7). Two guides are legitimate only when they cover
|
|
61
|
+
distinct concerns — typically an operative guide plus the comprehension map of
|
|
62
|
+
the component being touched; three is a smell, not a thorough lookup.
|
|
63
|
+
- **Under subagent dispatch** the consult happens at plan-authoring time (the
|
|
64
|
+
orchestrator populates each task's `guides` field); a context-free subagent
|
|
65
|
+
reads the pointers it was handed and does not run its own router lookup. See
|
|
66
|
+
`dispatch.md`.
|
|
67
|
+
|
|
68
|
+
## 1. When to trigger
|
|
69
|
+
|
|
70
|
+
Trigger test is origin + purpose, not content taxonomy (no "is this technical
|
|
71
|
+
enough" judgement call):
|
|
72
|
+
- **Origin**: the user hands you indications to follow — a document to adhere
|
|
73
|
+
to, a pasted policy, "do it this way", a style guide, a runbook.
|
|
74
|
+
- **Purpose**: the material is meant to GOVERN how the agent operates, not
|
|
75
|
+
just inform a one-off answer.
|
|
76
|
+
|
|
77
|
+
Both hold → this is guide material. Either is missing (e.g. the user pastes
|
|
78
|
+
background context with no operative intent, or asks a one-off question) →
|
|
79
|
+
this is not a guide; answer normally, do not create a file.
|
|
80
|
+
|
|
81
|
+
Never manufacture a guide from model knowledge. If the user asks for "a guide
|
|
82
|
+
on X" without handing over source material, ask for the source first — a
|
|
83
|
+
guide with no `distilled_from` is not this pipeline's output.
|
|
84
|
+
|
|
85
|
+
### Proactive trigger (after reusable success)
|
|
86
|
+
|
|
87
|
+
The trigger above is reactive (the user hands material over). It has a proactive
|
|
88
|
+
twin: **after completing work that was governed by user-provided indications and
|
|
89
|
+
is plausibly reusable** — it would prepare a future task — **PROPOSE** distilling
|
|
90
|
+
a guide.
|
|
91
|
+
|
|
92
|
+
- It is a **proposal to the user**, routed into this same pipeline (§2 onward):
|
|
93
|
+
the user confirms topic/scope before any file is written.
|
|
94
|
+
- **Never a silent write, never from model knowledge.** If the work was not
|
|
95
|
+
governed by user-provided material there is nothing to distill — do not invent
|
|
96
|
+
a guide from general knowledge (the `distilled_from` fidelity constraint, §3,
|
|
97
|
+
is absolute). This adds a moment to PROPOSE, not a new writer.
|
|
98
|
+
|
|
99
|
+
### Comprehension trigger (code source, autonomous — a duty, not a proposal)
|
|
100
|
+
|
|
101
|
+
The two triggers above are for `source_kind: document` (the user hands material
|
|
102
|
+
over). There is a third, for `source_kind: code`: while doing L2/L3 work, when you
|
|
103
|
+
recognize that a component / feature / abstraction layer is **high-complexity** and
|
|
104
|
+
no CURRENT guide already covers it, it is your **duty to WRITE a comprehension
|
|
105
|
+
guide** — autonomously, no proposal, no human gate. The next session (or another
|
|
106
|
+
agent) must not have to re-derive the model you just paid to build, and then break
|
|
107
|
+
the component from partial understanding.
|
|
108
|
+
|
|
109
|
+
- **Why autonomous is allowed here** (it is NOT for `document` guides): a
|
|
110
|
+
comprehension guide is **additive, code-anchored and reversible** (git). It changes
|
|
111
|
+
no code, plan or governed artifact — so the skill-wide "propose, never a silent
|
|
112
|
+
write" rule is relaxed for THIS kind only. The anti-hallucination floor still holds:
|
|
113
|
+
§3 fidelity is absolute — every claim traces to a verbatim code excerpt in the
|
|
114
|
+
snapshot, never to your assumption about what the code does.
|
|
115
|
+
- **Recognize "high-complexity" by concrete signals** (any strong combination, not a
|
|
116
|
+
vibe): you had to trace one behavior across several files/modules (summaries were
|
|
117
|
+
not enough); high fan-in / large blast radius (many consumers); non-obvious control
|
|
118
|
+
or data flow (state machine, async/eventing, DI/plugin indirection, metaprogramming,
|
|
119
|
+
cross-cutting invariants); the area was already broken once — or **repeatedly
|
|
120
|
+
across sessions** — from partial understanding (handoff / diary / git shows it);
|
|
121
|
+
the "why" is not reconstructable from a single file.
|
|
122
|
+
- **Guard-rails (autonomous is not unconstrained).** Search first (§2.0 — one CURRENT
|
|
123
|
+
guide per topic, both routers). Honor the fidelity floor (§3). RECOMMEND the
|
|
124
|
+
independent guide-vs-source review (§5) — it matters more here, since no human gated
|
|
125
|
+
creation. Announce the autonomous write in the closure / handoff so it is visible.
|
|
126
|
+
- **When it fires.** As soon as you recognize the signal, during the work. The
|
|
127
|
+
Phase-5 **Comprehension checkpoint** (`SKILL.md` §5) is the backstop that asks the
|
|
128
|
+
question out loud before closure — a safety net for a signal you noticed and did not
|
|
129
|
+
act on, never a licence to defer. Writing it at closure is still far better than not
|
|
130
|
+
writing it: the model you built is complete now and gone next session.
|
|
131
|
+
|
|
132
|
+
## 2. Pipeline
|
|
133
|
+
|
|
134
|
+
0. **Search before creating (DRY — one CURRENT guide per topic).** Before
|
|
135
|
+
proposing anything, read `ai_docs/reference/INDEX.md` and grep
|
|
136
|
+
`reference/GUIDE_*.md` for topic overlap with the new material. Never end
|
|
137
|
+
up with two CURRENT guides on the same topic. Search BOTH routers: project
|
|
138
|
+
`ai_docs/reference/INDEX.md` AND the agent KB router
|
|
139
|
+
`~/.agentic-sdlc/ai_docs/reference/INDEX.md` (if present) — one CURRENT
|
|
140
|
+
guide per topic PER SCOPE; a project guide on a KB topic requires the
|
|
141
|
+
explicit `overrides:` declaration. On overlap, pick by provenance:
|
|
142
|
+
- **Same source, evolved** → UPDATE the existing guide in place: new
|
|
143
|
+
snapshot, new `source_hash`, same file (history lives in git).
|
|
144
|
+
- **Different source replacing the old one** → NEW guide + mark the old
|
|
145
|
+
one `status: SUPERSEDED` (its provenance chain must stay honest — do not
|
|
146
|
+
graft a new source onto a guide distilled from another).
|
|
147
|
+
- **Different source, partial overlap** → flag it to the user explicitly:
|
|
148
|
+
the current frontmatter binds ONE source per guide (`distilled_from`/
|
|
149
|
+
`source_hash` are singular), so a clean multi-source merge is not yet
|
|
150
|
+
supported — regenerate from the prevailing source and mark what the
|
|
151
|
+
merge drops, or keep the topics separate if they truly are.
|
|
152
|
+
Semantic overlap is NOT mechanically detectable: this step is agent
|
|
153
|
+
discipline plus the human reviewing the router — say what you found.
|
|
154
|
+
**Also verify the handed SOURCE itself is current**: check its lifecycle
|
|
155
|
+
(status/supersedes headers) and search the project for a newer version of
|
|
156
|
+
the same document before snapshotting. A user may hand you a path that a
|
|
157
|
+
migrated copy has since superseded — distilling from it produces a guide
|
|
158
|
+
that is born stale. If you find a newer version, surface it and distill
|
|
159
|
+
from that one. (Learned the hard way on first field use, 2026-07-02.)
|
|
160
|
+
1. **Decompose into PREPARATION units — and weigh the fragmentation risk.**
|
|
161
|
+
A guide's goal is to PREPARE an agent for a situation: everything that
|
|
162
|
+
situation needs must arrive in ONE guide. The risk is asymmetric — extra
|
|
163
|
+
context injected costs tokens (cheap, recoverable); missing context makes
|
|
164
|
+
the agent invent or fail (the exact failure this pipeline exists to
|
|
165
|
+
prevent). Every split is a bet that no future task will cross the cut.
|
|
166
|
+
Therefore:
|
|
167
|
+
- **Default = one guide per source/domain.** Split ONLY when the resulting
|
|
168
|
+
guides would be consulted in DISJOINT situations — no plausible task
|
|
169
|
+
needs two of them at once.
|
|
170
|
+
- **Run the split test per proposed fragment and DECLARE it** in the
|
|
171
|
+
proposal: "which tasks consult this fragment, and would any of those
|
|
172
|
+
tasks also need another fragment?" Any overlap → merge, do not split.
|
|
173
|
+
- Heterogeneous sources (unrelated policies handed over together) are the
|
|
174
|
+
legitimate split case; a single coherent document about one subsystem
|
|
175
|
+
almost never is.
|
|
176
|
+
- **Also decide SCOPE per proposed guide**: project-scope
|
|
177
|
+
(`ai_docs/reference/`) or agent-scope (`~/.agentic-sdlc/ai_docs/reference/`,
|
|
178
|
+
governs the agent across ALL projects; origin+purpose test unchanged,
|
|
179
|
+
scope is a LOCATION decision by the user, never a content taxonomy; KB
|
|
180
|
+
created lazily with `.sources/` on the first agent-scope guide).
|
|
181
|
+
2. **User confirms** the topic decomposition — including the fragmentation-risk
|
|
182
|
+
assessment and scope decision — before any file is written. **`source_kind: code`
|
|
183
|
+
skips this gate**: the comprehension guide is written autonomously (§1
|
|
184
|
+
comprehension trigger). Still run the fragmentation/scope judgement yourself — just
|
|
185
|
+
do not block on confirmation.
|
|
186
|
+
3. **Snapshot each source verbatim** into
|
|
187
|
+
`ai_docs/reference/.sources/<slug>-<hash8>.md`:
|
|
188
|
+
- `slug` derives from the topic (lowercase, hyphenated).
|
|
189
|
+
- `hash8` = first 8 hex chars of the snapshot file's own SHA-256 (compute
|
|
190
|
+
the snapshot first, hash it, then name it — the hash is of the file you
|
|
191
|
+
just wrote, not of the original source).
|
|
192
|
+
- The hash is computed over LF-normalized content (CRLF → LF), exactly as
|
|
193
|
+
`sdlc_check.py` does in `sha256_file` — so recorded hashes survive
|
|
194
|
+
checkouts that rewrite line endings (e.g. Windows `core.autocrlf=true`).
|
|
195
|
+
- Recommended for consumer projects: add
|
|
196
|
+
`ai_docs/reference/.sources/** -text` to `.gitattributes` so git never
|
|
197
|
+
rewrites snapshot bytes at all (keeps snapshots byte-verbatim; the
|
|
198
|
+
normalized hash stays stable either way).
|
|
199
|
+
- The snapshot is verbatim: no paraphrasing, no reformatting beyond what is
|
|
200
|
+
needed to save it as markdown.
|
|
201
|
+
- **For `source_kind: code`** the snapshot is the verbatim CODE EXCERPTS the guide
|
|
202
|
+
explains — the specific functions / classes / regions of the real files, each
|
|
203
|
+
labelled with its `path:symbol` (or `path:startLine-endLine`) — assembled into
|
|
204
|
+
the one `.sources/<slug>-<hash8>.md` and hashed identically. Copy the code
|
|
205
|
+
verbatim (no paraphrase); include ONLY the regions the guide covers, not whole
|
|
206
|
+
files, so `stale` tracks the code that matters. `distilled_from` records those
|
|
207
|
+
code paths.
|
|
208
|
+
4. **Source-anchored SYNTHESIS (not restatement).** Select and compress what
|
|
209
|
+
the source says into the operative essence — decision rules, invariants,
|
|
210
|
+
the "where people go wrong" list — and POINT INTO the snapshot for the
|
|
211
|
+
detail (`[source: <snapshot>#anchor]` doubles as the detail-lookup
|
|
212
|
+
pointer: "full checklist → snapshot §7"). Every claim must still trace to
|
|
213
|
+
a specific point in the snapshot; do not extract from memory of the
|
|
214
|
+
conversation — re-read the snapshot while writing each section. Selection
|
|
215
|
+
and compression are allowed and expected; ADDITION is not (that stays
|
|
216
|
+
summarize-and-expand, forbidden). A guide approaching the source's own
|
|
217
|
+
length is a paraphrase, not a synthesis — wrong output.
|
|
218
|
+
5. **Render per template** (`templates.md` → `## ai_docs/reference/GUIDE_[topic].md`):
|
|
219
|
+
frontmatter with `source_kind` (`document` | `code`), `source`, `distilled_from`,
|
|
220
|
+
`source_hash` (the snapshot's SHA-256, matching what you just computed), optional
|
|
221
|
+
`source_version`; body sections chosen from the repertoire (a `code` guide uses the
|
|
222
|
+
comprehension repertoire — how it works / control & data flow / invariants / where
|
|
223
|
+
it breaks), each with a fidelity marker.
|
|
224
|
+
**Write for the two-level read**: the guide (synthesis) is small enough to
|
|
225
|
+
be read WHOLE before acting; the snapshot (book) is where size lives and
|
|
226
|
+
where readers grep/partial-read on demand, following the section markers.
|
|
227
|
+
Use the repertoire's stable, self-describing headings, keep one concern per
|
|
228
|
+
`##` section, and make the frontmatter `description` the "should I open
|
|
229
|
+
this file at all" answer. This is why one synthesis + one book beats
|
|
230
|
+
several fragments: the synthesis guarantees the whole picture, the book
|
|
231
|
+
guarantees the details, the markers connect them.
|
|
232
|
+
6. **Run `sdlc_check.py index`** so both `ai_docs/INDEX.md` and
|
|
233
|
+
`ai_docs/reference/INDEX.md` (the guide router) regenerate.
|
|
234
|
+
|
|
235
|
+
## 3. Fidelity rules (mandatory, the D5 constraint)
|
|
236
|
+
|
|
237
|
+
"The source" below means the SNAPSHOT — a handed document for `source_kind: document`,
|
|
238
|
+
verbatim code excerpts for `source_kind: code`. The constraint is identical for both:
|
|
239
|
+
never from UNVERIFIED knowledge. A code guide's every claim traces to the actual code
|
|
240
|
+
in the snapshot, never to your assumption about what the code does.
|
|
241
|
+
|
|
242
|
+
- Only what the source supports goes in the guide. If the source is silent on
|
|
243
|
+
something a reader might expect, mark the section `[not covered by source]`
|
|
244
|
+
— never fill the gap from general knowledge.
|
|
245
|
+
- Every `##` section body carries exactly one kind of marker: `[source:
|
|
246
|
+
<snapshot>#<anchor-or-line>]` for content traceable to the snapshot, or the
|
|
247
|
+
literal `[not covered by source]` for an acknowledged gap. A section with
|
|
248
|
+
neither is a validator warning.
|
|
249
|
+
- `summarize-and-expand` is forbidden: do not take a short source note and
|
|
250
|
+
"helpfully" expand it into a longer procedure using inferred steps. If the
|
|
251
|
+
source says one sentence, the guide section says that one sentence
|
|
252
|
+
(source-anchored), not an elaborated version of it.
|
|
253
|
+
- When in doubt about whether something is "supported" by the source, treat it
|
|
254
|
+
as not covered rather than stretching the marker to fit.
|
|
255
|
+
|
|
256
|
+
## 4. Ingestion bound (T9)
|
|
257
|
+
|
|
258
|
+
If a source document exceeds roughly 2000 lines, do not silently truncate or
|
|
259
|
+
skim it. Stop and ask the user to either split it into smaller documents or
|
|
260
|
+
select the specific sections relevant to the guide being built. Silent
|
|
261
|
+
truncation produces a guide that looks complete but is missing unreviewed
|
|
262
|
+
material — worse than asking.
|
|
263
|
+
|
|
264
|
+
## 5. Review
|
|
265
|
+
|
|
266
|
+
Before the guide is used operatively for the first time, recommend an
|
|
267
|
+
independent guide-vs-source review (a fresh pass comparing the rendered guide
|
|
268
|
+
against the snapshot, checking every marker) — process control per the
|
|
269
|
+
threat model (P-TM). This is a recommendation to the user, not a hard gate:
|
|
270
|
+
state it explicitly when handing off a newly created guide.
|
|
271
|
+
|
|
272
|
+
## 6. Maintenance
|
|
273
|
+
|
|
274
|
+
- **Source changed**: create a new snapshot (new hash), regenerate the guide
|
|
275
|
+
from it (new `source_hash`), and if the guide is replacing a prior guide
|
|
276
|
+
rather than updating in place, mark the old one `status: SUPERSEDED`.
|
|
277
|
+
- **`stale` flags hash drift**: `sdlc_check.py stale` (also under `--hybrid`)
|
|
278
|
+
compares each guide's recorded `source_hash` against the live snapshot file
|
|
279
|
+
and reports `[stale]` when they diverge — that is the signal to regenerate,
|
|
280
|
+
not a manual freshness check.
|
|
281
|
+
- **`source_kind: code` freshness**: `stale` works unchanged (the code-excerpt
|
|
282
|
+
snapshot drifts when the code changes → regenerate). ADDITIONALLY, when you modify
|
|
283
|
+
the code a comprehension guide describes, refresh that guide in the SAME closure
|
|
284
|
+
(docs travel with the code) — do not wait for `stale` to catch it. A stale
|
|
285
|
+
comprehension guide is a confident-wrong map, worse than none.
|
|
286
|
+
- **Agent-global KB guides** use the same pipeline and validator via
|
|
287
|
+
`--root ~/.agentic-sdlc`; freshness via the same `stale` engine.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Reconciliation — what happens when two claims meet
|
|
2
|
+
|
|
3
|
+
**For whom**: the agent that placed a new claim on a node already holding claims about
|
|
4
|
+
the same subject.
|
|
5
|
+
**Answers**: "is this new, corroborating, refining, coexisting or conflicting — and who
|
|
6
|
+
resolves a conflict".
|
|
7
|
+
**Does not answer**: how claims are extracted (`distillation.md`) or placed
|
|
8
|
+
(`taxonomy.md`).
|
|
9
|
+
|
|
10
|
+
**The principle, owner-set: the machine detects and holds; it never decides.** A
|
|
11
|
+
conflict is resolved only by **new information** — a newer source, or a fact the
|
|
12
|
+
practitioner knows that the corpus lacks. Silence is impossible by construction:
|
|
13
|
+
both sides stay, marked, until information ends the disagreement.
|
|
14
|
+
|
|
15
|
+
## 1. Five outcomes — the agent classifies, the machine verifies
|
|
16
|
+
|
|
17
|
+
Subject-sameness is semantic judgement; no query performs it. Classify:
|
|
18
|
+
|
|
19
|
+
| Outcome | When | Action |
|
|
20
|
+
|---|---|---|
|
|
21
|
+
| **new** | nothing on that subject | insert the row |
|
|
22
|
+
| **corroboration** | same assertion, different source | append the source to the existing row (`;`-separated). **Never a second row.** The id keeps its first source |
|
|
23
|
+
| **refinement** | strictly more precise, not contradictory ("Q1" → "15 March") | new row; the old one becomes `SUPERSEDED <new-id>`, its text intact |
|
|
24
|
+
| **coexistence** | contradictory only if scopes overlapped — and by the half-open rule they do not | both rows stay `OK`. "12k until March" and "15k from March" are two truths, not a conflict |
|
|
25
|
+
| **conflict** | contradictory, scopes overlap | **every** row in the set becomes `CONTESTED` listing all counterparts. Nothing is picked |
|
|
26
|
+
|
|
27
|
+
The machine then verifies (the `graph` check): ids recompute, sources resolve and their
|
|
28
|
+
spans exist, `CONTESTED` is **symmetric** (editing one cell to `OK` fails the check —
|
|
29
|
+
the cheapest laundering), a `CONTESTED` pointer at a `SUPERSEDED` row is an error,
|
|
30
|
+
dangling ids are errors, duplicates are errors.
|
|
31
|
+
|
|
32
|
+
## 2. Resolution — only new information
|
|
33
|
+
|
|
34
|
+
1. **A newer source arrives.** Ingest it normally; re-classify the set with it in view;
|
|
35
|
+
record what supersedes what.
|
|
36
|
+
2. **The practitioner rules.** A ruling is a note in `corpus/notes/` whose mandatory
|
|
37
|
+
`basis:` states **the fact they know that the corpus lacks** ("client confirmed Q3 by
|
|
38
|
+
phone on 30 Jul"; "doc B is an unsigned draft"). The ruling enters the ledger as a
|
|
39
|
+
claim (`prov: RULING`, source = that note), and **every prior member of the set —
|
|
40
|
+
including the one it agrees with — becomes `SUPERSEDED <ruling-id>`**: the ruling row
|
|
41
|
+
is now the assertion, and no row lingers contested against rows that no longer
|
|
42
|
+
contest it.
|
|
43
|
+
|
|
44
|
+
**No basis, no ruling.** A preference is not a fact; the validator refuses a ruling note
|
|
45
|
+
without `basis:` exactly as it refuses a DERIVED note without `derived_from:`. If the
|
|
46
|
+
practitioner knows nothing new, the set stays `CONTESTED` — a legitimate, permanent,
|
|
47
|
+
honest state.
|
|
48
|
+
|
|
49
|
+
**Rulings are challengeable.** A later source that contradicts a ruling opens a **new**
|
|
50
|
+
contested set carrying the ruling's `basis:` beside the new evidence — the practitioner
|
|
51
|
+
decides with both in view. Rule-once-forever would be wrong on this corpus's own
|
|
52
|
+
premise: signed amendments arrive later.
|
|
53
|
+
|
|
54
|
+
## 3. The state machine (claim-level, never node-level)
|
|
55
|
+
|
|
56
|
+
| Event | Effect |
|
|
57
|
+
|---|---|
|
|
58
|
+
| conflict classified | all members → `CONTESTED <all counterparts>` (symmetric by construction) |
|
|
59
|
+
| ruling recorded | ruling row `OK`; every prior member → `SUPERSEDED <ruling-id>` |
|
|
60
|
+
| newer source vs a ruling | new set {new row, ruling row}; escalation shows the `basis:` |
|
|
61
|
+
| member refined | the refining row inherits the member's contested relations (re-judged); counterparts rewritten to the new id |
|
|
62
|
+
| corroboration of a contested member | source appended; the set untouched — more evidence is not new information, and the escalation form shows source counts |
|
|
63
|
+
|
|
64
|
+
## 4. Escalation — batched, and in the legal form only
|
|
65
|
+
|
|
66
|
+
Escalations are presented **once, at the end of a run** — the pipeline never stops
|
|
67
|
+
mid-ingest to ask. Each escalation names: the claims in the set, each one's source
|
|
68
|
+
(reopenable), date and provenance, and one line on why the machine cannot decide
|
|
69
|
+
("same subject, overlapping validity, GIVEN vs GIVEN, no newer source"). **A question
|
|
70
|
+
that cannot fill this form is not askable** — it is the symptom that the answer is in
|
|
71
|
+
the corpus and was not searched. Generic confirmations are not questions.
|
|
72
|
+
|
|
73
|
+
## 5. Document-level supersession (unchanged)
|
|
74
|
+
|
|
75
|
+
Whole documents keep the family lifecycle: a superseding note or guide marks the old one
|
|
76
|
+
`status: SUPERSEDED`; `supersedes:` in the new one's frontmatter links them. Claims and
|
|
77
|
+
documents move independently — superseding a document does not silently resolve the
|
|
78
|
+
claims extracted from it; the `corpus` check reports claims resting on superseded
|
|
79
|
+
originals for re-verification.
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# Review Discipline
|
|
2
|
+
|
|
3
|
+
The single definition of how to request, receive, and perform a review. Other
|
|
4
|
+
places that need review behavior point here instead of restating it (DRY) —
|
|
5
|
+
including devPNT's §4.5/§4.6 gates and any future review step.
|
|
6
|
+
|
|
7
|
+
## When a review is due
|
|
8
|
+
|
|
9
|
+
Two moments, and they review different things:
|
|
10
|
+
|
|
11
|
+
| # | Moment | Object | Level |
|
|
12
|
+
|---|---|---|---|
|
|
13
|
+
| **1. Design review** | End of Phase 3 — **before any implementation** | the ANALYSIS (Standalone) / the `E-ISP`+`E-TDD` (Hybrid) | L3 |
|
|
14
|
+
| **1b. Late arrival** | Work that became L3 *after* code existed — an L1/L2 reclassified mid-flight, or a design increment on a feature already implemented — runs moment 1 **now**, before any further implementation, logged `design (late)` | same | L3 |
|
|
15
|
+
| **2. Closure review** | Phase 5, before DONE | the actual diff, against that approved design | L2 / L3 — the L2 row is optional |
|
|
16
|
+
|
|
17
|
+
**Why the design review is its own moment, and not a nicety.** The closure review
|
|
18
|
+
can only tell you the code matches the design; it cannot tell you the design was
|
|
19
|
+
wrong. An omission in the design — an impacted file nobody listed, a threat with no
|
|
20
|
+
answering requirement, a capability ruled EXISTS on an assumption — is *cheapest*
|
|
21
|
+
to fix before code exists and most expensive after. And the author cannot catch it:
|
|
22
|
+
a self-review runs in the context that produced the omission and is structurally
|
|
23
|
+
blind to it, which is why independence, not effort, is what this gate buys.
|
|
24
|
+
|
|
25
|
+
**Independence, best realization the client supports** — declare which one you used:
|
|
26
|
+
|
|
27
|
+
1. **A fresh subagent** (Claude Code's Task tool, or the equivalent facility) with
|
|
28
|
+
its own context, given the artifacts below and nothing from this conversation.
|
|
29
|
+
2. **A one-shot run of the client itself** (`gemini -p "…"`, `codex exec "…"`) with
|
|
30
|
+
a SELF-CONTAINED prompt — the reviewer session has no other context, which is
|
|
31
|
+
exactly what makes it independent.
|
|
32
|
+
3. **A declared self-pass** — a separate, explicitly adversarial pass by you,
|
|
33
|
+
against the same checklist. **Rung 3 is illegitimate wherever rung 1 or 2
|
|
34
|
+
exists**: on a client with a subagent facility or a one-shot CLI, descending to
|
|
35
|
+
it is choosing zero independence, which is the one thing this gate buys. When
|
|
36
|
+
you do use it, the log row must carry *why* — `self-pass (declared; no subagent
|
|
37
|
+
facility on this client)` — not merely that you did. A rung named without its
|
|
38
|
+
reason is indistinguishable from a rung chosen for convenience.
|
|
39
|
+
|
|
40
|
+
Rung 3 stays in the ladder deliberately: it is what keeps the methodology
|
|
41
|
+
completable with no network, no account and no subagent facility. It is a floor,
|
|
42
|
+
never a default.
|
|
43
|
+
|
|
44
|
+
Use a different model from the author's where the client allows it.
|
|
45
|
+
|
|
46
|
+
**Rounds are capped at 3.** FAIL → revise → re-review. If findings still stand
|
|
47
|
+
after the third, stop and surface them to the user with the artifact — a gate that
|
|
48
|
+
can block forever gets removed. **Log one row per completed review, PASS or FAIL**
|
|
49
|
+
— a FAIL surfaced to the user is the highest-value outcome the gate produces, and
|
|
50
|
+
logging only passes would erase exactly that evidence. The row goes in
|
|
51
|
+
`ai_docs/audit/reviews/REVIEW_LOG.md` (create it if absent — `templates.md`):
|
|
52
|
+
`| date | doc_key | tier | reviewer | findings_raised | findings_real | verdict | revise_rounds |`,
|
|
53
|
+
with `tier` = `design` or `closure` in Standalone. One schema for both modes: a
|
|
54
|
+
Hybrid project's devPNT gates write to the same file.
|
|
55
|
+
The log is how the gate's value is measured over time; skipping it makes the gate
|
|
56
|
+
unfalsifiable, the same defect as an unnamed EXISTS or a faked router verdict.
|
|
57
|
+
|
|
58
|
+
**The reviewer is read-only and advisory.** It never edits, never commits, never
|
|
59
|
+
marks anything DONE, and a PASS is not an approval to merge — the human owns that.
|
|
60
|
+
|
|
61
|
+
## Requesting
|
|
62
|
+
|
|
63
|
+
When you hand work to a reviewer (human or agent), give them:
|
|
64
|
+
|
|
65
|
+
- **Scope**: what changed and why, in one or two lines.
|
|
66
|
+
- **The authoritative design artifact**: the ANALYSIS, E-TDD, or equivalent
|
|
67
|
+
the change was built against — not a paraphrase of it.
|
|
68
|
+
- **The actual diff**: the real changed files, not a description of them. (For a
|
|
69
|
+
**design** review there is no diff yet — that is the point; hand the artifact
|
|
70
|
+
plus the constraints below, and say the object under review is the design.)
|
|
71
|
+
- **For an impact/solution-analysis review, the constraints it derives from**:
|
|
72
|
+
the **Vision**, including its `## Actors` (Hybrid: the `M-VISION`; Standalone:
|
|
73
|
+
`project_vision.md`/`roadmap.md` + the ANALYSIS Vision-Alignment), the
|
|
74
|
+
**use-cases / user-needs** (Hybrid: `D-UC`;
|
|
75
|
+
Standalone: the ANALYSIS `## Use Cases / User Needs`), and the **threat model**
|
|
76
|
+
(Hybrid: `P-TM`; Standalone: the ANALYSIS `## Security and Threat Model`). Hand these
|
|
77
|
+
*in addition to* the design artifact — the reviewer checks the artifact **against**
|
|
78
|
+
them, not only for internal consistency.
|
|
79
|
+
- **For a design review, the threat model too** (same sources as above). Why this
|
|
80
|
+
one and not the whole set: file coverage crosses the impact-analysis→design hop on
|
|
81
|
+
a mechanical gate (every impacted file needs a design block), so a dropped file is
|
|
82
|
+
caught; **threats have no such gate** — a threat answered in the impact analysis
|
|
83
|
+
can silently fail to become a security requirement in the design, and the later
|
|
84
|
+
code review only verifies the requirements that are there, never the ones that
|
|
85
|
+
should have been. The design reviewer checks that every threat surface the change
|
|
86
|
+
touches has a matching security requirement.
|
|
87
|
+
|
|
88
|
+
Never ask a reviewer to "review my session" or "review what I just did"
|
|
89
|
+
without the artifacts above — that forces them to reconstruct scope from
|
|
90
|
+
conversation instead of reviewing the change itself. Say which finding
|
|
91
|
+
classes you want covered (correctness, security, conformance to the design,
|
|
92
|
+
test coverage) if the default scope is not obvious.
|
|
93
|
+
|
|
94
|
+
## Receiving
|
|
95
|
+
|
|
96
|
+
**MUST answer findings one by one — fix, or justify with evidence; why:
|
|
97
|
+
silent drops turn review into theater** — a review whose findings are not
|
|
98
|
+
tracked to a resolution gives the appearance of quality control without its
|
|
99
|
+
substance.
|
|
100
|
+
|
|
101
|
+
If you disagree with a finding, say so explicitly with your reasoning; never
|
|
102
|
+
resolve a disagreement by rewording the finding until it goes away. When the
|
|
103
|
+
project keeps a `REVIEW_LOG` (or equivalent), log the outcome of each
|
|
104
|
+
finding there.
|
|
105
|
+
|
|
106
|
+
## Reviewing
|
|
107
|
+
|
|
108
|
+
When you are the reviewer:
|
|
109
|
+
|
|
110
|
+
- Verify claims against the real source, not against the diff's own
|
|
111
|
+
description of itself.
|
|
112
|
+
- Cite evidence as `file:line` for every finding — a finding without a
|
|
113
|
+
location is not actionable.
|
|
114
|
+
- Keep severity honest: do not inflate a style preference to a blocker, and
|
|
115
|
+
do not soften a real correctness or security issue to a nit.
|
|
116
|
+
- No praise padding. A review reports problems and their fixes, not a
|
|
117
|
+
summary of what looks fine.
|
|
118
|
+
- **Conformance statement (impact/solution-analysis & design reviews only — not a
|
|
119
|
+
plain code-diff review).** When the artifact under review carries Vision / use-case
|
|
120
|
+
/ threat-model constraints, your output MUST map each constraint to its evidence: for
|
|
121
|
+
every use-case/user-need (and the Actor it serves — a use-case with no defined Actor,
|
|
122
|
+
or an Actor UX expectation the solution does not meet, is a finding), every threat, and
|
|
123
|
+
every applicable Vision benefit/Non-Goal, state WHERE the artifact satisfies it (section
|
|
124
|
+
or `file:line`) or raise it as a finding. A PASS/approve is **not valid on "found nothing"** — the conformance
|
|
125
|
+
statement is the proof the check ran; an unfalsifiable "I checked" is the review
|
|
126
|
+
theater this discipline exists to prevent (the reviewer-side twin of §Receiving's
|
|
127
|
+
silent-drop rule). Plain code reviews stay findings-only.
|
|
128
|
+
- **Restated facts (cite, never copy).** Every governance slot has ONE owning document
|
|
129
|
+
per project. A fact restated in the artifact under review when another document owns
|
|
130
|
+
it is a **finding**: the fix is a citation naming the owner, not a better copy. This
|
|
131
|
+
binds the conformance statement too — where a constraint is satisfied by another
|
|
132
|
+
document, name that document as the evidence instead of repeating what it says. Two
|
|
133
|
+
copies of one fact diverge at the first edit, and the reader then has no way to tell
|
|
134
|
+
which one is current. The rule bites hardest across domains, where the same slot
|
|
135
|
+
("threat model", "vision", "handoff") carries a different meaning under each lens and
|
|
136
|
+
a copy looks like an independent second source.
|
|
137
|
+
- **Capability Ledger (same reviews).** **An L3 impact/solution analysis or design
|
|
138
|
+
that carries NO Capability Ledger is itself a finding** — the lens's capability
|
|
139
|
+
pass (`architect.md` in the code lens, `taxonomy.md` in the knowledge lens) left
|
|
140
|
+
no record, and "the artifact does not have one" is what a skipped pass looks like,
|
|
141
|
+
not a reason to skip the check. (This half is load-bearing in Hybrid, where the
|
|
142
|
+
validator backstop reads Standalone ANALYSIS files only and this clause is the
|
|
143
|
+
sole check that the pass ran.) When the ledger is there, map each
|
|
144
|
+
ledger row to where the design or diff realizes it. Three findings live here and
|
|
145
|
+
nowhere else (the capability-pass file named above): a capability ruled MISSING but implemented inside
|
|
146
|
+
the feature's code path, with no component owning it; a component whose contract
|
|
147
|
+
names the feature (a second consumer would force it open); and a capability ruled
|
|
148
|
+
MISSING, not built, and absorbed by quietly reshaping the feature — that is a
|
|
149
|
+
scope change owed to the user, not a design detail. An EXISTS row with no named
|
|
150
|
+
path or symbol is itself a finding. A capability built in this change and absent
|
|
151
|
+
from the `## Component Map` (`strategic/architecture.md`, where the lens keeps one) is a finding too — and
|
|
152
|
+
so is **a component the pass merely DISCOVERED and did not write**, especially
|
|
153
|
+
when the change marks that area ANALYZED: the area now looks read, the map is
|
|
154
|
+
still silent, and the next feature may lawfully rule the capability MISSING and
|
|
155
|
+
build it twice. And a **MISSING row in an area `audit/audit_plan.md` does not
|
|
156
|
+
mark ANALYZED, with no searches named**, is the finding that matters most on a
|
|
157
|
+
project the methodology arrived in recently — an unread map reported as an empty
|
|
158
|
+
one is how a duplicate of the existing codebase gets designed.
|
|
159
|
+
|
|
160
|
+
## Anti-patterns
|
|
161
|
+
|
|
162
|
+
- **Batch-dismissal**: closing out a whole findings list with one blanket
|
|
163
|
+
reply instead of addressing each finding individually.
|
|
164
|
+
- **Rewording instead of addressing**: editing the finding's text to look
|
|
165
|
+
resolved without changing the code or providing evidence it is a
|
|
166
|
+
non-issue.
|
|
167
|
+
- **Scope-creep findings**: raising issues unrelated to the change under
|
|
168
|
+
review instead of filing them separately.
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Domain Routing — which lens owns this unit of work
|
|
2
|
+
|
|
3
|
+
The family ships as sibling skills built from one shared core: each lens carries its
|
|
4
|
+
own **fidelity discipline** (what the work must be faithful to) and its own validation
|
|
5
|
+
rules, over **one** `ai_docs/` tree. This file answers one question: *which lens's
|
|
6
|
+
method governs THIS unit of work?* It does not decide where the resulting file is
|
|
7
|
+
stored (step 5), and it never runs before the triage level is known — L1 never
|
|
8
|
+
reaches it.
|
|
9
|
+
|
|
10
|
+
## 0. Installed-lens detection — run first, fail open
|
|
11
|
+
|
|
12
|
+
Look in the skills directory this skill was loaded from for sibling lenses of the
|
|
13
|
+
family, identified by the `name:` in their `SKILL.md`:
|
|
14
|
+
|
|
15
|
+
| Lens | Skill name | Faithful to |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| code | `agentic-sdlc` | this repository's code |
|
|
18
|
+
| knowledge | `kb-agentic` | documents the user supplied |
|
|
19
|
+
| marketing | `mkt-agentic-sdlc` | market evidence |
|
|
20
|
+
|
|
21
|
+
- **No sibling installed, or the directory cannot be read** → the router does NOT run.
|
|
22
|
+
Work under the loaded lens; read no further. This is the normal single-lens case and
|
|
23
|
+
it costs nothing.
|
|
24
|
+
- **At least one sibling installed** → run the router below, after the level test, on
|
|
25
|
+
every L2, L3 and Spike.
|
|
26
|
+
|
|
27
|
+
Fail-open is deliberate: a detection that cannot answer must never block the work. A
|
|
28
|
+
single-lens project that silently gains a router verdict it cannot act on is worse
|
|
29
|
+
than no verdict at all.
|
|
30
|
+
|
|
31
|
+
## 1. The router
|
|
32
|
+
|
|
33
|
+
Run the steps in order. Stop at the first one that decides.
|
|
34
|
+
|
|
35
|
+
1. **Fidelity / purpose.** What must the work be faithful to?
|
|
36
|
+
- *This repository's code* → provisional **code**; continue to step 2.
|
|
37
|
+
- *Documents the user supplied* → **knowledge**. Decided.
|
|
38
|
+
- *Market evidence* → **marketing**. Decided.
|
|
39
|
+
- *A deliverable whose purpose is market-facing persuasion* (copy, positioning,
|
|
40
|
+
campaign material) → **marketing regardless of source**. Decided. Without this
|
|
41
|
+
branch the marketing lens is reachable only when the *source* is market evidence,
|
|
42
|
+
never when the *purpose* is marketing — and the launch post written from the
|
|
43
|
+
release notes routes to code.
|
|
44
|
+
|
|
45
|
+
2. **Deliverable class** — only on the provisional `code` branch. The predicate is on
|
|
46
|
+
the deliverable, not on its audience:
|
|
47
|
+
- *Part of this repository's own document set, shipping and maintained with the
|
|
48
|
+
code* (`ai_docs/`, README, CHANGELOG, comprehension guides, migration notes) →
|
|
49
|
+
**code**; continue to step 3.
|
|
50
|
+
- *A standalone knowledge deliverable whose fidelity extends beyond this repo's
|
|
51
|
+
code* (user documentation for an external audience, a distilled corpus) →
|
|
52
|
+
**knowledge**. Decided; step 3 is not reached.
|
|
53
|
+
|
|
54
|
+
3. **Build-consumed override** — only on the provisional `code` branch, never
|
|
55
|
+
overriding a *marketing* or *supplied-documents* verdict. *Is the deliverable a
|
|
56
|
+
file the project's build or test toolchain consumes?* Executable or imported
|
|
57
|
+
source: yes. Committed Markdown: no. A yes confirms **code**.
|
|
58
|
+
|
|
59
|
+
4. **Split rule.** A request whose work must be faithful to two sources is **two units
|
|
60
|
+
of work**, split before routing: the distillation (knowledge) and the design that
|
|
61
|
+
cites it (code) each route alone. The router returns one lens per unit; it never
|
|
62
|
+
returns two lenses for one unit.
|
|
63
|
+
|
|
64
|
+
5. **Owning tree.** A straddling artifact keeps its lens for *method* and takes this
|
|
65
|
+
repository's tree and validator for *storage*. Lens and location are separate
|
|
66
|
+
answers — a marketing-lens document written in a code repository still lives in
|
|
67
|
+
that repository's `ai_docs/` and passes that project's validator.
|
|
68
|
+
|
|
69
|
+
6. **Cross-check.** If the verdict contradicts an installed skill's `description`, the
|
|
70
|
+
descriptions are wrong: fix them. Never silently override the test with a
|
|
71
|
+
description.
|
|
72
|
+
|
|
73
|
+
## 2. Worked verdicts
|
|
74
|
+
|
|
75
|
+
| Request | 1 | 2 | 3 | Lens |
|
|
76
|
+
|---|---|---|---|---|
|
|
77
|
+
| "write the API reference docs" (hand-written, ships with the repo) | code | repo's own doc set → code | not build-consumed → no flip | **code** |
|
|
78
|
+
| "write user documentation for our customers' admins" | code | standalone knowledge deliverable → knowledge | n/a (left the code branch at 2) | **knowledge** |
|
|
79
|
+
| "write the API reference docs" (generated — the work edits docstrings in source) | code | repo's own doc set → code | **build-consumed: yes → confirms code** | **code** |
|
|
80
|
+
| "write a comprehension guide for the auth module" | code | repo's own doc set → code | not build-consumed → no flip | **code** |
|
|
81
|
+
| "turn these vendor specs into a technical design" | split (step 4): spec = supplied docs; design = this repo | — | — | **knowledge** for the distillation; **code** for the design, citing it |
|
|
82
|
+
| "write the pricing page copy from our market research" | **purpose: market-facing → marketing** | never reached | never reached | **marketing**; stored in this repo's tree (step 5) |
|
|
83
|
+
| "write the launch blog post from the release notes" | purpose: market-facing → marketing | never reached | never reached | **marketing** |
|
|
84
|
+
|
|
85
|
+
## 3. Acting on the verdict
|
|
86
|
+
|
|
87
|
+
The verdict binds the **method and the validation rules**, not the storage:
|
|
88
|
+
|
|
89
|
+
- **Verdict = the loaded lens** → continue; nothing changes.
|
|
90
|
+
- **Verdict = a sibling lens** → say so, and work that unit under the sibling's method
|
|
91
|
+
and its rule set (its templates, its mandatory risk section — code
|
|
92
|
+
`## Security and Threat Model`, knowledge `## Sources and Verification`, marketing
|
|
93
|
+
`## Threat Map / Plan Risks`). The artifact is written with an explicit
|
|
94
|
+
`domain:` field so the answer survives the session, and it stays in this project's
|
|
95
|
+
`ai_docs/` tree (step 5).
|
|
96
|
+
- **The unit was split** (step 4) → route and declare each half separately.
|
|
97
|
+
|
|
98
|
+
Documents under `vision/` — the project vision, principles, the roadmap — sit **above**
|
|
99
|
+
the domain split: they belong to no lens and are validated by the core's structural
|
|
100
|
+
rules only. The router is not consulted for them.
|