sillyspec 3.23.5 → 3.23.6

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.
@@ -0,0 +1 @@
1
+ //registry.npmjs.org/:_authToken=${NPM_TOKEN}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sillyspec",
3
- "version": "3.23.5",
3
+ "version": "3.23.6",
4
4
  "description": "SillySpec CLI — 流程状态机,让 AI 严格按步骤来",
5
5
  "icon": "logo.jpg",
6
6
  "homepage": "https://sillyspec.ppdmq.top/",
@@ -134,8 +134,10 @@ function parseTaskDependencies(planContent) {
134
134
  * @param {string} taskName - task-04
135
135
  * @returns {{ ok: boolean, endpoints: Array, artifactPath: string|null }}
136
136
  */
137
- export function extractProviderArtifact(changeDir, worktreePath, specBase, taskName) {
138
- const artifactDir = join(specBase, '.runtime', 'contract-artifacts', taskName)
137
+ export function extractProviderArtifact(changeDir, worktreePath, specBase, taskName, runtimeRoot) {
138
+ // 平台模式 contract-artifacts 落 runtimeRoot;否则落 specBase/.runtime
139
+ const artifactRoot = runtimeRoot || join(specBase, '.runtime')
140
+ const artifactDir = join(artifactRoot, 'contract-artifacts', taskName)
139
141
  const artifactPath = join(artifactDir, 'endpoints.json')
140
142
 
141
143
  if (!worktreePath || !existsSync(worktreePath)) {
@@ -179,13 +181,15 @@ export function extractProviderArtifact(changeDir, worktreePath, specBase, taskN
179
181
  * @param {Array<{ provider: string, consumer: string, type: string }>} contracts
180
182
  * @returns {string|null} 注入到 prompt 的契约文本,无契约时返回 null
181
183
  */
182
- export function buildConsumerInjection(changeDir, specBase, taskName, contracts) {
184
+ export function buildConsumerInjection(changeDir, specBase, taskName, contracts, runtimeRoot) {
185
+ // 平台模式 contract-artifacts 落 runtimeRoot;否则落 specBase/.runtime
186
+ const artifactRoot = runtimeRoot || join(specBase, '.runtime')
183
187
  const myContracts = contracts.filter(c => c.consumer === taskName)
184
188
  if (myContracts.length === 0) return null
185
189
 
186
190
  const parts = []
187
191
  for (const contract of myContracts) {
188
- const artifactDir = join(specBase, '.runtime', 'contract-artifacts', contract.provider)
192
+ const artifactDir = join(artifactRoot, 'contract-artifacts', contract.provider)
189
193
  const artifactFile = join(artifactDir, 'endpoints.json')
190
194
 
191
195
  let endpoints = []
@@ -293,11 +297,13 @@ export function buildContractFieldInjection(changeDir, taskName) {
293
297
  * @param {string} worktreePath - worktree 路径
294
298
  * @returns {{ ok: boolean, missingBackend: Array, unusedBackend: Array, summary: string }}
295
299
  */
296
- export function verifyApiParity(specBase, worktreePath) {
300
+ export function verifyApiParity(specBase, worktreePath, runtimeRoot) {
297
301
  const { diffApiParity } = require('./endpoint-extractor.js')
298
302
 
303
+ // 平台模式 contract-artifacts 落 runtimeRoot;否则落 specBase/.runtime
304
+ const artifactRoot = runtimeRoot || join(specBase, '.runtime')
299
305
  // 读取所有 provider artifacts
300
- const artifactBase = join(specBase, '.runtime', 'contract-artifacts')
306
+ const artifactBase = join(artifactRoot, 'contract-artifacts')
301
307
  const allProviderEndpoints = []
302
308
 
303
309
  if (existsSync(artifactBase)) {
package/src/progress.js CHANGED
@@ -731,7 +731,11 @@ export class ProgressManager {
731
731
  console.warn('⚠️ initChange: changeName 为空,跳过');
732
732
  return null;
733
733
  }
734
- this._ensureChangeDir(cwd, changeName);
734
+ // quick 会话 id(quick-<uuid8>,见 run.js QUICK_SID_RE)只作 progress 的跨进程 session key,
735
+ // 进度存 SQL 不需要实体 change 目录——跳过避免 changes/quick-<uuid>/ 空目录残留。
736
+ if (!/^quick-[0-9a-f]{8}$/.test(changeName)) {
737
+ this._ensureChangeDir(cwd, changeName);
738
+ }
735
739
 
736
740
  const db = await this._ensureDB(cwd);
737
741
  db.transaction((sqlDb) => {
package/src/run.js CHANGED
@@ -1511,6 +1511,15 @@ export async function runCommand(args, cwd, specDir = null) {
1511
1511
  }
1512
1512
  }
1513
1513
 
1514
+ // execute 阶段必须带 --change:不允许自动检测或默认值,变更名必须由 agent 显式传入
1515
+ // --status 豁免(纯查看不需要指定变更)
1516
+ if (stageName === 'execute' && !changeName && !isStatus) {
1517
+ console.error('❌ execute 阶段必须用 --change <变更名> 指定要操作的变更。')
1518
+ console.error(' agent 必须传参,不设默认值、不做自动检测。')
1519
+ console.error(' 请加 --change <变更名> 重新执行。')
1520
+ process.exit(1)
1521
+ }
1522
+
1514
1523
  let progress = await pm.read(cwd, changeName)
1515
1524
 
1516
1525
  if (!progress) {
@@ -1844,7 +1853,7 @@ async function runStage(pm, progress, stageName, cwd, changeName, skipApproval =
1844
1853
  if (stageName === 'execute') {
1845
1854
  const { generateExecuteRunId } = await import('./task-review.js')
1846
1855
  const execSpecBase = platformOpts?.specRoot || join(cwd, '.sillyspec')
1847
- const runtimeRoot = join(execSpecBase, '.runtime')
1856
+ const runtimeRoot = platformOpts?.runtimeRoot || join(execSpecBase, '.runtime')
1848
1857
  const runIdFile = join(runtimeRoot, `current-execute-run-id-${changeName}`)
1849
1858
  mkdirSync(runtimeRoot, { recursive: true })
1850
1859
  // 优先读取已有的变更专属标记文件
@@ -3315,7 +3324,7 @@ async function completeStep(pm, progress, stageName, cwd, outputText, inputText
3315
3324
 
3316
3325
  if (planPath && existsSync(planPath)) {
3317
3326
  const planContent = readFileSync(planPath, 'utf8')
3318
- const runtimeRoot = join(effectiveSpecBase, '.runtime')
3327
+ const runtimeRoot = platformOpts?.runtimeRoot || join(effectiveSpecBase, '.runtime')
3319
3328
 
3320
3329
  // execute run id:从变更专属标记文件读取
3321
3330
  const runIdFile = join(runtimeRoot, `current-execute-run-id-${changeName}`)