@antoneeo/agentic-sdlc-skill 1.26.0 → 1.27.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,107 @@
2
2
 
3
3
  Tutte le modifiche significative a questa skill saranno documentate in questo file.
4
4
 
5
+ ## [1.27.0 / kb 1.5.0 / mkt 0.5.0] - 2026-08-25
6
+
7
+ F-036 — the orientation hook installs itself.
8
+
9
+ ### Fixed
10
+ - **`ENFORCEMENT.md` 4 said "wire it on every project" and nothing ever did.** The
11
+ SessionStart orientation hook was real, tested and fail-open, but installing it was a
12
+ manual step, so it was skipped — and a session that never enters Phase 1 explicitly
13
+ then never meets the guide router at all. Field result: an agent worked a governed
14
+ project without invoking the process. `init` now wires the hook itself.
15
+ - **The invariant that looked like it guarded this guarded only prose** — it asserted
16
+ the documentation section exists (`assertIn("## 4. SessionStart hook", t)`) and that
17
+ `orient` runs. It gains a companion asserting the shipped installer actually CALLS the
18
+ writer. Mutation-tested: the first draft asserted the bare symbol and passed on a file
19
+ that imports the writer without invoking it, which is exactly the disabled-installer
20
+ case it exists to catch.
21
+
22
+ ### Fixed (also)
23
+ - **ENFORCEMENT 4/2's own worked hook examples named a skill directory that two of
24
+ the three lenses do not install.** kb and mkt both printed
25
+ `.claude/skills/agentic-sdlc/scripts/...`; kb installs under `kb-agentic` and mkt
26
+ under `mkt-agentic-sdlc`, so anyone who copied the snippet got a hook that runs,
27
+ prints `can't open file`, and emits nothing — the wired-and-dead defect this release
28
+ detects, sitting in the instructions that produce it. Four paths corrected, and a new
29
+ invariant derives the expected directory and validator from what the distribution
30
+ actually ships and fails if an example names anything else. Mutation-tested.
31
+
32
+ ### Added
33
+ - **A portability rule the doctrine did not have.** The hook command names a validator,
34
+ and where that validator lives decides which settings file may carry it: a repo that
35
+ vendors the validator gets a repo-relative command in the shared, committed
36
+ `.claude/settings.json`; a normal project gets an absolute path, which goes to the
37
+ git-ignored `.claude/settings.local.json` instead — committing it would hand every
38
+ teammate a hook naming a directory they do not have. `init` picks the file and adds
39
+ the local one to `.gitignore`. ENFORCEMENT 4's own worked example showed an absolute
40
+ path and did not mention the distinction; it now does.
41
+ - **A wired-but-dead hook is detected and reported instead of counted as done.** Found
42
+ in the field: a repository whose hook named a sibling lens's path, so it ran every
43
+ session, printed `can't open file`, and emitted nothing. A bare "is a hook present?"
44
+ check answers "already wired" to that and makes the silence permanent, so the existing
45
+ command's validator path is checked on disk. Never rewritten — it may be hand-tuned —
46
+ but never passed off as working either.
47
+
48
+ ### Notes
49
+ - `init` declines rather than guessing: no Python, skill not installed, a settings file
50
+ that is not valid JSON (never rewritten — a merge would discard what is in it), or a
51
+ skill path containing a double quote. Each case prints the snippet to paste.
52
+ - Only Claude Code's hook shape is wired. Codex and Gemini keep the manual snippet: this
53
+ repository has no fixture pinning their schema, and writing a hook file in a shape
54
+ nobody has verified is how the wired-but-dead defect above was born.
55
+ - A blocking `PreToolUse` gate would be real enforcement rather than a nudge, and it is
56
+ refused by the Vision's no-ceremony-ratchet Non-Goal. Recorded in the analysis so the
57
+ next person to have the idea finds the ruling instead of re-deriving it.
58
+
59
+ ## [1.26.1 / kb 1.4.7 / mkt 0.4.7] - 2026-08-06
60
+
61
+ The late design review of F-034 (`review.md` row 1b, run after 1.26.0 had shipped because the
62
+ gate had been skipped) returned FAIL with four blockers. Three were defects in the shipped
63
+ doctrine and are fixed here; the fourth was a governance-record gap, fixed in `ai_docs/`.
64
+
65
+ ### Fixed
66
+ - **`dispatch.md` contradicted the scoped re-review it delegates to `review.md` to define.**
67
+ It said "exactly three review touches per task, never a loop" and "not an extra review slot",
68
+ while `review.md` requires every review-driven correction to be re-reviewed — so an agent
69
+ executing a dispatched plan received two irreconcilable instructions. Reconciled: the scoped
70
+ re-review is a round **inside** slot 2 or 3, never a fourth slot; "never a loop" bounds the
71
+ slots, not the rounds within one. (Shared spine — the contradiction had shipped in all three
72
+ distributions; `dispatch.md` was missing from 1.26.0's impact map.)
73
+ - **The claim-to-evidence rule had no enforcement point.** Its acceptance criterion promised a
74
+ completion claim without fresh proof would be "nameable by the closure review", but
75
+ `review.md` §Reviewing had no such finding class and the reviewer is never handed `SKILL.md`.
76
+ Added: an unproven or stale completion claim — including one resting on a narrower check than
77
+ the claim needs, or on a delegated agent's report rather than the diff — is now a finding.
78
+ - **`SKILL.md`'s branch hygiene contradicted its own destructive guard.** One bullet ordered the
79
+ agent to "clean up the branch/worktree; never leave orphan branches"; the next reserved
80
+ destruction for the user's explicit request. The cleanup is now PROPOSED once the user has
81
+ chosen, with the anti-orphan duty kept as something to raise rather than to perform.
82
+ - **Two gaps in the scoped re-review's own wording:** a PASS that carried findings is now
83
+ explicitly provisional until its corrections pass a round (the commonest real case, previously
84
+ unruled — the rule's trigger fired but its gate was already behind the fixes); and the single
85
+ REVIEW_LOG row now carries the round-1 verdict alongside the final one (`FAIL → PASS`) instead
86
+ of collapsing a first-round FAIL into a bare PASS, which erased the evidence the same file
87
+ says logging exists to preserve.
88
+
89
+ - **`revise_rounds` had no defined meaning**, in the very document `SKILL.md` names as the owner
90
+ of the review log's schema and column meanings — and the historical rows already used it both
91
+ ways. Defined: it counts **review rounds**, not fix cycles (the first review is round 1, each
92
+ scoped re-review adds one), so a review whose findings were corrected always reads ≥ 2 and 3 is
93
+ the ceiling. The `verdict` column's format is defined alongside it (`FAIL → PASS` when the
94
+ round-1 and final verdicts differ), and the second example row — which taught a bare `PASS`
95
+ after two real findings closed in one round — now teaches both rules instead of contradicting
96
+ one. Raised at the review's round-3 cap and fixed before release rather than deferred.
97
+
98
+ ### Changed
99
+ - `ai_docs/solutions/ANALYSIS_execution_integrity.md` gains what the design review found
100
+ missing: the **ceremony-cost disclosure** Non-Goal 3 requires (measured on the shipped diff)
101
+ with the owner's explicit acceptance recorded; the **rulings placement** run per mechanism
102
+ against the ledger's own criterion (the previous claim used a narrower "user-facing" test the
103
+ ledger does not define); the **lens-scoping decision** stated; and a named disposition for the
104
+ chronic `stale` debt. No shipped file changes from these.
105
+
5
106
  ## [1.26.0 / kb 1.4.6 / mkt 0.4.6] - 2026-08-06
