@sienklogic/plan-build-run 2.21.0 → 2.22.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.
Files changed (104) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/CLAUDE.md +2 -2
  3. package/package.json +1 -1
  4. package/plugins/copilot-pbr/agents/codebase-mapper.agent.md +1 -1
  5. package/plugins/copilot-pbr/agents/debugger.agent.md +2 -0
  6. package/plugins/copilot-pbr/agents/executor.agent.md +4 -1
  7. package/plugins/copilot-pbr/agents/general.agent.md +2 -1
  8. package/plugins/copilot-pbr/agents/integration-checker.agent.md +2 -0
  9. package/plugins/copilot-pbr/agents/plan-checker.agent.md +1 -1
  10. package/plugins/copilot-pbr/agents/planner.agent.md +3 -1
  11. package/plugins/copilot-pbr/agents/researcher.agent.md +5 -3
  12. package/plugins/copilot-pbr/agents/synthesizer.agent.md +1 -1
  13. package/plugins/copilot-pbr/agents/verifier.agent.md +3 -3
  14. package/plugins/copilot-pbr/hooks/hooks.json +37 -13
  15. package/plugins/copilot-pbr/plugin.json +1 -1
  16. package/plugins/copilot-pbr/skills/audit/SKILL.md +1 -1
  17. package/plugins/copilot-pbr/skills/build/SKILL.md +7 -8
  18. package/plugins/copilot-pbr/skills/config/SKILL.md +1 -1
  19. package/plugins/copilot-pbr/skills/continue/SKILL.md +8 -2
  20. package/plugins/copilot-pbr/skills/debug/SKILL.md +1 -1
  21. package/plugins/copilot-pbr/skills/import/SKILL.md +3 -1
  22. package/plugins/copilot-pbr/skills/milestone/SKILL.md +2 -0
  23. package/plugins/copilot-pbr/skills/pause/SKILL.md +7 -1
  24. package/plugins/copilot-pbr/skills/plan/SKILL.md +1 -1
  25. package/plugins/copilot-pbr/skills/review/SKILL.md +4 -4
  26. package/plugins/copilot-pbr/skills/scan/SKILL.md +4 -4
  27. package/plugins/copilot-pbr/skills/shared/config-loading.md +1 -1
  28. package/plugins/copilot-pbr/skills/shared/context-budget.md +3 -3
  29. package/plugins/copilot-pbr/skills/shared/state-loading.md +1 -1
  30. package/plugins/copilot-pbr/skills/shared/state-update.md +12 -4
  31. package/plugins/copilot-pbr/skills/shared/universal-anti-patterns.md +1 -1
  32. package/plugins/copilot-pbr/templates/ROADMAP.md.tmpl +7 -0
  33. package/plugins/cursor-pbr/.cursor-plugin/plugin.json +1 -1
  34. package/plugins/cursor-pbr/agents/codebase-mapper.md +1 -1
  35. package/plugins/cursor-pbr/agents/debugger.md +2 -0
  36. package/plugins/cursor-pbr/agents/executor.md +4 -1
  37. package/plugins/cursor-pbr/agents/general.md +2 -1
  38. package/plugins/cursor-pbr/agents/integration-checker.md +2 -0
  39. package/plugins/cursor-pbr/agents/plan-checker.md +1 -1
  40. package/plugins/cursor-pbr/agents/planner.md +3 -1
  41. package/plugins/cursor-pbr/agents/researcher.md +5 -3
  42. package/plugins/cursor-pbr/agents/synthesizer.md +1 -1
  43. package/plugins/cursor-pbr/agents/verifier.md +3 -3
  44. package/plugins/cursor-pbr/hooks/hooks.json +20 -0
  45. package/plugins/cursor-pbr/skills/audit/SKILL.md +1 -1
  46. package/plugins/cursor-pbr/skills/build/SKILL.md +7 -8
  47. package/plugins/cursor-pbr/skills/config/SKILL.md +1 -1
  48. package/plugins/cursor-pbr/skills/continue/SKILL.md +8 -2
  49. package/plugins/cursor-pbr/skills/debug/SKILL.md +1 -1
  50. package/plugins/cursor-pbr/skills/import/SKILL.md +3 -1
  51. package/plugins/cursor-pbr/skills/milestone/SKILL.md +2 -0
  52. package/plugins/cursor-pbr/skills/pause/SKILL.md +7 -1
  53. package/plugins/cursor-pbr/skills/plan/SKILL.md +1 -1
  54. package/plugins/cursor-pbr/skills/review/SKILL.md +4 -4
  55. package/plugins/cursor-pbr/skills/scan/SKILL.md +4 -4
  56. package/plugins/cursor-pbr/skills/shared/config-loading.md +1 -1
  57. package/plugins/cursor-pbr/skills/shared/context-budget.md +3 -3
  58. package/plugins/cursor-pbr/skills/shared/state-loading.md +1 -1
  59. package/plugins/cursor-pbr/skills/shared/state-update.md +12 -4
  60. package/plugins/cursor-pbr/skills/shared/universal-anti-patterns.md +1 -1
  61. package/plugins/cursor-pbr/templates/ROADMAP.md.tmpl +7 -0
  62. package/plugins/pbr/.claude-plugin/plugin.json +1 -1
  63. package/plugins/pbr/agents/codebase-mapper.md +1 -1
  64. package/plugins/pbr/agents/debugger.md +2 -0
  65. package/plugins/pbr/agents/executor.md +4 -1
  66. package/plugins/pbr/agents/general.md +2 -1
  67. package/plugins/pbr/agents/integration-checker.md +2 -0
  68. package/plugins/pbr/agents/plan-checker.md +0 -1
  69. package/plugins/pbr/agents/planner.md +2 -1
  70. package/plugins/pbr/agents/researcher.md +2 -0
  71. package/plugins/pbr/agents/synthesizer.md +0 -1
  72. package/plugins/pbr/agents/verifier.md +1 -1
  73. package/plugins/pbr/commands/do.md +5 -0
  74. package/plugins/pbr/hooks/hooks.json +20 -0
  75. package/plugins/pbr/scripts/auto-continue.js +26 -2
  76. package/plugins/pbr/scripts/block-skill-self-read.js +72 -0
  77. package/plugins/pbr/scripts/check-agent-state-write.js +63 -0
  78. package/plugins/pbr/scripts/check-cross-plugin-sync.js +93 -0
  79. package/plugins/pbr/scripts/check-dangerous-commands.js +2 -2
  80. package/plugins/pbr/scripts/check-phase-boundary.js +2 -8
  81. package/plugins/pbr/scripts/check-plan-format.js +188 -24
  82. package/plugins/pbr/scripts/check-roadmap-sync.js +140 -1
  83. package/plugins/pbr/scripts/check-skill-workflow.js +3 -11
  84. package/plugins/pbr/scripts/check-state-sync.js +75 -11
  85. package/plugins/pbr/scripts/check-subagent-output.js +78 -6
  86. package/plugins/pbr/scripts/check-summary-gate.js +1 -1
  87. package/plugins/pbr/scripts/log-tool-failure.js +1 -4
  88. package/plugins/pbr/scripts/post-write-dispatch.js +47 -0
  89. package/plugins/pbr/scripts/pre-write-dispatch.js +9 -2
  90. package/plugins/pbr/scripts/session-cleanup.js +3 -4
  91. package/plugins/pbr/scripts/status-line.js +44 -11
  92. package/plugins/pbr/scripts/validate-commit.js +8 -7
  93. package/plugins/pbr/scripts/validate-skill-args.js +2 -1
  94. package/plugins/pbr/scripts/validate-task.js +14 -24
  95. package/plugins/pbr/skills/build/SKILL.md +7 -8
  96. package/plugins/pbr/skills/continue/SKILL.md +8 -2
  97. package/plugins/pbr/skills/health/SKILL.md +0 -2
  98. package/plugins/pbr/skills/import/SKILL.md +2 -0
  99. package/plugins/pbr/skills/milestone/SKILL.md +2 -0
  100. package/plugins/pbr/skills/pause/SKILL.md +7 -1
  101. package/plugins/pbr/skills/plan/SKILL.md +1 -1
  102. package/plugins/pbr/skills/review/SKILL.md +4 -4
  103. package/plugins/pbr/skills/shared/state-update.md +10 -2
  104. package/plugins/pbr/templates/ROADMAP.md.tmpl +2 -0
