@antoneeo/agentic-sdlc-skill 1.26.1 → 1.27.1
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 +71 -0
- package/README.md +13 -0
- package/gemini-extension.json +6 -6
- package/package.json +50 -50
- package/scripts/init.js +123 -6
- package/scripts/lib.js +434 -227
- package/skills/agentic-sdlc-skill/ENFORCEMENT.md +31 -0
- package/skills/agentic-sdlc-skill/SKILL.md +352 -352
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,77 @@
|
|
|
2
2
|
|
|
3
3
|
Tutte le modifiche significative a questa skill saranno documentate in questo file.
|
|
4
4
|
|
|
5
|
+
## [1.27.1 / kb 1.5.1 / mkt 0.5.1] - 2026-08-25
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
- **The three README front pages did not mention the hook wiring that 1.27.0 added.**
|
|
9
|
+
`init` now changes what every project gets, and the README *is* the npm page, so two
|
|
10
|
+
of the three said nothing about it and the third barely did. Each now describes the
|
|
11
|
+
wiring, the settings.json / settings.local.json split and why it exists, and the
|
|
12
|
+
broken-hook report. `GUIDE_release.md` step 2 already made this a release duty; it was
|
|
13
|
+
skipped in 1.27.0 and this is the catch-up.
|
|
14
|
+
- **`publish_all.bat`'s verify block reported the previous version after a successful
|
|
15
|
+
publish — twice.** `--prefer-online` (added in kb 1.4.8) forces revalidation but cannot
|
|
16
|
+
outrun CDN propagation of the `latest` tag in the seconds after publishing, so the
|
|
17
|
+
1.27.0 run printed mkt `0.4.7` when `0.5.0` had in fact landed. The flag alone was the
|
|
18
|
+
wrong fix and the note claiming otherwise is corrected: the block now **polls** each
|
|
19
|
+
package until the registry agrees with the local version, and prints both when it does
|
|
20
|
+
not, so "did it publish?" is answerable from the run instead of a manual `npm view`.
|
|
21
|
+
|
|
22
|
+
## [1.27.0 / kb 1.5.0 / mkt 0.5.0] - 2026-08-25
|
|
23
|
+
|
|
24
|
+
F-036 — the orientation hook installs itself.
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
- **`ENFORCEMENT.md` 4 said "wire it on every project" and nothing ever did.** The
|
|
28
|
+
SessionStart orientation hook was real, tested and fail-open, but installing it was a
|
|
29
|
+
manual step, so it was skipped — and a session that never enters Phase 1 explicitly
|
|
30
|
+
then never meets the guide router at all. Field result: an agent worked a governed
|
|
31
|
+
project without invoking the process. `init` now wires the hook itself.
|
|
32
|
+
- **The invariant that looked like it guarded this guarded only prose** — it asserted
|
|
33
|
+
the documentation section exists (`assertIn("## 4. SessionStart hook", t)`) and that
|
|
34
|
+
`orient` runs. It gains a companion asserting the shipped installer actually CALLS the
|
|
35
|
+
writer. Mutation-tested: the first draft asserted the bare symbol and passed on a file
|
|
36
|
+
that imports the writer without invoking it, which is exactly the disabled-installer
|
|
37
|
+
case it exists to catch.
|
|
38
|
+
|
|
39
|
+
### Fixed (also)
|
|
40
|
+
- **ENFORCEMENT 4/2's own worked hook examples named a skill directory that two of
|
|
41
|
+
the three lenses do not install.** kb and mkt both printed
|
|
42
|
+
`.claude/skills/agentic-sdlc/scripts/...`; kb installs under `kb-agentic` and mkt
|
|
43
|
+
under `mkt-agentic-sdlc`, so anyone who copied the snippet got a hook that runs,
|
|
44
|
+
prints `can't open file`, and emits nothing — the wired-and-dead defect this release
|
|
45
|
+
detects, sitting in the instructions that produce it. Four paths corrected, and a new
|
|
46
|
+
invariant derives the expected directory and validator from what the distribution
|
|
47
|
+
actually ships and fails if an example names anything else. Mutation-tested.
|
|
48
|
+
|
|
49
|
+
### Added
|
|
50
|
+
- **A portability rule the doctrine did not have.** The hook command names a validator,
|
|
51
|
+
and where that validator lives decides which settings file may carry it: a repo that
|
|
52
|
+
vendors the validator gets a repo-relative command in the shared, committed
|
|
53
|
+
`.claude/settings.json`; a normal project gets an absolute path, which goes to the
|
|
54
|
+
git-ignored `.claude/settings.local.json` instead — committing it would hand every
|
|
55
|
+
teammate a hook naming a directory they do not have. `init` picks the file and adds
|
|
56
|
+
the local one to `.gitignore`. ENFORCEMENT 4's own worked example showed an absolute
|
|
57
|
+
path and did not mention the distinction; it now does.
|
|
58
|
+
- **A wired-but-dead hook is detected and reported instead of counted as done.** Found
|
|
59
|
+
in the field: a repository whose hook named a sibling lens's path, so it ran every
|
|
60
|
+
session, printed `can't open file`, and emitted nothing. A bare "is a hook present?"
|
|
61
|
+
check answers "already wired" to that and makes the silence permanent, so the existing
|
|
62
|
+
command's validator path is checked on disk. Never rewritten — it may be hand-tuned —
|
|
63
|
+
but never passed off as working either.
|
|
64
|
+
|
|
65
|
+
### Notes
|
|
66
|
+
- `init` declines rather than guessing: no Python, skill not installed, a settings file
|
|
67
|
+
that is not valid JSON (never rewritten — a merge would discard what is in it), or a
|
|
68
|
+
skill path containing a double quote. Each case prints the snippet to paste.
|
|
69
|
+
- Only Claude Code's hook shape is wired. Codex and Gemini keep the manual snippet: this
|
|
70
|
+
repository has no fixture pinning their schema, and writing a hook file in a shape
|
|
71
|
+
nobody has verified is how the wired-but-dead defect above was born.
|
|
72
|
+
- A blocking `PreToolUse` gate would be real enforcement rather than a nudge, and it is
|
|
73
|
+
refused by the Vision's no-ceremony-ratchet Non-Goal. Recorded in the analysis so the
|
|
74
|
+
next person to have the idea finds the ruling instead of re-deriving it.
|
|
75
|
+
|
|
5
76
|
## [1.26.1 / kb 1.4.7 / mkt 0.4.7] - 2026-08-06
|
|
6
77
|
|
|
7
78
|
The late design review of F-034 (`review.md` row 1b, run after 1.26.0 had shipped because the
|
package/README.md
CHANGED
|
@@ -54,6 +54,19 @@ agentic-sdlc-init
|
|
|
54
54
|
|
|
55
55
|
Run it inside a project to create `ai_docs/`, Vision documents, strategic docs, audit plan, and agent protocol files (`AGENTS.md` — also the Antigravity CLI surface, `CLAUDE.md`, `GEMINI.md`, `.cursorrules`).
|
|
56
56
|
|
|
57
|
+
It also **wires the SessionStart orientation hook** into `.claude/`, so an agent opening
|
|
58
|
+
the project is handed the reading guide, the generated manifest, the guide router and the
|
|
59
|
+
last handoff before it does anything — instead of only when it remembers to look. That
|
|
60
|
+
wiring used to be a manual step documented in `ENFORCEMENT.md`; being manual, it was
|
|
61
|
+
skipped, and a project could run fully governed with an agent that never met the process.
|
|
62
|
+
|
|
63
|
+
The hook command names a validator, so where that validator lives decides which file gets
|
|
64
|
+
it: a repo that vendors it gets a repo-relative command in the shared `.claude/settings.json`
|
|
65
|
+
(portable — commit it); otherwise the path is machine-specific and goes to the git-ignored
|
|
66
|
+
`.claude/settings.local.json`, and each teammate runs `init` once. Re-running `init` never
|
|
67
|
+
duplicates the hook, and a hook whose validator no longer resolves is reported as **broken**
|
|
68
|
+
with the correction rather than counted as installed.
|
|
69
|
+
|
|
57
70
|
## Runtime Shape
|
|
58
71
|
|
|
59
72
|
The actual runtime skill is the folder:
|
package/gemini-extension.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "agentic-sdlc-skill",
|
|
3
|
-
"version": "1.
|
|
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.1",
|
|
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.
|
|
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.1",
|
|
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
|
-
|
|
160
|
-
|
|
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
|
-
|
|
345
|
+
// detectedPython is probed once, above: one answer for the hook and for this.
|
|
346
|
+
if (detectedPython) {
|
|
229
347
|
try {
|
|
230
|
-
execSync(`${
|
|
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) {
|