6
107
 
7
108
  ### Added
@@ -1,6 +1,6 @@
1
- {
2
- "name": "agentic-sdlc-skill",
3
- "version": "1.26.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.27.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,50 +1,50 @@
1
- {
2
- "name": "@antoneeo/agentic-sdlc-skill",
3
- "version": "1.26.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/routing.md",
39
- "skills/agentic-sdlc-skill/ENFORCEMENT.md",
40
- "skills/agentic-sdlc-skill/scripts/sdlc_check.py",
41
- "skills/agentic-sdlc-skill/scripts/sdlc_core.py",
42
- "gemini-extension.json",
43
- "README.md",
44
- "CHANGELOG.md",
45
- "scripts/lib.js",
46
- "scripts/init.js",
47
- "scripts/postinstall.js",
48
- "scripts/preuninstall.js"
49
- ]
50
- }
1
+ {
2
+ "name": "@antoneeo/agentic-sdlc-skill",
3
+ "version": "1.27.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/routing.md",
39
+ "skills/agentic-sdlc-skill/ENFORCEMENT.md",
40
+ "skills/agentic-sdlc-skill/scripts/sdlc_check.py",
41
+ "skills/agentic-sdlc-skill/scripts/sdlc_core.py",
42
+ "gemini-extension.json",
43
+ "README.md",
44
+ "CHANGELOG.md",
45
+ "scripts/lib.js",
46
+ "scripts/init.js",
47
+ "scripts/postinstall.js",
48
+ "scripts/preuninstall.js"
49
+ ]
50
+ }
package/scripts/init.js CHANGED
@@ -3,7 +3,7 @@
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
5
  const { execSync } = require('child_process');
