@ryuenn3123/agentic-senior-core 5.8.13 → 5.8.14

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.
@@ -0,0 +1,74 @@
1
+ {
2
+ "hooks": {
3
+ "SessionStart": [
4
+ {
5
+ "matcher": "startup|resume|clear|compact",
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/session-start.js\"; exit 0",
10
+ "commandWindows": "if (Get-Command node -ErrorAction SilentlyContinue) { node \"$env:CLAUDE_PLUGIN_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 \"${CLAUDE_PLUGIN_ROOT}/hooks/subagent-start.js\"; exit 0",
23
+ "commandWindows": "if (Get-Command node -ErrorAction SilentlyContinue) { node \"$env:CLAUDE_PLUGIN_ROOT\\hooks\\subagent-start.js\" }",
24
+ "timeout": 5,
25
+ "statusMessage": "Loading ASC rules..."
26
+ }
27
+ ]
28
+ }
29
+ ],
30
+ "PreToolUse": [
31
+ {
32
+ "matcher": "Edit|Write",
33
+ "hooks": [
34
+ {
35
+ "type": "command",
36
+ "if": "Edit(**/package.json)",
37
+ "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/pre-tool-dependency-gate.js\"; exit 0",
38
+ "commandWindows": "if (Get-Command node -ErrorAction SilentlyContinue) { node \"$env:CLAUDE_PLUGIN_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)",
45
+ "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/pre-tool-dependency-gate.js\"; exit 0",
46
+ "commandWindows": "if (Get-Command node -ErrorAction SilentlyContinue) { node \"$env:CLAUDE_PLUGIN_ROOT\\hooks\\pre-tool-dependency-gate.js\" }",
47
+ "timeout": 5,
48
+ "statusMessage": "ASC Pre-tool dependency check (Write)..."
49
+ }
50
+ ]
51
+ }
52
+ ],
53
+ "PostToolUse": [
54
+ {
55
+ "matcher": "Edit|Write",
56
+ "hooks": [
57
+ {
58
+ "type": "command",
59
+ "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/post-edit-enforce.js\"; exit 0",
60
+ "commandWindows": "if (Get-Command node -ErrorAction SilentlyContinue) { node \"$env:CLAUDE_PLUGIN_ROOT\\hooks\\post-edit-enforce.js\" }",
61
+ "timeout": 5,
62
+ "statusMessage": "ASC ladder & spec gate check..."
63
+ },
64
+ {
65
+ "type": "prompt",
66
+ "if": "Edit(**/package.json)",
67
+ "prompt": "A new dependency '$ARGUMENTS' was added to package.json. Does it duplicate Node.js standard library or platform features? If yes, return JSON: {\"hookSpecificOutput\": {\"hookEventName\": \"PostToolUse\", \"additionalContext\": \"[ASC Advisory] The newly added dependency appears to duplicate stdlib or platform features. Consider native alternatives.\"}}. If no, return {}.",
68
+ "timeout": 30
69
+ }
70
+ ]
71
+ }
72
+ ]
73
+ }
74
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "description": "Single source of truth for packages that duplicate standard library or native platform features.",
3
+ "duplicates": [
4
+ "lodash",
5
+ "lodash-es",
6
+ "underscore",
7
+ "moment",
8
+ "dayjs",
9
+ "uuid",
10
+ "nanoid",
11
+ "chalk",
12
+ "kleur",
13
+ "colorette",
14
+ "axios",
15
+ "got",
16
+ "node-fetch",
17
+ "superagent",
18
+ "mkdirp",
19
+ "rimraf",
20
+ "del",
21
+ "glob",
22
+ "globby",
23
+ "left-pad",
24
+ "pad-left",
25
+ "is-odd",
26
+ "is-even",
27
+ "is-number",
28
+ "is-string",
29
+ "path-exists",
30
+ "fs-extra"
31
+ ]
32
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }
@@ -0,0 +1,23 @@
1
+ const crypto = require('crypto');
2
+ const path = require('path');
3
+ const os = require('os');
4
+
5
+ /**
6
+ * Computes a stable path for the workflow gate file based on the project path.
7
+ * Normalizes the path (resolves absolute, lowercase, forward slashes, no trailing slash)
8
+ * to ensure identical hashes regardless of OS path separator or drive letter casing.
9
+ * Note: .toLowerCase() deliberately treats Linux/Mac paths case-insensitively,
10
+ * accepting the negligible risk of collisions for the benefit of Windows stability.
11
+ *
12
+ * @param {string} projectPath - The root path of the project.
13
+ * @returns {string} Absolute path to the global workflow gate JSON file.
14
+ */
15
+ function getWorkflowGatePath(projectPath) {
16
+ const normalizedPath = path.resolve(projectPath).replace(/\\/g, '/').toLowerCase().replace(/\/$/, '');
17
+ const projectHash = crypto.createHash('sha256').update(normalizedPath).digest('hex').substring(0, 16);
18
+ return path.join(os.homedir(), '.config', 'agentic-senior-core', 'gates', `${projectHash}.json`);
19
+ }
20
+
21
+ module.exports = {
22
+ getWorkflowGatePath
23
+ };
@@ -0,0 +1,234 @@
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
+ }
@@ -0,0 +1,108 @@
1
+ #!/usr/bin/env node
2
+ // Agentic Senior Core — PreToolUse dependency gate hook
3
+ // Hard-blocks edits/writes to package.json if new dependencies duplicate stdlib/platform features.
4
+ // Supports Claude Code hookSpecificOutput permissionDecision deny response format.
5
+
6
+ const fs = require('fs');
7
+ const path = require('path');
8
+
9
+ let knownDuplicates = new Set();
10
+ try {
11
+ const knownPath = path.join(__dirname, 'lib', 'known-duplicates.json');
12
+ if (fs.existsSync(knownPath)) {
13
+ const raw = JSON.parse(fs.readFileSync(knownPath, 'utf8'));
14
+ if (Array.isArray(raw.duplicates)) {
15
+ knownDuplicates = new Set(raw.duplicates);
16
+ }
17
+ }
18
+ } catch (_) {
19
+ // Fallback set if JSON loading fails
20
+ knownDuplicates = new Set(['lodash', 'underscore', 'moment', 'dayjs', 'uuid', 'axios', 'rimraf']);
21
+ }
22
+
23
+ let inputBuffer = '';
24
+ process.stdin.setEncoding('utf8');
25
+ process.stdin.on('data', function (chunk) { inputBuffer += chunk; });
26
+ process.stdin.on('end', function () {
27
+ try {
28
+ const data = JSON.parse(inputBuffer);
29
+ const toolName = data.tool_name || '';
30
+ const toolInput = data.tool_input || {};
31
+ const filePath = toolInput.file_path || '';
32
+
33
+ if (!filePath.endsWith('package.json')) {
34
+ process.exit(0);
35
+ return;
36
+ }
37
+
38
+ const target = toolName === 'Edit' ? (toolInput.new_string || '') : (toolInput.content || '');
39
+ const baseline = toolName === 'Edit' ? (toolInput.old_string || '') : '';
40
+
41
+ const depPattern = /"([^"]+)"\s*:\s*"[~^>=<*]?\d/g;
42
+ const newDeps = extractDeps(target, depPattern);
43
+ const oldDeps = extractDeps(baseline, depPattern);
44
+
45
+ const added = newDeps.filter(function (d) { return oldDeps.indexOf(d) === -1; });
46
+ if (added.length === 0) {
47
+ process.exit(0);
48
+ return;
49
+ }
50
+
51
+ const allowlist = loadAllowlist();
52
+ const forbidden = added.filter(function (dep) {
53
+ return knownDuplicates.has(dep) && !allowlist.has(dep);
54
+ });
55
+
56
+ if (forbidden.length > 0) {
57
+ const reason = '[ASC Hard-Block] Dependency ' + forbidden.map(function(d){ return "'" + d + "'"; }).join(', ')
58
+ + ' duplicates standard library or native platform features. '
59
+ + 'Ladder step 3: use stdlib/native features instead, or add to .asc/dependency-allowlist.json to override.';
60
+
61
+ const output = {
62
+ hookSpecificOutput: {
63
+ hookEventName: 'PreToolUse',
64
+ permissionDecision: 'deny',
65
+ permissionDecisionReason: reason
66
+ }
67
+ };
68
+ process.stdout.write(JSON.stringify(output));
69
+ process.exit(0);
70
+ return;
71
+ }
72
+ } catch (_) {
73
+ // Silent fail to ensure session stability
74
+ }
75
+ process.exit(0);
76
+ });
77
+
78
+ function extractDeps(text, pattern) {
79
+ const matches = [];
80
+ let match;
81
+ while ((match = pattern.exec(text)) !== null) {
82
+ matches.push(match[1]);
83
+ }
84
+ return matches;
85
+ }
86
+
87
+ function loadAllowlist() {
88
+ const allowed = new Set();
89
+ const candidates = [
90
+ path.join(process.cwd(), '.asc', 'dependency-allowlist.json'),
91
+ path.join(process.cwd(), '.agents', 'dependency-allowlist.json')
92
+ ];
93
+
94
+ for (let i = 0; i < candidates.length; i++) {
95
+ try {
96
+ if (fs.existsSync(candidates[i])) {
97
+ const content = JSON.parse(fs.readFileSync(candidates[i], 'utf8'));
98
+ const deps = content.allowedDependencies || content.allowed || {};
99
+ if (Array.isArray(deps)) {
100
+ deps.forEach(function (d) { allowed.add(d); });
101
+ } else if (typeof deps === 'object') {
102
+ Object.keys(deps).forEach(function (d) { allowed.add(d); });
103
+ }
104
+ }
105
+ } catch (_) {}
106
+ }
107
+ return allowed;
108
+ }
@@ -0,0 +1,36 @@
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
+ }
@@ -0,0 +1,38 @@
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
+ }
@@ -10,11 +10,11 @@ Structured brownfield workflow. Adapted from QRSPI to prevent context rot and en
10
10
 
