@antoneeo/agentic-sdlc-skill 1.10.0 → 1.11.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,16 @@
2
2
 
3
3
  Tutte le modifiche significative a questa skill saranno documentate in questo file.
4
4
 
5
+ ## [1.11.0] - 2026-07-03 (M4: Consolidation & Proactive Activation — self-activating, self-consulting, self-testing skill)
6
+ ### Added
7
+ - **SessionStart orientation hook** (`sdlc_check.py orient`): emits a bounded, repo-sourced orientation (README + INDEX + guide router + handoff + Rule-Zero triage) at session start. Zero-execution, **fail-OPEN** (a missing/empty `ai_docs/` never blocks the session), size-capped. Manual per-client wiring in `ENFORCEMENT.md` §4; `--hybrid` points at the devPNT bootstrap instead of duplicating plan/KL. `test_session_start.py` (9 cases).
8
+ - **Guide-layer consumption** (closes the write-only gap — Layer D "point to them"): a **consult trigger** (before operative L2/L3 work, targeted router match, L1 exempt, never blanket) and a **proactive-creation trigger** (propose a guide after user-indication-governed reusable work; never silent, never from model knowledge). Mechanics in `guides.md` §0/§1; hooked from `SKILL.md` Operative Guides + Phase 4/5; reconciled with subagent dispatch in `dispatch.md`.
9
+ - **Worktree/branch hygiene** in the closure discipline (`SKILL.md` Phase 4 isolate-on-branch / Phase 5 merge-decision + cleanup).
10
+ - **Skill eval harness** (dev-only, not shipped): `test_skill_invariants.py` is the deterministic static release gate (`python -m unittest discover -s scripts -p "test_*.py"` — asserts the skill's own doctrine invariants: triggers/hook/worktree present and wired, indexes idempotent, support pointers resolve; zero LLM/network/subprocess). Opt-in behavioral corpus `evals/scenarios/` + `run_behavioral.py` (non-CI, never gates). `ENFORCEMENT.md` §5.
11
+
12
+ ### Process note
13
+ - Full governance per unit: M-VISION v2.1 (revised — added the guide-consumption unit) → D-UC + P-TM → per-unit E-ISP (deep review) + E-TDD (light review) → implement → §4.6 code review. The independent-review gate caught real defects at design time (incomplete eval invariant set, the M3↔M4 dispatch interaction, a REPO path off-by-one, a P-TM overclaim of unbuilt guards). Battery 51/51 green. ADR `adr_2026-07-03_skill_eval_harness`; KL architecture v1.4 + principles v1.2.
14
+
5
15
  ## [1.10.0] - 2026-07-03 (M3: Subagent Execution / Feature A — opt-in executable plan)
6
16
  ### Added
7
17
  - **`dispatch.md`**: subagent-execution doctrine (opt-in for L3). The dispatch loop — validate the plan → per-task brief → economy-tier implementer → one-shot review → ledger — with client-relative model tiers (no provider names), one-shot review slots (no iterative loops), degradation to same-session where subagents do not exist, and guides injected by pointer (never pasted).
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-sdlc-skill",
3
- "version": "1.10.0",
3
+ "version": "1.11.0",
4
4
  "description": "Documentation-First SDLC protocol with triage, Vision governance and optional devPNT integration.",
5
5
  "author": "Antonio Pinto (https://github.com/Antoneeo)"
6
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antoneeo/agentic-sdlc-skill",
3
- "version": "1.10.0",
3
+ "version": "1.11.0",
4
4
  "description": "Documentation-First SDLC protocol for Claude Code, Gemini CLI and Codex with risk triage, Vision governance, installed support files and optional devPNT integration.",
5
5
  "keywords": [
6
6
  "claude-code",
@@ -54,3 +54,55 @@ Semantics: exit code 2 + message on stderr ⇒ the write is blocked and the mess
54
54
  - `ai_docs/`, `tests/` and `test/` are always excluded from blocking.
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
+
58
+ ## 4. SessionStart hook (orientation, optional)
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.
61
+
62
+ Wire it via each client's SessionStart mechanism — the same command everywhere (add `--hybrid` on devPNT/Hybrid projects):
63
+
64
+ Claude Code — in the project's `.claude/settings.json`:
65
+
66
+ ```json
67
+ {
68
+ "hooks": {
69
+ "SessionStart": [
70
+ {
71
+ "hooks": [
72
+ {
73
+ "type": "command",
74
+ "command": "python \"C:\\Users\\<user>\\.claude\\skills\\agentic-sdlc\\scripts\\sdlc_check.py\" orient"
75
+ }
76
+ ]
77
+ }
78
+ ]
79
+ }
80
+ }
81
+ ```
82
+
83
+ Codex — in `.codex/hooks.json`, the same `SessionStart` → `{"type":"command","command":"… orient"}` shape (this replaces the legacy static-echo protocol some fixtures still carry).
84
+
85
+ Gemini CLI — wire the same command into its startup-hook mechanism if present; otherwise the step simply degrades to the manual Phase-1 reads (no capability lost).
86
+
87
+ **Usage notes:**
88
+ - The hook assumes the working directory is the project root (standard Claude Code hook behavior); it also accepts `--root <path>`.
89
+ - **Hybrid/devPNT projects**: add `--hybrid` — the hook then appends a one-line pointer to run `devpnt_mcp_get_bootstrap` for the Master Plan / Knowledge Layer and does not replicate them; the filesystem orientation (router + handoff + README) still emits.
90
+ - Like the CI gate (§2), if you copied `sdlc_check.py` into the repo, the hook references that copy — keep it current when you update the skill.
91
+
92
+ ## 5. Skill eval battery (release gate)
93
+
94
+ The skill self-tests its own doctrine invariants. Two layers over one scenario corpus:
95
+
96
+ **Static battery — the deterministic release gate.** Run before any publish:
97
+
98
+ ```
99
+ python -m unittest discover -s skills/agentic-sdlc-skill/scripts -p "test_*.py"
100
+ ```
101
+
102
+ It aggregates the three test files (`test_plan.py` + `test_session_start.py` + `test_skill_invariants.py`) and asserts the skill's invariants: the M4 triggers/hook/worktree doctrine is present and wired, support-file pointers resolve, and the generated indexes are idempotent. A non-zero exit **blocks the release** — a failing eval is always a real regression, never flakiness: the battery is stdlib-only, makes no model/network/subprocess call (deterministic by construction). If `test_indexes_idempotent` fails, run `sdlc_check.py index` and re-run.
103
+
104
+ **Behavioral corpus — opt-in, non-CI.** `evals/scenarios/*.md` (declarative, model-neutral) + `evals/run_behavioral.py` seed a fixture and print a prompt + pass criteria for a human/agent to run and self-assess. Because live adherence is nondeterministic, this layer **never gates** — it is the reproducible way to check that, e.g., the consult trigger actually fires on a seeded repo (the "demonstrably" artifact).
105
+
106
+ **Optional CI** (same shape as §2, not mandatory): add a `run:` step invoking the `unittest discover` command above.
107
+
108
+ **T10 note:** if you copied `sdlc_check.py` and the `test_*.py` battery into the repo for CI, that copy is authoritative — keep it current when you update the skill.
@@ -156,6 +156,7 @@ gate) instead of requiring an IN_PROGRESS ANALYSIS.
156
156
 
157
157
  - Read `ai_docs/audit/handoff.md` if it exists; if its Date/Branch are inconsistent, treat it as history.
158
158
  - 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.
159
+ - 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).
159
160
  - If `ai_docs/` is missing or incomplete, create the structure and minimal documents by analyzing the project in batches.
