@haposoft/cafekit 0.18.0 → 0.18.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.
Files changed (83) hide show
  1. package/README.md +1 -1
  2. package/bin/__tests__/codex-hooks.test.js +169 -236
  3. package/bin/__tests__/codex-native.test.js +54 -114
  4. package/bin/__tests__/develop-contract.test.js +101 -1361
  5. package/bin/__tests__/legacy-authority-decoupled.test.js +14 -19
  6. package/bin/__tests__/package-inventory.test.js +1 -395
  7. package/bin/__tests__/spec-narrowing.test.js +30 -134
  8. package/bin/__tests__/specs-v2-execution-closeout.test.js +0 -372
  9. package/bin/__tests__/test-runtime-dependency-closure.cjs +1 -2
  10. package/bin/__tests__/validator-grounding.test.js +17 -2929
  11. package/bin/lib/managed-writer.js +2 -3
  12. package/bin/phases/codex-runtime.js +6 -3
  13. package/bin/phases/copy-payload.js +13 -28
  14. package/bin/phases/omp-runtime.js +6 -3
  15. package/package.json +2 -3
  16. package/src/claude/agents/code-auditor.md +9 -6
  17. package/src/claude/agents/debugger.md +3 -9
  18. package/src/claude/agents/docs-keeper.md +4 -7
  19. package/src/claude/agents/git-ops.md +2 -4
  20. package/src/claude/agents/implementer.md +6 -7
  21. package/src/claude/agents/inspector.md +2 -0
  22. package/src/claude/agents/project-manager.md +2 -2
  23. package/src/claude/agents/spec-maker.md +4 -4
  24. package/src/claude/agents/test-runner.md +8 -11
  25. package/src/claude/agents/ui-ux-designer.md +0 -1
  26. package/src/claude/hooks/__tests__/spec-gate.test.js +170 -330
  27. package/src/claude/hooks/__tests__/spec-state-touched.test.js +26 -0
  28. package/src/claude/hooks/spec-gate.cjs +8 -63
  29. package/src/claude/hooks/spec-state.cjs +47 -38
  30. package/src/claude/migration-manifest.json +12 -7
  31. package/src/claude/output-styles/coding-level-0-eli5.md +9 -9
  32. package/src/claude/output-styles/coding-level-1-junior.md +3 -3
  33. package/src/claude/output-styles/coding-level-2-mid.md +3 -3
  34. package/src/claude/output-styles/coding-level-3-senior.md +2 -2
  35. package/src/claude/output-styles/coding-level-4-lead.md +5 -5
  36. package/src/claude/output-styles/coding-level-5-god.md +6 -6
  37. package/src/claude/rules/ai-dev-rules.md +1 -2
  38. package/src/claude/rules/workflow.md +1 -1
  39. package/src/claude/scripts/spec-receipt.cjs +0 -114
  40. package/src/claude/scripts/spec-resolver.cjs +41 -457
  41. package/src/claude/scripts/workflow-policy.cjs +3 -1801
  42. package/src/claude/skills/agent-browser/SKILL.md +1 -1
  43. package/src/claude/skills/chrome-devtools/SKILL.md +14 -31
  44. package/src/claude/skills/code-review/SKILL.md +25 -108
  45. package/src/claude/skills/code-review/references/spec-compliance-review.md +4 -7
  46. package/src/claude/skills/develop/SKILL.md +22 -70
  47. package/src/claude/skills/develop/references/subagent-patterns.md +0 -6
  48. package/src/claude/skills/research/SKILL.md +24 -55
  49. package/src/claude/skills/sync/SKILL.md +12 -34
  50. package/src/claude/skills/sync/references/rebind-and-audit.md +2 -2
  51. package/src/claude/skills/test/SKILL.md +39 -123
  52. package/src/claude/skills/test/references/execution-strategy.md +11 -22
  53. package/src/claude/skills/ui-ux/SKILL.md +1 -1
  54. package/src/claude/skills/ui-ux-pro-max/SKILL.md +24 -79
  55. package/src/claude/skills/web-testing/SKILL.md +2 -20
  56. package/src/codex/hooks/lib/spec-receipt.cjs +2 -30
  57. package/src/codex/hooks/lib/spec-utils.cjs +6 -45
  58. package/src/codex/hooks/spec-gate.cjs +11 -68
  59. package/src/codex/hooks/spec-state.cjs +37 -41
  60. package/src/common/AGENTS.md +4 -10
  61. package/bin/__tests__/change-firewall.semantic-firewall.test.js +0 -2133
  62. package/bin/__tests__/finalizer-pass-gate.semantic-firewall.test.js +0 -342
  63. package/bin/__tests__/release-preflight.semantic-firewall.test.js +0 -586
  64. package/bin/__tests__/review-receipt-c2.semantic-firewall.test.js +0 -378
  65. package/bin/__tests__/specs-v2-policy-and-scaffold.test.js +0 -665
  66. package/bin/__tests__/specs-v2-validator-grounder-contract.test.js +0 -1132
  67. package/src/claude/hooks/lib/context.cjs +0 -527
  68. package/src/claude/hooks/lib/detect.cjs +0 -474
  69. package/src/claude/scripts/change-firewall.cjs +0 -1748
  70. package/src/claude/scripts/spec-authoring-digest.cjs +0 -151
  71. package/src/claude/scripts/spec-authoring-validation.cjs +0 -126
  72. package/src/claude/scripts/spec-final-state.cjs +0 -290
  73. package/src/claude/scripts/spec-ground.cjs +0 -650
  74. package/src/claude/scripts/spec-readiness.cjs +0 -425
  75. package/src/claude/scripts/spec-scaffold.cjs +0 -2317
  76. package/src/claude/scripts/spec-semantic-model.cjs +0 -396
  77. package/src/claude/scripts/validate-spec-output.cjs +0 -3914
  78. package/src/claude/skills/code-review/references/verification-gate.md +0 -41
  79. package/src/claude/skills/specs/templates/design.md +0 -82
  80. package/src/claude/skills/specs/templates/requirements-init.md +0 -8
  81. package/src/claude/skills/specs/templates/requirements.md +0 -42
  82. package/src/claude/skills/specs/templates/spec-state.json +0 -56
  83. package/src/claude/skills/specs/templates/task.md +0 -47
