cc-devflow 4.5.10 → 4.5.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.
Files changed (45) hide show
  1. package/.claude/skills/cc-act/CHANGELOG.md +5 -0
  2. package/.claude/skills/cc-act/SKILL.md +9 -2
  3. package/.claude/skills/cc-check/CHANGELOG.md +6 -0
  4. package/.claude/skills/cc-check/SKILL.md +9 -7
  5. package/.claude/skills/cc-dev/CHANGELOG.md +5 -0
  6. package/.claude/skills/cc-dev/SKILL.md +9 -2
  7. package/.claude/skills/cc-do/CHANGELOG.md +6 -0
  8. package/.claude/skills/cc-do/SKILL.md +16 -7
  9. package/.claude/skills/cc-investigate/CHANGELOG.md +7 -0
  10. package/.claude/skills/cc-investigate/PLAYBOOK.md +4 -4
  11. package/.claude/skills/cc-investigate/SKILL.md +160 -426
  12. package/.claude/skills/cc-investigate/assets/TASKS_TEMPLATE.md +8 -5
  13. package/.claude/skills/cc-investigate/assets/TASK_MANIFEST_TEMPLATE.json +3 -4
  14. package/.claude/skills/cc-investigate/references/investigation-contract.md +3 -2
  15. package/.claude/skills/cc-plan/CHANGELOG.md +13 -0
  16. package/.claude/skills/cc-plan/SKILL.md +197 -540
  17. package/.claude/skills/cc-plan/assets/TASKS_TEMPLATE.md +3 -0
  18. package/.claude/skills/cc-plan/assets/TASK_MANIFEST_TEMPLATE.json +2 -3
  19. package/.claude/skills/cc-plan/references/planning-contract.md +2 -1
  20. package/CHANGELOG.md +14 -0
  21. package/README.md +5 -3
  22. package/README.zh-CN.md +5 -3
  23. package/docs/examples/START-HERE.md +2 -1
  24. package/docs/examples/example-bindings.json +6 -6
  25. package/docs/examples/full-design-blocked/README.md +1 -1
  26. package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/planning/design.md +1 -1
  27. package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/planning/task-manifest.json +1 -1
  28. package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/planning/tasks.md +1 -1
  29. package/docs/examples/local-handoff/README.md +1 -1
  30. package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/planning/design.md +1 -1
  31. package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/planning/task-manifest.json +1 -1
  32. package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/planning/tasks.md +1 -1
  33. package/docs/examples/pdca-loop/README.md +1 -1
  34. package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/planning/design.md +1 -1
  35. package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/planning/task-manifest.json +1 -1
  36. package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/planning/tasks.md +1 -1
  37. package/docs/guides/artifact-contract.md +4 -0
  38. package/docs/guides/getting-started.md +4 -3
  39. package/docs/guides/getting-started.zh-CN.md +4 -3
  40. package/docs/guides/minimize-artifacts.md +19 -5
  41. package/lib/skill-runtime/__tests__/benchmark-skills.test.js +109 -0
  42. package/lib/skill-runtime/__tests__/task-contract.test.js +92 -1
  43. package/lib/skill-runtime/operations/task-contract.js +75 -6
  44. package/lib/skill-runtime/task-contract.js +2 -1
  45. package/package.json +8 -7
@@ -239,6 +239,12 @@ Repair Boundary:
239
239
  - Introduce in-flight map keyed by cache key; reject propagation errors to all awaiters.
240
240
  - Do not touch eviction policy or TTL logic.
241
241
 
