@ryuenn3123/agentic-senior-core 6.11.0 → 6.12.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/.agents/plugins/agentic-senior-core/.codex-plugin/plugin.json +1 -1
- package/.agents/plugins/agentic-senior-core/hooks/post-edit-enforce.js +82 -10
- package/.agents/plugins/agentic-senior-core/hooks.json +22 -138
- package/.agents/plugins/agentic-senior-core/plugin.json +1 -1
- package/.agents/plugins/agentic-senior-core/rules/agentic-senior-core.md +6 -2
- package/.agents/plugins/agentic-senior-core/skills/asc/SKILL.md +5 -1
- package/.agents/plugins/agentic-senior-core/skills/asc-add-feature/SKILL.md +12 -6
- package/.agents/plugins/agentic-senior-core/skills/asc-audit/SKILL.md +11 -10
- package/.agents/plugins/agentic-senior-core/skills/asc-fingerprint/SKILL.md +2 -1
- package/.agents/plugins/agentic-senior-core/skills/asc-new-project/SKILL.md +2 -2
- package/.agents/plugins/agentic-senior-core/skills/asc-refactor/SKILL.md +1 -0
- package/.agents/plugins/agentic-senior-core/skills/asc-reference/SKILL.md +15 -5
- package/.agents/plugins/agentic-senior-core/skills/asc-review/SKILL.md +8 -5
- package/bin/agentic-senior-core.js +0 -8
- package/gemini-extension.json +1 -1
- package/lib/cli/commands/git-hook-generator.mjs +12 -2
- package/package.json +1 -3
- package/plugin.yaml +1 -1
- package/lib/cli/commands/mcp.mjs +0 -3
- package/scripts/mcp-server/constants.mjs +0 -57
- package/scripts/mcp-server/tool-registry.mjs +0 -204
- package/scripts/mcp-server/tools.mjs +0 -592
- package/scripts/mcp-server.mjs +0 -202
|
@@ -57,16 +57,50 @@ const {
|
|
|
57
57
|
} = require('./constants.cjs');
|
|
58
58
|
|
|
59
59
|
// Module-level counter for Claude Code path (resets per process spawn)
|
|
60
|
-
|
|
60
|
+
function logHook(event, msg) {
|
|
61
|
+
try {
|
|
62
|
+
const os = require('os');
|
|
63
|
+
const logDir = path.join(os.homedir(), '.asc');
|
|
64
|
+
if (!fs.existsSync(logDir)) fs.mkdirSync(logDir, { recursive: true });
|
|
65
|
+
const logFile = path.join(logDir, 'hooks.log');
|
|
66
|
+
try {
|
|
67
|
+
if (fs.existsSync(logFile)) {
|
|
68
|
+
const stats = fs.statSync(logFile);
|
|
69
|
+
if (stats.size > 100 * 1024) {
|
|
70
|
+
const content = fs.readFileSync(logFile, 'utf8');
|
|
71
|
+
const trimmed = content.slice(-50 * 1024);
|
|
72
|
+
const firstNewline = trimmed.indexOf('\n');
|
|
73
|
+
fs.writeFileSync(logFile, firstNewline >= 0 ? trimmed.slice(firstNewline + 1) : trimmed, 'utf8');
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
} catch (_) {}
|
|
77
|
+
fs.appendFileSync(logFile, `[${new Date().toISOString()}] [post-edit-enforce] [${event}] ${msg}\n`, 'utf8');
|
|
78
|
+
} catch (_) {}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
logHook('ScriptStart', `pid=${process.pid} cwd=${process.cwd()}`);
|
|
82
|
+
|
|
83
|
+
if (process.stdin.isTTY) {
|
|
84
|
+
logHook('StdinTTY', 'Exiting because stdin is a TTY');
|
|
85
|
+
process.exit(0);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const stdinTimeout = setTimeout(() => {
|
|
89
|
+
logHook('StdinTimeout', `No input after 3s, exiting bufferLen=${inputBuffer.length}`);
|
|
90
|
+
process.exit(0);
|
|
91
|
+
}, 3000);
|
|
61
92
|
|
|
62
93
|
let inputBuffer = '';
|
|
63
94
|
process.stdin.setEncoding('utf8');
|
|
64
95
|
process.stdin.on('data', chunk => {
|
|
65
96
|
inputBuffer += chunk;
|
|
97
|
+
logHook('DataChunk', `len=${chunk.length} preview=${chunk.slice(0, 100).replace(/[\r\n]+/g, ' ')}`);
|
|
66
98
|
try {
|
|
67
99
|
const data = JSON.parse(inputBuffer);
|
|
100
|
+
clearTimeout(stdinTimeout);
|
|
101
|
+
logHook('StdinData', 'keys=' + Object.keys(data).join(','));
|
|
68
102
|
|
|
69
|
-
if (data.
|
|
103
|
+
if (data.transcriptPath) {
|
|
70
104
|
handleAntigravityPostInvocation(data);
|
|
71
105
|
return;
|
|
72
106
|
}
|
|
@@ -82,6 +116,32 @@ process.stdin.on('data', chunk => {
|
|
|
82
116
|
}
|
|
83
117
|
});
|
|
84
118
|
|
|
119
|
+
process.stdin.on('end', () => {
|
|
120
|
+
clearTimeout(stdinTimeout);
|
|
121
|
+
logHook('StdinEnd', `bufferLen=${inputBuffer.length}`);
|
|
122
|
+
if (inputBuffer.trim()) {
|
|
123
|
+
try {
|
|
124
|
+
const data = JSON.parse(inputBuffer);
|
|
125
|
+
logHook('ParsedInputOnEnd', 'keys=' + Object.keys(data).join(','));
|
|
126
|
+
if (data.transcriptPath) {
|
|
127
|
+
handleAntigravityPostInvocation(data);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const toolName = data.tool_name || '';
|
|
131
|
+
const toolInput = data.tool_input || {};
|
|
132
|
+
processSingleEdit(toolName, toolInput, function (nudge) {
|
|
133
|
+
emitClaude(nudge);
|
|
134
|
+
});
|
|
135
|
+
process.exit(0);
|
|
136
|
+
} catch (e) {
|
|
137
|
+
logHook('JsonParseErrorOnEnd', e.message);
|
|
138
|
+
process.exit(0);
|
|
139
|
+
}
|
|
140
|
+
} else {
|
|
141
|
+
process.exit(0);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
|
|
85
145
|
function handleAntigravityPostInvocation(data) {
|
|
86
146
|
try {
|
|
87
147
|
if (!fs.existsSync(data.transcriptPath)) return;
|
|
@@ -133,22 +193,32 @@ function handleAntigravityPostInvocation(data) {
|
|
|
133
193
|
+ '(2) Does the codebase already have this? (3) Stdlib/native? (4) Existing dependency?');
|
|
134
194
|
}
|
|
135
195
|
|
|
136
|
-
|
|
196
|
+
const isPostToolUse = data.stepIdx !== undefined;
|
|
197
|
+
logHook('AntigravityResult', `sourceEdits=${sourceEditsSinceStart}, findings=${findings.length}, isPostToolUse=${isPostToolUse}`);
|
|
198
|
+
|
|
199
|
+
if (isPostToolUse) {
|
|
200
|
+
process.stdout.write(JSON.stringify({}) + '\n');
|
|
201
|
+
} else if (findings.length > 0) {
|
|
137
202
|
const injectSteps = findings.map(function (f) { return { ephemeralMessage: f }; });
|
|
138
203
|
process.stdout.write(JSON.stringify({ injectSteps: injectSteps }) + '\n');
|
|
139
204
|
} else {
|
|
140
205
|
process.stdout.write(JSON.stringify({}) + '\n');
|
|
141
206
|
}
|
|
142
207
|
} catch (e) {
|
|
208
|
+
logHook('AntigravityError', e.message);
|
|
143
209
|
process.stdout.write(JSON.stringify({}) + '\n');
|
|
144
210
|
}
|
|
211
|
+
process.exit(0);
|
|
145
212
|
}
|
|
146
213
|
|
|
147
214
|
function processSingleEdit(toolName, toolInput, emitFn, skipArray) {
|
|
148
|
-
const filePath = toolInput.file_path || '';
|
|
215
|
+
const filePath = toolInput.file_path || toolInput.TargetFile || toolInput.filePath || '';
|
|
149
216
|
if (!filePath) return;
|
|
150
217
|
const findings = [];
|
|
151
218
|
|
|
219
|
+
const isEdit = toolName === 'Edit' || toolName === 'replace_file_content' || toolName === 'multi_replace_file_content';
|
|
220
|
+
const isWrite = toolName === 'Write' || toolName === 'write_to_file';
|
|
221
|
+
|
|
152
222
|
// Increment per-process counter for Claude Code drift detection
|
|
153
223
|
const ext = path.extname(filePath).slice(1);
|
|
154
224
|
if (SOURCE_EXTENSIONS.has(ext)) {
|
|
@@ -168,9 +238,9 @@ function processSingleEdit(toolName, toolInput, emitFn, skipArray) {
|
|
|
168
238
|
}
|
|
169
239
|
|
|
170
240
|
if (SOURCE_EXTENSIONS.has(ext)) {
|
|
171
|
-
if (
|
|
241
|
+
if (isEdit) {
|
|
172
242
|
checkLocDelta(toolInput, filePath, findings);
|
|
173
|
-
} else if (
|
|
243
|
+
} else if (isWrite) {
|
|
174
244
|
checkNewFileSize(toolInput, filePath, findings);
|
|
175
245
|
}
|
|
176
246
|
}
|
|
@@ -191,6 +261,8 @@ function processSingleEdit(toolName, toolInput, emitFn, skipArray) {
|
|
|
191
261
|
checkWorkflowGate(toolName, filePath, ext, findings);
|
|
192
262
|
}
|
|
193
263
|
|
|
264
|
+
logHook('ProcessSingleEdit', 'tool=' + toolName + ', file=' + filePath + ', findings=' + findings.length);
|
|
265
|
+
|
|
194
266
|
if (findings.length === 0) return;
|
|
195
267
|
|
|
196
268
|
const nudge = '[ASC enforcement] ' + findings.join(' ') + ' Review the decision ladder before continuing.';
|
|
@@ -256,8 +328,8 @@ function extractDeps(text, pattern) {
|
|
|
256
328
|
}
|
|
257
329
|
|
|
258
330
|
function checkLocDelta(toolInput, filePath, findings) {
|
|
259
|
-
var newLines = (toolInput.new_string || '').split('\n').length;
|
|
260
|
-
var oldLines = (toolInput.old_string || '').split('\n').length;
|
|
331
|
+
var newLines = (toolInput.new_string || toolInput.ReplacementContent || '').split('\n').length;
|
|
332
|
+
var oldLines = (toolInput.old_string || toolInput.TargetContent || '').split('\n').length;
|
|
261
333
|
var delta = newLines - oldLines;
|
|
262
334
|
if (delta > LOC_DELTA_THRESHOLD) {
|
|
263
335
|
findings.push(
|
|
@@ -268,7 +340,7 @@ function checkLocDelta(toolInput, filePath, findings) {
|
|
|
268
340
|
}
|
|
269
341
|
|
|
270
342
|
function checkNewFileSize(toolInput, filePath, findings) {
|
|
271
|
-
var lines = (toolInput.content || '').split('\n').length;
|
|
343
|
+
var lines = (toolInput.content || toolInput.CodeContent || '').split('\n').length;
|
|
272
344
|
if (lines > NEW_FILE_LINE_THRESHOLD) {
|
|
273
345
|
// Step 1-2 coverage ("does this already exist?") moved to dedup-gate.js
|
|
274
346
|
// which provides concrete file-name + overlap-percentage feedback.
|
|
@@ -327,7 +399,7 @@ function checkSecurityPatterns(toolName, toolInput, filePath, findings) {
|
|
|
327
399
|
}
|
|
328
400
|
|
|
329
401
|
function checkUiSlopPatterns(toolName, toolInput, filePath, findings) {
|
|
330
|
-
var target = toolName === 'Edit' ? (toolInput.new_string || '') : (toolInput.content || '');
|
|
402
|
+
var target = toolName === 'Edit' ? (toolInput.new_string || toolInput.ReplacementContent || '') : (toolInput.content || toolInput.CodeContent || '');
|
|
331
403
|
if (!target) return;
|
|
332
404
|
|
|
333
405
|
if (UI_SLOP_PATTERNS.patterns) {
|
|
@@ -1,121 +1,4 @@
|
|
|
1
1
|
{
|
|
2
|
-
"agentic-senior-core": {
|
|
3
|
-
"SessionStart": [
|
|
4
|
-
{
|
|
5
|
-
"matcher": "startup|resume|clear|compact",
|
|
6
|
-
"hooks": [
|
|
7
|
-
{
|
|
8
|
-
"type": "command",
|
|
9
|
-
"command": "node -e \"const p=require('path'),fs=require('fs'),os=require('os');const local=p.join(process.cwd(),'.agents','plugins','agentic-senior-core','hooks','session-start.js');const g1=p.join(os.homedir(),'.agents','plugins','agentic-senior-core','hooks','session-start.js');const g2=p.join(os.homedir(),'.gemini','config','plugins','agentic-senior-core','hooks','session-start.js');const g3=p.join(os.homedir(),'.gemini','antigravity-cli','plugins','agentic-senior-core','hooks','session-start.js');require(fs.existsSync(local)?local:(fs.existsSync(g1)?g1:(fs.existsSync(g2)?g2:g3)));\"",
|
|
10
|
-
"commandWindows": "if (Get-Command node -ErrorAction SilentlyContinue) { $root = if ($env:PLUGIN_ROOT) { $env:PLUGIN_ROOT } else { if ($env:CLAUDE_PLUGIN_ROOT) { $env:CLAUDE_PLUGIN_ROOT } else { if (Test-Path \"$env:USERPROFILE\\.agents\\plugins\\agentic-senior-core\") { \"$env:USERPROFILE\\.agents\\plugins\\agentic-senior-core\" } else { \"$env:USERPROFILE\\.gemini\\config\\plugins\\agentic-senior-core\" } } }; node \"$root\\hooks\\session-start.js\" }",
|
|
11
|
-
"timeout": 5,
|
|
12
|
-
"statusMessage": "Loading ASC rules..."
|
|
13
|
-
}
|
|
14
|
-
]
|
|
15
|
-
}
|
|
16
|
-
],
|
|
17
|
-
"SubagentStart": [
|
|
18
|
-
{
|
|
19
|
-
"hooks": [
|
|
20
|
-
{
|
|
21
|
-
"type": "command",
|
|
22
|
-
"command": "node -e \"const p=require('path'),fs=require('fs'),os=require('os');const local=p.join(process.cwd(),'.agents','plugins','agentic-senior-core','hooks','subagent-start.js');const g1=p.join(os.homedir(),'.agents','plugins','agentic-senior-core','hooks','subagent-start.js');const g2=p.join(os.homedir(),'.gemini','config','plugins','agentic-senior-core','hooks','subagent-start.js');const g3=p.join(os.homedir(),'.gemini','antigravity-cli','plugins','agentic-senior-core','hooks','subagent-start.js');require(fs.existsSync(local)?local:(fs.existsSync(g1)?g1:(fs.existsSync(g2)?g2:g3)));\"",
|
|
23
|
-
"commandWindows": "if (Get-Command node -ErrorAction SilentlyContinue) { $root = if ($env:PLUGIN_ROOT) { $env:PLUGIN_ROOT } else { if ($env:CLAUDE_PLUGIN_ROOT) { $env:CLAUDE_PLUGIN_ROOT } else { if (Test-Path \"$env:USERPROFILE\\.agents\\plugins\\agentic-senior-core\") { \"$env:USERPROFILE\\.agents\\plugins\\agentic-senior-core\" } else { \"$env:USERPROFILE\\.gemini\\config\\plugins\\agentic-senior-core\" } } }; node \"$root\\hooks\\subagent-start.js\" }",
|
|
24
|
-
"timeout": 5,
|
|
25
|
-
"statusMessage": "Loading ASC rules..."
|
|
26
|
-
}
|
|
27
|
-
]
|
|
28
|
-
}
|
|
29
|
-
],
|
|
30
|
-
"PreToolUse": [
|
|
31
|
-
{
|
|
32
|
-
"matcher": "Edit|Write|replace_file_content|write_to_file|write_file|multi_replace_file_content",
|
|
33
|
-
"hooks": [
|
|
34
|
-
{
|
|
35
|
-
"type": "command",
|
|
36
|
-
"if": "Edit(**/package.json)|Edit(**/requirements.txt)|Edit(**/pyproject.toml)|Edit(**/go.mod)|Edit(**/Cargo.toml)|Edit(**/Gemfile)",
|
|
37
|
-
"command": "node -e \"const p=require('path'),fs=require('fs'),os=require('os');const local=p.join(process.cwd(),'.agents','plugins','agentic-senior-core','hooks','pre-tool-dependency-gate.js');const g1=p.join(os.homedir(),'.agents','plugins','agentic-senior-core','hooks','pre-tool-dependency-gate.js');const g2=p.join(os.homedir(),'.gemini','config','plugins','agentic-senior-core','hooks','pre-tool-dependency-gate.js');const g3=p.join(os.homedir(),'.gemini','antigravity-cli','plugins','agentic-senior-core','hooks','pre-tool-dependency-gate.js');require(fs.existsSync(local)?local:(fs.existsSync(g1)?g1:(fs.existsSync(g2)?g2:g3)));\"",
|
|
38
|
-
"commandWindows": "if (Get-Command node -ErrorAction SilentlyContinue) { $root = if ($env:PLUGIN_ROOT) { $env:PLUGIN_ROOT } else { if ($env:CLAUDE_PLUGIN_ROOT) { $env:CLAUDE_PLUGIN_ROOT } else { if (Test-Path \"$env:USERPROFILE\\.agents\\plugins\\agentic-senior-core\") { \"$env:USERPROFILE\\.agents\\plugins\\agentic-senior-core\" } else { \"$env:USERPROFILE\\.gemini\\config\\plugins\\agentic-senior-core\" } } }; node \"$root\\hooks\\pre-tool-dependency-gate.js\" }",
|
|
39
|
-
"timeout": 5,
|
|
40
|
-
"statusMessage": "ASC Pre-tool dependency check (Edit)..."
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
"type": "command",
|
|
44
|
-
"if": "Write(**/package.json)|Write(**/requirements.txt)|Write(**/pyproject.toml)|Write(**/go.mod)|Write(**/Cargo.toml)|Write(**/Gemfile)",
|
|
45
|
-
"command": "node -e \"const p=require('path'),fs=require('fs'),os=require('os');const local=p.join(process.cwd(),'.agents','plugins','agentic-senior-core','hooks','pre-tool-dependency-gate.js');const g1=p.join(os.homedir(),'.agents','plugins','agentic-senior-core','hooks','pre-tool-dependency-gate.js');const g2=p.join(os.homedir(),'.gemini','config','plugins','agentic-senior-core','hooks','pre-tool-dependency-gate.js');const g3=p.join(os.homedir(),'.gemini','antigravity-cli','plugins','agentic-senior-core','hooks','pre-tool-dependency-gate.js');require(fs.existsSync(local)?local:(fs.existsSync(g1)?g1:(fs.existsSync(g2)?g2:g3)));\"",
|
|
46
|
-
"commandWindows": "if (Get-Command node -ErrorAction SilentlyContinue) { $root = if ($env:PLUGIN_ROOT) { $env:PLUGIN_ROOT } else { if ($env:CLAUDE_PLUGIN_ROOT) { $env:CLAUDE_PLUGIN_ROOT } else { if (Test-Path \"$env:USERPROFILE\\.agents\\plugins\\agentic-senior-core\") { \"$env:USERPROFILE\\.agents\\plugins\\agentic-senior-core\" } else { \"$env:USERPROFILE\\.gemini\\config\\plugins\\agentic-senior-core\" } } }; node \"$root\\hooks\\pre-tool-dependency-gate.js\" }",
|
|
47
|
-
"timeout": 5,
|
|
48
|
-
"statusMessage": "ASC Pre-tool dependency check (Write)..."
|
|
49
|
-
}
|
|
50
|
-
]
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
"matcher": "Bash|run_command|run_shell_command|terminal|execute_command",
|
|
54
|
-
"hooks": [
|
|
55
|
-
{
|
|
56
|
-
"type": "command",
|
|
57
|
-
"command": "node -e \"const p=require('path'),fs=require('fs'),os=require('os');const local=p.join(process.cwd(),'.agents','plugins','agentic-senior-core','hooks','pre-tool-dependency-gate.js');const g1=p.join(os.homedir(),'.agents','plugins','agentic-senior-core','hooks','pre-tool-dependency-gate.js');const g2=p.join(os.homedir(),'.gemini','config','plugins','agentic-senior-core','hooks','pre-tool-dependency-gate.js');const g3=p.join(os.homedir(),'.gemini','antigravity-cli','plugins','agentic-senior-core','hooks','pre-tool-dependency-gate.js');require(fs.existsSync(local)?local:(fs.existsSync(g1)?g1:(fs.existsSync(g2)?g2:g3)));\"",
|
|
58
|
-
"commandWindows": "if (Get-Command node -ErrorAction SilentlyContinue) { $root = if ($env:PLUGIN_ROOT) { $env:PLUGIN_ROOT } else { if ($env:CLAUDE_PLUGIN_ROOT) { $env:CLAUDE_PLUGIN_ROOT } else { if (Test-Path \"$env:USERPROFILE\\.agents\\plugins\\agentic-senior-core\") { \"$env:USERPROFILE\\.agents\\plugins\\agentic-senior-core\" } else { \"$env:USERPROFILE\\.gemini\\config\\plugins\\agentic-senior-core\" } } }; node \"$root\\hooks\\pre-tool-dependency-gate.js\" }",
|
|
59
|
-
"timeout": 5,
|
|
60
|
-
"statusMessage": "ASC Pre-tool dependency check (Terminal)..."
|
|
61
|
-
}
|
|
62
|
-
]
|
|
63
|
-
}
|
|
64
|
-
],
|
|
65
|
-
"PostToolUse": [
|
|
66
|
-
{
|
|
67
|
-
"matcher": "Edit|Write|replace_file_content|write_to_file|write_file|multi_replace_file_content",
|
|
68
|
-
"hooks": [
|
|
69
|
-
{
|
|
70
|
-
"type": "command",
|
|
71
|
-
"command": "node -e \"const p=require('path'),fs=require('fs'),os=require('os');const local=p.join(process.cwd(),'.agents','plugins','agentic-senior-core','hooks','post-edit-enforce.js');const g1=p.join(os.homedir(),'.agents','plugins','agentic-senior-core','hooks','post-edit-enforce.js');const g2=p.join(os.homedir(),'.gemini','config','plugins','agentic-senior-core','hooks','post-edit-enforce.js');const g3=p.join(os.homedir(),'.gemini','antigravity-cli','plugins','agentic-senior-core','hooks','post-edit-enforce.js');require(fs.existsSync(local)?local:(fs.existsSync(g1)?g1:(fs.existsSync(g2)?g2:g3)));\"",
|
|
72
|
-
"commandWindows": "if (Get-Command node -ErrorAction SilentlyContinue) { $root = if ($env:PLUGIN_ROOT) { $env:PLUGIN_ROOT } else { if ($env:CLAUDE_PLUGIN_ROOT) { $env:CLAUDE_PLUGIN_ROOT } else { if (Test-Path \"$env:USERPROFILE\\.agents\\plugins\\agentic-senior-core\") { \"$env:USERPROFILE\\.agents\\plugins\\agentic-senior-core\" } else { \"$env:USERPROFILE\\.gemini\\config\\plugins\\agentic-senior-core\" } } }; node \"$root\\hooks\\post-edit-enforce.js\" }",
|
|
73
|
-
"timeout": 5,
|
|
74
|
-
"statusMessage": "ASC ladder & spec gate check..."
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
"type": "command",
|
|
78
|
-
"command": "node -e \"const p=require('path'),fs=require('fs'),os=require('os');const local=p.join(process.cwd(),'.agents','plugins','agentic-senior-core','hooks','dedup-gate.js');const g1=p.join(os.homedir(),'.agents','plugins','agentic-senior-core','hooks','dedup-gate.js');const g2=p.join(os.homedir(),'.gemini','config','plugins','agentic-senior-core','hooks','dedup-gate.js');const g3=p.join(os.homedir(),'.gemini','antigravity-cli','plugins','agentic-senior-core','hooks','dedup-gate.js');require(fs.existsSync(local)?local:(fs.existsSync(g1)?g1:(fs.existsSync(g2)?g2:g3)));\"",
|
|
79
|
-
"commandWindows": "if (Get-Command node -ErrorAction SilentlyContinue) { $root = if ($env:PLUGIN_ROOT) { $env:PLUGIN_ROOT } else { if ($env:CLAUDE_PLUGIN_ROOT) { $env:CLAUDE_PLUGIN_ROOT } else { if (Test-Path \"$env:USERPROFILE\\.agents\\plugins\\agentic-senior-core\") { \"$env:USERPROFILE\\.agents\\plugins\\agentic-senior-core\" } else { \"$env:USERPROFILE\\.gemini\\config\\plugins\\agentic-senior-core\" } } }; node \"$root\\hooks\\dedup-gate.js\" }",
|
|
80
|
-
"timeout": 15,
|
|
81
|
-
"statusMessage": "ASC duplicate-code scan..."
|
|
82
|
-
}
|
|
83
|
-
]
|
|
84
|
-
}
|
|
85
|
-
],
|
|
86
|
-
"PreInvocation": [
|
|
87
|
-
{
|
|
88
|
-
"type": "command",
|
|
89
|
-
"command": "node -e \"const p=require('path'),fs=require('fs'),os=require('os');const local=p.join(process.cwd(),'.agents','plugins','agentic-senior-core','hooks','session-pulse.js');const g1=p.join(os.homedir(),'.agents','plugins','agentic-senior-core','hooks','session-pulse.js');const g2=p.join(os.homedir(),'.gemini','config','plugins','agentic-senior-core','hooks','session-pulse.js');const g3=p.join(os.homedir(),'.gemini','antigravity-cli','plugins','agentic-senior-core','hooks','session-pulse.js');require(fs.existsSync(local)?local:(fs.existsSync(g1)?g1:(fs.existsSync(g2)?g2:g3)));\"",
|
|
90
|
-
"commandWindows": "if (Get-Command node -ErrorAction SilentlyContinue) { $root = if ($env:PLUGIN_ROOT) { $env:PLUGIN_ROOT } else { if ($env:CLAUDE_PLUGIN_ROOT) { $env:CLAUDE_PLUGIN_ROOT } else { if (Test-Path \"$env:USERPROFILE\\.agents\\plugins\\agentic-senior-core\") { \"$env:USERPROFILE\\.agents\\plugins\\agentic-senior-core\" } else { \"$env:USERPROFILE\\.gemini\\config\\plugins\\agentic-senior-core\" } } }; node \"$root\\hooks\\session-pulse.js\" }",
|
|
91
|
-
"timeout": 5,
|
|
92
|
-
"statusMessage": "Loading ASC rules..."
|
|
93
|
-
},
|
|
94
|
-
{
|
|
95
|
-
"type": "command",
|
|
96
|
-
"command": "node -e \"const p=require('path'),fs=require('fs'),os=require('os');const local=p.join(process.cwd(),'.agents','plugins','agentic-senior-core','hooks','ladder-pulse.js');const g1=p.join(os.homedir(),'.agents','plugins','agentic-senior-core','hooks','ladder-pulse.js');const g2=p.join(os.homedir(),'.gemini','config','plugins','agentic-senior-core','hooks','ladder-pulse.js');const g3=p.join(os.homedir(),'.gemini','antigravity-cli','plugins','agentic-senior-core','hooks','ladder-pulse.js');require(fs.existsSync(local)?local:(fs.existsSync(g1)?g1:(fs.existsSync(g2)?g2:g3)));\"",
|
|
97
|
-
"commandWindows": "if (Get-Command node -ErrorAction SilentlyContinue) { $root = if ($env:PLUGIN_ROOT) { $env:PLUGIN_ROOT } else { if ($env:CLAUDE_PLUGIN_ROOT) { $env:CLAUDE_PLUGIN_ROOT } else { if (Test-Path \"$env:USERPROFILE\\.agents\\plugins\\agentic-senior-core\") { \"$env:USERPROFILE\\.agents\\plugins\\agentic-senior-core\" } else { \"$env:USERPROFILE\\.gemini\\config\\plugins\\agentic-senior-core\" } } }; node \"$root\\hooks\\ladder-pulse.js\" }",
|
|
98
|
-
"timeout": 5,
|
|
99
|
-
"statusMessage": "ASC ladder pulse..."
|
|
100
|
-
}
|
|
101
|
-
],
|
|
102
|
-
"PostInvocation": [
|
|
103
|
-
{
|
|
104
|
-
"type": "command",
|
|
105
|
-
"command": "node -e \"const p=require('path'),fs=require('fs'),os=require('os');const local=p.join(process.cwd(),'.agents','plugins','agentic-senior-core','hooks','post-edit-enforce.js');const g1=p.join(os.homedir(),'.agents','plugins','agentic-senior-core','hooks','post-edit-enforce.js');const g2=p.join(os.homedir(),'.gemini','config','plugins','agentic-senior-core','hooks','post-edit-enforce.js');const g3=p.join(os.homedir(),'.gemini','antigravity-cli','plugins','agentic-senior-core','hooks','post-edit-enforce.js');require(fs.existsSync(local)?local:(fs.existsSync(g1)?g1:(fs.existsSync(g2)?g2:g3)));\"",
|
|
106
|
-
"timeout": 15
|
|
107
|
-
}
|
|
108
|
-
],
|
|
109
|
-
"PreCompact": [
|
|
110
|
-
{
|
|
111
|
-
"type": "command",
|
|
112
|
-
"command": "node -e \"const p=require('path'),fs=require('fs'),os=require('os');const local=p.join(process.cwd(),'.agents','plugins','agentic-senior-core','hooks','pre-compact-pin.js');const g1=p.join(os.homedir(),'.agents','plugins','agentic-senior-core','hooks','pre-compact-pin.js');const g2=p.join(os.homedir(),'.gemini','config','plugins','agentic-senior-core','hooks','pre-compact-pin.js');const g3=p.join(os.homedir(),'.gemini','antigravity-cli','plugins','agentic-senior-core','hooks','pre-compact-pin.js');require(fs.existsSync(local)?local:(fs.existsSync(g1)?g1:(fs.existsSync(g2)?g2:g3)));\"",
|
|
113
|
-
"commandWindows": "if (Get-Command node -ErrorAction SilentlyContinue) { $root = if ($env:PLUGIN_ROOT) { $env:PLUGIN_ROOT } else { if ($env:CLAUDE_PLUGIN_ROOT) { $env:CLAUDE_PLUGIN_ROOT } else { if (Test-Path \"$env:USERPROFILE\\.agents\\plugins\\agentic-senior-core\") { \"$env:USERPROFILE\\.agents\\plugins\\agentic-senior-core\" } else { \"$env:USERPROFILE\\.gemini\\config\\plugins\\agentic-senior-core\" } } }; node \"$root\\hooks\\pre-compact-pin.js\" }",
|
|
114
|
-
"timeout": 5,
|
|
115
|
-
"statusMessage": "ASC constraint pinning..."
|
|
116
|
-
}
|
|
117
|
-
]
|
|
118
|
-
},
|
|
119
2
|
"hooks": {
|
|
120
3
|
"SessionStart": [
|
|
121
4
|
{
|
|
@@ -123,8 +6,8 @@
|
|
|
123
6
|
"hooks": [
|
|
124
7
|
{
|
|
125
8
|
"type": "command",
|
|
126
|
-
"command": "node
|
|
127
|
-
"commandWindows": "
|
|
9
|
+
"command": "node hooks/session-start.js",
|
|
10
|
+
"commandWindows": "node hooks/session-start.js",
|
|
128
11
|
"timeout": 5,
|
|
129
12
|
"statusMessage": "Loading ASC rules..."
|
|
130
13
|
}
|
|
@@ -136,8 +19,8 @@
|
|
|
136
19
|
"hooks": [
|
|
137
20
|
{
|
|
138
21
|
"type": "command",
|
|
139
|
-
"command": "node
|
|
140
|
-
"commandWindows": "
|
|
22
|
+
"command": "node hooks/subagent-start.js",
|
|
23
|
+
"commandWindows": "node hooks/subagent-start.js",
|
|
141
24
|
"timeout": 5,
|
|
142
25
|
"statusMessage": "Loading ASC rules..."
|
|
143
26
|
}
|
|
@@ -151,16 +34,16 @@
|
|
|
151
34
|
{
|
|
152
35
|
"type": "command",
|
|
153
36
|
"if": "Edit(**/package.json)|Edit(**/requirements.txt)|Edit(**/pyproject.toml)|Edit(**/go.mod)|Edit(**/Cargo.toml)|Edit(**/Gemfile)",
|
|
154
|
-
"command": "node
|
|
155
|
-
"commandWindows": "
|
|
37
|
+
"command": "node hooks/pre-tool-dependency-gate.js",
|
|
38
|
+
"commandWindows": "node hooks/pre-tool-dependency-gate.js",
|
|
156
39
|
"timeout": 5,
|
|
157
40
|
"statusMessage": "ASC Pre-tool dependency check (Edit)..."
|
|
158
41
|
},
|
|
159
42
|
{
|
|
160
43
|
"type": "command",
|
|
161
44
|
"if": "Write(**/package.json)|Write(**/requirements.txt)|Write(**/pyproject.toml)|Write(**/go.mod)|Write(**/Cargo.toml)|Write(**/Gemfile)",
|
|
162
|
-
"command": "node
|
|
163
|
-
"commandWindows": "
|
|
45
|
+
"command": "node hooks/pre-tool-dependency-gate.js",
|
|
46
|
+
"commandWindows": "node hooks/pre-tool-dependency-gate.js",
|
|
164
47
|
"timeout": 5,
|
|
165
48
|
"statusMessage": "ASC Pre-tool dependency check (Write)..."
|
|
166
49
|
}
|
|
@@ -171,8 +54,8 @@
|
|
|
171
54
|
"hooks": [
|
|
172
55
|
{
|
|
173
56
|
"type": "command",
|
|
174
|
-
"command": "node
|
|
175
|
-
"commandWindows": "
|
|
57
|
+
"command": "node hooks/pre-tool-dependency-gate.js",
|
|
58
|
+
"commandWindows": "node hooks/pre-tool-dependency-gate.js",
|
|
176
59
|
"timeout": 5,
|
|
177
60
|
"statusMessage": "ASC Pre-tool dependency check (Terminal)..."
|
|
178
61
|
}
|
|
@@ -185,15 +68,15 @@
|
|
|
185
68
|
"hooks": [
|
|
186
69
|
{
|
|
187
70
|
"type": "command",
|
|
188
|
-
"command": "node
|
|
189
|
-
"commandWindows": "
|
|
71
|
+
"command": "node hooks/post-edit-enforce.js",
|
|
72
|
+
"commandWindows": "node hooks/post-edit-enforce.js",
|
|
190
73
|
"timeout": 5,
|
|
191
74
|
"statusMessage": "ASC ladder & spec gate check..."
|
|
192
75
|
},
|
|
193
76
|
{
|
|
194
77
|
"type": "command",
|
|
195
|
-
"command": "node
|
|
196
|
-
"commandWindows": "
|
|
78
|
+
"command": "node hooks/dedup-gate.js",
|
|
79
|
+
"commandWindows": "node hooks/dedup-gate.js",
|
|
197
80
|
"timeout": 15,
|
|
198
81
|
"statusMessage": "ASC duplicate-code scan..."
|
|
199
82
|
}
|
|
@@ -203,15 +86,15 @@
|
|
|
203
86
|
"PreInvocation": [
|
|
204
87
|
{
|
|
205
88
|
"type": "command",
|
|
206
|
-
"command": "node
|
|
207
|
-
"commandWindows": "
|
|
89
|
+
"command": "node hooks/session-pulse.js",
|
|
90
|
+
"commandWindows": "node hooks/session-pulse.js",
|
|
208
91
|
"timeout": 5,
|
|
209
92
|
"statusMessage": "Loading ASC rules..."
|
|
210
93
|
},
|
|
211
94
|
{
|
|
212
95
|
"type": "command",
|
|
213
|
-
"command": "node
|
|
214
|
-
"commandWindows": "
|
|
96
|
+
"command": "node hooks/ladder-pulse.js",
|
|
97
|
+
"commandWindows": "node hooks/ladder-pulse.js",
|
|
215
98
|
"timeout": 5,
|
|
216
99
|
"statusMessage": "ASC ladder pulse..."
|
|
217
100
|
}
|
|
@@ -219,15 +102,16 @@
|
|
|
219
102
|
"PostInvocation": [
|
|
220
103
|
{
|
|
221
104
|
"type": "command",
|
|
222
|
-
"command": "node
|
|
105
|
+
"command": "node hooks/post-edit-enforce.js",
|
|
106
|
+
"commandWindows": "node hooks/post-edit-enforce.js",
|
|
223
107
|
"timeout": 15
|
|
224
108
|
}
|
|
225
109
|
],
|
|
226
110
|
"PreCompact": [
|
|
227
111
|
{
|
|
228
112
|
"type": "command",
|
|
229
|
-
"command": "node
|
|
230
|
-
"commandWindows": "
|
|
113
|
+
"command": "node hooks/pre-compact-pin.js",
|
|
114
|
+
"commandWindows": "node hooks/pre-compact-pin.js",
|
|
231
115
|
"timeout": 5,
|
|
232
116
|
"statusMessage": "ASC constraint pinning..."
|
|
233
117
|
}
|
|
@@ -19,6 +19,8 @@ When picking step 5 or 6 (unless trivial):
|
|
|
19
19
|
- One-line comment noting rationale and upgrade trigger if there is a ceiling.
|
|
20
20
|
- One runnable check (assertion, test, or demo) proving it works.
|
|
21
21
|
- Never simulate success or return hardcoded values mimicking live integrations. Temporary stubs must be marked with `// ASC-STUB: [reason] [ASC-DEBT-xxx]` and tracked in the debt ledger.
|
|
22
|
+
- Action Feedback Invariant: Every mutation/user action (submit, delete, update) MUST have a pending state (disabled button/spinner) and visible completion feedback (toast or banner with actionable retry). Never silently swallow errors.
|
|
23
|
+
- Resilience Invariant: Soft dependencies must have defined fallbacks (static safe default, stale cache, or degraded mode). Protect UI sections with localized error boundaries.
|
|
22
24
|
|
|
23
25
|
## Security (never skip)
|
|
24
26
|
- Validate and normalize ALL inputs at trust boundaries.
|
|
@@ -50,9 +52,11 @@ When picking step 5 or 6 (unless trivial):
|
|
|
50
52
|
- UI component reuse: Component re-invention across pages is forbidden. Before declaring markup or styling, check existing components in `components/` or `ui/`. Compose or extend existing components via props/variants. Do not introduce single-page clones or ad-hoc styling that diverges from established pages.
|
|
51
53
|
|
|
52
54
|
## Error Handling & Observability
|
|
53
|
-
- Fail fast on invalid input at trust boundaries
|
|
55
|
+
- Fail fast on invalid input at trust boundaries; fail safe with graceful fallback for external runtime dependencies.
|
|
54
56
|
- Structured error responses with safe details (RFC 9457). Distinguish client (4xx) from server (5xx) errors.
|
|
55
|
-
-
|
|
57
|
+
- Action feedback: mutations (create, update, delete, submit) must provide immediate pending state (disable button/spinner) and clear success/error notification (toast or banner with retry). Never silently swallow mutation errors.
|
|
58
|
+
- UI data states: handle the state quad — loading skeleton/spinner, empty state, error state with retry, and populated data. Wrap critical UI widgets in localized error boundaries.
|
|
59
|
+
- External dependency resilience: classify dependencies as hard (fail fast + actionable error) or soft (fallback to static safe default, stale cache, or degraded mode).
|
|
56
60
|
- Surface every operational error with context. Empty catch blocks mask production issues.
|
|
57
61
|
- Structured key-value logging for significant events. Never leak stack traces or credentials in production logs.
|
|
58
62
|
|
|
@@ -14,9 +14,13 @@ Universal AI coding rules. Write code like a staff engineer.
|
|
|
14
14
|
- `/asc-add-feature` -- Brownfield workflow (Research -> Plan -> Implement)
|
|
15
15
|
- `/asc-refactor` -- Structured refactoring workflow with pre-checks and validation
|
|
16
16
|
- `/asc-review` -- Production-risk code review with severity-ordered findings
|
|
17
|
-
- `/asc-audit` -- Security and
|
|
17
|
+
- `/asc-audit` -- Security, architecture, and resilience audit
|
|
18
18
|
- `/asc-reference` -- Domain-specific rules (testing, API, database, frontend, infra, resilience)
|
|
19
|
+
- `/asc-fingerprint` -- Map repository conventions, notification providers, and error patterns
|
|
20
|
+
- `/asc-dedup` -- Token-level clone and duplicate code audit via jscpd
|
|
19
21
|
- `/asc-debt` -- Track deferred enforcement violations (add, list, resolve, summary)
|
|
22
|
+
- `/asc-learn` -- Mine adaptive user preferences from session history
|
|
23
|
+
- `/asc-bootstrap` -- Seed baseline UI and notification preferences
|
|
20
24
|
- `/asc-help` -- Show this help
|
|
21
25
|
|
|
22
26
|
## Enforcement
|
|
@@ -30,8 +30,8 @@ Format:
|
|
|
30
30
|
|
|
31
31
|
1. Write `workflow-gate.json` with phase `research`.
|
|
32
32
|
2. Map existing code: patterns, utilities, dependencies already in use. Locate at least one analogous feature/module and record its file paths.
|
|
33
|
-
3. **UI Component &
|
|
34
|
-
4. Output a factual research summary that separates what exists from what is proposed, including
|
|
33
|
+
3. **UI Component, Notification & Error Pattern Inventory**: Scan existing shared components (`components/`, `ui/`), page patterns, active toast/notification providers (e.g., Sonner, react-hot-toast, custom alert banners), and existing fallback/error boundary conventions. Explicitly identify what must NOT be rebuilt.
|
|
34
|
+
4. Output a factual research summary that separates what exists from what is proposed, including explicit `[REUSED COMPONENTS & HELPERS]` and `[NOTIFICATION & ERROR CONVENTIONS]` lists, with file paths for the two or three claims that drive the plan.
|
|
35
35
|
5. **STOP and wait for user approval.** Do not plan or implement.
|
|
36
36
|
|
|
37
37
|
## Phase 2: Plan
|
|
@@ -41,14 +41,20 @@ Format:
|
|
|
41
41
|
3. Check if `.github/workflows/asc-quality-gate.yml` exists. If not, include scaffolding it in your plan (must run linter, type-check, and audit) and remind the user to enable Branch Protection.
|
|
42
42
|
4. Create a numbered, step-by-step implementation plan with specific files, functions, and line references.
|
|
43
43
|
5. Include a "Don't Build" list and a "Reused Components" list from the research phase. For any proposed new UI component, justify why existing components cannot be reused or extended via props/variants.
|
|
44
|
-
6. **
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
6. **Mandatory Failure Modes, Fallbacks & User Feedback Matrix**: Define concrete behavior for every failure scenario:
|
|
45
|
+
- What happens on network/API failure or timeout? (Specify exact fallback data or state).
|
|
46
|
+
- What feedback does the user see? (Specify pending spinner, field error, or toast/banner message).
|
|
47
|
+
- How can the user recover? (Retry button, offline warning, or fallback form).
|
|
48
|
+
7. **Callout: Plan-Reading Illusion.** Ask the user to explicitly verify the critical plan claims against the referenced files, not just skim it.
|
|
49
|
+
8. Output the plan.
|
|
50
|
+
9. **STOP and wait for user approval.** Do not implement.
|
|
47
51
|
|
|
48
52
|
## Phase 3: Implement
|
|
49
53
|
|
|
50
54
|
1. On approval of Phase 2, update `workflow-gate.json` phase to `implement`.
|
|
51
55
|
2. Recommend a fresh context (intentional compaction) at the phase boundary or after roughly 20-30 tool calls. Do not wait until degradation is subjectively noticeable.
|
|
52
56
|
3. Execute the approved plan.
|
|
53
|
-
4. **Mandatory Verification**:
|
|
57
|
+
4. **Mandatory Verification**:
|
|
58
|
+
- Execute the project test suite (`ascx test`, `npm test`, `pytest`, `go test ./...`, or `cargo test`). The test runner MUST exit with code 0. Do NOT declare completion or weaken test assertions if tests fail.
|
|
59
|
+
- Verify failure and edge-case behavior: ensure pending indicators resolve, mutation errors show user-facing notifications with retry, and non-critical dependency failures trigger defined fallbacks instead of white-screens or unhandled rejections.
|
|
54
60
|
5. On verified pass, give a short comprehension summary of what changed and why, then clear the state in `workflow-gate.json` by overwriting it with `{}`.
|
|
@@ -24,21 +24,22 @@ Grounded in: OWASP Top 10 (2025), OWASP ASVS v5.0, OWASP Top 10 for Agentic Appl
|
|
|
24
24
|
4. **Architecture boundaries**: Business logic in transport layer, shared databases between services, circular dependencies, internal model leakage through public APIs.
|
|
25
25
|
5. **Dependency health**: Known vulnerabilities, unmaintained packages, excessive dependency surface.
|
|
26
26
|
6. **Error exposure**: Stack traces, internal paths, or implementation details exposed to clients.
|
|
27
|
+
7. **Reliability & Fault-Tolerance**: Unhandled async promises, unbounded network timeouts, empty catch blocks, missing fallbacks on non-critical dependencies, and silent mutation failures without user notifications.
|
|
27
28
|
|
|
28
29
|
## Agentic Risk Scope (OWASP Top 10 for Agentic Applications)
|
|
29
30
|
|
|
30
31
|
When the target is an AI agent system, MCP server, or plugin:
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
33
|
+
8. **Agent Goal Hijack (ASI01)**: Content read by the agent that could override instructions.
|
|
34
|
+
9. **Tool Misuse (ASI02)**: Tools callable without adequate validation of parameters.
|
|
35
|
+
10. **Identity & Privilege Abuse (ASI03)**: Agent running with broader permissions than needed.
|
|
36
|
+
11. **Agentic Supply Chain (ASI04)**: Untrusted plugins, MCP servers, or dependencies.
|
|
37
|
+
12. **Unexpected Code Execution (ASI05)**: Agent-generated code running without sandbox.
|
|
38
|
+
13. **Memory & Context Poisoning (ASI06)**: State files or persistent memory injectable by untrusted sources. Note: ASC's own `debt-ledger.json` and `workflow-gate.json` are potential targets — treat as untrusted input at load time.
|
|
39
|
+
14. **Inter-Agent Communication (ASI07)**: Agent-to-agent messages without integrity checks.
|
|
40
|
+
15. **Cascading Failures (ASI08)**: Multi-agent chains where one failure propagates.
|
|
41
|
+
16. **Human-Agent Trust Exploitation (ASI09)**: UI/UX that misleads user about agent actions.
|
|
42
|
+
17. **Rogue Agents (ASI10)**: Agent behavior diverging from intended purpose.
|
|
42
43
|
|
|
43
44
|
## For Every Finding
|
|
44
45
|
|
|
@@ -18,7 +18,8 @@ generic architecture score.
|
|
|
18
18
|
|
|
19
19
|
1. Read local instructions and list the active runtime, test, and deployment surfaces.
|
|
20
20
|
2. Find two or more analogous modules. Record their layer split, naming, validation,
|
|
21
|
-
error handling,
|
|
21
|
+
error handling, user notification/toast provider, fallback patterns, tests, and
|
|
22
|
+
documentation conventions with file paths.
|
|
22
23
|
3. Inspect recent Git history (up to 200 commits, or since the last fingerprint) for
|
|
23
24
|
repeated review corrections, reverts, and release conventions.
|
|
24
25
|
4. Read a debt ledger only when it exists. Treat repeated entries as a possible
|
|
@@ -15,8 +15,8 @@ Grounded in: Spec-Driven Development (SDD) with scaffolding-spec approach. Core
|
|
|
15
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
16
|
|
|
17
17
|
For greenfield projects (`asc-new-project`), Phase 2 requires creating the **3 Core SDD Documents** in `docs/` or project root:
|
|
18
|
-
1. `PRD.md` — Product intent, goals, non-goals, and user
|
|
19
|
-
2. `Architecture.md` — System structure, module boundaries,
|
|
18
|
+
1. `PRD.md` — Product intent, goals, non-goals, user problems, and user feedback expectations.
|
|
19
|
+
2. `Architecture.md` — System structure, module boundaries, tech stack choices, and global error handling, fallback, and notification strategy.
|
|
20
20
|
3. `Schema.md` — Data contracts, database entities, API endpoints.
|
|
21
21
|
|
|
22
22
|
*Note on Rules:* Coding conventions and project constraints are automatically loaded from global plugin rules (`agentic-senior-core.md`) or workspace `AGENTS.md`. No duplicate `docs/Rules.md` file is required.
|
|
@@ -38,6 +38,7 @@ After reading the target code, classify the refactor:
|
|
|
38
38
|
## Refactor Rules
|
|
39
39
|
|
|
40
40
|
- Improve clarity, boundaries, naming, validation, error handling, and tests.
|
|
41
|
+
- Action Feedback & Fallbacks: Preserve all user feedback indicators, error toasts, and dependency fallbacks. Refactoring must never silently drop error-handling branches.
|
|
41
42
|
- Prioritize maintainability over compressed one-liners.
|
|
42
43
|
- Keep the main flow traceable. Use early returns where they reduce nesting.
|
|
43
44
|
- Introduce abstractions only when the repeated pattern is real and visible.
|