cc-devflow 4.5.11 → 4.5.12
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 +18 -0
- package/.claude/skills/cc-act/PLAYBOOK.md +17 -269
- package/.claude/skills/cc-act/SKILL.md +38 -425
- package/.claude/skills/cc-act/assets/PROJECT_POSTMORTEM_INDEX_TEMPLATE.md +2 -13
- package/.claude/skills/cc-act/assets/PROJECT_POSTMORTEM_TEMPLATE.md +1 -9
- package/.claude/skills/cc-act/assets/PR_BRIEF_TEMPLATE.md +21 -177
- package/.claude/skills/cc-act/references/closure-contract.md +12 -63
- package/.claude/skills/cc-act/references/git-commit-guidelines.md +5 -5
- package/.claude/skills/cc-act/scripts/cc-act-common.sh +5 -322
- package/.claude/skills/cc-act/scripts/detect-ship-target.sh +11 -2
- package/.claude/skills/cc-act/scripts/inspect-git-index.sh +58 -0
- package/.claude/skills/cc-act/scripts/render-pr-brief.sh +40 -440
- package/.claude/skills/cc-act/scripts/verify-act-gate.sh +10 -50
- package/.claude/skills/cc-check/CHANGELOG.md +18 -0
- package/.claude/skills/cc-check/PLAYBOOK.md +19 -273
- package/.claude/skills/cc-check/SKILL.md +33 -456
- package/.claude/skills/cc-check/references/review-contract.md +12 -147
- package/.claude/skills/cc-dev/CHANGELOG.md +15 -0
- package/.claude/skills/cc-dev/PLAYBOOK.md +1 -1
- package/.claude/skills/cc-dev/SKILL.md +52 -137
- package/.claude/skills/cc-dev/scripts/resolve-cc-devflow.sh +181 -0
- package/.claude/skills/cc-do/CHANGELOG.md +11 -0
- package/.claude/skills/cc-do/PLAYBOOK.md +19 -113
- package/.claude/skills/cc-do/SKILL.md +39 -245
- package/.claude/skills/cc-do/references/execution-recovery.md +15 -109
- package/.claude/skills/cc-do/scripts/cc-do-common.sh +5 -57
- package/.claude/skills/cc-do/scripts/check-task-status.sh +35 -65
- package/.claude/skills/cc-do/scripts/mark-task-complete.sh +9 -46
- package/.claude/skills/cc-do/scripts/select-ready-tasks.sh +29 -97
- package/.claude/skills/cc-investigate/CHANGELOG.md +16 -0
- package/.claude/skills/cc-investigate/PLAYBOOK.md +20 -180
- package/.claude/skills/cc-investigate/SKILL.md +64 -246
- package/.claude/skills/cc-investigate/assets/TASKS_TEMPLATE.md +48 -98
- package/.claude/skills/cc-investigate/references/investigation-contract.md +14 -218
- package/.claude/skills/cc-next/CHANGELOG.md +6 -0
- package/.claude/skills/cc-next/PLAYBOOK.md +12 -8
- package/.claude/skills/cc-next/SKILL.md +34 -140
- package/.claude/skills/cc-plan/CHANGELOG.md +16 -0
- package/.claude/skills/cc-plan/PLAYBOOK.md +22 -161
- package/.claude/skills/cc-plan/SKILL.md +45 -295
- package/.claude/skills/cc-plan/assets/TASKS_TEMPLATE.md +30 -228
- package/.claude/skills/cc-plan/references/planning-contract.md +24 -161
- package/.claude/skills/cc-plan/scripts/next-change-key.sh +8 -44
- package/.claude/skills/cc-plan/scripts/parse-task-dependencies.js +2 -2
- package/.claude/skills/cc-plan/scripts/validate-scope.sh +1 -1
- package/.claude/skills/cc-pr-land/SKILL.md +14 -114
- package/.claude/skills/cc-pr-review/CHANGELOG.md +4 -0
- package/.claude/skills/cc-pr-review/SKILL.md +20 -103
- package/.claude/skills/cc-review/CHANGELOG.md +17 -0
- package/.claude/skills/cc-review/PLAYBOOK.md +13 -86
- package/.claude/skills/cc-review/SKILL.md +53 -241
- package/.claude/skills/cc-review/references/e2e-and-plugin-verification.md +2 -2
- package/.claude/skills/cc-review/references/implementation-review-branch.md +7 -147
- package/.claude/skills/cc-review/references/plan-review-branch.md +5 -147
- package/.claude/skills/cc-review/references/review-methods.md +10 -218
- package/.claude/skills/cc-review/scripts/collect-review-context.sh +4 -63
- package/.claude/skills/cc-roadmap/PLAYBOOK.md +1 -1
- package/.claude/skills/cc-roadmap/SKILL.md +3 -3
- package/.claude/skills/cc-simplify/CHANGELOG.md +7 -0
- package/.claude/skills/cc-simplify/SKILL.md +26 -21
- package/.claude/skills/cc-spec-init/PLAYBOOK.md +12 -48
- package/.claude/skills/cc-spec-init/SKILL.md +29 -132
- package/.claude/skills/cc-spec-init/references/spec-contract.md +8 -17
- package/CHANGELOG.md +13 -0
- package/bin/cc-devflow-cli.js +20 -260
- package/bin/cc-devflow.js +44 -7
- package/docs/commands/README.md +1 -1
- package/docs/commands/README.zh-CN.md +1 -1
- package/docs/examples/README.md +1 -1
- package/docs/examples/START-HERE.md +14 -15
- package/docs/examples/example-bindings.json +11 -11
- package/docs/examples/full-design-blocked/README.md +4 -6
- package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/{planning/tasks.md → task.md} +20 -15
- package/docs/examples/local-handoff/README.md +8 -11
- package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/handoff/pr-brief.md +31 -0
- package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/{planning/tasks.md → task.md} +18 -13
- package/docs/examples/pdca-loop/README.md +6 -9
- package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/handoff/pr-brief.md +9 -11
- package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/{planning/tasks.md → task.md} +18 -13
- package/docs/examples/scripts/check-example-bindings.sh +11 -62
- package/docs/guides/artifact-contract.md +10 -40
- package/docs/guides/getting-started.md +8 -8
- package/docs/guides/getting-started.zh-CN.md +8 -8
- package/docs/guides/minimize-artifacts.md +16 -130
- package/docs/guides/project-postmortem.md +14 -71
- package/lib/compiler/__tests__/skills-registry.test.js +9 -8
- package/lib/compiler/resource-copier.js +29 -0
- package/lib/skill-runtime/__tests__/archive-change.test.js +2 -2
- package/lib/skill-runtime/__tests__/benchmark-skills.test.js +3 -3
- package/lib/skill-runtime/__tests__/cli-bootstrap.integration.test.js +14 -4
- package/lib/skill-runtime/errors.js +3 -3
- package/lib/skill-runtime/index.js +5 -23
- package/lib/skill-runtime/paths.js +5 -52
- package/lib/skill-runtime/query-registry.js +4 -4
- package/lib/skill-runtime/query.js +89 -201
- package/lib/skill-runtime/store.js +4 -40
- package/lib/skill-runtime/trace.js +2 -2
- package/package.json +2 -5
- package/.claude/skills/cc-act/assets/PROJECT_POSTMORTEM_PRINCIPLES_TEMPLATE.md +0 -29
- package/.claude/skills/cc-act/assets/RELEASE_NOTE_TEMPLATE.md +0 -54
- package/.claude/skills/cc-act/scripts/generate-status-report.sh +0 -92
- package/.claude/skills/cc-act/scripts/sync-act-docs.sh +0 -355
- package/.claude/skills/cc-check/assets/REPORT_CARD_TEMPLATE.json +0 -234
- package/.claude/skills/cc-check/scripts/render-report-card.js +0 -438
- package/.claude/skills/cc-check/scripts/verify-gate.sh +0 -85
- package/.claude/skills/cc-do/scripts/build-task-context.sh +0 -175
- package/.claude/skills/cc-do/scripts/record-review-decision.sh +0 -88
- package/.claude/skills/cc-do/scripts/recover-workflow.sh +0 -82
- package/.claude/skills/cc-do/scripts/run-problem-analysis.sh +0 -70
- package/.claude/skills/cc-do/scripts/verify-task-gates.sh +0 -109
- package/.claude/skills/cc-do/scripts/write-task-checkpoint.sh +0 -92
- package/.claude/skills/cc-investigate/assets/TASK_MANIFEST_TEMPLATE.json +0 -224
- package/.claude/skills/cc-plan/assets/TASK_MANIFEST_TEMPLATE.json +0 -178
- package/.claude/skills/cc-spec-init/assets/CHANGE_META_TEMPLATE.json +0 -28
- package/.claude/skills/cc-spec-init/scripts/validate-spec-links.sh +0 -45
- package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/planning/design.md +0 -234
- package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/planning/task-manifest.json +0 -488
- package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/review/report-card.json +0 -189
- package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/handoff/resume-index.md +0 -39
- package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/handoff/status.md +0 -29
- package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/planning/design.md +0 -123
- package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/planning/task-manifest.json +0 -292
- package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/review/report-card.json +0 -136
- package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/handoff/status.md +0 -29
- package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/planning/design.md +0 -124
- package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/planning/task-manifest.json +0 -292
- package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/review/report-card.json +0 -136
- package/docs/get-shit-done-strategy-audit.md +0 -518
- package/docs/skill-runtime-migration.md +0 -46
- package/lib/skill-runtime/__tests__/approve.test.js +0 -92
- package/lib/skill-runtime/__tests__/autopilot.test.js +0 -253
- package/lib/skill-runtime/__tests__/benchmark-artifacts.test.js +0 -165
- package/lib/skill-runtime/__tests__/delegation.test.js +0 -97
- package/lib/skill-runtime/__tests__/dispatch.test.js +0 -237
- package/lib/skill-runtime/__tests__/intent.test.js +0 -203
- package/lib/skill-runtime/__tests__/lifecycle.test.js +0 -169
- package/lib/skill-runtime/__tests__/planner.tdd.test.js +0 -331
- package/lib/skill-runtime/__tests__/prepare-pr.test.js +0 -126
- package/lib/skill-runtime/__tests__/query.test.js +0 -860
- package/lib/skill-runtime/__tests__/readiness.test.js +0 -53
- package/lib/skill-runtime/__tests__/release.test.js +0 -85
- package/lib/skill-runtime/__tests__/review-check-integration.test.js +0 -148
- package/lib/skill-runtime/__tests__/review-records.test.js +0 -619
- package/lib/skill-runtime/__tests__/runtime.integration.test.js +0 -351
- package/lib/skill-runtime/__tests__/schemas.test.js +0 -337
- package/lib/skill-runtime/__tests__/task-contract-migrate.test.js +0 -137
- package/lib/skill-runtime/__tests__/task-contract.test.js +0 -874
- package/lib/skill-runtime/__tests__/team-state.test.js +0 -51
- package/lib/skill-runtime/__tests__/verify-artifacts.test.js +0 -203
- package/lib/skill-runtime/__tests__/worker-run.test.js +0 -275
- package/lib/skill-runtime/__tests__/worker.test.js +0 -56
- package/lib/skill-runtime/__tests__/workflow-context-legacy-fallback.test.js +0 -31
- package/lib/skill-runtime/__tests__/workflow-context.test.js +0 -98
- package/lib/skill-runtime/artifacts.js +0 -88
- package/lib/skill-runtime/context-index.js +0 -545
- package/lib/skill-runtime/delegation.js +0 -533
- package/lib/skill-runtime/intent.js +0 -309
- package/lib/skill-runtime/lifecycle.js +0 -294
- package/lib/skill-runtime/operations/CLAUDE.md +0 -19
- package/lib/skill-runtime/operations/approve.js +0 -81
- package/lib/skill-runtime/operations/autopilot-core.js +0 -337
- package/lib/skill-runtime/operations/autopilot-execution.js +0 -307
- package/lib/skill-runtime/operations/autopilot-shared.js +0 -48
- package/lib/skill-runtime/operations/autopilot.js +0 -163
- package/lib/skill-runtime/operations/dispatch.js +0 -416
- package/lib/skill-runtime/operations/init.js +0 -60
- package/lib/skill-runtime/operations/janitor.js +0 -61
- package/lib/skill-runtime/operations/plan.js +0 -59
- package/lib/skill-runtime/operations/prepare-pr.js +0 -25
- package/lib/skill-runtime/operations/release.js +0 -99
- package/lib/skill-runtime/operations/resume.js +0 -126
- package/lib/skill-runtime/operations/review-records.js +0 -265
- package/lib/skill-runtime/operations/snapshot.js +0 -45
- package/lib/skill-runtime/operations/task-contract.js +0 -593
- package/lib/skill-runtime/operations/verify.js +0 -170
- package/lib/skill-runtime/operations/worker-run.js +0 -531
- package/lib/skill-runtime/operations/worker.js +0 -33
- package/lib/skill-runtime/planner.js +0 -539
- package/lib/skill-runtime/readiness.js +0 -84
- package/lib/skill-runtime/review-records.js +0 -123
- package/lib/skill-runtime/review.js +0 -855
- package/lib/skill-runtime/schemas.js +0 -746
- package/lib/skill-runtime/task-contract.js +0 -188
- package/lib/skill-runtime/team-state.js +0 -122
- package/lib/skill-runtime/workflow-context.js +0 -748
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* [INPUT]: 依赖 planner.createTaskManifest,接收 changeId/goal/overwrite 参数。
|
|
3
|
-
* [OUTPUT]: 生成并返回已校验的 task-manifest.json 摘要。
|
|
4
|
-
* [POS]: skill runtime Stage-3 计划生成入口,供内部规划链路复用。
|
|
5
|
-
* [PROTOCOL]: 变更时更新此头部,然后检查 CLAUDE.md
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
const { createTaskManifest } = require('../planner');
|
|
9
|
-
const { getIntentHandoffArtifactPaths } = require('../artifacts');
|
|
10
|
-
const {
|
|
11
|
-
getTaskManifestPath,
|
|
12
|
-
getRuntimeStatePath,
|
|
13
|
-
getReportCardPath,
|
|
14
|
-
exists,
|
|
15
|
-
readJson,
|
|
16
|
-
writeJson,
|
|
17
|
-
removePath
|
|
18
|
-
} = require('../store');
|
|
19
|
-
|
|
20
|
-
async function runPlan({ repoRoot, changeId, goal, overwrite }) {
|
|
21
|
-
const manifest = await createTaskManifest({
|
|
22
|
-
repoRoot,
|
|
23
|
-
changeId,
|
|
24
|
-
goal,
|
|
25
|
-
overwrite
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
// Update change-state.json with plannedAt timestamp
|
|
29
|
-
const statePath = getRuntimeStatePath(repoRoot, changeId);
|
|
30
|
-
if (await exists(statePath)) {
|
|
31
|
-
const state = await readJson(statePath);
|
|
32
|
-
state.status = 'planned';
|
|
33
|
-
state.plannedAt = new Date().toISOString();
|
|
34
|
-
state.approval = {
|
|
35
|
-
status: 'pending',
|
|
36
|
-
executionMode: state.approval?.executionMode || 'delegate'
|
|
37
|
-
};
|
|
38
|
-
delete state.verifiedAt;
|
|
39
|
-
delete state.releasedAt;
|
|
40
|
-
state.updatedAt = new Date().toISOString();
|
|
41
|
-
await writeJson(statePath, state);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
await Promise.all([
|
|
45
|
-
removePath(getReportCardPath(repoRoot, changeId)),
|
|
46
|
-
...getIntentHandoffArtifactPaths(repoRoot, changeId).map((target) => removePath(target))
|
|
47
|
-
]);
|
|
48
|
-
|
|
49
|
-
return {
|
|
50
|
-
changeId,
|
|
51
|
-
manifestPath: getTaskManifestPath(repoRoot, changeId),
|
|
52
|
-
taskCount: manifest.tasks.length,
|
|
53
|
-
source: manifest.metadata.source
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
module.exports = {
|
|
58
|
-
runPlan
|
|
59
|
-
};
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* [INPUT]: 依赖 intent 的 PR brief 生成能力,接收 repoRoot 与 changeId。
|
|
3
|
-
* [OUTPUT]: 生成 `devflow/changes/<goal>/handoff/pr-brief.md`,并清理冲突 handoff 文件。
|
|
4
|
-
* [POS]: skill runtime 的 PR-ready 收尾入口,被 autopilot 与内部收尾链路复用。
|
|
5
|
-
* [PROTOCOL]: 变更时更新此头部,然后检查 CLAUDE.md
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
const { getIntentPrBriefPath } = require('../artifacts');
|
|
9
|
-
const { syncIntentMemory, syncIntentPrBrief } = require('../intent');
|
|
10
|
-
|
|
11
|
-
async function runPreparePr({ repoRoot, changeId }) {
|
|
12
|
-
const prepared = await syncIntentPrBrief(repoRoot, changeId);
|
|
13
|
-
await syncIntentMemory(repoRoot, changeId);
|
|
14
|
-
|
|
15
|
-
return {
|
|
16
|
-
changeId,
|
|
17
|
-
prBriefPath: prepared.prBriefPath || getIntentPrBriefPath(repoRoot, changeId),
|
|
18
|
-
suggestedTitle: prepared.suggestedTitle,
|
|
19
|
-
status: 'prepared'
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
module.exports = {
|
|
24
|
-
runPreparePr
|
|
25
|
-
};
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* [INPUT]: 依赖 report-card 与 task-manifest 的最终状态。
|
|
3
|
-
* [OUTPUT]: 在 handoff 目录生成 release-note.md,并更新 change-state 为 released。
|
|
4
|
-
* [POS]: skill runtime 发布收尾入口,供内部收尾链路复用。
|
|
5
|
-
* [PROTOCOL]: 变更时更新此头部,然后检查 CLAUDE.md
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
const {
|
|
9
|
-
nowIso,
|
|
10
|
-
readJson,
|
|
11
|
-
writeText,
|
|
12
|
-
writeJson,
|
|
13
|
-
getReportCardPath,
|
|
14
|
-
getTaskManifestPath,
|
|
15
|
-
getReleaseNotePath,
|
|
16
|
-
getRuntimeStatePath
|
|
17
|
-
} = require('../store');
|
|
18
|
-
const { parseReportCard, parseManifest } = require('../schemas');
|
|
19
|
-
const { syncIntentMemory } = require('../intent');
|
|
20
|
-
const { assertShipReady } = require('../readiness');
|
|
21
|
-
|
|
22
|
-
function formatReleaseNote({ changeId, manifest, report }) {
|
|
23
|
-
const passedTasks = manifest.tasks.filter((task) => task.status === 'passed');
|
|
24
|
-
const failedTasks = manifest.tasks.filter((task) => task.status === 'failed');
|
|
25
|
-
|
|
26
|
-
return [
|
|
27
|
-
`# Release Note - ${changeId}`,
|
|
28
|
-
'',
|
|
29
|
-
`- Released At: ${nowIso()}`,
|
|
30
|
-
`- Verdict: ${(report.verdict || report.overall).toUpperCase()}`,
|
|
31
|
-
`- Verification: ${report.overall.toUpperCase()}`,
|
|
32
|
-
`- Review: ${(report.review?.status || 'skipped').toUpperCase()}`,
|
|
33
|
-
'',
|
|
34
|
-
'## Task Summary',
|
|
35
|
-
'',
|
|
36
|
-
`- Passed: ${passedTasks.length}`,
|
|
37
|
-
`- Failed: ${failedTasks.length}`,
|
|
38
|
-
'',
|
|
39
|
-
'## Completed Tasks',
|
|
40
|
-
'',
|
|
41
|
-
...(passedTasks.length > 0
|
|
42
|
-
? passedTasks.map((task) => `- ${task.id}: ${task.title}`)
|
|
43
|
-
: ['- (none)']),
|
|
44
|
-
'',
|
|
45
|
-
'## Blocking Findings',
|
|
46
|
-
'',
|
|
47
|
-
...(report.blockingFindings.length > 0
|
|
48
|
-
? report.blockingFindings.map((item) => `- ${item}`)
|
|
49
|
-
: ['- None']),
|
|
50
|
-
''
|
|
51
|
-
].join('\n');
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
async function runRelease({ repoRoot, changeId }) {
|
|
55
|
-
const reportPath = getReportCardPath(repoRoot, changeId);
|
|
56
|
-
const manifestPath = getTaskManifestPath(repoRoot, changeId);
|
|
57
|
-
const statePath = getRuntimeStatePath(repoRoot, changeId);
|
|
58
|
-
|
|
59
|
-
const report = parseReportCard(await readJson(reportPath));
|
|
60
|
-
const manifest = parseManifest(await readJson(manifestPath));
|
|
61
|
-
const previousState = await readJson(statePath, null);
|
|
62
|
-
|
|
63
|
-
assertShipReady(report, {
|
|
64
|
-
reportPath,
|
|
65
|
-
errorName: 'ReleaseReadinessError',
|
|
66
|
-
rescueAction: 'run cc-check until ship-readiness is ready before release'
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
const note = formatReleaseNote({ changeId, manifest, report });
|
|
70
|
-
const releaseNotePath = getReleaseNotePath(repoRoot, changeId);
|
|
71
|
-
|
|
72
|
-
await writeText(releaseNotePath, note);
|
|
73
|
-
await writeJson(statePath, {
|
|
74
|
-
...(previousState || {}),
|
|
75
|
-
changeId,
|
|
76
|
-
changeKey: previousState?.changeKey,
|
|
77
|
-
slug: previousState?.slug,
|
|
78
|
-
createdAt: previousState?.createdAt,
|
|
79
|
-
goal: manifest.goal || previousState?.goal,
|
|
80
|
-
status: 'released',
|
|
81
|
-
initializedAt: previousState?.initializedAt || nowIso(),
|
|
82
|
-
plannedAt: previousState?.plannedAt,
|
|
83
|
-
verifiedAt: previousState?.verifiedAt,
|
|
84
|
-
approval: previousState?.approval,
|
|
85
|
-
releasedAt: nowIso(),
|
|
86
|
-
updatedAt: nowIso()
|
|
87
|
-
});
|
|
88
|
-
await syncIntentMemory(repoRoot, changeId);
|
|
89
|
-
|
|
90
|
-
return {
|
|
91
|
-
changeId,
|
|
92
|
-
releaseNotePath,
|
|
93
|
-
status: 'released'
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
module.exports = {
|
|
98
|
-
runRelease
|
|
99
|
-
};
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* [INPUT]: 依赖 manifest 当前状态与 dispatch 执行器,接收 changeId/并行度/重试参数。
|
|
3
|
-
* [OUTPUT]: 将失败执行恢复到最近已通过的 manifest 任务边界,把未稳定任务重新排队后继续执行。
|
|
4
|
-
* [POS]: skill runtime 恢复执行入口,供内部恢复链路复用。
|
|
5
|
-
* [PROTOCOL]: 变更时更新此头部,然后检查 CLAUDE.md
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
const {
|
|
9
|
-
readJson,
|
|
10
|
-
writeJson,
|
|
11
|
-
getTaskManifestPath,
|
|
12
|
-
getRuntimeStatePath
|
|
13
|
-
} = require('../store');
|
|
14
|
-
const { parseManifest } = require('../schemas');
|
|
15
|
-
const { applyManifestExecutionState } = require('../planner');
|
|
16
|
-
const { runDispatch } = require('./dispatch');
|
|
17
|
-
const { syncIntentMemory } = require('../intent');
|
|
18
|
-
const { getApprovalState, isExecutionApproved } = require('../lifecycle');
|
|
19
|
-
|
|
20
|
-
async function resolveStableManifestPoint(manifest) {
|
|
21
|
-
const passedTasks = manifest.tasks
|
|
22
|
-
.filter((task) => task.status === 'passed')
|
|
23
|
-
.map((task) => ({
|
|
24
|
-
taskId: task.id,
|
|
25
|
-
status: task.status,
|
|
26
|
-
title: task.title || '',
|
|
27
|
-
planVersion: manifest.metadata?.planVersion || 1
|
|
28
|
-
}));
|
|
29
|
-
|
|
30
|
-
return passedTasks[passedTasks.length - 1] || null;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function restoreTaskToPending(task, restoreLabel) {
|
|
34
|
-
const previousError = task.lastError ? ` Previous error: ${task.lastError}` : '';
|
|
35
|
-
task.status = 'pending';
|
|
36
|
-
task.attempts = 0;
|
|
37
|
-
task.lastError = `Restored from ${restoreLabel}.${previousError}`.trim();
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function requeueFromStableManifestPoint(manifest, restoreTarget) {
|
|
41
|
-
const restoreLabel = restoreTarget ? `stable manifest task ${restoreTarget.taskId}` : 'execution start';
|
|
42
|
-
const restoredTaskIds = [];
|
|
43
|
-
|
|
44
|
-
for (const task of manifest.tasks) {
|
|
45
|
-
if (task.status === 'running' || task.status === 'failed') {
|
|
46
|
-
restoreTaskToPending(task, restoreLabel);
|
|
47
|
-
restoredTaskIds.push(task.id);
|
|
48
|
-
continue;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
if (task.status === 'skipped' && task.lastError === 'Blocked by failed dependency') {
|
|
52
|
-
restoreTaskToPending(task, restoreLabel);
|
|
53
|
-
restoredTaskIds.push(task.id);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return {
|
|
58
|
-
restoreLabel,
|
|
59
|
-
restoredTaskIds
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
async function runResume({
|
|
64
|
-
repoRoot,
|
|
65
|
-
changeId,
|
|
66
|
-
parallel,
|
|
67
|
-
maxRetries,
|
|
68
|
-
executionScope = 'all',
|
|
69
|
-
fromCheckpoint = 'stable'
|
|
70
|
-
}) {
|
|
71
|
-
const manifestPath = getTaskManifestPath(repoRoot, changeId);
|
|
72
|
-
const manifest = parseManifest(await readJson(manifestPath));
|
|
73
|
-
const state = await readJson(getRuntimeStatePath(repoRoot, changeId), null);
|
|
74
|
-
const approval = getApprovalState(state, manifest);
|
|
75
|
-
|
|
76
|
-
if (!isExecutionApproved(state, manifest)) {
|
|
77
|
-
await syncIntentMemory(repoRoot, changeId, {
|
|
78
|
-
event: 'resume_blocked_unapproved',
|
|
79
|
-
reason: `Plan version ${approval.planVersion || manifest.metadata?.planVersion || 1} must be approved before resume`
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
return {
|
|
83
|
-
changeId,
|
|
84
|
-
manifestPath,
|
|
85
|
-
summary: null,
|
|
86
|
-
success: false,
|
|
87
|
-
reason: `Execution blocked until plan_version ${approval.planVersion || manifest.metadata?.planVersion || 1} is approved. Return to the cc-plan approval gate and keep execution mode ${approval.executionMode}.`
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
if (fromCheckpoint && fromCheckpoint !== 'stable') {
|
|
92
|
-
throw new Error(`Unsupported resume point: ${fromCheckpoint}`);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
const restoreTarget = await resolveStableManifestPoint(manifest);
|
|
96
|
-
const restoreSummary = requeueFromStableManifestPoint(manifest, restoreTarget);
|
|
97
|
-
|
|
98
|
-
applyManifestExecutionState(manifest);
|
|
99
|
-
await writeJson(manifestPath, manifest);
|
|
100
|
-
await syncIntentMemory(repoRoot, changeId, {
|
|
101
|
-
event: 'resume_restored_manifest_state',
|
|
102
|
-
reason: restoreSummary.restoredTaskIds.length > 0
|
|
103
|
-
? `Restored ${restoreSummary.restoredTaskIds.join(', ')} from ${restoreSummary.restoreLabel}`
|
|
104
|
-
: `Resume confirmed ${restoreSummary.restoreLabel}; no unresolved tasks required requeue`
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
const dispatchResult = await runDispatch({
|
|
108
|
-
repoRoot,
|
|
109
|
-
changeId,
|
|
110
|
-
parallel,
|
|
111
|
-
maxRetries,
|
|
112
|
-
resume: true,
|
|
113
|
-
executionScope
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
return {
|
|
117
|
-
...dispatchResult,
|
|
118
|
-
restoredState: restoreTarget,
|
|
119
|
-
restoredTasks: restoreSummary.restoredTaskIds,
|
|
120
|
-
reason: dispatchResult.reason || `Resumed from ${restoreSummary.restoreLabel}`
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
module.exports = {
|
|
125
|
-
runResume
|
|
126
|
-
};
|
|
@@ -1,265 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* [INPUT]: 依赖 review-records helper、store.appendJsonl、ReviewLedgerEventSchema。
|
|
3
|
-
* [OUTPUT]: 实现 review durable records CLI operation,当前只写 review-started。
|
|
4
|
-
* [POS]: CLI 与 durable review ledger 的边界层;负责校验后追加 JSONL。
|
|
5
|
-
* [PROTOCOL]: 变更时更新此头部,然后检查 CLAUDE.md
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
const path = require('path');
|
|
9
|
-
|
|
10
|
-
const { getChangePaths } = require('../paths');
|
|
11
|
-
const { appendJsonl, readText, writeText } = require('../store');
|
|
12
|
-
const { parseReviewLedgerEvent } = require('../schemas');
|
|
13
|
-
const {
|
|
14
|
-
getReviewLedgerPath,
|
|
15
|
-
nextReviewId,
|
|
16
|
-
parseSkippedNode
|
|
17
|
-
} = require('../review-records');
|
|
18
|
-
|
|
19
|
-
function readLedgerEvents(text) {
|
|
20
|
-
return String(text || '')
|
|
21
|
-
.split('\n')
|
|
22
|
-
.map((line) => line.trim())
|
|
23
|
-
.filter(Boolean)
|
|
24
|
-
.map((line) => JSON.parse(line));
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function normalizeArray(values) {
|
|
28
|
-
return (values || [])
|
|
29
|
-
.flatMap((value) => String(value || '').split(','))
|
|
30
|
-
.map((value) => value.trim())
|
|
31
|
-
.filter(Boolean);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
async function loadLedger(repoRoot, changeId, changeKey) {
|
|
35
|
-
const change = getChangePaths(repoRoot, changeId, { changeKey });
|
|
36
|
-
const ledgerPath = getReviewLedgerPath(repoRoot, changeId, { changeKey });
|
|
37
|
-
const events = readLedgerEvents(await readText(ledgerPath, ''));
|
|
38
|
-
return { change, ledgerPath, events };
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function hasStarted(events, reviewId) {
|
|
42
|
-
return events.some((event) => event.reviewId === reviewId && event.event === 'review-started');
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function hasClosed(events, reviewId) {
|
|
46
|
-
return events.some((event) => event.reviewId === reviewId && event.event === 'review-closed');
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
async function appendReviewEvent(options, eventFields) {
|
|
50
|
-
const {
|
|
51
|
-
repoRoot,
|
|
52
|
-
changeId,
|
|
53
|
-
changeKey,
|
|
54
|
-
reviewId,
|
|
55
|
-
now = new Date()
|
|
56
|
-
} = options;
|
|
57
|
-
const { change, ledgerPath, events } = await loadLedger(repoRoot, changeId, changeKey);
|
|
58
|
-
|
|
59
|
-
if (!reviewId || !hasStarted(events, reviewId)) {
|
|
60
|
-
return {
|
|
61
|
-
code: 4,
|
|
62
|
-
stderr: `Review ${reviewId || '<missing>'} has not been started`
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (eventFields.event === 'review-closed' && hasClosed(events, reviewId)) {
|
|
67
|
-
return {
|
|
68
|
-
code: 4,
|
|
69
|
-
stderr: `Review ${reviewId} is already closed`
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const event = parseReviewLedgerEvent({
|
|
74
|
-
schema: 'review-ledger.v2',
|
|
75
|
-
change: change.changeKey,
|
|
76
|
-
reviewId,
|
|
77
|
-
createdAt: now.toISOString(),
|
|
78
|
-
createdBy: 'cc-devflow-cli',
|
|
79
|
-
...eventFields
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
await appendJsonl(ledgerPath, event);
|
|
83
|
-
|
|
84
|
-
return {
|
|
85
|
-
code: 0,
|
|
86
|
-
reviewId,
|
|
87
|
-
ledgerPath: path.relative(repoRoot, ledgerPath),
|
|
88
|
-
event: event.event
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
async function runReviewStart(options) {
|
|
93
|
-
const {
|
|
94
|
-
repoRoot,
|
|
95
|
-
changeId,
|
|
96
|
-
changeKey,
|
|
97
|
-
mode = 'implementation',
|
|
98
|
-
scope = 'current-diff',
|
|
99
|
-
baseSha = 'unknown',
|
|
100
|
-
headSha = 'unknown',
|
|
101
|
-
selectedNodes = [],
|
|
102
|
-
skippedNodes = [],
|
|
103
|
-
riskLanes = [],
|
|
104
|
-
now = new Date()
|
|
105
|
-
} = options;
|
|
106
|
-
const change = getChangePaths(repoRoot, changeId, { changeKey });
|
|
107
|
-
const ledgerPath = getReviewLedgerPath(repoRoot, changeId, { changeKey });
|
|
108
|
-
const existingEvents = readLedgerEvents(await readText(ledgerPath, ''));
|
|
109
|
-
const reviewId = nextReviewId(existingEvents, now);
|
|
110
|
-
const event = parseReviewLedgerEvent({
|
|
111
|
-
schema: 'review-ledger.v2',
|
|
112
|
-
change: change.changeKey,
|
|
113
|
-
reviewId,
|
|
114
|
-
createdAt: now.toISOString(),
|
|
115
|
-
createdBy: 'cc-devflow-cli',
|
|
116
|
-
event: 'review-started',
|
|
117
|
-
mode,
|
|
118
|
-
scope,
|
|
119
|
-
baseSha,
|
|
120
|
-
headSha,
|
|
121
|
-
selectedNodes: normalizeArray(selectedNodes),
|
|
122
|
-
skippedNodes: skippedNodes.map(parseSkippedNode),
|
|
123
|
-
riskLanes: normalizeArray(riskLanes)
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
await appendJsonl(ledgerPath, event);
|
|
127
|
-
|
|
128
|
-
return {
|
|
129
|
-
code: 0,
|
|
130
|
-
reviewId,
|
|
131
|
-
ledgerPath: path.relative(repoRoot, ledgerPath),
|
|
132
|
-
event: event.event
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
async function runReviewRecordNode(options) {
|
|
137
|
-
return appendReviewEvent(options, {
|
|
138
|
-
event: 'review-node-checked',
|
|
139
|
-
nodeId: options.nodeId,
|
|
140
|
-
mode: options.mode || 'implementation',
|
|
141
|
-
target: options.target,
|
|
142
|
-
status: options.status || 'checked',
|
|
143
|
-
coverage: normalizeArray(options.coverage),
|
|
144
|
-
evidenceRefs: normalizeArray(options.evidenceRefs),
|
|
145
|
-
findings: normalizeArray(options.findings),
|
|
146
|
-
next: options.next || 'cc-check'
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
async function runReviewAddFinding(options) {
|
|
151
|
-
return appendReviewEvent(options, {
|
|
152
|
-
event: 'review-finding-added',
|
|
153
|
-
findingId: options.findingId,
|
|
154
|
-
severity: options.severity || 'important',
|
|
155
|
-
confidence: Number(options.confidence),
|
|
156
|
-
displayTier: options.displayTier || 'blocking',
|
|
157
|
-
fingerprint: options.fingerprint,
|
|
158
|
-
scope: options.scope,
|
|
159
|
-
path: options.path,
|
|
160
|
-
evidence: options.evidence,
|
|
161
|
-
recommendation: options.recommendation,
|
|
162
|
-
route: options.route || 'cc-do'
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
async function runReviewClose(options) {
|
|
167
|
-
return appendReviewEvent(options, {
|
|
168
|
-
event: 'review-closed',
|
|
169
|
-
status: options.status || 'clean',
|
|
170
|
-
blockingCount: Number(options.blockingCount || 0),
|
|
171
|
-
warningCount: Number(options.warningCount || 0),
|
|
172
|
-
next: options.next || 'cc-check'
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
function renderReviewMarkdown({ changeKey, reviewId, events }) {
|
|
177
|
-
const closed = events.find((event) => event.event === 'review-closed');
|
|
178
|
-
const findings = events.filter((event) => event.event === 'review-finding-added');
|
|
179
|
-
const lines = [
|
|
180
|
-
'---',
|
|
181
|
-
'Output language: en',
|
|
182
|
-
`reviewId: ${reviewId}`,
|
|
183
|
-
`change: ${changeKey}`,
|
|
184
|
-
'---',
|
|
185
|
-
'',
|
|
186
|
-
`# Review ${reviewId}`,
|
|
187
|
-
'',
|
|
188
|
-
'## Summary',
|
|
189
|
-
'',
|
|
190
|
-
`- Status: ${closed?.status || 'open'}`,
|
|
191
|
-
`- Blocking findings: ${closed?.blockingCount ?? 0}`,
|
|
192
|
-
`- Warnings: ${closed?.warningCount ?? 0}`,
|
|
193
|
-
`- Next: ${closed?.next || 'cc-check'}`,
|
|
194
|
-
'',
|
|
195
|
-
'## Findings',
|
|
196
|
-
''
|
|
197
|
-
];
|
|
198
|
-
|
|
199
|
-
if (findings.length === 0) {
|
|
200
|
-
lines.push('- None');
|
|
201
|
-
} else {
|
|
202
|
-
for (const finding of findings) {
|
|
203
|
-
lines.push(
|
|
204
|
-
`- ${finding.findingId} [${finding.severity}/${finding.displayTier}, confidence ${finding.confidence}] ${finding.path}`,
|
|
205
|
-
` - Evidence: ${finding.evidence}`,
|
|
206
|
-
` - Recommendation: ${finding.recommendation}`,
|
|
207
|
-
` - Route: ${finding.route}`
|
|
208
|
-
);
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
lines.push('', '## Ledger Events', '');
|
|
213
|
-
for (const event of events) {
|
|
214
|
-
lines.push(`- ${event.event} at ${event.createdAt}`);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
return `${lines.join('\n')}\n`;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
async function runReviewRender(options) {
|
|
221
|
-
const {
|
|
222
|
-
repoRoot,
|
|
223
|
-
changeId,
|
|
224
|
-
changeKey,
|
|
225
|
-
reviewId,
|
|
226
|
-
output
|
|
227
|
-
} = options;
|
|
228
|
-
const { change, events } = await loadLedger(repoRoot, changeId, changeKey);
|
|
229
|
-
const selectedReviewId = reviewId
|
|
230
|
-
|| [...events].reverse().find((event) => event.event === 'review-started')?.reviewId;
|
|
231
|
-
|
|
232
|
-
if (!selectedReviewId) {
|
|
233
|
-
return { code: 4, stderr: 'No reviewId available to render' };
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
if (!output) {
|
|
237
|
-
return { code: 4, stderr: 'review render --output is required' };
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
const reviewEvents = events.filter((event) => event.reviewId === selectedReviewId);
|
|
241
|
-
if (reviewEvents.length === 0) {
|
|
242
|
-
return { code: 4, stderr: `Review ${selectedReviewId} has no ledger events` };
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
const outputPath = path.isAbsolute(output) ? output : path.join(repoRoot, output);
|
|
246
|
-
await writeText(outputPath, renderReviewMarkdown({
|
|
247
|
-
changeKey: change.changeKey,
|
|
248
|
-
reviewId: selectedReviewId,
|
|
249
|
-
events: reviewEvents
|
|
250
|
-
}));
|
|
251
|
-
|
|
252
|
-
return {
|
|
253
|
-
code: 0,
|
|
254
|
-
reviewId: selectedReviewId,
|
|
255
|
-
outputPath: path.relative(repoRoot, outputPath)
|
|
256
|
-
};
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
module.exports = {
|
|
260
|
-
runReviewAddFinding,
|
|
261
|
-
runReviewClose,
|
|
262
|
-
runReviewRecordNode,
|
|
263
|
-
runReviewRender,
|
|
264
|
-
runReviewStart
|
|
265
|
-
};
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* [INPUT]: 依赖 store 读取 change-state/package scripts,并通过 git 命令收集仓库事实。
|
|
3
|
-
* [OUTPUT]: 返回 discover 阶段需要的仓库事实,不再落盘 planning-snapshot.md。
|
|
4
|
-
* [POS]: skill runtime Stage-2 内部快照入口,被 autopilot discover 阶段调用。
|
|
5
|
-
* [PROTOCOL]: 变更时更新此头部,然后检查 CLAUDE.md
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
const {
|
|
9
|
-
readJson,
|
|
10
|
-
getRuntimeStatePath,
|
|
11
|
-
runCommand,
|
|
12
|
-
getPackageScripts
|
|
13
|
-
} = require('../store');
|
|
14
|
-
|
|
15
|
-
async function collectGitFacts(repoRoot) {
|
|
16
|
-
const [branch, commit, status] = await Promise.all([
|
|
17
|
-
runCommand('git rev-parse --abbrev-ref HEAD', { cwd: repoRoot }),
|
|
18
|
-
runCommand('git rev-parse HEAD', { cwd: repoRoot }),
|
|
19
|
-
runCommand('git status --short', { cwd: repoRoot })
|
|
20
|
-
]);
|
|
21
|
-
|
|
22
|
-
return {
|
|
23
|
-
branch: branch.code === 0 ? branch.stdout.trim() : 'unknown',
|
|
24
|
-
commit: commit.code === 0 ? commit.stdout.trim() : 'unknown',
|
|
25
|
-
status: status.code === 0 ? status.stdout.trim() : '(clean)'
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
async function runPlanningSnapshot({ repoRoot, changeId, goal }) {
|
|
30
|
-
const state = (await readJson(getRuntimeStatePath(repoRoot, changeId), {})) || {};
|
|
31
|
-
const effectiveGoal = goal || state.goal || `Deliver ${changeId} safely with task-state truth.`;
|
|
32
|
-
const gitFacts = await collectGitFacts(repoRoot);
|
|
33
|
-
const scripts = await getPackageScripts(repoRoot);
|
|
34
|
-
|
|
35
|
-
return {
|
|
36
|
-
changeId,
|
|
37
|
-
goal: effectiveGoal,
|
|
38
|
-
gitFacts,
|
|
39
|
-
scripts
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
module.exports = {
|
|
44
|
-
runPlanningSnapshot
|
|
45
|
-
};
|