sillyspec 3.29.5 → 3.30.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.
- package/.claude/skills/sillyspec-auto/SKILL.md +54 -54
- package/.claude/skills/sillyspec-brainstorm/SKILL.md +2 -2
- package/.claude/skills/sillyspec-commit/SKILL.md +1 -1
- package/.claude/skills/sillyspec-flow/SKILL.md +57 -0
- package/.claude/skills/sillyspec-quick/SKILL.md +18 -116
- package/AGENTS.md +38 -20
- package/SKILL.md +9 -3
- package/assets/command-cards/flow.md +32 -0
- package/assets/command-cards/run-brainstorm.md +1 -1
- package/assets/command-cards/run-quick.md +8 -25
- package/package.json +2 -1
- package/packages/dashboard/server/executor.js +2 -1
- package/packages/dashboard/server/parser.js +7 -7
- package/r7-test-env/README-R7-TEST.md +93 -0
- package/r7-test-env/demo-project/lib/calc.js +6 -0
- package/r7-test-env/demo-project/package.json +1 -0
- package/r7-test-env/demo-project/test.js +10 -0
- package/r7-test-env/prompt-R7-SMOKE.md +41 -0
- package/r7-test-env/sillyspec-r7.cmd +3 -0
- package/round4/account.mjs +18 -5
- package/round4/b1-analyze-task08.mjs +40 -0
- package/round4/b1-b1-target-validation.md +32 -0
- package/round4/b3a-prompt-audit-result.md +66 -0
- package/round4/b3a-prompt-audit.mjs +89 -0
- package/round4/optimization-plan.md +165 -0
- package/round4/r4-final-report.html +347 -0
- package/round4/r5-scenario-matrix.md +46 -0
- package/src/change-list.js +9 -0
- package/src/classify-change.js +6 -0
- package/src/command-cards.js +2 -1
- package/src/commit-guard.js +2 -0
- package/src/config-schema.js +64 -12
- package/src/db.js +35 -4
- package/src/decision-distill.js +9 -3
- package/src/docs-check.js +1 -1
- package/src/doctor-diagnostics.js +44 -2
- package/src/flow-draft.js +748 -0
- package/src/flow-parity.js +236 -0
- package/src/flow-review.js +184 -0
- package/src/flow.js +1492 -0
- package/src/foreign-declared.js +17 -1
- package/src/fr-index.js +396 -22
- package/src/fs-atomic.js +5 -1
- package/src/git-helper.js +2 -2
- package/src/greenfield-bootstrap.js +98 -0
- package/src/handoff.js +120 -7
- package/src/hunk-attribution.js +191 -0
- package/src/index.js +570 -16
- package/src/knowledge-classify.js +47 -1
- package/src/knowledge-digest.js +162 -0
- package/src/knowledge-quicklog.js +246 -0
- package/src/machine-draft.js +128 -0
- package/src/machine-interface.js +107 -5
- package/src/mcp-server.js +1 -0
- package/src/module-resolve.js +3 -1
- package/src/preview-progress.js +160 -0
- package/src/progress/change-registry.js +11 -3
- package/src/progress/shared.js +3 -2
- package/src/progress.js +56 -13
- package/src/quicklog.js +44 -6
- package/src/redomain.js +147 -0
- package/src/review-material-pack.js +204 -1
- package/src/run/archive-distill.js +4 -2
- package/src/run/bg-sync.js +67 -0
- package/src/run/command.js +123 -10
- package/src/run/complete-handlers.js +327 -72
- package/src/run/complete.js +350 -71
- package/src/run/gate-snapshot-ledger.js +213 -0
- package/src/run/gate-snapshot.js +250 -34
- package/src/run/gates.js +370 -233
- package/src/run/green-cache.js +123 -0
- package/src/run/junction-rm.js +70 -0
- package/src/run/next.js +14 -0
- package/src/run/prompt.js +185 -55
- package/src/run/quick-audit.js +185 -12
- package/src/run/shared.js +120 -3
- package/src/run/stage.js +182 -216
- package/src/run/test-ledger.js +264 -0
- package/src/run/verify-quality-scan.js +84 -7
- package/src/scope-audit.js +6 -1
- package/src/sentinel-assertions.js +114 -0
- package/src/setup.js +3 -3
- package/src/spec-sync.js +41 -1
- package/src/stage-contract.js +26 -8
- package/src/stage-review-checklist.js +2 -0
- package/src/stage-review.js +7 -2
- package/src/stage-templates.js +157 -0
- package/src/stages/archive.js +2 -0
- package/src/stages/brainstorm.js +24 -106
- package/src/stages/execute.js +221 -84
- package/src/stages/knowledge.js +74 -1
- package/src/stages/plan-postcheck.js +352 -1
- package/src/stages/plan.js +23 -1
- package/src/stages/quick.js +10 -2
- package/src/stages/verify.js +4 -2
- package/src/sync.js +81 -23
- package/src/task-done.js +181 -0
- package/src/task-review.js +8 -55
- package/src/test-bindings.js +549 -0
- package/src/timeline.js +218 -0
- package/src/ui-visual.js +175 -0
- package/src/verify-draft.js +214 -0
- package/src/verify-postcheck.js +860 -158
- package/src/verify-probes.js +59 -3
- package/src/watcher.js +1031 -0
- package/src/worktree-apply.js +44 -4
- package/src/worktree-deps.js +22 -8
- package/src/worktree-policy.js +42 -0
- package/src/worktree.js +102 -15
- package/templates/agents-instruction.md +37 -18
package/src/run/command.js
CHANGED
|
@@ -20,14 +20,14 @@
|
|
|
20
20
|
* './run/stage.js' → './shared.js' 等同级
|
|
21
21
|
*/
|
|
22
22
|
import { basename, join, resolve, dirname } from 'node:path'
|
|
23
|
-
import { existsSync, readdirSync, mkdirSync, writeFileSync, readFileSync, rmSync, unlinkSync } from 'node:fs'
|
|
23
|
+
import { existsSync, readdirSync, mkdirSync, writeFileSync, readFileSync, rmSync, unlinkSync, statSync } from 'node:fs'
|
|
24
24
|
import { randomBytes, randomUUID } from 'node:crypto'
|
|
25
25
|
import { fileURLToPath } from 'node:url'
|
|
26
26
|
import { writeAtomicSync } from '../fs-atomic.js'
|
|
27
|
-
import { resolveSpecDir, countAncestorSpecDirs, ancestorSpecDirs, resolveAncestorCeiling, resolveChangeDir, triggerSync, getStageSteps, formatWaitOptions, checkApproval, warnApprovalUnknown, didYouMean, assertSafeChangeName, assertDatedChangeName, detectQuickSessionDrift, detectWorktreeSpecDrift, resolveRuntimeRoot, resolveQuickSessionsDir, writePlatformPointer, checkPlatformManaged, isSelfReferentialSpecRoot, isTempResidueSpecRoot, PLATFORM_MANAGED_FILENAME, warnSelfRefPointerOnce } from './shared.js'
|
|
27
|
+
import { resolveSpecDir, countAncestorSpecDirs, ancestorSpecDirs, resolveAncestorCeiling, resolveChangeDir, triggerSync, getStageSteps, formatWaitOptions, checkApproval, warnApprovalUnknown, didYouMean, assertSafeChangeName, assertDatedChangeName, detectQuickSessionDrift, detectWorktreeSpecDrift, resolveRuntimeRoot, resolveQuickSessionsDir, writePlatformPointer, checkPlatformManaged, isSelfReferentialSpecRoot, isTempResidueSpecRoot, PLATFORM_MANAGED_FILENAME, warnSelfRefPointerOnce, readStageBurst, STAGE_BURST_STAGES } from './shared.js'
|
|
28
28
|
import { resolveQuickLinkedChanges } from './quick-audit.js'
|
|
29
29
|
import { outputStep, collectStageWaitHistory } from './prompt.js'
|
|
30
|
-
import { completeStep, skipStep, waitStep, continueStep, synthesizeStepOutput } from './complete.js'
|
|
30
|
+
import { completeStep, completeStepBurst, skipStep, waitStep, continueStep, synthesizeStepOutput } from './complete.js'
|
|
31
31
|
import { runStage } from './stage.js'
|
|
32
32
|
import { sanitizeDesc } from '../quicklog.js'
|
|
33
33
|
import { ProgressManager, resolveSessionIdentity } from '../progress.js'
|
|
@@ -52,6 +52,7 @@ const VALUE_FLAGS = new Set([
|
|
|
52
52
|
'--base', // scan diff 基线 commit(吃值;只在 run scan --diff 转发路径消费)
|
|
53
53
|
'--session', // 显式会话标识(吃值;2026-09-14-change-ownership-guards task-02 所有权三级解析最高优先级层,启动 claim 消费)
|
|
54
54
|
'--inherit-from', // wait 继承盖章锚点 <D-xxx@vN>(吃值;2026-09-18-preflight-slimming task-03 / D-003@v2:仅 --wait 场景合法,--wait 分发点校验消费)
|
|
55
|
+
'--step', // --done --step <名|序号> 意图断言(吃值;:340 消费。漏登记死路同 --wait-interactive 前例:burst 说明书出示该形态却被未知参数 exit(2) 拦死,2026-09-23 执行会话实证)
|
|
55
56
|
])
|
|
56
57
|
|
|
57
58
|
/**
|
|
@@ -720,6 +721,10 @@ export async function runCommand(args, cwd, specDir = null, opts = {}) {
|
|
|
720
721
|
'--takeover', // 所有权护栏显式强制接管(task-02 / FR-01:本层只注册透传,实际消费在 index.js apply/cleanup 子命令层——run 侧带上不报未知参数,语义出口在 worktree 命令)
|
|
721
722
|
'--skip-apply', // 归档收口跳过 apply 校验(task-02 只注册透传不改行为,消费归 task-03 archive 接线)
|
|
722
723
|
'--inherit-from', // wait 继承盖章 <D-xxx@vN>(2026-09-18-preflight-slimming task-03:仅 --wait 场景合法,hasDecisionId 校验+盖章在 --wait 分发点/complete 层)
|
|
724
|
+
'--step', // --done 意图断言 <名|序号>(吃值,VALUE_FLAGS 同步登记;:340 消费——漏登记则说明书出示的 --done --step 形态进命令即被未知参数拦死,2026-09-23 执行会话实证)
|
|
725
|
+
'--upgrade-thick', // 轻量→完整升档用户同意门(2026-09-25-thin-upgrade-consent:布尔 flag,混跑回退写侧 :1362 消费——无 flag 拒跑,带 flag 落 legacy_fallback+同意时点留痕)
|
|
726
|
+
'--same-session', // R17 实验实证死路清偿(cli-protocol-trust):STAGE_WALL 报错指引「加 --same-session 重跑」(stage.js 硬墙文案),消费在 runStage 逃生口——此前漏登记,照指引重跑即被本白名单 exit 2(指引指向死路的自我矛盾)
|
|
727
|
+
'--force', // 同族第二实例(静态扫描新发现):quick --cancel 强清消费点与报错指引(可用 --force)在场但未登记——同死路;一致性钉 test/flag-contract.test.mjs 守护整类
|
|
723
728
|
'-h',
|
|
724
729
|
])
|
|
725
730
|
for (let i = 0; i < flags.length; i++) {
|
|
@@ -795,6 +800,43 @@ export async function runCommand(args, cwd, specDir = null, opts = {}) {
|
|
|
795
800
|
} catch {}
|
|
796
801
|
}
|
|
797
802
|
if (!quickSessionId) {
|
|
803
|
+
// 坑 quick-done-长静默与快照行尾假阳性 坑3(2026-09-21 实证):`quick --status` 不带
|
|
804
|
+
// --change 时缺省语义是「新建」而非「查看」——查进度忘带 --change 直接误开空壳会话
|
|
805
|
+
//(需 --cancel 清理)。只读意图(--status)拦截:读 current marker 与最近 guard 目录
|
|
806
|
+
// 展示最近会话状态 + 提示带 --change,零副作用退出(绝不新建)。
|
|
807
|
+
if (isStatus) {
|
|
808
|
+
const recentRoot = resolveRuntimeRoot(platformOpts, specRoot)
|
|
809
|
+
let recent = null
|
|
810
|
+
try {
|
|
811
|
+
const idFile = join(recentRoot, 'current-quick-run-id')
|
|
812
|
+
if (existsSync(idFile)) {
|
|
813
|
+
const v = readFileSync(idFile, 'utf8').trim()
|
|
814
|
+
if (QUICK_SID_RE.test(v)) recent = v
|
|
815
|
+
}
|
|
816
|
+
} catch { /* 读失败按无 marker 处理 */ }
|
|
817
|
+
if (!recent) {
|
|
818
|
+
try {
|
|
819
|
+
const sessRoot = join(recentRoot, 'quick-sessions')
|
|
820
|
+
if (existsSync(sessRoot)) {
|
|
821
|
+
const cands = readdirSync(sessRoot, { withFileTypes: true })
|
|
822
|
+
.filter(d => d.isDirectory() && QUICK_SID_RE.test(d.name))
|
|
823
|
+
.map(d => ({ name: d.name, m: statSync(join(sessRoot, d.name, 'guard.json')).mtimeMs }))
|
|
824
|
+
.filter(x => x.m > 0)
|
|
825
|
+
.sort((a, b) => b.m - a.m)
|
|
826
|
+
if (cands.length > 0) recent = cands[0].name
|
|
827
|
+
}
|
|
828
|
+
} catch { /* 枚举失败按无近期会话处理 */ }
|
|
829
|
+
}
|
|
830
|
+
console.log('ℹ️ `run quick --status` 不带 --change 查的是最近会话,不会新建(查进度请带 --change <sessionId>)')
|
|
831
|
+
if (recent) {
|
|
832
|
+
console.log(` 最近会话: ${recent}(本命令将展示其状态)`)
|
|
833
|
+
quickSessionId = recent
|
|
834
|
+
quickFallbackUsed = true
|
|
835
|
+
} else {
|
|
836
|
+
console.log(' 本仓无近期 quick 会话记录(current marker 与 quick-sessions 均空)——新工作请走轻量变更:sillyspec flow start --change <名> --input "<动机与背景;随后独立一行『成功标准:』;再每行一条『- <可验证标准>』>"')
|
|
837
|
+
process.exit(0)
|
|
838
|
+
}
|
|
839
|
+
} else {
|
|
798
840
|
// 坑 quick-no-input-placeholder-title(2026-08-24 二期①;2026-09-19 上移):全新 quick 会话
|
|
799
841
|
// (即将生成新 sessionId)缺 --input 且无可取标题的 --linked-changes → 拒绝启动(exit 2,
|
|
800
842
|
// 零沉没成本)。原位置在 flag 校验之后,但 sessionId 生成/「已建立」公告与 agent-log 平台
|
|
@@ -828,6 +870,7 @@ export async function runCommand(args, cwd, specDir = null, opts = {}) {
|
|
|
828
870
|
// 若把命令拖过 exec 超时,调用方仍能从输出头部拿到 sessionId 续用(--status / guard.json
|
|
829
871
|
// 核对),不会误开空壳新会话。
|
|
830
872
|
console.log(`📌 quick 会话已建立: ${quickSessionId}(后续若超时/中断,用 --change ${quickSessionId} 续用)`)
|
|
873
|
+
}
|
|
831
874
|
}
|
|
832
875
|
changeName = quickSessionId
|
|
833
876
|
} else {
|
|
@@ -1305,6 +1348,45 @@ export async function runCommand(args, cwd, specDir = null, opts = {}) {
|
|
|
1305
1348
|
// 注册变更到全局活跃列表(如果尚未注册)
|
|
1306
1349
|
if (effectiveChange) {
|
|
1307
1350
|
pm.registerChange(cwd, effectiveChange)
|
|
1351
|
+
// ── watcher 拉起(R7 切片一 / D-001:观测与协议解耦)──
|
|
1352
|
+
// effectiveChange 解析后无条件 spawn(不做「检测新建」——registerChange 是 INSERT OR
|
|
1353
|
+
// IGNORE 不返回新建信号),活锁在跑由单飞锁合并 coalesced。best-effort:失败只 warn
|
|
1354
|
+
// 绝不阻断主流程;未连接平台也 spawn(本地 jsonl 是事件唯一真相源);
|
|
1355
|
+
// SILLYSPEC_WATCHER=0 逃生阀。default 容器行不监听(非真实变更)。
|
|
1356
|
+
if (effectiveChange !== 'default') {
|
|
1357
|
+
// ── 混跑回退写侧(R7 切片二 / FR-06 / D-002:thin change 上跑 run <stage> = 该 change
|
|
1358
|
+
// 回 legacy 记账——flow done 读侧拒裁并指路厚档;两套记账不叠加。一次性置位留痕。)──
|
|
1359
|
+
// 升厚同意门(2026-09-25-thin-upgrade-consent,R16 实测驱动):轻量→完整是成本数倍的资源
|
|
1360
|
+
// 决策,归属用户——agent 不得凭 CLI 的 advisory 自行转道。混跑回退须显式 --upgrade-thick
|
|
1361
|
+
// (=「用户已同意」的落痕 flag,同 --force 留痕先例);无 flag 拒跑指路。
|
|
1362
|
+
try {
|
|
1363
|
+
const flowStatePath = join(specRoot, 'changes', effectiveChange, 'flow-state.yaml')
|
|
1364
|
+
if (existsSync(flowStatePath)) {
|
|
1365
|
+
const { readFlowState, writeFlowState } = await import('../flow.js')
|
|
1366
|
+
const changeDir = join(specRoot, 'changes', effectiveChange)
|
|
1367
|
+
const st = readFlowState(changeDir)
|
|
1368
|
+
if (st && !st.legacy_fallback) {
|
|
1369
|
+
if (!flags.includes('--upgrade-thick')) {
|
|
1370
|
+
console.error(`⛔ 本变更在轻量跑道上(flow-state 在场)——升厚走完整流程需用户同意,agent 不得自行转道:`)
|
|
1371
|
+
console.error(` · 征得用户同意后带 --upgrade-thick 重跑本命令(落痕留档,首次转厚即转)`)
|
|
1372
|
+
console.error(` · 用户未确认或选择轻量跑 → 继续轻量变更:直接干活,收口 sillyspec flow done --change ${effectiveChange}`)
|
|
1373
|
+
process.exit(2)
|
|
1374
|
+
}
|
|
1375
|
+
writeFlowState(changeDir, { legacy_fallback: true, upgraded_by_consent: new Date().toISOString() })
|
|
1376
|
+
console.warn(`⚠️ [flow] thin change「${effectiveChange}」经用户同意(--upgrade-thick 落痕)升厚——已混跑回退 legacy(flow done 将按厚档拒裁并指路;两套记账不叠加)`)
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
} catch { /* 探测失败不阻断既有 run 流程(process.exit 直出不经 catch) */ }
|
|
1380
|
+
try {
|
|
1381
|
+
const { spawnWatcher } = await import('../watcher.js')
|
|
1382
|
+
const r = await spawnWatcher(cwd, effectiveChange, { ...platformOpts, specBase })
|
|
1383
|
+
if (r.status === 'spawned') {
|
|
1384
|
+
console.log(`🔄 [watcher] 观测旁路已拉起(产物签名轮询,事件恒带 provisional:true): ${effectiveChange}`)
|
|
1385
|
+
}
|
|
1386
|
+
} catch (e) {
|
|
1387
|
+
console.warn(`⚠️ [watcher] 拉起失败(观测旁路 best-effort,不影响主流程): ${(e && e.message) || e}`)
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1308
1390
|
// ── 所有权首建 claim(2026-09-14-change-ownership-guards task-02 / FR-01 / D-001@v1)──
|
|
1309
1391
|
// run <stage> 启动即认领 owner(claimChangeOwner 守卫语义:已有值不覆盖——他人持有不抢
|
|
1310
1392
|
// 也不拒;拒绝语义只锁接管类操作,见 index.js apply/cleanup/assess 接线)。会话标识三级:
|
|
@@ -1656,11 +1738,16 @@ export async function runCommand(args, cwd, specDir = null, opts = {}) {
|
|
|
1656
1738
|
const doneAnswer = getFlagValue('--answer')
|
|
1657
1739
|
// isSkipApply/sessionFlag(task-03):--skip-apply 归档收口跳过 + --session 所有权会话标识,
|
|
1658
1740
|
// 随 completeStep options 透传(isNoDocs 同款链路)——消费点 archive/quick 收尾 handler。
|
|
1741
|
+
// burst 分发门(2026-09-22-stage-burst-fold D-003@v2/FR-06):白名单主阶段 + readStageBurst
|
|
1742
|
+
// 开启 → completeStepBurst 循环收口(completeStep 本体零改动,守卫逐轮生效);options 原样透传。
|
|
1743
|
+
if (STAGE_BURST_STAGES.includes(stageName) && await readStageBurst(cwd)) {
|
|
1744
|
+
return await completeStepBurst(pm, progress, stageName, cwd, outputText, inputText, { confirm: isConfirm, changeName: effectiveChange, nonInteractive: isNonInteractive && !isInteractive, platformOpts, doneAnswer, isForceBaseline, isAllowNew, isAllowDelete, isNoDocs, isSkipApply, sessionFlag: getFlagValue('--session'), quickFiles, stepAssert: stepAssertValue })
|
|
1745
|
+
}
|
|
1659
1746
|
return await completeStep(pm, progress, stageName, cwd, outputText, inputText, { confirm: isConfirm, changeName: effectiveChange, nonInteractive: isNonInteractive && !isInteractive, platformOpts, doneAnswer, isForceBaseline, isAllowNew, isAllowDelete, isNoDocs, isSkipApply, sessionFlag: getFlagValue('--session'), quickFiles, stepAssert: stepAssertValue })
|
|
1660
1747
|
}
|
|
1661
1748
|
|
|
1662
1749
|
// 默认:输出当前步骤
|
|
1663
|
-
return await runStage(pm, progress, stageName, cwd, effectiveChange, isSkipApproval, platformOpts, { quickFiles, isAllowNew, isAllowDelete, isForceBaseline, isForceRescan, linkedChanges, linkedChangesAuto: linkedAuto, taskDescription: inputText, adoptBranch: stageName === 'execute' && flags.includes('--adopt-branch') })
|
|
1750
|
+
return await runStage(pm, progress, stageName, cwd, effectiveChange, isSkipApproval, platformOpts, { quickFiles, isAllowNew, isAllowDelete, isForceBaseline, isForceRescan, linkedChanges, linkedChangesAuto: linkedAuto, taskDescription: inputText, adoptBranch: stageName === 'execute' && flags.includes('--adopt-branch'), sameSession: flags.includes('--same-session') })
|
|
1664
1751
|
}
|
|
1665
1752
|
|
|
1666
1753
|
/**
|
|
@@ -1848,6 +1935,23 @@ async function runAutoMode(pm, progress, cwd, flags, changeName, platformOpts =
|
|
|
1848
1935
|
// 零活跃建变更已上移入口守卫层,多活跃 exit 2 由入口守卫处理)。
|
|
1849
1936
|
if (changeName) console.log(`🎯 auto 目标变更(单活跃自动选中或显式指定):${changeName}`)
|
|
1850
1937
|
|
|
1938
|
+
// ── watcher 拉起(2026-09-23-sentinel-rules task-05 / FR-09)──
|
|
1939
|
+
// run auto 在 runCommand 主干的 spawnWatcher 挂点(effectiveChange 解析后那处)之前
|
|
1940
|
+
// 早退进本函数——auto 路径是 run 族唯一观测缺口。语义同 flow start 接线:best-effort
|
|
1941
|
+
// 失败只 warn 不阻断,SILLYSPEC_WATCHER=0 逃生阀在 spawnWatcher 内短路,活锁合并
|
|
1942
|
+
// coalesced,未连接平台也 spawn(本地 jsonl 是事件唯一真相源)。
|
|
1943
|
+
if (changeName && changeName !== 'default') {
|
|
1944
|
+
try {
|
|
1945
|
+
const { spawnWatcher } = await import('../watcher.js')
|
|
1946
|
+
const r = await spawnWatcher(cwd, changeName, { ...platformOpts, specBase })
|
|
1947
|
+
if (r.status === 'spawned') {
|
|
1948
|
+
console.log(`🔄 [watcher] 观测旁路已拉起(auto 路径补挂,事件恒带 provisional:true): ${changeName}`)
|
|
1949
|
+
}
|
|
1950
|
+
} catch (e) {
|
|
1951
|
+
console.warn(`⚠️ [watcher] 拉起失败(观测旁路 best-effort,不影响主流程): ${(e && e.message) || e}`)
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
|
|
1851
1955
|
// Helper: 在 auto 模式下获取步骤定义
|
|
1852
1956
|
const getAutoSteps = async (stage) => {
|
|
1853
1957
|
if (stage === 'brainstorm') {
|
|
@@ -1905,8 +2009,9 @@ async function runAutoMode(pm, progress, cwd, flags, changeName, platformOpts =
|
|
|
1905
2009
|
const localConfig = readAutoModeFromLocalYaml(cwd)
|
|
1906
2010
|
const classification = classifyChange({ description: inputText || '', explicitMode, localConfig })
|
|
1907
2011
|
if (classification.mode === 'quick') {
|
|
1908
|
-
console.log(`📊 auto 模式分类:${classification.
|
|
1909
|
-
console.log(`
|
|
2012
|
+
console.log(`📊 auto 模式分类:${classification.reason} 判为小变更`)
|
|
2013
|
+
console.log(` 小变更请走轻量变更(quick 通道已退役,v3.30.0 起拒绝新会话):`)
|
|
2014
|
+
console.log(` sillyspec flow start --change <名> --input "<动机与背景;随后独立一行『成功标准:』;再每行一条『- <可验证标准>』>"`)
|
|
1910
2015
|
return
|
|
1911
2016
|
}
|
|
1912
2017
|
console.log(`📊 auto 模式分类:${classification.mode}(${classification.reason})`)
|
|
@@ -1993,16 +2098,24 @@ async function runAutoMode(pm, progress, cwd, flags, changeName, platformOpts =
|
|
|
1993
2098
|
return
|
|
1994
2099
|
}
|
|
1995
2100
|
|
|
1996
|
-
|
|
2101
|
+
// burst 分发门(2026-09-22-stage-burst-fold D-003@v2/X-4,FR-06):auto 路径 burst 分支跳过
|
|
2102
|
+
// --output 预合成(预合成文本在 burst 下沦为横幅重复打印——burst 直接透传原始 outputText,
|
|
2103
|
+
// 横幅去重归 completeStepBurst 单点),循环收口后本路径既有推进逻辑(nextPendingIdx 渲染 /
|
|
2104
|
+
// nextInFlow 阶段推进)基于重读 progress 自然衔接。
|
|
2105
|
+
const _autoBurstOn = STAGE_BURST_STAGES.includes(currentStage) && await readStageBurst(cwd)
|
|
2106
|
+
|
|
2107
|
+
if (!outputText && !_autoBurstOn) {
|
|
1997
2108
|
// P0-2(noai-ir-roadmap §3):auto --done 的 --output 同样可省略——与 completeStep 同源
|
|
1998
2109
|
// 的事实性摘要合成(此前硬拒 exit 2 是用法守卫;SS-META 的 doneCommand 仍带 --output,
|
|
1999
2110
|
// 照抄路径零变化,省略路径不再罚一轮)。
|
|
2000
2111
|
const _autoStep = progress?.stages?.[currentStage]?.steps?.find((s) => s && ['pending', 'in-progress', 'blocked'].includes(s.status))
|
|
2001
|
-
outputText = synthesizeStepOutput({ stageName: currentStage, stepName: _autoStep?.name || currentStage, cwd })
|
|
2112
|
+
outputText = synthesizeStepOutput({ stageName: currentStage, stepName: _autoStep?.name || currentStage, cwd, platformOpts })
|
|
2002
2113
|
console.log(`🤖 auto --done 未带 --output——CLI 已按事实合成步骤摘要(语义说明下次带 --output 手写)。`)
|
|
2003
2114
|
}
|
|
2004
2115
|
|
|
2005
|
-
const result =
|
|
2116
|
+
const result = _autoBurstOn
|
|
2117
|
+
? await completeStepBurst(pm, progress, currentStage, cwd, outputText, inputText, { printNext: false, changeName, platformOpts })
|
|
2118
|
+
: await completeStep(pm, progress, currentStage, cwd, outputText, inputText, { printNext: false, changeName, platformOpts })
|
|
2006
2119
|
if (!result) return
|
|
2007
2120
|
progress = pm.read(cwd, changeName)
|
|
2008
2121
|
// change 行被并发归档/删除时 read 返回 null(体检 BUG-05):引导排查而非 TypeError 崩溃
|
|
@@ -2161,7 +2274,7 @@ export async function maybeWaitInteractive(stepDef, changeName, stageName, { rlF
|
|
|
2161
2274
|
const { execFileSync } = await import('node:child_process')
|
|
2162
2275
|
const binSelf = resolveBinSelfPath()
|
|
2163
2276
|
try {
|
|
2164
|
-
execFileSync(process.execPath, [binSelf, 'run', 'auto', '--continue', '--answer', answer.trim(), '--change', changeName], { stdio: 'inherit', cwd: process.cwd() })
|
|
2277
|
+
execFileSync(process.execPath, [binSelf, 'run', 'auto', '--continue', '--answer', answer.trim(), '--change', changeName], { stdio: 'inherit', cwd: process.cwd(), windowsHide: true })
|
|
2165
2278
|
} catch { /* continue 失败(非 waiting 态等)静默——回三段式由 agent 走 */ }
|
|
2166
2279
|
}
|
|
2167
2280
|
} catch (e) {
|