160
161
  - In Standalone use `ai_docs/audit/audit_plan.md` for mapping and state.
161
162
  - In Hybrid prefer the devPNT/KL mapping when available; do not duplicate plan governance.
@@ -192,8 +193,10 @@ Hybrid L3:
192
193
  ### 4. Development and Testing
193
194
 
194
195
  - Implement only after the documentation gate required by the level.
196
+ - 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.
195
197
  - Modify surgically, consistently with the plan.
196
198
  - Implementation work follows the TDD discipline in `tdd.md` (RED/GREEN/REFACTOR — the L2/L3 default; record the reason when it does not apply).
199
+ - Before implementing (L2/L3; L1 exempt), **consult the guide router** for a guide covering the task and read it first — the consult trigger (`guides.md` §0, summarized under `## Operative Guides`). A targeted description match, not a blanket read.
197
200
  - If the environment does not allow automated tests, declare the alternative verification and the reason.
198
201
  - For bugs (L2/L3), follow the systematic debugging method in `debugging.md`.
199
202
  - 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.
@@ -205,6 +208,7 @@ Hybrid L3:
205
208
  - Run the relevant tests/lint/smoke checks.
206
209
  - 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).
207
210
  - Verify alignment with the local Vision or the devPNT M-VISION.
211
+ - 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.
208
212
  - Update only the documents actually impacted.
