@antoneeo/agentic-sdlc-skill 1.11.0 → 1.13.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 +248 -227
- package/README.md +88 -87
- package/gemini-extension.json +6 -6
- package/package.json +46 -43
- package/scripts/init.js +154 -153
- package/scripts/lib.js +168 -138
- package/skills/agentic-sdlc-skill/SKILL.md +1 -0
- package/skills/agentic-sdlc-skill/review.md +16 -0
- package/skills/agentic-sdlc-skill/templates.md +5 -0
package/scripts/lib.js
CHANGED
|
@@ -1,138 +1,168 @@
|
|
|
1
|
-
// Shared helpers for the Agentic SDLC npm scripts (init / postinstall / preuninstall).
|
|
2
|
-
// Single source for client detection and skill-target paths: init and postinstall
|
|
3
|
-
// must never disagree on what "Claude Code is installed" means.
|
|
4
|
-
|
|
5
|
-
const fs = require('fs');
|
|
6
|
-
const path = require('path');
|
|
7
|
-
const os = require('os');
|
|
8
|
-
const { execSync } = require('child_process');
|
|
9
|
-
|
|
10
|
-
const PACKAGE_ROOT = path.resolve(__dirname, '..');
|
|
11
|
-
const SKILL_SOURCE = path.join(PACKAGE_ROOT, 'skills', 'agentic-sdlc-skill');
|
|
12
|
-
const TEMPLATES_PATH = path.join(SKILL_SOURCE, 'templates.md');
|
|
13
|
-
|
|
14
|
-
// One entry per supported AI client. `home` may be overridden by an env var
|
|
15
|
-
// (Claude Desktop / portable installs); presence of the home dir counts as
|
|
16
|
-
// detection even when the CLI is not on PATH.
|
|
17
|
-
const CLIENTS = [
|
|
18
|
-
{
|
|
19
|
-
key: 'claude',
|
|
20
|
-
label: 'Claude Code',
|
|
21
|
-
cmd: 'claude',
|
|
22
|
-
home: process.env.CLAUDE_CONFIG_DIR || path.join(os.homedir(), '.claude'),
|
|
23
|
-
envVar: 'CLAUDE_CONFIG_DIR',
|
|
24
|
-
reload: 'Restart Claude Code to load it. Invoke via Skill tool as "agentic-sdlc".',
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
key: 'gemini',
|
|
28
|
-
label: 'Gemini CLI',
|
|
29
|
-
cmd: 'gemini',
|
|
30
|
-
home: process.env.GEMINI_HOME || path.join(os.homedir(), '.gemini'),
|
|
31
|
-
envVar: 'GEMINI_HOME',
|
|
32
|
-
reload: 'Run "gemini skills reload" or restart Gemini CLI to load it.',
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
key: 'codex',
|
|
36
|
-
label: 'Codex AI',
|
|
37
|
-
cmd: 'codex',
|
|
38
|
-
home: process.env.CODEX_HOME || path.join(os.homedir(), '.codex'),
|
|
39
|
-
envVar: 'CODEX_HOME',
|
|
40
|
-
reload: 'Restart Codex to load it. Invoke it as "$agentic-sdlc" or by asking for Agentic SDLC.',
|
|
41
|
-
},
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
*
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
1
|
+
// Shared helpers for the Agentic SDLC npm scripts (init / postinstall / preuninstall).
|
|
2
|
+
// Single source for client detection and skill-target paths: init and postinstall
|
|
3
|
+
// must never disagree on what "Claude Code is installed" means.
|
|
4
|
+
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const os = require('os');
|
|
8
|
+
const { execSync } = require('child_process');
|
|
9
|
+
|
|
10
|
+
const PACKAGE_ROOT = path.resolve(__dirname, '..');
|
|
11
|
+
const SKILL_SOURCE = path.join(PACKAGE_ROOT, 'skills', 'agentic-sdlc-skill');
|
|
12
|
+
const TEMPLATES_PATH = path.join(SKILL_SOURCE, 'templates.md');
|
|
13
|
+
|
|
14
|
+
// One entry per supported AI client. `home` may be overridden by an env var
|
|
15
|
+
// (Claude Desktop / portable installs); presence of the home dir counts as
|
|
16
|
+
// detection even when the CLI is not on PATH.
|
|
17
|
+
const CLIENTS = [
|
|
18
|
+
{
|
|
19
|
+
key: 'claude',
|
|
20
|
+
label: 'Claude Code',
|
|
21
|
+
cmd: 'claude',
|
|
22
|
+
home: process.env.CLAUDE_CONFIG_DIR || path.join(os.homedir(), '.claude'),
|
|
23
|
+
envVar: 'CLAUDE_CONFIG_DIR',
|
|
24
|
+
reload: 'Restart Claude Code to load it. Invoke via Skill tool as "agentic-sdlc".',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
key: 'gemini',
|
|
28
|
+
label: 'Gemini CLI',
|
|
29
|
+
cmd: 'gemini',
|
|
30
|
+
home: process.env.GEMINI_HOME || path.join(os.homedir(), '.gemini'),
|
|
31
|
+
envVar: 'GEMINI_HOME',
|
|
32
|
+
reload: 'Run "gemini skills reload" or restart Gemini CLI to load it.',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
key: 'codex',
|
|
36
|
+
label: 'Codex AI',
|
|
37
|
+
cmd: 'codex',
|
|
38
|
+
home: process.env.CODEX_HOME || path.join(os.homedir(), '.codex'),
|
|
39
|
+
envVar: 'CODEX_HOME',
|
|
40
|
+
reload: 'Restart Codex to load it. Invoke it as "$agentic-sdlc" or by asking for Agentic SDLC.',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
// Google Antigravity 2.0 discovers global agent skills under
|
|
44
|
+
// ~/.gemini/config/skills/ -- the SAME home the legacy Gemini CLI claims.
|
|
45
|
+
// To avoid a shared-home double-install (P-TM T1), this entry sets:
|
|
46
|
+
// - skillsSubdir 'config/skills': distinct target from gemini's ~/.gemini/skills
|
|
47
|
+
// - homeMarker on ~/.gemini/config/skills: detection never fires on bare
|
|
48
|
+
// ~/.gemini (which every Antigravity user has); only the Antigravity skills
|
|
49
|
+
// dir, the `agy` CLI, or ANTIGRAVITY_HOME count as "Antigravity installed".
|
|
50
|
+
key: 'antigravity',
|
|
51
|
+
label: 'Google Antigravity',
|
|
52
|
+
cmd: 'agy',
|
|
53
|
+
home: process.env.ANTIGRAVITY_HOME || path.join(os.homedir(), '.gemini'),
|
|
54
|
+
envVar: 'ANTIGRAVITY_HOME',
|
|
55
|
+
skillsSubdir: 'config/skills',
|
|
56
|
+
homeMarker: path.join(
|
|
57
|
+
process.env.ANTIGRAVITY_HOME || path.join(os.homedir(), '.gemini'),
|
|
58
|
+
'config',
|
|
59
|
+
'skills',
|
|
60
|
+
),
|
|
61
|
+
reload: 'Restart Antigravity, or run "agy skills reload", to load it. Invoke by asking for Agentic SDLC.',
|
|
62
|
+
},
|
|
63
|
+
];
|
|
64
|
+
|
|
65
|
+
function commandExists(cmd) {
|
|
66
|
+
try {
|
|
67
|
+
execSync(`${cmd} --version`, { stdio: 'ignore' });
|
|
68
|
+
return true;
|
|
69
|
+
} catch (e) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function clientDetected(client) {
|
|
75
|
+
// An entry may override the fs-existence probe with a `homeMarker` (a more
|
|
76
|
+
// specific path than the bare home) so two clients sharing a home dir do not
|
|
77
|
+
// both fire on its mere existence. Entries without a marker check `home`
|
|
78
|
+
// exactly as before (backward-compatible).
|
|
79
|
+
const homePathToCheck = client.homeMarker || client.home;
|
|
80
|
+
return commandExists(client.cmd)
|
|
81
|
+
|| Boolean(process.env[client.envVar])
|
|
82
|
+
|| fs.existsSync(homePathToCheck);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function skillTarget(client) {
|
|
86
|
+
// An entry may override the default `skills` sub-path with `skillsSubdir`
|
|
87
|
+
// (split on '/' to keep cross-platform path.join correctness). Entries
|
|
88
|
+
// without it resolve to <home>/skills/agentic-sdlc exactly as before.
|
|
89
|
+
const subdir = client.skillsSubdir ? client.skillsSubdir.split('/') : ['skills'];
|
|
90
|
+
return path.join(client.home, ...subdir, 'agentic-sdlc');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function copyRecursive(src, dest) {
|
|
94
|
+
if (typeof fs.cpSync === 'function') {
|
|
95
|
+
fs.cpSync(src, dest, { recursive: true, force: true });
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
// Fallback for Node < 16.7
|
|
99
|
+
if (!fs.existsSync(dest)) fs.mkdirSync(dest, { recursive: true });
|
|
100
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
101
|
+
const s = path.join(src, entry.name);
|
|
102
|
+
const d = path.join(dest, entry.name);
|
|
103
|
+
if (entry.isDirectory()) copyRecursive(s, d);
|
|
104
|
+
else fs.copyFileSync(s, d);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Parse templates.md into { headingText: [fencedBlock, ...] }.
|
|
110
|
+
* Templates are single-sourced there: the init script must extract them
|
|
111
|
+
* instead of carrying its own inline copies (which historically drifted).
|
|
112
|
+
*/
|
|
113
|
+
function loadTemplates() {
|
|
114
|
+
const text = fs.readFileSync(TEMPLATES_PATH, 'utf8');
|
|
115
|
+
const lines = text.split(/\r?\n/);
|
|
116
|
+
const sections = {};
|
|
117
|
+
let heading = null;
|
|
118
|
+
let block = null;
|
|
119
|
+
for (const line of lines) {
|
|
120
|
+
const h = line.match(/^##\s+(.*)$/);
|
|
121
|
+
if (h && block === null) {
|
|
122
|
+
heading = h[1].trim();
|
|
123
|
+
sections[heading] = sections[heading] || [];
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
if (/^```/.test(line)) {
|
|
127
|
+
if (block === null) {
|
|
128
|
+
block = [];
|
|
129
|
+
} else {
|
|
130
|
+
if (heading) sections[heading].push(block.join('\n') + '\n');
|
|
131
|
+
block = null;
|
|
132
|
+
}
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
if (block !== null) block.push(line);
|
|
136
|
+
}
|
|
137
|
+
return sections;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Return the Nth fenced block of the section whose heading contains `needle`.
|
|
142
|
+
* Throws with a clear message when missing: writing a wrong or empty
|
|
143
|
+
* boilerplate silently would be worse than failing the init.
|
|
144
|
+
*/
|
|
145
|
+
function templateFor(sections, needle, index = 0) {
|
|
146
|
+
const heading = Object.keys(sections).find((h) => h.includes(needle));
|
|
147
|
+
const blocks = heading ? sections[heading] : undefined;
|
|
148
|
+
if (!blocks || !blocks[index]) {
|
|
149
|
+
throw new Error(
|
|
150
|
+
`Template section containing "${needle}" (block ${index}) not found in ${TEMPLATES_PATH}. ` +
|
|
151
|
+
'The package is corrupted or templates.md was restructured: fix templates.md, do not improvise content.'
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
return blocks[index];
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
module.exports = {
|
|
158
|
+
PACKAGE_ROOT,
|
|
159
|
+
SKILL_SOURCE,
|
|
160
|
+
TEMPLATES_PATH,
|
|
161
|
+
CLIENTS,
|
|
162
|
+
commandExists,
|
|
163
|
+
clientDetected,
|
|
164
|
+
skillTarget,
|
|
165
|
+
copyRecursive,
|
|
166
|
+
loadTemplates,
|
|
167
|
+
templateFor,
|
|
168
|
+
};
|
|
@@ -183,6 +183,7 @@ Standalone L3:
|
|
|
183
183
|
- Before creating a new `ANALYSIS_[feature].md`, search `ai_docs/solutions/` with glob/grep for an existing analysis on the same topic: if there is one, update it instead of duplicating it.
|
|
184
184
|
- Create or update `ai_docs/solutions/ANALYSIS_[feature].md`.
|
|
185
185
|
- Minimum sections: Objective, Feature Vision (or Vision Alignment), Impact, Security and Threat Model, Action Plan, Test Strategy, Diary/Current State.
|
|
186
|
+
- 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 use-case / threat / benefit each part serves) so the closure review (`review.md`) can verify conformance. Do not draft the Impact in isolation.
|
|
186
187
|
- For features spanning multiple milestones or multiple analyses, also create `ai_docs/vision/features/VISION_[feature].md`.
|
|
187
188
|
|
|
188
189
|
Hybrid L3:
|
|
@@ -14,6 +14,13 @@ When you hand work to a reviewer (human or agent), give them:
|
|
|
14
14
|
- **The authoritative design artifact**: the ANALYSIS, E-TDD, or equivalent
|
|
15
15
|
the change was built against — not a paraphrase of it.
|
|
16
16
|
- **The actual diff**: the real changed files, not a description of them.
|
|
17
|
+
- **For an impact/solution-analysis review, the constraints it derives from**:
|
|
18
|
+
the **Vision** (Hybrid: the `M-VISION`; Standalone: `project_vision.md`/`roadmap.md`
|
|
19
|
+
+ the ANALYSIS Vision-Alignment), the **use-cases / user-needs** (Hybrid: `D-UC`;
|
|
20
|
+
Standalone: the ANALYSIS `## Use Cases / User Needs`), and the **threat model**
|
|
21
|
+
(Hybrid: `P-TM`; Standalone: the ANALYSIS `## Security and Threat Model`). Hand these
|
|
22
|
+
*in addition to* the design artifact — the reviewer checks the artifact **against**
|
|
23
|
+
them, not only for internal consistency.
|
|
17
24
|
|
|
18
25
|
Never ask a reviewer to "review my session" or "review what I just did"
|
|
19
26
|
without the artifacts above — that forces them to reconstruct scope from
|
|
@@ -45,6 +52,15 @@ When you are the reviewer:
|
|
|
45
52
|
do not soften a real correctness or security issue to a nit.
|
|
46
53
|
- No praise padding. A review reports problems and their fixes, not a
|
|
47
54
|
summary of what looks fine.
|
|
55
|
+
- **Conformance statement (impact/solution-analysis & design reviews only — not a
|
|
56
|
+
plain code-diff review).** When the artifact under review carries Vision / use-case
|
|
57
|
+
/ threat-model constraints, your output MUST map each constraint to its evidence: for
|
|
58
|
+
every use-case/user-need, every threat, and every applicable Vision benefit/Non-Goal,
|
|
59
|
+
state WHERE the artifact satisfies it (section or `file:line`) or raise it as a
|
|
60
|
+
finding. A PASS/approve is **not valid on "found nothing"** — the conformance
|
|
61
|
+
statement is the proof the check ran; an unfalsifiable "I checked" is the review
|
|
62
|
+
theater this discipline exists to prevent (the reviewer-side twin of §Receiving's
|
|
63
|
+
silent-drop rule). Plain code reviews stay findings-only.
|
|
48
64
|
|
|
49
65
|
## Anti-patterns
|
|
50
66
|
|
|
@@ -154,6 +154,11 @@ end_date:
|
|
|
154
154
|
VISION_[feature].md is created only if the feature spans multiple
|
|
155
155
|
ANALYSIS documents or multiple milestones. -->
|
|
156
156
|
|
|
157
|
+
## Use Cases / User Needs
|
|
158
|
+
<!-- who needs this and why: the concrete use-cases / user-needs the change serves
|
|
159
|
+
(the Standalone home for what Hybrid keeps in D-UC). Derived from the elicitation
|
|
160
|
+
round; the Impact below must cover each, and the closure review checks coverage. -->
|
|
161
|
+
|
|
157
162
|
## Impact
|
|
158
163
|
<!-- existing files touched, APIs/contracts, performance, new dependencies -->
|
|
159
164
|
|