@@ -9,11 +9,12 @@ tools:
9
9
  - Bash
10
10
  - Glob
11
11
  - Grep
12
- - WebFetch
13
12
  ---
14
13
 
15
14
  # Plan-Build-Run Planner
16
15
 
16
+ > **Memory note:** Project memory is enabled to provide planning continuity and awareness of prior phase decisions.
17
+
17
18
  You are **planner**, the planning agent for the Plan-Build-Run development system. You transform research, phase goals, and user requirements into executable plans that the executor agent can follow mechanically.
18
19
 
19
20
  ## Core Principle: Context Fidelity
@@ -60,6 +60,8 @@ All claims must be attributed to a source level. Higher levels override lower le
60
60
 
61
61
  **Attribution rules**: Every factual claim needs a source tag (`[S1]`, `[S2]`, etc.). Version-sensitive information (API signatures, config syntax) MUST come from S1-S3. When citing S2, note the version: `[S2-v14.2]`. Contradictions resolve in favor of higher source level.
62
62
 
63
+ **Offline Fallback**: If web tools are unavailable (air-gapped environment, MCP not configured), rely on local sources: codebase analysis via Glob/Grep, existing documentation, and README files. Assign these S3-S4 confidence levels. Do not attempt WebFetch or WebSearch — note in the output header that external sources were unavailable.
64
+
63
65
  ---
