@zhuan-ai/zhuanspec 2.11.16 → 2.11.19
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.
|
@@ -70,9 +70,11 @@ export async function deviationCheckHook(options) {
|
|
|
70
70
|
const toolName = options.tool || 'Write';
|
|
71
71
|
// Read stdin for Claude Code hook input
|
|
72
72
|
let stdinData = {};
|
|
73
|
+
let rawStdin = '';
|
|
73
74
|
try {
|
|
74
75
|
const stdinContent = await readStdin();
|
|
75
76
|
if (stdinContent) {
|
|
77
|
+
rawStdin = stdinContent;
|
|
76
78
|
stdinData = JSON.parse(stdinContent);
|
|
77
79
|
}
|
|
78
80
|
}
|
|
@@ -80,9 +82,20 @@ export async function deviationCheckHook(options) {
|
|
|
80
82
|
// Ignore parse errors
|
|
81
83
|
}
|
|
82
84
|
// Get file path from stdin or options
|
|
83
|
-
|
|
85
|
+
// 兼容 Claude Code 两种输入形态:tool_input.file_path 或 tool_input.path
|
|
86
|
+
const toolInput = stdinData.tool_input || {};
|
|
87
|
+
const filePath = toolInput.file_path
|
|
88
|
+
|| toolInput.path
|
|
89
|
+
|| toolInput.notebook_path
|
|
84
90
|
|| options.file
|
|
85
91
|
|| '';
|
|
92
|
+
// DEBUG: 临时记录 stdin 与解析结果,定位路径传递问题后移除
|
|
93
|
+
try {
|
|
94
|
+
fs.appendFileSync('/tmp/zhuanspec-deviation-debug.log', `[${new Date().toISOString()}] phase=${process.env.ZHUANSPEC_PHASE} tool=${toolName} filePath="${filePath}"\n raw=${rawStdin.slice(0, 500)}\n`, 'utf-8');
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
// ignore
|
|
98
|
+
}
|
|
86
99
|
const promptText = stdinData?.prompt
|
|
87
100
|
|| options.prompt
|
|
88
101
|
|| '';
|
|
@@ -238,13 +251,28 @@ async function runDeviationCheck(filePath, trigger, promptText, _options) {
|
|
|
238
251
|
// Propose phase → block all code modifications (Iron Law 1: No Spec No Code)
|
|
239
252
|
// But check if we can transition to Apply phase
|
|
240
253
|
if (phase === 'propose') {
|
|
241
|
-
//
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
//
|
|
246
|
-
|
|
247
|
-
|
|
254
|
+
// UserPromptSubmit(post-prompt) 和 resume 无 filePath 上下文,静默放行,仅 pre-tool 做拦截
|
|
255
|
+
if (trigger !== 'pre-tool') {
|
|
256
|
+
return { continue: true };
|
|
257
|
+
}
|
|
258
|
+
// 兼底:若 filePath 为空(stdin 未传 / 解析失败),不拦截,避免误伤用户修改提案文件
|
|
259
|
+
if (!filePath) {
|
|
260
|
+
return {
|
|
261
|
+
continue: true,
|
|
262
|
+
systemMessage: '⚠️ deviation-check: filePath empty, skip (see /tmp/zhuanspec-deviation-debug.log)',
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
// Allow proposal file modifications
|
|
266
|
+
// 修复:用正则匹配,同时兼容绝对路径和相对路径
|
|
267
|
+
// 匹配: changes/xxx / zhuanspec/changes/xxx / /abs/.../changes/xxx
|
|
268
|
+
const isProposalArtifact = /(?:^|\/)(?:zhuanspec\/)?changes\//.test(filePath) ||
|
|
269
|
+
/(?:^|\/)(?:zhuanspec\/)?specs\//.test(filePath);
|
|
270
|
+
if (isProposalArtifact) {
|
|
271
|
+
return {
|
|
272
|
+
continue: true,
|
|
273
|
+
systemMessage: '✓ Proposal file modification allowed in propose phase',
|
|
274
|
+
};
|
|
275
|
+
}
|
|
248
276
|
// Check if this is a code file that might trigger Apply phase transition
|
|
249
277
|
const isCodeFile = !filePath.includes('zhuanspec/') &&
|
|
250
278
|
/\.(java|ts|tsx|js|jsx|py|go|rs|sql|kt|scala|c|cpp|cs)$/i.test(filePath);
|