11
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
12
 
13
- ## Gate Mechanism
13
+ ## Gate Mechanism & Scaled Spec Requirement
14
14
 
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
- **Known limitation:** Bypass-to-debt-ledger logging is self-reported by the agent, not enforced by the hook. The PostToolUse hook has no MCP access it nudges the agent to log, but cannot write the debt entry itself.
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
18
 
19
19
  To track phase, write to `workflow-gate.json` via the `state_write` MCP tool.
20
20
  Format:
@@ -37,11 +37,12 @@ Format:
37
37
  ## Phase 2: Plan
38
38
 
39
39
  1. On approval of Phase 1, update `workflow-gate.json` phase to `plan`.
40
- 2. Create a numbered, step-by-step implementation plan with specific files, functions, and line references.
41
- 3. Include a "Don't Build" list from the research phase.
42
- 4. **Callout: Plan-Reading Illusion.** Ask the user to explicitly verify the plan against the codebase, not just skim it.
43
- 5. Output the plan.
44
- 6. **STOP and wait for user approval.** Do not implement.
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.
45
46
 
46
47
  ## Phase 3: Implement
47
48
 
@@ -8,13 +8,19 @@ description: >
8
8
 
9
9
  Structured greenfield workflow. Prevents building before alignment on what to build.
10
10
 
