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.
- package/.claude/skills/cc-act/CHANGELOG.md +5 -0
- package/.claude/skills/cc-act/SKILL.md +9 -2
- package/.claude/skills/cc-check/CHANGELOG.md +6 -0
- package/.claude/skills/cc-check/SKILL.md +9 -7
- package/.claude/skills/cc-dev/CHANGELOG.md +5 -0
- package/.claude/skills/cc-dev/SKILL.md +9 -2
- package/.claude/skills/cc-do/CHANGELOG.md +6 -0
- package/.claude/skills/cc-do/SKILL.md +16 -7
- package/.claude/skills/cc-investigate/CHANGELOG.md +7 -0
- package/.claude/skills/cc-investigate/PLAYBOOK.md +4 -4
- package/.claude/skills/cc-investigate/SKILL.md +160 -426
- package/.claude/skills/cc-investigate/assets/TASKS_TEMPLATE.md +8 -5
- package/.claude/skills/cc-investigate/assets/TASK_MANIFEST_TEMPLATE.json +3 -4
- package/.claude/skills/cc-investigate/references/investigation-contract.md +3 -2
- package/.claude/skills/cc-plan/CHANGELOG.md +13 -0
- package/.claude/skills/cc-plan/SKILL.md +197 -540
- package/.claude/skills/cc-plan/assets/TASKS_TEMPLATE.md +3 -0
- package/.claude/skills/cc-plan/assets/TASK_MANIFEST_TEMPLATE.json +2 -3
- package/.claude/skills/cc-plan/references/planning-contract.md +2 -1
- package/CHANGELOG.md +14 -0
- package/README.md +5 -3
- package/README.zh-CN.md +5 -3
- package/docs/examples/START-HERE.md +2 -1
- package/docs/examples/example-bindings.json +6 -6
- package/docs/examples/full-design-blocked/README.md +1 -1
- package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/planning/design.md +1 -1
- package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/planning/task-manifest.json +1 -1
- package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/planning/tasks.md +1 -1
- package/docs/examples/local-handoff/README.md +1 -1
- package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/planning/design.md +1 -1
- package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/planning/task-manifest.json +1 -1
- package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/planning/tasks.md +1 -1
- package/docs/examples/pdca-loop/README.md +1 -1
- package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/planning/design.md +1 -1
- package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/planning/task-manifest.json +1 -1
- package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/planning/tasks.md +1 -1
- package/docs/guides/artifact-contract.md +4 -0
- package/docs/guides/getting-started.md +4 -3
- package/docs/guides/getting-started.zh-CN.md +4 -3
- package/docs/guides/minimize-artifacts.md +19 -5
- package/lib/skill-runtime/__tests__/benchmark-skills.test.js +109 -0
- package/lib/skill-runtime/__tests__/task-contract.test.js +92 -1
- package/lib/skill-runtime/operations/task-contract.js +75 -6
- package/lib/skill-runtime/task-contract.js +2 -1
- 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
|
|
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 =
|
|
348
|
-
if (!contract
|
|
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
|
|
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.
|
|
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
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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",
|