@ryuenn3123/agentic-senior-core 5.8.21 → 5.8.22
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/.agents/plugins/agentic-senior-core/plugin.json +1 -1
- package/.agents/plugins/agentic-senior-core/skills/asc-new-project/SKILL.md +5 -6
- package/gemini-extension.json +6 -6
- package/lib/cli/commands/adapter.mjs +21 -13
- package/lib/cli/commands/global.mjs +8 -8
- package/package.json +1 -21
- package/plugin.yaml +1 -1
- package/.claude-plugin/marketplace.json +0 -17
- package/.claude-plugin/plugin.json +0 -17
- package/.clinerules/agentic-senior-core.md +0 -109
- package/.codex-plugin/plugin.json +0 -24
- package/.continue/rules/agentic-senior-core.md +0 -109
- package/.cursor/rules/agentic-senior-core.mdc +0 -114
- package/.devin/rules/agentic-senior-core.md +0 -109
- package/.devin-plugin/plugin.json +0 -13
- package/.github/copilot-instructions.md +0 -109
- package/.github/plugin/marketplace.json +0 -20
- package/.github/plugin/plugin.json +0 -16
- package/.kilocode/rules/agentic-senior-core.md +0 -109
- package/.kiro/steering/agentic-senior-core.md +0 -109
- package/.openclaw/skills/asc/SKILL.md +0 -36
- package/.openclaw/skills/asc-adapter/SKILL.md +0 -43
- package/.openclaw/skills/asc-add-feature/SKILL.md +0 -53
- package/.openclaw/skills/asc-audit/SKILL.md +0 -36
- package/.openclaw/skills/asc-debt/SKILL.md +0 -72
- package/.openclaw/skills/asc-new-project/SKILL.md +0 -62
- package/.openclaw/skills/asc-refactor/SKILL.md +0 -62
- package/.openclaw/skills/asc-reference/SKILL.md +0 -59
- package/.openclaw/skills/asc-review/SKILL.md +0 -63
- package/.opencode/plugins/agentic-senior-core.mjs +0 -31
- package/.openhands/microagents/agentic-senior-core.md +0 -109
- package/.roo/rules/agentic-senior-core.md +0 -109
- package/.windsurf/rules/agentic-senior-core.md +0 -109
- package/.zed/rules/agentic-senior-core.md +0 -109
- package/hooks/copilot-hooks.json +0 -30
- package/hooks/hooks.json +0 -86
- package/hooks/lib/known-duplicates.json +0 -32
- package/hooks/package.json +0 -3
- package/hooks/path-util.cjs +0 -23
- package/hooks/post-edit-enforce.js +0 -234
- package/hooks/pre-tool-dependency-gate.js +0 -155
- package/hooks/session-start.js +0 -36
- package/hooks/subagent-start.js +0 -38
- package/skills/asc/SKILL.md +0 -36
- package/skills/asc-adapter/SKILL.md +0 -43
- package/skills/asc-add-feature/SKILL.md +0 -53
- package/skills/asc-audit/SKILL.md +0 -36
- package/skills/asc-debt/SKILL.md +0 -72
- package/skills/asc-new-project/SKILL.md +0 -62
- package/skills/asc-refactor/SKILL.md +0 -62
- package/skills/asc-reference/SKILL.md +0 -59
- package/skills/asc-review/SKILL.md +0 -63
- /package/{commands → .agents/plugins/agentic-senior-core/commands}/asc-add-feature.md +0 -0
- /package/{commands → .agents/plugins/agentic-senior-core/commands}/asc-add-feature.toml +0 -0
- /package/{commands → .agents/plugins/agentic-senior-core/commands}/asc-audit.md +0 -0
- /package/{commands → .agents/plugins/agentic-senior-core/commands}/asc-audit.toml +0 -0
- /package/{commands → .agents/plugins/agentic-senior-core/commands}/asc-help.md +0 -0
- /package/{commands → .agents/plugins/agentic-senior-core/commands}/asc-help.toml +0 -0
- /package/{commands → .agents/plugins/agentic-senior-core/commands}/asc-new-project.md +0 -0
- /package/{commands → .agents/plugins/agentic-senior-core/commands}/asc-new-project.toml +0 -0
- /package/{commands → .agents/plugins/agentic-senior-core/commands}/asc-refactor.md +0 -0
- /package/{commands → .agents/plugins/agentic-senior-core/commands}/asc-refactor.toml +0 -0
- /package/{commands → .agents/plugins/agentic-senior-core/commands}/asc-review.md +0 -0
- /package/{commands → .agents/plugins/agentic-senior-core/commands}/asc-review.toml +0 -0
|
@@ -1,234 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// Agentic Senior Core — PostToolUse enforcement hook
|
|
3
|
-
// Fires after Edit/Write. Checks for ladder violations and injects a nudge.
|
|
4
|
-
// Supports Claude Code, Codex CLI, and GitHub Copilot CLI.
|
|
5
|
-
|
|
6
|
-
const fs = require('fs');
|
|
7
|
-
const path = require('path');
|
|
8
|
-
|
|
9
|
-
let STDLIB_DUPLICATES = new Set([
|
|
10
|
-
'lodash', 'lodash-es', 'underscore',
|
|
11
|
-
'moment', 'dayjs',
|
|
12
|
-
'uuid', 'nanoid',
|
|
13
|
-
'chalk', 'kleur', 'colorette',
|
|
14
|
-
'axios', 'got', 'node-fetch', 'superagent',
|
|
15
|
-
'mkdirp', 'rimraf', 'del',
|
|
16
|
-
'glob', 'globby',
|
|
17
|
-
'left-pad', 'pad-left',
|
|
18
|
-
'is-odd', 'is-even', 'is-number', 'is-string',
|
|
19
|
-
'path-exists', 'fs-extra',
|
|
20
|
-
]);
|
|
21
|
-
|
|
22
|
-
try {
|
|
23
|
-
const knownPath = path.join(__dirname, 'lib', 'known-duplicates.json');
|
|
24
|
-
if (fs.existsSync(knownPath)) {
|
|
25
|
-
const raw = JSON.parse(fs.readFileSync(knownPath, 'utf8'));
|
|
26
|
-
if (Array.isArray(raw.duplicates)) {
|
|
27
|
-
STDLIB_DUPLICATES = new Set(raw.duplicates);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
} catch (_) {}
|
|
31
|
-
|
|
32
|
-
const SOURCE_EXTENSIONS = new Set([
|
|
33
|
-
'js', 'ts', 'mjs', 'cjs', 'jsx', 'tsx',
|
|
34
|
-
'py', 'rb', 'go', 'rs', 'java', 'kt', 'swift', 'cs',
|
|
35
|
-
]);
|
|
36
|
-
|
|
37
|
-
const LOC_DELTA_THRESHOLD = 30;
|
|
38
|
-
const NEW_FILE_LINE_THRESHOLD = 50;
|
|
39
|
-
|
|
40
|
-
let inputBuffer = '';
|
|
41
|
-
process.stdin.setEncoding('utf8');
|
|
42
|
-
process.stdin.on('data', function (chunk) { inputBuffer += chunk; });
|
|
43
|
-
process.stdin.on('end', function () {
|
|
44
|
-
try {
|
|
45
|
-
const data = JSON.parse(inputBuffer);
|
|
46
|
-
const toolName = data.tool_name || '';
|
|
47
|
-
const toolInput = data.tool_input || {};
|
|
48
|
-
const filePath = toolInput.file_path || '';
|
|
49
|
-
const findings = [];
|
|
50
|
-
|
|
51
|
-
if (filePath.endsWith('package.json')) {
|
|
52
|
-
checkDependencyAddition(toolName, toolInput, findings);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const ext = path.extname(filePath).slice(1);
|
|
56
|
-
if (SOURCE_EXTENSIONS.has(ext)) {
|
|
57
|
-
if (toolName === 'Edit') {
|
|
58
|
-
checkLocDelta(toolInput, filePath, findings);
|
|
59
|
-
} else if (toolName === 'Write') {
|
|
60
|
-
checkNewFileSize(toolInput, filePath, findings);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
checkLivingDocNudge(filePath, findings);
|
|
65
|
-
|
|
66
|
-
if (ext !== 'md') {
|
|
67
|
-
checkWorkflowGate(toolName, filePath, ext, findings);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (findings.length === 0) return;
|
|
71
|
-
|
|
72
|
-
const nudge = '[ASC enforcement] ' + findings.join(' ') + ' Review the decision ladder before continuing.';
|
|
73
|
-
emit(nudge);
|
|
74
|
-
} catch (_) {
|
|
75
|
-
// Silent fail — enforcement must not break the session
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
function checkDependencyAddition(toolName, toolInput, findings) {
|
|
80
|
-
var target = toolName === 'Edit' ? (toolInput.new_string || '') : (toolInput.content || '');
|
|
81
|
-
var baseline = toolName === 'Edit' ? (toolInput.old_string || '') : '';
|
|
82
|
-
|
|
83
|
-
var depPattern = /"([^"]+)"\s*:\s*"[~^>=<*]?\d/g;
|
|
84
|
-
var newDeps = extractDeps(target, depPattern);
|
|
85
|
-
var oldDeps = extractDeps(baseline, depPattern);
|
|
86
|
-
|
|
87
|
-
var added = newDeps.filter(function (d) { return oldDeps.indexOf(d) === -1; });
|
|
88
|
-
if (added.length === 0) return;
|
|
89
|
-
|
|
90
|
-
var stdlibDupes = added.filter(function (d) { return STDLIB_DUPLICATES.has(d); });
|
|
91
|
-
if (stdlibDupes.length > 0) {
|
|
92
|
-
findings.push(
|
|
93
|
-
'Dependency ' + stdlibDupes.join(', ') + ' may duplicate stdlib/platform features. '
|
|
94
|
-
+ 'Ladder step 3: does the standard library cover this?'
|
|
95
|
-
);
|
|
96
|
-
} else {
|
|
97
|
-
findings.push(
|
|
98
|
-
'New dependency added: ' + added.join(', ') + '. '
|
|
99
|
-
+ 'Ladder step 3-4: stdlib or already-installed alternative?'
|
|
100
|
-
);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function extractDeps(text, pattern) {
|
|
105
|
-
var matches = [];
|
|
106
|
-
var match;
|
|
107
|
-
while ((match = pattern.exec(text)) !== null) {
|
|
108
|
-
matches.push(match[1]);
|
|
109
|
-
}
|
|
110
|
-
return matches;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
function checkLocDelta(toolInput, filePath, findings) {
|
|
114
|
-
var newLines = (toolInput.new_string || '').split('\n').length;
|
|
115
|
-
var oldLines = (toolInput.old_string || '').split('\n').length;
|
|
116
|
-
var delta = newLines - oldLines;
|
|
117
|
-
if (delta > LOC_DELTA_THRESHOLD) {
|
|
118
|
-
findings.push(
|
|
119
|
-
'Edit added ' + delta + ' net lines to ' + path.basename(filePath) + '. '
|
|
120
|
-
+ 'Ladder step 5: can this be one straightforward function?'
|
|
121
|
-
);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
function checkNewFileSize(toolInput, filePath, findings) {
|
|
126
|
-
var lines = (toolInput.content || '').split('\n').length;
|
|
127
|
-
if (lines > NEW_FILE_LINE_THRESHOLD) {
|
|
128
|
-
findings.push(
|
|
129
|
-
'New file ' + path.basename(filePath) + ' created with ' + lines + ' lines. '
|
|
130
|
-
+ 'Ladder step 1-2: does this need to be built? Does the codebase already have this?'
|
|
131
|
-
);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function checkLivingDocNudge(filePath, findings) {
|
|
136
|
-
var lower = filePath.toLowerCase();
|
|
137
|
-
if (lower.includes('schema') || lower.includes('migration') || lower.includes('model') || lower.includes('prisma')) {
|
|
138
|
-
findings.push(
|
|
139
|
-
'[ASC Living Doc] Data contract/model modified in ' + path.basename(filePath) + '. '
|
|
140
|
-
+ 'Ensure docs/Schema.md and docs/Architecture.md are kept in sync to prevent spec drift.'
|
|
141
|
-
);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
function checkWorkflowGate(toolName, filePath, ext, findings) {
|
|
146
|
-
try {
|
|
147
|
-
var pathUtil = require('./path-util.cjs');
|
|
148
|
-
var gatePath = pathUtil.getWorkflowGatePath(process.cwd());
|
|
149
|
-
if (!fs.existsSync(gatePath)) return;
|
|
150
|
-
|
|
151
|
-
var gateStr = fs.readFileSync(gatePath, 'utf8');
|
|
152
|
-
var gate = JSON.parse(gateStr);
|
|
153
|
-
|
|
154
|
-
if (gate.updatedAt) {
|
|
155
|
-
var ageHours = (Date.now() - new Date(gate.updatedAt).getTime()) / (1000 * 60 * 60);
|
|
156
|
-
if (ageHours > 4) {
|
|
157
|
-
fs.unlinkSync(gatePath);
|
|
158
|
-
findings.push('Cleared stale workflow gate (' + gate.workflow + ').');
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
if (gate.phase === 'research' || gate.phase === 'plan') {
|
|
164
|
-
findings.push(
|
|
165
|
-
'Workflow gate bypass: ' + gate.workflow + ' is in ' + gate.phase + ' phase but source code was edited. '
|
|
166
|
-
+ 'Stop and wait for phase approval. If you must proceed, log this bypass to the debt ledger.'
|
|
167
|
-
);
|
|
168
|
-
} else if (gate.phase === 'implement') {
|
|
169
|
-
validateDocSpecs(gate.workflow, findings);
|
|
170
|
-
}
|
|
171
|
-
} catch (_) {
|
|
172
|
-
// Silent fail
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
function validateDocSpecs(workflow, findings) {
|
|
177
|
-
try {
|
|
178
|
-
var cwd = process.cwd();
|
|
179
|
-
var docsDir = path.join(cwd, 'docs');
|
|
180
|
-
|
|
181
|
-
// Anti-typo check for common doc typos (e.g. Architectyre.md)
|
|
182
|
-
var searchDirs = [cwd, docsDir];
|
|
183
|
-
var typoFound = false;
|
|
184
|
-
searchDirs.forEach(function (d) {
|
|
185
|
-
if (fs.existsSync(d)) {
|
|
186
|
-
var files = fs.readdirSync(d);
|
|
187
|
-
files.forEach(function (f) {
|
|
188
|
-
if (f.toLowerCase() !== f && /architect[y|u]re/i.test(f) && f !== 'Architecture.md') {
|
|
189
|
-
findings.push('[ASC Spec Typo Alert] Typo detected in doc filename "' + f + '". Rename to "Architecture.md".');
|
|
190
|
-
typoFound = true;
|
|
191
|
-
}
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
if (workflow === 'asc-new-project') {
|
|
197
|
-
var requiredDocs = ['PRD.md', 'Architecture.md', 'Design.md', 'Schema.md'];
|
|
198
|
-
var missing = requiredDocs.filter(function (doc) {
|
|
199
|
-
return !fs.existsSync(path.join(cwd, doc)) && !fs.existsSync(path.join(docsDir, doc));
|
|
200
|
-
});
|
|
201
|
-
if (missing.length > 0) {
|
|
202
|
-
findings.push(
|
|
203
|
-
'[ASC 5-Doc SDD Gate] Greenfield project missing spec document(s): ' + missing.join(', ') + '. '
|
|
204
|
-
+ 'Create them in docs/ to align requirements before continuing implementation.'
|
|
205
|
-
);
|
|
206
|
-
}
|
|
207
|
-
} else if (workflow === 'asc-add-feature') {
|
|
208
|
-
var hasPrd = fs.existsSync(path.join(cwd, 'PRD.md')) || fs.existsSync(path.join(docsDir, 'PRD.md'));
|
|
209
|
-
if (!hasPrd) {
|
|
210
|
-
findings.push(
|
|
211
|
-
'[ASC SDD Gate] Feature addition missing docs/PRD.md. Define goals and non-goals before coding.'
|
|
212
|
-
);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
} catch (_) {}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
function emit(nudge) {
|
|
219
|
-
try {
|
|
220
|
-
var isCopilot = Boolean(process.env.COPILOT_PLUGIN_DATA);
|
|
221
|
-
var output = {
|
|
222
|
-
hookSpecificOutput: {
|
|
223
|
-
hookEventName: 'PostToolUse',
|
|
224
|
-
additionalContext: nudge,
|
|
225
|
-
},
|
|
226
|
-
};
|
|
227
|
-
if (isCopilot) {
|
|
228
|
-
output = { additionalContext: nudge };
|
|
229
|
-
}
|
|
230
|
-
process.stdout.write(JSON.stringify(output));
|
|
231
|
-
} catch (_) {
|
|
232
|
-
// EPIPE — silent
|
|
233
|
-
}
|
|
234
|
-
}
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// Agentic Senior Core — PreToolUse dependency gate hook
|
|
3
|
-
// Hard-blocks edits/writes to package.json AND shell commands (npm install/yarn add/ascx)
|
|
4
|
-
// if new dependencies duplicate stdlib/platform features.
|
|
5
|
-
// Supports Claude Code, Antigravity IDE (run_command), and Copilot CLI hook response formats.
|
|
6
|
-
|
|
7
|
-
const fs = require('fs');
|
|
8
|
-
const path = require('path');
|
|
9
|
-
|
|
10
|
-
let knownDuplicates = new Set();
|
|
11
|
-
try {
|
|
12
|
-
const knownPath = path.join(__dirname, 'lib', 'known-duplicates.json');
|
|
13
|
-
if (fs.existsSync(knownPath)) {
|
|
14
|
-
const raw = JSON.parse(fs.readFileSync(knownPath, 'utf8'));
|
|
15
|
-
if (Array.isArray(raw.duplicates)) {
|
|
16
|
-
knownDuplicates = new Set(raw.duplicates);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
} catch (_) {
|
|
20
|
-
// Fallback set if JSON loading fails
|
|
21
|
-
knownDuplicates = new Set(['lodash', 'underscore', 'moment', 'dayjs', 'uuid', 'axios', 'rimraf']);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
let inputBuffer = '';
|
|
25
|
-
process.stdin.setEncoding('utf8');
|
|
26
|
-
process.stdin.on('data', function (chunk) { inputBuffer += chunk; });
|
|
27
|
-
process.stdin.on('end', function () {
|
|
28
|
-
try {
|
|
29
|
-
const data = JSON.parse(inputBuffer);
|
|
30
|
-
const toolName = data.tool_name || data.toolName || '';
|
|
31
|
-
const toolInput = data.tool_input || data.toolInput || {};
|
|
32
|
-
let added = [];
|
|
33
|
-
|
|
34
|
-
const isTerminal = ['Bash', 'run_command', 'run_shell_command', 'terminal', 'execute_command'].includes(toolName);
|
|
35
|
-
const isFileEdit = ['Edit', 'Write', 'replace_file_content', 'write_to_file', 'write_file', 'multi_replace_file_content'].includes(toolName);
|
|
36
|
-
|
|
37
|
-
if (isTerminal) {
|
|
38
|
-
const command = toolInput.command || toolInput.CommandLine || toolInput.cmd || toolInput.commandLine || '';
|
|
39
|
-
added = extractCommandDeps(command);
|
|
40
|
-
} else if (isFileEdit) {
|
|
41
|
-
const filePath = toolInput.file_path || toolInput.TargetFile || toolInput.path || toolInput.target_file || '';
|
|
42
|
-
if (!filePath.endsWith('package.json')) {
|
|
43
|
-
process.exit(0);
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
const target = (toolName === 'Edit' || toolName === 'replace_file_content')
|
|
47
|
-
? (toolInput.new_string || toolInput.ReplacementContent || toolInput.content || '')
|
|
48
|
-
: (toolInput.content || toolInput.CodeContent || '');
|
|
49
|
-
const baseline = (toolName === 'Edit' || toolName === 'replace_file_content')
|
|
50
|
-
? (toolInput.old_string || toolInput.TargetContent || '')
|
|
51
|
-
: '';
|
|
52
|
-
|
|
53
|
-
const depPattern = /"([^"]+)"\s*:\s*"[~^>=<*]?\d/g;
|
|
54
|
-
const newDeps = extractDeps(target, depPattern);
|
|
55
|
-
const oldDeps = extractDeps(baseline, depPattern);
|
|
56
|
-
|
|
57
|
-
added = newDeps.filter(function (d) { return oldDeps.indexOf(d) === -1; });
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (added.length === 0) {
|
|
61
|
-
process.exit(0);
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const allowlist = loadAllowlist();
|
|
66
|
-
const forbidden = added.filter(function (dep) {
|
|
67
|
-
return knownDuplicates.has(dep) && !allowlist.has(dep);
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
if (forbidden.length > 0) {
|
|
71
|
-
const reason = '[ASC Hard-Block] Dependency ' + forbidden.map(function(d){ return "'" + d + "'"; }).join(', ')
|
|
72
|
-
+ ' duplicates standard library or native platform features. '
|
|
73
|
-
+ 'Ladder step 3: use stdlib/native features instead, or add to .asc/dependency-allowlist.json to override.';
|
|
74
|
-
|
|
75
|
-
const output = {
|
|
76
|
-
allow_tool: false,
|
|
77
|
-
deny_reason: reason,
|
|
78
|
-
hookSpecificOutput: {
|
|
79
|
-
hookEventName: 'PreToolUse',
|
|
80
|
-
permissionDecision: 'deny',
|
|
81
|
-
permissionDecisionReason: reason
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
process.stdout.write(JSON.stringify(output) + '\n');
|
|
85
|
-
process.exit(2);
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
} catch (_) {
|
|
89
|
-
// Silent fail to ensure session stability
|
|
90
|
-
}
|
|
91
|
-
process.exit(0);
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
function extractDeps(text, pattern) {
|
|
95
|
-
const matches = [];
|
|
96
|
-
let match;
|
|
97
|
-
while ((match = pattern.exec(text)) !== null) {
|
|
98
|
-
matches.push(match[1]);
|
|
99
|
-
}
|
|
100
|
-
return matches;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
function extractCommandDeps(command) {
|
|
104
|
-
const installRegex = /(?:npm|yarn|pnpm|bun|ascx)\s+(?:install|i|add)(?:\s+[^\s]+)*/i;
|
|
105
|
-
if (!installRegex.test(command)) return [];
|
|
106
|
-
|
|
107
|
-
const parts = command.split(/\s+/);
|
|
108
|
-
const pkgIndex = parts.findIndex(p => ['install', 'i', 'add'].includes(p.toLowerCase()));
|
|
109
|
-
if (pkgIndex === -1 || pkgIndex >= parts.length - 1) return [];
|
|
110
|
-
|
|
111
|
-
const rawArgs = parts.slice(pkgIndex + 1);
|
|
112
|
-
const deps = [];
|
|
113
|
-
for (let arg of rawArgs) {
|
|
114
|
-
if (arg.startsWith('-')) continue; // Skip flags like -D, --save-dev
|
|
115
|
-
if (arg.startsWith('http://') || arg.startsWith('https://') || arg.startsWith('git+')) continue;
|
|
116
|
-
|
|
117
|
-
// Remove scope/version if any, e.g. lodash@^4.17 -> lodash, @types/node@18 -> @types/node
|
|
118
|
-
let name = arg;
|
|
119
|
-
if (name.startsWith('@')) {
|
|
120
|
-
const slashIndex = name.indexOf('/');
|
|
121
|
-
if (slashIndex !== -1) {
|
|
122
|
-
const atIndex = name.indexOf('@', slashIndex);
|
|
123
|
-
if (atIndex !== -1) name = name.substring(0, atIndex);
|
|
124
|
-
}
|
|
125
|
-
} else {
|
|
126
|
-
const atIndex = name.indexOf('@');
|
|
127
|
-
if (atIndex !== -1) name = name.substring(0, atIndex);
|
|
128
|
-
}
|
|
129
|
-
if (name) deps.push(name);
|
|
130
|
-
}
|
|
131
|
-
return deps;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
function loadAllowlist() {
|
|
135
|
-
const allowed = new Set();
|
|
136
|
-
const candidates = [
|
|
137
|
-
path.join(process.cwd(), '.asc', 'dependency-allowlist.json'),
|
|
138
|
-
path.join(process.cwd(), '.agents', 'dependency-allowlist.json')
|
|
139
|
-
];
|
|
140
|
-
|
|
141
|
-
for (let i = 0; i < candidates.length; i++) {
|
|
142
|
-
try {
|
|
143
|
-
if (fs.existsSync(candidates[i])) {
|
|
144
|
-
const content = JSON.parse(fs.readFileSync(candidates[i], 'utf8'));
|
|
145
|
-
const deps = content.allowedDependencies || content.allowed || {};
|
|
146
|
-
if (Array.isArray(deps)) {
|
|
147
|
-
deps.forEach(function (d) { allowed.add(d); });
|
|
148
|
-
} else if (typeof deps === 'object') {
|
|
149
|
-
Object.keys(deps).forEach(function (d) { allowed.add(d); });
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
} catch (_) {}
|
|
153
|
-
}
|
|
154
|
-
return allowed;
|
|
155
|
-
}
|
package/hooks/session-start.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// Agentic Senior Core — SessionStart hook
|
|
3
|
-
// Injects universal coding rules on every session start.
|
|
4
|
-
// Supports Claude Code, Codex CLI, and GitHub Copilot CLI.
|
|
5
|
-
|
|
6
|
-
const fs = require('fs');
|
|
7
|
-
const path = require('path');
|
|
8
|
-
|
|
9
|
-
const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT || path.resolve(__dirname, '..');
|
|
10
|
-
const isCopilot = Boolean(process.env.COPILOT_PLUGIN_DATA);
|
|
11
|
-
const isCodex = !isCopilot && Boolean(process.env.PLUGIN_DATA);
|
|
12
|
-
|
|
13
|
-
let content;
|
|
14
|
-
try {
|
|
15
|
-
content = fs.readFileSync(path.join(pluginRoot, 'AGENTS.md'), 'utf8');
|
|
16
|
-
} catch (e) {
|
|
17
|
-
process.exit(0);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
try {
|
|
21
|
-
if (isCopilot) {
|
|
22
|
-
process.stdout.write(JSON.stringify({ additionalContext: content }));
|
|
23
|
-
} else if (isCodex) {
|
|
24
|
-
process.stdout.write(JSON.stringify({
|
|
25
|
-
systemMessage: 'ASC:ACTIVE',
|
|
26
|
-
hookSpecificOutput: {
|
|
27
|
-
hookEventName: 'SessionStart',
|
|
28
|
-
additionalContext: content,
|
|
29
|
-
},
|
|
30
|
-
}));
|
|
31
|
-
} else {
|
|
32
|
-
process.stdout.write(content);
|
|
33
|
-
}
|
|
34
|
-
} catch (e) {
|
|
35
|
-
// Silent fail — stdout closed/EPIPE at hook exit must not surface as a hook failure
|
|
36
|
-
}
|
package/hooks/subagent-start.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// Agentic Senior Core — SubagentStart hook
|
|
3
|
-
// SessionStart context is parent-thread only and never reaches subagents.
|
|
4
|
-
// This injects the same ruleset into each subagent.
|
|
5
|
-
|
|
6
|
-
const fs = require('fs');
|
|
7
|
-
const path = require('path');
|
|
8
|
-
|
|
9
|
-
const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT || path.resolve(__dirname, '..');
|
|
10
|
-
const isCopilot = Boolean(process.env.COPILOT_PLUGIN_DATA);
|
|
11
|
-
const isCodex = !isCopilot && Boolean(process.env.PLUGIN_DATA);
|
|
12
|
-
|
|
13
|
-
let content;
|
|
14
|
-
try {
|
|
15
|
-
content = fs.readFileSync(path.join(pluginRoot, 'AGENTS.md'), 'utf8');
|
|
16
|
-
} catch (e) {
|
|
17
|
-
process.exit(0);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
try {
|
|
21
|
-
if (isCodex) {
|
|
22
|
-
process.stdout.write(JSON.stringify({
|
|
23
|
-
hookSpecificOutput: {
|
|
24
|
-
hookEventName: 'SubagentStart',
|
|
25
|
-
additionalContext: content,
|
|
26
|
-
},
|
|
27
|
-
}));
|
|
28
|
-
} else {
|
|
29
|
-
process.stdout.write(JSON.stringify({
|
|
30
|
-
hookSpecificOutput: {
|
|
31
|
-
hookEventName: 'SubagentStart',
|
|
32
|
-
additionalContext: content,
|
|
33
|
-
},
|
|
34
|
-
}));
|
|
35
|
-
}
|
|
36
|
-
} catch (e) {
|
|
37
|
-
// Silent fail
|
|
38
|
-
}
|
package/skills/asc/SKILL.md
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: asc
|
|
3
|
-
description: >
|
|
4
|
-
Universal AI coding rules. Write code like a staff engineer. Use this skill when user asks for general coding guidelines, best practices, standard rules, code quality standards, or when acting as a senior/staff software engineer.
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Agentic Senior Core
|
|
8
|
-
|
|
9
|
-
Universal AI coding rules. Write code like a staff engineer.
|
|
10
|
-
|
|
11
|
-
## Available Commands
|
|
12
|
-
|
|
13
|
-
- `/asc-new-project` -- Greenfield workflow (Define -> Spec -> Implement -> Validate)
|
|
14
|
-
- `/asc-add-feature` -- Brownfield workflow (Research -> Plan -> Implement)
|
|
15
|
-
- `/asc-refactor` -- Structured refactoring workflow with pre-checks and validation
|
|
16
|
-
- `/asc-review` -- Production-risk code review with severity-ordered findings
|
|
17
|
-
- `/asc-audit` -- Security and architecture audit
|
|
18
|
-
- `/asc-reference` -- Domain-specific rules (testing, API, database, frontend, infra, resilience)
|
|
19
|
-
- `/asc-debt` -- Track deferred enforcement violations (add, list, resolve, summary)
|
|
20
|
-
- `/asc-help` -- Show this help
|
|
21
|
-
|
|
22
|
-
## Enforcement
|
|
23
|
-
|
|
24
|
-
On plugin-tier hosts (Claude Code, Codex CLI, Copilot CLI), a PostToolUse hook fires after every Edit/Write and checks:
|
|
25
|
-
- New dependencies against stdlib duplicates (decision ladder step 3)
|
|
26
|
-
- LOC delta > 30 lines on edits (step 5)
|
|
27
|
-
- New files > 50 lines (steps 1–2)
|
|
28
|
-
- Workflow gate violations: source/config edits during research or plan phases
|
|
29
|
-
|
|
30
|
-
Violations inject a nudge referencing the specific ladder step or workflow phase. The hook is silent when no issues are found. All enforcement is advisory — nudges, not hard blocks.
|
|
31
|
-
|
|
32
|
-
## What It Does
|
|
33
|
-
|
|
34
|
-
Loads universal engineering rules on every session: code quality, architecture, security, error handling, testing, API design, database, frontend, infrastructure, resilience, and async patterns.
|
|
35
|
-
|
|
36
|
-
Rules apply to any project, stack, language, or framework. No per-project configuration needed.
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: asc-adapter
|
|
3
|
-
description: >
|
|
4
|
-
Detect installed AI coding hosts and generate adapter files for the current project. Use this skill when user asks to install, configure, setup, or initialize Agentic Senior Core rules, adapter files, or plugins for their IDE (Cursor, Windsurf, Devin, Copilot, Roo, Cline, Aider, Kiro).
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# ASC Adapter
|
|
8
|
-
|
|
9
|
-
Detect installed AI coding hosts and generate adapter files for the current project.
|
|
10
|
-
|
|
11
|
-
## When to use
|
|
12
|
-
|
|
13
|
-
Run this when setting up a new project or when a developer wants ASC rules active across all their AI coding tools.
|
|
14
|
-
|
|
15
|
-
## Steps
|
|
16
|
-
|
|
17
|
-
1. Run `asc status` to detect which AI coding hosts are installed on this system.
|
|
18
|
-
2. Check which adapter files already exist in the current project directory.
|
|
19
|
-
3. For any detected host that is missing an adapter, run `asc adapter --<host>` to generate it.
|
|
20
|
-
4. Use `asc adapter --all` to generate adapters for all supported hosts at once.
|
|
21
|
-
|
|
22
|
-
## Supported hosts
|
|
23
|
-
|
|
24
|
-
Plugin hosts (always-on, no adapter needed): Claude Code, Codex CLI, Gemini CLI, Antigravity CLI, Copilot CLI, Devin CLI, Hermes, OpenCode, OpenClaw.
|
|
25
|
-
|
|
26
|
-
Adapter hosts (one file per project): Cursor, Devin Desktop, Cline, GitHub Copilot, Kiro, Continue, Zed, Aider, Kilo Code, Roo Code, OpenHands.
|
|
27
|
-
|
|
28
|
-
## Commands
|
|
29
|
-
|
|
30
|
-
```bash
|
|
31
|
-
asc status # Show detected hosts
|
|
32
|
-
asc adapter --all # Generate all adapters
|
|
33
|
-
asc adapter --cursor # Generate for specific host
|
|
34
|
-
asc uninstall # Remove all ASC adapter files
|
|
35
|
-
asc uninstall --dry-run # Preview what would be removed
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
## Notes
|
|
39
|
-
|
|
40
|
-
- Adapter files contain the ASC universal coding rules, compressed to fit within each host's size limits.
|
|
41
|
-
- Cursor uses `.mdc` format with `alwaysApply: true` frontmatter.
|
|
42
|
-
- Windsurf is now Devin Desktop. Use `--devin` for the preferred path, `--windsurf` for legacy.
|
|
43
|
-
- Zed also reads `AGENTS.md` natively, so the adapter is optional.
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: asc-add-feature
|
|
3
|
-
description: >
|
|
4
|
-
Structured brownfield workflow. Adapted from QRSPI to prevent context rot and ensure alignment before building. Use this skill when user asks to add new features, build new endpoints, extend existing functionality, implement new UI components, modify an existing codebase, or work on brownfield development.
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Add Feature Workflow
|
|
8
|
-
|
|
9
|
-
Structured brownfield workflow. Adapted from QRSPI to prevent context rot and ensure alignment before building.
|
|
10
|
-
|
|
11
|
-
Grounded in: RPI (Dex Horthy, HumanLayer 2025) with corrections from QRSPI 8-stage evolution (Coding Agents Conference, March 2026). Plan-reading illusion fix and instruction budget constraint applied. Stages 2/5/7 adapted; stages 1/3/4/6/8 skipped as too heavyweight for individual-developer workflow.
|
|
12
|
-
|
|
13
|
-
## Gate Mechanism & Scaled Spec Requirement
|
|
14
|
-
|
|
15
|
-
This workflow nudges the agent to stop at each phase boundary, same enforcement tier as the existing decision ladder — not a hard block. Bypasses are logged to the debt ledger.
|
|
16
|
-
|
|
17
|
-
For brownfield feature development (`asc-add-feature`), Phase 2 requires a lightweight **PRD.md** (or feature spec in `docs/PRD.md`) defining product intent, goals, and non-goals to avoid scope creep and context rot.
|
|
18
|
-
|
|
19
|
-
To track phase, write to `workflow-gate.json` via the `state_write` MCP tool.
|
|
20
|
-
Format:
|
|
21
|
-
```json
|
|
22
|
-
{
|
|
23
|
-
"workflow": "asc-add-feature",
|
|
24
|
-
"phase": "<current_phase>",
|
|
25
|
-
"updatedAt": "<ISO-timestamp>"
|
|
26
|
-
}
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
## Phase 1: Research (No Code Changes)
|
|
30
|
-
|
|
31
|
-
1. Write `workflow-gate.json` with phase `research`.
|
|
32
|
-
2. Map existing code: patterns, utilities, dependencies already in use.
|
|
33
|
-
3. Identify what must NOT be rebuilt (e.g., existing validation helpers).
|
|
34
|
-
4. Output a factual research summary.
|
|
35
|
-
5. **STOP and wait for user approval.** Do not plan or implement.
|
|
36
|
-
|
|
37
|
-
## Phase 2: Plan
|
|
38
|
-
|
|
39
|
-
1. On approval of Phase 1, update `workflow-gate.json` phase to `plan`.
|
|
40
|
-
2. Ensure `docs/PRD.md` or feature brief exists.
|
|
41
|
-
3. Create a numbered, step-by-step implementation plan with specific files, functions, and line references.
|
|
42
|
-
4. Include a "Don't Build" list from the research phase.
|
|
43
|
-
5. **Callout: Plan-Reading Illusion.** Ask the user to explicitly verify the plan against the codebase, not just skim it.
|
|
44
|
-
6. Output the plan.
|
|
45
|
-
7. **STOP and wait for user approval.** Do not implement.
|
|
46
|
-
|
|
47
|
-
## Phase 3: Implement
|
|
48
|
-
|
|
49
|
-
1. On approval of Phase 2, update `workflow-gate.json` phase to `implement`.
|
|
50
|
-
2. Recommend a fresh context (intentional compaction) if the context window is getting full.
|
|
51
|
-
3. Execute the approved plan.
|
|
52
|
-
4. Validate: tests pass, no duplicate code introduced, plan items checked off.
|
|
53
|
-
5. On completion, clear the state in `workflow-gate.json` by overwriting it with `{}`.
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: asc-audit
|
|
3
|
-
description: >
|
|
4
|
-
Security and architecture audit. Deeper than review, focused on finding vulnerabilities and structural anti-patterns. Use this skill for deep security audits, architecture reviews, vulnerability scanning, threat modeling, finding OWASP risks (XSS, SQLi), penetration testing, or identifying structural anti-patterns.
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Audit Skill
|
|
8
|
-
|
|
9
|
-
Security and architecture audit. Deeper than review, focused on finding vulnerabilities and structural anti-patterns.
|
|
10
|
-
|
|
11
|
-
Grounded in: OWASP Top 10 (2021), OWASP ASVS v4, CVSS vulnerability report structure, CWE classification.
|
|
12
|
-
|
|
13
|
-
## Audit Scope
|
|
14
|
-
|
|
15
|
-
1. **Trust boundaries**: Every point where external input enters the system. Validate that inputs are sanitized, normalized, and rejected when invalid.
|
|
16
|
-
2. **Authentication and authorization**: Verify auth checks exist on every endpoint. Check for resource-level authorization, not just identity.
|
|
17
|
-
3. **Data handling**: Secrets in code or logs, PII exposure, unsafe deserialization, SQL injection, command injection.
|
|
18
|
-
4. **Architecture boundaries**: Business logic in transport layer, shared databases between services, circular dependencies, internal model leakage through public APIs.
|
|
19
|
-
5. **Dependency health**: Known vulnerabilities, unmaintained packages, excessive dependency surface.
|
|
20
|
-
6. **Error exposure**: Stack traces, internal paths, or implementation details exposed to clients.
|
|
21
|
-
|
|
22
|
-
## For Every Finding
|
|
23
|
-
|
|
24
|
-
```
|
|
25
|
-
Severity: critical | high | medium | low
|
|
26
|
-
Class: vulnerability class (e.g., SQL Injection, Broken Access Control)
|
|
27
|
-
Location: file:line
|
|
28
|
-
Impact: who or what is affected
|
|
29
|
-
Evidence: exact code, behavior, or command output
|
|
30
|
-
Remediation: specific fix direction
|
|
31
|
-
Validation: how to prove it is fixed
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
## Output
|
|
35
|
-
|
|
36
|
-
Findings ordered by severity. If no findings, state that explicitly and describe audit coverage.
|