11
- Grounded in: Spec-Driven Development (SDD) with scaffolding-spec approach. Specs guide implementation, then the code becomes the source of truth specs are not maintained as living documents unless the team explicitly opts in.
11
+ Grounded in: Spec-Driven Development (SDD) with scaffolding-spec approach. Core spec documents guide greenfield implementation (`PRD.md`, `Architecture.md`, `Design.md`, `Schema.md`). Once implemented, the code becomes the primary ground truth, while docs are updated on structural changes.
12
12
 
13
- ## Gate Mechanism
13
+ ## Gate Mechanism & 4 Spec Document Requirement
14
14
 
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
- **Known limitation:** Bypass-to-debt-ledger logging is self-reported by the agent, not enforced by the hook. The PostToolUse hook has no MCP access — it nudges the agent to log, but cannot write the debt entry itself.
17
+ For greenfield projects (`asc-new-project`), Phase 2 requires creating the **4 Core SDD Documents** in `docs/` or project root:
18
+ 1. `PRD.md` — Product intent, goals, non-goals, and user problems.
19
+ 2. `Architecture.md` — System structure, module boundaries, and tech stack choices.
20
+ 3. `Design.md` — UX / UI layout, component hierarchy, interaction rules.
21
+ 4. `Schema.md` — Data contracts, database entities, API endpoints.
22
+
23
+ *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.
18
24
 
19
25
  To track phase, write to `workflow-gate.json` via the `state_write` MCP tool.
20
26
  Format:
