@zhuan-ai/zhuanspec 2.11.3 → 2.11.4
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/dist/core/hooks/notify-milestone.js +31 -5
- package/dist/core/hooks/review-hooks.js +5 -4
- package/dist/core/hooks/review-orchestrator.js +9 -0
- package/dist/core/init.js +13 -1
- package/dist/core/templates/slash-command-templates.js +13 -12
- package/dist/core/templates/tasks-template.js +1 -0
- package/dist/core/validation/strict-rules.d.ts +9 -0
- package/dist/core/validation/strict-rules.js +71 -0
- package/package.json +22 -20
|
@@ -122,16 +122,42 @@ function parseTasks(content) {
|
|
|
122
122
|
currentWave = parseInt(waveMatch[1], 10);
|
|
123
123
|
continue;
|
|
124
124
|
}
|
|
125
|
-
// Match task lines: - [ ] X.Y description or - [x] X.Y description
|
|
126
|
-
const
|
|
127
|
-
if (
|
|
128
|
-
const statusChar =
|
|
129
|
-
const taskId =
|
|
125
|
+
// Match new format task lines: - [ ] X.Y description or - [x] X.Y description
|
|
126
|
+
const newFormatMatch = line.match(/^-\s*\[([x ])\]\s*(\d+\.\d+)\s*(.+)/);
|
|
127
|
+
if (newFormatMatch) {
|
|
128
|
+
const statusChar = newFormatMatch[1];
|
|
129
|
+
const taskId = newFormatMatch[2];
|
|
130
130
|
tasks.push({
|
|
131
131
|
taskId,
|
|
132
132
|
status: statusChar === 'x' ? 'completed' : 'pending',
|
|
133
133
|
wave: currentWave,
|
|
134
134
|
});
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
// Match legacy format task headers: #### T1: description or #### T2: description
|
|
138
|
+
const legacyMatch = line.match(/^####\s*(T\d+)\s*:\s*(.+)$/);
|
|
139
|
+
if (legacyMatch) {
|
|
140
|
+
const taskId = legacyMatch[1];
|
|
141
|
+
const rawDescription = legacyMatch[2].trim();
|
|
142
|
+
const isCompleted = rawDescription.endsWith('✅');
|
|
143
|
+
tasks.push({
|
|
144
|
+
taskId,
|
|
145
|
+
status: isCompleted ? 'completed' : 'pending',
|
|
146
|
+
wave: currentWave,
|
|
147
|
+
});
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
// Match "Task X.Y" format: #### Task 1.0: description or #### Task 1.1: description
|
|
151
|
+
const taskXYMatch = line.match(/^####\s*Task\s+(\d+\.\d+)\s*:\s*(.+)$/i);
|
|
152
|
+
if (taskXYMatch) {
|
|
153
|
+
const taskId = taskXYMatch[1];
|
|
154
|
+
const rawDescription = taskXYMatch[2].trim();
|
|
155
|
+
const isCompleted = rawDescription.endsWith('✅');
|
|
156
|
+
tasks.push({
|
|
157
|
+
taskId,
|
|
158
|
+
status: isCompleted ? 'completed' : 'pending',
|
|
159
|
+
wave: currentWave,
|
|
160
|
+
});
|
|
135
161
|
}
|
|
136
162
|
}
|
|
137
163
|
return tasks;
|
|
@@ -420,11 +420,12 @@ function formatConsistencyFixPrompt(output, loopCount) {
|
|
|
420
420
|
|
|
421
421
|
${uncoveredList}
|
|
422
422
|
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
2. 或更新 Spec 描述以反映当前实现状态
|
|
423
|
+
⚠️ 铁律:Spec is Truth — 文档与代码冲突时,错的一定是代码。
|
|
424
|
+
🚫 禁止修改 Spec 文件内容(包括 Requirement 名称、Scenario 描述、Given/When/Then 条件)。
|
|
426
425
|
|
|
427
|
-
|
|
426
|
+
请通过以下方式修复:
|
|
427
|
+
1. 补充或修改代码实现,使其满足上述 Scenario 描述的业务诉求
|
|
428
|
+
2. 修复后重新运行 spec-code-consistency 检查验证覆盖情况
|
|
428
429
|
`;
|
|
429
430
|
}
|
|
430
431
|
// ============================================================
|
|
@@ -45,6 +45,12 @@ function generateUnitTestPrompt(changeId) {
|
|
|
45
45
|
## 任务目标
|
|
46
46
|
为 changeId=${changeId} 的代码变更生成并验证单元测试
|
|
47
47
|
|
|
48
|
+
## TDD 模式感知
|
|
49
|
+
在生成单测前,检查 Apply 阶段是否已有 TDD 生成的测试文件:
|
|
50
|
+
- 读取 zhuanspec/changes/${changeId}/tasks.md,查看是否有已完成的 @test-case 任务
|
|
51
|
+
- 若存在 TDD 已生成的测试,识别已有测试做增量补全
|
|
52
|
+
- 若不存在 TDD 测试,按正常流程全量生成单测
|
|
53
|
+
|
|
48
54
|
## 自闭环指令
|
|
49
55
|
1. 执行 generate-mockito-unit-test skill 生成单测
|
|
50
56
|
2. 运行单测,检查通过率和覆盖率
|
|
@@ -111,6 +117,9 @@ function generateSpecConsistencyPrompt(changeId) {
|
|
|
111
117
|
|
|
112
118
|
### Step 4:自闭环修复
|
|
113
119
|
- 发现 ❌ 未覆盖的 Scenario → 补充对应代码实现
|
|
120
|
+
- ⚠️ **铁律:Spec is Truth** — 文档与代码冲突时,错的一定是代码
|
|
121
|
+
- 🚫 **绝对禁止修改 Spec 文件**(包括 Requirement 名称、Scenario 标题、Given/When/Then 描述)
|
|
122
|
+
- 只能通过新增或修改代码来满足 Spec 描述的业务诉求
|
|
114
123
|
- 修复后重新执行 Step 2 验证(最多3轮)
|
|
115
124
|
- ⚠️ 仅修复真实遗漏,禁止把"文件存在但逻辑未实现"误报为已覆盖
|
|
116
125
|
|
package/dist/core/init.js
CHANGED
|
@@ -1552,6 +1552,18 @@ export class InitCommand {
|
|
|
1552
1552
|
}
|
|
1553
1553
|
const spinner = this.startSpinner('正在安装 claude-hud(用于版本信息展示)...');
|
|
1554
1554
|
try {
|
|
1555
|
+
// Step 1: Add the claude-hud marketplace (skip if already added)
|
|
1556
|
+
try {
|
|
1557
|
+
execSync('claude plugin marketplace add jarrodwatts/claude-hud', {
|
|
1558
|
+
encoding: 'utf-8',
|
|
1559
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
1560
|
+
timeout: 30000,
|
|
1561
|
+
});
|
|
1562
|
+
}
|
|
1563
|
+
catch {
|
|
1564
|
+
// Marketplace may already be added, ignore error and proceed
|
|
1565
|
+
}
|
|
1566
|
+
// Step 2: Install the plugin from the marketplace
|
|
1555
1567
|
execSync('claude plugin install claude-hud', {
|
|
1556
1568
|
encoding: 'utf-8',
|
|
1557
1569
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
@@ -1565,7 +1577,7 @@ export class InitCommand {
|
|
|
1565
1577
|
catch {
|
|
1566
1578
|
spinner.stopAndPersist({
|
|
1567
1579
|
symbol: PALETTE.midGray('▌'),
|
|
1568
|
-
text: PALETTE.midGray('claude-hud 安装失败,可手动执行: claude
|
|
1580
|
+
text: PALETTE.midGray('claude-hud 安装失败,可手动执行: claude plugin marketplace add jarrodwatts/claude-hud && claude plugin install claude-hud'),
|
|
1569
1581
|
});
|
|
1570
1582
|
}
|
|
1571
1583
|
}
|
|
@@ -293,8 +293,8 @@ const applySteps = `**步骤**
|
|
|
293
293
|
4. 如果 Skill 异常或超时,跳过 Skill 继续实施
|
|
294
294
|
|
|
295
295
|
- **阶段职责(按 Agent 类型区分)**:
|
|
296
|
-
* **applyAgent
|
|
297
|
-
* **tddApplyAgent(TDD 模式,任务有 \`@test-case\` 标注)**:基于 test-cases.md
|
|
296
|
+
* **applyAgent(普通模式)**:专注代码实现,不生成单元测试文件
|
|
297
|
+
* **tddApplyAgent(TDD 模式,任务有 \`@test-case\` 标注)**:基于 test-cases.md 先写测试再写实现,执行 Red-Green-Refactor 循环(详见 tdd-apply-agent.md)
|
|
298
298
|
4. **确认完成** - 在更新状态之前确保 \`tasks.md\` 中的每个项目都已完成。
|
|
299
299
|
5. **更新清单** - 所有工作完成后,将每个任务设置为 \`- [x]\`,以便列表反映实际情况。
|
|
300
300
|
6. **处理 Subagent 状态报告**(Wave 并行执行时):
|
|
@@ -303,7 +303,7 @@ const applySteps = `**步骤**
|
|
|
303
303
|
- **DONE_WITH_CONCERNS**:转发进度汇报 → 记录 concerns 并评估是否需要修复
|
|
304
304
|
- **BLOCKED**:转发进度汇报 → 评估 blocker 类型并决定处理策略(提供上下文/换更强模型/拆分任务)
|
|
305
305
|
- **NEEDS_CONTEXT**:转发进度汇报 → 提供缺失信息并重新启动 subagent
|
|
306
|
-
- 所有任务报告文件均保存在 \`changes/<change-id>/reports/\` 目录,可告知用户按 task-id 查阅
|
|
306
|
+
- 所有任务报告文件均保存在 \`zhuanspec/changes/<change-id>/reports/\` 目录,可告知用户按 task-id 查阅
|
|
307
307
|
7. **Wave 完成后集成验证**(Wave 并行执行时):
|
|
308
308
|
每个 Wave 全部任务完成后,编排 Agent 自动执行以下检查:
|
|
309
309
|
|
|
@@ -337,8 +337,8 @@ const applySteps = `**步骤**
|
|
|
337
337
|
9. **触发审查门禁** - 所有任务完成后选项式提问用户是否进入 Review 阶段`;
|
|
338
338
|
const applyGuardrails = `${baseGuardrails}\n- **Wave 并行执行**:当 tasks.md 包含 \`@depends\` 时,按 Wave 编号串行执行,Wave 内任务通过 Agent tool 并行启动 subagent。
|
|
339
339
|
- **Agent 类型选择**:根据任务 \`@test-case\` 标注选择 subagent 类型:
|
|
340
|
-
* 无 \`@test-case\` 标注 → \`applyAgent
|
|
341
|
-
* 有 \`@test-case:TC-XXX\` 标注 → \`tddApplyAgent\`(TDD
|
|
340
|
+
* 无 \`@test-case\` 标注 → \`applyAgent\`(普通模式)
|
|
341
|
+
* 有 \`@test-case:TC-XXX\` 标注 → \`tddApplyAgent\`(TDD 模式,先写测试再写实现,详见 tdd-apply-agent.md)
|
|
342
342
|
- **Rules 和 Knowledge 注入**:编排 Agent MUST 在每个 subagent prompt 中注入 Rules(根据 @skill)和 Knowledge(踩坑警告、最佳实践)。
|
|
343
343
|
- **偏差处理**:PreToolUse Hook 检测到提案范围外修改时弹出选项式交互(更新提案/Bug修复豁免/取消)。3次偏差后强制更新提案。`;
|
|
344
344
|
const applyReferences = `**参考**
|
|
@@ -436,27 +436,28 @@ const reviewSteps = `**步骤**
|
|
|
436
436
|
- **轨道 A:Code Review 轨**
|
|
437
437
|
- 使用 Skill 工具调用 \`code-review-expert\` skill
|
|
438
438
|
- 输出 \`code-review-report.md\`,记录 Critical/Important 问题
|
|
439
|
-
- skill 完成后,**AI 将结果写入** \`changes/<id>/review/code-review-result.json\`,格式:
|
|
439
|
+
- skill 完成后,**AI 将结果写入** \`zhuanspec/changes/<id>/review/code-review-result.json\`,格式:
|
|
440
440
|
\`\`\`json
|
|
441
441
|
{ "criticalCount": 0, "importantCount": 0, "infoCount": 0, "issues": [], "sonarStatus": "skip", "loopCount": 0 }
|
|
442
442
|
\`\`\`
|
|
443
443
|
- **轨道 B:Unit Test 轨(Skill)**
|
|
444
444
|
- 使用 Skill 工具调用 \`generate-mockito-unit-test\`
|
|
445
|
-
-
|
|
446
|
-
-
|
|
445
|
+
- 检查 Apply 阶段是否已有 TDD 生成的测试,若有则识别已有测试做增量补全,若无则全量生成
|
|
446
|
+
- 运行全部单测并执行测试命令,输出单测结果
|
|
447
|
+
- skill 完成后,**AI 将结果写入** \`zhuanspec/changes/<id>/review/unit-test-result.json\`,格式:
|
|
447
448
|
\`\`\`json
|
|
448
449
|
{ "testPassed": true, "passRate": 100, "coverage": 85, "coverageThreshold": 80, "newTestsGenerated": [], "failedTests": [], "loopCount": 0 }
|
|
449
450
|
\`\`\`
|
|
450
451
|
- **轨道 C:Spec-Code 一致性轨**
|
|
451
452
|
- 运行 \`zhuanspec validate <change-id> --strict\`
|
|
452
453
|
- 确认 \`spec-code-consistent\` 规则通过
|
|
453
|
-
- validate 完成后,**AI 将结果写入** \`changes/<id>/review/spec-consistency-result.json\`,格式:
|
|
454
|
+
- validate 完成后,**AI 将结果写入** \`zhuanspec/changes/<id>/review/spec-consistency-result.json\`,格式:
|
|
454
455
|
\`\`\`json
|
|
455
456
|
{ "consistencyRate": 100, "totalRequirements": 0, "totalScenarios": 0, "coveredScenarios": 0, "uncoveredScenarios": [], "mapping": [], "loopCount": 0 }
|
|
456
457
|
\`\`\`
|
|
457
458
|
3. **汇总执行 CLI Review**:
|
|
458
459
|
- 运行 \`zhuanspec review <change-id>\`
|
|
459
|
-
- CLI 读取三个 JSON,生成 \`changes/<id>/review/review-report.md\`
|
|
460
|
+
- CLI 读取三个 JSON,生成 \`zhuanspec/changes/<id>/review/review-report.md\`
|
|
460
461
|
- 如果 skill JSON 未写入,CLI 将打印缺失文件列表并退出
|
|
461
462
|
4. **审查结果处理**:
|
|
462
463
|
- **PASS**:三轨全部通过(CR=PASS、UT=PASS、Spec-Code=PASS)且 Critical=0,可以继续归档
|
|
@@ -469,9 +470,9 @@ const reviewSteps = `**步骤**
|
|
|
469
470
|
- 提示可以使用 \`/zhuanspec:archive\` 进行归档`;
|
|
470
471
|
const reviewReferences = `**参考**
|
|
471
472
|
- 使用 \`zhuanspec review --help\` 查看完整选项
|
|
472
|
-
- 审查报告文件均位于 \`changes/<id>/review/\` 目录下:\`code-review-result.json\`、\`unit-test-result.json\`、\`spec-consistency-result.json\`、\`review-report.md\`
|
|
473
|
+
- 审查报告文件均位于 \`zhuanspec/changes/<id>/review/\` 目录下:\`code-review-result.json\`、\`unit-test-result.json\`、\`spec-consistency-result.json\`、\`review-report.md\`
|
|
473
474
|
- 单元测试覆盖率阈值默认 80%,可通过 \`--coverage-threshold\` 调整
|
|
474
|
-
- \`code-review-expert\` Skill 结果由 AI 写入 \`changes/<id>/review/code-review-result.json\`,\`generate-mockito-unit-test\` Skill 结果由 AI 写入 \`changes/<id>/review/unit-test-result.json\``;
|
|
475
|
+
- \`code-review-expert\` Skill 结果由 AI 写入 \`zhuanspec/changes/<id>/review/code-review-result.json\`,\`generate-mockito-unit-test\` Skill 结果由 AI 写入 \`zhuanspec/changes/<id>/review/unit-test-result.json\``;
|
|
475
476
|
const knowledgeGuardrails = `${baseGuardrails}\n- **知识管理阶段**:knowledge 命令用于管理项目级知识库(最佳实践、陷阱、隐式约定)。
|
|
476
477
|
- **跨变更积累**:知识不绑定单个变更,是长期积累的项目资产。
|
|
477
478
|
- **职责分离**:
|
|
@@ -150,6 +150,15 @@ export declare function checkTestCaseCoverage(tasksContent: string, hasTestCase?
|
|
|
150
150
|
*/
|
|
151
151
|
export declare function checkTechSpecCoverage(changeDir: string): StrictCheckResult;
|
|
152
152
|
export declare function checkTaskIdFormat(tasksContent: string): StrictCheckResult;
|
|
153
|
+
/**
|
|
154
|
+
* Rule: task-checkbox-format
|
|
155
|
+
*
|
|
156
|
+
* Validates that all tasks under Wave headers use standard GitHub Flavored Markdown
|
|
157
|
+
* checkbox format: `- [ ] N.M description` or `- [x] N.M description`.
|
|
158
|
+
* Rejects legacy formats like `#### Task N.M:` headers or `✅` emoji as completion marker.
|
|
159
|
+
* This ensures automated progress tracking (parseTasks, record-progress, review gate) works correctly.
|
|
160
|
+
*/
|
|
161
|
+
export declare function checkTaskCheckboxFormat(tasksContent: string): StrictCheckResult;
|
|
153
162
|
/**
|
|
154
163
|
* Main entry: Run all strict validation rules
|
|
155
164
|
*/
|
|
@@ -1179,6 +1179,76 @@ export function checkTaskIdFormat(tasksContent) {
|
|
|
1179
1179
|
result.passed = invalidIds.length === 0;
|
|
1180
1180
|
return result;
|
|
1181
1181
|
}
|
|
1182
|
+
/**
|
|
1183
|
+
* Rule: task-checkbox-format
|
|
1184
|
+
*
|
|
1185
|
+
* Validates that all tasks under Wave headers use standard GitHub Flavored Markdown
|
|
1186
|
+
* checkbox format: `- [ ] N.M description` or `- [x] N.M description`.
|
|
1187
|
+
* Rejects legacy formats like `#### Task N.M:` headers or `✅` emoji as completion marker.
|
|
1188
|
+
* This ensures automated progress tracking (parseTasks, record-progress, review gate) works correctly.
|
|
1189
|
+
*/
|
|
1190
|
+
export function checkTaskCheckboxFormat(tasksContent) {
|
|
1191
|
+
const result = {
|
|
1192
|
+
ruleId: 'task-checkbox-format',
|
|
1193
|
+
ruleName: 'Task checkbox format',
|
|
1194
|
+
passed: false,
|
|
1195
|
+
errors: [],
|
|
1196
|
+
warnings: [],
|
|
1197
|
+
};
|
|
1198
|
+
// 1. Check for legacy #### Task headers (should not be used)
|
|
1199
|
+
const legacyTaskHeaders = tasksContent.match(/^####\s*(?:Task\s+\d+\.\d+|T\d+)\s*:.+$/gm) || [];
|
|
1200
|
+
if (legacyTaskHeaders.length > 0) {
|
|
1201
|
+
for (const header of legacyTaskHeaders) {
|
|
1202
|
+
result.errors.push(`Legacy task format detected: "${header.trim()}". ` +
|
|
1203
|
+
`Must use checkbox format: "- [ ] N.M description" or "- [x] N.M description"`);
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
// 2. Find all lines under Wave headers that look like tasks but don't use checkbox format
|
|
1207
|
+
const lines = tasksContent.split('\n');
|
|
1208
|
+
let inWaveSection = false;
|
|
1209
|
+
for (const line of lines) {
|
|
1210
|
+
// Detect Wave header
|
|
1211
|
+
if (/^###\s+Wave\s+\d+/i.test(line)) {
|
|
1212
|
+
inWaveSection = true;
|
|
1213
|
+
continue;
|
|
1214
|
+
}
|
|
1215
|
+
// Detect next non-Wave section header (## or ### not Wave)
|
|
1216
|
+
if (/^#{2,3}\s+(?!Wave\s+\d+)/i.test(line)) {
|
|
1217
|
+
inWaveSection = false;
|
|
1218
|
+
continue;
|
|
1219
|
+
}
|
|
1220
|
+
if (!inWaveSection)
|
|
1221
|
+
continue;
|
|
1222
|
+
// Skip empty lines, comments, and non-list lines
|
|
1223
|
+
const trimmed = line.trim();
|
|
1224
|
+
if (!trimmed || trimmed.startsWith('<!--') || !trimmed.startsWith('-'))
|
|
1225
|
+
continue;
|
|
1226
|
+
// Line starts with - but is NOT a valid checkbox format
|
|
1227
|
+
if (/^-\s+(?!\[[ xX]\])\S/.test(trimmed)) {
|
|
1228
|
+
// Only flag lines that look like task items (have N.M id or substantial content)
|
|
1229
|
+
if (/^-\s+\d+\.\d+\s/.test(trimmed) || /^-\s+[A-Z]/.test(trimmed)) {
|
|
1230
|
+
result.warnings.push(`Task line without checkbox: "${trimmed.substring(0, 80)}". ` +
|
|
1231
|
+
`Expected format: "- [ ] N.M description"`);
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
// 3. Verify checkbox tasks exist (at least one task under Wave headers)
|
|
1236
|
+
const checkboxTasks = tasksContent.match(/^-\s+\[[ xX]\]\s+\d+\.\d+\s+.+$/gm) || [];
|
|
1237
|
+
if (checkboxTasks.length === 0 && legacyTaskHeaders.length === 0) {
|
|
1238
|
+
// No tasks at all - just a warning, not an error (template might be empty)
|
|
1239
|
+
result.warnings.push('No tasks found in checkbox format under Wave headers');
|
|
1240
|
+
}
|
|
1241
|
+
// 4. Check that completed tasks use [x] not ✅ emoji on checkbox lines
|
|
1242
|
+
const checkboxWithEmoji = tasksContent.match(/^-\s+\[[ ]\]\s+.+\u2705\s*$/gm) || [];
|
|
1243
|
+
if (checkboxWithEmoji.length > 0) {
|
|
1244
|
+
for (const line of checkboxWithEmoji) {
|
|
1245
|
+
result.warnings.push(`Task uses ✅ emoji but checkbox is unchecked: "${line.trim().substring(0, 80)}". ` +
|
|
1246
|
+
`Use "- [x]" to mark completion instead of ✅ emoji`);
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
result.passed = result.errors.length === 0;
|
|
1250
|
+
return result;
|
|
1251
|
+
}
|
|
1182
1252
|
/**
|
|
1183
1253
|
* Main entry: Run all strict validation rules
|
|
1184
1254
|
*/
|
|
@@ -1194,6 +1264,7 @@ export async function runStrictValidation(tasksContent, parsedTasks, knownSkillN
|
|
|
1194
1264
|
checkFileConflicts(parsedTasks),
|
|
1195
1265
|
checkTestCaseCoverage(tasksContent, hasTestCase),
|
|
1196
1266
|
checkTaskIdFormat(tasksContent),
|
|
1267
|
+
checkTaskCheckboxFormat(tasksContent),
|
|
1197
1268
|
];
|
|
1198
1269
|
// Add new rules if parameters are provided
|
|
1199
1270
|
if (options?.proposalContent) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhuan-ai/zhuanspec",
|
|
3
|
-
"version": "2.11.
|
|
3
|
+
"version": "2.11.4",
|
|
4
4
|
"description": "AI-native system for spec-driven development",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"zhuanspec",
|
|
@@ -39,6 +39,26 @@
|
|
|
39
39
|
"!dist/**/__tests__",
|
|
40
40
|
"!dist/**/*.map"
|
|
41
41
|
],
|
|
42
|
+
"scripts": {
|
|
43
|
+
"lint": "eslint src/",
|
|
44
|
+
"build": "node build.js",
|
|
45
|
+
"dev": "tsc --watch",
|
|
46
|
+
"dev:cli": "pnpm build && node bin/zhuanspec.js",
|
|
47
|
+
"test": "vitest run",
|
|
48
|
+
"test:watch": "vitest",
|
|
49
|
+
"test:ui": "vitest --ui",
|
|
50
|
+
"test:coverage": "vitest --coverage",
|
|
51
|
+
"test:postinstall": "node scripts/postinstall.js",
|
|
52
|
+
"prepare": "npm run build",
|
|
53
|
+
"prepublishOnly": "npm run build",
|
|
54
|
+
"postinstall": "node scripts/postinstall.js",
|
|
55
|
+
"check:pack-version": "node scripts/pack-version-check.mjs",
|
|
56
|
+
"diagnose:cursor": "node scripts/diagnose-cursor-commands.js",
|
|
57
|
+
"release": "pnpm run release:ci",
|
|
58
|
+
"release:ci": "pnpm run check:pack-version && pnpm exec changeset publish",
|
|
59
|
+
"release:local": "pnpm exec changeset version && pnpm run check:pack-version && pnpm exec changeset publish",
|
|
60
|
+
"changeset": "changeset"
|
|
61
|
+
},
|
|
42
62
|
"engines": {
|
|
43
63
|
"node": ">=20.19.0"
|
|
44
64
|
},
|
|
@@ -60,23 +80,5 @@
|
|
|
60
80
|
"ora": "^8.2.0",
|
|
61
81
|
"yaml": "^2.8.2",
|
|
62
82
|
"zod": "^4.0.17"
|
|
63
|
-
},
|
|
64
|
-
"scripts": {
|
|
65
|
-
"lint": "eslint src/",
|
|
66
|
-
"build": "node build.js",
|
|
67
|
-
"dev": "tsc --watch",
|
|
68
|
-
"dev:cli": "pnpm build && node bin/zhuanspec.js",
|
|
69
|
-
"test": "vitest run",
|
|
70
|
-
"test:watch": "vitest",
|
|
71
|
-
"test:ui": "vitest --ui",
|
|
72
|
-
"test:coverage": "vitest --coverage",
|
|
73
|
-
"test:postinstall": "node scripts/postinstall.js",
|
|
74
|
-
"postinstall": "node scripts/postinstall.js",
|
|
75
|
-
"check:pack-version": "node scripts/pack-version-check.mjs",
|
|
76
|
-
"diagnose:cursor": "node scripts/diagnose-cursor-commands.js",
|
|
77
|
-
"release": "pnpm run release:ci",
|
|
78
|
-
"release:ci": "pnpm run check:pack-version && pnpm exec changeset publish",
|
|
79
|
-
"release:local": "pnpm exec changeset version && pnpm run check:pack-version && pnpm exec changeset publish",
|
|
80
|
-
"changeset": "changeset"
|
|
81
83
|
}
|
|
82
|
-
}
|
|
84
|
+
}
|