6
- const { SKILL_SOURCE, INSTALLED_SKILL_NAME, SELF_LENS, SIBLING_LENSES, CLIENTS, clientDetected, skillTarget, loadTemplates, templateFor } = require('./lib');
6
+ const { SKILL_SOURCE, INSTALLED_SKILL_NAME, SELF_LENS, SIBLING_LENSES, CLIENTS, clientDetected, skillTarget, wireOrientHook, loadTemplates, templateFor } = require('./lib');
7
7
 
8
8
  const cwd = process.cwd();
9
9
 
@@ -156,8 +156,22 @@ const protocolFiles = {
156
156
  // written aside and merged by hand.
157
157
  let protocolPreexisting = false;
158
158
 
159
- for (const client of CLIENTS) {
160
- if (clientDetected(client)) {
159
+ // Probed ONCE and reused by section 6c: re-filtering CLIENTS there would
160
+ // run every client's detection a second time.
161
+ const detectedClients = CLIENTS.filter(clientDetected);
162
+ const PYTHON_CANDIDATES = ['python', 'python3', 'py'];
163
+ const detectedPython = (() => {
164
+ for (const py of PYTHON_CANDIDATES) {
165
+ try {
166
+ execSync(`${py} --version`, { stdio: 'ignore' });
167
+ return py;
168
+ } catch (e) { /* try the next interpreter */ }
169
+ }
170
+ return null;
171
+ })();
172
+
173
+ for (const client of detectedClients) {
174
+ {
161
175
  console.log(`✅ ${client.label} detected.`);
162
176
  const created = writeIfNotExists(protocolFiles[client.key], protocolContent, `${client.label} protocol pointer`);
163
177
  if (!created) protocolPreexisting = true;
@@ -221,16 +235,119 @@ Delete it once the merge is done.
221
235
  }
222
236
  }
223
237
 
238
+
239
+ // 6c. SessionStart orientation hook (F-036).
240
+ // ENFORCEMENT.md §4 asks for this on every project with a docs root and Python.
241
+ // It was a manual step until now, so it was skipped -- and a session that never
242
+ // enters Phase 1 explicitly then never meets the guide router at all.
243
+
244
+ // devPNT projects want `--hybrid`: without it the hook reports audit-plan
245
+ // staleness that devPNT/KL owns, and noise at every session start is how a
246
+ // session-start message stops being read.
247
+ const hybridProject = fs.existsSync(path.join(cwd, '.devpnt'));
248
+
249
+ // Only touch .gitignore when the wiring landed in the machine-specific file:
250
+ // if that file is not ignored, the absolute path reaches teammates anyway and
251
+ // the whole reason for choosing it is undone. Append-only and marker-guarded,
252
+ // exactly like gitattributes() above. Wrapped, because the installer has already
253
+ // written the seed files and must not die here.
254
+ const ignoreLocalSettings = () => {
255
+ const marker = '.claude/settings.local.json';
256
+ if (!fs.existsSync(path.join(cwd, '.git'))) return;
257
+ const filePath = path.join(cwd, '.gitignore');
258
+ try {
259
+ const current = fs.existsSync(filePath) ? fs.readFileSync(filePath, 'utf8') : '';
260
+ // Line-wise, not substring: a `!.claude/settings.local.json` un-ignore would
261
+ // satisfy `includes()` and leave the machine-specific path committed.
262
+ if (current.split(/\r?\n/).some((l) => l.trim() === marker)) return;
263
+ fs.writeFileSync(filePath, current + [
264
+ '',
265
+ '# agentic-sdlc: the orientation hook here names a path on THIS machine.',
266
+ marker,
267
+ '',
268
+ ].join(EOL), 'utf8');
269
+ console.log(`OK .gitignore: ${marker} ignored (it names a machine-specific path).`);
270
+ console.log(' If it is already tracked, run: git rm --cached ' + marker);
271
+ } catch (e) {
272
+ console.log(`⚠️ Could not update .gitignore (${e.message}). Add "${marker}" by hand.`);
273
+ }
274
+ };
275
+
276
+ const claudeClient = detectedClients.find((c) => c.key === 'claude');
277
+ const otherClients = detectedClients.filter((c) => c.key !== 'claude');
278
+ if (!claudeClient) {
279
+ console.log('ℹ️ Claude Code not detected: SessionStart orientation hook not wired.');
280
+ } else {
281
+ const r = wireOrientHook({
282
+ cwd, client: claudeClient, python: detectedPython,
283
+ hybrid: hybridProject, docsLabel: 'ai_docs',
284
+ });
285
+ switch (r.code) {
286
+ case 'wired':
287
+ console.log(`🪝 Wired the SessionStart orientation hook in .claude/${r.file}.`);
288
+ if (r.local) {
289
+ console.log(' It names a path on THIS machine, so it went to the git-ignored');
290
+ console.log(' file: each teammate runs init once to get their own.');
291
+ ignoreLocalSettings();
292
+ }
293
+ break;
294
+ case 'already':
295
+ console.log(`⏭️ SessionStart orientation hook already wired (.claude/${r.file}).`);
296
+ if (r.file === 'settings.local.json') ignoreLocalSettings();
297
+ break;
298
+ case 'broken':
299
+ console.log(`⚠️ The SessionStart orientation hook in .claude/${r.file} is BROKEN —`);
300
+ console.log(' its validator does not resolve, so it has been emitting nothing:');
301
+ console.log(` ${r.existing}`);
302
+ console.log(' Not overwritten (it may be hand-tuned). Correct it to:');
303
+ console.log(` ${r.command}`);
304
+ break;
305
+ case 'unverifiable':
306
+ console.log(`ℹ️ A SessionStart orientation hook exists in .claude/${r.file} but names`);
307
+ console.log(' no validator this installer recognises, so it was left alone:');
308
+ console.log(` ${r.existing}`);
309
+ break;
310
+ case 'malformed':
311
+ console.log(`⚠️ .claude/${r.file} has a shape this installer will not rewrite`);
312
+ console.log(` (${r.why}): left untouched. Add the hook by hand — command:`);
313
+ console.log(` ${JSON.stringify(r.command)}`);
314
+ break;
315
+ case 'write-failed':
316
+ console.log(`⚠️ Could not write .claude/${r.file} (${r.error}). Add by hand:`);
317
+ console.log(` ${JSON.stringify(r.command)}`);
318
+ break;
319
+ case 'no-python':
320
+ console.log('ℹ️ Python not found: SessionStart orientation hook not wired.');
321
+ break;
322
+ case 'no-validator':
323
+ console.log('ℹ️ Skill not installed yet: orientation hook not wired. Install it');
324
+ console.log(' (below), then re-run init.');
325
+ break;
326
+ case 'unsafe-path':
327
+ console.log('⚠️ The validator path contains a character that cannot be placed in a');
328
+ console.log(` hook command safely: ${r.validator}`);
329
+ console.log(' Refusing to build one. Wire it by hand (ENFORCEMENT.md §4).');
330
+ break;
331
+ }
332
+ }
333
+ for (const c of otherClients) {
334
+ // Said out loud rather than skipped in silence: ENFORCEMENT.md §4's manual
335
+ // snippet is these clients' only route, and a silent skip is what let the
336
+ // "documented default nobody installs" defect live in the first place.
337
+ console.log(`ℹ️ ${c.label}: hook not wired (only Claude Code's shape is verified) —`);
338
+ console.log(' wire it by hand from ENFORCEMENT.md §4 if that client supports it.');
339
+ }
340
+
224
341
  // 7. Generate ai_docs/INDEX.md so the very first `validate` is already clean.
225
342
  // The manifest is generated, never seeded: delegate to the validator if Python is available.
226
343
  const validator = path.join(SKILL_SOURCE, 'scripts', 'sdlc_check.py');
227
344
  let indexed = false;
228
- for (const py of ['python', 'python3', 'py']) {
345
+ // detectedPython is probed once, above: one answer for the hook and for this.
346
+ if (detectedPython) {
229
347
  try {
230
- execSync(`${py} "${validator}" index --root "${cwd}"`, { stdio: 'ignore' });
348
+ execSync(`${detectedPython} "${validator}" index --root "${cwd}"`, { stdio: 'ignore' });
231
349
  console.log('📇 Generated ai_docs/INDEX.md (document manifest).');
232
350
  indexed = true;
233
- break;
234
351
  } catch (e) { /* try the next interpreter */ }
235
352
  }
236
353
  if (!indexed) {