sillyspec 3.28.3 → 3.28.5
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 +114 -114
- package/.claude/skills/sillyspec-continue/SKILL.md +17 -17
- package/.claude/skills/sillyspec-execute/SKILL.md +222 -222
- package/.claude/skills/sillyspec-knowledge/SKILL.md +40 -40
- package/.claude/skills/sillyspec-plan/SKILL.md +156 -156
- package/.claude/skills/sillyspec-propose/SKILL.md +16 -16
- package/.claude/skills/sillyspec-resume/SKILL.md +21 -21
- package/.claude/skills/sillyspec-state/SKILL.md +25 -25
- package/.claude/skills/sillyspec-workspace/SKILL.md +33 -33
- package/AGENTS.md +25 -0
- package/INSTRUCTIONS.md +12 -0
- package/package.json +1 -1
- package/results-review-tier.md +18 -0
- package/src/agent-session-log.js +4 -3
- package/src/archive-delta.js +82 -0
- package/src/change-delete.js +2 -1
- package/src/change-list.js +18 -3
- package/src/change-risk-profile.js +77 -6
- package/src/commit-suggest.js +52 -1
- package/src/config-cat.js +17 -1
- package/src/constants.js +3 -1
- package/src/decision-distill.js +45 -5
- package/src/decisions-io.js +96 -0
- package/src/design-facts.js +3 -0
- package/src/dispatch/probe.js +31 -8
- package/src/docs-check.js +102 -3
- package/src/doctor-diagnostics.js +441 -5
- package/src/foreign-declared.js +53 -2
- package/src/index.js +606 -22
- package/src/mcp-server.js +144 -0
- package/src/module-impact.js +84 -12
- package/src/modules.js +46 -34
- package/src/plan-adopt-waves.js +13 -5
- package/src/progress/change-registry.js +34 -0
- package/src/progress.js +75 -2
- package/src/quick-recommend.js +6 -1
- package/src/quicklog.js +70 -8
- package/src/review-dispatch.js +377 -0
- package/src/run/archive-distill.js +48 -0
- package/src/run/command.js +48 -13
- package/src/run/complete-handlers.js +215 -9
- package/src/run/complete.js +184 -2
- package/src/run/gate-snapshot.js +88 -0
- package/src/run/gates.js +206 -58
- package/src/run/prompt.js +150 -14
- package/src/run/quick-audit.js +38 -13
- package/src/run/shared.js +183 -12
- package/src/run/stage.js +52 -2
- package/src/run/verify-quality-scan.js +336 -0
- package/src/runtime-hygiene.js +84 -0
- package/src/scope-audit.js +735 -0
- package/src/sillyhub-mcp/client.js +58 -3
- package/src/spec-sync.js +63 -8
- package/src/stage-contract.js +83 -3
- package/src/stage-review-checklist.js +44 -0
- package/src/stage-review.js +125 -4
- package/src/stages/archive.js +60 -167
- package/src/stages/brainstorm.js +7 -17
- package/src/stages/doctor.js +41 -515
- package/src/stages/execute.js +13 -10
- package/src/stages/plan-postcheck.js +191 -7
- package/src/stages/plan.js +7 -35
- package/src/stages/quick.js +11 -11
- package/src/stages/verify.js +24 -39
- package/src/sync-noise.js +158 -0
- package/src/sync.js +93 -27
- package/src/task-review.js +133 -17
- package/src/taskcard.js +46 -3
- package/src/validate-artifacts.js +163 -0
- package/src/verify-facts-schema.js +141 -0
- package/src/verify-postcheck.js +347 -29
- package/src/verify-probes.js +275 -24
- package/src/workflow.js +6 -0
- package/src/worktree-apply.js +167 -24
- package/src/worktree.js +5 -1
- package/templates/agents-instruction.md +1 -0
package/src/foreign-declared.js
CHANGED
|
@@ -14,6 +14,7 @@ import { existsSync, readFileSync, readdirSync } from 'fs'
|
|
|
14
14
|
import { join } from 'path'
|
|
15
15
|
import { parseFileChangeListDetailed } from './change-list.js'
|
|
16
16
|
import { safeGit, unquoteGitPath } from './git-helper.js'
|
|
17
|
+
import { parseAllowedPaths, parseTargetFiles } from './stages/plan-postcheck.js'
|
|
17
18
|
|
|
18
19
|
/**
|
|
19
20
|
* 主仓未提交文件集(staged + unstaged + untracked,rename 取新路径)。
|
|
@@ -138,8 +139,53 @@ export function collectForeignDeclaredFiles(cwd, currentChangeName, opts = {}) {
|
|
|
138
139
|
return foreign
|
|
139
140
|
}
|
|
140
141
|
|
|
142
|
+
/**
|
|
143
|
+
* 本变更(currentChangeName)的 own 声明集——own 优先判据(坑
|
|
144
|
+
* verify-reconcile-own-file-foreign-false-positive,2026-09-09 实证):
|
|
145
|
+
* quick 会话 = guard.allowedFiles;变更 = design §6 清单 ∪ task 卡 allowed_paths/target_files。
|
|
146
|
+
* 文件被本变更与他者**双方声明**时归 own:foreign 排除的职责是「他者的工作不混进我的
|
|
147
|
+
* 判定」,不是「我声明并真实修改的文件因他者(尤其未归档旧变更的陈旧 design 声明)也
|
|
148
|
+
* 声明过就被剔出我的对账」。读不出来(无 design/无 task 卡/quick guard 损坏)→ 空集
|
|
149
|
+
* (退回旧 foreign-first 行为,fail-closed 不放大放行面)。
|
|
150
|
+
* @returns {Set<string>} 正斜杠归一后的声明路径集
|
|
151
|
+
*/
|
|
152
|
+
function loadOwnDeclaredSet(specBase, runtimeRoot, currentChangeName) {
|
|
153
|
+
const set = new Set()
|
|
154
|
+
if (!currentChangeName) return set
|
|
155
|
+
const norm = (p) => String(p || '').replace(/\\/g, '/')
|
|
156
|
+
const addAll = (paths) => { for (const p of paths) { const n = norm(p); if (n) set.add(n) } }
|
|
157
|
+
try {
|
|
158
|
+
if (/^quick-[0-9a-f]{8}$/.test(currentChangeName)) {
|
|
159
|
+
try {
|
|
160
|
+
const guard = JSON.parse(readFileSync(join(runtimeRoot, 'quick-sessions', currentChangeName, 'guard.json'), 'utf8'))
|
|
161
|
+
addAll(Array.isArray(guard?.allowedFiles) ? guard.allowedFiles : [])
|
|
162
|
+
} catch { /* guard 缺失/损坏 → 空集退回旧行为 */ }
|
|
163
|
+
return set
|
|
164
|
+
}
|
|
165
|
+
const changeDir = join(specBase, 'changes', currentChangeName)
|
|
166
|
+
try { addAll(parseFileChangeListDetailed(join(changeDir, 'design.md')).map(e => e.path)) } catch {}
|
|
167
|
+
let taskFiles = []
|
|
168
|
+
try { taskFiles = readdirSync(join(changeDir, 'tasks')).filter(f => /^task-\d+\.md$/.test(f)) } catch {}
|
|
169
|
+
for (const tf of taskFiles) {
|
|
170
|
+
try {
|
|
171
|
+
const content = readFileSync(join(changeDir, 'tasks', tf), 'utf8')
|
|
172
|
+
addAll(parseAllowedPaths(content))
|
|
173
|
+
addAll(parseTargetFiles(content).entries.map(e => e.path))
|
|
174
|
+
} catch { /* 单卡损坏跳过 */ }
|
|
175
|
+
}
|
|
176
|
+
} catch { /* 整体异常 → 空集 */ }
|
|
177
|
+
return set
|
|
178
|
+
}
|
|
179
|
+
|
|
141
180
|
/**
|
|
142
181
|
* 按他者声明集切分 diff 文件(collectForeignDeclaredFiles 的消费端快捷封装)。
|
|
182
|
+
*
|
|
183
|
+
* own 优先(2026-09-09 坑 verify-reconcile-own-file-foreign-false-positive 修复):文件在
|
|
184
|
+
* 本变更 own 声明集(design §6 / task allowed_paths / target_files / quick guard)内时
|
|
185
|
+
* 永不判 foreign——哪怕他者变更(含未归档旧变更的陈旧声明,其活性被本变更自己的 dirty
|
|
186
|
+
* 反向喂活)也声明过。双方都声明 = 归属歧义按「自己声明优先」收敛:本变更的 dirty 是
|
|
187
|
+
* 自己工作的一部分,剔除它只会制造「声明未做」假红。
|
|
188
|
+
*
|
|
143
189
|
* @param {string} cwd 项目根
|
|
144
190
|
* @param {string|null} currentChangeName 本变更名
|
|
145
191
|
* @param {string[]|null} diffFiles 待切分文件列表(null 透传,保持调用方 null 语义)
|
|
@@ -148,12 +194,17 @@ export function collectForeignDeclaredFiles(cwd, currentChangeName, opts = {}) {
|
|
|
148
194
|
*/
|
|
149
195
|
export function splitOwnVsForeignDiffFiles(cwd, currentChangeName, diffFiles, opts = {}) {
|
|
150
196
|
if (!Array.isArray(diffFiles)) return { own: diffFiles, foreign: [] }
|
|
151
|
-
const
|
|
197
|
+
const specBase = opts.specBase || join(cwd, '.sillyspec')
|
|
198
|
+
const runtimeRoot = opts.runtimeRoot || join(specBase, '.runtime')
|
|
199
|
+
const foreignMap = collectForeignDeclaredFiles(cwd, currentChangeName, { specBase, runtimeRoot })
|
|
152
200
|
if (foreignMap.size === 0) return { own: diffFiles, foreign: [] }
|
|
201
|
+
const ownDeclared = loadOwnDeclaredSet(specBase, runtimeRoot, currentChangeName)
|
|
153
202
|
const own = []
|
|
154
203
|
const foreign = []
|
|
155
204
|
for (const f of diffFiles) {
|
|
156
|
-
const
|
|
205
|
+
const n = String(f).replace(/\\/g, '/')
|
|
206
|
+
if (ownDeclared.size > 0 && ownDeclared.has(n)) { own.push(f); continue } // own 优先
|
|
207
|
+
const owners = foreignMap.get(n)
|
|
157
208
|
if (owners) foreign.push({ file: f, owners })
|
|
158
209
|
else own.push(f)
|
|
159
210
|
}
|