242
+ Verification:
243
+
244
+ \`\`\`bash
245
+ npm test -- lib/cache/remote.test.js
246
+ \`\`\`
247
+
242
248
  Prevention:
243
249
  - Add a regression test that fires 50 parallel callers with an empty cache and asserts origin.fetch called once.
244
250
 
@@ -341,6 +347,11 @@ describe('extractTasksRootCauseContract', () => {
341
347
  ]);
342
348
  });
343
349
 
350
+ test('fields parses Verification as a fenced command block', () => {
351
+ const result = extractTasksRootCauseContract(FIX_SAMPLE_WITH_HEADING);
352
+ expect(result.fields.verification).toBe('npm test -- lib/cache/remote.test.js');
353
+ });
354
+
344
355
  test('fields parses Prevention as a bullet list', () => {
345
356
  const result = extractTasksRootCauseContract(FIX_SAMPLE_WITH_HEADING);
346
357
  expect(result.fields.prevention).toEqual([
@@ -564,6 +575,86 @@ describe('task-contract compile', () => {
564
575
  expect(changeMeta._meta.generatedBy).toBe('cc-devflow task-contract');
565
576
  });
566
577
 
578
+ test('compiles Root Cause Contract into generated manifest and change-meta', async () => {
579
+ const changeId = 'FIX-781';
580
+ const changeKey = 'FIX-781-compile-root-cause';
581
+ const changeDir = path.join(repoRoot, 'devflow', 'changes', changeKey);
582
+ const planningDir = path.join(changeDir, 'planning');
583
+ fs.mkdirSync(planningDir, { recursive: true });
584
+ fs.writeFileSync(
585
+ path.join(planningDir, 'tasks.md'),
586
+ [
587
+ '# TASKS',
588
+ '',
589
+ '## Root Cause Contract',
590
+ '',
591
+ 'Change: FIX-781-compile-root-cause',
592
+ 'Mode: investigation',
593
+ 'Profile: standard',
594
+ 'Diagnosis: confirmed',
595
+ '',
596
+ 'Symptom:',
597
+ '- Task-contract compile rejects bug investigations.',
598
+ '',
599
+ 'Reproduction:',
600
+ '- Run compile against a Root Cause Contract-only tasks.md.',
601
+ '',
602
+ 'Expected:',
603
+ '- CLI owns task-manifest.json and change-meta.json.',
604
+ '',
605
+ 'Actual:',
606
+ '- Compile required Contract Summary.',
607
+ '',
608
+ 'Root Cause:',
609
+ '- The compile path reused only the planning contract parser.',
610
+ '',
611
+ 'Evidence Chain:',
612
+ '- validate already accepts Root Cause Contract.',
613
+ '',
614
+ 'Repair Boundary:',
615
+ '- Accept Root Cause Contract as the human-authored source.',
616
+ '',
617
+ 'Verification:',
618
+ '',
619
+ '```bash',
620
+ 'npm test -- lib/skill-runtime/__tests__/task-contract.test.js',
621
+ '```',
622
+ '',
623
+ 'Prevention:',
624
+ '- Keep generated machine records behind task-contract compile.',
625
+ '',
626
+ 'Risk / Escalate If:',
627
+ '- Generated metadata loses the root-cause source.',
628
+ '',
629
+ '## Phase 1: Compile',
630
+ '',
631
+ '- [ ] T001 compile root-cause metadata',
632
+ ' Goal: Generate machine artifacts from the root-cause contract.',
633
+ ' Files: `lib/skill-runtime/operations/task-contract.js`',
634
+ ' Verification: npm test -- lib/skill-runtime/__tests__/task-contract.test.js',
635
+ ' Evidence: generated metadata assertions',
636
+ ''
637
+ ].join('\n')
638
+ );
639
+
640
+ const result = await runCompile({ repoRoot, changeId, changeKey });
641
+ const manifest = JSON.parse(fs.readFileSync(path.join(planningDir, 'task-manifest.json'), 'utf8'));
642
+ const changeMeta = JSON.parse(fs.readFileSync(path.join(changeDir, 'change-meta.json'), 'utf8'));
643
+
644
+ expect(result.code).toBe(0);
645
+ expect(manifest.goal).toBe('The compile path reused only the planning contract parser.');
646
+ expect(manifest.metadata.generatedBy).toBe('cc-devflow task-contract');
647
+ expect(changeMeta.specReference.source).toBe('planning/tasks.md#root-cause-contract');
648
+ expect(changeMeta.rootCause.confirmed).toEqual([
649
+ 'The compile path reused only the planning contract parser.'
650
+ ]);
651
+ expect(changeMeta.acceptance).toEqual([
652
+ 'Accept Root Cause Contract as the human-authored source.',
653
+ 'npm test -- lib/skill-runtime/__tests__/task-contract.test.js'
654
+ ]);
655
+ expect(changeMeta._meta.generatedBy).toBe('cc-devflow task-contract');
656
+ });
657
+
567
658
  test('returns exit code 3 when Contract Summary is missing', async () => {
568
659
  const changeId = 'REQ-781';
569
660
  const changeKey = 'REQ-781-missing-contract-summary';
@@ -589,7 +680,7 @@ describe('task-contract compile', () => {
589
680
  const result = await runCompile({ repoRoot, changeId, changeKey });
590
681
 
591
682
  expect(result.code).toBe(3);
592
- expect(result.error).toMatch(/Missing ## Contract Summary/);
683
+ expect(result.error).toMatch(/Missing ## Contract Summary or ## Root Cause Contract/);
593
684
  expect(fs.existsSync(path.join(changeDir, 'change-meta.json'))).toBe(false);
594
685
  });
595
686
  });
@@ -37,7 +37,7 @@ function listField(value) {
37
37
  return value ? [value] : [];
38
38
  }
39
39
 
40
- function buildChangeMeta(change, fields) {
40
+ function buildSummaryChangeMeta(change, fields) {
41
41
  const contractChange = fields.change || change.changeKey;
42
42
  return {
43
43
  changeId: contractChange,
@@ -58,6 +58,75 @@ function buildChangeMeta(change, fields) {
58
58
  };
59
59
  }
60
60
 
61
+ function buildRootCauseChangeMeta(change, fields) {
62
+ const contractChange = fields.change || change.changeKey;
63
+ return {
64
+ changeId: contractChange,
65
+ requirementId: contractChange,
66
+ goal: listField(fields.rootCause || fields.symptom || `Repair confirmed root cause for ${contractChange}`),
67
+ acceptance: [
68
+ ...listField(fields.repairBoundary),
69
+ ...listField(fields.verification)
70
+ ],
71
+ specReference: {
72
+ source: 'planning/tasks.md#root-cause-contract',
73
+ change: contractChange,
74
+ mode: fields.mode || 'investigation',
75
+ profile: fields.profile || '',
76
+ approval: fields.diagnosis || ''
77
+ },
78
+ rootCause: {
79
+ diagnosis: fields.diagnosis || '',
80
+ symptom: listField(fields.symptom),
81
+ reproduction: listField(fields.reproduction),
82
+ confirmed: listField(fields.rootCause),
83
+ repairBoundary: listField(fields.repairBoundary),
84
+ prevention: listField(fields.prevention)
85
+ },
86
+ _meta: {
87
+ generatedBy: GENERATED_BY,
88
+ generatedAt: new Date().toISOString()
89
+ }
90
+ };
91
+ }
92
+
93
+ function extractCompileContract(tasksText) {
94
+ const summary = extractTasksContractSummary(tasksText);
95
+ if (summary.found) {
96
+ return {
97
+ type: 'summary',
98
+ source: 'planning/tasks.md#contract-summary',
99
+ fields: summary.fields
100
+ };
101
+ }
102
+
103
+ const rootCause = extractTasksRootCauseContract(tasksText);
104
+ if (rootCause.found) {
105
+ return {
106
+ type: 'root-cause',
107
+ source: 'planning/tasks.md#root-cause-contract',
108
+ fields: rootCause.fields
109
+ };
110
+ }
111
+
112
+ return null;
113
+ }
114
+
115
+ function buildChangeMeta(change, contract) {
116
+ if (contract.type === 'root-cause') {
117
+ return buildRootCauseChangeMeta(change, contract.fields);
118
+ }
119
+ return buildSummaryChangeMeta(change, contract.fields);
120
+ }
121
+
122
+ function summarizeContractGoal(contract) {
123
+ const fields = contract.fields || {};
124
+ if (contract.type === 'root-cause') {
125
+ return listField(fields.rootCause)[0] || listField(fields.symptom)[0] || '';
126
+ }
127
+ return listField(fields.goal)[0] || '';
128
+ }
129
+
61
130
  async function relativeExists(change, relativePath) {
62
131
  return exists(path.join(change.changeDir, relativePath));
63
132
  }
@@ -344,13 +413,13 @@ async function runCompile({
344
413
  };
345
414
  }
346
415
 
347
- const contract = extractTasksContractSummary(await readText(tasksPath));
348
- if (!contract.found) {
416
+ const contract = extractCompileContract(await readText(tasksPath));
417
+ if (!contract) {
349
418
  return {
350
419
  code: 3,
351
420
  changeId,
352
421
  changeKey: change.changeKey,
353
- error: `Missing ## Contract Summary in planning/tasks.md: ${tasksPath}`
422
+ error: `Missing ## Contract Summary or ## Root Cause Contract in planning/tasks.md: ${tasksPath}`
354
423
  };
355
424
  }
356
425
 
@@ -358,7 +427,7 @@ async function runCompile({
358
427
  repoRoot,
359
428
  changeId,
360
429
  changeKey: change.changeKey,
361
- goal,
430
+ goal: goal || summarizeContractGoal(contract),
362
431
  overwrite
363
432
  });
364
433
 
@@ -375,7 +444,7 @@ async function runCompile({
375
444
  };
376
445
 
377
446
  await writeJson(manifestPath, compiled);
378
- await writeJson(changeMetaPath, buildChangeMeta(change, contract.fields));
447
+ await writeJson(changeMetaPath, buildChangeMeta(change, contract));
379
448
 
380
449
  return {
381
450
  code: 0,
@@ -38,6 +38,7 @@ const ROOT_CAUSE_FIELD_MAP = {
38
38
  'Root Cause': 'rootCause',
39
39
  'Evidence Chain': 'evidenceChain',
40
40
  'Repair Boundary': 'repairBoundary',
41
+ 'Verification': 'verification',
41
42
  'Prevention': 'prevention',
42
43
  'Risk / Escalate If': 'risk'
43
44
  };
@@ -54,7 +55,7 @@ const ROOT_CAUSE_LIST = new Set([
54
55
  'prevention',
55
56
  'risk'
56
57
  ]);
57
- const ROOT_CAUSE_VERIFICATION = new Set();
58
+ const ROOT_CAUSE_VERIFICATION = new Set(['verification']);
58
59
 
59
60
  // ============================================================================
60
61
  // Heading block extraction (shared engine)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cc-devflow",
3
- "version": "4.5.10",
3
+ "version": "4.5.11",
4
4
  "description": "Multi-platform CLI and skill pack for agent coding",
5
5
  "main": "bin/cc-devflow.js",
6
6
  "bin": {
@@ -44,12 +44,13 @@
44
44
  "scripts": {
45
45
  "prepublishOnly": "node scripts/validate-publish.js",
46
46
  "test": "jest",
47
- "verify": "npm test && npm run verify:examples && npm run verify:artifacts",
48
- "verify:examples": "bash docs/examples/scripts/check-example-bindings.sh",
49
- "verify:artifacts": "node scripts/verify-artifacts.js",
50
- "verify:publish": "node scripts/validate-publish.js",
51
- "benchmark:artifacts": "node scripts/benchmark-artifacts.js",
52
- "benchmark:workflow-context": "node scripts/benchmark-workflow-context-tokens.js",
47
+ "verify": "npm test && npm run verify:examples && npm run verify:artifacts && npm run benchmark:skills",
48
+ "verify:examples": "bash docs/examples/scripts/check-example-bindings.sh",
49
+ "verify:artifacts": "node scripts/verify-artifacts.js",
50
+ "verify:publish": "node scripts/validate-publish.js",
51
+ "benchmark:artifacts": "node scripts/benchmark-artifacts.js",
52
+ "benchmark:skills": "node scripts/benchmark-skills.js",
53
+ "benchmark:workflow-context": "node scripts/benchmark-workflow-context-tokens.js",
53
54
  "start": "node bin/cc-devflow.js",
54
55
  "adapt": "node bin/adapt.js",
55
56
  "adapt:check": "node bin/adapt.js --check",