@antoneeo/agentic-sdlc-skill 1.15.0 → 1.19.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,61 @@
2
2
 
3
3
  Tutte le modifiche significative a questa skill saranno documentate in questo file.
4
4
 
5
+ ## [1.19.0] - 2026-07-28 (Design Review Gate)
6
+ ### Added
7
+ - **The design is reviewed before the code exists (F-021).** In Standalone the ANALYSIS was reviewed only as an *input* to the closure review — that is, after implementation. The Vision's Goal 3 names two moments ("make divergence visible **before** implementation, and again before merge"); only the second was implemented. Hybrid had the first (devPNT §4.5 on `E-ISP`/`E-TDD`); Standalone had nothing. Now `review.md` carries **`## When a review is due`** with both moments — **1. design** (end of Phase 3, before any implementation, L3) and **2. closure** (Phase 5, the diff against that design, L2/L3) — plus **1b. late arrival**, for work that became L3 after code existed (an L1/L2 reclassified mid-flight): run moment 1 now, before any further implementation, logged `design (late)`. The reason the moment is its own gate: *the closure review can prove the code matches the design, never that the design was right* — and the author cannot catch what their own design omitted, which is why the gate buys **independence, not effort**. A three-rung ladder makes that concrete on any client: a fresh subagent, a one-shot CLI run (`gemini -p`, `codex exec`) with a self-contained prompt, or — **only where neither exists** — a declared self-pass whose log row must carry *why* the higher rungs were unavailable. Rung 3 stays deliberately: it is what keeps the methodology completable with no network, no account and no subagent facility. Rounds capped at 3, then the findings go to the user; one row per completed review, **PASS or FAIL**, in `ai_docs/audit/reviews/REVIEW_LOG.md` — one schema for both modes, since devPNT's gates write to the same file. New advisory in `sdlc_check.py` (`design_review_due` + `review_logged`) notices an L3 in implementation with no design row: epoch-grandfathered, PLANNED-exempt (the review is due at the *end* of Phase 3, so a design still being drafted is not late), suppressed under `--hybrid` where devPNT owns the slot, and advisory-only as always.
8
+ - **Evidence this was needed, from this repository's own log.** `REVIEW_LOG.md` now records the seven independent reviews run during F-020 — **every one at closure**, 72 findings raised, **72 real**, none rejected as noise, and none caught by the author's self-review beforehand. The two rows that opened the sequence were design defects found after the design had already been implemented.
9
+
10
+ - **Then the closure review ran on the diff and found the cost statement wrong again.** The design review had already forced "3 items → 6"; the closure review measured item 6 and found **255 words** of always-loaded `SKILL.md`, not the restated "~90" — the count had included the Phase-3 paragraph and silently omitted the Write-Triggers row and three ownership-matrix rows, which an agent loads just as unconditionally. Under the Vision's *"Omission resolves against the proposal"* that voids the acceptance, so it was restated from `git diff | wc -w` and re-accepted (Antonio Pinto, 2026-07-28). Twice on one feature the disclosure was written from what felt like the change rather than from what was measured; the acceptance history is kept in the ANALYSIS because the pattern is more instructive than the number. **The hybrid fix also had zero test coverage** — the reviewer proved it by mutation, reverting each of the three `hybrid` forwarding lines and then deleting the advisory outright, all four shipping green; `test_design_review_advisory_end_to_end` now exercises `cmd_validate`/`cmd_check` end to end and all four mutations are caught (re-run to confirm, not assumed). `review_logged` read the `tier` column positionally, so a log with one extra leading column produced a permanent, unclearable false "you skipped the review" — the column is now found by its header — and it matched the ANALYSIS filename as a bare substring, so `ANALYSIS_vision_clarity` would have satisfied `ANALYSIS_vision`'s gate (word-boundary now). `SKILL.md`'s Write-Triggers row still restated three things `review.md` owns and **had already drifted on one of them** in the very commit that fixed the DRY violation; reduced to a pointer. And the eight log rows this release appended carried no `## Notes` — the mechanism it shipped to answer "what did it find" — now written. **Left as a true positive:** `validate` on this repository flags `ANALYSIS_architect_pass.md` as an L3 with no design-review row, because F-020's seven reviews were all at closure — precisely the gap this feature closes. The flagship repo ships with one honest advisory rather than a back-dated row. Battery 75/75.
11
+
12
+ ### Changed
13
+ - **The gate ran on its own design and returned FAIL — 3 BLOCK, before shipping.** (1) The independence ladder had an escape hatch: rung 3 was selectable at the agent's discretion with no duty to justify descending to it, so the cheapest path through the gate delivered zero independence while satisfying every word of the doctrine. (2) The declared ceremony cost was **three items of six** — the `conformance_statement`, the reviewer input packet and the per-finding disposition duty were all mandatory and undisclosed; under the Vision's "Omission resolves against the proposal" the recorded acceptance was void, so the cost was restated in full and re-accepted. (3) `cmd_check` never passed `hybrid` to `cmd_validate`, and devPNT's log rows are keyed on `e_isp_`/`e_tdd_` doc_keys, so the new advisory fired **permanently and unfixably on Hybrid projects** — the exact "worst outcome" the feature's own threat model names. Warnings fixed in the same pass: the log row is written on FAIL too (the highest-value review there is); the moment is read from the `tier` column, since matching "design" anywhere in a row let a *closure* row saying "conformance to the design" satisfy the check — **and the invariant asserting otherwise was vacuous**, its fixture merely omitted the word; `SKILL.md` restated `review.md` wholesale against `review.md`'s own DRY rule, and the two copies had already drifted in the same release that created the second one, so Phase 3 is now trigger-plus-pointer; the REVIEW_LOG template gained the `## Notes` section that "what did it find" requires; and mode is declared **per unit of change**, not per project. Battery 74/74.
14
+
15
+ ## [1.18.0] - 2026-07-28 (Architect Pass)
16
+ ### Added
17
+ - **`architect.md` — the architect pass: capabilities before files (F-020).** Phase 3 went from the spec elicitation straight to the **Impact** (the list of files that change). Nothing in between asked *what the system must be able to do* and *whether a component already does it* — so the agent designed the feature and built whatever it lacked **inside the feature's own code path**: no component owned the new capability, the next feature that needed it rebuilt it differently, and the platform accreted feature-shaped code nobody could reuse. Myopia one level above the file: the change is complete, the tests pass, and the architecture is worse. The pass runs at L3 between elicitation and the Impact, in three moves: **(1)** state the feature as required **capabilities** — verbs over domain nouns, naming no file, no class, no library (that is the decoupling); **(2)** rule each one against the platform — **EXISTS** (name the component and where it lives), **INADEQUATE** (same, plus the gap), **MISSING** (say what you searched: a MISSING declared without a real search is how duplication enters, the architecture-level DRY check); **(3)** design what is missing as a component whose **contract is stated in its own vocabulary, with the feature as one consumer, never the owner** — the test is mechanical, write the contract without naming the feature, and if you cannot, it is feature-shaped and the second consumer will force it open. Guarded on both sides: it is not a licence to build a framework (the rule constrains the contract's vocabulary and ownership, not its scope), and it is a question rather than a form (when every capability plainly exists, one line answers it). **Split rule** (§4): a capability becomes its own ANALYSIS/branch/closure when it will have more than one consumer, is independently mergeable and testable, or carries its own risk surface (security, public contract, data model, new dependency) — otherwise it is the first phase of this feature's plan, still with its own contract and its own tests, never inlined. The split rule decides the paperwork; it never decides whether the component exists. Five anti-patterns are named so a review can catch them: **inlining**, **feature-shaped platform**, **silent degradation** (a MISSING capability nobody builds, absorbed by quietly reshaping the feature — that is a scope change owed to the user, not a design detail), **speculative platform**, and the **paper ledger** (every row EXISTS, nothing named — unfalsifiable, exactly like a review that reports "I checked"). L1/L2 do not run the pass: a capability discovered MISSING during L2 work is itself an escalation trigger to L3.
18
+
19
+ - **`## Component Map` — the inventory the pass reads (F-020b).** The pass shipped with nothing to consult: §2 said *rule each capability against the platform*, and no artifact described the platform's components. `strategic/architecture.md` carried stack, directories and patterns — `## Directory Structure` names folders, not capability owners — and `source_kind: code` guides cover one component at a time, on a complexity trigger, never the inventory. So the platform had to be re-derived from source every session: the myopia the skill exists to prevent, reproduced inside the cure for it. Two more gaps came with it: **no trigger fired when a component was born** (the `architecture.md` row was keyed on *"when the stack … changed"*, and a new component is not a stack change — that is how an inventory rots silently), and the three architecture artifacts (ledger, architecture doc, ADR) never cited each other. All three close with one movement: a **`## Component Map`** section inside the canonical `architecture.md` — one row per component that OWNS a capability, carrying *capability owned* (a verb over a domain noun), *contract* (what it guarantees consumers, stated without naming any single one) and *where* (`path#symbol`). Not a new document: `architecture.md` already exists, is canonical, manifested and lifecycled, and adding a file beside it would be the **speculative platform** anti-pattern this same feature names. Wired as a loop: `architect.md` §2 reads the map **before** searching source (the map is the index, never the evidence — verify against code), the map gets its **own Write-Triggers row keyed on the component's birth**, and `review.md` makes a capability built-but-absent-from-the-map a finding, because the next feature reads that map, rules the same capability MISSING and builds it a second time. This repo's own map ships with it (7 rows: client roster, project seeder, skill deployer, template source, doctrine, validator, invariant battery). New invariant `test_component_map_wired` (asserts the trigger is *not* the bootstrap/stack row it would hide behind); battery 60/60. Left open deliberately: the ADR trigger stays prose — *no decision, no ADR* blocks useless ADRs, but nothing detects a decision taken and not recorded, and a stdlib validator cannot read a diff and judge.
20
+
21
+ - **Brownfield safety: an unread map is not an empty one (F-020c).** Telling the pass to read the Component Map first created a trap on every project the methodology arrives in late: `init.js` seeds `architecture.md` with an **empty** map, so the pass would read an authoritative-looking empty index, rule every capability MISSING, and design duplicates of components already in the codebase — the exact DRY failure the pass exists to prevent, now with a document vouching for it. Closed with an asymmetric rule instead of a caveat: **the map lowers the COST of a verdict, never the STANDARD of one** — it is a cache of evidence somebody already paid for, so a hit means the search is written down, a miss means you pay full price, and reading a row never excuses checking that it is still true. **Its silence is unread, not empty**: the map covers only the areas `audit/audit_plan.md` marks ANALYZED, and outside them it **can never ground a MISSING verdict** — you search, and the MISSING you reach carries its terms, its tool and the areas covered (an unfalsifiable MISSING is the same defect as an EXISTS with no symbol named). The deferral is scoped where it cannot do damage: **understanding is never deferred, only WRITING the map is** — the incremental licence covers the rest of the repository and never what the change touches or depends on, which is understood now, at full standard, mapped or not. Named **`Empty-map MISSING`** in the anti-patterns so a review can catch it, and `review.md` makes an unnamed-search MISSING on unmapped ground the finding that matters most on a freshly-onboarded project. **Phase 1 gains the order and the bound**: write `audit/audit_plan.md` FIRST (the scope ledger everything else is built on), then let the map start at whatever the first task made you understand — **no full-codebase sweep is required before the first feature**, because an unbounded up-front sweep is skipped silently, which is worse than an incremental map. Discovering an existing component now writes its row too, and marks the area (`sdlc_check.py mark`), so the inventory grows by the feature that needed the knowledge. This repo's own map declares its coverage. New invariant `test_unmapped_never_grounds_missing`; battery 61/61.
22
+
23
+ - **Mechanical backstops for the pass (F-020d): a skipped pass and a rotting map are now noticed, not trusted.** The pass shipped as prose plus invariants on the prose — the battery proved the doctrine was *wired*, nothing noticed whether an agent *executed* it, and a Component Map row whose symbol got renamed stayed green forever (guides have `source_hash`; the map had no equivalent). Both closed in `sdlc_check.py`, warnings only, never a gate: **(1) skipped pass** — `validate` warns when an ACTIVE (PLANNED/IN_PROGRESS) L3 ANALYSIS started on/after 2026-07-28 lacks `## Capability Ledger`; closed history and analyses born before the pass never nag (`ARCHITECT_PASS_EPOCH` grandfathering — the pre-1.17 handoff's lazy-convert doctrine applied again). **(2) rotting map** — `validate` resolves every path-shaped ref in the map's `Where` column (glob-aware, `confine_under` fail-closed on escapes) and greps the `#symbol` in the matched files: a dead path or a renamed-away symbol is flagged with the row to fix. Proof of usefulness on day one: the check caught a rotten ref in this repo's own freshly-written map. **(3) adherence** — two behavioral scenarios join the non-gating eval layer (the F-016 route): `architect_rules_before_impact` (capabilities ruled before files, EXISTS cites the map, MISSING names its searches) and `unmapped_never_grounds_missing` (the brownfield trap seeded for real: an existing `RateLimiter` in a PENDING `legacy/` area — the run that rules MISSING from the map's silence FAILS). `architect.md` gains §Mechanical backstops naming all three. New invariants `test_ledger_due_gating`, `test_component_map_rot_detected`, `test_architect_scenarios_present`; battery 64/64.
24
+
25
+ - **Independent pre-publication review, and what it changed (F-020e).** Two read-only reviewers with fresh context (conformance+correctness; adversarial Vision+doctrine) both returned FAIL on the release candidate. Five blockers, all real, all fixed before publishing: **(1)** the skipped-pass backstop could never fire — `ledger_due` required PLANNED/IN_PROGRESS, but closure flips the ANALYSIS to COMPLETED *before* `check` runs, so it was silent at the only moment the process mandates the validator (status filter dropped; `start_date` is the sole guard, which is all grandfathering needed — and the invariant that had locked the defect in is inverted). **(2)** A component the pass merely DISCOVERED had no write trigger: `architect.md` mandated the row, but `SKILL.md` — the authoritative write index — and `review.md` fired on a component's *birth* only, so an agent could obey every shipped rule, mark the area ANALYZED, leave the map silent, and let the next feature lawfully rule MISSING and build a duplicate. The trigger and the review finding now cover discovery, and `architect.md` forbids marking an area whose owners are not yet rows. **(3)** "Warnings — never a gate" was false: `--strict` escalates warnings to exit 1 and `ENFORCEMENT.md` recommends it in CI, so the ledger check was a *blocking* gate on consumer pipelines — a cost the ceremony-budget acceptance never named. Fixed by honoring the accepted budget instead of expanding it: a third severity, **advisories**, printed as `[note]`, never counted as warnings, inert even under `--strict`. **(4)** A literal bracket in a path (`app/[id]/page.tsx` — every Next.js/SvelteKit project) was interpreted as a glob and reported as rot; literal existence is tried first. **(5)** The rot check was inert in silence — `Where` assumed to be the last column, refs without `/` skipped (9 of this repo's own 18 refs unchecked), Windows separators skipped, and `#Notif` passing against `Notifier` on a substring match; all fixed, plus a notice when a map has rows but no checkable ref, because an inert check reported as clean is the same defect as an unread map reported as empty. Doctrine hardening from the same round: §4's split rule had an unreachable default branch (bullet 2 named a property §3 mandates of *every* component, so each one earned its own L3) — resharpened to "delivers value merged alone" with an IN/OUT pair; the contract test gained the re-description clause that paraphrase defeated; the MISSING search gained a floor (domain noun + two synonyms + verb, across every listed area) and a stopping rule; the "one line" licence now says the answer still lives under the heading and still names the component; `SKILL.md` phase 3 states both modes' homes and the Hybrid coverage asymmetry; the duplicated `Coverage:` list became a pointer to `audit_plan.md`. Battery 65/65.
26
+
27
+ - **Second review round: a traversal crash and a check that could not fire (F-020f).** A verification reviewer confirmed all five round-1 blockers fixed by execution; a *cold* adversarial reviewer with no knowledge of round 1 found two more. **(1)** `cmd_stale` and `cmd_mark` never confined the paths they read out of `audit_plan.md` — and `init.js` seeded the row `| / | PENDING |`. Mark that area and `root / "/"` becomes the drive: the closure gate walked the whole filesystem and died on `ValueError: ... is not in the subpath of ...`. A `../escape` row walked outside the project just as happily. The one place that walks the filesystem was the one place not using `confine_under`, which every other path input already goes through — and 1.18.0 is what promoted `audit_plan.md` to load-bearing, so a pre-existing bug became a release blocker. Both commands now confine fail-closed (`mark` refuses, `stale` warns and skips), the seeder writes `.`, and `relative_to` is guarded. **(2)** `SKILL.md` claimed the review clause was the sole Hybrid check that the pass ran, while that clause was conditional on *"when the artifact carries one"* — so on a skipped pass, which produces no ledger, it could never fire. The clause is now unconditional at L3: **an impact/solution analysis or design carrying no Capability Ledger is itself a finding.** Also from the cold round: the extension heuristic turned prose into rot warnings (`app.core`, `OrderStore.save`, `1.18.0` all reported "the map is rotting") — now a closed suffix list; a freshly seeded project emitted an advisory about the placeholder row the seeder had just written (the day-zero false positive that trains readers to ignore the channel) — placeholder rows are skipped and the template no longer ships a half-real ref; the map heading match was case-sensitive and anchored, so `## component map` silently disabled both the check and the notice meant to catch its absence; a headerless or ragged table mis-indexed columns and reported silence as cleanliness — a `Where` header is now required and ragged rows are counted and reported; and two zero-cost bypasses of the ledger backstop are closed (deleting the optional `level:` line now warns; the heading is matched anchored on comment-stripped text, so a `<!-- TODO: ## Capability Ledger -->` no longer counts). New: an advisory for **a mark nobody paid for** — an area marked ANALYZED that owns no Component Map row, the missing half of the loop, since marking is one cheap command and it is what converts the map's silence into a groundable MISSING. Doctrine: the split rule's second bullet became a real discriminator (ships on its own cadence, before the feature) instead of a restatement of the first; the MISSING search floor was unexecutable as written (it prescribed a symbol-graph tool for a query that tool cannot take, and quantified over an undefined unit) — now text-search-first, symbol-graph-to-confirm, with triage as the stopping rule and a *provisional* MISSING when the area is still PENDING; the ledger template gained the Evidence column its own rules require. Battery 69/69.
28
+
29
+ - **Third review round — and the first time anyone USED it (F-020g).** Static review had run three times; nobody had run the methodology end to end. A reviewer did, cold, on a 25-file brownfield fixture with two components hidden behind unhelpful names — and found a different class of defect than any reading had. **The convergent BLOCK** (found independently by the usage trial and a code-delta reviewer): the "a mark nobody paid for" check harvested backticked refs from the **whole** `architecture.md`, and the canonical template puts `## Directory Structure` — full of backticked paths — directly above the Component Map, so the only automated guard that a mark asserted something real was **inert on every project that filled in the shipped template**; the harvest is now scoped to the map's `Where` column. **From the usage trial:** the guide router is a mandatory Rule Zero read whose verdict may not be faked, yet `index` refused to write it with zero guides and `init.js` never created it — the required declaration was **unsatisfiable on every project's first day** (now an empty stub is always written, and `guides.md` names a third legal verdict, `router: absent`); `SKILL.md`'s L3 minimum sections omitted `## Use Cases / User Needs` while `review.md` makes an uncovered use-case a finding, so an ANALYSIS could pass `check` CLEAN and then fail its own closure review. **CI honesty, again:** the `level`-missing guard added last round shipped as a *warning*, and `--strict` escalates warnings to exit 1 — the exact defect the advisories bucket exists to prevent, reintroduced one round later, this time reddening CI on every pre-1.18 analysis that never carried the optional field. It is now an advisory, epoch-gated like the check it guards. The same applies to bootstrap DRAFT visions: the skill *mandates* `Status: DRAFT`, so `validate --strict` was red on every freshly bootstrapped project until a human ran the blind check — a pipeline teams delete rather than block on. DRAFT is a state, not a defect: advisory. Also fixed: multi-line HTML comments leaked into the generated manifest (the `project_vision.md` row read `... -->`, and the manifest is what every future agent reads to orient); `Next.js`, `Node.js` and `OrderStore.save` were reported as rotting paths (a slash-less token now needs a known suffix **and** a stem that is not a CamelCase prose word); `mark` printed `[ok] … added as ANALYZED` for paths it then discarded (all paths are validated before anything is printed or written); the `gate` message told the author to create the analysis they had just written instead of naming the real remedy (`status: IN_PROGRESS`); `SKILL.md` Phase 4 now states that flip, which nothing else performed; and `elicitation.md` gained the unattended path the trial had to improvise — declared assumptions plus `BLOCKED on the user`, never a silent guess, because a bootstrap Vision is DRAFT by mandate and the skip path is therefore unreachable on a project's first L3. Battery 73/73.
30
+ - **What the trial confirmed works, recorded so it is not refactored away.** The `architect.md` search floor's "**at least two** plausible synonyms" clause is load-bearing: in the fixture the domain noun alone returned **zero hits** for both hidden components, and the synonym clause found both — without it the run builds two duplicates. "Its silence is unread, not empty" made a confident MISSING *doctrinally unavailable* on a virgin repo. And the ledger's Evidence column turned a lookup into comprehension: re-reading the component it found surfaced a 4×-per-worker limit defect that no file-level impact analysis would have asked about, which the Silent-degradation rule then routed to the user as a scope decision instead of a quietly shipped bug. **The honest negative, not fixed here:** ceremony is proportional at the feature level and not at the *arrival* level — the first L3 in any repository pays a full product-Vision authoring round regardless of the task's size, because the incremental licence covers the audit map and pointedly not the Vision. That is a Vision-scope decision for the owner, not a bug to patch in a release.
31
+
32
+ - **Fourth round — narrow verification, and every defect it found was in a fix (F-020h).** Scope declared up front: verify the previous round's dispositions and hunt regressions in the code it introduced. Eight of nine fixes landed clean; the ninth was a **BLOCK of my own making**: the router-stub change replaced "guides exist but the router is missing → ERROR" with an unconditional advisory, so a project that has guides and loses its router (gitignored, dropped by a merge) reports CLEAN — the agent's mandatory Rule Zero lookup finds nothing, legally declares `router: absent`, and the guide that governs the work is never consulted. An **absent** router was graded below a merely **stale** one. The error is restored when guides exist; the advisory now covers only the zero-guide case. Three further defects, all the same shape — a fix whose blast radius went unmeasured: the advisory instructed users to write `owns no component` in the audit plan's Notes column and **nothing read that column** (a documented escape hatch that was fiction — now implemented, so an area that genuinely owns nothing can be declared instead of nagged forever); the unterminated-comment strip nuked to end-of-file, so an ANALYSIS that merely *mentions* `<!--` inline, or shows an unclosed example inside a fenced block, was told it had no Capability Ledger when it plainly did (heading detection now strips fences first and only opens an unterminated comment at line start); and the CamelCase exclusion added to stop `Next.js` being reported as rot silenced **22 of 39 probed filenames** — `App.tsx`, `Program.cs`, `Main.java`, `Cargo.toml`, exactly what React/C#/Java projects write in a `Where` cell — now narrowed to the one real class, a CamelCase stem with a `.js` tail. **An invariant was also theater**: the test claiming to cover the comment-bypass asserted `cmd_validate(...) == 0`, but advisories never move the exit code, so it passed against the pre-fix module; it now asserts on the extracted `has_ledger_heading()` including both false-positive cases. Finally, the manifest description fallback emitted markdown table rows (`| Milestone | Expected Benefit |`) as document descriptions — the manifest is the first thing an agent reads to orient, so table rows and bare bullets are skipped now. Battery 73/73; a freshly bootstrapped project exits 0 under `validate --strict`.
33
+
34
+ ### Changed
35
+ - **`SKILL.md` phase 3 invokes the pass before the blast radius**, the L3 minimum sections gain `Capability Ledger`, and the Write-Triggers ANALYSIS row states that a split-out capability gets its own ANALYSIS with the two documents naming each other. **`templates.md`** carries the `## Capability Ledger` section immediately before `## Impact`, which it feeds. **`review.md`** gains a ledger clause on the conformance statement — the three findings that live nowhere else (MISSING implemented inside the feature's code path; a contract naming the feature; a MISSING capability absorbed as a silent scope reduction), plus an unnamed EXISTS row as a finding in itself. Authored and never checked is how a pass becomes theater. New invariant `test_architect_pass_wired` (asserts the ordering too: capabilities are ruled before files are listed); battery 59/59.
36
+ - **Ceremony budget declared, per the Vision's `no ceremony ratchet` Non-Goal**: this adds cost at L3 and removes nothing, so it takes that rule's second branch — cost stated, owner accepts explicitly, and stated in full because "Omission resolves against the proposal". The six costs, all landing on L3 only: **(1)** the architect pass itself, before the Impact; **(2)** one ANALYSIS section (`## Capability Ledger`); **(3)** one support file (`architect.md`), read only when the trigger fires; **(4)** a `## Component Map` row written at closure whenever a component is born, changes contract, or is discovered; **(5)** the `sdlc_check.py mark` obligation on an area the pass searched; **(6)** one more clause on the `review.md` conformance statement for impact/design reviews. Two validator checks report on (2), (4) and (5) as **advisories** that cannot fail a build. Accepted by Antonio Pinto, 2026-07-28, scoped to L3; L1 and L2 are verifiably untouched (`ledger_due` returns False for any non-L3 level). No validator rule lands on consumer projects — a warning on every existing ANALYSIS is the nagging the Vision forbids. Governed by `ai_docs/solutions/ANALYSIS_architect_pass.md`.
37
+
38
+ ## [1.17.0] - 2026-07-27 (Parallel Handoff)
39
+ ### Changed
40
+ - **`audit/handoff.md` becomes a workstream registry (F-019)** — the single narrative handoff was session-scoped: with milestones in parallel, the last session to close overwrote everyone else's resume point (observed live: two 2026-07-27 sessions clobbered each other's handoff). Now: **one row per open workstream** (feature, level, branch, status, since, next step, pointers) — closing one milestone removes one row and never touches another's; whoever opens the project sees at a glance what is in PROGRESS, on which branch, since when. Volatile resume logistics (branch/worktree, uncommitted state, environment notes, next command) move to **`audit/HANDOFF_[feature].md`** — ephemeral by design, **deleted at that feature's closure**: the ANALYSIS Diary keeps the durable narrative (DRY — anything in the HANDOFF file worth keeping was in the wrong file). The registry is an inventory for lookup, not a work board: no assignment, no due dates, no execution ordering (the Vision's work-management Non-Goal is the binding constraint, checked in the ANALYSIS). `ORIENT_DOCS` path unchanged — the registry flows through the SessionStart hook with no validator change. Touches `SKILL.md` (Write Triggers row split, Phase 1, Phase 5), `templates.md` (registry + per-feature templates with the Diary/logistics boundary), new invariant `test_parallel_handoff_wired`. Governed by `ai_docs/solutions/ANALYSIS_parallel_handoff.md`.
41
+ - **Upgrading from ≤1.16 costs nothing and requires nothing.** A legacy narrative handoff keeps working: the validator checks only its `Date:` header and age, the orientation hook reads the same path verbatim, and installing the skill never touches a consumer's `ai_docs/`. It reads as a one-row registry; **convert it lazily, the next time the write trigger fires** — `## Active features` bullets become rows, `## Next step` becomes that row's next step, `## Session notes` becomes `## Project-wide notes`. No migration sweep, no script, and deliberately **no validator warning** for the old form: nagging every existing project about a file that works is exactly the ceremony the Vision forbids. The invariant now asserts the migration clause is present — shipping a format change that strands existing projects is a caught regression.
42
+
43
+ ## [1.16.0] - 2026-07-27 (Guide Activation + Verifiable Vision)
44
+ ### Changed
45
+ - **Rule Zero declares the router verdict** — the triage level is declared together with the guide-router lookup result, as one line (`Level: L2 · router: no match` / `Level: L3 · router: GUIDE_x.md → read`). L1 stays exempt. Rationale: the consult trigger already existed in three places (Phase 4 bullet, `## Operative Guides`, `guides.md` §0) and still did not fire — none of them sits on a path every request executes. Making the lookup a **declared output** is what closes it: an undeclared lookup is indistinguishable from a skipped one, so `no match` is the expected, correct output on a repo with no matching guide. Field report that triggered this: guides were written and then never consulted unless the user asked by hand.
46
+ - **Phase 1 reads the guide router** — `ai_docs/reference/INDEX.md` joins `README.md` + `INDEX.md` as a mandatory orientation read: it is the only step that tells you a guide already governs the work you are about to do. The `templates.md` README template and this repo's own `ai_docs/README.md` list it first, so new projects inherit the fix.
47
+ - **SessionStart `orient` hook promoted from optional to recommended default** (`ENFORCEMENT.md` §4) and wired in this repo (`.claude/settings.json`). It already emitted the router (`ORIENT_DOCS`); it was simply off by default. Prompt placement carries the process, the hook is the backstop that survives long contexts and compaction. `sdlc_check.py` unchanged.
48
+ - **`source_kind: code` write trigger gets a real phase** — the Write-Triggers row moves from phase `any` (nobody's phase) to `4 / 5`, and Phase 5 gains a **Comprehension checkpoint** that asks the question out loud before closure: did this session force me to build a model of a high-complexity component no CURRENT guide covers? The duty still fires the moment the signal is recognized; the checkpoint is a backstop, not a deferral.
49
+ - **`guides.md` §0** gains the declare-the-verdict rule and its anti-theater twin (never fake a verdict; a verdict listing several guides means the match was not targeted, T7). **`dispatch.md`** pins verdict ownership: the orchestrator declares once at plan-authoring; a dispatched subagent does not.
50
+
51
+ ### Added
52
+ - **`vision.md` — the drafting discipline that makes a Vision verifiable by a cold reviewer (F-018).** A Vision is a gate: a reader with no other context must rule ACCEPT or REJECT on a proposed change, quoting one line. Most cannot, and the gap is invisible from the inside. This file is the *why it works*, derived empirically from six blind adversarial rounds (reviewers with no repository access, ~25 attack proposals) by comparing the rules that survived every attack against the rules that fell. It carries: the **nine properties of a rule that holds** (key it to an observable property of the artifact, never to intent — *a rule whose predicate is a promise is satisfied by making the opposite promise*; both branches of the decision question answered; counterfactual phrasing; near-miss verbs enumerated; terms defined by effect with a closure rule; forms rather than instances; a checkable subject predicate; an IN/OUT pair on one axis; the anticipated re-descriptions named inside the rule's own sentence); the **five structural clauses** around them (supremacy, exceptions attached affirmatively, anti-abuse on every exemption, stated defaults per path, precedence); the **reject/admit asymmetry** — *only prohibitions reject, only positives admit*, so a Goal cannot stop anything and a criterion phrased as an already-true state cannot be advanced; the **minimum operable sections**; the **five failure classes no wording fixes** (each mapped to a mechanism, not better prose); and the **blind-check procedure** — text pasted not linked, fresh context, a battery with an accept side because *a gate that can only reject is half a gate*, and the demand for the mechanism behind each ruling. Wired from the Vision Gate (Standalone and Hybrid/M-VISION), the Write-Triggers Vision row and the `templates.md` Vision template, which is restructured to the operable sections with each marked `[gate]` or orientation. Shipped in the package allowlist. New invariant `test_vision_discipline_wired`; battery 57/57. Anchored by the owner's definition (`## What a Vision IS`): *a Vision states the benefit to be obtained while leaving the most degrees of freedom possible — it binds nothing that does not obstruct that benefit.* Operationalized as: benefit-not-mechanism (the test a North Star must pass), the **deletion test** as the generative rule for every constraint (remove the rule — benefit still reachable? delete it) and its stop rule, constraints that accumulate as work reveals obstacles (an almost-empty first draft is correct: DRAFT informs, APPROVED binds), and the invariant that a constraint never obstructs the Vision — a conflict is an amendment, owner-owned. The deletion test decides WHICH rules exist; the nine properties decide HOW to write one that holds. `elicitation.md` aligned: a mechanism is not an acceptable answer to the benefit question.
53
+
54
+ ### Repository (this project's own `ai_docs/`, not shipped in the package)
55
+ - **Vision rewritten after a blind-reviewer clarity check (F-017)** — three reviewers with fresh context and **no repository access** read `ai_docs/vision/project_vision.md` cold: verdict FAIL, 10 convergent findings. Decisive one: the proposal *"cap how many operative guides a free user may create per month"* was **admissible on the literal text** — no Non-Goal covered metering, and every anti-paywall constraint was bound to the proper noun `devPNT` rather than to paywalling as a class, so the same proposal under another name passed untouched. The Vision was also undecidable in general: its only affirmative admission test was that a change "inherits `ai_docs/` frontmatter, manifest and lifecycle" — a test of form, not substance. Rewritten as `Status: DRAFT` (pending owner promotion): the product is stated in its own terms with no competitor in the North Star, a `## Core Problem` names myopia, Non-Goals are rules over classes (metering/paywall/account-gating; required network or off-repo storage; code or release coupling), a new `## The admission test` requires a change to advance a Success Signal and not merely be well-formed, and the six Success Signals are each checkable against a named artifact or command. The A/B/C/D layer map moved to its real home `strategic/capabilities_and_positioning.md`, declared a dated snapshot. Evidence: `audit/reviews/BLIND_VISION_REVIEW_2026-07-27.md`; finding-by-finding disposition: `solutions/ANALYSIS_vision_clarity.md`. **No skill file changed** — this is the project's own governance, and the improvement is asserted until the blind lenses are re-run against the promoted text.
56
+
57
+ ### Process note
58
+ Doc-only + tests: no `sdlc_check.py` or packaging change. Standalone L3 (devPNT off this session). Governed by `ai_docs/solutions/ANALYSIS_guide_activation.md` (F-016). Four new static invariants (Rule-Zero verdict, Phase-1 router read, code-guide phase, hook promotion) — battery 56/56 green; `validate` 0 errors. New behavioral scenario `verdict_declared_on_no_match.md` proves the "looked, nothing fitted" case; `consult_fires_on_match.md` now also asserts the verdict and that the consult fires unprompted.
59
+
5
60
  ## [1.15.0] - 2026-07-19 (Write Triggers + Code-Comprehension Guides)
6
61
  ### Added
7
62
  - **Code-comprehension guides (`source_kind: code`)** — a new guide kind the agent writes **autonomously** (a duty, no proposal) when it recognizes a high-complexity component / feature / abstraction layer with no CURRENT guide: a source-faithful map of how the thing works, so the next session starts with the model instead of re-deriving it and breaking the component from partial understanding. Reuses the ENTIRE guide machinery (snapshot + `source_hash` + `stale` + router + fidelity markers) — the source is verbatim CODE EXCERPTS in `.sources/` instead of a handed document; `sdlc_check.py` is unchanged. The skill-wide "propose, never a silent write" rule is relaxed for THIS kind only (additive, code-anchored, reversible); the anti-hallucination floor holds — every claim traces to a code excerpt. Triggered by concrete signals (high comprehension cost, high fan-in, non-obvious flow, prior / repeated-across-sessions breakage from partial understanding, non-local rationale) and by **chronic fragility** (a component breaking repeatedly across sessions → write the guide AND escalate a refactor as its own L3; stop patching). Touches `guides.md` §1–§6, `SKILL.md` (4th "Comprehend" moment + Write-Triggers `code` row + consult wording), `templates.md` (`source_kind` + comprehension repertoire), `debugging.md` (capture-the-model + chronic-fragility). Positioned under Vision **Layer A** (Documentation-First lifecycle applied to code understanding), distinct from Layer D's user-indication operative guides.
package/README.md CHANGED
@@ -6,13 +6,14 @@
6
6
 
7
7
  - **Risk-proportional workflow**: L1/L2/L3/Spike triage avoids heavyweight process for trivial work, with a symmetric **Write Triggers** table mapping each event to the document it produces (one event, one destination).
8
8
  - **Vision-guided governance**: Standalone projects use `ai_docs/vision/`; Hybrid projects use devPNT `M-VISION` as the milestone north star. The Vision names its **Actors** — the cast a feature serves, one light line each — so UX is designed for concrete roles, not an implicit "user".
9
+ - **Architect pass — capabilities before files**: at L3, before listing what changes, the feature is stated as the *capabilities* it needs and each is ruled against the platform (EXISTS / INADEQUATE / MISSING); what is missing is designed as a component with its own contract, of which the feature is one consumer — never inlined into the feature's code path. A `## Component Map` in `strategic/architecture.md` is the durable inventory the pass reads, so the platform is not re-derived from source every session. On a codebase the methodology arrives in late, the map's silence is treated as **unread, not empty**: it can never ground a MISSING verdict.
9
10
  - **Execution disciplines**: explicit TDD (RED/GREEN/REFACTOR), systematic debugging, an L3 spec-elicitation round, and a single code-review definition wired into the workflow phases.
10
11
  - **Operative + comprehension guides + agent-global KB**: distil user-provided indications into source-faithful operative `GUIDE_*.md` (`source_kind: document`), and let the agent autonomously author **code-comprehension guides** (`source_kind: code`) for complex components — a source-faithful mental-model map that survives across sessions, so the next session doesn't re-derive and break the component from partial understanding. Consulted before work; shared cross-project via `~/.agentic-sdlc`.
11
12
  - **Opt-in subagent execution**: an approved design projects into a validated executable plan an orchestrator can drive through subagents.
12
13
  - **Self-activating**: a SessionStart hook emits repo-sourced orientation; a deterministic self-eval battery guards the skill's own doctrine as the release gate.
13
14
  - **Standalone complete**: works fully with local `ai_docs/` without requiring devPNT.
14
15
  - **devPNT symbiosis**: when devPNT is available, Master Plan, Action Plan, M-VISION, and governed artifacts become the authoritative planning layer, with independent fresh-context reviews of technical artifacts and diffs.
15
- - **Installed support files**: Claude, Codex, Gemini, and Google Antigravity receive the full skill folder, including `templates.md`, `guides.md`, `tdd.md`, `debugging.md`, `elicitation.md`, `review.md`, `dispatch.md`, `ENFORCEMENT.md`, and `scripts/sdlc_check.py`.
16
+ - **Installed support files**: Claude, Codex, Gemini, and Google Antigravity receive the full skill folder, including `templates.md`, `architect.md`, `guides.md`, `vision.md`, `tdd.md`, `debugging.md`, `elicitation.md`, `review.md`, `dispatch.md`, `ENFORCEMENT.md`, and `scripts/sdlc_check.py`.
16
17
  - **Mechanical checks**: optional validator for document structure, generated feature history, stale audit areas, and protected-path gates.
17
18
 
18
19
  ## Installation
@@ -49,7 +50,9 @@ The actual runtime skill is the folder:
49
50
  skills/agentic-sdlc-skill/
50
51
  ├── SKILL.md
51
52
  ├── templates.md
53
+ ├── architect.md
52
54
  ├── guides.md
55
+ ├── vision.md
53
56
  ├── tdd.md
54
57
  ├── debugging.md
55
58
  ├── elicitation.md
@@ -1,6 +1,6 @@
1
- {
2
- "name": "agentic-sdlc-skill",
3
- "version": "1.15.0",
4
- "description": "Documentation-First SDLC protocol with triage, Vision governance and optional devPNT integration.",
5
- "author": "Antonio Pinto (https://github.com/Antoneeo)"
6
- }
1
+ {
2
+ "name": "agentic-sdlc-skill",
3
+ "version": "1.19.0",
4
+ "description": "Documentation-First SDLC protocol with triage, Vision governance and optional devPNT integration.",
5
+ "author": "Antonio Pinto (https://github.com/Antoneeo)"
6
+ }
package/package.json CHANGED
@@ -1,46 +1,48 @@
1
- {
2
- "name": "@antoneeo/agentic-sdlc-skill",
3
- "version": "1.15.0",
4
- "description": "Documentation-First SDLC protocol for Claude Code, Gemini CLI, Google Antigravity and Codex with risk triage, Vision governance, installed support files and optional devPNT integration.",
5
- "keywords": [
6
- "claude-code",
7
- "claude-skill",
8
- "gemini-cli",
9
- "skill",
10
- "sdlc",
11
- "documentation",
12
- "ai-agent"
13
- ],
14
- "author": "Antonio Pinto (https://github.com/Antoneeo)",
15
- "license": "MIT",
16
- "publishConfig": {
17
- "access": "public"
18
- },
19
- "bin": {
20
- "agentic-sdlc-init": "scripts/init.js",
21
- "agentic-sdlc-install-skill": "scripts/postinstall.js"
22
- },
23
- "scripts": {
24
- "postinstall": "node scripts/postinstall.js",
25
- "preuninstall": "node scripts/preuninstall.js"
26
- },
27
- "files": [
28
- "skills/agentic-sdlc-skill/SKILL.md",
29
- "skills/agentic-sdlc-skill/templates.md",
30
- "skills/agentic-sdlc-skill/guides.md",
31
- "skills/agentic-sdlc-skill/tdd.md",
32
- "skills/agentic-sdlc-skill/debugging.md",
33
- "skills/agentic-sdlc-skill/elicitation.md",
34
- "skills/agentic-sdlc-skill/review.md",
35
- "skills/agentic-sdlc-skill/dispatch.md",
36
- "skills/agentic-sdlc-skill/ENFORCEMENT.md",
37
- "skills/agentic-sdlc-skill/scripts/sdlc_check.py",
38
- "gemini-extension.json",
39
- "README.md",
40
- "CHANGELOG.md",
41
- "scripts/lib.js",
42
- "scripts/init.js",
43
- "scripts/postinstall.js",
44
- "scripts/preuninstall.js"
45
- ]
46
- }
1
+ {
2
+ "name": "@antoneeo/agentic-sdlc-skill",
3
+ "version": "1.19.0",
4
+ "description": "Documentation-First SDLC protocol for Claude Code, Gemini CLI, Google Antigravity and Codex with risk triage, Vision governance, installed support files and optional devPNT integration.",
5
+ "keywords": [
6
+ "claude-code",
7
+ "claude-skill",
8
+ "gemini-cli",
9
+ "skill",
10
+ "sdlc",
11
+ "documentation",
12
+ "ai-agent"
13
+ ],
14
+ "author": "Antonio Pinto (https://github.com/Antoneeo)",
15
+ "license": "MIT",
16
+ "publishConfig": {
17
+ "access": "public"
18
+ },
19
+ "bin": {
20
+ "agentic-sdlc-init": "scripts/init.js",
21
+ "agentic-sdlc-install-skill": "scripts/postinstall.js"
22
+ },
23
+ "scripts": {
24
+ "postinstall": "node scripts/postinstall.js",
25
+ "preuninstall": "node scripts/preuninstall.js"
26
+ },
27
+ "files": [
28
+ "skills/agentic-sdlc-skill/SKILL.md",
29
+ "skills/agentic-sdlc-skill/templates.md",
30
+ "skills/agentic-sdlc-skill/architect.md",
31
+ "skills/agentic-sdlc-skill/guides.md",
32
+ "skills/agentic-sdlc-skill/vision.md",
33
+ "skills/agentic-sdlc-skill/tdd.md",
34
+ "skills/agentic-sdlc-skill/debugging.md",
35
+ "skills/agentic-sdlc-skill/elicitation.md",
36
+ "skills/agentic-sdlc-skill/review.md",
37
+ "skills/agentic-sdlc-skill/dispatch.md",
38
+ "skills/agentic-sdlc-skill/ENFORCEMENT.md",
39
+ "skills/agentic-sdlc-skill/scripts/sdlc_check.py",
40
+ "gemini-extension.json",
41
+ "README.md",
42
+ "CHANGELOG.md",
43
+ "scripts/lib.js",
44
+ "scripts/init.js",
45
+ "scripts/postinstall.js",
46
+ "scripts/preuninstall.js"
47
+ ]
48
+ }
package/scripts/init.js CHANGED
@@ -67,7 +67,9 @@ function initialAuditPlan() {
67
67
  const lines = tpl.split('\n');
68
68
  const sepIdx = lines.findIndex((l) => /^\|[-\s|:]+\|$/.test(l.trim()));
69
69
  if (sepIdx === -1) return tpl; // unexpected shape: keep the template as-is
70
- return lines.slice(0, sepIdx + 1).join('\n') + '\n| / | PENDING | - | Initial analysis |\n';
70
+ // '.' (the project root), never '/': an absolute row makes `stale` walk the
71
+ // whole drive once the area is marked ANALYZED.
72
+ return lines.slice(0, sepIdx + 1).join('\n') + '\n| . | PENDING | - | Initial analysis |\n';
71
73
  }
72
74
 
73
75
  let seedFiles;
@@ -55,9 +55,11 @@ Semantics: exit code 2 + message on stderr ⇒ the write is blocked and the mess
55
55
  - The hook assumes the working directory is the project root (standard behavior of Claude Code hooks).
56
56
  - **Hybrid/devPNT projects**: add `--hybrid` to the gate command. Governed designs live in the devPNT DB, so the gate also unlocks when an approved E-TDD shadow (`ai_docs/solutions/SHADOW_*tdd*.md`, exported before implementation — see the SKILL.md shadow discipline) is present. Without the flag the gate would block legitimate governed work. The flag is deliberately explicit: never auto-detected.
57
57
 
58
- ## 4. SessionStart hook (orientation, optional)
58
+ ## 4. SessionStart hook (orientation, recommended default)
59
59
 
60
- Emits the `ai_docs/` orientation — reading guide (`README.md`), manifest (`INDEX.md`), guide router (`reference/INDEX.md`) and last `handoff.md` — plus the Rule-Zero triage reminder to stdout at session start, so the agent begins already oriented instead of reading them only if it remembers to. It is **fail-open**: a missing, unreadable or oversized doc is skipped, the output is size-capped, and it always exits 0 — a broken or empty `ai_docs/` never blocks the session. It is **zero-execution** (it reads and prints, never runs anything) and opt-in.
60
+ Emits the `ai_docs/` orientation — reading guide (`README.md`), manifest (`INDEX.md`), guide router (`reference/INDEX.md`) and last `handoff.md` — plus the Rule-Zero triage reminder to stdout at session start, so the agent begins already oriented instead of reading them only if it remembers to. It is **fail-open**: a missing, unreadable or oversized doc is skipped, the output is size-capped, and it always exits 0 — a broken or empty `ai_docs/` never blocks the session. It is **zero-execution** (it reads and prints, never runs anything).
61
+
62
+ **Wire it on every project that has `ai_docs/` and a Python interpreter.** It was opt-in until v1.16.0 and the field result was the defect this level exists to prevent: the guide router stayed unread unless the user asked for it by hand, so guides were written and never consulted. Prompt-level placement (Rule Zero declares the router verdict; Phase 1 reads the router) carries the process on its own — this hook is the backstop that survives long contexts, compaction and a session that never enters Phase 1 explicitly. Skip it only where Python is unavailable, and know what you are trading.
61
63
 
62
64
  Wire it via each client's SessionStart mechanism — the same command everywhere (add `--hybrid` on devPNT/Hybrid projects):
63
65
 
@@ -91,6 +93,8 @@ Gemini CLI — wire the same command into its startup-hook mechanism if present;
91
93
 
92
94
  ## 5. Skill eval battery (release gate)
93
95
 
96
+ **Skill development only.** `test_*.py` and `evals/` are deliberately absent from the npm `files` allowlist — they never reach an installed consumer, so this section applies to whoever builds the skill, not to a project that uses it. (Consumers get `sdlc_check.py`; §1–§4 are theirs.)
97
+
94
98
  The skill self-tests its own doctrine invariants. Two layers over one scenario corpus:
95
99
 
96
100
  **Static battery — the deterministic release gate.** Run before any publish:
@@ -13,8 +13,10 @@ This skill guides software development with a Documentation-First process propor
13
13
 
14
14
  Support files in the skill directory:
15
15
  - `templates.md`: templates for Vision, ANALYSIS, Spike, audit plan and handoff.
16
+ - `architect.md`: the architect pass — do the components and services this feature needs already exist? Run at L3 before drafting the Impact.
16
17
  - `guides.md`: pipeline for distilling user-provided indications into `ai_docs/reference/GUIDE_[topic].md`.
17
- - `scripts/sdlc_check.py`: mechanical validator for `ai_docs/` (`check`, `validate`, `index`, `stale`, `mark`, `gate`).
18
+ - `vision.md`: how to write a Vision a cold reviewer can actually apply — the properties that make a rule hold, the minimum operable sections, and the blind check run before promoting one to APPROVED.
19
+ - `scripts/sdlc_check.py`: mechanical validator for `ai_docs/` (`check`, `validate`, `index`, `stale`, `mark`, `gate`, `plan`, `orient`).
18
20
  - `ENFORCEMENT.md`: optional setup for CI and hooks.
19
21
 
20
22
  Read these files only when needed. `SKILL.md` is the operating contract; the support files are progressive resources.
@@ -35,6 +37,8 @@ If a patch looks easy but you do not understand why the current code is shaped t
35
37
 
36
38
  Always classify the request before choosing the process. Declare the chosen level to the user when you start operational work.
37
39
 
40
+ **Declare the level WITH the router verdict** (one line, for L2, L3 and Spike — L1 declares the level alone): the result of the guide-router lookup described under `## Operative Guides`, i.e. `Level: L2 · router: no match` or `Level: L3 · router: GUIDE_release.md → read`. The lookup is the consult trigger; making its result a declared output is what keeps it from being skipped — a level declared without a verdict makes "did not look" indistinguishable from "looked, nothing matched". Name the guide you matched, or `no match`; name a second one only when it covers a genuinely distinct concern (typically one operative guide plus the comprehension map of the component you are touching). The verdict is never a listing of the catalogue, and never an excuse to read every guide.
41
+
38
42
  | Level | Criteria | Required process |
39
43
  |---|---|---|
40
44
  | **L1 - Trivial** | About 10 lines in 1-2 files; no API, dependency or new-behavior change; typos or fixes restoring already-expected behavior | Implement. Run relevant existing tests. No new documents. |
@@ -54,16 +58,20 @@ Triage decides IF documentation is due; this table decides WHICH document each e
54
58
 
55
59
  | Document | Write trigger | Phase |
56
60
  |---|---|---|
57
- | `solutions/ANALYSIS_[feature].md` | Every L3, after elicitation and before any code. On topic match with an existing analysis, update that one instead of a new file. | 3 |
61
+ | `solutions/ANALYSIS_[feature].md` | Every L3, after elicitation and before any code. On topic match with an existing analysis, update that one instead of a new file. A capability the architect pass splits out as its own unit of change (`architect.md` §4) gets its own ANALYSIS, and the two documents name each other. | 3 |
58
62
  | `solutions/SPIKE_[topic].md` | Closing any Spike — including a failed one (a negative outcome is still an outcome). | — |
59
63
  | `vision/features/VISION_[feature].md` | Feature known multi-milestone at analysis time, OR the retroactive trigger: you are about to create the SECOND `ANALYSIS_*` on the same theme — extract the shared feature vision first, then let both analyses reference it. | 3 |
60
- | `audit/handoff.md` | Mandatory at every L3 closure, and at session end when an ANALYSIS is still IN_PROGRESS (even without closure); discretionary after an L2 when useful. Refresh Date / Branch / active features / next step; ≤ 20 lines. | 5 / session end |
64
+ | `audit/handoff.md` (workstream registry) | One row per OPEN workstream (feature, level, branch, status, since, next step, pointer to its Diary/HANDOFF file) parallel-safe: closing one milestone touches one row, never another's resume point. Refresh the row at every L3 closure (remove it) and at session end when that ANALYSIS is IN_PROGRESS; discretionary after an L2. ≤ 20 lines. | 5 / session end |
65
+ | `audit/handoff.md` — legacy narrative form (pre-1.17 projects) | **Convert lazily, on first write, never as a migration sweep.** A narrative handoff still works: read it as a single-row registry (`## Active features` bullets = the rows, `## Next step` = that row's next step). The first time the Write Trigger above fires, write it in registry form; until then, leave it. Nothing breaks in the meantime — the validator checks only the `Date:` header and its age, and the `orient` hook reads the file verbatim at the same path. | 5 / session end |
66
+ | `audit/HANDOFF_[feature].md` | Session ends with that feature unfinished AND there is volatile resume state (branch/worktree, uncommitted work, environment notes, next command). **Resume logistics only — the ANALYSIS Diary keeps the durable narrative (DRY)**; the file is ephemeral and is DELETED at that feature's closure, same step that flips the ANALYSIS to COMPLETED. | 4 / 5 / session end |
61
67
  | `audit/audit_plan.md` (Standalone) | Bootstrap, and whenever a mapped area changes state (`sdlc_check.py mark` records the reference — git hash, else UTC timestamp). | 1 |
62
68
  | `reference/GUIDE_[topic].md` (`source_kind: document`) | Origin+purpose test (`guides.md`), or a proactive proposal the user accepted. Propose, never a silent write, never from model knowledge. | 4 / 5 |
63
- | `reference/GUIDE_[topic].md` (`source_kind: code`) | Recognized high-complexity component/feature/layer with no CURRENT guide — including one that breaks repeatedly across sessions → **duty to write autonomously** (no proposal; additive, code-anchored, reversible). Fidelity floor: every claim traces to a code excerpt. Signals + guard-rails: `guides.md` §1. | any |
69
+ | `reference/GUIDE_[topic].md` (`source_kind: code`) | Recognized high-complexity component/feature/layer with no CURRENT guide — including one that breaks repeatedly across sessions → **duty to write autonomously** (no proposal; additive, code-anchored, reversible). Fidelity floor: every claim traces to a code excerpt. Signals + guard-rails: `guides.md` §1. Write it as soon as you recognize the signal; the Phase-5 Comprehension checkpoint is the backstop that asks the question, never the only moment it may fire. | 4 / 5 |
70
+ | `audit/reviews/REVIEW_LOG.md` | Every completed review — when and what to write is `review.md` §When a review is due; schema and column meanings are `templates.md`. | 3 / 5 |
64
71
  | ADR — `architecture/` (Standalone) or devPNT DB (Hybrid) | An architectural decision was taken (new pattern, layer or contract change, structural dependency): record it at closure, before DONE. No decision, no ADR. | 5 |
65
72
  | `strategic/architecture.md`, `strategic/existing_features.md` | Bootstrap; update at closure when the stack or the feature catalog actually changed. | 1 / 5 |
66
- | `vision/project_vision.md`, `roadmap.md`, `principles.md` | Bootstrap, as `Status: DRAFT`; promoted to APPROVED only by explicit user confirmation. | 1 / 2 |
73
+ | `strategic/architecture.md` — `## Component Map` | A component was BORN, its contract changed, **or the pass DISCOVERED an existing one while searching an unmapped area** — the same closure adds or corrects its row (`architect.md`). Keyed on the component, not on the stack: a new component is not a stack change, and a discovered one is how an area gets marked ANALYZED while the map stays silent about what lives there — after which the next feature may lawfully rule it MISSING and build it twice. | 5 |
74
+ | `vision/project_vision.md`, `roadmap.md`, `principles.md` | Bootstrap, as `Status: DRAFT`; promoted to APPROVED only by explicit user confirmation, and only after the blind check (`vision.md` §6) — which also gates any amendment of an APPROVED Vision. Write it against `vision.md` §1–§4 from the first draft. | 1 / 2 |
67
75
  | `INDEX.md`, `reference/INDEX.md`, `strategic/features_history.md` | Never by hand: regenerated by `sdlc_check.py index` at closure when canonical docs or guides changed (prose discipline where the validator is not adopted). | 5 |
68
76
 
69
77
  ## Operating Modes
@@ -118,6 +126,9 @@ process; it never replaces it.
118
126
  | Feature state | ANALYSIS frontmatter `status` | Action Plan node status | mapping table below; at closure both must move together |
119
127
  | ADR | `architecture/` (canonical dir) | devPNT DB (`adr_YYYY-MM-DD_slug`) | optional filesystem shadow `SHADOW_adr_*` exported at closure for grep-ability |
120
128
  | Audit / freshness | `audit/audit_plan.md` + `stale`/`mark` | devPNT KL coverage + summary status | run `check --hybrid` (skips audit-plan staleness) |
129
+ | Design review (pre-implementation) | `review.md` moment 1, on the ANALYSIS | devPNT §4.5 gate on `E-ISP`/`E-TDD` | same slot, richer backend — run ONE of them, never both |
130
+ | *(mode is per unit of change, not per project)* | a Hybrid-capable project may work one feature Standalone: the slot follows the ARTIFACT the design lives in, and the mode is declared in that artifact. `validate --hybrid` suppresses the Standalone design-review backstop, since devPNT owns the slot there | | |
131
+ | Review log | `audit/reviews/REVIEW_LOG.md` | devPNT `REVIEW_LOG.md` (same path) | always filesystem |
121
132
  | Operative guides | `ai_docs/reference/` | `ai_docs/reference/` — **filesystem-first even in Hybrid** | devPNT bootstrap may point at their index; it never copies their content |
122
133
  | Handoff | `audit/handoff.md` | `audit/handoff.md` | always filesystem |
123
134
 
@@ -174,10 +185,11 @@ gate) instead of requiring an IN_PROGRESS ANALYSIS.
174
185
 
175
186
  ### 1. Audit and Alignment
176
187
 
177
- - Read `ai_docs/audit/handoff.md` if it exists; if its Date/Branch are inconsistent, treat it as history.
178
- - Read `ai_docs/README.md` (curated must-reads) and `ai_docs/INDEX.md` (generated manifest of all canonical docs) to know what exists before exploring the code. `solutions/` and `audit/` are not indexed per file: search them with glob/grep.
179
- - Optional: a SessionStart hook (`ENFORCEMENT.md` §4) can emit this orientation automatically at session start (README + INDEX + guide router + handoff + triage reminder); when it is not wired, do these reads manually as above. The hook is a convenience, never a requirement it introduces no Python dependency for the process itself and fails open (a missing/empty `ai_docs/` never blocks the session).
188
+ - Read `ai_docs/audit/handoff.md` if it exists the **workstream registry**: one row per open workstream, so you see at a glance what is in PROGRESS, on which branch, since when, before touching anything. If a row's Date/Branch are inconsistent with reality, treat that row as history. When resuming a specific workstream, read its `audit/HANDOFF_[feature].md` (volatile resume logistics) AND its ANALYSIS Diary (durable narrative) — the registry row points at both. A **narrative handoff from a pre-1.17 project** reads as a single-row registry; convert it when you next write it, not now (Write Triggers).
189
+ - Read `ai_docs/README.md` (curated must-reads), `ai_docs/INDEX.md` (generated manifest of all canonical docs) and `ai_docs/reference/INDEX.md` (the guide router) to know what exists before exploring the code. The router is a mandatory read, not an optional one: it is the only orientation step that tells you a guide already governs the work you are about to do. On a project with no guides yet it exists as an empty stub (`sdlc_check.py index` writes it precisely so the mandatory read has something to read) — the honest verdict there is `router: no match`, and if the file is genuinely absent, say `router: absent (no router file)` and regenerate it rather than inventing a match. `solutions/` and `audit/` are not indexed per file: search them with glob/grep.
190
+ - Recommended default: a SessionStart hook (`ENFORCEMENT.md` §4) emits this orientation automatically at session start (README + INDEX + guide router + handoff + triage reminder), so the router reaches the context even in a session that never opens Phase 1 explicitly. Wire it wherever Python is available; when it is not wired, do these reads manually as above the process never depends on it, and it fails open (a missing/empty `ai_docs/` never blocks the session).
180
191
  - If `ai_docs/` is missing or incomplete, create the structure and the **bootstrap set** by analyzing the project in batches: `README.md`, the three `vision/` docs (`Status: DRAFT`), `strategic/architecture.md`, `strategic/existing_features.md` and — Standalone — `audit/audit_plan.md`; then regenerate `INDEX.md`. Nothing else is mandatory at bootstrap (per-document triggers: Write Triggers).
192
+ - **Arriving in a project that was never curated** (the usual case — you arrive with a task, not with a bootstrap): write `audit/audit_plan.md` FIRST. It is the scope ledger the rest is built on — one row per area, all PENDING, `SKIPPED` for what genuinely does not merit reading (vendored, generated). Then the other bootstrap documents describe what you have actually analyzed, and the `## Component Map` in `strategic/architecture.md` starts at whatever the first task made you understand. **No full-codebase sweep is required before the first feature**: the map grows feature by feature, each one marking the areas it covered (`sdlc_check.py mark`). What is NOT deferred is comprehension of what the change touches or depends on — that is understood now, at full standard, mapped or not. The licence is about writing the inventory, never about designing on a guess (`architect.md` §2: unmapped is *unread*, not *empty*, and can never ground a MISSING verdict).
181
193
  - In Standalone use `ai_docs/audit/audit_plan.md` for mapping and state.
182
194
  - In Hybrid prefer the devPNT/KL mapping when available; do not duplicate plan governance.
183
195
  - For detailed templates use `templates.md`.
@@ -189,25 +201,31 @@ Standalone:
189
201
  - If a document declares `Status: DRAFT`, treat it as a hypothesis: flag conflicts, but do not block an explicit user request.
190
202
  - If it declares `Status: APPROVED` and the request conflicts, stop and ask for a choice: update the Vision or modify/reject the request.
191
203
  - Never promote a Vision to `APPROVED` without the user's confirmation.
204
+ - **Writing or amending a Vision is its own discipline — follow `vision.md`.** Draft against its §1–§4 (the properties that make a rule survive a motivated reader, and the minimum sections a gate needs), then run the **blind check** (§6) before promotion to APPROVED and before any amendment of an approved Vision. A Vision that has never been read cold by someone with no other context has not been tested at the only thing it exists to do.
192
205
 
193
206
  Hybrid:
194
207
  - Read the milestone's M-VISION, or ask for/create the step required by the devPNT protocol.
195
208
  - Verify that the request serves a benefit or success signal of the M-VISION.
196
209
  - If the request adds unauthorized scope, treat it as a Vision divergence.
210
+ - The M-VISION is a Vision: `vision.md` applies to it too. The gate lens of the blind check (§6) is the proportional subset for a milestone-scope document.
197
211
 
198
212
  ### 3. Request Analysis
199
213
 
200
214
  For any L3, run the spec elicitation round in `elicitation.md` BEFORE drafting the analysis (skip path inside — one-line note when the spec is already complete).
201
215
 
216
+ **Architect before you list files.** Once the spec is known and BEFORE drafting the Impact, run the architect pass in `architect.md`: state what the feature requires the system to be able to DO (capabilities — verbs over domain nouns, no files), rule each one against the platform — **EXISTS** (name the component and where it lives) / **INADEQUATE** (name the gap) / **MISSING** (say what you searched) — and design what is missing as a component with **its own contract, in its own vocabulary**, of which this feature is one consumer. The output goes where that mode keeps designs — Standalone: the ANALYSIS `## Capability Ledger`; Hybrid: the `E-ISP`, above its Impacted Components map (`architect.md`; never a second copy in `ai_docs/`) — and it feeds the Impact. Note the coverage asymmetry: the validator backstop reads Standalone ANALYSIS files only, so in Hybrid the sole check that the pass ran is `review.md`'s ledger clause — which is why that clause fires on a MISSING ledger and not only on the rows of one that is present. Why it is its own step: a feature is not a unit of construction, and an agent that skips it builds the missing capability inside the feature's code path, where no component owns it and the next feature rebuilds it differently. The pass is a question, not a form — when every capability plainly exists, one line answers it.
217
+
202
218
  **Blast-radius enumeration is an authoring duty, not a review finding.** Before writing the Impact (the list of what changes), for every symbol whose signature you change, thread a new field through, or that has more than one caller: mechanically enumerate EVERY consumer with the best symbol-graph tool your toolchain offers — an LSP/IDE call hierarchy or a find-usages / call-graph capability — with `grep` only as a last-resort fallback, and list the full set in the Impact. Anchor to symbol identity, not line numbers (they rot). This is deterministic and cheap: doing it up-front collapses the review into one pass, instead of the reviewer returning "you missed a consumer" one round at a time. Leaving completeness to the closure review is the myopia failure this whole workflow exists to prevent.
203
219
 
204
220
  Standalone L3:
205
221
  - Before creating a new `ANALYSIS_[feature].md`, search `ai_docs/solutions/` with glob/grep for an existing analysis on the same topic: if there is one, update it instead of duplicating it.
206
222
  - Create or update `ai_docs/solutions/ANALYSIS_[feature].md`.
207
- - Minimum sections: Objective, Feature Vision (or Vision Alignment), Impact, Security and Threat Model, Action Plan, Test Strategy, Diary/Current State.
223
+ - Minimum sections: Objective, Feature Vision (or Vision Alignment), Use Cases / User Needs, Capability Ledger, Impact, Security and Threat Model, Action Plan, Test Strategy, Diary/Current State. (`review.md` makes an uncovered use-case a finding, so an ANALYSIS without that section fails its own closure review.)
208
224
  - Build the Impact/solution **on** the Vision, the use-cases/user-needs and the Security & Threat Model — read and trace to them first, and state the trace (which actor / use-case / threat / benefit each part serves) so the closure review (`review.md`) can verify conformance. Do not draft the Impact in isolation.
209
225
  - For a feature known to span multiple milestones, also create `ai_docs/vision/features/VISION_[feature].md`; the retroactive case (extract it when the SECOND `ANALYSIS_*` on a theme appears) is in Write Triggers.
210
226
 
227
+ **Design review gate — the design is reviewed BEFORE any code (L3).** Close Phase 3 by handing the finished ANALYSIS to an *independent* reviewer: the procedure, the independence ladder, the round cap and the log row are `review.md` §When a review is due, moment 1 — follow it there, it is not restated here. Why the moment exists: the closure review can prove the code matches the design, never that the design was right, and the author is structurally blind to what their own design omitted. In Hybrid this slot belongs to devPNT's §4.5 gate on the `E-ISP`/`E-TDD` — run one, never both.
228
+
211
229
  Hybrid L3:
212
230
  - Restore the Master Plan, Action Plan and linked documents.
213
231
  - Use devPNT for plans and governed artifacts.
@@ -215,11 +233,11 @@ Hybrid L3:
215
233
 
216
234
  ### 4. Development and Testing
217
235
 
218
- - Implement only after the documentation gate required by the level.
236
+ - Implement only after the documentation gate required by the level. **Flip the ANALYSIS frontmatter `PLANNED` → `IN_PROGRESS` when implementation starts** — that flip is what `gate` and the handoff registry key on, and nothing else performs it.
219
237
  - Isolate the work: run an L3 change on its own branch. In Hybrid, prefer a git worktree from the start — a running devPNT server locks `.devpnt/*.db` and blocks in-place branch switches/merges in the primary worktree.
220
238
  - Modify surgically, consistently with the plan.
221
239
  - Implementation work follows the TDD discipline in `tdd.md` (RED/GREEN/REFACTOR — the L2/L3 default; record the reason when it does not apply).
222
- - Before implementing (L2/L3; L1 exempt), **consult the guide router** for a guide covering the task — operative, or a comprehension map of the component you are about to touch — and read it first (the consult trigger, `guides.md` §0, summarized under `## Operative Guides`). A targeted description match, not a blanket read.
240
+ - Before implementing (L2/L3; L1 exempt), **consult the guide router** for a guide covering the task — operative, or a comprehension map of the component you are about to touch — and read it first (the consult trigger, `guides.md` §0, summarized under `## Operative Guides`). A targeted description match, not a blanket read. Its result is the router verdict already declared with the triage level (Rule Zero); re-run the lookup here only if the work has moved to a topic the first lookup did not cover, and say so if the verdict changes.
223
241
  - If the environment does not allow automated tests, declare the alternative verification and the reason.
224
242
  - For bugs (L2/L3), follow the systematic debugging method in `debugging.md`.
225
243
  - Circuit breaker: after 3 consecutive runs without progress on the tests, stop, switch to the systematic method in `debugging.md`, and ask for instructions if still stuck. `debugging.md` also covers **chronic fragility** — a component that breaks repeatedly across sessions is a comprehension + complexity signal (write the `source_kind: code` guide AND escalate a refactor), not a fourth patch.
@@ -232,8 +250,9 @@ Hybrid L3:
232
250
  - For the review itself follow `review.md` (requesting and receiving findings) — the single definition, intended for reuse by the Hybrid review gates (devPNT-side wiring out of this unit's scope).
233
251
  - Verify alignment with the local Vision or the devPNT M-VISION.
234
252
  - If the work was governed by user-provided indications and is reusable, **PROPOSE distilling a guide** (proactive trigger, `guides.md` §1) — a proposal for the user, never a silent write, never from model knowledge.
253
+ - **Comprehension checkpoint**: ask explicitly — *did this session force me to build a model of a high-complexity component that no CURRENT guide covers?* If yes, WRITE the `source_kind: code` guide now (a duty, not a proposal — `guides.md` §1) and say so in the closure. The knowledge you paid to build is at its most complete right here; one closure later it is gone, and the next session re-derives it or breaks the component from partial understanding.
235
254
  - Update only the documents actually impacted.
236
- - **Update `audit/handoff.md`** — mandatory at every L3 closure (Date, Branch, active features, next step; ≤ 20 lines). The session-end rule and the L2 case: Write Triggers.
255
+ - **Update the workstream registry (`audit/handoff.md`)** — mandatory at every L3 closure: REMOVE the closed workstream's row and DELETE its `audit/HANDOFF_[feature].md` (history lives in git and in the Diary); leave every other row untouched — that is the parallel-safety the registry exists for. ≤ 20 lines. The session-end rule and the L2 case: Write Triggers.
237
256
  - **Aligned indexes (Poka-Yoke)**: if you created, moved or removed canonical documents (`vision/`, `reference/`, `architecture/`, `functional/`, `strategic/`):
238
257
  - regenerate the manifest with `sdlc_check.py index` (writes `ai_docs/INDEX.md`) — never write it by hand;
239
258
  - if the document is a must-read, add/update its line in the curated `README.md`;
@@ -274,7 +293,7 @@ Legacy note: the validator also accepts the deprecated Italian frontmatter keys
274
293
  ## Operative Guides
275
294
 
276
295
  Guides are **consulted, created, proposed, and (for code) authored for comprehension** — four moments; the mechanics live once in `guides.md`. Two source kinds: `document` (user indications, operative) and `code` (a comprehension map of a complex component):
277
- - **Consult (before acting):** before operative L2/L3 work (L1 exempt), check the guide router for a guide covering the task and read the match first — a targeted description match, never a blanket read. → `guides.md` §0.
296
+ - **Consult (before acting):** before operative L2/L3 work (L1 exempt), check the guide router for a guide covering the task and read the match first — a targeted description match, never a blanket read. **Declare the verdict** on the same line as the triage level (Rule Zero): the lookup is only reliable when its result is visible. → `guides.md` §0.
278
297
  - **Create (from user indications):** the origin+purpose test below (`source_kind: document`).
279
298
  - **Propose proactively (after success):** after reusable, user-indication-governed work, PROPOSE distilling a guide — a proposal, never a silent write, never from model knowledge. → `guides.md` §1.
280
299
  - **Comprehend (code, autonomous):** when a component/feature/layer is high-complexity and no CURRENT guide covers it, it is your DUTY to WRITE a `source_kind: code` comprehension guide autonomously — no proposal (additive, code-anchored, reversible); every claim traces to a code excerpt. Signals + guard-rails: `guides.md` §1.