@@ -37,16 +43,17 @@ Format:
37
43
  ## Phase 2: Spec (No Implementation Code)
38
44
 
39
45
  1. On approval of Phase 1, update `workflow-gate.json` phase to `plan`.
40
- 2. Write per-feature specs with acceptance criteria and edge cases.
41
- 3. Specs are scaffoldingthey guide the build, then the code is the source of truth.
46
+ 2. Generate the 4 core SDD documents from templates (`docs/PRD.md`, `docs/Architecture.md`, `docs/Design.md`, `docs/Schema.md`).
47
+ 3. Verify exact file naming check for typos like `Architectyre.md`.
42
48
  4. Output specs for review.
43
- 5. **STOP and wait for user approval.** Do not implement.
49
+ 5. **STOP and wait for user approval.** Do not implement code.
44
50
 
45
51
  ## Phase 3: Implement
46
52
 
47
53
  1. On approval of Phase 2, update `workflow-gate.json` phase to `implement`.
48
- 2. Build against the approved specs. Apply the ASC decision ladder on every file.
49
- 3. Run the decision ladder: does this need to exist? Does stdlib cover it? One function or full module?
54
+ 2. Run Anti Context-Blindness check: verify entities/tables mentioned in `Schema.md` or `Architecture.md` align with proposed code targets.
55
+ 3. Build against the approved specs. Apply the ASC decision ladder on every file.
56
+ 4. Run the decision ladder: does this need to exist? Does stdlib cover it? One function or full module?
50
57
 
51
58
  ## Phase 4: Validate
52
59
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-senior-core",
3
- "version": "5.8.13",
3
+ "version": "5.8.14",
4
4
  "displayName": "Agentic Senior Core",
5
5
  "description": "Universal AI coding rules. Write code like a staff engineer.",
6
6
  "author": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-senior-core",
3
- "version": "5.8.13",
3
+ "version": "5.8.14",
4
4
  "description": "Universal AI coding rules. Write code like a staff engineer.",
5
5
  "author": {
6
6
  "name": "fatidaprilian",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-senior-core",
3
- "version": "5.8.13",
3
+ "version": "5.8.14",
4
4
  "description": "Universal AI coding rules. Write code like a staff engineer.",
5
5
  "author": {
6
6
  "name": "fatidaprilian",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "agentic-senior-core",
3
3
  "description": "Universal AI coding rules. Write code like a staff engineer.",
4
- "version": "5.8.13",
4
+ "version": "5.8.14",
5
5
  "author": {
6
6
  "name": "fatidaprilian",
7
7
  "url": "https://github.com/fatidaprilian"
package/README.md CHANGED
@@ -13,12 +13,19 @@
13
13
 
14
14
  </div>
15
15
 
16
- ## How Skills Work (Plugins)
16
+ ## How Skills & Hooks Work (Multi-Tier Architecture)
17
17
 
18
- The plugin comes bundled with specialized skills (like security audits, refactoring, etc.).
18
+ Agentic Senior Core operates on a two-tier architecture:
19
19
 
20
- - **Automatic Triggering**: Agents attempt to detect and load these skills if your prompt matches the skill's description (e.g., asking "perform a security audit" will likely load the `asc-audit` skill). However, because AI relies on semantic probability, this is **never 100% guaranteed**.
21
- - **Manual Triggering (Highly Recommended)**: For maximum reliability and zero guesswork, explicitly call the skill using pseudo-commands like `/asc-refactor` or `/asc-new-project`. This forces the agent to enter the exact workflow immediately.
20
+ 1. **Instructional Layer (Universal Works in 23+ AI Tools)**:
21
+ - **Rules (`AGENTS.md` / `agentic-senior-core.md`) & Skills (`SKILL.md`)** are cross-compatible across **Google Antigravity IDE, Claude Code, Cursor, Windsurf, Copilot, Codex, Kiro, Roo, OpenCode, Zed, Aider, etc.**.
22
+ - **Automatic Skill Triggering**: Agents attempt to detect and load skills if your prompt matches the skill's description (e.g., asking "perform a security audit" loads `asc-audit`).
23
+ - **Manual Skill Triggering (Highly Recommended)**: Explicitly call skills using commands like `/asc-refactor` or `/asc-new-project` for guaranteed execution.
24
+
25
+ 2. **Active Enforcement Layer (Hooks — Host-Specific Hard Guardrails)**:
26
+ - **Hard-Block Guardrails**: For tools supporting active hook execution engines (Claude Code, GitHub Copilot CLI, Google Antigravity IDE, Cursor), ASC automatically intercepts tool calls:
27
+ - **PreToolUse Hard Block**: Immediately rejects edits adding stdlib-duplicating dependencies (e.g., `lodash`, `moment`, `uuid`) before execution (`permissionDecision: "deny"`). Escape hatch available via `.asc/dependency-allowlist.json`.
28
+ - **PostToolUse Advisory**: Soft nudges for LOC deltas, spec drift, and workflow gate bypasses.
22
29
 
23
30
  ---
24
31
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-senior-core",
3
- "version": "5.8.13",
3
+ "version": "5.8.14",
4
4
  "description": "Universal AI coding rules. Write code like a staff engineer.",
5
5
  "author": "fatidaprilian",
6
6
  "license": "MIT",
package/hooks/hooks.json CHANGED
@@ -27,6 +27,29 @@
27
27
  ]
28
28
  }
29
29
  ],
