soloforge 1.3.10 → 1.4.1
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/README.md +10 -0
- package/dist/adapters/claude_code/hooks.d.ts.map +1 -1
- package/dist/adapters/claude_code/hooks.js +9 -0
- package/dist/adapters/claude_code/hooks.js.map +1 -1
- package/dist/adapters/claude_code/tools.d.ts.map +1 -1
- package/dist/adapters/claude_code/tools.js +44 -3
- package/dist/adapters/claude_code/tools.js.map +1 -1
- package/dist/adapters/codex/codex_config.d.ts.map +1 -1
- package/dist/adapters/codex/codex_config.js +10 -0
- package/dist/adapters/codex/codex_config.js.map +1 -1
- package/dist/bin/soloforge.d.ts.map +1 -1
- package/dist/bin/soloforge.js +154 -0
- package/dist/bin/soloforge.js.map +1 -1
- package/dist/engine/control_plane_contract.d.ts +59 -0
- package/dist/engine/control_plane_contract.d.ts.map +1 -0
- package/dist/engine/control_plane_contract.js +246 -0
- package/dist/engine/control_plane_contract.js.map +1 -0
- package/dist/engine/historical_issue_mechanization_matrix.js +7 -7
- package/dist/engine/historical_issue_mechanization_matrix.js.map +1 -1
- package/dist/engine/implementation_roadmap_registry.d.ts.map +1 -1
- package/dist/engine/implementation_roadmap_registry.js +45 -1
- package/dist/engine/implementation_roadmap_registry.js.map +1 -1
- package/dist/engine/intent_expander.d.ts.map +1 -1
- package/dist/engine/intent_expander.js +18 -7
- package/dist/engine/intent_expander.js.map +1 -1
- package/dist/engine/release_readiness_gate.d.ts +1 -0
- package/dist/engine/release_readiness_gate.d.ts.map +1 -1
- package/dist/engine/release_readiness_gate.js +95 -4
- package/dist/engine/release_readiness_gate.js.map +1 -1
- package/dist/engine/tool_invocation_contract_registry.js +17 -17
- package/dist/engine/tool_invocation_contract_registry.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex_config.d.ts","sourceRoot":"","sources":["../../../src/adapters/codex/codex_config.ts"],"names":[],"mappings":"AAmBA;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAgBlE;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,
|
|
1
|
+
{"version":3,"file":"codex_config.d.ts","sourceRoot":"","sources":["../../../src/adapters/codex/codex_config.ts"],"names":[],"mappings":"AAmBA;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAgBlE;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CAwCjD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex_config.js","sourceRoot":"","sources":["../../../src/adapters/codex/codex_config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAE/C,SAAS,gBAAgB,CAAC,KAAa;IACrC,OAAO,KAAK;SACT,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;SACpB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;SACrB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;SACrB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAC3B,CAAC;AAED,SAAS,WAAW,CAAC,KAAe;IAClC,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,gBAAgB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAC7D,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;AACnC,CAAC;AAED,MAAM,WAAW,GAAG,CAAC,UAAkB,EAAE,EAAE,CACzC,6EAA6E,UAAU,EAAE,CAAC;AAE5F;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,WAAmB;IACxD,KAAK,CAAC,SAAS,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC;IAC7C,OAAO;;SAEA,WAAW,CAAC,CAAC,KAAK,CAAC,CAAC;;;uBAGN,gBAAgB,CAAC,WAAW,CAAC;;;;SAI3C,WAAW,CAAC,CAAC,wBAAwB,EAAE,YAAY,CAAC,CAAC;;;;CAI7D,CAAC;AACF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,wBAAwB;IACtC,KAAK,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;IAChC,OAAO,IAAI,CAAC,SAAS,CAAC;QACpB,KAAK,EAAE;YACL,UAAU,EAAE;gBACV;oBACE,OAAO,EAAE,4BAA4B;oBACrC,KAAK,EAAE;wBACL;4BACE,IAAI,EAAE,SAAS;4BACf,OAAO,EAAE,WAAW,CAAC,aAAa,CAAC;4BACnC,OAAO,EAAE,EAAE;yBACZ;qBACF;iBACF;aACF;YACD,WAAW,EAAE;gBACX;oBACE,OAAO,EAAE,QAAQ;oBACjB,KAAK,EAAE;wBACL;4BACE,IAAI,EAAE,SAAS;4BACf,OAAO,EAAE,WAAW,CAAC,WAAW,CAAC;4BACjC,OAAO,EAAE,EAAE;yBACZ;qBACF;iBACF;aACF;SACF;KACF,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACd,CAAC"}
|
|
1
|
+
{"version":3,"file":"codex_config.js","sourceRoot":"","sources":["../../../src/adapters/codex/codex_config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAE/C,SAAS,gBAAgB,CAAC,KAAa;IACrC,OAAO,KAAK;SACT,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;SACpB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;SACrB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;SACrB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAC3B,CAAC;AAED,SAAS,WAAW,CAAC,KAAe;IAClC,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,gBAAgB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAC7D,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;AACnC,CAAC;AAED,MAAM,WAAW,GAAG,CAAC,UAAkB,EAAE,EAAE,CACzC,6EAA6E,UAAU,EAAE,CAAC;AAE5F;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,WAAmB;IACxD,KAAK,CAAC,SAAS,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC;IAC7C,OAAO;;SAEA,WAAW,CAAC,CAAC,KAAK,CAAC,CAAC;;;uBAGN,gBAAgB,CAAC,WAAW,CAAC;;;;SAI3C,WAAW,CAAC,CAAC,wBAAwB,EAAE,YAAY,CAAC,CAAC;;;;CAI7D,CAAC;AACF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,wBAAwB;IACtC,KAAK,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;IAChC,OAAO,IAAI,CAAC,SAAS,CAAC;QACpB,KAAK,EAAE;YACL,UAAU,EAAE;gBACV;oBACE,OAAO,EAAE,4BAA4B;oBACrC,KAAK,EAAE;wBACL;4BACE,IAAI,EAAE,SAAS;4BACf,OAAO,EAAE,WAAW,CAAC,aAAa,CAAC;4BACnC,OAAO,EAAE,EAAE;yBACZ;qBACF;iBACF;gBACD;oBACE,OAAO,EAAE,QAAQ;oBACjB,KAAK,EAAE;wBACL;4BACE,IAAI,EAAE,SAAS;4BACf,OAAO,EAAE,WAAW,CAAC,YAAY,CAAC;4BAClC,OAAO,EAAE,EAAE;yBACZ;qBACF;iBACF;aACF;YACD,WAAW,EAAE;gBACX;oBACE,OAAO,EAAE,QAAQ;oBACjB,KAAK,EAAE;wBACL;4BACE,IAAI,EAAE,SAAS;4BACf,OAAO,EAAE,WAAW,CAAC,WAAW,CAAC;4BACjC,OAAO,EAAE,EAAE;yBACZ;qBACF;iBACF;aACF;SACF;KACF,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACd,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"soloforge.d.ts","sourceRoot":"","sources":["../../src/bin/soloforge.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"soloforge.d.ts","sourceRoot":"","sources":["../../src/bin/soloforge.ts"],"names":[],"mappings":";AA87BA,OAAO,EAAE,0BAA0B,EAAE,MAAM,gDAAgD,CAAC"}
|
package/dist/bin/soloforge.js
CHANGED
|
@@ -17,6 +17,7 @@ import { resolveCurrentProjectConfigReports, validateConfigPrecedence, } from ".
|
|
|
17
17
|
import { isReadForbidden } from "../engine/privacy_secret_contract.js";
|
|
18
18
|
import { routeIntent } from "../engine/intent_router.js";
|
|
19
19
|
import { debugLog, debug, userInfo, userWarn, userError, internalWarn, jsonSafeError, initLoggerFromEnv } from "../engine/logger.js";
|
|
20
|
+
import { auditControlPlaneProject, isSoloforgeStateBypassCommand } from "../engine/control_plane_contract.js";
|
|
20
21
|
const command = process.argv[2];
|
|
21
22
|
const args = process.argv.slice(3);
|
|
22
23
|
async function main() {
|
|
@@ -45,6 +46,9 @@ async function main() {
|
|
|
45
46
|
case "check-write":
|
|
46
47
|
await cmdCheckWrite();
|
|
47
48
|
break;
|
|
49
|
+
case "check-bash":
|
|
50
|
+
await cmdCheckBash();
|
|
51
|
+
break;
|
|
48
52
|
case "post-bash":
|
|
49
53
|
await cmdPostBash();
|
|
50
54
|
break;
|
|
@@ -81,6 +85,9 @@ async function main() {
|
|
|
81
85
|
case "validate-release":
|
|
82
86
|
await cmdValidateReleaseGate();
|
|
83
87
|
break;
|
|
88
|
+
case "doctor":
|
|
89
|
+
await cmdDoctor();
|
|
90
|
+
break;
|
|
84
91
|
case "audit-template-visibility":
|
|
85
92
|
await cmdAuditTemplateVisibility();
|
|
86
93
|
break;
|
|
@@ -167,6 +174,8 @@ async function main() {
|
|
|
167
174
|
generate-trae 生成 .trae/mcp.json 和 .trae/rules/project_rules.md
|
|
168
175
|
generate-codex 生成 .codex/ 配置和 AGENTS.md
|
|
169
176
|
check-write PreToolUse hook,用于范围检查(读取 stdin JSON)
|
|
177
|
+
check-bash PreToolUse hook,阻止 Bash 直接篡改 .soloforge/state
|
|
178
|
+
doctor 审计 MCP 控制面、适配器 hook、状态可信和恢复路径
|
|
170
179
|
post-bash PostToolUse hook,用于跟踪 Bash 执行结果
|
|
171
180
|
validate 验证项目配置和知识文件(config.yaml 可选,缺失时自动推断)
|
|
172
181
|
validate-mechanisms 验证双层机制承载模型完整性(模板层 + 机制层)
|
|
@@ -194,6 +203,7 @@ async function main() {
|
|
|
194
203
|
stage 显示当前项目阶段和任务阶段
|
|
195
204
|
stage --explain 详细解释当前阶段(判断依据、必要条件、下一阶段)
|
|
196
205
|
cleanup 清理过期任务和 evidence(默认 dry-run,--apply 执行实际清理)
|
|
206
|
+
cleanup --stale 检测陈旧 current-task 指针(--apply 时受控归档)
|
|
197
207
|
`);
|
|
198
208
|
}
|
|
199
209
|
}
|
|
@@ -697,10 +707,41 @@ async function cmdCheckWrite() {
|
|
|
697
707
|
if (!isDesignArtifactFile) {
|
|
698
708
|
const { TaskContextManager } = await import("../engine/task_context.js");
|
|
699
709
|
const stateDir = path.join(projectPath, ".soloforge", "state");
|
|
710
|
+
const implementationSource = isImplementationSourcePath(relativeFilePath);
|
|
700
711
|
if (fss.existsSync(stateDir)) {
|
|
701
712
|
const manager = new TaskContextManager(stateDir);
|
|
702
713
|
const currentTask = await manager.getCurrentTask();
|
|
703
714
|
const designPack = currentTask?.design_artifact_pack;
|
|
715
|
+
if (implementationSource && currentTask && ["classifying", "clarifying", "expanding"].includes(currentTask.status)) {
|
|
716
|
+
process.stdout.write(JSON.stringify({
|
|
717
|
+
hookSpecificOutput: {
|
|
718
|
+
hookEventName: "PreToolUse",
|
|
719
|
+
permissionDecision: "deny",
|
|
720
|
+
permissionDecisionReason: `当前 SoloForge 任务仍处于 ${currentTask.status},说明分类、澄清或意图膨胀未闭合。不得绕过 sf_expand 直接写业务实现;请先运行 soloforge next 或 sf_status action=archive_stale confirm=true 处理任务状态。`,
|
|
721
|
+
},
|
|
722
|
+
}));
|
|
723
|
+
process.exit(0);
|
|
724
|
+
}
|
|
725
|
+
if (implementationSource && !currentTask && hasDesignArtifacts(projectPath)) {
|
|
726
|
+
process.stdout.write(JSON.stringify({
|
|
727
|
+
hookSpecificOutput: {
|
|
728
|
+
hookEventName: "PreToolUse",
|
|
729
|
+
permissionDecision: "deny",
|
|
730
|
+
permissionDecisionReason: "检测到项目已有架构/详细/API/数据库设计产物,但当前没有受控 SoloForge 任务。不得绕过 sf_classify/sf_expand 直接写业务实现;请先运行 soloforge next 或通过 MCP 建立编码任务。",
|
|
731
|
+
},
|
|
732
|
+
}));
|
|
733
|
+
process.exit(0);
|
|
734
|
+
}
|
|
735
|
+
if (implementationSource && currentTask && !designPack && hasDesignArtifacts(projectPath)) {
|
|
736
|
+
process.stdout.write(JSON.stringify({
|
|
737
|
+
hookSpecificOutput: {
|
|
738
|
+
hookEventName: "PreToolUse",
|
|
739
|
+
permissionDecision: "deny",
|
|
740
|
+
permissionDecisionReason: "检测到项目已有设计产物,但当前任务缺少 design_artifact_pack 复验状态。不得直接写业务实现;请先运行 soloforge audit-design-artifacts,并通过 sf_expand/sf_verify 绑定设计产物包。",
|
|
741
|
+
},
|
|
742
|
+
}));
|
|
743
|
+
process.exit(0);
|
|
744
|
+
}
|
|
704
745
|
if (designPack && designPack.status !== "implementation_ready") {
|
|
705
746
|
process.stdout.write(JSON.stringify({
|
|
706
747
|
hookSpecificOutput: {
|
|
@@ -742,12 +783,95 @@ function resolveProjectPath() {
|
|
|
742
783
|
}
|
|
743
784
|
return process.cwd();
|
|
744
785
|
}
|
|
786
|
+
function isImplementationSourcePath(relativeFilePath) {
|
|
787
|
+
if (/^(?:docs|templates|\.soloforge|\.claude|\.codex|\.trae)\//.test(relativeFilePath))
|
|
788
|
+
return false;
|
|
789
|
+
if (/(^|\/)(?:package-lock|pnpm-lock|yarn.lock)$/.test(relativeFilePath))
|
|
790
|
+
return false;
|
|
791
|
+
return /\.(?:java|kt|kts|scala|ts|tsx|js|jsx|mjs|cjs|py|go|rs|php|rb|cs|swift|vue|svelte|sql|xml|yml|yaml|properties)$/.test(relativeFilePath);
|
|
792
|
+
}
|
|
793
|
+
function hasDesignArtifacts(projectPath) {
|
|
794
|
+
const candidates = [
|
|
795
|
+
path.join(projectPath, "docs", "architecture", "00-架构决策记录.md"),
|
|
796
|
+
path.join(projectPath, "docs", "architecture", "01-架构设计文档.md"),
|
|
797
|
+
path.join(projectPath, "docs", "architecture", "02-数据库设计文档.md"),
|
|
798
|
+
path.join(projectPath, "docs", "architecture", "03-API接口规格文档.md"),
|
|
799
|
+
path.join(projectPath, "docs", "architecture", "04-详细设计文档.md"),
|
|
800
|
+
path.join(projectPath, "docs", "architecture", "99-设计一致性验收报告.md"),
|
|
801
|
+
path.join(projectPath, "docs", "api", "openapi.yaml"),
|
|
802
|
+
path.join(projectPath, "docs", "api", "openapi.yml"),
|
|
803
|
+
path.join(projectPath, "db", "migrations"),
|
|
804
|
+
path.join(projectPath, "db", "migration"),
|
|
805
|
+
];
|
|
806
|
+
return candidates.some((candidate) => fss.existsSync(candidate));
|
|
807
|
+
}
|
|
745
808
|
async function cmdPostBash() {
|
|
746
809
|
debugLog("CLI: 执行 cmdPostBash");
|
|
747
810
|
// Bash 的 PostToolUse hook — 目前为空操作占位符
|
|
748
811
|
// 未来: 跟踪命令结果,检测构建/测试失败
|
|
749
812
|
process.exit(0);
|
|
750
813
|
}
|
|
814
|
+
function extractBashCommand(rawInput) {
|
|
815
|
+
const trimmed = rawInput.trim();
|
|
816
|
+
if (!trimmed)
|
|
817
|
+
return "";
|
|
818
|
+
try {
|
|
819
|
+
const parsed = JSON.parse(trimmed);
|
|
820
|
+
const input = parsed.tool_input || parsed.toolInput || parsed.input || parsed;
|
|
821
|
+
return String(input.command || input.cmd || parsed.command || "");
|
|
822
|
+
}
|
|
823
|
+
catch {
|
|
824
|
+
return trimmed;
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
async function cmdCheckBash() {
|
|
828
|
+
debugLog("CLI: 执行 cmdCheckBash");
|
|
829
|
+
try {
|
|
830
|
+
const chunks = [];
|
|
831
|
+
for await (const chunk of process.stdin) {
|
|
832
|
+
chunks.push(chunk);
|
|
833
|
+
}
|
|
834
|
+
const stdin = Buffer.concat(chunks).toString();
|
|
835
|
+
const commandText = extractBashCommand(stdin || args.join(" "));
|
|
836
|
+
if (isSoloforgeStateBypassCommand(commandText)) {
|
|
837
|
+
process.stdout.write(JSON.stringify({
|
|
838
|
+
hookSpecificOutput: {
|
|
839
|
+
hookEventName: "PreToolUse",
|
|
840
|
+
permissionDecision: "deny",
|
|
841
|
+
permissionDecisionReason: "禁止通过 Bash 直接修改 .soloforge/state;请使用 SoloForge MCP 工具,例如 sf_status action=archive_stale confirm=true。",
|
|
842
|
+
},
|
|
843
|
+
}));
|
|
844
|
+
}
|
|
845
|
+
process.exit(0);
|
|
846
|
+
}
|
|
847
|
+
catch (e) {
|
|
848
|
+
userError(`SoloForge Bash 检查错误: ${e instanceof Error ? e.message : String(e)}`);
|
|
849
|
+
process.exit(1);
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
async function cmdDoctor() {
|
|
853
|
+
debugLog("CLI: 执行 cmdDoctor");
|
|
854
|
+
const isJson = args.includes("--json");
|
|
855
|
+
const projectPath = process.cwd();
|
|
856
|
+
const report = auditControlPlaneProject(projectPath);
|
|
857
|
+
if (isJson) {
|
|
858
|
+
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
859
|
+
return;
|
|
860
|
+
}
|
|
861
|
+
userInfo(`SoloForge 控制面诊断: ${projectPath}`);
|
|
862
|
+
userInfo(` 状态: ${report.passed ? "通过" : "需修复"}`);
|
|
863
|
+
userInfo(` 控制面矩阵: ${report.matrix_count} 类`);
|
|
864
|
+
userInfo(` 枝叶细节: ${report.branch_detail_count} 条`);
|
|
865
|
+
if (report.findings.length === 0) {
|
|
866
|
+
userInfo(" finding: 0");
|
|
867
|
+
return;
|
|
868
|
+
}
|
|
869
|
+
for (const finding of report.findings) {
|
|
870
|
+
const marker = finding.severity === "hard_fail" ? "❌" : finding.severity === "warning" ? "⚠️" : "ℹ️";
|
|
871
|
+
userInfo(` ${marker} [${finding.code}] ${finding.message}`);
|
|
872
|
+
userInfo(` 恢复: ${finding.recovery}`);
|
|
873
|
+
}
|
|
874
|
+
}
|
|
751
875
|
export { buildHookAdditionalContext } from "../adapters/claude_code/pre_prompt_contract.js";
|
|
752
876
|
async function cmdPrePrompt() {
|
|
753
877
|
debugLog("CLI: 执行 cmdPrePrompt");
|
|
@@ -2458,11 +2582,41 @@ async function cmdStage() {
|
|
|
2458
2582
|
async function cmdCleanup() {
|
|
2459
2583
|
debug("CLI", "执行 cmdCleanup");
|
|
2460
2584
|
const dryRun = !args.includes("--apply");
|
|
2585
|
+
const staleOnly = args.includes("--stale");
|
|
2461
2586
|
const projectPath = process.cwd();
|
|
2462
2587
|
const stateDir = path.join(projectPath, ".soloforge", "state");
|
|
2463
2588
|
let hasError = false;
|
|
2464
2589
|
userInfo(`SoloForge 清理: ${projectPath}`);
|
|
2465
2590
|
userInfo(` 模式: ${dryRun ? "dry-run(仅评估)" : "⚠️ 实际清理"}`);
|
|
2591
|
+
if (staleOnly) {
|
|
2592
|
+
try {
|
|
2593
|
+
const { detectStaleCurrentTask, archiveStaleCurrentPointer } = await import("../engine/stale_current_task_detector.js");
|
|
2594
|
+
const stale = await detectStaleCurrentTask(stateDir);
|
|
2595
|
+
userInfo("");
|
|
2596
|
+
userInfo(" 陈旧 current-task 检测:");
|
|
2597
|
+
if (!stale.is_stale || !stale.task_id) {
|
|
2598
|
+
userInfo(" 未发现陈旧指针");
|
|
2599
|
+
return;
|
|
2600
|
+
}
|
|
2601
|
+
userInfo(` 陈旧任务: ${stale.task_id}`);
|
|
2602
|
+
userInfo(` 原因: ${stale.reason_zh}`);
|
|
2603
|
+
if (dryRun) {
|
|
2604
|
+
userInfo(" 处理: dry-run,仅提示;使用 --apply 归档指针");
|
|
2605
|
+
return;
|
|
2606
|
+
}
|
|
2607
|
+
const archived = await archiveStaleCurrentPointer(stateDir, stale.task_id);
|
|
2608
|
+
if (!archived) {
|
|
2609
|
+
userError(" ❌ 陈旧指针归档失败");
|
|
2610
|
+
process.exit(1);
|
|
2611
|
+
}
|
|
2612
|
+
userInfo(" 处理: 已归档 current-task 指针,任务文件未删除");
|
|
2613
|
+
return;
|
|
2614
|
+
}
|
|
2615
|
+
catch (e) {
|
|
2616
|
+
userError(` ❌ 陈旧 current-task 检测失败: ${e.message}`);
|
|
2617
|
+
process.exit(1);
|
|
2618
|
+
}
|
|
2619
|
+
}
|
|
2466
2620
|
// 收集所有 evidence 引用来源:task-*.json 中的 evidence 文件名 / evidence id
|
|
2467
2621
|
const referencedEvidenceIds = new Set();
|
|
2468
2622
|
// 扫描 task context 文件中的 evidence 引用
|