209
213
  - **Aligned indexes (Poka-Yoke)**: if you created, moved or removed canonical documents (`vision/`, `reference/`, `architecture/`, `functional/`, `strategic/`):
210
214
  - regenerate the manifest with `sdlc_check.py index` (writes `ai_docs/INDEX.md`) — never write it by hand;
@@ -216,6 +220,7 @@ Hybrid L3:
216
220
  - In Hybrid propose ADR/KL updates when there were architectural decisions.
217
221
  - In Standalone, if the project adopts `sdlc_check.py`, run `python <skill_dir>/scripts/sdlc_check.py check --root <project_root>` or the equivalent local copy.
218
222
  - Updated documents must travel in the same commit/PR as the code they describe.
223
+ - **Branch/worktree hygiene**: an L3 ran on its own branch (Phase 4) — close it with an explicit merge decision (merge, keep open, or discard) and clean up the branch/worktree; never leave orphan branches. In Hybrid, the running devPNT server locks `.devpnt/*.db`, so the merge is done from a separate git worktree or via a ref-only push, never an in-place branch switch in the primary worktree.
219
224
 
220
225
  ## ai_docs documents: two indexes + lifecycle
221
226
 
@@ -244,6 +249,11 @@ Legacy note: the validator also accepts the deprecated Italian frontmatter keys
244
249
 
245
250
  ## Operative Guides
246
251
 
252
+ Guides are **consulted, created, and proposed** — three moments; the mechanics live once in `guides.md`:
253
+ - **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.
254
+ - **Create (from user indications):** the origin+purpose test below.
255
+ - **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.
256
+
247
257
  Trigger test: the user hands over indications to follow (origin = user, not model
248
258
  knowledge) meant to govern how the agent operates (purpose = operative), not just
249
259
  inform an answer. Both hold → distill into `ai_docs/reference/GUIDE_[topic].md`.
@@ -265,6 +275,7 @@ regenerate with `sdlc_check.py index`.
265
275
  The prompt is not enforcement. When the project needs repeatable guarantees:
266
276
  - read `ENFORCEMENT.md`;
267
277
  - use `scripts/sdlc_check.py validate --strict` in CI;
268
- - use `scripts/sdlc_check.py gate` only for security-critical directories, not for the whole repository.
278
+ - use `scripts/sdlc_check.py gate` only for security-critical directories, not for the whole repository;
279
+ - (skill development) the self-eval battery `python -m unittest discover -s scripts -p "test_*.py"` guards the skill's own doctrine invariants and is the deterministic release gate — see `ENFORCEMENT.md` §5.
269
280
 
270
281
  The validator is a support, not a universal prerequisite: the skill must stay usable in environments without Python or hooks, declaring what it cannot verify automatically.
@@ -33,6 +33,14 @@ without an E-ISP.
33
33
  - Write `{status, verify_result, timestamp}` back to the ledger. The
34
34
  validator never writes the ledger — single-writer, orchestrator-owned.
35
35
 
36
+ **Guide consumption under dispatch.** Selecting each task's `guides` field IS the
37
+ consult trigger (`guides.md` §0) applied at plan-authoring time: the orchestrator
38
+ runs the router lookup (project router `ai_docs/reference/INDEX.md` + the agent-KB
39
+ router) when populating `guides`. A dispatched context-free subagent does **NOT**
40
+ run its own router consult — it reads the guide pointers handed to it in the
41
+ brief. (Proactive guide-creation stays at closure — the same broad final pass
42
+ below — so it needs no separate dispatch hook.)
43
+
36
44
  ## Model tiers (client-relative, no provider names)