30
+ "PreToolUse": [
31
+ {
32
+ "matcher": "Edit|Write",
33
+ "hooks": [
34
+ {
35
+ "type": "command",
36
+ "if": "Edit(**/package.json)",
37
+ "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/pre-tool-dependency-gate.js\"; exit 0",
38
+ "commandWindows": "if (Get-Command node -ErrorAction SilentlyContinue) { node \"$env:CLAUDE_PLUGIN_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)",
45
+ "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/pre-tool-dependency-gate.js\"; exit 0",
46
+ "commandWindows": "if (Get-Command node -ErrorAction SilentlyContinue) { node \"$env:CLAUDE_PLUGIN_ROOT\\hooks\\pre-tool-dependency-gate.js\" }",
47
+ "timeout": 5,
48
+ "statusMessage": "ASC Pre-tool dependency check (Write)..."
49
+ }
50
+ ]
51
+ }
52
+ ],
30
53
  "PostToolUse": [
31
54
  {
32
55
  "matcher": "Edit|Write",
@@ -36,7 +59,13 @@
36
59
  "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/post-edit-enforce.js\"; exit 0",
37
60
  "commandWindows": "if (Get-Command node -ErrorAction SilentlyContinue) { node \"$env:CLAUDE_PLUGIN_ROOT\\hooks\\post-edit-enforce.js\" }",
38
61
  "timeout": 5,
39
- "statusMessage": "ASC ladder check..."
62
+ "statusMessage": "ASC ladder & spec gate check..."
63
+ },
64
+ {
65
+ "type": "prompt",
66
+ "if": "Edit(**/package.json)",
67
+ "prompt": "A new dependency '$ARGUMENTS' was added to package.json. Does it duplicate Node.js standard library or platform features? If yes, return JSON: {\"hookSpecificOutput\": {\"hookEventName\": \"PostToolUse\", \"additionalContext\": \"[ASC Advisory] The newly added dependency appears to duplicate stdlib or platform features. Consider native alternatives.\"}}. If no, return {}.",
68
+ "timeout": 30
40
69
  }
41
70
  ]
42
71
  }
@@ -0,0 +1,32 @@
1
+ {
2
+ "description": "Single source of truth for packages that duplicate standard library or native platform features.",
3
+ "duplicates": [
4
+ "lodash",
5
+ "lodash-es",
6
+ "underscore",
7
+ "moment",
8
+ "dayjs",
9
+ "uuid",
10
+ "nanoid",
11
+ "chalk",
12
+ "kleur",
13
+ "colorette",
14
+ "axios",
15
+ "got",
16
+ "node-fetch",
17
+ "superagent",
18
+ "mkdirp",
19
+ "rimraf",
20
+ "del",
21
+ "glob",
22
+ "globby",
23
+ "left-pad",
24
+ "pad-left",
25
+ "is-odd",
26
+ "is-even",
27
+ "is-number",
28
+ "is-string",
29
+ "path-exists",
30
+ "fs-extra"
31
+ ]
32
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }
@@ -6,7 +6,7 @@
6
6
  const fs = require('fs');
7
7
  const path = require('path');
8
8
 
