@antoneeo/agentic-sdlc-skill 1.49.0 → 1.51.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 +76 -0
- package/README.md +47 -16
- package/gemini-extension.json +1 -1
- package/package.json +2 -1
- package/skills/agentic-sdlc-skill/ENFORCEMENT.md +2 -1
- package/skills/agentic-sdlc-skill/SKILL.md +7 -6
- package/skills/agentic-sdlc-skill/coordination.md +139 -0
- package/skills/agentic-sdlc-skill/elicitation.md +5 -3
- package/skills/agentic-sdlc-skill/review.md +31 -1
- package/skills/agentic-sdlc-skill/scripts/sdlc_check.py +119 -2
- package/skills/agentic-sdlc-skill/scripts/sdlc_core.py +54 -14
- package/skills/agentic-sdlc-skill/templates.md +49 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,82 @@
|
|
|
2
2
|
|
|
3
3
|
Tutte le modifiche significative a questa skill saranno documentate in questo file.
|
|
4
4
|
|
|
5
|
+
## [1.51.0] - 2026-10-31
|
|
6
|
+
|
|
7
|
+
### What's new
|
|
8
|
+
|
|
9
|
+
**Several sessions can work on one repository, one of them coordinating.** When you run several agent sessions on the same project at once and tell one of them that it coordinates the others, they follow shared rules. Each request record has a single writer, so its entries are never numbered twice. A resource only one session can use at a time, such as the development container or the test database, is taken and released through the coordinator, so one session no longer restarts what another is running against. An authorization you gave one session is not passed to another by message. A session that stops reports what it did, and the coordinator checks it before telling you the work is done. Before a commit that carries several sessions' work, the coordinator checks that every changed file is assigned to the right unit. If you name no coordinator, nothing changes.
|
|
10
|
+
|
|
11
|
+
**Decisions taken on your behalf are labelled.** In the request record, a decision a session took under a delegation you gave it, and words you gave one session for work another session records, now carry their own heading. They are never read later as something you said yourself, and a delegated decision never overrides one of yours: a choice that would change it comes back to you as a question.
|
|
12
|
+
|
|
13
|
+
**The reminder of what must not break also covers files written from the shell.** From 1.49.0 the agent is reminded of a unit's constraints before it edits a file; a file it writes through a shell command never triggered that reminder, so the agent now looks the constraints up itself.
|
|
14
|
+
|
|
15
|
+
#### What to do
|
|
16
|
+
|
|
17
|
+
**1. Update (everyone).** The changes arrive only with the update.
|
|
18
|
+
1. Run `npm install -g @antoneeo/agentic-sdlc-skill@latest`, then `agentic-sdlc-install-skill`.
|
|
19
|
+
2. Close and reopen your agent sessions: the new version loads only at startup.
|
|
20
|
+
|
|
21
|
+
To check: `npm ls -g @antoneeo/agentic-sdlc-skill` shows 1.51.0.
|
|
22
|
+
|
|
23
|
+
**2. Coordinating several sessions (only if you run them in parallel).**
|
|
24
|
+
- **This concerns you if** you run more than one agent session on the same repository at the same time.
|
|
25
|
+
- **Why:** without a coordinator, sessions can write the same record at once, restart a container another session is using, or leave one commit nobody can split by unit.
|
|
26
|
+
- **Steps:** tell the session you want as coordinator, in your own words, that it coordinates the others; it records your words, and the rules apply from then on. Each other session asks it before using a shared resource. Before committing several sessions' work together, it writes the commit map and runs `sdlc_check.py commit-map <map file>`.
|
|
27
|
+
- **To check:** when a session takes a shared resource, `ai_docs/audit/leases.md` gains a `take` line naming it.
|
|
28
|
+
|
|
29
|
+
| New file | Skill | Who reads it |
|
|
30
|
+
|---|---|---|
|
|
31
|
+
| `coordination.md` | agentic-sdlc | the agent, only while several sessions share a repository |
|
|
32
|
+
|
|
33
|
+
### Added
|
|
34
|
+
- `coordination.md` (F-088): rules for several peer sessions on one repository once the owner names a coordinating session in a request-record entry — one writer per record (a part's owner words for the shared unit go through its own record and the coordinator), leases on exclusive resources in `audit/leases.md` (`take`/`release` lines, written by the coordinator only; a permission given before the naming exempts no session; the code-writer lease passes only once the holder's code is committed or set aside with the owner's yes), decisions under delegation recorded as labelled entries that never reach an earlier owner decision, authorizations valid only in the session they were given to, a fixed closure message per part (and, for a part that stopped without one, the coordinator reads its HANDOFF and working tree and tells the owner what it can and cannot tell), and the commit map. Rulings r40, r41.
|
|
35
|
+
- `sdlc_check.py commit-map MAP`: checks a commit map against the working tree against HEAD. Errors: a generated file under a unit, a changed authored file under Regenerated, a changed HANDOFF or request record in no section, a file under two units outside Shared, a file both under a unit and in Left out. Warnings: a change in no section, a listed file with no change. Exit 1 on any error.
|
|
36
|
+
|
|
37
|
+
### Changed
|
|
38
|
+
- Request record (`templates.md`): labelled entries `decided under delegation R<m>` and `received for <unit>`; `review.md` and `elicitation.md` treat them as the deciding session's choice or relayed words, never an owner statement (all four lenses).
|
|
39
|
+
- `SKILL.md` Phase 4: constraint recall asks the agent to run `constraints --file` itself for a file written from the shell, which the recall hook never sees; `ENFORCEMENT.md` §3 names the residual. Phase 4 also names the code-writer lease as the one exception to "own worktree" under coordination.
|
|
40
|
+
|
|
41
|
+
## [1.50.0] - 2026-10-31
|
|
42
|
+
|
|
43
|
+
### What's new
|
|
44
|
+
|
|
45
|
+
**You approve the design before any code is written.** On significant work, once the independent design review passes, the agent stops and shows you a short summary of the design: what the change does, for whom and through which surfaces, which files it touches, the risks and how they are handled, and what the review found. The work starts only after your yes, which the agent records in the unit's request record. A "go ahead" given before you saw the design does not count, and in a session with nobody to answer the unit waits for you. A design that is right but not what you meant is cheapest to fix before the code exists. If you work with devPNT, your acceptance of the design proposal there is this approval, and nothing else is asked.
|
|
46
|
+
|
|
47
|
+
**The npm page tells you what is new.** This section, at the top of the package page, now summarizes each version for the people who install it.
|
|
48
|
+
|
|
49
|
+
**From 1.49.0, published without notes:**
|
|
50
|
+
- **Fewer regressions on significant changes.** When an analysis states what must not break, the agent is reminded of it just before it edits that file, not only at the start of the work, and the reviewer has the list to check. It is a reminder and never blocks the work; for now it works on Claude Code.
|
|
51
|
+
- **The process checks can no longer be bypassed by accident.** Quoting a work level inside a sentence no longer counts as declaring it, and protected parts of the project stay protected when the agent changes folder.
|
|
52
|
+
- **You know what the project memory has not read yet.** The agent can tell how much of the project it has never examined (automatically in projects with a corpus, on request otherwise).
|
|
53
|
+
- **Defects found after the merge can be recorded** without distorting the review statistics.
|
|
54
|
+
|
|
55
|
+
#### What to do
|
|
56
|
+
|
|
57
|
+
**1. Update (everyone).** The changes arrive only with the update.
|
|
58
|
+
1. Run `npm install -g @antoneeo/agentic-sdlc-skill@latest`, then `agentic-sdlc-install-skill`.
|
|
59
|
+
2. Close and reopen your agent sessions: the new version loads only at startup.
|
|
60
|
+
|
|
61
|
+
To check: `npm ls -g @antoneeo/agentic-sdlc-skill` shows 1.50.0.
|
|
62
|
+
|
|
63
|
+
If you do not want the constraint reminder (Claude Code only, from 1.49.0): remove the entry that contains `constraints --hook` from `~/.claude/settings.json`. Later updates will not put it back.
|
|
64
|
+
|
|
65
|
+
**2. Approving the design (significant units).**
|
|
66
|
+
- **This concerns you if** you use the skill for significant (L3) work. Nothing to configure: after the design review passes, the agent asks whether to proceed. Answer yes to start the code, or say what to change; the design is then revised and, where the change touches what the review judged, reviewed again before you are asked again.
|
|
67
|
+
- **A unit already in progress.** Units started before 2026-10-31 are not affected. If a unit started on or after 2026-10-31 with an earlier version is already in progress or finished, `sdlc_check.py validate` shows a `[note]` saying it has `no design approval in its request record`. Why: the earlier version never asked you. To clear it, tell the agent that you approve the design as it was implemented; it records your words under a label that begins `design approved` (for example `design approved after implementation`). The note never fails a check, so you can also leave it.
|
|
68
|
+
- **To check:** on your next significant unit, the agent stops after the design review and asks you before any code starts.
|
|
69
|
+
|
|
70
|
+
**3. Protected folders in a repository with several `ai_docs/` (only if you use them; from 1.49.0).**
|
|
71
|
+
- **This concerns you if** your agent settings contain `gate --hook --protected` and the repository has more than one `ai_docs/` folder, for example a package with its own.
|
|
72
|
+
- **Why:** protected paths are now read from the `ai_docs/` nearest to the edited file. A path written from the repository root, such as `packages/api/src/auth`, no longer matches the files inside `packages/api`, so the agent could change them without an analysis.
|
|
73
|
+
- **Steps:** rewrite those paths from the package: `packages/api/src/auth` becomes `src/auth`. Note that `src/auth` then protects the folder with that name in every project that has its own `ai_docs/`.
|
|
74
|
+
- **To check:** in a session with no open analysis, ask the agent for a small change to a protected file. It must be refused.
|
|
75
|
+
|
|
76
|
+
### Changed
|
|
77
|
+
- After the design review's final PASS, an L3 unit stops: the agent presents a short summary of the design (what it does, for whom and through which surfaces, what it touches, threats, the review's verdict) and asks the owner whether to proceed. Only a yes, recorded in the request record under a label that begins `design approved`, moves the ANALYSIS to `IN_PROGRESS`. An instruction given before the design was shown is not an approval; unattended, the unit is `BLOCKED on the user`; in Hybrid the approval in devPNT counts. The rule is in `review.md`; `SKILL.md`, `elicitation.md` and `templates.md` point at it (F-087).
|
|
78
|
+
- The shared validator: `validate` notes an L3 ANALYSIS in implementation, started on or after 2026-10-31, whose request record holds no entry whose label begins `design approved`. It is a `[note]`: `--strict` exits as before. The `gate` refusal message adds that at L3 the ANALYSIS goes `IN_PROGRESS` only after the owner's design approval; its exit codes are unchanged (F-087).
|
|
79
|
+
- The package's npm page (its README) gains a "What's new in <version>" section right after the introduction, written for the people who install the package and linking the full CHANGELOG. It appears from the first version that carries one; each version's notes are the `### What's new` at the top of its CHANGELOG section (F-070). The "Shared project memory" section moves from the top of the page to just after the features, unchanged.
|
|
80
|
+
|
|
5
81
|
## [1.49.0] - 2026-10-27
|
|
6
82
|
|
|
7
83
|
### Added
|
package/README.md
CHANGED
|
@@ -1,22 +1,37 @@
|
|
|
1
1
|
# Agentic SDLC Skill for Claude Code, Gemini CLI, Google Antigravity & Codex
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`agentic-sdlc` is a Documentation-First SDLC protocol for AI coding agents. It supports Claude Code, Codex, Gemini CLI, Google Antigravity 2.0, Cursor/Windsurf-style project instructions, and optional devPNT governance.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
`recall "onboarding"` finds related metadata across domains; optional
|
|
9
|
-
`topics: [onboarding]` links documents by subject. Read the originals for authority,
|
|
10
|
-
status and evidence: discovery is not approval or proof of implementation.
|
|
5
|
+
<!-- whats-new:begin -->
|
|
6
|
+
<!-- generated by scripts/whats_new.js from CHANGELOG.md: edit the CHANGELOG, then run node scripts/whats_new.js --write -->
|
|
7
|
+
## What's new in 1.51.0
|
|
11
8
|
|
|
12
|
-
|
|
13
|
-
watcher. Existing projects acquire the catalog on their next `index`; `recall`
|
|
14
|
-
also sees live metadata. The KB lens remains the specialist for ingestion and
|
|
15
|
-
taxonomy. Marketing retains its numerical validators. See the skill's `memory.md`.
|
|
16
|
-
Vendoring requires all three files: the entry point, `sdlc_core.py`, `knowledge.py`.
|
|
9
|
+
**Several sessions can work on one repository, one of them coordinating.** When you run several agent sessions on the same project at once and tell one of them that it coordinates the others, they follow shared rules. Each request record has a single writer, so its entries are never numbered twice. A resource only one session can use at a time, such as the development container or the test database, is taken and released through the coordinator, so one session no longer restarts what another is running against. An authorization you gave one session is not passed to another by message. A session that stops reports what it did, and the coordinator checks it before telling you the work is done. Before a commit that carries several sessions' work, the coordinator checks that every changed file is assigned to the right unit. If you name no coordinator, nothing changes.
|
|
17
10
|
|
|
11
|
+
**Decisions taken on your behalf are labelled.** In the request record, a decision a session took under a delegation you gave it, and words you gave one session for work another session records, now carry their own heading. They are never read later as something you said yourself, and a delegated decision never overrides one of yours: a choice that would change it comes back to you as a question.
|
|
18
12
|
|
|
19
|
-
|
|
13
|
+
**The reminder of what must not break also covers files written from the shell.** From 1.49.0 the agent is reminded of a unit's constraints before it edits a file; a file it writes through a shell command never triggered that reminder, so the agent now looks the constraints up itself.
|
|
14
|
+
|
|
15
|
+
#### What to do
|
|
16
|
+
|
|
17
|
+
**1. Update (everyone).** The changes arrive only with the update.
|
|
18
|
+
1. Run `npm install -g @antoneeo/agentic-sdlc-skill@latest`, then `agentic-sdlc-install-skill`.
|
|
19
|
+
2. Close and reopen your agent sessions: the new version loads only at startup.
|
|
20
|
+
|
|
21
|
+
To check: `npm ls -g @antoneeo/agentic-sdlc-skill` shows 1.51.0.
|
|
22
|
+
|
|
23
|
+
**2. Coordinating several sessions (only if you run them in parallel).**
|
|
24
|
+
- **This concerns you if** you run more than one agent session on the same repository at the same time.
|
|
25
|
+
- **Why:** without a coordinator, sessions can write the same record at once, restart a container another session is using, or leave one commit nobody can split by unit.
|
|
26
|
+
- **Steps:** tell the session you want as coordinator, in your own words, that it coordinates the others; it records your words, and the rules apply from then on. Each other session asks it before using a shared resource. Before committing several sessions' work together, it writes the commit map and runs `sdlc_check.py commit-map <map file>`.
|
|
27
|
+
- **To check:** when a session takes a shared resource, `ai_docs/audit/leases.md` gains a `take` line naming it.
|
|
28
|
+
|
|
29
|
+
| New file | Skill | Who reads it |
|
|
30
|
+
|---|---|---|
|
|
31
|
+
| `coordination.md` | agentic-sdlc | the agent, only while several sessions share a repository |
|
|
32
|
+
|
|
33
|
+
Full history: [CHANGELOG](https://github.com/Antoneeo/agentic-sdlc-skill/blob/main/CHANGELOG.md)
|
|
34
|
+
<!-- whats-new:end -->
|
|
20
35
|
|
|
21
36
|
## Key Features
|
|
22
37
|
|
|
@@ -33,11 +48,26 @@ Vendoring requires all three files: the entry point, `sdlc_core.py`, `knowledge.
|
|
|
33
48
|
- **Self-activating**: a SessionStart hook emits repo-sourced orientation; a deterministic self-eval battery guards the skill's own doctrine as the release gate.
|
|
34
49
|
- **Standalone complete**: works fully with local `ai_docs/` without requiring devPNT.
|
|
35
50
|
- **devPNT symbiosis**: when devPNT is available, Master Plan, Action Plan, M-VISION, and governed artifacts become the authoritative planning layer, and every governed artifact passes an independent agent review before it is proposed; devPNT itself performs no review — it is where you review and approve.
|
|
36
|
-
- **Independent review, twice**: the design is reviewed before it is implemented and the diff before the work is declared done — by somebody other than its author, who receives the whole review mandate in a fixed block copied verbatim, never a paraphrase of it. Three rungs of independence (fresh-context subagent > one-shot run > a declared self-pass, legal only when no higher rung is usable: absent, or permission-gated and declined — a gated rung is asked about, never silently skipped, and the log says which), capped at 3 rounds, one log line per review, and a PASS is invalid on "found nothing" — it must state where each constraint is satisfied.
|
|
51
|
+
- **Independent review, twice**: the design is reviewed before it is implemented and the diff before the work is declared done — by somebody other than its author, who receives the whole review mandate in a fixed block copied verbatim, never a paraphrase of it. Three rungs of independence (fresh-context subagent > one-shot run > a declared self-pass, legal only when no higher rung is usable: absent, or permission-gated and declined — a gated rung is asked about, never silently skipped, and the log says which), capped at 3 rounds, one log line per review, and a PASS is invalid on "found nothing" — it must state where each constraint is satisfied. After the design review passes, the owner approves the design before any code is written.
|
|
37
52
|
- **Question discipline**: a real doubt is asked when it emerges, before its answer is written into any document — grouped, with the pros and cons of each option. A choice whose pros clearly win is taken without asking, and the weighing is written next to it; a fact is settled by evidence or asked, never weighed. A question is legal only when the agent searched first, names the search with its result, and names the decision it unblocks — never a stream of "shall I proceed?".
|
|
38
|
-
- **Installed support files**: Claude, Codex, Gemini, and Google Antigravity receive the full skill folder, including `templates.md`, `architect.md`, `guides.md`, `vision.md`, `tdd.md`, `debugging.md`, `elicitation.md`, `review.md`, `dispatch.md`, `routing.md`, `hybrid.md`, `ENFORCEMENT.md`, `memory.md`, and the validator's three files, `scripts/sdlc_check.py` + `scripts/sdlc_core.py` + `scripts/knowledge.py` — plus the docs site generator `scripts/docs_site.py` and its page `docs_site/`, and the `LICENSE` and `NOTICE` it ships under.
|
|
53
|
+
- **Installed support files**: Claude, Codex, Gemini, and Google Antigravity receive the full skill folder, including `templates.md`, `architect.md`, `guides.md`, `vision.md`, `tdd.md`, `debugging.md`, `elicitation.md`, `review.md`, `dispatch.md`, `routing.md`, `coordination.md`, `hybrid.md`, `ENFORCEMENT.md`, `memory.md`, and the validator's three files, `scripts/sdlc_check.py` + `scripts/sdlc_core.py` + `scripts/knowledge.py` — plus the docs site generator `scripts/docs_site.py` and its page `docs_site/`, and the `LICENSE` and `NOTICE` it ships under.
|
|
39
54
|
- **Docs site** (`scripts/docs_site.py --root <project> [--open] [--zip <file>]`): a static, offline, read-only website of what the agent reads in the project — reading guide, Vision, rules, documents, open work with each next step, analyses and, with a knowledge base, the topic map, each fact with its exact source passage, and the source documents. Written to `.docs-site/` (added to `.gitignore` on the first run), outside `ai_docs/`; nothing is ranked or recommended.
|
|
40
|
-
- **Mechanical checks**: optional validator for document structure, generated feature history, stale audit areas, and protected-path gates — `check`, `validate`, `index`, `stale`, `mark`, `benefit`, `gate`, `plan`, `orient`, `migrate`, `review-map` (code lens: classes the files of a change for the merge review brief), `constraints` (code lens: a unit's constraints, or those binding a file). `benefit` reports what the review gates have already caught, beside what the doctrine costs to read — it always exits 0 and carries no verdict, because a measurement that can fail a build becomes a target.
|
|
55
|
+
- **Mechanical checks**: optional validator for document structure, generated feature history, stale audit areas, and protected-path gates — `check`, `validate`, `index`, `stale`, `mark`, `benefit`, `gate`, `plan`, `orient`, `migrate`, `review-map` (code lens: classes the files of a change for the merge review brief), `commit-map` (code lens: checks the map of one commit carrying several parallel sessions' work), `constraints` (code lens: a unit's constraints, or those binding a file). `benefit` reports what the review gates have already caught, beside what the doctrine costs to read — it always exits 0 and carries no verdict, because a measurement that can fail a build becomes a target.
|
|
56
|
+
|
|
57
|
+
## Shared project memory
|
|
58
|
+
|
|
59
|
+
All four lenses include project memory by default; install the lens you need,
|
|
60
|
+
not a second skill just for recall. `index` registers guides, decisions and plans
|
|
61
|
+
in the docs root's `memory/INDEX.md`, linking originals without copying them.
|
|
62
|
+
`recall "onboarding"` finds related metadata across domains; optional
|
|
63
|
+
`topics: [onboarding]` links documents by subject. Read the originals for authority,
|
|
64
|
+
status and evidence: discovery is not approval or proof of implementation.
|
|
65
|
+
|
|
66
|
+
Registration happens at `index`/documentation closure, not through a background
|
|
67
|
+
watcher. Existing projects acquire the catalog on their next `index`; `recall`
|
|
68
|
+
also sees live metadata. The KB lens remains the specialist for ingestion and
|
|
69
|
+
taxonomy. Marketing retains its numerical validators. See the skill's `memory.md`.
|
|
70
|
+
Vendoring requires all three files: the entry point, `sdlc_core.py`, `knowledge.py`.
|
|
41
71
|
|
|
42
72
|
## Installation
|
|
43
73
|
|
|
@@ -104,6 +134,7 @@ skills/agentic-sdlc-skill/
|
|
|
104
134
|
├── review.md
|
|
105
135
|
├── dispatch.md
|
|
106
136
|
├── routing.md
|
|
137
|
+
├── coordination.md
|
|
107
138
|
├── hybrid.md
|
|
108
139
|
├── memory.md
|
|
109
140
|
├── ENFORCEMENT.md
|
package/gemini-extension.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@antoneeo/agentic-sdlc-skill",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.51.0",
|
|
4
4
|
"description": "Documentation-First SDLC protocol for Claude Code, Gemini CLI, Google Antigravity and Codex with risk triage, Vision governance, installed support files and optional devPNT integration.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude-code",
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
"skills/agentic-sdlc-skill/dispatch.md",
|
|
38
38
|
"skills/agentic-sdlc-skill/hybrid.md",
|
|
39
39
|
"skills/agentic-sdlc-skill/routing.md",
|
|
40
|
+
"skills/agentic-sdlc-skill/coordination.md",
|
|
40
41
|
"skills/agentic-sdlc-skill/ENFORCEMENT.md",
|
|
41
42
|
"skills/agentic-sdlc-skill/scripts/sdlc_check.py",
|
|
42
43
|
"skills/agentic-sdlc-skill/scripts/sdlc_core.py",
|
|
@@ -130,7 +130,8 @@ is the one holding the edited file, never the hook's working directory.
|
|
|
130
130
|
It informs and never decides: its JSON carries `additionalContext` only, never a
|
|
131
131
|
`permissionDecision`, so the user's permission flow is the one without it. It is silent
|
|
132
132
|
everywhere else and whenever it cannot tell (subagent, oversized or unreadable
|
|
133
|
-
transcript, any error), and always exits 0.
|
|
133
|
+
transcript, any error), and always exits 0. A file written from the shell never reaches
|
|
134
|
+
it: for that file the agent runs `constraints --file` itself (SKILL.md Phase 4).
|
|
134
135
|
|
|
135
136
|
Cost: up to 15 lines of context on a bound edit at L3 (owner-accepted,
|
|
136
137
|
`REQUEST_working_model.md` R12 (b)), zero tokens at any other level; and about 0.25 s
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: agentic-sdlc
|
|
3
|
-
version: 1.
|
|
3
|
+
version: 1.51.0
|
|
4
4
|
description: Documentation-First SDLC protocol with risk-proportional triage, Vision as a guide, a complete Standalone mode and optional symbiosis with devPNT. Use for features, significant bugs, refactors, audits and documented maintenance.
|
|
5
5
|
author: Antonio Pinto (https://github.com/Antoneeo)
|
|
6
6
|
copyright: (c) 2026 Antonio Pinto
|
|
@@ -20,6 +20,7 @@ Support files in the skill directory:
|
|
|
20
20
|
- `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.
|
|
21
21
|
- `hybrid.md`: the devPNT seam — the authoritative hierarchy, the ownership matrix (who owns what when both authorities are live), the triage equivalence, the feature-state mapping and the shadow discipline. Read it when the `devpnt_*` tools point at this project; a Standalone session never needs it.
|
|
22
22
|
- `routing.md`: which lens owns this unit of work. Read ONLY when a sibling lens skill is installed alongside this one; a single-lens install never reads it.
|
|
23
|
+
- `coordination.md`: several sessions on one repository, one of them coordinating. Read ONLY when the owner has named a coordinating session; otherwise never.
|
|
23
24
|
- `scripts/sdlc_check.py` + `scripts/sdlc_core.py`: the mechanical validator for the docs root (`check`, `validate`, `index`, `stale`, `mark`, `benefit`, `gate`, `plan`, `orient`, `migrate`). Keep the entry point, `scripts/sdlc_core.py` and `scripts/knowledge.py` together; the last supplies common memory and KB integrity.
|
|
24
25
|
- `scripts/docs_site.py --root <project> --open` (`--zip <file>` to share): opens in the user's browser a read-only site of what the agent reads; use it to show the project state.
|
|
25
26
|
It is what users mean by "docs site", "minisito", "documentation site" or "project site": run it, never build a page by hand.
|
|
@@ -86,7 +87,7 @@ Triage decides IF documentation is due; this table decides WHICH document each e
|
|
|
86
87
|
| Document | Write trigger | Phase |
|
|
87
88
|
|---|---|---|
|
|
88
89
|
| `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 revision re-reads the WHOLE document and rewrites it to current state (history in the Diary), never an appended delta section. 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 |
|
|
89
|
-
| `audit/requests/REQUEST_[feature].md` | Every L3, the moment the level is declared — before the Vision Gate and the first question: R1 quotes the owner's opening words verbatim; every later owner statement that settles something for the unit (answer, approval, cost, ruling, merge) is appended before acting on it. Append-only, never deleted; artifacts cite its entries, a paraphrase never replacing the citation (`templates.md`). | 1 → 5 |
|
|
90
|
+
| `audit/requests/REQUEST_[feature].md` | Every L3, the moment the level is declared — before the Vision Gate and the first question: R1 quotes the owner's opening words verbatim; every later owner statement that settles something for the unit (answer, approval, cost, ruling, merge) is appended before acting on it. Append-only, never deleted; artifacts cite its entries, a paraphrase never replacing the citation (`templates.md`). Under coordination, which record an entry goes to: `coordination.md` §1. | 1 → 5 |
|
|
90
91
|
| `solutions/SPIKE_[topic].md` | Closing any Spike — including a failed one (a negative outcome is still an outcome). | — |
|
|
91
92
|
| `solutions/E2E_TEST_[feature].md` | Every L3, before the closure review (it is part of the reviewed diff): the human tester's post-merge script — new-behavior scenarios when behavior changed, regression scenarios always (`templates.md`). | 5 |
|
|
92
93
|
| `solutions/MERGE_REVIEW_[feature].md` | Every L3, after the closure review: the integrator's brief — what to review (`sdlc_check.py review-map`), what was verified by which gate, what only a human can judge (`templates.md`). The PR description links it. | 5 |
|
|
@@ -195,7 +196,7 @@ Standalone L3:
|
|
|
195
196
|
- Build the Impact/solution **on** the Vision, the use-cases/user-needs and the Security & Threat Model — read and trace to them first, and state the trace (which actor / use-case / threat / benefit each part serves) so the closure review (`review.md`) can verify conformance. Do not draft the Impact in isolation.
|
|
196
197
|
- For a feature known to span multiple milestones, also create `ai_docs/vision/features/VISION_[feature].md`; the retroactive case (extract it when the SECOND `ANALYSIS_*` on a theme appears) is in Write Triggers.
|
|
197
198
|
|
|
198
|
-
**Design review gate — the design is reviewed BEFORE any code (L3).** Close Phase 3 by handing the finished ANALYSIS to an *independent* reviewer: the procedure, the independence ladder, the round cap and the log row are `review.md` §When a review is due, moment 1 — follow it there, it is not restated here. Why the moment exists: the closure review can prove the code matches the design, never that the design was right, and the author is structurally blind to what their own design omitted. In Hybrid the same review runs on the `E-ISP`/`E-TDD`, by the client's agent, and its PASS precedes the proposal to devPNT, where the human reviews — `review.md` §When a review is due owns the order.
|
|
199
|
+
**Design review gate — the design is reviewed BEFORE any code (L3).** Close Phase 3 by handing the finished ANALYSIS to an *independent* reviewer: the procedure, the independence ladder, the round cap and the log row are `review.md` §When a review is due, moment 1 — follow it there, it is not restated here. Why the moment exists: the closure review can prove the code matches the design, never that the design was right, and the author is structurally blind to what their own design omitted. In Hybrid the same review runs on the `E-ISP`/`E-TDD`, by the client's agent, and its PASS precedes the proposal to devPNT, where the human reviews — `review.md` §When a review is due owns the order. In Standalone the final PASS is followed by the owner's approval of the design, asked and recorded before any code (same section).
|
|
199
200
|
|
|
200
201
|
Hybrid L3:
|
|
201
202
|
- Restore the Master Plan, Action Plan and linked documents.
|
|
@@ -206,13 +207,13 @@ Hybrid L3:
|
|
|
206
207
|
|
|
207
208
|
### 4. Development and Testing
|
|
208
209
|
|
|
209
|
-
- Implement only after the documentation gate required by the level. **Flip the ANALYSIS frontmatter `PLANNED` → `IN_PROGRESS` when implementation starts** — that flip is what `gate` and the handoff registry key on, and nothing else performs it.
|
|
210
|
-
- Isolate the work: run an L3 change on its own branch. In Hybrid, prefer a git worktree from the start — a running devPNT server locks `.devpnt/*.db` and blocks in-place branch switches/merges in the primary worktree. A session that may run while another session uses the same checkout works in its **own git worktree**, and never switches branch, stashes, resets or runs `index` in a checkout another session may be using. Parallel work also shares ids: choose a new unit's id **after fetching**, as the first id free on every branch and tag the checkout can see (`check` names a collision while the unit is open).
|
|
210
|
+
- Implement only after the documentation gate required by the level; at L3 it ends with the owner's design approval (`review.md` §When a review is due). **Flip the ANALYSIS frontmatter `PLANNED` → `IN_PROGRESS` when implementation starts** — that flip is what `gate` and the handoff registry key on, and nothing else performs it.
|
|
211
|
+
- Isolate the work: run an L3 change on its own branch. In Hybrid, prefer a git worktree from the start — a running devPNT server locks `.devpnt/*.db` and blocks in-place branch switches/merges in the primary worktree. A session that may run while another session uses the same checkout works in its **own git worktree**, and never switches branch, stashes, resets or runs `index` in a checkout another session may be using; under coordination, the code-writer lease is the one exception (`coordination.md` §2). Parallel work also shares ids: choose a new unit's id **after fetching**, as the first id free on every branch and tag the checkout can see (`check` names a collision while the unit is open).
|
|
211
212
|
- Modify surgically, consistently with the plan.
|
|
212
213
|
- Implementation work follows the TDD discipline in `tdd.md` (RED/GREEN/REFACTOR — the L2/L3 default; record the reason when it does not apply).
|
|
213
214
|
- Before implementing (L2/L3; L1 exempt), **consult the guide router** — the verdict already declared with the triage level (`## Operative Guides`). Re-run the lookup here only if the work has moved to a topic the first one did not cover, and say so if the verdict changes.
|
|
214
215
|
- If the environment does not allow automated tests, declare the alternative verification and the reason.
|
|
215
|
-
- **Constraint recall (L3).** Where the recall hook is wired (`ENFORCEMENT.md` §3), an edit of a file the open unit's constraints bind shows them first. Without it, run `sdlc_check.py constraints --file <path>` before its first edit of a file in a session.
|
|
216
|
+
- **Constraint recall (L3).** Where the recall hook is wired (`ENFORCEMENT.md` §3), an edit of a file the open unit's constraints bind shows them first. Without it — or for a file you write from the shell, which the hook never sees — run `sdlc_check.py constraints --file <path>` before its first edit of a file in a session.
|
|
216
217
|
- For bugs (L2/L3), continue the investigation and design-verification method in `debugging.md`; implementation follows the `tdd.md` discipline above.
|
|
217
218
|
- 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.
|
|
218
219
|
- Update the ANALYSIS Diary or the Action Plan when you complete milestones, hit blockers, change decisions, or a session ends with work unfinished.
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Coordinating Parallel Sessions
|
|
2
|
+
|
|
3
|
+
Rules for several peer sessions working on one repository at once, one of them
|
|
4
|
+
coordinating. Read this only when they apply (§Trigger); a session that is not
|
|
5
|
+
coordinated never needs it.
|
|
6
|
+
|
|
7
|
+
## Trigger and roles
|
|
8
|
+
|
|
9
|
+
The rules apply while more than one session works on the same repository **and**
|
|
10
|
+
the owner has named the coordinating session in a request-record entry. The skill
|
|
11
|
+
never elects a coordinator. Without that naming no session coordinates: each works
|
|
12
|
+
in its own worktree, asks the owner before using an exclusive resource, and appends
|
|
13
|
+
to no record it does not own.
|
|
14
|
+
|
|
15
|
+
- **Coordinator** — the session the owner named. It keeps the shared files below,
|
|
16
|
+
writes the record of the shared unit, and acts for the owner only within what the
|
|
17
|
+
owner delegated.
|
|
18
|
+
- **Part** — a peer session the owner can talk to, working on its own unit and
|
|
19
|
+
following the whole skill for it (triage, design, review, closure). It is not a
|
|
20
|
+
dispatched subagent: `dispatch.md` governs those, unchanged.
|
|
21
|
+
|
|
22
|
+
Out of scope: which part runs next, in what order, with what priority — the owner
|
|
23
|
+
decides that, and nothing here records it (Non-Goal 1, ruling r3).
|
|
24
|
+
|
|
25
|
+
## 1. Every record has one writer
|
|
26
|
+
|
|
27
|
+
A request record numbers its entries; two writers number them twice (field case:
|
|
28
|
+
three sessions wrote R156–R158 into one record at once). So:
|
|
29
|
+
|
|
30
|
+
- A part's unit has its own record when its triage gives it one (every L3); the
|
|
31
|
+
part is its only writer.
|
|
32
|
+
- The record of the shared unit the parts serve — the milestone, the umbrella — is
|
|
33
|
+
written only by the coordinator.
|
|
34
|
+
- Owner words a part receives are recorded **before it acts on them**, in the record
|
|
35
|
+
of the unit they settle. Words settling the part's own unit go to its own record.
|
|
36
|
+
Words settling the shared unit are appended verbatim to the part's own record
|
|
37
|
+
under the received heading (`templates.md` §REQUEST) and sent to the coordinator,
|
|
38
|
+
which appends them verbatim to the shared record citing
|
|
39
|
+
`REQUEST_[part].md#R<n>`.
|
|
40
|
+
- A part with no record of its own (below L3) sends the words; the coordinator's
|
|
41
|
+
shared entry names that part and the date received, and the part acts once it
|
|
42
|
+
exists.
|
|
43
|
+
- Every such entry keeps every rule of the record: verbatim, redaction, the owner
|
|
44
|
+
told so they can correct a quotation.
|
|
45
|
+
- An artifact of the shared unit cites only the shared record: the coordinator
|
|
46
|
+
enters the words before any such artifact relies on them.
|
|
47
|
+
|
|
48
|
+
## 2. Leases on exclusive resources
|
|
49
|
+
|
|
50
|
+
An exclusive resource has one holder at a time: the development container, the test
|
|
51
|
+
database, the code-writer role in a checkout a runtime mounts, any other the owner
|
|
52
|
+
names. A part asks the coordinator; the coordinator appends to `audit/leases.md`:
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
take <resource> — <session> — YYYY-MM-DD
|
|
56
|
+
release <resource> — <session> — YYYY-MM-DD
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The file opens by citing the entry that names the coordinator; only the coordinator
|
|
60
|
+
writes it. A lease names a resource and a session, never a unit; it keeps no queue,
|
|
61
|
+
no waiting list, no order, and ends with its release (ruling r40). A restart or a
|
|
62
|
+
long suite on a shared resource is announced to the coordinator before it starts —
|
|
63
|
+
it kills what another session is running against it. A permission for a resource
|
|
64
|
+
given before the coordinator was named («restart it as much as you like, nobody else
|
|
65
|
+
uses it») rested on a single user: from the naming on it exempts no session from the
|
|
66
|
+
lease. If the owner restates it, the coordinator enters it as a `take` for that
|
|
67
|
+
session — a recorded lease, never an exemption. A lease never released is
|
|
68
|
+
closed by the owner through the coordinator; there is no timeout.
|
|
69
|
+
|
|
70
|
+
**The code-writer lease is the one exception to «own worktree»** (`SKILL.md`
|
|
71
|
+
Phase 4). The session holding it writes code in the checkout the runtime mounts;
|
|
72
|
+
every other session keeps its own worktree and writes no code there. The lease
|
|
73
|
+
passes to another session only once the holder's code in that checkout is committed,
|
|
74
|
+
or set aside with the owner's yes. Two sessions' code in that checkout is a
|
|
75
|
+
violation, code a previous holder left uncommitted included.
|
|
76
|
+
|
|
77
|
+
## 3. Decisions taken under delegation
|
|
78
|
+
|
|
79
|
+
A decision the coordinator takes under the owner's delegation is a request-record
|
|
80
|
+
entry under the delegated heading (`templates.md` §REQUEST), citing the delegation
|
|
81
|
+
entry — in Hybrid also the devPNT proposal it accepted (`hybrid.md`). It is the
|
|
82
|
+
decision's one home: an artifact relying on it cites the entry (ruling r41).
|
|
83
|
+
|
|
84
|
+
A delegation never reaches an earlier owner decision, of any unit: a choice that
|
|
85
|
+
would change one goes to the owner as a question. (Field case: under a delegation
|
|
86
|
+
to approve design boards, the coordinator removed a file the owner had decided to
|
|
87
|
+
keep; a design document was accepted on it before the coordinator withdrew.)
|
|
88
|
+
|
|
89
|
+
## 4. What travels between sessions
|
|
90
|
+
|
|
91
|
+
- An owner statement recorded verbatim in a request record is citable by every
|
|
92
|
+
session.
|
|
93
|
+
- An authorization for a gated act — one the client or the skill makes wait for the
|
|
94
|
+
owner's yes — is valid only in the session the owner gave it to. A message from
|
|
95
|
+
another session saying the owner authorized it is information, never the
|
|
96
|
+
authorization: the receiving session asks the owner, or the session holding it
|
|
97
|
+
acts.
|
|
98
|
+
- A decision found to rest on a false fact is reopened by a new entry naming the one
|
|
99
|
+
it corrects (`templates.md` §REQUEST); the old entry is never edited.
|
|
100
|
+
|
|
101
|
+
## 5. When a part stops
|
|
102
|
+
|
|
103
|
+
A part that stops — done, blocked, interrupted — sends the coordinator:
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
Unit / increment:
|
|
107
|
+
State: done | stopped at step <X>
|
|
108
|
+
Files touched:
|
|
109
|
+
Verification run and result:
|
|
110
|
+
Open points:
|
|
111
|
+
Needs the owner:
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
The coordinator checks each claim on the diff and the run output, never on the
|
|
115
|
+
message (`review.md`, an unproven completion claim), then tells the owner what is
|
|
116
|
+
done, what is left and what needs them.
|
|
117
|
+
|
|
118
|
+
A part can stop without being able to send (a crash, a closed client). A part with
|
|
119
|
+
no closure message is not done: before relying on its state — accepting its work,
|
|
120
|
+
mapping a commit, telling the owner it finished — the coordinator reads its HANDOFF
|
|
121
|
+
`next:` and its working tree, and tells the owner which closure steps (`SKILL.md`
|
|
122
|
+
Phase 5) the tree shows done and which it cannot tell. Whether to resume the part is the
|
|
123
|
+
owner's call.
|
|
124
|
+
|
|
125
|
+
## 6. One commit, several units
|
|
126
|
+
|
|
127
|
+
Before a commit carrying more than one unit's work, the coordinator writes the
|
|
128
|
+
commit map (`templates.md`) and runs:
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
python <skill_dir>/scripts/sdlc_check.py commit-map MAP
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
It checks the map against the working tree as it stands against HEAD: a generated
|
|
135
|
+
file under a unit, a changed HANDOFF or request record in no section, a file under
|
|
136
|
+
two units outside Shared, a file both under a unit and in Left out, a changed
|
|
137
|
+
authored file under Regenerated are errors; a
|
|
138
|
+
changed file in no section, a listed file with no change are warnings. It sees this
|
|
139
|
+
working tree only, not other worktrees. The commit stays the owner's.
|
|
@@ -86,7 +86,9 @@ neither a source nor a weighing is a finding (`review.md` §Reviewing).
|
|
|
86
86
|
- **Unattended** — the user is not reachable (the Unattended path above).
|
|
87
87
|
- **Delegated** — the user's own words handed you this choice ("your call"); cite
|
|
88
88
|
their entry in the request record, or quote them where the unit has none (below
|
|
89
|
-
L3). A general "go ahead" is not a delegation.
|
|
89
|
+
L3). A general "go ahead" is not a delegation. A choice you make under it goes, where the
|
|
90
|
+
unit has a request record, into it as a delegated entry (`templates.md` §REQUEST) and the artifact
|
|
91
|
+
cites that entry; it never changes an earlier decision of theirs — ask instead.
|
|
90
92
|
|
|
91
93
|
Each states **what it is taken from** and **the alternative it excludes**, and is
|
|
92
94
|
listed where the user will read it: an assumption recorded alone is a decision
|
|
@@ -126,8 +128,8 @@ Never legal:
|
|
|
126
128
|
|
|
127
129
|
What questions are FOR — what the user uniquely owns: the benefit, priorities
|
|
128
130
|
between conflicting goods, non-goals, acceptance, and the approvals doctrine
|
|
129
|
-
reserves to them (Vision promotion and amendment,
|
|
130
|
-
acceptance, merge decisions). Facts about intent come from the user; facts about
|
|
131
|
+
reserves to them (Vision promotion and amendment, design approval at L3, scope
|
|
132
|
+
changes, proposal acceptance, merge decisions). Facts about intent come from the user; facts about
|
|
131
133
|
the system come from search.
|
|
132
134
|
|
|
133
135
|
**Precedence, because both halves can fire at once:** this paragraph wins over
|
|
@@ -198,6 +198,34 @@ is a belief: the row would say a gate ran and never whether it could do its job,
|
|
|
198
198
|
the correlation with `revise_rounds` and `findings_real` — the only evidence the
|
|
199
199
|
policy pays — could not be drawn.
|
|
200
200
|
|
|
201
|
+
**The owner approves the design before the work starts (L3).** The reviewer judges
|
|
202
|
+
whether the design holds and serves the Vision; only the owner can say whether it is
|
|
203
|
+
what they meant beyond what the Vision wrote, and an intent error costs least before
|
|
204
|
+
the work exists. So the final design PASS — final once any scoped re-review it owed
|
|
205
|
+
has passed (§Review-driven corrections) — does not start the work: the agent
|
|
206
|
+
presents the design and asks the owner whether to proceed, in the form
|
|
207
|
+
`elicitation.md` §The form of a question gives a reserved approval. The presentation
|
|
208
|
+
is a short summary — what the change does (the Functional Spec, or the lens's
|
|
209
|
+
equivalent), for whom and through which surfaces (use cases, contract), what it
|
|
210
|
+
touches (Impact), the threats and their mitigations, the review's verdict with any
|
|
211
|
+
open findings — and the path of the full design. At the round cap, the hand-over the
|
|
212
|
+
cap prescribes, followed by this one question, takes the place of the form, and the
|
|
213
|
+
owner's answer settles both. An approval is recorded verbatim in the request record
|
|
214
|
+
under a label that begins `design approved`; a no or a correction takes its own
|
|
215
|
+
label, and the design goes back — where the revision changes what the review judged,
|
|
216
|
+
moment 1 runs again on that part first (the delta rule above). Only after the
|
|
217
|
+
approval does the ANALYSIS go `PLANNED` → `IN_PROGRESS` and the work start: code,
|
|
218
|
+
drafting or production, by lens. An instruction given before the design was shown
|
|
219
|
+
("carry on", "do the whole unit") does not approve it. Where a lens's own phases
|
|
220
|
+
already have the owner approve the design — the marketing lens's strategy USER GATE
|
|
221
|
+
— that gate is this approval, never a second question, and the lens's own unattended
|
|
222
|
+
path applies. Otherwise, unattended, the unit is `BLOCKED on the user`
|
|
223
|
+
(`elicitation.md` Unattended path), never approved by assumption; a late arrival
|
|
224
|
+
(moment 1b) asks before any further work. Hybrid: the owner's approval of the
|
|
225
|
+
`E-ISP`/`E-TDD` proposal in devPNT, under devPNT's own authorization rules, is this
|
|
226
|
+
approval. In Standalone, `validate` notes an L3 ANALYSIS in implementation, started
|
|
227
|
+
on or after 2026-10-31, whose request record holds no `design approved` entry.
|
|
228
|
+
|
|
201
229
|
**One schema for both modes**, meaning one required CORE plus each mode's own
|
|
202
230
|
**mode-specific** realization columns. The core is what both modes actually share: `date`, `doc_key`,
|
|
203
231
|
`tier`, `model`, `findings_raised`, `findings_real`, `verdict`, `revise_rounds`.
|
|
@@ -439,7 +467,9 @@ When you are the reviewer:
|
|
|
439
467
|
the artifact relies on — an answer, an approval, a cost acceptance, a ruling, a
|
|
440
468
|
delegation — that resolves to no entry of the unit's request record, or that the
|
|
441
469
|
record contradicts, is a finding; so is a quotation in the record carrying what
|
|
442
|
-
its template says to redact
|
|
470
|
+
its template says to redact, a delegated entry citing no delegation or changing
|
|
471
|
+
an earlier owner decision, and an artifact of a shared unit citing a received
|
|
472
|
+
entry instead of the shared record (`templates.md` §REQUEST, labelled entries). What makes a ground
|
|
443
473
|
or an assumption legal is each lens's `elicitation.md` §The question discipline —
|
|
444
474
|
cite it, never restate it. The fix is the question, not a better justification.
|
|
445
475
|
- **Restated facts (cite, never copy).** Every governance slot has ONE owning document
|
|
@@ -41,7 +41,7 @@ sdlc_core.set_profile(
|
|
|
41
41
|
unit_noun="feature",
|
|
42
42
|
support_files=("templates.md", "architect.md", "guides.md", "vision.md", "tdd.md",
|
|
43
43
|
"debugging.md", "elicitation.md", "review.md", "dispatch.md",
|
|
44
|
-
"routing.md", "hybrid.md", "ENFORCEMENT.md", "memory.md"),
|
|
44
|
+
"routing.md", "coordination.md", "hybrid.md", "ENFORCEMENT.md", "memory.md"),
|
|
45
45
|
capabilities=(
|
|
46
46
|
# spine
|
|
47
47
|
"triage", "write_triggers", "workstream_registry", "vision_gate",
|
|
@@ -84,7 +84,11 @@ REVIEW_INSTRUCTIONS = {
|
|
|
84
84
|
REVIEW_MAP_HELP = ("\nCode lens:\n review-map [--base REF] [--root DIR] [--docs-dir NAME]\n"
|
|
85
85
|
" classify every file changed since the merge-base with REF "
|
|
86
86
|
"(default main):\n REVIEW / DESIGN / EVIDENCE / GENERATED, "
|
|
87
|
-
"as a markdown table for the merge review brief"
|
|
87
|
+
"as a markdown table for the merge review brief\n"
|
|
88
|
+
" commit-map MAP [--root DIR] [--docs-dir NAME]\n"
|
|
89
|
+
" check a commit map (one commit carrying several units' work, "
|
|
90
|
+
"templates.md)\n against the working tree as it stands against "
|
|
91
|
+
"HEAD; sees this working tree only,\n not other worktrees")
|
|
88
92
|
|
|
89
93
|
|
|
90
94
|
def table_cell(text):
|
|
@@ -268,10 +272,123 @@ def cmd_review_map(argv):
|
|
|
268
272
|
return 0
|
|
269
273
|
|
|
270
274
|
|
|
275
|
+
# ------------------------------------------------------------- commit-map (F-088)
|
|
276
|
+
# The coordinator's map of ONE commit carrying several units' work: a section per
|
|
277
|
+
# unit, Shared, Regenerated, Left out. The grouping is a judgement, so the map is
|
|
278
|
+
# hand-written; this checks only what a tree can contradict. The base is HEAD:
|
|
279
|
+
# the map describes the next commit, not the branch. Paths from the map are
|
|
280
|
+
# compared with git's list as text, never opened.
|
|
281
|
+
|
|
282
|
+
COMMIT_MAP_SPECIAL = {"shared": "shared", "regenerated": "regenerated",
|
|
283
|
+
"left out": "left_out"}
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
def parse_commit_map(text):
|
|
287
|
+
"""{path: [section, ...]} where a section is a unit heading, or one of
|
|
288
|
+
'shared' / 'regenerated' / 'left_out'. An item is a list line whose first
|
|
289
|
+
code span is the path; text after it (a reason, the units sharing it) is free."""
|
|
290
|
+
import re
|
|
291
|
+
listed, section = {}, None
|
|
292
|
+
for line in text.splitlines():
|
|
293
|
+
if line.startswith("## "):
|
|
294
|
+
head = line[3:].strip()
|
|
295
|
+
section = COMMIT_MAP_SPECIAL.get(head.lower(), head)
|
|
296
|
+
continue
|
|
297
|
+
m = re.match(r"^\s*[-*] +`([^`]+)`", line)
|
|
298
|
+
if m and section is not None:
|
|
299
|
+
path = m.group(1).strip().replace("\\", "/")
|
|
300
|
+
while path.startswith("./"):
|
|
301
|
+
path = path[2:]
|
|
302
|
+
listed.setdefault(path, []).append(section)
|
|
303
|
+
return listed
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
def cmd_commit_map(argv):
|
|
307
|
+
import argparse
|
|
308
|
+
ap = argparse.ArgumentParser(prog="sdlc_check.py commit-map")
|
|
309
|
+
ap.add_argument("map")
|
|
310
|
+
ap.add_argument("--root")
|
|
311
|
+
ap.add_argument("--docs-dir", dest="docs_dir")
|
|
312
|
+
args = ap.parse_args(argv)
|
|
313
|
+
map_path = Path(args.map).resolve()
|
|
314
|
+
try:
|
|
315
|
+
text = map_path.read_text(encoding="utf-8")
|
|
316
|
+
except (OSError, UnicodeDecodeError) as exc:
|
|
317
|
+
print(f"[ERROR] cannot read the commit map {table_cell(args.map)}: {exc}")
|
|
318
|
+
return 1
|
|
319
|
+
try:
|
|
320
|
+
discovered, name = sdlc_core.resolve_docs_dir(args, args.root)
|
|
321
|
+
except sdlc_core.AmbiguousDocsRoot as exc:
|
|
322
|
+
print(f"[ERROR] {exc}")
|
|
323
|
+
return 1
|
|
324
|
+
sdlc_core.set_docs_dir(name)
|
|
325
|
+
root = Path(args.root).resolve() if args.root else (discovered or sdlc_core.find_project_root())
|
|
326
|
+
if not sdlc_core.require_ai_docs(root, "commit-map"):
|
|
327
|
+
return 1
|
|
328
|
+
top = _git(root, "rev-parse", "--show-toplevel")
|
|
329
|
+
if top.returncode != 0:
|
|
330
|
+
print(f"[ERROR] {root} is not inside a git repository: commit-map compares the map with HEAD.")
|
|
331
|
+
return 1
|
|
332
|
+
top = Path(top.stdout.strip()).resolve()
|
|
333
|
+
if _git(top, "rev-parse", "--verify", "--quiet", "HEAD^{commit}").returncode != 0:
|
|
334
|
+
print("[ERROR] the repository has no commit yet: commit-map compares the map with HEAD.")
|
|
335
|
+
return 1
|
|
336
|
+
docs = sdlc_core.ai_path(root).resolve()
|
|
337
|
+
try:
|
|
338
|
+
docs_prefix = docs.relative_to(top).as_posix()
|
|
339
|
+
except ValueError:
|
|
340
|
+
print(f"[ERROR] {docs} is outside the git repository {top}.")
|
|
341
|
+
return 1
|
|
342
|
+
try:
|
|
343
|
+
own = map_path.relative_to(top).as_posix()
|
|
344
|
+
except ValueError:
|
|
345
|
+
own = None
|
|
346
|
+
changed = {p for _c, p, _a, _d in _changes(top, "HEAD") if p != own}
|
|
347
|
+
generated = set()
|
|
348
|
+
if any(classify_path(p, docs_prefix, set()) != "REVIEW" for p in changed):
|
|
349
|
+
generated = _generated_set(docs)
|
|
350
|
+
if generated is None:
|
|
351
|
+
return 1
|
|
352
|
+
listed = parse_commit_map(text)
|
|
353
|
+
special = set(COMMIT_MAP_SPECIAL.values())
|
|
354
|
+
errors, warnings = [], []
|
|
355
|
+
for path in sorted(set(changed) | set(listed)):
|
|
356
|
+
sections = listed.get(path, [])
|
|
357
|
+
units = [s for s in sections if s not in special]
|
|
358
|
+
is_generated = classify_path(path, docs_prefix, generated) == "GENERATED"
|
|
359
|
+
rel = path[len(docs_prefix) + 1:] if path.startswith(docs_prefix + "/") else ""
|
|
360
|
+
if units and is_generated:
|
|
361
|
+
errors.append((path, "regenerated by the validator, listed under a unit: "
|
|
362
|
+
"move it to Regenerated"))
|
|
363
|
+
if len(set(units)) > 1 and "shared" not in sections:
|
|
364
|
+
errors.append((path, "under " + ", ".join(sorted(set(units)))
|
|
365
|
+
+ " outside Shared: move it to Shared"))
|
|
366
|
+
if units and "left_out" in sections:
|
|
367
|
+
errors.append((path, "both under a unit and in Left out"))
|
|
368
|
+
if "regenerated" in sections and path in changed and not is_generated:
|
|
369
|
+
errors.append((path, "under Regenerated, but the validator does not write it: "
|
|
370
|
+
"list it under its unit"))
|
|
371
|
+
if path in changed and not sections:
|
|
372
|
+
if rel.startswith("audit/HANDOFF_") or rel.startswith("audit/requests/"):
|
|
373
|
+
errors.append((path, "a changed HANDOFF or request record in no section"))
|
|
374
|
+
else:
|
|
375
|
+
warnings.append((path, "changed, in no section"))
|
|
376
|
+
if path not in changed:
|
|
377
|
+
warnings.append((path, "listed, but not changed against HEAD"))
|
|
378
|
+
for level, items in (("ERROR", errors), ("WARN", warnings)):
|
|
379
|
+
for path, rule in items:
|
|
380
|
+
print(f"[{level}] `{table_cell(path)}` -- {rule}")
|
|
381
|
+
print(f"commit-map: {len(changed)} changed files against HEAD; "
|
|
382
|
+
f"{len(errors)} errors, {len(warnings)} warnings")
|
|
383
|
+
return 1 if errors else 0
|
|
384
|
+
|
|
385
|
+
|
|
271
386
|
def main(argv=None):
|
|
272
387
|
argv = list(sys.argv[1:] if argv is None else argv)
|
|
273
388
|
if argv[:1] == ["review-map"]:
|
|
274
389
|
return cmd_review_map(argv[1:])
|
|
390
|
+
if argv[:1] == ["commit-map"]:
|
|
391
|
+
return cmd_commit_map(argv[1:])
|
|
275
392
|
rc = knowledge.main(argv)
|
|
276
393
|
if argv[:1] in (["-h"], ["--help"]):
|
|
277
394
|
print(REVIEW_MAP_HELP)
|
|
@@ -100,6 +100,10 @@ CHRONOLOGY_EPOCH = "2026-10-18"
|
|
|
100
100
|
# filled '## Guide check'. The day AFTER the rule was written, so the analyses
|
|
101
101
|
# opened that day by parallel units (which never saw the template) stay quiet.
|
|
102
102
|
GUIDE_CHECK_EPOCH = "2026-10-24"
|
|
103
|
+
# Owner design approval (F-087): an L3 started on/after this date owes a request-
|
|
104
|
+
# record entry labelled `design approved` before implementation. The day AFTER the
|
|
105
|
+
# rule was written, like GUIDE_CHECK_EPOCH.
|
|
106
|
+
DESIGN_APPROVAL_EPOCH = "2026-10-31"
|
|
103
107
|
NEXT_MAX_CHARS = 240 # this repository's longest `next:` was 214 at the epoch
|
|
104
108
|
ID_SCAN_MAX_REFS = 300 # A3 is skipped above it (one advisory says so, T9)
|
|
105
109
|
ID_SCAN_REFS_PER_CALL = 50 # keeps one git command line far below 32k chars
|
|
@@ -1479,17 +1483,50 @@ def id_advisories(root):
|
|
|
1479
1483
|
return out
|
|
1480
1484
|
|
|
1481
1485
|
|
|
1482
|
-
def
|
|
1483
|
-
"""True when an L3 ANALYSIS
|
|
1484
|
-
|
|
1485
|
-
shipped. PLANNED is exempt -- the review is due at the END of Phase 3, so an
|
|
1486
|
-
analysis still being drafted is not late."""
|
|
1486
|
+
def _l3_in_work_since(meta, epoch):
|
|
1487
|
+
"""True when an L3 ANALYSIS is in implementation or done and began on/after
|
|
1488
|
+
`epoch` (an ISO date string)."""
|
|
1487
1489
|
if meta.get("level", "").upper() != "L3":
|
|
1488
1490
|
return False
|
|
1489
1491
|
if meta.get("status") not in ("IN_PROGRESS", "COMPLETED"):
|
|
1490
1492
|
return False
|
|
1491
1493
|
started = parse_iso((meta.get("start_date") or "").strip().strip("'\""))
|
|
1492
|
-
return started is not None and started >= parse_iso(
|
|
1494
|
+
return started is not None and started >= parse_iso(epoch)
|
|
1495
|
+
|
|
1496
|
+
|
|
1497
|
+
def design_review_due(meta):
|
|
1498
|
+
"""True when an L3 ANALYSIS owes a design-review row (review.md moment 1):
|
|
1499
|
+
implementation has started or finished, and it began on/after the gate
|
|
1500
|
+
shipped. PLANNED is exempt -- the review is due at the END of Phase 3, so an
|
|
1501
|
+
analysis still being drafted is not late."""
|
|
1502
|
+
return _l3_in_work_since(meta, DESIGN_REVIEW_EPOCH)
|
|
1503
|
+
|
|
1504
|
+
|
|
1505
|
+
def design_approval_due(meta):
|
|
1506
|
+
"""True when an L3 ANALYSIS owes the owner's design approval (review.md
|
|
1507
|
+
section When a review is due): in implementation or done, begun on/after
|
|
1508
|
+
DESIGN_APPROVAL_EPOCH. PLANNED is exempt -- the question comes after the PASS."""
|
|
1509
|
+
return _l3_in_work_since(meta, DESIGN_APPROVAL_EPOCH)
|
|
1510
|
+
|
|
1511
|
+
|
|
1512
|
+
def requests_naming(root, analysis_name):
|
|
1513
|
+
"""The request records whose `analysis:` field names this ANALYSIS file."""
|
|
1514
|
+
req = ai_path(root, "audit", "requests")
|
|
1515
|
+
if not req.is_dir():
|
|
1516
|
+
return []
|
|
1517
|
+
return [r for r in sorted(req.glob("REQUEST_*.md"))
|
|
1518
|
+
if str(load_frontmatter(read_text(r).splitlines()).get("analysis") or "")
|
|
1519
|
+
.strip().strip("'\"`") == analysis_name]
|
|
1520
|
+
|
|
1521
|
+
|
|
1522
|
+
def design_approval_logged(root, analysis_name):
|
|
1523
|
+
"""True when a request record naming this ANALYSIS has an entry whose LABEL
|
|
1524
|
+
begins `design approved` (case-insensitive). Only the label is read, never
|
|
1525
|
+
the quoted words: a quotation is data, and a 'design approved?' inside a
|
|
1526
|
+
refusal approves nothing."""
|
|
1527
|
+
return any(label.lower().startswith("design approved")
|
|
1528
|
+
for r in requests_naming(root, analysis_name)
|
|
1529
|
+
for _, _, label, _ in request_entries(read_text(r))[0])
|
|
1493
1530
|
|
|
1494
1531
|
|
|
1495
1532
|
def review_logged(root, analysis_name):
|
|
@@ -1801,6 +1838,12 @@ def cmd_validate(root, strict=False, hybrid=False):
|
|
|
1801
1838
|
advisories.append(f"{rel}: L3 in implementation with no design-review row in "
|
|
1802
1839
|
f"{review_log_rel()} -- the design was reviewed by nobody but its "
|
|
1803
1840
|
"author before code was written (review.md moment 1)")
|
|
1841
|
+
if (not hybrid and design_approval_due(meta)
|
|
1842
|
+
and not design_approval_logged(root, p.name)):
|
|
1843
|
+
advisories.append(f"{rel}: L3 in implementation with no design approval in its "
|
|
1844
|
+
"request record (no entry whose label begins 'design approved') -- the "
|
|
1845
|
+
"owner never said the design was what they meant before the "
|
|
1846
|
+
"work started (review.md, When a review is due)")
|
|
1804
1847
|
if ledger_due(meta) and not has_ledger_heading(text):
|
|
1805
1848
|
advisories.append(f"{rel}: L3 without '## Capability Ledger' -- the architect pass "
|
|
1806
1849
|
"left no record (architect.md); run it before the Impact")
|
|
@@ -2562,7 +2605,8 @@ def cmd_gate(args):
|
|
|
2562
2605
|
sys.stderr.write(
|
|
2563
2606
|
f"[sdlc gate] '{rel}' is on a protected path but no ANALYSIS_*.md is IN_PROGRESS. "
|
|
2564
2607
|
"If your analysis already exists, set its frontmatter to 'status: IN_PROGRESS' "
|
|
2565
|
-
"(that flip is what opens the gate
|
|
2608
|
+
"(that flip is what opens the gate; at L3, only after the owner's design approval, "
|
|
2609
|
+
"review.md); otherwise write it first (Phase 3).\n")
|
|
2566
2610
|
return 2
|
|
2567
2611
|
|
|
2568
2612
|
|
|
@@ -3063,13 +3107,9 @@ def _unit_documents(root, p):
|
|
|
3063
3107
|
reading or writing any of them is working on the unit."""
|
|
3064
3108
|
slug = p.stem[len("ANALYSIS_"):]
|
|
3065
3109
|
docs = {p, ai_path(root, "audit", f"HANDOFF_{slug}.md")}
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
meta = load_frontmatter(read_text(r).splitlines())
|
|
3070
|
-
if str(meta.get("analysis") or "").strip().strip("'\"`") == p.name:
|
|
3071
|
-
docs.add(r)
|
|
3072
|
-
docs.add(ai_path(root, "audit", f"HANDOFF_{r.stem[len('REQUEST_'):]}.md"))
|
|
3110
|
+
for r in requests_naming(root, p.name):
|
|
3111
|
+
docs.add(r)
|
|
3112
|
+
docs.add(ai_path(root, "audit", f"HANDOFF_{r.stem[len('REQUEST_'):]}.md"))
|
|
3073
3113
|
return {_norm_rel(d.resolve().as_posix()) for d in docs}
|
|
3074
3114
|
|
|
3075
3115
|
|
|
@@ -377,7 +377,7 @@ checks: [marketing.funnel] # optional — extra portable checks to run on t
|
|
|
377
377
|
the responsibility-level flow that deliver them; it NAMES the components in
|
|
378
378
|
the flow, never their mechanism or file-level design (that is the Impact's
|
|
379
379
|
vocabulary). After
|
|
380
|
-
design approval, changing a contracted surface, flow or feedback is a scope
|
|
380
|
+
the owner's design approval (`review.md`), changing a contracted surface, flow or feedback is a scope
|
|
381
381
|
change the USER approves: the solution may propose it, never enact it
|
|
382
382
|
silently. Every contracted flow is covered by ## Test Strategy. -->
|
|
383
383
|
|
|
@@ -549,9 +549,57 @@ Context (agent): "the question it answered, quoted"
|
|
|
549
549
|
entered only as `[NOT VERBATIM — from <source>]`, never as a quote.
|
|
550
550
|
- **Unattended**: R1 quotes the trigger that started the unit, labelled as such.
|
|
551
551
|
Declared assumptions are not owner statements and never enter the record.
|
|
552
|
+
- **Labelled entries** (r41): a decision taken under the owner's delegation is
|
|
553
|
+
`### R<n> — YYYY-MM-DD — decided under delegation R<m> — <what it settles>`, citing
|
|
554
|
+
the delegation entry (in Hybrid also the devPNT proposal it accepted); it is the
|
|
555
|
+
deciding session's choice, never an owner statement, and never changes an earlier
|
|
556
|
+
owner decision — that goes to the owner as a question. Owner words received for a
|
|
557
|
+
unit whose record another session writes are
|
|
558
|
+
`### R<n> — YYYY-MM-DD — received for <unit> — <what it settles>`, then sent to that
|
|
559
|
+
record's writer, who enters them verbatim citing this entry. Several sessions on one
|
|
560
|
+
repository: `coordination.md` §1.
|
|
561
|
+
- **Design approval** (L3): the owner's approval of the design is an entry whose
|
|
562
|
+
label begins `design approved`; a no or a correction takes its own label
|
|
563
|
+
(`review.md` §When a review is due).
|
|
552
564
|
- **Hybrid**: always on the filesystem; governed artifacts cite entries too; an
|
|
553
565
|
approval given in devPNT is named by its proposal, not quoted.
|
|
554
566
|
|
|
567
|
+
## ai_docs/audit/leases.md (several sessions, one coordinating)
|
|
568
|
+
|
|
569
|
+
Written only by the coordinating session (`coordination.md` §2); append-only.
|
|
570
|
+
|
|
571
|
+
```markdown
|
|
572
|
+
# Leases
|
|
573
|
+
|
|
574
|
+
Coordinator named in `REQUEST_[unit].md#R<n>`.
|
|
575
|
+
|
|
576
|
+
take dev-container — wave-6 session — YYYY-MM-DD
|
|
577
|
+
release dev-container — wave-6 session — YYYY-MM-DD
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
## Commit map (one commit, several units)
|
|
581
|
+
|
|
582
|
+
Written by the coordinating session before a commit carrying more than one unit's
|
|
583
|
+
work, checked with `sdlc_check.py commit-map MAP` (`coordination.md` §6); not
|
|
584
|
+
committed. Each item is a list line whose first code span is the path.
|
|
585
|
+
|
|
586
|
+
```markdown
|
|
587
|
+
# Commit map: [what this commit carries]
|
|
588
|
+
|
|
589
|
+
## F-001 [unit]
|
|
590
|
+
- `src/app.py`
|
|
591
|
+
- `ai_docs/audit/HANDOFF_[feature].md`
|
|
592
|
+
|
|
593
|
+
## Shared
|
|
594
|
+
- `ai_docs/audit/reviews/REVIEW_LOG.md` — F-001, F-002
|
|
595
|
+
|
|
596
|
+
## Regenerated
|
|
597
|
+
- `ai_docs/INDEX.md`
|
|
598
|
+
|
|
599
|
+
## Left out
|
|
600
|
+
- `scratch/notes.md` — why it is not in this commit
|
|
601
|
+
```
|
|
602
|
+
|
|
555
603
|
## ai_docs/solutions/E2E_TEST_[feature].md
|
|
556
604
|
|
|
557
605
|
Every L3, written before the closure review so it is part of the reviewed diff.
|