sillyspec 3.26.9 → 3.26.11
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/.claude/skills/sillyspec-archive/SKILL.md +85 -85
- package/.claude/skills/sillyspec-brainstorm/SKILL.md +114 -114
- package/.claude/skills/sillyspec-commit/SKILL.md +109 -109
- package/.claude/skills/sillyspec-continue/SKILL.md +45 -45
- package/.claude/skills/sillyspec-doctor/SKILL.md +76 -76
- package/.claude/skills/sillyspec-execute/SKILL.md +200 -200
- package/.claude/skills/sillyspec-explore/SKILL.md +95 -95
- package/.claude/skills/sillyspec-knowledge/SKILL.md +269 -269
- package/.claude/skills/sillyspec-plan/SKILL.md +148 -148
- package/.claude/skills/sillyspec-quick/SKILL.md +111 -111
- package/.claude/skills/sillyspec-resume/SKILL.md +68 -68
- package/.claude/skills/sillyspec-scan/SKILL.md +79 -79
- package/.claude/skills/sillyspec-state/SKILL.md +64 -64
- package/.claude/skills/sillyspec-status/SKILL.md +54 -54
- package/.claude/skills/sillyspec-verify/SKILL.md +83 -81
- package/.claude/skills/sillyspec-workspace/SKILL.md +169 -169
- package/.gitattributes +2 -0
- package/.husky/pre-push +20 -20
- package/.npmrc-publish +2 -0
- package/README.md +201 -201
- package/SKILL.md +90 -90
- package/package.json +39 -39
- package/packages/dashboard/dist/assets/index-Bq_Z2hne.js +7446 -7446
- package/packages/dashboard/dist/assets/index-O2W5RV4z.css +1 -1
- package/packages/dashboard/dist/index.html +16 -16
- package/packages/dashboard/package.json +25 -25
- package/packages/dashboard/server/executor.js +86 -86
- package/packages/dashboard/server/index.js +601 -601
- package/packages/dashboard/server/parser.js +526 -526
- package/src/change-risk-profile.js +254 -254
- package/src/classify-change.js +109 -109
- package/src/config-schema.js +310 -310
- package/src/contract-matrix.js +379 -379
- package/src/db.js +350 -350
- package/src/dispatch/backends/local-agent.js +155 -155
- package/src/dispatch/backends/sillyhub-mcp.js +245 -245
- package/src/dispatch/probe.js +210 -210
- package/src/dispatch/strategy.js +121 -121
- package/src/docs-check.js +131 -4
- package/src/doctor-diagnostics.js +711 -711
- package/src/endpoint-extractor.js +401 -401
- package/src/fs-atomic.js +69 -69
- package/src/git-helper.js +79 -79
- package/src/hooks/claude-pre-tool-use.cjs +125 -125
- package/src/hooks/worktree-guard.js +848 -848
- package/src/index.js +90 -8
- package/src/init.js +623 -623
- package/src/knowledge-match.js +130 -130
- package/src/local-detect.js +120 -120
- package/src/machine-interface.js +543 -543
- package/src/migrate.js +127 -127
- package/src/progress/change-registry.js +297 -260
- package/src/progress/consistency-doctor.js +355 -355
- package/src/progress/shared.js +36 -36
- package/src/progress/stage-machine.js +29 -1
- package/src/progress/step-store.js +261 -261
- package/src/progress.js +1131 -1127
- package/src/quicklog.js +693 -675
- package/src/review-tier.js +77 -77
- package/src/run/command.js +1385 -1364
- package/src/run/complete-handlers.js +198 -9
- package/src/run/complete.js +225 -24
- package/src/run/concurrent-detect.js +22 -0
- package/src/run/gates.js +755 -755
- package/src/run/prompt.js +761 -721
- package/src/run/quick-audit.js +155 -146
- package/src/run/shared.js +1268 -1197
- package/src/run/stage.js +487 -479
- package/src/scan-postcheck.js +371 -371
- package/src/setup.js +416 -416
- package/src/sillyhub-mcp/client.js +529 -529
- package/src/spec-sync.js +323 -0
- package/src/stage-contract.js +897 -897
- package/src/stage-review.js +549 -549
- package/src/stages/archive.js +155 -154
- package/src/stages/brainstorm-auto.js +236 -236
- package/src/stages/brainstorm.js +596 -597
- package/src/stages/cmd-existence.js +145 -145
- package/src/stages/doctor.js +371 -371
- package/src/stages/execute.js +1003 -991
- package/src/stages/explore.js +34 -34
- package/src/stages/index.js +29 -29
- package/src/stages/knowledge.js +498 -498
- package/src/stages/plan-postcheck.js +1302 -1281
- package/src/stages/plan.js +625 -604
- package/src/stages/quick.js +151 -143
- package/src/stages/scan.js +606 -605
- package/src/stages/status.js +64 -64
- package/src/stages/verify.js +264 -261
- package/src/sync.js +1223 -1125
- package/src/task-review.js +1019 -1019
- package/src/verify-postcheck.js +1186 -1186
- package/src/workflow.js +600 -600
- package/src/worktree-apply.js +1213 -1136
- package/src/worktree-deps.js +353 -353
- package/src/worktree.js +1481 -1437
- package/templates/workflows/archive-impact.yaml +79 -79
- package/templates/workflows/scan-docs.yaml +132 -132
package/src/index.js
CHANGED
|
@@ -585,12 +585,19 @@ async function main() {
|
|
|
585
585
|
// json 变量(filteredArgs 不含);分支内 BARE_FLAGS(无值)置位剔除、PAIRED_FLAGS(带值)
|
|
586
586
|
// 成对剔除;未知 --xxx 显式 exit 2——不再静默落入文档路径误报"不存在"
|
|
587
587
|
// (历史两次踩坑:--json 恒失效、--suggest 被当文档路径)。
|
|
588
|
-
|
|
588
|
+
// task-03(2026-08-18 platform-map-auto-anchors):白名单加 --fix / --dry-run——
|
|
589
|
+
// --fix 对 fixable 失效引用自动重锚(消费 task-01 的 inv.fix 分类 + task-02 的 applyFixes
|
|
590
|
+
// 写回);--dry-run 预览不写盘,单独传(无 --fix)也走预览路径——design §5.2 行为矩阵
|
|
591
|
+
// --dry-run 列独立存在(「报告修复预览 + exit 1」),即 dryRun 置位 = fix 语义自动生效
|
|
592
|
+
// 但零写盘(本口径记录于此,防歧义)。
|
|
593
|
+
const BARE_FLAGS = ['--suggest', '--fix', '--dry-run'];
|
|
589
594
|
const PAIRED_FLAGS = ['--paths'];
|
|
590
595
|
const rawDocsArgs = filteredArgs.slice(2);
|
|
591
596
|
const docsCheckFlags = [];
|
|
592
597
|
let cliPaths = null;
|
|
593
598
|
let suggest = false;
|
|
599
|
+
let fix = false;
|
|
600
|
+
let dryRun = false;
|
|
594
601
|
for (let i = 0; i < rawDocsArgs.length; i++) {
|
|
595
602
|
const a = rawDocsArgs[i];
|
|
596
603
|
if (a === '--paths' && rawDocsArgs[i + 1] !== undefined) {
|
|
@@ -601,6 +608,8 @@ async function main() {
|
|
|
601
608
|
process.exit(2);
|
|
602
609
|
} else if (BARE_FLAGS.includes(a)) {
|
|
603
610
|
if (a === '--suggest') suggest = true;
|
|
611
|
+
else if (a === '--fix') fix = true;
|
|
612
|
+
else if (a === '--dry-run') dryRun = true;
|
|
604
613
|
} else if (a.startsWith('--')) {
|
|
605
614
|
console.error(`❌ docs check: 未知 flag「${a}」。已知 flag:${[...BARE_FLAGS, ...PAIRED_FLAGS].join(' ')}(--json 为全局 flag)`);
|
|
606
615
|
process.exit(2);
|
|
@@ -608,7 +617,7 @@ async function main() {
|
|
|
608
617
|
docsCheckFlags.push(a);
|
|
609
618
|
}
|
|
610
619
|
}
|
|
611
|
-
const { runDocsCheck, readDocsCheckConfig, DocsCheckConfigError } = await import('./docs-check.js');
|
|
620
|
+
const { runDocsCheck, readDocsCheckConfig, DocsCheckConfigError, applyFixes } = await import('./docs-check.js');
|
|
612
621
|
try {
|
|
613
622
|
// 配置优先级:--paths > local.yaml docs-check.paths > 缺省 docs/**/*.md
|
|
614
623
|
const cfg = readDocsCheckConfig(dir);
|
|
@@ -619,7 +628,29 @@ async function main() {
|
|
|
619
628
|
skip: cfg.skip,
|
|
620
629
|
keywordAssert: cfg.keywordAssert,
|
|
621
630
|
});
|
|
631
|
+
// task-03 修复链路(FR-04,platform-map-auto-anchors):fixActive 才构造 fixes——
|
|
632
|
+
// 仅 fix.fixable===true 且 newLine 为整数的条目可重锚;newRef = ref 的行号部分替换为
|
|
633
|
+
// newLine(文件名原样保留;范围引用 src/a.js:3-8 重锚后收窄为单行语义,design §5.1
|
|
634
|
+
// 「自动改写为该行号」)。多命中/零命中(needs-manual)只报告不修(D-006),无 --force 逃生口。
|
|
635
|
+
// applyFixes 空列表零 IO 直返 {0,[]},全绿时调用无副作用;fixes 与 invalid 条目一一对应,
|
|
636
|
+
// needs-manual 数 = invalid.length - fixes.length。
|
|
637
|
+
const fixActive = fix || dryRun;
|
|
638
|
+
const fixes = [];
|
|
639
|
+
const newRefByInv = new Map();
|
|
640
|
+
if (fixActive && !result.ok) {
|
|
641
|
+
for (const inv of result.invalid) {
|
|
642
|
+
if (inv.fix && inv.fix.fixable === true && Number.isInteger(inv.fix.newLine)) {
|
|
643
|
+
const newRef = inv.ref.replace(/(\d+)(?:-\d+)?$/, String(inv.fix.newLine));
|
|
644
|
+
fixes.push({ doc: inv.doc, docLine: inv.docLine, ref: inv.ref, newRef });
|
|
645
|
+
newRefByInv.set(inv, newRef);
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
const fixResult = fixActive ? applyFixes(dir, fixes, dryRun ? { dryRun: true } : {}) : null;
|
|
622
650
|
if (json) {
|
|
651
|
+
// --fix 与 --json 组合保持 stdout 纯 JSON 可解析(constraints):修复统计作 result.fixReport
|
|
652
|
+
// 附加后整体 stringify,主体仍是 runDocsCheck 返回(invalid[].fix 是 task-01 设计内增量)
|
|
653
|
+
if (fixResult) result.fixReport = { applied: fixResult.applied, skipped: fixResult.skipped.length, dryRun };
|
|
623
654
|
console.log(JSON.stringify(result, null, 2));
|
|
624
655
|
} else {
|
|
625
656
|
for (const w of result.warnings) console.warn(`⚠️ ${w}`);
|
|
@@ -627,17 +658,50 @@ async function main() {
|
|
|
627
658
|
console.log(`✅ docs check: ${result.total} 处引用全通过(其中 ${result.kwChecked} 处带关键词断言)`);
|
|
628
659
|
} else {
|
|
629
660
|
console.error(`\n❌ docs check: ${result.invalid.length}/${result.total} 处引用失效:`);
|
|
661
|
+
let appliedLeft = fixResult ? fixResult.applied : 0;
|
|
662
|
+
const skippedQueue = fixResult ? [...fixResult.skipped] : [];
|
|
630
663
|
for (const inv of result.invalid) {
|
|
631
|
-
|
|
664
|
+
const newRef = newRefByInv.get(inv);
|
|
665
|
+
if (newRef !== undefined && appliedLeft > 0) {
|
|
666
|
+
// 已应用(dry-run 为将应用):归因按构造顺序消耗 applied 计数——写回 skipped 仅
|
|
667
|
+
// 防御路径(文档消失/行内失配)触发,CLI 正常流 fixable 必然落位
|
|
668
|
+
console.error(` ✅ [${inv.doc}:L${inv.docLine}] ${inv.ref} → ${newRef}${dryRun ? '(dry-run 未写盘)' : ''}`);
|
|
669
|
+
appliedLeft--;
|
|
670
|
+
} else if (newRef !== undefined) {
|
|
671
|
+
const s = skippedQueue.shift();
|
|
672
|
+
console.error(` ⚠️ [${inv.doc}:L${inv.docLine}] ${inv.ref} → 写回跳过:${s ? s.reason : '未知原因'}`);
|
|
673
|
+
} else if (fixResult) {
|
|
674
|
+
// needs-manual:多命中歧义/零命中/无 token——fix.reason 含候选行号,交人工
|
|
675
|
+
console.error(` ❌ [${inv.doc}:L${inv.docLine}] ${inv.ref} → ${(inv.fix && inv.fix.reason) || inv.reason}(待人工)`);
|
|
676
|
+
} else {
|
|
677
|
+
console.error(` ❌ [${inv.doc}:L${inv.docLine}] ${inv.ref} → ${inv.reason}`);
|
|
678
|
+
}
|
|
632
679
|
if (suggest && inv.suggest && inv.suggest.length > 0) {
|
|
633
680
|
console.error(` 💡 候选行号: ${inv.suggest.join(', ')}(token 命中行,人工确认后更新文档锚)`);
|
|
634
681
|
}
|
|
635
682
|
}
|
|
683
|
+
if (fixResult) {
|
|
684
|
+
console.error(`\n🔧 重锚报告:${fixResult.applied} 处已${dryRun ? '预览' : '改写'}${dryRun ? '(dry-run 未写盘)' : ''}、${result.invalid.length - fixes.length} 处待人工${fixResult.skipped.length > 0 ? `、${fixResult.skipped.length} 处写回跳过` : ''}。`);
|
|
685
|
+
}
|
|
636
686
|
console.error(`\n修复指引:行号漂移 → 更新文档行号到当前源码;文件删改名 → 更新引用路径;`);
|
|
637
687
|
console.error(`关键词缺失但行号正确 → 确认符号是否改名,改文档 token 或行号。`);
|
|
638
688
|
}
|
|
639
689
|
}
|
|
640
|
-
|
|
690
|
+
// exit code(design §5.2 行为矩阵逐字对齐):全绿 → 0(--fix 无操作);--fix 后全部
|
|
691
|
+
// fixable 修复完且无 needs-manual 残留 → 0;仍有 needs-manual 或写回 skipped → 1;
|
|
692
|
+
// 配置错误 → 2(上方 catch DocsCheckConfigError 维持现状)。判定不重跑 runDocsCheck:
|
|
693
|
+
// fixable 条目数 === applied 且 needs-manual 数为 0 即全修(定点替换确定性成功,复查无
|
|
694
|
+
// 增量信息)。无 --fix/--dry-run 时维持 result.ok ? 0 : 1 现状(D-004 逐字节一致)。
|
|
695
|
+
if (result.ok) {
|
|
696
|
+
process.exit(0);
|
|
697
|
+
} else if (fixActive) {
|
|
698
|
+
const allFixed = fixResult.applied === fixes.length &&
|
|
699
|
+
fixResult.skipped.length === 0 &&
|
|
700
|
+
result.invalid.length - fixes.length === 0;
|
|
701
|
+
process.exit(allFixed ? 0 : 1);
|
|
702
|
+
} else {
|
|
703
|
+
process.exit(1);
|
|
704
|
+
}
|
|
641
705
|
} catch (e) {
|
|
642
706
|
if (e instanceof DocsCheckConfigError) {
|
|
643
707
|
console.error(`❌ docs check 配置错误:${e.message}`);
|
|
@@ -691,7 +755,7 @@ async function main() {
|
|
|
691
755
|
}
|
|
692
756
|
process.exit(g.exitCode);
|
|
693
757
|
} else {
|
|
694
|
-
console.log('用法: sillyspec docs migrate | sillyspec docs check [--paths <glob,...>] [--json] [--suggest] | sillyspec docs gate [--init-baseline] [--json]');
|
|
758
|
+
console.log('用法: sillyspec docs migrate | sillyspec docs check [--paths <glob,...>] [--json] [--suggest] [--fix] [--dry-run] | sillyspec docs gate [--init-baseline] [--json]');
|
|
695
759
|
process.exit(2);
|
|
696
760
|
}
|
|
697
761
|
break;
|
|
@@ -714,6 +778,11 @@ async function main() {
|
|
|
714
778
|
const { runCommand } = await import('./run.js')
|
|
715
779
|
// 平台模式(--spec-dir 已指定)时,--dir 是明确的 source_root,不应被 resolveEffectiveDir 纠正
|
|
716
780
|
const effectiveDir = specDir ? dir : resolveEffectiveDir(dir)
|
|
781
|
+
// 下行 pull:对齐顶层 stage 别名块(task-10 / D-009 / FR-04)。修复前 case 'run' 漏接,
|
|
782
|
+
// sillyspec run <stage>(含 --done)从不 pull,与别名路径行为分裂(ql-20260818-008)。
|
|
783
|
+
// 未连接平台静默跳过;本地脏时 pull 内部 skipIfLocalDirty 保守跳过,不覆盖本地进度。
|
|
784
|
+
const { triggerPullActiveChange } = await import('./run/shared.js')
|
|
785
|
+
await triggerPullActiveChange(effectiveDir)
|
|
717
786
|
await runCommand(filteredArgs.slice(1), effectiveDir, specDir, { json })
|
|
718
787
|
break
|
|
719
788
|
}
|
|
@@ -927,7 +996,7 @@ SillySpec worktree — git worktree 隔离管理
|
|
|
927
996
|
|
|
928
997
|
用法:
|
|
929
998
|
sillyspec worktree create <change-name> [--base <branch>] 创建隔离 worktree
|
|
930
|
-
sillyspec worktree apply <change-name> [--check-only]
|
|
999
|
+
sillyspec worktree apply <change-name> [--check-only] [--base merge-base|baseline] [--merge] 校验并应用变更到主工作区
|
|
931
1000
|
sillyspec worktree assess <change-name> 风险审计 + 自动 apply
|
|
932
1001
|
sillyspec worktree diff <change-name> [--base <commit>] 查看 worktree 相对 base 的变更
|
|
933
1002
|
sillyspec worktree list 列出所有活跃 worktree
|
|
@@ -974,11 +1043,24 @@ SillySpec worktree — git worktree 隔离管理
|
|
|
974
1043
|
}
|
|
975
1044
|
case 'apply': {
|
|
976
1045
|
if (!wtName) {
|
|
977
|
-
console.error('❌ 用法: sillyspec worktree apply <change-name> [--check-only] [--merge]');
|
|
1046
|
+
console.error('❌ 用法: sillyspec worktree apply <change-name> [--check-only] [--base merge-base|baseline] [--merge]');
|
|
978
1047
|
process.exit(1);
|
|
979
1048
|
}
|
|
980
1049
|
const checkOnly = args.includes('--check-only');
|
|
981
1050
|
const merge = args.includes('--merge');
|
|
1051
|
+
|
|
1052
|
+
// 解析 --base 参数(默认 merge-base)
|
|
1053
|
+
let base = 'merge-base';
|
|
1054
|
+
const baseIdx = args.indexOf('--base');
|
|
1055
|
+
if (baseIdx !== -1) {
|
|
1056
|
+
const baseVal = args[baseIdx + 1];
|
|
1057
|
+
if (!baseVal || (!['merge-base', 'baseline'].includes(baseVal))) {
|
|
1058
|
+
console.error('❌ --base 参数值非法,必须是 merge-base 或 baseline');
|
|
1059
|
+
process.exit(1);
|
|
1060
|
+
}
|
|
1061
|
+
base = baseVal;
|
|
1062
|
+
}
|
|
1063
|
+
|
|
982
1064
|
const { applyWorktree } = await import('./worktree-apply.js');
|
|
983
1065
|
// W3 task-09:apply 链路构造 ctx(D-013),让 task-05 applyWorktree 按 ctx 区分主仓 A5 / 跨仓 no-op。
|
|
984
1066
|
// 跨仓 apply=no-op(G1 D-009):校验 review.head 是跨仓真实 commit + 跳过 wm.cleanup。
|
|
@@ -991,7 +1073,7 @@ SillySpec worktree — git worktree 隔离管理
|
|
|
991
1073
|
console.error(`❌ apply 失败:跨仓 MultiRepoContext 构造失败(${e.message})`);
|
|
992
1074
|
process.exit(1);
|
|
993
1075
|
}
|
|
994
|
-
const result = applyWorktree(wtName, { cwd: dir, checkOnly, merge, ctx: _applyCtx });
|
|
1076
|
+
const result = applyWorktree(wtName, { cwd: dir, checkOnly, merge, base, ctx: _applyCtx });
|
|
995
1077
|
|
|
996
1078
|
if (result.errors.length > 0) {
|
|
997
1079
|
console.error(`❌ 校验失败:`);
|