9
- const STDLIB_DUPLICATES = new Set([
9
+ let STDLIB_DUPLICATES = new Set([
10
10
  'lodash', 'lodash-es', 'underscore',
11
11
  'moment', 'dayjs',
12
12
  'uuid', 'nanoid',
@@ -19,6 +19,16 @@ const STDLIB_DUPLICATES = new Set([
19
19
  'path-exists', 'fs-extra',
20
20
  ]);
21
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
+
22
32
  const SOURCE_EXTENSIONS = new Set([
23
33
  'js', 'ts', 'mjs', 'cjs', 'jsx', 'tsx',
24
34
  'py', 'rb', 'go', 'rs', 'java', 'kt', 'swift', 'cs',
@@ -38,7 +48,7 @@ process.stdin.on('end', function () {
38
48
  const filePath = toolInput.file_path || '';
39
49
  const findings = [];
40
50
 
41
- if (filePath.endsWith('package.json') || filePath.endsWith('package.json5')) {
51
+ if (filePath.endsWith('package.json')) {
42
52
  checkDependencyAddition(toolName, toolInput, findings);
43
53
  }
44
54
 
@@ -51,6 +61,8 @@ process.stdin.on('end', function () {
51
61
  }
52
62
  }
53
63
 
64
+ checkLivingDocNudge(filePath, findings);
65
+
54
66
  if (ext !== 'md') {
55
67
  checkWorkflowGate(toolName, filePath, ext, findings);
56
68
  }
@@ -120,6 +132,16 @@ function checkNewFileSize(toolInput, filePath, findings) {
120
132
  }
121
133
  }
122
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
+
123
145
  function checkWorkflowGate(toolName, filePath, ext, findings) {
124
146
  try {
125
147
  var pathUtil = require('./path-util.cjs');
@@ -143,12 +165,56 @@ function checkWorkflowGate(toolName, filePath, ext, findings) {
143
165
  'Workflow gate bypass: ' + gate.workflow + ' is in ' + gate.phase + ' phase but source code was edited. '
144
166
  + 'Stop and wait for phase approval. If you must proceed, log this bypass to the debt ledger.'
145
167
  );
168
+ } else if (gate.phase === 'implement') {
169
+ validateDocSpecs(gate.workflow, findings);
146
170
  }
147
171
  } catch (_) {
148
172
  // Silent fail
149
173
  }
150
174
  }
151
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
+
152
218
  function emit(nudge) {
153
219
  try {
154
220
  var isCopilot = Boolean(process.env.COPILOT_PLUGIN_DATA);
@@ -0,0 +1,108 @@
1
+ #!/usr/bin/env node
2
+ // Agentic Senior Core — PreToolUse dependency gate hook
3
+ // Hard-blocks edits/writes to package.json if new dependencies duplicate stdlib/platform features.
4
+ // Supports Claude Code hookSpecificOutput permissionDecision deny response format.
5
+
6
+ const fs = require('fs');
7
+ const path = require('path');
8
+
9
+ let knownDuplicates = new Set();
10
+ try {
11
+ const knownPath = path.join(__dirname, 'lib', 'known-duplicates.json');
12
+ if (fs.existsSync(knownPath)) {
13
+ const raw = JSON.parse(fs.readFileSync(knownPath, 'utf8'));
14
+ if (Array.isArray(raw.duplicates)) {
15
+ knownDuplicates = new Set(raw.duplicates);
16
+ }
17
+ }
18
+ } catch (_) {
19
+ // Fallback set if JSON loading fails
20
+ knownDuplicates = new Set(['lodash', 'underscore', 'moment', 'dayjs', 'uuid', 'axios', 'rimraf']);
21
+ }
22
+
23
+ let inputBuffer = '';
24
+ process.stdin.setEncoding('utf8');
25
+ process.stdin.on('data', function (chunk) { inputBuffer += chunk; });
26
+ process.stdin.on('end', function () {
27
+ try {
28
+ const data = JSON.parse(inputBuffer);
29
+ const toolName = data.tool_name || '';
30
+ const toolInput = data.tool_input || {};
31
+ const filePath = toolInput.file_path || '';
32
+
33
+ if (!filePath.endsWith('package.json')) {
34
+ process.exit(0);
35
+ return;
36
+ }
37
+
38
+ const target = toolName === 'Edit' ? (toolInput.new_string || '') : (toolInput.content || '');
39
+ const baseline = toolName === 'Edit' ? (toolInput.old_string || '') : '';
40
+
41
+ const depPattern = /"([^"]+)"\s*:\s*"[~^>=<*]?\d/g;
42
+ const newDeps = extractDeps(target, depPattern);
43
+ const oldDeps = extractDeps(baseline, depPattern);
44
+
45
+ const added = newDeps.filter(function (d) { return oldDeps.indexOf(d) === -1; });
46
+ if (added.length === 0) {
47
+ process.exit(0);
48
+ return;
49
+ }
50
+
51
+ const allowlist = loadAllowlist();
52
+ const forbidden = added.filter(function (dep) {
53
+ return knownDuplicates.has(dep) && !allowlist.has(dep);
54
+ });
55
+
56
+ if (forbidden.length > 0) {
57
+ const reason = '[ASC Hard-Block] Dependency ' + forbidden.map(function(d){ return "'" + d + "'"; }).join(', ')
58
+ + ' duplicates standard library or native platform features. '
59
+ + 'Ladder step 3: use stdlib/native features instead, or add to .asc/dependency-allowlist.json to override.';
60
+
61
+ const output = {
62
+ hookSpecificOutput: {
63
+ hookEventName: 'PreToolUse',
64
+ permissionDecision: 'deny',
65
+ permissionDecisionReason: reason
66
+ }
67
+ };
68
+ process.stdout.write(JSON.stringify(output));
69
+ process.exit(0);
70
+ return;
71
+ }
72
+ } catch (_) {
73
+ // Silent fail to ensure session stability
74
+ }
75
+ process.exit(0);
76
+ });
77
+
78
+ function extractDeps(text, pattern) {
79
+ const matches = [];
80
+ let match;
81
+ while ((match = pattern.exec(text)) !== null) {
82
+ matches.push(match[1]);
83
+ }
84
+ return matches;
85
+ }
86
+
87
+ function loadAllowlist() {
88
+ const allowed = new Set();
89
+ const candidates = [
90
+ path.join(process.cwd(), '.asc', 'dependency-allowlist.json'),
91
+ path.join(process.cwd(), '.agents', 'dependency-allowlist.json')
92
+ ];
93
+
94
+ for (let i = 0; i < candidates.length; i++) {
95
+ try {
96
+ if (fs.existsSync(candidates[i])) {
97
+ const content = JSON.parse(fs.readFileSync(candidates[i], 'utf8'));
98
+ const deps = content.allowedDependencies || content.allowed || {};
99
+ if (Array.isArray(deps)) {
100
+ deps.forEach(function (d) { allowed.add(d); });
101
+ } else if (typeof deps === 'object') {
102
+ Object.keys(deps).forEach(function (d) { allowed.add(d); });
103
+ }
104
+ }
105
+ } catch (_) {}
106
+ }
107
+ return allowed;
108
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ryuenn3123/agentic-senior-core",
3
- "version": "5.8.13",
3
+ "version": "5.8.14",
4
4
  "type": "module",
5
5
  "description": "Agentic Senior Core: Universal AI coding rules and workflows. Write code like a staff engineer, not a junior.",
6
6
  "bin": {
package/plugin.yaml CHANGED
@@ -1,5 +1,5 @@
1
1
  name: agentic-senior-core
2
- version: 5.8.13
2
+ version: 5.8.14
3
3
  description: Universal AI coding rules. Write code like a staff engineer.
4
4
  author: fatidaprilian
5
5
  provides_hooks:
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: asc-add-feature
3
3
  description: >
4
- Structured brownfield workflow. Adapted from QRSPI to prevent context rot and ensure alignment before building.
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
5
  ---
6
6
 
7
7
  # Add Feature Workflow
@@ -10,11 +10,11 @@ Structured brownfield workflow. Adapted from QRSPI to prevent context rot and en
10
10
 
11
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
12
 
13
- ## Gate Mechanism
13
+ ## Gate Mechanism & Scaled Spec Requirement
14
14
 
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
- **Known limitation:** Bypass-to-debt-ledger logging is self-reported by the agent, not enforced by the hook. The PostToolUse hook has no MCP access it nudges the agent to log, but cannot write the debt entry itself.
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
18
 
19
19
  To track phase, write to `workflow-gate.json` via the `state_write` MCP tool.
20
20
  Format:
@@ -37,11 +37,12 @@ Format:
37
37
  ## Phase 2: Plan
38
38
 
39
39
  1. On approval of Phase 1, update `workflow-gate.json` phase to `plan`.
40
- 2. Create a numbered, step-by-step implementation plan with specific files, functions, and line references.
41
- 3. Include a "Don't Build" list from the research phase.
42
- 4. **Callout: Plan-Reading Illusion.** Ask the user to explicitly verify the plan against the codebase, not just skim it.
43
- 5. Output the plan.
44
- 6. **STOP and wait for user approval.** Do not implement.
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.
45
46
 
46
47
  ## Phase 3: Implement
47
48
 
@@ -1,20 +1,26 @@
1
1
  ---
2
2
  name: asc-new-project
3
3
  description: >
4
- Structured greenfield workflow. Prevents building before alignment on what to build.
4
+ Structured greenfield workflow. Prevents building before alignment on what to build. Use this skill for greenfield projects, scaffolding new repositories, bootstrapping apps, starting from scratch, planning new system architectures, or creating a new project.
5
5
  ---
6
6
 
7
7
  # New Project Workflow
8
8
 
9
9
  Structured greenfield workflow. Prevents building before alignment on what to build.
10
10
 
11
- Grounded in: Spec-Driven Development (SDD) with scaffolding-spec approach. Specs guide implementation, then the code becomes the source of truth specs are not maintained as living documents unless the team explicitly opts in.
11
+ Grounded in: Spec-Driven Development (SDD) with scaffolding-spec approach. Core spec documents guide greenfield implementation (`PRD.md`, `Architecture.md`, `Design.md`, `Schema.md`). Once implemented, the code becomes the primary ground truth, while docs are updated on structural changes.
12
12
 
13
- ## Gate Mechanism
13
+ ## Gate Mechanism & 4 Spec Document Requirement
14
14
 
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
- **Known limitation:** Bypass-to-debt-ledger logging is self-reported by the agent, not enforced by the hook. The PostToolUse hook has no MCP access — it nudges the agent to log, but cannot write the debt entry itself.
17
+ For greenfield projects (`asc-new-project`), Phase 2 requires creating the **4 Core SDD Documents** in `docs/` or project root:
18
+ 1. `PRD.md` — Product intent, goals, non-goals, and user problems.
19
+ 2. `Architecture.md` — System structure, module boundaries, and tech stack choices.
20
+ 3. `Design.md` — UX / UI layout, component hierarchy, interaction rules.
21
+ 4. `Schema.md` — Data contracts, database entities, API endpoints.
22
+
23
+ *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.
18
24
 
19
25
  To track phase, write to `workflow-gate.json` via the `state_write` MCP tool.
20
26
  Format:
@@ -37,16 +43,17 @@ Format:
37
43
  ## Phase 2: Spec (No Implementation Code)
38
44
 
39
45
  1. On approval of Phase 1, update `workflow-gate.json` phase to `plan`.
40
- 2. Write per-feature specs with acceptance criteria and edge cases.
41
- 3. Specs are scaffoldingthey guide the build, then the code is the source of truth.
46
+ 2. Generate the 4 core SDD documents from templates (`docs/PRD.md`, `docs/Architecture.md`, `docs/Design.md`, `docs/Schema.md`).
47
+ 3. Verify exact file naming check for typos like `Architectyre.md`.
42
48
  4. Output specs for review.
43
- 5. **STOP and wait for user approval.** Do not implement.
49
+ 5. **STOP and wait for user approval.** Do not implement code.
44
50
 
45
51
  ## Phase 3: Implement
46
52
 
47
53
  1. On approval of Phase 2, update `workflow-gate.json` phase to `implement`.
48
- 2. Build against the approved specs. Apply the ASC decision ladder on every file.
49
- 3. Run the decision ladder: does this need to exist? Does stdlib cover it? One function or full module?
54
+ 2. Run Anti Context-Blindness check: verify entities/tables mentioned in `Schema.md` or `Architecture.md` align with proposed code targets.
55
+ 3. Build against the approved specs. Apply the ASC decision ladder on every file.
56
+ 4. Run the decision ladder: does this need to exist? Does stdlib cover it? One function or full module?
50
57
 
51
58
  ## Phase 4: Validate
52
59