@@ -132,3 +132,29 @@ test('a prompt touch is remembered even when two packets are active', () => {
132
132
  assert.match(fx.prompt('s7', 'Continue'), /auth-flow/);
133
133
  });
134
134
  });
135
+
136
+ function writeLegacyPacket(root, name) {
137
+ const dir = path.join(root, 'specs', name);
138
+ fs.mkdirSync(path.join(dir, 'tasks'), { recursive: true });
139
+ fs.writeFileSync(path.join(dir, 'spec.json'), JSON.stringify({ feature_name: name, status: 'in_progress' }));
140
+ }
141
+
142
+ const LEGACY_NOTICE = /`specs\/old` is a legacy Specs packet without plan\.md; CafeKit no longer reads it/;
143
+
144
+ test('a leftover legacy packet is noticed once per session, before the touch filter', () => {
145
+ within(fixture(['auth-flow']), (fx) => {
146
+ writeLegacyPacket(fx.root, 'old');
147
+ const first = fx.prompt('s1', 'Continue');
148
+ assert.match(first, LEGACY_NOTICE);
149
+ assert.strictEqual(first.match(new RegExp(LEGACY_NOTICE.source, 'g')).length, 1);
150
+ assert.strictEqual(fx.prompt('s1', 'Continue'), '', 'the same session is not told twice');
151
+ assert.match(fx.prompt('s2', 'Continue'), LEGACY_NOTICE, 'a new session is told once');
152
+ });
153
+ });
154
+
155
+ test('a legacy packet is noticed even when it is the only packet', () => {
156
+ within(fixture([]), (fx) => {
157
+ writeLegacyPacket(fx.root, 'old');
158
+ assert.match(fx.prompt('s1', 'Continue'), LEGACY_NOTICE);
159
+ });
160
+ });
@@ -97,8 +97,7 @@ try {
97
97
  RESOLVER = require(path.join(__dirname, '..', 'scripts', 'spec-resolver.cjs'));
98
98
  RECEIPT = require(path.join(__dirname, '..', 'scripts', 'spec-receipt.cjs'));
99
99
  if (typeof POLICY.validateCanonicalReceipt !== 'function'
100
- || typeof POLICY.completionDecisionForSpec !== 'function'
101
- || typeof RECEIPT.checkTaskReceipt !== 'function'
100
+ || typeof RECEIPT.checkWorkflowTaskReceipt !== 'function'
102
101
  || typeof RECEIPT.checkWorkflowReceiptSet !== 'function'
103
102
  || typeof RESOLVER.resolveWorkflowCandidate !== 'function') {
104
103
  throw new Error('shared workflow policy lacks completion authority functions');
@@ -164,7 +163,7 @@ try {
164
163
  if (resolved.error === 'invalid_specs') {
165
164
  process.stdout.write(JSON.stringify({
166
165
  decision: 'block',
167
- reason: `Completion gate: invalid spec JSON detected (${resolved.candidates.join(', ')}): ${resolved.reason}. Fix or remove malformed spec.json before completing tasks.`
166
+ reason: `Completion gate: invalid workflow packet detected (${resolved.candidates.join(', ')}): ${resolved.reason}. Fix the packet's plan.md or task files before completing tasks.`,
168
167
  }) + '\n');
169
168
  process.exit(0);
170
169
  }
@@ -177,22 +176,12 @@ try {
177
176
  }
178
177
  if (resolved.error) process.exit(0);
179
178
 
180
- const activeSpec = resolved.spec || {};
181
- const processWorkflow = resolved.layoutKind === 'process-v3';
182
179
  const featureName = resolved.featureName;
183
180
  const specsPath = resolved.specsDir;
184
- const lifecyclePhase = activeSpec.current_phase || activeSpec.phase;
185
- const explicitCloseout = ['done', 'completed', 'complete'].includes(activeSpec.status)
186
- || ['closeout', 'completion', 'completed', 'complete'].includes(lifecyclePhase);
187
- // Legacy 2.1 closeout is retired; a 2.1 packet mid-execution keeps the ordinary receipt checks.
188
- if (!processWorkflow && activeSpec.schema_version === '2.1' && explicitCloseout) {
189
- emitBlock('Completion gate: Legacy spec.json closeout is no longer supported; move the packet to plan.md with flat task files');
190
- process.exit(0);
191
- }
192
181
  const runtimeContext = POLICY.deriveRuntimeContext({
193
182
  projectRoot: baseDir,
194
183
  specsRoot: specsPath,
195
- specFile: resolved.stateFile || resolved.specFile || path.join(specsPath, featureName, 'spec.json'),
184
+ specFile: resolved.stateFile,
196
185
  featureName,
197
186
  runtimeSession: sessionIdentity(payload),
198
187
  });
@@ -202,7 +191,7 @@ try {
202
191
  emitBlock('Completion gate: runtime.spec.completion_gate is a worker-writable flag, not an authorization; no completion-gate bypass is supported. Remove the flag and satisfy the gate.');
203
192
  process.exit(0);
204
193
  }
205
- const taskRegistry = resolved.taskRegistry || activeSpec.task_registry || {};
194
+ const taskRegistry = resolved.taskRegistry || {};
206
195
  const cacheFile = path.join(require('./lib/hook-state-dir.cjs').hookStateDir(), 'spec-gate-last.json');
207
196
  const cacheExists = fs.existsSync(cacheFile);
208
197
  let cache = {};
@@ -215,17 +204,6 @@ try {
215
204
  currentStatuses[tp] = task?.status || 'pending';
216
205
  }
217
206
 
218
- const staleFlashTasks = processWorkflow ? [] : Object.entries(taskRegistry)
219
- .filter(([, task]) => POLICY.isStaleFlashDone(task))
220
- .map(([taskPath]) => taskPath);
221
- if (staleFlashTasks.length > 0) {
222
- process.stdout.write(JSON.stringify({
223
- decision: 'block',
224
- reason: `Completion gate: ${staleFlashTasks.length} task(s) marked done with FLASH_UNVERIFIED (${staleFlashTasks.join(', ')}). Run /cf:test for exact proof, then use explicit sync-finalize.`
225
- }) + '\n');
226
- process.exit(0);
227
- }
228
-
229
207
  // Cache hardening: every Stop re-reads and re-checks the receipt of every
230
208
  // task currently marked done, so a cached PASS cannot hide later mutations
231
209
  // (deletion, placeholder, changed Verification/Command/Exit, missing
@@ -241,29 +219,11 @@ try {
241
219
  const featureDir = path.join(specsPath, featureName);
242
220
  const failures = allDoneTasks
243
221
  .map((taskPath) => {
244
- const proof = processWorkflow
245
- ? RECEIPT.checkWorkflowTaskReceipt(featureDir, taskPath, runtimeContext, POLICY)
246
- : RECEIPT.checkTaskReceipt(featureDir, taskPath, taskRegistry[taskPath], runtimeContext, POLICY);
222
+ const proof = RECEIPT.checkWorkflowTaskReceipt(featureDir, taskPath, runtimeContext, POLICY);
247
223
  return { taskPath, fails: proof.failures, body: proof.body };
248
224
  })
249
225
  .filter((f) => f.fails.length > 0);
250
226
 
251
- const featureCloseoutRequired = !processWorkflow && explicitCloseout && allDoneTasks.length > 0;
252
- const featureReceipt = featureCloseoutRequired
253
- ? RECEIPT.checkFeatureReceipt(featureDir, runtimeContext, POLICY)
254
- : null;
255
- if (featureReceipt && featureReceipt.failures.length) {
256
- failures.push({ taskPath: 'feature-receipt.md', fails: featureReceipt.failures });
257
- }
258
- const completion = featureCloseoutRequired && featureReceipt?.failures.length === 0
259
- && Object.prototype.hasOwnProperty.call(activeSpec, 'workflow_policy')
260
- ? POLICY.completionDecisionForSpec(activeSpec, {
261
- runtimeContext,
262
- executionReceipt: featureReceipt.body,
263
- taskContext: {},
264
- })
265
- : null;
266
-
267
227
  // Always persist status transitions, including done → pending. Keep
268
228
  // failing done tasks at their previous cached status so a stale valid
269
229
  // entry cannot mask a mutated receipt on the next Stop; with
@@ -279,27 +239,12 @@ try {
279
239
  fs.writeFileSync(cacheFile, JSON.stringify(cache));
280
240
  } catch { /* fail-open */ }
281
241
 
282
- const completionBlocked = completion && completion.completion !== 'complete' && completion.completion !== 'not_applicable';
283
- if (failures.length === 0 && !completionBlocked) process.exit(0);
242
+ if (failures.length === 0) process.exit(0);
284
243
 
285
- const lines = [
286
- failures.length > 0
287
- ? `⚠️ Completion gate: ${failures.length} done task(s) lack a verification receipt.`
288
- : '⚠️ Completion gate: workflow completion proof is incomplete.',
289
- ];
244
+ const lines = [`⚠️ Completion gate: ${failures.length} done task(s) lack a verification receipt.`];
290
245
  for (const { taskPath, fails, body } of failures) {
291
246
  lines.push(`- \`${taskPath}\`: failed check(s) ${fails.join(', ')}`);
292
- lines.push(taskPath === 'feature-receipt.md'
293
- ? ` Fix: run final integration proof, then write \`specs/${featureName}/feature-receipt.md\`.`
294
- : processWorkflow
295
- ? ` Fix in \`specs/${featureName}/${path.posix.basename(taskPath)}\`: ${(typeof RECEIPT.receiptFixHint === 'function' && RECEIPT.receiptFixHint(fails, body)) || 'write a runtime-bound `## Receipt` with command output'}.`
296
- : ` Fix: write canonical proof to \`specs/${featureName}/receipts/${path.posix.basename(taskPath)}\`; legacy \`## Evidence\` remains read-compatible.`);
297
- }
298
- if (completionBlocked) {
299
- lines.push(`- Completion decision unfinished: ${completion.blocker || 'required workflow proof is missing.'}`);
300
- if (Array.isArray(completion.missingProof) && completion.missingProof.length > 0) {
301
- lines.push(` Missing proof: ${completion.missingProof.join(', ')}`);
302
- }
247
+ lines.push(` Fix in \`specs/${featureName}/${path.posix.basename(taskPath)}\`: ${(typeof RECEIPT.receiptFixHint === 'function' && RECEIPT.receiptFixHint(fails, body)) || 'write a runtime-bound `## Receipt` with command output'}.`);
303
248
  }
304
249
  process.stdout.write(JSON.stringify({ decision: 'block', reason: lines.slice(0, 8).join('\n') }) + '\n');
305
250
  process.exit(0);
@@ -96,7 +96,7 @@ try {
96
96
  POLICY = require(path.join(__dirname, '..', 'scripts', 'workflow-policy.cjs'));
97
97
  RESOLVER = require(path.join(__dirname, '..', 'scripts', 'spec-resolver.cjs'));
98
98
  RECEIPT = require(path.join(__dirname, '..', 'scripts', 'spec-receipt.cjs'));
99
- if (typeof POLICY.flashState !== 'function') throw new Error('shared workflow policy has no flashState function');
99
+ if (typeof RESOLVER.resolveWorkflowCandidate !== 'function') throw new Error('shared spec resolver has no resolveWorkflowCandidate function');
100
100
  } catch (error) {
101
101
  logCrash(error);
102
102
  emitControlledFailure(error.message);
@@ -167,6 +167,38 @@ try {
167
167
  process.exit(0);
168
168
  }
169
169
 
170
+ // A legacy packet (a specs/<x>/ directory without plan.md that the old flow left
171
+ // behind) is no longer read. Say so once per session instead of on every prompt.
172
+ const legacyPackets = typeof RESOLVER.findLegacyPackets === 'function'
173
+ ? RESOLVER.findLegacyPackets(baseDir, runtime)
174
+ : [];
175
+ if (legacyPackets.length > 0) {
176
+ const sessionKey = sessionIdentity(payload);
177
+ const noticeFile = sessionKey
178
+ ? path.join(
179
+ require('./lib/hook-state-dir.cjs').hookStateDir(),
180
+ `legacy-notice-${require('crypto').createHash('sha256').update(sessionKey).digest('hex')}.json`,
181
+ )
182
+ : null;
183
+ let noticed = [];
184
+ if (noticeFile) {
185
+ try { noticed = JSON.parse(fs.readFileSync(noticeFile, 'utf8')); } catch { noticed = []; }
186
+ if (!Array.isArray(noticed)) noticed = [];
187
+ }
188
+ const fresh = legacyPackets.filter((name) => !noticed.includes(name));
189
+ if (fresh.length > 0) {
190
+ for (const name of fresh) {
191
+ console.log(`\n> ⚠️ \`specs/${name}\` is a legacy Specs packet without plan.md; CafeKit no longer reads it. Move ongoing work to a process-first plan.md packet.`);
192
+ }
193
+ if (noticeFile) {
194
+ try {
195
+ fs.mkdirSync(path.dirname(noticeFile), { recursive: true });
196
+ fs.writeFileSync(noticeFile, JSON.stringify([...noticed, ...fresh].sort()));
197
+ } catch { /* an unwritable state dir only repeats the notice */ }
198
+ }
199
+ }
200
+ }
201
+
170
202
  if (touchFilter) {
171
203
  let packets = [];
172
204
  try {
@@ -177,10 +209,7 @@ try {
177
209
  if (named.length) addTouched(named);
178
210
  }
179
211
 
180
- const resolveWorkflow = typeof RESOLVER.resolveWorkflowCandidate === 'function'
181
- ? RESOLVER.resolveWorkflowCandidate
182
- : RESOLVER.resolveActiveSpec;
183
- const resolved = resolveWorkflow({ projectRoot: baseDir, runtime, explicitFeature, explicitPath });
212
+ const resolved = RESOLVER.resolveWorkflowCandidate({ projectRoot: baseDir, runtime, explicitFeature, explicitPath });
184
213
 
185
214
  if (!resolved) {
186
215
  process.exit(0); // No active spec, do nothing
@@ -194,7 +223,7 @@ try {
194
223
 
195
224
  if (resolved.error === 'invalid_specs') {
196
225
  const cands = resolved.candidates.join(', ');
197
- console.log(`\n> ⚠️ Invalid spec JSON detected: ${cands}. ${resolved.reason}. Fix or remove malformed spec.json before continuing. Tollgate paused.\n`);
226
+ console.log(`\n> ⚠️ Invalid workflow packet detected: ${cands}. ${resolved.reason}. Fix the packet's plan.md or task files before continuing. Tollgate paused.\n`);
198
227
  process.exit(0);
199
228
  }
200
229
 
@@ -208,22 +237,19 @@ try {
208
237
  process.exit(0);
209
238
  }
210
239
 
211
- const activeSpec = resolved.spec || {};
212
- const processWorkflow = resolved.layoutKind === 'process-v3';
213
240
  const featureName = resolved.featureName;
214
241
  if (touchFilter && !readTouched().has(featureName)) process.exit(0);
215
242
  const specsPath = resolved.specsDir;
216
243
  const runtimeContext = POLICY.deriveRuntimeContext({
217
244
  projectRoot: baseDir,
218
245
  specsRoot: specsPath,
219
- specFile: resolved.stateFile || resolved.specFile || path.join(specsPath, featureName, 'spec.json'),
246
+ specFile: resolved.stateFile,
220
247
  featureName,
221
248
  runtimeSession: sessionIdentity(payload),
222
249
  });
223
250
 
224
- const phase = resolved.phase || activeSpec.current_phase || activeSpec.phase || 'unknown';
225
- const taskRegistry = resolved.taskRegistry || activeSpec.task_registry || {};
226
- const flashTasks = POLICY.flashState(taskRegistry);
251
+ const phase = resolved.phase || 'unknown';
252
+ const taskRegistry = resolved.taskRegistry || {};
227
253
  const taskEntries = Object.entries(taskRegistry);
228
254
  const taskCounts = taskEntries.reduce((acc, [, task]) => {
229
255
  const status = task?.status || 'pending';
@@ -231,10 +257,7 @@ try {
231
257
  return acc;
232
258
  }, {});
233
259
  const featureDir = path.join(specsPath, featureName);
234
- const taskStatusByPath = new Map(taskEntries.map(([taskPath, task]) => [taskPath, task?.status || 'pending']));
235
- const dependencyProof = processWorkflow
236
- ? RECEIPT.workflowDependencyProofState(featureDir, taskRegistry, runtimeContext, POLICY)
237
- : {};
260
+ const dependencyProof = RECEIPT.workflowDependencyProofState(featureDir, taskRegistry, runtimeContext, POLICY);
238
261
  const taskState = taskEntries.map(([taskPath, task]) => [
239
262
  taskPath,
240
263
  task?.status || 'pending',
@@ -250,12 +273,9 @@ try {
250
273
  const nextUnblocked = taskEntries.find(([, task]) => {
251
274
  const status = task?.status || 'pending';
252
275
  const deps = Array.isArray(task?.dependencies) ? task.dependencies : [];
253
- return resolved.queueReady !== false && status === 'pending' && deps.every((dep) => (
254
- processWorkflow ? dependencyProof[dep]?.eligible === true : taskStatusByPath.get(dep) === 'done'
255
- ));
276
+ return resolved.queueReady !== false && status === 'pending'
277
+ && deps.every((dep) => dependencyProof[dep]?.eligible === true);
256
278
  });
257
- const featureReceiptPresent = !processWorkflow
258
- && RECEIPT.safeRead(featureDir, 'feature-receipt.md').status === 'ok';
259
279
 
260
280
  // ── State-change gate: only emit the full tollgate when spec state changed ──
261
281
  // The cache is shared by installed hook copies, so its key must carry the
@@ -278,7 +298,6 @@ try {
278
298
  proofState,
279
299
  done: taskCounts.done || 0,
280
300
  total: taskEntries.length,
281
- featureReceiptPresent,
282
301
  });
283
302
  const cacheFile = path.join(require('./lib/hook-state-dir.cjs').hookStateDir(), 'tollgate-last.txt');
284
303
 
@@ -288,11 +307,10 @@ try {
288
307
  }
289
308
 
290
309
  if (stateKey && lastKey === stateKey) {
291
- const stateTarget = processWorkflow ? 'task Markdown' : '`spec.json`';
292
- const migration = processWorkflow && resolved.queueReady === false
310
+ const migration = resolved.queueReady === false
293
311
  ? ' Add `Specs-Contract: process-first-ready-v1` after the plan title before tasks can enter Next.'
294
312
  : '';
295
- console.log(`\n> 🔵 Spec \`${featureName}\` @ \`${phase}\` (${taskCounts.done || 0}/${taskEntries.length} tasks done). Tollgate active — sync ${stateTarget} when state changes.${migration}\n`);
313
+ console.log(`\n> 🔵 Spec \`${featureName}\` @ \`${phase}\` (${taskCounts.done || 0}/${taskEntries.length} tasks done). Tollgate active — sync task Markdown when state changes.${migration}\n`);
296
314
  process.exit(0);
297
315
  }
298
316
 
@@ -312,20 +330,11 @@ try {
312
330
  if (nextUnblocked) {
313
331
  lines.push(`- Next unblocked: \`${nextUnblocked[0]}\``);
314
332
  }
315
- if (flashTasks.length > 0) {
316
- lines.push(`- Flash verification pending: ${flashTasks.map((taskPath) => `\`${taskPath}\``).join(', ')}. A PASS proof keeps the persisted task in_progress until explicit sync-finalize.`);
317
- }
318
- if (processWorkflow) {
319
- if (resolved.queueReady === false) {
320
- lines.push('- Migration required: add `Specs-Contract: process-first-ready-v1` after the plan title before tasks can enter Next.');
321
- }
322
- lines.push('- Sync each flat task `Status:` only after verified work; task proof belongs in that task\'s inline `## Receipt`.');
323
- lines.push(`- Workflow source: \`specs/${featureName}/plan.md\`; Stop re-checks every done receipt, binding Base/Head to the runtime only while a committed task file no longer matches its committed bytes.`);
324
- } else {
325
- lines.push('- Sync `spec.json` + task Markdown status after verified work; task proof belongs in `receipts/<task-basename>.md`.');
326
- lines.push(`- Create \`feature-receipt.md\` once after final integration proof${featureReceiptPresent ? ' (present)' : ' (not required before closeout)'}.`);
327
- lines.push(`- Validate with \`node ${runtimeDirName()}/scripts/validate-spec-output.cjs specs/${featureName}\`; hooks revalidate receipt bytes but never grant approval.`);
333
+ if (resolved.queueReady === false) {
334
+ lines.push('- Migration required: add `Specs-Contract: process-first-ready-v1` after the plan title before tasks can enter Next.');
328
335
  }
336
+ lines.push('- Sync each flat task `Status:` only after verified work; task proof belongs in that task\'s inline `## Receipt`.');
337
+ lines.push(`- Workflow source: \`specs/${featureName}/plan.md\`; Stop re-checks every done receipt, binding Base/Head to the runtime only while a committed task file no longer matches its committed bytes.`);
329
338
  lines.push('');
330
339
 
331
340
  console.log(lines.join('\n'));
@@ -59,15 +59,10 @@
59
59
  "validate-docs.cjs",
60
60
  "validate-docs-reconstruct.cjs",
61
61
  "generate-skill-catalog.cjs",
62
- "validate-spec-output.cjs",
63
62
  "scan-staged-secrets.cjs",
64
63
  "workflow-policy.cjs",
65
64
  "spec-resolver.cjs",
66
65
  "spec-receipt.cjs",
67
- "spec-ground.cjs",
68
- "spec-semantic-model.cjs",
69
- "spec-final-state.cjs",
70
- "spec-readiness.cjs",
71
66
  "provenance.cjs"
72
67
  ]
73
68
  },
@@ -97,6 +92,18 @@
97
92
  "codex": ["agents/god_developer.toml"]
98
93
  },
99
94
  "runtimeFiles": [
95
+ "scripts/validate-spec-output.cjs",
96
+ "scripts/spec-ground.cjs",
97
+ "scripts/spec-authoring-digest.cjs",
98
+ "scripts/spec-semantic-model.cjs",
99
+ "scripts/spec-final-state.cjs",
100
+ "skills/code-review/references/verification-gate.md",
101
+ "scripts/change-firewall.cjs",
102
+ "scripts/spec-scaffold.cjs",
103
+ "scripts/spec-readiness.cjs",
104
+ "scripts/spec-authoring-validation.cjs",
105
+ "hooks/lib/context.cjs",
106
+ "hooks/lib/detect.cjs",
100
107
  "hooks/skill-router.cjs",
101
108
  "hooks/lib/skill-router-routes.cjs",
102
109
  "scripts/browser-tool.cjs",
@@ -161,8 +168,6 @@
161
168
  "hooks/lib/counter.cjs",
162
169
  "hooks/lib/git.cjs",
163
170
  "hooks/lib/config.cjs",
164
- "hooks/lib/context.cjs",
165
- "hooks/lib/detect.cjs",
166
171
  "hooks/lib/hook-state-dir.cjs",
167
172
  "hooks/lib/runtime-dir.cjs",
168
173
  "hooks/lib/hook-payload.cjs",
@@ -10,18 +10,18 @@ You are teaching someone who has NEVER written a single line of code. They don't
10
10
 
11
11
  ---
12
12
 
13
- ## MANDATORY RULES (You MUST follow ALL of these)
13
+ ## Rules
14
14
 
15
15
  ### Language Rules
16
16
  1. **MUST** use at least ONE real-world analogy per concept (cooking recipes, LEGO blocks, labeled boxes, etc.)
17
17
  2. **MUST** define EVERY technical term on first use with a simple comparison
18
18
  3. **MUST** spell out ALL acronyms and explain them (e.g., "API - Application Programming Interface - think of it like a waiter taking your order to the kitchen")
19
19
  4. **MUST** use "we" language to create partnership ("Let's try...", "We can...")
20
- 5. **MUST** end EVERY response with a check-in: "Does this make sense so far? Any questions about [specific topic]?"
20
+ 5. **MUST** end explanations with a short check-in, in the user's language, naming the topic just covered
21
21
 
22
22
  ### Code Rules
23
- 1. **MUST** add a comment explaining what EVERY single line does
24
- 2. **MUST** keep code blocks to 5-10 lines maximum - break larger examples into steps
23
+ 1. **MUST** add a comment explaining what every line does in code shown in chat (code written to files follows the project's comment rules)
24
+ 2. **MUST** keep each code block to one small idea - break larger examples into steps
25
25
  3. **MUST** use descriptive variable names that read like plain English (e.g., `numberOfApples` not `n`)
26
26
  4. **MUST** show the expected output/result after EVERY code block
27
27
  5. **MUST** start with the SIMPLEST possible version, then add complexity gradually
@@ -29,17 +29,17 @@ You are teaching someone who has NEVER written a single line of code. They don't
29
29
  ### Teaching Rules
30
30
  1. **MUST** explain the "why" BEFORE the "how"
31
31
  2. **MUST** use visual metaphors and real-world comparisons
32
- 3. **MUST** celebrate progress: "Great question!", "You're getting it!"
32
+ 3. **MUST** acknowledge progress specifically when the user gets something right
33
33
  4. **MUST** encourage experimentation: "Try changing X to see what happens!"
34
34
  5. **MUST** preemptively explain anything that might be confusing
35
35
 
36
36
  ---
37
37
 
38
- ## FORBIDDEN at this level (You MUST NOT do these)
38
+ ## Avoid at this level
39
39
 
40
40
  1. **NEVER** assume they know ANY programming concept
41
41
  2. **NEVER** use technical jargon without explaining it first
42
- 3. **NEVER** show code blocks longer than 10 lines
42
+ 3. **NEVER** show a code block that teaches more than one idea at once
43
43
  4. **NEVER** use acronyms without spelling them out AND explaining
44
44
  5. **NEVER** skip steps - break everything into the smallest pieces
45
45
  6. **NEVER** use phrases like "obviously", "simply", "just", "easy"
@@ -50,7 +50,7 @@ You are teaching someone who has NEVER written a single line of code. They don't
50
50
 
51
51
  ## Required Response Structure
52
52
 
53
- Every response MUST follow this structure:
53
+ Use this structure for explanations; answer quick questions and report tool work directly:
54
54
 
55
55
  ### 1. Big Picture (1-2 sentences)
56
56
  What are we trying to accomplish? Use everyday language.
@@ -70,7 +70,7 @@ Give them something simple to experiment with.
70
70
  "Try changing the number 5 to 10 and see what happens!"
71
71
 
72
72
  ### 5. Check-In
73
- "Does this make sense so far? Any questions about [specific topic we just covered]?"
73
+ A short question, in the user's language, about the topic just covered.
74
74
 
75
75
  ---
76
76
 
@@ -10,7 +10,7 @@ You are mentoring a junior developer who understands basic programming (variable
10
10
 
11
11
  ---
12
12
 
13
- ## MANDATORY RULES (You MUST follow ALL of these)
13
+ ## Rules
14
14
 
15
15
  ### Explanation Rules
16
16
  1. **MUST** always explain WHY before showing HOW
@@ -24,7 +24,7 @@ You are mentoring a junior developer who understands basic programming (variable
24
24
  2. **MUST** use meaningful variable/function names that express intent
25
25
  3. **MUST** show before/after comparisons when refactoring or improving code
26
26
  4. **MUST** explain what each import/dependency does on first use
27
- 5. **MUST** keep code blocks under 30 lines - split larger examples
27
+ 5. **MUST** keep code examples focused - split larger examples
28
28
 
29
29
  ### Teaching Rules
30
30
  1. **MUST** define technical terms on first use (briefly, not ELI5-level)
@@ -35,7 +35,7 @@ You are mentoring a junior developer who understands basic programming (variable
35
35
 
36
36
  ---
37
37
 
38
- ## FORBIDDEN at this level (You MUST NOT do these)
38
+ ## Avoid at this level
39
39
 
40
40
  1. **NEVER** assume they know advanced patterns (design patterns, architecture)
41
41
  2. **NEVER** skip explaining WHY - always give reasoning
@@ -10,7 +10,7 @@ You are collaborating with a solid developer who has 3-5 years of experience. Th
10
10
 
11
11
  ---
12
12
 
13
- ## MANDATORY RULES (You MUST follow ALL of these)
13
+ ## Rules
14
14
 
15
15
  ### Communication Rules
16
16
  1. **MUST** discuss design patterns and when/why to apply them
@@ -29,13 +29,13 @@ You are collaborating with a solid developer who has 3-5 years of experience. Th
29
29
  ### Growth Rules
30
30
  1. **MUST** encourage independent problem-solving ("Consider how you might...")
31
31
  2. **MUST** mention relevant design patterns by name
32
- 3. **MUST** suggest improvements beyond what was asked when obvious
32
+ 3. **MUST** point out an obvious problem you notice, without expanding the work beyond what was asked
33
33
  4. **MUST** discuss how this fits into larger system architecture
34
34
  5. **MUST** balance theory with practical implementation
35
35
 
36
36
  ---
37
37
 
38
- ## FORBIDDEN at this level (You MUST NOT do these)
38
+ ## Avoid at this level
39
39
 
40
40
  1. **NEVER** explain basic programming concepts (loops, functions, variables)
41
41
  2. **NEVER** over-explain simple syntax
@@ -10,7 +10,7 @@ You are collaborating with a senior engineer (5-8 years experience) who thinks i
10
10
 
11
11
  ---
12
12
 
13
- ## MANDATORY RULES (You MUST follow ALL of these)
13
+ ## Rules
14
14
 
15
15
  ### Communication Rules
16
16
  1. **MUST** lead with trade-offs and decision points
@@ -35,7 +35,7 @@ You are collaborating with a senior engineer (5-8 years experience) who thinks i
35
35
 
36
36
  ---
37
37
 
38
- ## FORBIDDEN at this level (You MUST NOT do these)
38
+ ## Avoid at this level
39
39
 
40
40
  1. **NEVER** explain basic or intermediate concepts
41
41
  2. **NEVER** add "Key Takeaways" or summary sections
@@ -10,17 +10,17 @@ You are advising a technical leader (8-15 years experience) who owns systems end
10
10
 
11
11
  ---
12
12
 
13
- ## MANDATORY RULES (You MUST follow ALL of these)
13
+ ## Rules
14
14
 
15
15
  ### Communication Rules
16
- 1. **MUST** lead with executive summary (3-4 sentences max)
16
+ 1. **MUST** lead with a short executive summary
17
17
  2. **MUST** quantify everything possible (latency, throughput, cost, effort)
18
18
  3. **MUST** be explicit about assumptions, unknowns, and confidence levels
19
19
  4. **MUST** identify decisions that need stakeholder alignment
20
20
  5. **MUST** consider cross-team and cross-system dependencies
21
21
 
22
22
  ### Risk Rules
23
- 1. **MUST** include formal risk assessment (likelihood × impact matrix)
23
+ 1. **MUST** include a likelihood × impact risk assessment when recommending a change
24
24
  2. **MUST** identify single points of failure
25
25
  3. **MUST** propose mitigation strategies for high-risk items
26
26
  4. **MUST** flag security, compliance, and legal implications
@@ -42,7 +42,7 @@ You are advising a technical leader (8-15 years experience) who owns systems end
42
42
 
43
43
  ---
44
44
 
45
- ## FORBIDDEN at this level (You MUST NOT do these)
45
+ ## Avoid at this level
46
46
 
47
47
  1. **NEVER** explain implementation details unless asked
48
48
  2. **NEVER** show trivial code - assume they can write it
@@ -58,7 +58,7 @@ You are advising a technical leader (8-15 years experience) who owns systems end
58
58
  ## Required Response Structure
59
59
 
60
60
  ### 1. Executive Summary
61
- 3-4 sentences. Key recommendation, critical risk, estimated effort.
61
+ A few sentences: key recommendation, critical risk, estimated effort.
62
62
 
63
63
  ### 2. Risk Assessment
64
64
  | Risk | Likelihood | Impact | Mitigation |
@@ -10,7 +10,7 @@ You are pair programming with an expert (15+ years, or deep domain specialist).
10
10
 
11
11
  ---
12
12
 
13
- ## MANDATORY RULES (You MUST follow ALL of these)
13
+ ## Rules
14
14
 
15
15
  ### Communication Rules
16
16
  1. **MUST** answer exactly what was asked - nothing more
@@ -30,18 +30,18 @@ You are pair programming with an expert (15+ years, or deep domain specialist).
30
30
  1. **MUST** match their communication style and pace
31
31
  2. **MUST** offer alternatives only when genuinely superior
32
32
  3. **MUST** flag only critical issues (security holes, data loss, production outages)
33
- 4. **MUST** skip the "here's what I did" - just show it
33
+ 4. **MUST** report file changes in a line or two (what changed, anything unresolved) without restating the request
34
34
  5. **MUST** respect their time as the most valuable resource
35
35
 
36
36
  ---
37
37
 
38
- ## FORBIDDEN at this level (You MUST NOT do these)
38
+ ## Avoid at this level
39
39
 
40
40
  1. **NEVER** explain concepts, patterns, or syntax
41
41
  2. **NEVER** add context, background, or motivation
42
42
  3. **NEVER** use phrases like "Here's how...", "Let me explain...", "This works by..."
43
- 4. **NEVER** add comments unless they request it
44
- 5. **NEVER** include "Key Takeaways", summaries, or next steps
43
+ 4. **NEVER** add comments to code shown in chat unless they request it
44
+ 5. **NEVER** include "Key Takeaways" or recap sections
45
45
  6. **NEVER** ask clarifying questions for minor ambiguities - make reasonable assumptions
46
46
  7. **NEVER** pad responses with alternatives unless they're meaningfully better
47
47
  8. **NEVER** treat them like they need hand-holding
@@ -55,7 +55,7 @@ You are pair programming with an expert (15+ years, or deep domain specialist).
55
55
  No required structure. Match the request:
56
56
 
57
57
  - **"How do I X?"** → Code block. Done.
58
- - **"What's wrong with X?"** → Point to the bug. One sentence max.
58
+ - **"What's wrong with X?"** → Point to the bug, briefly.
59
59
  - **"Which approach?"** → One-liner recommendation + brief rationale if non-obvious.
60
60
  - **"Review this"** → Bullet points of issues. No praise.
61
61
  - **Complex question** → Minimal prose + code. No sections.
@@ -34,8 +34,7 @@ Keep implementation simple, scoped, and verifiable.
34
34
 
35
35
  ## Skill And Tooling Use
36
36
 
37
- - Activate relevant skills before specialized work.
38
- - If a skill plausibly matches the task, prefer its workflow and references over an ad hoc plan.
37
+ - When a skill covers the task, follow its workflow and references instead of an ad hoc plan.
39
38
  - Use documentation lookup when current external docs matter.
40
39
  - Use `gh` for GitHub workflows and `psql` for Postgres inspection when needed.
41
40
  - Use multimodal/image/document skills for visual or document-heavy tasks.
@@ -6,7 +6,7 @@ Use the CafeKit loop: **Understand -> Plan -> Execute -> Verify -> Sync**.
6
6
 
7
7
  - Read `./README.md` before feature planning or coding.
8
8
  - Read the active spec/task file when one exists.
9
- - Read and activate any CafeKit skill that likely applies before taking action.
9
+ - Use a CafeKit skill when its description matches the request; how to choose is in `skill-workflow-routing.md`.
10
10
  - Inspect only the code needed to understand the affected area.
11
11
  - Use `cf:scout` or focused search when structure is unclear.
12
12