@antoneeo/agentic-sdlc-skill 1.17.0 → 1.20.2
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 +431 -299
- package/README.md +122 -93
- package/gemini-extension.json +6 -6
- package/package.json +4 -1
- package/scripts/init.js +224 -154
- package/scripts/lib.js +177 -168
- package/skills/agentic-sdlc-skill/ENFORCEMENT.md +11 -5
- package/skills/agentic-sdlc-skill/SKILL.md +19 -5
- package/skills/agentic-sdlc-skill/architect.md +215 -0
- package/skills/agentic-sdlc-skill/elicitation.md +124 -8
- package/skills/agentic-sdlc-skill/guides.md +8 -0
- package/skills/agentic-sdlc-skill/review.md +92 -7
- package/skills/agentic-sdlc-skill/routing.md +100 -0
- package/skills/agentic-sdlc-skill/scripts/sdlc_check.py +52 -1100
- package/skills/agentic-sdlc-skill/scripts/sdlc_core.py +1996 -0
- package/skills/agentic-sdlc-skill/templates.md +93 -2
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
# The Architect Pass
|
|
2
|
+
|
|
3
|
+
Applies at L3, in phase 3, AFTER the spec elicitation and BEFORE the Impact is
|
|
4
|
+
drafted. It answers the one question the Impact cannot ask: *does the system
|
|
5
|
+
already have the components and services this feature needs?*
|
|
6
|
+
|
|
7
|
+
Why it exists: **a feature is not a unit of construction.** Left alone, an agent
|
|
8
|
+
designs the feature and builds whatever it lacks inside the feature's own code
|
|
9
|
+
path — so no component owns the capability, the next feature that needs it
|
|
10
|
+
rebuilds it differently, and the platform accretes feature-shaped code nobody can
|
|
11
|
+
reuse. That is myopia one level above the file: the change is complete, the tests
|
|
12
|
+
pass, and the architecture is worse.
|
|
13
|
+
|
|
14
|
+
## 1. State the feature as capabilities, not as files
|
|
15
|
+
|
|
16
|
+
Write what the system must be able to DO for this feature to exist — "persist a
|
|
17
|
+
draft across sessions", "notify a third party asynchronously", "authorize per
|
|
18
|
+
tenant". A capability is a verb over a domain noun. It names no file, no class and
|
|
19
|
+
no library: **that** is the decoupling. Files come later, in the Impact.
|
|
20
|
+
|
|
21
|
+
Two or three capabilities is a normal feature. When the list has one obvious entry
|
|
22
|
+
and it plainly exists, say so in one line **under the `## Capability Ledger`
|
|
23
|
+
heading, still naming the component and where it lives**, and move on — this pass
|
|
24
|
+
is a question to answer, not a form to fill. The heading is what makes a cheap
|
|
25
|
+
answer distinguishable from a skipped pass; a bare "everything already exists"
|
|
26
|
+
names nothing and is the **Paper ledger** anti-pattern, not the licence.
|
|
27
|
+
|
|
28
|
+
## 2. Rule each capability against the platform
|
|
29
|
+
|
|
30
|
+
One verdict per capability:
|
|
31
|
+
|
|
32
|
+
| Verdict | Meaning | What the row must carry |
|
|
33
|
+
|---|---|---|
|
|
34
|
+
| **EXISTS** | a component already owns this capability and covers the need | the component, where it lives (path / symbol), and the one guarantee you re-read it to confirm |
|
|
35
|
+
| **INADEQUATE** | a component owns it but does not cover the need | the same, plus the gap in one line |
|
|
36
|
+
| **MISSING** | no component owns it | the terms you searched, the tool, and the areas covered |
|
|
37
|
+
|
|
38
|
+
Read the **`## Component Map`** in `strategic/architecture.md` first — the project's
|
|
39
|
+
inventory of what owns which capability, kept so this pass does not re-derive the
|
|
40
|
+
platform from source every session.
|
|
41
|
+
|
|
42
|
+
**The map is a cache of evidence somebody already paid for. It lowers the COST of a
|
|
43
|
+
verdict, never the STANDARD of one.** Every verdict carries the same evidence
|
|
44
|
+
whether the map answered it or not; a hit means the search is already written down,
|
|
45
|
+
a miss means you pay full price. Reading a row does not excuse you from checking
|
|
46
|
+
that it is still true — the map is the index, the code is the evidence.
|
|
47
|
+
|
|
48
|
+
**Its silence is unread, not empty.** The map covers only the areas `audit/
|
|
49
|
+
audit_plan.md` marks ANALYZED — and that state is a claim someone made, not a fact
|
|
50
|
+
the tooling verified: marking asserts *the area was read closely enough to name the
|
|
51
|
+
capabilities it owns*, so an area marked after two greps is a false ANALYZED and
|
|
52
|
+
the person who wrote it owns the duplicate that follows. In an area still PENDING —
|
|
53
|
+
or SKIPPED, or absent from the plan entirely — **the map can never ground a MISSING
|
|
54
|
+
verdict.** Nothing there has been looked at yet, and "the inventory does not mention
|
|
55
|
+
it" is the reasoning that builds a second copy of a component that already exists.
|
|
56
|
+
|
|
57
|
+
**Searching for an owner** is text search first, symbol-graph second — in that
|
|
58
|
+
order, because you are looking for a name you do not know yet, and a call-hierarchy
|
|
59
|
+
tool needs a resolved symbol as *input*. Grep the repository (minus SKIPPED areas)
|
|
60
|
+
for the domain noun, at least two plausible synonyms, and the verb; then use the
|
|
61
|
+
symbol-graph tool to confirm or dismiss the candidates the search surfaced.
|
|
62
|
+
|
|
63
|
+
**The floor for a MISSING** is about triage, not term count: every hit that lands in
|
|
64
|
+
an unmapped area gets opened, or the MISSING is **provisional** and says so in its
|
|
65
|
+
row. Record what you ran — terms, tool, areas — and stop when the terms are
|
|
66
|
+
exhausted and no candidate remains unopened. A provisional MISSING is honest and
|
|
67
|
+
cheap; an unfalsifiable one is the same defect as an EXISTS with no symbol named.
|
|
68
|
+
|
|
69
|
+
**Understanding is never deferred; only WRITING the map is.** You may leave the rest
|
|
70
|
+
of the repository unmapped and grow the inventory feature by feature — you may not
|
|
71
|
+
leave unexamined anything this change touches or depends on. That blast zone is
|
|
72
|
+
understood now, at full standard, mapped or not. The incremental licence is about
|
|
73
|
+
the artifact, never about the comprehension.
|
|
74
|
+
|
|
75
|
+
Ground every verdict. An EXISTS with no named symbol is an assumption wearing a
|
|
76
|
+
verdict's clothes, and it is the row that breaks in implementation. A MISSING
|
|
77
|
+
declared without a real search is how duplication enters — the component may be
|
|
78
|
+
there under a name you did not guess. This is the DRY check at architecture level.
|
|
79
|
+
|
|
80
|
+
## 3. Design what is missing as a component, not as feature internals
|
|
81
|
+
|
|
82
|
+
INADEQUATE and MISSING produce design work of their own, governed by one rule:
|
|
83
|
+
|
|
84
|
+
**The component's contract is stated in the component's own vocabulary. The feature
|
|
85
|
+
is one consumer, never the owner.**
|
|
86
|
+
|
|
87
|
+
The test is mechanical: write the contract — what it does, what it takes, what it
|
|
88
|
+
guarantees — *without naming the feature*. If you cannot, the contract is
|
|
89
|
+
feature-shaped, and the second consumer will force it open. **Renaming the
|
|
90
|
+
feature's nouns is not stating the contract in the component's vocabulary**:
|
|
91
|
+
`store(ConfirmationPayload) -> id` described as "stores records by id" still fails.
|
|
92
|
+
The question the wording cannot dodge — *would a second plausible consumer have to
|
|
93
|
+
change this signature?* If yes it is feature-shaped, however it is phrased.
|
|
94
|
+
|
|
95
|
+
The opposite error is equally real: this is not a licence to build a framework.
|
|
96
|
+
Build for the need you have, at the size you need. What the rule constrains is the
|
|
97
|
+
contract's **vocabulary and ownership**, not its scope — a five-line component with
|
|
98
|
+
a clean contract satisfies it in full.
|
|
99
|
+
|
|
100
|
+
## 4. Decide the unit of change
|
|
101
|
+
|
|
102
|
+
A capability that needs building becomes **its own ANALYSIS, its own branch and its
|
|
103
|
+
own closure** when ANY of these holds:
|
|
104
|
+
|
|
105
|
+
- it will have more than one consumer, now or in the declared roadmap;
|
|
106
|
+
- **it can ship before this feature does** — merged and adopted on its own cadence,
|
|
107
|
+
with the feature still unfinished. (Not "buildable and testable on its own": §3
|
|
108
|
+
requires that of every component, so reading it that way makes the default branch
|
|
109
|
+
below unreachable and puts every five-line helper through its own L3.) IN: a
|
|
110
|
+
storage layer another team can adopt next sprint while this feature is still in
|
|
111
|
+
design. OUT: a helper nobody can use until the feature that motivated it lands;
|
|
112
|
+
- it carries its own risk surface: security, a public contract, a data model, or a
|
|
113
|
+
new dependency.
|
|
114
|
+
|
|
115
|
+
Otherwise it is a **phase inside this feature's plan** — the first phase, before the
|
|
116
|
+
feature consumes it — and it is still a component: own contract, own tests, never
|
|
117
|
+
inlined into the feature's code path. **The split rule decides the paperwork; it
|
|
118
|
+
never decides whether the component exists.**
|
|
119
|
+
|
|
120
|
+
When it does become its own unit, each document names the other: the feature's
|
|
121
|
+
ANALYSIS points at the component's, and the component's lists its consumers.
|
|
122
|
+
|
|
123
|
+
## 5. Order
|
|
124
|
+
|
|
125
|
+
The component is designed before the feature that consumes it, and normally built
|
|
126
|
+
and tested before it too. A feature blocked on a capability it does not have is not
|
|
127
|
+
"in progress" — it is a component task wearing a feature's name.
|
|
128
|
+
|
|
129
|
+
## Anti-patterns
|
|
130
|
+
|
|
131
|
+
- **Inlining** — the capability is implemented inside the feature's code path and no
|
|
132
|
+
component owns it. Symptom: the next feature that needs it must copy it or
|
|
133
|
+
refactor yours. This is the failure the pass exists to prevent.
|
|
134
|
+
- **Feature-shaped platform** — the component exists, but its contract speaks the
|
|
135
|
+
feature's vocabulary. Symptom: the second consumer forces a contract change.
|
|
136
|
+
- **Silent degradation** — a capability comes out MISSING, nobody wants to build it,
|
|
137
|
+
so the feature is quietly reshaped around what exists and ships as less than what
|
|
138
|
+
was asked. The reduced benefit must be surfaced to the user as a scope change and
|
|
139
|
+
recorded in the ANALYSIS; absorbing it silently is the Vision-divergence rule
|
|
140
|
+
broken one level down.
|
|
141
|
+
- **Speculative platform** — a general framework built for a single known need.
|
|
142
|
+
- **Paper ledger** — every row EXISTS, nothing named. Unfalsifiable, exactly like a
|
|
143
|
+
review that reports "I checked".
|
|
144
|
+
- **Empty-map MISSING** — ruling a capability MISSING because the Component Map is
|
|
145
|
+
silent about it, in an area nobody has analyzed yet. The map's silence is
|
|
146
|
+
*unread*, not *empty*. On a project the methodology has just arrived in, the map
|
|
147
|
+
is nearly all silence, and this is the anti-pattern that duplicates the existing
|
|
148
|
+
codebase one component at a time.
|
|
149
|
+
|
|
150
|
+
## Where the output is recorded
|
|
151
|
+
|
|
152
|
+
Standalone: the `## Capability Ledger` section of the ANALYSIS (`templates.md`),
|
|
153
|
+
immediately before `## Impact`, which it feeds — every INADEQUATE or MISSING row
|
|
154
|
+
lands there as files to create or change. The closure review maps the ledger row by
|
|
155
|
+
row (`review.md`).
|
|
156
|
+
|
|
157
|
+
**A component that gets built lands in the `## Component Map`** of
|
|
158
|
+
`strategic/architecture.md`, in the same closure — capability owned, contract,
|
|
159
|
+
where it lives. This is the loop that makes the pass repeatable instead of
|
|
160
|
+
per-session: the ledger asks the map what exists, so a component the map never
|
|
161
|
+
learned about is one the next feature rules MISSING and builds a second time. The
|
|
162
|
+
trigger is the component's birth, not a stack change (Write Triggers).
|
|
163
|
+
|
|
164
|
+
**So does a component you merely discovered.** When the pass searches an unmapped
|
|
165
|
+
area and finds an existing owner, write that row too, then `sdlc_check.py mark` the
|
|
166
|
+
area you covered — **in that order, and never the mark without the rows.** Marking
|
|
167
|
+
an area ANALYZED while its owners stay unwritten is the worst of both states: the
|
|
168
|
+
area now looks read, so the map's silence there becomes groundable, and the next
|
|
169
|
+
feature rules MISSING and builds a duplicate — lawfully. What a mark asserts is
|
|
170
|
+
exactly this: *the area was read closely enough to name the capabilities it owns.*
|
|
171
|
+
The map then grows by the feature that needed the knowledge instead of by an
|
|
172
|
+
up-front sweep — the understanding was paid for either way, and this is the step
|
|
173
|
+
that stops the next session paying for it again.
|
|
174
|
+
|
|
175
|
+
Hybrid: the ledger goes in the `E-ISP`, above its Impacted Components map. A
|
|
176
|
+
capability split out as its own unit of change gets its own `E-ISP`/`E-TDD`, and the
|
|
177
|
+
feature's `E-ISP` names it as a dependency.
|
|
178
|
+
|
|
179
|
+
## Mechanical backstops
|
|
180
|
+
|
|
181
|
+
Prose is not enforcement; these are the checks that notice when the pass did not
|
|
182
|
+
run or its output rotted. Both are **advisories** — printed as `[note]`, never
|
|
183
|
+
counted as warnings, and never failing a build, **not even under `--strict`**. That
|
|
184
|
+
is deliberate: the ceremony budget accepted for this pass was a signal, and a
|
|
185
|
+
warning that reddens a pipeline is a gate under another name.
|
|
186
|
+
|
|
187
|
+
- **Skipped pass**: `validate` notes an L3 ANALYSIS started on/after 2026-07-28
|
|
188
|
+
that lacks `## Capability Ledger`. Grandfathered by `start_date` alone —
|
|
189
|
+
analyses born before the pass existed never nag — and deliberately NOT by
|
|
190
|
+
status: closure flips the ANALYSIS to COMPLETED *before* `check` runs, so a
|
|
191
|
+
status filter would silence the backstop at the exact moment the process
|
|
192
|
+
mandates the validator.
|
|
193
|
+
- **Rotting map**: `validate` resolves every path-shaped ref in the Component
|
|
194
|
+
Map's `Where` column — a path that no longer exists, or a `#symbol` no longer
|
|
195
|
+
present as a whole word in the file, is flagged; so is a map whose rows carry
|
|
196
|
+
no checkable path at all, or whose header has no `Where` column (an inert check
|
|
197
|
+
reported as a clean one is the same defect as an unread map reported as empty).
|
|
198
|
+
This is the map's equivalent of the guides' `source_hash`, with the same honest
|
|
199
|
+
limit: it proves the ref resolves, never that the row still describes the
|
|
200
|
+
component correctly.
|
|
201
|
+
- **A mark nobody paid for**: `validate` notes an area the audit plan marks
|
|
202
|
+
ANALYZED that owns no Component Map row. Marking is one cheap command and it is
|
|
203
|
+
what converts the map's silence into a groundable MISSING — so this is the other
|
|
204
|
+
half of the loop, the check that a mark asserted something real.
|
|
205
|
+
- **Adherence** (non-gating, **skill development only** — `evals/` is not shipped
|
|
206
|
+
in the installed package): `architect_rules_before_impact.md` runs the pass
|
|
207
|
+
cold; `unmapped_never_grounds_missing.md` sets the brownfield trap — an existing
|
|
208
|
+
component in a PENDING area, where ruling MISSING from the map's silence is the
|
|
209
|
+
failure.
|
|
210
|
+
|
|
211
|
+
## Below L3
|
|
212
|
+
|
|
213
|
+
L1 and L2 do not run this pass. A capability discovered MISSING during L2 work is
|
|
214
|
+
itself an escalation trigger: stop, reclassify to L3, declare it (Rule Zero). "The
|
|
215
|
+
component was not there" is never a reason to build it inside an L2.
|
|
@@ -1,15 +1,130 @@
|
|
|
1
1
|
# Spec Elicitation
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
`## The question discipline` below governs EVERY question to the user — any
|
|
4
|
+
phase, any level, inside or outside the round. The rest of the file is the spec
|
|
5
|
+
elicitation round: it applies when an L3 request enters phase 3 (Request
|
|
6
|
+
Analysis), BEFORE drafting the ANALYSIS document (Standalone) or the D-UC/E-ISP
|
|
7
|
+
(Hybrid).
|
|
5
8
|
|
|
6
|
-
Skip path: if the spec is already complete — an approved Vision or explicit
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
Skip path: if the spec is already complete — an approved Vision or explicit user
|
|
10
|
+
requirements already answer goal, scope, and constraints, or the remainder is
|
|
11
|
+
derivable from the repo, `ai_docs/` and the conversation — skip the round and add
|
|
12
|
+
a one-line note in the analysis stating why it was skipped and naming the
|
|
13
|
+
sources. Do not run the round as a formality when the answers are already on
|
|
14
|
+
record.
|
|
15
|
+
|
|
16
|
+
Unattended path: when the user is not reachable (a scheduled or autonomous run)
|
|
17
|
+
and the skip path does not answer all six, do not stall and do not invent
|
|
18
|
+
consensus. Write the missing answers as **declared assumptions** in
|
|
19
|
+
`## Objective`, mark the ANALYSIS `BLOCKED on the user`, and stop before
|
|
20
|
+
implementation. An assumption on the record is reviewable; a guess folded
|
|
21
|
+
silently into a design is not.
|
|
22
|
+
|
|
23
|
+
## The question discipline
|
|
24
|
+
|
|
25
|
+
A question to the user spends their attention and stalls the work; the round
|
|
26
|
+
below is the only place the process *plans* that cost. Everywhere, a question is
|
|
27
|
+
legal only when BOTH hold:
|
|
28
|
+
|
|
29
|
+
1. **Searched first, and the search is named — with its result.** The answer is
|
|
30
|
+
not on record and not derivable from the repo, `ai_docs/`, the Vision or the
|
|
31
|
+
conversation — and the question states the terms, tools and areas you searched
|
|
32
|
+
**and what they returned**. Same standard as a router verdict or an
|
|
33
|
+
architect-pass MISSING, and it carries their floors, not only their vocabulary
|
|
34
|
+
(`architect.md`, `guides.md`): a search whose scope does not cover the question
|
|
35
|
+
is not a search; a hit you did not open does not narrow anything; and **never
|
|
36
|
+
fake the search** — "I looked and found nothing" that names no terms and no
|
|
37
|
+
areas is a search not run. A question the repo can answer is a search
|
|
38
|
+
outsourced to the user.
|
|
39
|
+
2. **It names what is blocked.** The question states the specific decision or
|
|
40
|
+
fact that cannot be resolved without the reply — what you will do differently
|
|
41
|
+
depending on the answer. If nothing downstream changes with the answer, there
|
|
42
|
+
is no question.
|
|
43
|
+
|
|
44
|
+
Never legal:
|
|
45
|
+
|
|
46
|
+
- **Generic confirmation** — "shall I proceed?", "is this OK?". The process
|
|
47
|
+
authorizes proceeding; if a real risk motivates the ask, name the risk and the
|
|
48
|
+
fork — that is a blocking question and carries the form below.
|
|
49
|
+
- **Preference-fishing** — asking the user to pick among options that are
|
|
50
|
+
equivalent **in their effect on the benefit** and already decided by the
|
|
51
|
+
project's conventions. Cheapness to undo is NOT the test: nearly everything is
|
|
52
|
+
reversible under version control, and "it is reversible" as a licence to stop
|
|
53
|
+
asking is the silence-side evasion this clause must not fund.
|
|
54
|
+
- **Re-asking the record** — goal, scope or constraints that an APPROVED Vision,
|
|
55
|
+
an earlier reply, or the request itself already states.
|
|
56
|
+
|
|
57
|
+
What questions are FOR — what the user uniquely owns: the benefit, priorities
|
|
58
|
+
between conflicting goods, non-goals, acceptance, and the approvals doctrine
|
|
59
|
+
reserves to them (Vision promotion and amendment, scope changes, proposal
|
|
60
|
+
acceptance, merge decisions). Facts about intent come from the user; facts about
|
|
61
|
+
the system come from search. (The marketing sibling states the same rule as "ask
|
|
62
|
+
only what the user uniquely owns"; this is its code-domain form.)
|
|
63
|
+
|
|
64
|
+
**Precedence, because both halves can fire at once:** this paragraph wins over
|
|
65
|
+
the "never legal" list above it. A choice the user uniquely owns is never
|
|
66
|
+
preference-fishing, however cheap it is to undo; the list reaches choices that
|
|
67
|
+
are *not* theirs.
|
|
68
|
+
|
|
69
|
+
**Default non-blocking.** An unknown on which no fork of the work depends: write
|
|
70
|
+
it as a **declared assumption** in the artifact it touches — the same mechanism
|
|
71
|
+
the unattended path uses — proceed, and present the open points **batched**, with
|
|
72
|
+
the round for spec questions or with the deliverable otherwise, answered by
|
|
73
|
+
exception.
|
|
74
|
+
|
|
75
|
+
This is the path most work takes, so it carries the SAME evidence duty as a
|
|
76
|
+
question, not a lighter one — otherwise "assume it" becomes the way to skip the
|
|
77
|
+
standard. Each declared assumption states **what it is taken from** ("I take X
|
|
78
|
+
from Y" — the same shape the round uses) and **the alternative it excludes**, and
|
|
79
|
+
**every declared assumption reaches the batch**: an assumption nobody is shown is
|
|
80
|
+
not an open point, it is a silent decision. That pairing is what the kb family's
|
|
81
|
+
escalation rule actually does — keep BOTH sides with their sources and surface
|
|
82
|
+
them, never silently pick one — and this branch, not the blocking one, is where
|
|
83
|
+
it structurally belongs. An assumption recorded with its source and its rejected
|
|
84
|
+
alternative is reviewable; one recorded alone is a decision wearing an
|
|
85
|
+
assumption's clothes, and a session stalled on a question that could have been
|
|
86
|
+
an assumption is the waste this section exists to prevent.
|
|
87
|
+
|
|
88
|
+
**Blocking is reserved** for three cases: proceeding under ANY assumption would
|
|
89
|
+
waste the work (the forks diverge at once, and the wrong branch is rework of the
|
|
90
|
+
whole unit); the doctrine reserves the decision to the user (the approvals
|
|
91
|
+
above); or the doctrine itself mandates the stop — and a mandated stop is legal
|
|
92
|
+
by mandate, never re-argued here.
|
|
93
|
+
|
|
94
|
+
**Exactly two mandating files prescribe their own hand-over, and there the form
|
|
95
|
+
below does not apply** (two forms over one moment is the duplicate `review.md`
|
|
96
|
+
§Reviewing forbids): `debugging.md`'s circuit breaker — the minimal reproduction,
|
|
97
|
+
what was ruled out, the current best hypothesis; and `review.md`'s round cap —
|
|
98
|
+
the artifact plus the open findings. That list is closed. **Every other mandated
|
|
99
|
+
stop carries the form**, including one that names only its options and not its
|
|
100
|
+
evidence (`SKILL.md`'s Vision-Gate conflict names the two choices — the evidence
|
|
101
|
+
is still owed, and for a Vision conflict the quoted line IS the substance) and
|
|
102
|
+
one that prescribes nothing (`guides.md`'s guide proposal and its ingestion
|
|
103
|
+
bound). "The file mentions the moment" is not a prescription; only a stated
|
|
104
|
+
hand-over is.
|
|
105
|
+
|
|
106
|
+
A blocking question carries a mandatory form — surface both sides with their
|
|
107
|
+
evidence, never silently pick one:
|
|
108
|
+
|
|
109
|
+
- the fork: the concrete options and what each implies for the work;
|
|
110
|
+
- the evidence: what you searched, read or tried, and what it leaves undecided;
|
|
111
|
+
- why no assumption survives — what work is discarded if you assume and are
|
|
112
|
+
wrong. This is what makes case (a) falsifiable: without it, "this is a fork"
|
|
113
|
+
is an agent's assertion about its own convenience, and case (a) becomes the
|
|
114
|
+
licence for exactly the question this section forbids. Cases (b) and (c) answer
|
|
115
|
+
it by citing the approval or the mandate instead;
|
|
116
|
+
- why it is the user's call — what makes the remainder intent, priority or
|
|
117
|
+
approval rather than a derivable fact;
|
|
118
|
+
- what stays blocked until answered.
|
|
10
119
|
|
|
11
120
|
## The round
|
|
12
121
|
|
|
122
|
+
**Derive before asking.** Answer each of the six from the record first — the
|
|
123
|
+
Vision, `ai_docs/`, the conversation, the code. Ask only the residue, and carry
|
|
124
|
+
the derived answers into the round as declared assumptions corrected by
|
|
125
|
+
exception ("I take X from Y; the questions below are what no source answers"),
|
|
126
|
+
not re-confirmed one by one.
|
|
127
|
+
|
|
13
128
|
Ask ONE structured set of questions, not a drip of follow-ups. Keep each
|
|
14
129
|
question short and numbered; offer concrete options where a real choice
|
|
15
130
|
exists (this narrows the reply and speeds up the round). Cover:
|
|
@@ -46,8 +161,9 @@ run a second round to double-check answers that were already clear.
|
|
|
46
161
|
|
|
47
162
|
- **Interrogation**: an endless list of questions, or drip-feeding one
|
|
48
163
|
question at a time across many turns instead of one structured round.
|
|
49
|
-
- **Asking what the approved vision already answers**: re-asking goal or
|
|
50
|
-
non-goals that a `Status: APPROVED` Vision or M-VISION already states.
|
|
51
164
|
- **Collecting answers without folding them in**: getting replies in chat
|
|
52
165
|
and proceeding to design without writing them into the analysis document —
|
|
53
166
|
the next reader has no record of why the scope is what it is.
|
|
167
|
+
|
|
168
|
+
(The illegal question forms — generic confirmation, preference-fishing,
|
|
169
|
+
re-asking the record — are defined once, in `## The question discipline`.)
|
|
@@ -46,6 +46,14 @@ already cover how to do this well?*
|
|
|
46
46
|
undeclared lookup is indistinguishable from a skipped one, to the user, to a
|
|
47
47
|
later reviewer, and to you in the next session. Declaring `no match` on a repo
|
|
48
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`.
|
|
49
57
|
- **Never fake the verdict.** `no match` means the router was read and nothing
|
|
50
58
|
fitted. A verdict that is always `no match` certifies a lookup that did not
|
|
51
59
|
happen and is worse than silence; a verdict listing the catalogue means the
|
|
@@ -1,10 +1,62 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Review Discipline
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
and any future review step
|
|
6
|
-
|
|
7
|
-
|
|
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.
|
|
8
60
|
|
|
9
61
|
## Requesting
|
|
10
62
|
|
|
@@ -13,7 +65,9 @@ When you hand work to a reviewer (human or agent), give them:
|
|
|
13
65
|
- **Scope**: what changed and why, in one or two lines.
|
|
14
66
|
- **The authoritative design artifact**: the ANALYSIS, E-TDD, or equivalent
|
|
15
67
|
the change was built against — not a paraphrase of it.
|
|
16
|
-
- **The actual diff**: the real changed files, not a description of them.
|
|
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.)
|
|
17
71
|
- **For an impact/solution-analysis review, the constraints it derives from**:
|
|
18
72
|
the **Vision**, including its `## Actors` (Hybrid: the `M-VISION`; Standalone:
|
|
19
73
|
`project_vision.md`/`roadmap.md` + the ANALYSIS Vision-Alignment), the
|
|
@@ -71,6 +125,37 @@ When you are the reviewer:
|
|
|
71
125
|
statement is the proof the check ran; an unfalsifiable "I checked" is the review
|
|
72
126
|
theater this discipline exists to prevent (the reviewer-side twin of §Receiving's
|
|
73
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.
|
|
74
159
|
|
|
75
160
|
## Anti-patterns
|
|
76
161
|
|
|
@@ -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.
|