37
45
 
38
46
  - Default dispatch: **economy** implementer tier.
@@ -17,6 +17,26 @@ when a task needs detail. Two levels, both produced by this pipeline:
17
17
  A guide that restates the source at length is as wrong as a fragmented one:
18
18
  completeness is guaranteed by the book level, economy by the synthesis level.
19
19
 
20
+ ## 0. Consuming a guide (consult before acting)
21
+
22
+ Guides only pay off if they reach the work they govern. **Before operative work,
23
+ proportional to triage** — L1 is exempt; engaged for L2/L3 — ask: *does a guide
24
+ already cover how to do this well?*
25
+
26
+ - **Scan the router, not the guides.** Read the when-to-consult descriptions in
27
+ the guide router `ai_docs/reference/INDEX.md` **and** the agent-KB router
28
+ `~/.agentic-sdlc/ai_docs/reference/INDEX.md` (if present). Match by topic.
29
+ - **On a match, read that guide's synthesis whole** before acting (the snapshot
30
+ stays on demand via the section markers). No match → proceed normally.
31
+ - **Targeted match, never blanket.** Open only the guide whose description fits
32
+ the task — never load every guide, which would reintroduce the exact token
33
+ cost the "point to them" model exists to avoid. The two-level model (compact
34
+ synthesis / verbatim snapshot) already bounds a single guide's cost.
35
+ - **Under subagent dispatch** the consult happens at plan-authoring time (the
36
+ orchestrator populates each task's `guides` field); a context-free subagent
37
+ reads the pointers it was handed and does not run its own router lookup. See
38
+ `dispatch.md`.
39
+
20
40
  ## 1. When to trigger
21
41
 
22
42
  Trigger test is origin + purpose, not content taxonomy (no "is this technical
@@ -34,6 +54,20 @@ Never manufacture a guide from model knowledge. If the user asks for "a guide
34
54
  on X" without handing over source material, ask for the source first — a
35
55
  guide with no `distilled_from` is not this pipeline's output.
36
56
 
57
+ ### Proactive trigger (after reusable success)
58
+
59
+ The trigger above is reactive (the user hands material over). It has a proactive
60
+ twin: **after completing work that was governed by user-provided indications and
61
+ is plausibly reusable** — it would prepare a future task — **PROPOSE** distilling
62
+ a guide.
63
+
64
+ - It is a **proposal to the user**, routed into this same pipeline (§2 onward):
65
+ the user confirms topic/scope before any file is written.
66
+ - **Never a silent write, never from model knowledge.** If the work was not
67
+ governed by user-provided material there is nothing to distill — do not invent
68
+ a guide from general knowledge (the `distilled_from` fidelity constraint, §3,
69
+ is absolute). This adds a moment to PROPOSE, not a new writer.
70
+
37
71
  ## 2. Pipeline
38
72
 
39
73
  0. **Search before creating (DRY — one CURRENT guide per topic).** Before
@@ -85,6 +85,20 @@ except Exception:
85
85
  pass
86
86
 
87
87
 
88
+ # --- orient (SessionStart hook) ---
89
+ # Fixed, hard-coded doc set (label, path-relative-to-root). No content- or
90
+ # user-derived paths -> no traversal input (P-TM T3); confine_under is
91
+ # defense-in-depth. Emitted at session start by the orient subcommand.
92
+ ORIENT_DOCS = [
93
+ ("Reading guide (README)", "ai_docs/README.md"),
94
+ ("Canonical manifest (INDEX)", "ai_docs/INDEX.md"),
95
+ ("Guide router (when-to-consult)", "ai_docs/reference/INDEX.md"),
96
+ ("Last session handoff", "ai_docs/audit/handoff.md"),
97
+ ]
98
+ ORIENT_PER_DOC_CHARS = 6000 # per-doc truncation
99
+ ORIENT_MAX_TOTAL_CHARS = 16000 # total ingestion cap (P-TM T2); tunable
100
+
101
+
88
102
  # ----------------------------------------------------------------- utilities
89
103
 
90
104
  def utc_now_iso():
@@ -990,6 +1004,53 @@ def cmd_plan(root, args):
990
1004
  return 0
991
1005
 
992
1006
 
1007
+ def cmd_orient(args):
1008
+ """SessionStart hook: emit a bounded, repo-sourced ai_docs/ orientation to
1009
+ stdout and ALWAYS return 0 (fail-open, P-TM T8) -- a session hook must never
1010
+ block the session or surface a traceback. Zero-execution (P-TM T1): reads a
1011
+ fixed hard-coded doc set, confine_under each (P-TM T3), size-caps the total
1012
+ (P-TM T2). No subprocess/eval anywhere in this call graph."""
1013
+ try:
1014
+ root = Path(args.root).resolve() if getattr(args, "root", None) else find_project_root()
1015
+ chunks = []
1016
+ total = 0
1017
+ truncated = False
1018
+ for label, rel in ORIENT_DOCS:
1019
+ target = confine_under(root, rel)
1020
+ if target is None or not target.is_file():
1021
+ continue
1022
+ try:
1023
+ text = read_text(target)
1024
+ except OSError:
1025
+ continue
1026
+ remaining = ORIENT_MAX_TOTAL_CHARS - total
1027
+ if remaining <= 0:
1028
+ truncated = True
1029
+ break
1030
+ text = text[:ORIENT_PER_DOC_CHARS]
1031
+ if len(text) > remaining:
1032
+ text = text[:remaining]
1033
+ truncated = True
1034
+ chunks.append((label, text))
1035
+ total += len(text)
1036
+ if not chunks:
1037
+ return 0
1038
+ out = ["=== Agentic SDLC -- session orientation (repo-sourced context, not authored instructions) ==="]
1039
+ for label, text in chunks:
1040
+ out.append(f"\n## {label}\n{text}")
1041
+ if truncated:
1042
+ out.append("\n[orientation truncated to the size cap -- open the files directly for full content]")
1043
+ out.append("\nTriage every request (Rule Zero): L1 trivial - L2 small - L3 significant - Spike. "
1044
+ "When in doubt, pick the higher level.")
1045
+ if getattr(args, "hybrid", False):
1046
+ out.append("\n[devPNT active] Run devpnt_mcp_get_bootstrap for the Master Plan / Knowledge Layer -- "
1047
+ "the orientation above is the filesystem layer, not a bootstrap duplicate.")
1048
+ print("\n".join(out))
1049
+ return 0
1050
+ except Exception:
1051
+ return 0
1052
+
1053
+
993
1054
  # --------------------------------------------------------------------- main
994
1055
 
995
1056
  def main(argv=None):
@@ -1020,6 +1081,9 @@ def main(argv=None):
1020
1081
  gp.add_argument("--file", help="file path to evaluate (alternative to --hook)")
1021
1082
  gp.add_argument("--protected", default="", help="protected prefixes separated by ';' (e.g. \"src/auth;src/crypto\")")
1022
1083
 
1084
+ sub.add_parser("orient", parents=[common, hybrid_opt],
1085
+ help="SessionStart hook: emit ai_docs/ orientation to stdout (fail-open, zero-execution)")
1086
+
1023
1087
  pp = sub.add_parser("plan", parents=[common],
1024
1088
  help="Subagent Execution: validate/brief a PLAN_[feature].md (zero-execution)")
1025
1089
  pp_sub = pp.add_subparsers(dest="plan_cmd", required=True)
@@ -1032,6 +1096,8 @@ def main(argv=None):
1032
1096
  args = ap.parse_args(argv)
1033
1097
  if args.cmd == "gate":
1034
1098
  return cmd_gate(args)
1099
+ if args.cmd == "orient":
1100
+ return cmd_orient(args)
1035
1101
 
1036
1102
  root = Path(args.root).resolve() if args.root else find_project_root()
1037
1103
  if args.cmd == "check":