64
66
 
65
67
  ## Confidence Levels
@@ -6,7 +6,6 @@ memory: none
6
6
  tools:
7
7
  - Read
8
8
  - Write
9
- - Bash
10
9
  ---
11
10
 
12
11
  # Plan-Build-Run Synthesizer
@@ -222,7 +222,7 @@ Read `references/stub-patterns.md` for stub detection patterns by technology. Re
222
222
 
223
223
  ### Verifier-Specific Anti-Patterns
224
224
  1. DO NOT trust SUMMARY.md claims without verifying the actual codebase
225
- 2. DO NOT attempt to fix issues — you have no Write/Edit tools and that is intentional
225
+ 2. DO NOT attempt to fix issues — you have no Edit tool and that is intentional; Write access is only for VERIFICATION.md output
226
226
  3. DO NOT mark stubs as SUBSTANTIVE — if it has a TODO, it's a stub
227
227
  4. DO NOT mark orphaned code as WIRED — if nothing imports it, it's orphaned
228
228
  5. DO NOT skip Level 2 or Level 3 checks — existence alone is insufficient
@@ -0,0 +1,5 @@
1
+ ---
2
+ description: "Route freeform text to the right PBR skill automatically."
3
+ ---
4
+
5
+ This command is provided by the `pbr:do` skill.
@@ -77,6 +77,16 @@
77
77
  }
78
78
  ],
79
79
  "PreToolUse": [
80
+ {
81
+ "matcher": "Read",
82
+ "hooks": [
83
+ {
84
+ "type": "command",
85
+ "command": "node -e \"var r=process.env.CLAUDE_PLUGIN_ROOT||'',m=r.match(/^\\/([a-zA-Z])\\/(.*)/);if(m)r=m[1]+String.fromCharCode(58)+String.fromCharCode(92)+m[2];require(require('path').resolve(r,'scripts','run-hook.js'))\" block-skill-self-read.js",
86
+ "statusMessage": "Checking skill self-read..."
87
+ }
88
+ ]
89
+ },
80
90
  {
81
91
  "matcher": "Bash",
82
92
  "hooks": [
@@ -87,6 +97,16 @@
87
97
  }
88
98
  ]
89
99
  },
100
+ {
101
+ "matcher": "Bash",
102
+ "hooks": [
103
+ {
104
+ "type": "command",
105
+ "command": "node -e \"var r=process.env.CLAUDE_PLUGIN_ROOT||'',m=r.match(/^\\/([a-zA-Z])\\/(.*)/);if(m)r=m[1]+String.fromCharCode(58)+String.fromCharCode(92)+m[2];require(require('path').resolve(r,'scripts','run-hook.js'))\" check-cross-plugin-sync.js",
106
+ "statusMessage": "Checking cross-plugin sync..."
107
+ }
108
+ ]
109
+ },
90
110
  {
91
111
  "matcher": "Write|Edit",
92
112
  "hooks": [
@@ -63,6 +63,9 @@ function main() {
63
63
  } catch (_todoErr) {
64
64
  // Ignore errors scanning todos
65
65
  }
66
+ // Reset continue count on normal session stop (no signal)
67
+ const countPathNoSig = path.join(planningDir, '.continue-count');
68
+ try { fs.unlinkSync(countPathNoSig); } catch (_e) { /* ignore */ }
66
69
  logHook('auto-continue', 'Stop', 'no-signal', {});
67
70
  process.exit(0);
68
71
  }
@@ -97,19 +100,40 @@ function main() {
97
100
  process.exit(0);
98
101
  }
99
102
 
103
+ // Track consecutive continues for session length guard
104
+ const countPath = path.join(planningDir, '.continue-count');
105
+ let continueCount = 0;
106
+ try {
107
+ continueCount = parseInt(fs.readFileSync(countPath, 'utf8').trim(), 10) || 0;
108
+ } catch (_e) { /* file missing — start at 0 */ }
109
+ continueCount++;
110
+ try { fs.writeFileSync(countPath, String(continueCount)); } catch (_e) { /* ignore */ }
111
+
112
+ // Hard stop after 6 consecutive continues — context is likely degraded
113
+ if (continueCount > 6) {
114
+ logHook('auto-continue', 'Stop', 'hard-stop-session-length', { count: continueCount });
115
+ process.exit(0);
116
+ }
117
+
100
118
  // Extract last_assistant_message for richer continuation context
101
119
  const lastMsg = hookInput.last_assistant_message || '';
102
120
  const msgSuffix = lastMsg
103
121
  ? ` (last message excerpt: ${lastMsg.slice(0, 200)})`
104
122
  : '';
105
123
 
106
- logHook('auto-continue', 'Stop', 'continue', { next: nextCommand, hasLastMsg: !!lastMsg });
124
+ logHook('auto-continue', 'Stop', 'continue', { next: nextCommand, hasLastMsg: !!lastMsg, continueCount });
125
+
126
+ // Build reason string with optional advisory
127
+ let reasonStr = `Auto-continue: execute ${nextCommand}${msgSuffix}`;
128
+ if (continueCount > 3) {
129
+ reasonStr += `\n\n[pbr] Advisory: ${continueCount} consecutive continues. Consider /pbr:pause + fresh session to avoid context degradation.`;
130
+ }
107
131
 
108
132
  // Block the stop and inject the next command as Claude's continuation reason.
109
133
  // Claude Code Stop hooks use { decision: "block", reason: "..." } to keep going.
110
134
  const output = {
111
135
  decision: 'block',
112
- reason: `Auto-continue: execute ${nextCommand}${msgSuffix}`
136
+ reason: reasonStr
113
137
  };
114
138
  process.stdout.write(JSON.stringify(output));
115
139
  process.exit(0);
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * PreToolUse Read hook: blocks skills from re-reading their own SKILL.md.
5
+ *
6
+ * Skills are already loaded into context by Claude Code — re-reading
7
+ * wastes ~13k tokens. This hook checks .planning/.active-skill to
8
+ * determine the current skill and blocks if the Read target matches.
9
+ */
10
+
11
+ 'use strict';
12
+
13
+ const fs = require('fs');
14
+ const path = require('path');
15
+ const { logHook } = require('./hook-logger');
16
+
17
+ function main() {
18
+ try {
19
+ let hookInput = {};
20
+ try {
21
+ const stdin = fs.readFileSync(0, 'utf8').trim();
22
+ if (stdin) hookInput = JSON.parse(stdin);
23
+ } catch (_parseErr) {
24
+ // No stdin or invalid JSON
25
+ }
26
+
27
+ const cwd = hookInput.cwd || process.cwd();
28
+ const toolInput = hookInput.tool_input || {};
29
+ const filePath = toolInput.file_path || '';
30
+
31
+ if (!filePath) {
32
+ process.exit(0);
33
+ }
34
+
35
+ // Read .active-skill to get current skill name
36
+ const activeSkillPath = path.join(cwd, '.planning', '.active-skill');
37
+ let skillName = '';
38
+ try {
39
+ skillName = fs.readFileSync(activeSkillPath, 'utf8').trim();
40
+ } catch (_readErr) {
41
+ // No .active-skill file — nothing to block
42
+ process.exit(0);
43
+ }
44
+
45
+ if (!skillName) {
46
+ process.exit(0);
47
+ }
48
+
49
+ // Check if file_path ends with skills/{skill-name}/SKILL.md
50
+ const normalized = filePath.replace(/\\/g, '/');
51
+ const pattern = `skills/${skillName}/SKILL.md`.toLowerCase();
52
+ const match = normalized.toLowerCase().endsWith(pattern);
53
+
54
+ if (match) {
55
+ logHook('block-skill-self-read', 'PreToolUse', 'block', { skill: skillName, file: filePath });
56
+ const output = {
57
+ decision: 'block',
58
+ reason: `SKILL.md self-read blocked.\n\nThe active skill (${skillName}) attempted to read its own SKILL.md. Skills are already loaded into context by Claude Code \u2014 re-reading wastes ~13k tokens.\n\nNo action needed. The skill content is already available in your prompt.`
59
+ };
60
+ process.stdout.write(JSON.stringify(output));
61
+ } else {
62
+ logHook('block-skill-self-read', 'PreToolUse', 'allow', { skill: skillName, file: filePath });
63
+ }
64
+
65
+ process.exit(0);
66
+ } catch (_e) {
67
+ // Don't block on errors
68
+ process.exit(0);
69
+ }
70
+ }
71
+
72
+ main();
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * PreToolUse hook: Blocks subagents (except pbr:general) from writing STATE.md.
5
+ *
6
+ * STATE.md is the source of truth for project position and should only be
7
+ * written by skills (orchestrators) or the general agent, never by specialized
8
+ * agents like executor, planner, or verifier.
9
+ *
10
+ * Detection: reads .planning/.active-agent (written by log-subagent.js).
11
+ *
12
+ * Exit codes:
13
+ * 0 = allowed or not applicable
14
+ * 2 = blocked (agent not allowed to write STATE.md)
15
+ */
16
+
17
+ const fs = require('fs');
18
+ const path = require('path');
19
+
20
+ const BLOCKED_AGENTS = [
21
+ 'pbr:executor',
22
+ 'pbr:planner',
23
+ 'pbr:verifier',
24
+ 'pbr:researcher',
25
+ 'pbr:plan-checker',
26
+ 'pbr:integration-checker',
27
+ 'pbr:debugger',
28
+ 'pbr:codebase-mapper',
29
+ 'pbr:synthesizer',
30
+ 'pbr:audit',
31
+ ];
32
+
33
+ function checkAgentStateWrite(data) {
34
+ const filePath = data.tool_input?.file_path || data.tool_input?.path || '';
35
+ if (!filePath) return null;
36
+
37
+ const normalized = filePath.replace(/\\/g, '/');
38
+ if (!normalized.endsWith('.planning/STATE.md')) return null;
39
+
40
+ // Check if we're inside a subagent
41
+ const cwd = process.cwd();
42
+ const agentFile = path.join(cwd, '.planning', '.active-agent');
43
+
44
+ let agent;
45
+ try {
46
+ agent = fs.readFileSync(agentFile, 'utf8').trim();
47
+ } catch (_e) {
48
+ // No .active-agent file — not in an agent context
49
+ return null;
50
+ }
51
+
52
+ if (!agent || !BLOCKED_AGENTS.includes(agent)) return null;
53
+
54
+ return {
55
+ exitCode: 2,
56
+ output: {
57
+ decision: 'block',
58
+ reason: `Agent write to STATE.md blocked.\n\n${agent} is not allowed to write STATE.md. Only skills (orchestrators) and pbr:general may update this file to prevent state corruption.\n\nReturn results to the calling skill and let it update STATE.md.`
59
+ }
60
+ };
61
+ }
62
+
63
+ module.exports = { checkAgentStateWrite, BLOCKED_AGENTS };
@@ -0,0 +1,93 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * PreToolUse Bash hook: Advisory warning when committing pbr skill/agent
5
+ * changes without corresponding cursor-pbr/copilot-pbr counterparts.
6
+ *
7
+ * Only fires on `git commit` commands. Scripts directory is excluded
8
+ * because cursor-pbr and copilot-pbr share scripts via ../pbr/scripts/.
9
+ *
10
+ * Exit codes:
11
+ * 0 = always (advisory only, never blocks)
12
+ */
13
+
14
+ const { execSync } = require('child_process');
15
+ const { logHook } = require('./hook-logger');
16
+
17
+ /**
18
+ * Check if a git commit has cross-plugin sync drift.
19
+ * @param {Object} data - Parsed hook input
20
+ * @returns {null|{additionalContext: string}} null if clean, advisory if drift
21
+ */
22
+ function checkCrossPluginSync(data) {
23
+ const command = data.tool_input?.command || '';
24
+
25
+ // Only check git commit commands
26
+ if (!/\bgit\s+commit\b/.test(command)) {
27
+ return null;
28
+ }
29
+
30
+ let stagedFiles;
31
+ try {
32
+ stagedFiles = execSync('git diff --cached --name-only', { encoding: 'utf8' }).trim().split('\n').filter(Boolean);
33
+ } catch (_e) {
34
+ return null;
35
+ }
36
+
37
+ // Find pbr skill/agent files (not scripts — those are shared)
38
+ const pbrSyncFiles = stagedFiles.filter(f =>
39
+ /^plugins\/pbr\/(skills|agents)\//.test(f)
40
+ );
41
+
42
+ if (pbrSyncFiles.length === 0) {
43
+ return null;
44
+ }
45
+
46
+ // Check for missing counterparts
47
+ const missingCounterparts = [];
48
+ for (const pbrFile of pbrSyncFiles) {
49
+ const relativePath = pbrFile.replace(/^plugins\/pbr\//, '');
50
+ const cursorPath = `plugins/cursor-pbr/${relativePath}`;
51
+ const copilotPath = `plugins/copilot-pbr/${relativePath}`;
52
+
53
+ const hasCursor = stagedFiles.some(f => f === cursorPath);
54
+ const hasCopilot = stagedFiles.some(f => f === copilotPath);
55
+
56
+ if (!hasCursor || !hasCopilot) {
57
+ const missing = [];
58
+ if (!hasCursor) missing.push('cursor-pbr');
59
+ if (!hasCopilot) missing.push('copilot-pbr');
60
+ missingCounterparts.push(`${pbrFile} (missing: ${missing.join(', ')})`);
61
+ }
62
+ }
63
+
64
+ if (missingCounterparts.length === 0) {
65
+ return null;
66
+ }
67
+
68
+ const msg = `Advisory: Cross-plugin sync may be needed. Changed pbr files without cursor-pbr/copilot-pbr counterparts:\n${missingCounterparts.map(f => ` - ${f}`).join('\n')}`;
69
+ logHook('check-cross-plugin-sync', 'PreToolUse', 'warn', { missingCounterparts });
70
+
71
+ return { additionalContext: msg };
72
+ }
73
+
74
+ function main() {
75
+ let input = '';
76
+ process.stdin.setEncoding('utf8');
77
+ process.stdin.on('data', (chunk) => { input += chunk; });
78
+ process.stdin.on('end', () => {
79
+ try {
80
+ const data = JSON.parse(input);
81
+ const result = checkCrossPluginSync(data);
82
+ if (result) {
83
+ process.stdout.write(JSON.stringify(result));
84
+ }
85
+ } catch (_e) {
86
+ // Don't block on errors
87
+ }
88
+ process.exit(0);
89
+ });
90
+ }
91
+
92
+ module.exports = { checkCrossPluginSync };
93
+ if (require.main === module || process.argv[1] === __filename) { main(); }
@@ -86,7 +86,7 @@ function checkDangerous(data) {
86
86
  return {
87
87
  output: {
88
88
  decision: 'block',
89
- reason: `Dangerous command blocked.\n\n${reason}\n\nCommand: ${command.substring(0, 150)}`
89
+ reason: `Dangerous command blocked.\n\n${reason} Command: ${command.substring(0, 150)}\n\nUse a safer alternative or ask the user for explicit confirmation before running destructive commands.`
90
90
  },
91
91
  exitCode: 2
92
92
  };
@@ -146,7 +146,7 @@ function checkSkillSpecificBash(command) {
146
146
  return {
147
147
  output: {
148
148
  decision: 'block',
149
- reason: 'CRITICAL: Use Read + Write tools for JSON files, not shell text manipulation. Shell tools can corrupt JSON structure.'
149
+ reason: 'JSON shell manipulation blocked.\n\nShell tools like sed, awk, and perl can corrupt JSON structure. The statusline skill must use structured tools for JSON editing.\n\nUse the Read and Write tools to modify JSON files instead of shell text manipulation.'
150
150
  },
151
151
  exitCode: 2
152
152
  };
@@ -102,10 +102,7 @@ function main() {
102
102
  process.exit(2);
103
103
  } else {
104
104
  const output = {
105
- hookSpecificOutput: {
106
- hookEventName: 'PreToolUse',
107
- additionalContext: `Warning: editing phase ${filePhase} file but current phase is ${currentPhase}. Ensure this cross-phase edit is intentional.`
108
- }
105
+ additionalContext: `Warning: editing phase ${filePhase} file but current phase is ${currentPhase}. Ensure this cross-phase edit is intentional.`
109
106
  };
110
107
  process.stdout.write(JSON.stringify(output));
111
108
  }
@@ -184,10 +181,7 @@ function checkBoundary(data) {
184
181
  return {
185
182
  exitCode: 0,
186
183
  output: {
187
- hookSpecificOutput: {
188
- hookEventName: 'PreToolUse',
189
- additionalContext: `Warning: editing phase ${filePhase} file but current phase is ${currentPhase}. Ensure this cross-phase edit is intentional.`
190
- }
184
+ additionalContext: `Warning: editing phase ${filePhase} file but current phase is ${currentPhase}. Ensure this cross-phase edit is intentional.`
191
185
  }
192
186
  };
193
187
  }