cclaw-cli 0.34.1 → 0.36.0
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/dist/config.js +41 -2
- package/dist/content/meta-skill.js +21 -0
- package/dist/content/protocols.js +53 -2
- package/dist/content/stages/plan.js +2 -1
- package/dist/content/stages/spec.js +2 -0
- package/dist/content/stages/tdd.js +15 -3
- package/dist/doctor.js +31 -0
- package/dist/install.d.ts +2 -1
- package/dist/install.js +2 -1
- package/dist/types.d.ts +37 -0
- package/package.json +1 -1
package/dist/config.js
CHANGED
|
@@ -21,8 +21,11 @@ const ALLOWED_CONFIG_KEYS = new Set([
|
|
|
21
21
|
"gitHookGuards",
|
|
22
22
|
"defaultTrack",
|
|
23
23
|
"languageRulePacks",
|
|
24
|
-
"trackHeuristics"
|
|
24
|
+
"trackHeuristics",
|
|
25
|
+
"sliceReview"
|
|
25
26
|
]);
|
|
27
|
+
const DEFAULT_SLICE_REVIEW_THRESHOLD = 5;
|
|
28
|
+
const DEFAULT_SLICE_REVIEW_TRACKS = ["standard"];
|
|
26
29
|
function configFixExample() {
|
|
27
30
|
return `harnesses:
|
|
28
31
|
- claude
|
|
@@ -210,6 +213,41 @@ export async function readConfig(projectRoot) {
|
|
|
210
213
|
tracks
|
|
211
214
|
};
|
|
212
215
|
}
|
|
216
|
+
const sliceReviewRaw = parsed.sliceReview;
|
|
217
|
+
let sliceReview = undefined;
|
|
218
|
+
if (Object.prototype.hasOwnProperty.call(parsed, "sliceReview")) {
|
|
219
|
+
if (!isRecord(sliceReviewRaw)) {
|
|
220
|
+
throw configValidationError(fullPath, `"sliceReview" must be an object`);
|
|
221
|
+
}
|
|
222
|
+
const enabledRaw = sliceReviewRaw.enabled;
|
|
223
|
+
if (enabledRaw !== undefined && typeof enabledRaw !== "boolean") {
|
|
224
|
+
throw configValidationError(fullPath, `"sliceReview.enabled" must be a boolean`);
|
|
225
|
+
}
|
|
226
|
+
const thresholdRaw = sliceReviewRaw.filesChangedThreshold;
|
|
227
|
+
if (thresholdRaw !== undefined &&
|
|
228
|
+
(typeof thresholdRaw !== "number" || !Number.isInteger(thresholdRaw) || thresholdRaw < 1)) {
|
|
229
|
+
throw configValidationError(fullPath, `"sliceReview.filesChangedThreshold" must be a positive integer`);
|
|
230
|
+
}
|
|
231
|
+
const touchTriggers = validateStringArray(sliceReviewRaw.touchTriggers, "sliceReview.touchTriggers", fullPath);
|
|
232
|
+
const enforceRaw = sliceReviewRaw.enforceOnTracks;
|
|
233
|
+
let enforceOnTracks;
|
|
234
|
+
if (enforceRaw !== undefined) {
|
|
235
|
+
if (!Array.isArray(enforceRaw)) {
|
|
236
|
+
throw configValidationError(fullPath, `"sliceReview.enforceOnTracks" must be an array`);
|
|
237
|
+
}
|
|
238
|
+
const invalidTracks = enforceRaw.filter((value) => typeof value !== "string" || !FLOW_TRACK_SET.has(value));
|
|
239
|
+
if (invalidTracks.length > 0) {
|
|
240
|
+
throw configValidationError(fullPath, `"sliceReview.enforceOnTracks" must contain only: ${SUPPORTED_TRACKS_TEXT}`);
|
|
241
|
+
}
|
|
242
|
+
enforceOnTracks = [...new Set(enforceRaw)];
|
|
243
|
+
}
|
|
244
|
+
sliceReview = {
|
|
245
|
+
enabled: typeof enabledRaw === "boolean" ? enabledRaw : false,
|
|
246
|
+
filesChangedThreshold: typeof thresholdRaw === "number" ? thresholdRaw : DEFAULT_SLICE_REVIEW_THRESHOLD,
|
|
247
|
+
touchTriggers: touchTriggers ?? [],
|
|
248
|
+
enforceOnTracks: enforceOnTracks ?? DEFAULT_SLICE_REVIEW_TRACKS
|
|
249
|
+
};
|
|
250
|
+
}
|
|
213
251
|
return {
|
|
214
252
|
version: parsed.version ?? CCLAW_VERSION,
|
|
215
253
|
flowVersion: parsed.flowVersion ?? FLOW_VERSION,
|
|
@@ -220,7 +258,8 @@ export async function readConfig(projectRoot) {
|
|
|
220
258
|
gitHookGuards,
|
|
221
259
|
defaultTrack,
|
|
222
260
|
languageRulePacks,
|
|
223
|
-
trackHeuristics
|
|
261
|
+
trackHeuristics,
|
|
262
|
+
sliceReview
|
|
224
263
|
};
|
|
225
264
|
}
|
|
226
265
|
export async function writeConfig(projectRoot, config) {
|
|
@@ -18,6 +18,27 @@ description: "Routing brain for cclaw. Decide whether to start/resume a stage, a
|
|
|
18
18
|
|
|
19
19
|
If the user explicitly overrides a stage rule, record it in the artifact.
|
|
20
20
|
|
|
21
|
+
## Skill-before-response gate
|
|
22
|
+
|
|
23
|
+
If \`.cclaw/state/flow-state.json\` exists and \`currentStage\` is set,
|
|
24
|
+
load the matching stage SKILL before producing **substantive** work
|
|
25
|
+
(artifact edits, code, structured clarifying questions). Do not improvise
|
|
26
|
+
from memory. Also load a contextual utility skill when the task clearly
|
|
27
|
+
triggers it (security, performance, debugging, docs, finishing-a-branch,
|
|
28
|
+
verification-before-completion).
|
|
29
|
+
|
|
30
|
+
Substantive vs. non-substantive:
|
|
31
|
+
|
|
32
|
+
- **Substantive** (must load skill first): proposing design, editing an
|
|
33
|
+
artifact, running gates, dispatching subagents, asking a
|
|
34
|
+
\`Decision Protocol\` question, declaring a stage done.
|
|
35
|
+
- **Non-substantive** (skill load optional): one-line acknowledgement,
|
|
36
|
+
clarifying a typo, confirming a prior answer, pure conversation.
|
|
37
|
+
|
|
38
|
+
If the current stage is ambiguous because \`flow-state.json\` is missing
|
|
39
|
+
or corrupt, stop and route through \`/cc\` before any substantive
|
|
40
|
+
response.
|
|
41
|
+
|
|
21
42
|
## Routing flow
|
|
22
43
|
|
|
23
44
|
\`\`\`
|
|
@@ -19,11 +19,62 @@ Shared format for decisions that require user confirmation.
|
|
|
19
19
|
- OpenCode/Codex: plain text options
|
|
20
20
|
5. Wait for user choice before proceeding.
|
|
21
21
|
|
|
22
|
+
## Decision skeleton
|
|
23
|
+
|
|
24
|
+
Every Decision Protocol call — regardless of harness — follows this
|
|
25
|
+
four-part skeleton. Do not skip a part; if a part is trivially empty,
|
|
26
|
+
say so explicitly (e.g. "Re-ground: same branch, same task as prior
|
|
27
|
+
turn").
|
|
28
|
+
|
|
29
|
+
1. **Re-ground (1-2 sentences).** State the project, the active
|
|
30
|
+
feature slug, the active stage (from \`flow-state.json\`), and the
|
|
31
|
+
decision's plain-English context. Pull these values from the source
|
|
32
|
+
of truth, not from conversation memory.
|
|
33
|
+
2. **Simplify (2-4 sentences).** Explain the choice in plain English a
|
|
34
|
+
smart 16-year-old could follow. No internal jargon, no raw function
|
|
35
|
+
names, no implementation trivia. Say what each option DOES and
|
|
36
|
+
what changes for the user.
|
|
37
|
+
3. **Recommend.** One line of the form
|
|
38
|
+
\`RECOMMENDATION: Choose [Letter] because [one-line reason]\`.
|
|
39
|
+
Always prefer the more complete option unless an explicit constraint
|
|
40
|
+
says otherwise (see Completeness calibration below). Never present
|
|
41
|
+
options as equivalent when they are not.
|
|
42
|
+
4. **Options.** Lettered options \`A) ... B) ... C) ...\`. Each option
|
|
43
|
+
includes one-line \`Completeness: X/10\` plus, when effort differs
|
|
44
|
+
noticeably, a \`(human: ~Xh / agent: ~Ym)\` estimate.
|
|
45
|
+
|
|
46
|
+
## Completeness calibration
|
|
47
|
+
|
|
48
|
+
Use the same 1-10 scale for every option so comparisons stay honest:
|
|
49
|
+
|
|
50
|
+
- **10** = complete implementation: all stated edges handled,
|
|
51
|
+
traceable to spec, no known deferred work.
|
|
52
|
+
- **7** = covers the happy path; one or two non-critical edges
|
|
53
|
+
deferred with an explicit follow-up.
|
|
54
|
+
- **5** = partial; either drops edge cases silently or hands off
|
|
55
|
+
required work to a future run.
|
|
56
|
+
- **3** = shortcut; skips spec criteria, violates an Iron Law, or
|
|
57
|
+
defers significant work without tracking.
|
|
58
|
+
- **1** = acknowledged placeholder (\`TBD\`, \`TODO\`, "static for now").
|
|
59
|
+
|
|
60
|
+
Calibration rules:
|
|
61
|
+
|
|
62
|
+
- Mark any option at \`Completeness: ≤5\` and require the user to
|
|
63
|
+
acknowledge the gap before picking it.
|
|
64
|
+
- If two options are both \`≥8\`, recommend the higher one.
|
|
65
|
+
- "Static for now" / "we will add later" phrasing always scores \`≤3\`
|
|
66
|
+
and must be surfaced in Simplify, not buried in an option label.
|
|
67
|
+
|
|
22
68
|
## Ask format
|
|
23
69
|
|
|
24
70
|
- One question per call.
|
|
25
|
-
- Option labels are short and unambiguous
|
|
26
|
-
|
|
71
|
+
- Option labels are short and unambiguous; the full reasoning lives in
|
|
72
|
+
Simplify + per-option Completeness.
|
|
73
|
+
- If tool schema fails once, fall back to plain text immediately but
|
|
74
|
+
keep the skeleton (Re-ground / Simplify / RECOMMENDATION / lettered
|
|
75
|
+
Options with Completeness scores).
|
|
76
|
+
- Log the chosen letter into the stage artifact's decision log with
|
|
77
|
+
the Completeness score; do not rely on chat history.
|
|
27
78
|
|
|
28
79
|
## Retry and escalation
|
|
29
80
|
|
|
@@ -25,6 +25,7 @@ export const PLAN = {
|
|
|
25
25
|
"Group tasks into dependency batches — batch N+1 cannot start until batch N has verification evidence.",
|
|
26
26
|
"Slice into vertical tasks — each task targets 2-5 minutes, produces one testable outcome, and touches one coherent area.",
|
|
27
27
|
"Attach verification — every task has an acceptance criterion mapping and a concrete verification command.",
|
|
28
|
+
"Annotate slice-review metadata — if `.cclaw/config.yaml::sliceReview.enabled` is true, every task row additionally carries `touchCount` (rough number of files expected to change) and `touchPaths` (glob hints, e.g. `migrations/**`, `src/auth/**`). A task may set `highRisk: true` to force a review pass regardless of thresholds. These fields feed the TDD stage's Per-Slice Review checkpoint; when `sliceReview` is disabled they are optional.",
|
|
28
29
|
"Map scope Locked Decisions — every D-XX from scope is referenced by at least one plan task (or explicitly marked deferred with reason).",
|
|
29
30
|
"Run anti-placeholder + anti-scope-reduction scans — block `TODO/TBD/...` and phrasing like `v1`, `for now`, `later` for locked boundaries.",
|
|
30
31
|
"Define checkpoints — mark points where progress should be validated before continuing.",
|
|
@@ -143,7 +144,7 @@ export const PLAN = {
|
|
|
143
144
|
artifactValidation: [
|
|
144
145
|
{ section: "Dependency Graph", required: true, validationRule: "Ordering and parallel opportunities explicit. No circular dependencies." },
|
|
145
146
|
{ section: "Dependency Batches", required: true, validationRule: "Every task belongs to a batch. Each batch has an exit gate and dependency statement." },
|
|
146
|
-
{ section: "Task List", required: true, validationRule: "Each task row includes ID, description, acceptance criterion, verification command, and effort estimate (S/M/L). Every task must also carry a minutes estimate within the 2-5 minute budget." },
|
|
147
|
+
{ section: "Task List", required: true, validationRule: "Each task row includes ID, description, acceptance criterion, verification command, and effort estimate (S/M/L). Every task must also carry a minutes estimate within the 2-5 minute budget. When the sliceReview feature is enabled in the cclaw config, each task row additionally declares touchCount, touchPaths, and an optional highRisk flag so the TDD stage can decide whether a Per-Slice Review pass is required." },
|
|
147
148
|
{ section: "Acceptance Mapping", required: true, validationRule: "Every spec criterion is covered by at least one task." },
|
|
148
149
|
{ section: "Locked Decision Coverage", required: false, validationRule: "Every locked decision ID (D-XX) from scope is listed with linked task IDs or explicit defer rationale." },
|
|
149
150
|
{ section: "Risk Assessment", required: false, validationRule: "If present: per-task or per-batch risk identification with likelihood, impact, and mitigation strategy." },
|
|
@@ -31,6 +31,7 @@ export const SPEC = {
|
|
|
31
31
|
"Express each requirement in observable terms.",
|
|
32
32
|
"Resolve ambiguity before moving to plan. Challenge vague language.",
|
|
33
33
|
"Capture assumptions explicitly, not implicitly.",
|
|
34
|
+
"**Chunk acceptance criteria for review.** When presenting the spec to the user for sign-off, deliver acceptance criteria in batches of 3-5 and **pause for explicit ACK** (via Decision Protocol) before sending the next batch. Do not dump the full criteria wall in one message — small batches surface objections earlier and keep the sign-off meaningful. Full spec writeup still lands in `04-spec.md`, but the conversation itself must be digestible.",
|
|
34
35
|
"Require user confirmation on the written spec. **STOP.** Do NOT proceed to plan until user approves.",
|
|
35
36
|
"For each criterion, ask: how would you test this? If the answer is unclear, rewrite.",
|
|
36
37
|
"When encountering ambiguity, classify it before acting: (A) ask user for missing info, (B) enumerate interpretations and pick one with justification, (C) propose hypothesis with validation path. Do NOT silently resolve ambiguity."
|
|
@@ -40,6 +41,7 @@ export const SPEC = {
|
|
|
40
41
|
"Capture constraints, assumptions, and edge cases.",
|
|
41
42
|
"Build testability map: criterion -> test description.",
|
|
42
43
|
"Confirm testability for each criterion.",
|
|
44
|
+
"Present acceptance criteria to the user in 3-5-item batches, pausing for explicit ACK between batches (see Interaction Protocol).",
|
|
43
45
|
"Write spec artifact and request approval."
|
|
44
46
|
],
|
|
45
47
|
requiredGates: [
|
|
@@ -30,6 +30,7 @@ export const TDD = {
|
|
|
30
30
|
"REFACTOR: Improve code quality — without changing behavior. Document what you changed and why.",
|
|
31
31
|
"Record evidence — capture RED failure, GREEN output, and REFACTOR notes in the TDD artifact.",
|
|
32
32
|
"Annotate traceability — link to plan task ID and spec criterion.",
|
|
33
|
+
"Per-Slice Review (conditional) — if `.cclaw/config.yaml::sliceReview.enabled` is true and the slice meets any trigger (touchCount >= filesChangedThreshold, touchPaths match touchTriggers, or highRisk=true), append a `## Per-Slice Review` entry for this slice before moving on (see the dedicated section below).",
|
|
33
34
|
"Repeat for each slice — return to step 1 for the next plan slice."
|
|
34
35
|
],
|
|
35
36
|
interactionProtocol: [
|
|
@@ -41,7 +42,8 @@ export const TDD = {
|
|
|
41
42
|
"Run full suite, not partial checks, for GREEN validation.",
|
|
42
43
|
"Refactor without changing behavior and document rationale (REFACTOR).",
|
|
43
44
|
"Stop if regressions appear and fix before proceeding.",
|
|
44
|
-
"If a test passes unexpectedly, investigate: does the behavior already exist, or is the test wrong?"
|
|
45
|
+
"If a test passes unexpectedly, investigate: does the behavior already exist, or is the test wrong?",
|
|
46
|
+
"**Per-Slice Review checkpoint (conditional, opt-in).** When `.cclaw/config.yaml::sliceReview.enabled` is true, check every slice against the triggers before declaring it DONE. Triggers: `touchCount >= filesChangedThreshold`, any `touchPaths` match a `touchTriggers` glob, or the plan row declares `highRisk: true`. On a trigger, run two passes on the slice alone — (1) Spec-Compliance: trace RED/GREEN/REFACTOR evidence back to its plan task + spec criterion, noting edge cases the tests skip; (2) Quality: diff-scan for naming, error handling, dead code, simpler alternatives. Record both under `## Per-Slice Review` in `06-tdd.md`, naming the trigger that fired. Dispatch the `reviewer` subagent natively when available (log `fulfillmentMode: \"isolated\"`); otherwise fulfil via in-session role switch (`fulfillmentMode: \"role-switch\"`). Never fabricate an isolated pass from memory. Tracks outside `sliceReview.enforceOnTracks` still emit the section; doctor only escalates missed reviews on enforced tracks."
|
|
45
47
|
],
|
|
46
48
|
process: [
|
|
47
49
|
"Select slice and map to acceptance criterion.",
|
|
@@ -51,7 +53,7 @@ export const TDD = {
|
|
|
51
53
|
"Run full tests and build checks.",
|
|
52
54
|
"Perform refactor pass preserving behavior.",
|
|
53
55
|
"Record RED, GREEN, and REFACTOR evidence in artifact.",
|
|
54
|
-
"Annotate traceability to plan task and spec criterion."
|
|
56
|
+
"Annotate traceability to plan task and spec criterion; on `sliceReview` triggers, append a Per-Slice Review entry before closing the slice."
|
|
55
57
|
],
|
|
56
58
|
requiredGates: [
|
|
57
59
|
{ id: "tdd_red_test_written", description: "Failing tests exist before implementation changes." },
|
|
@@ -149,6 +151,15 @@ export const TDD = {
|
|
|
149
151
|
],
|
|
150
152
|
stopGate: false
|
|
151
153
|
},
|
|
154
|
+
{
|
|
155
|
+
title: "Per-Slice Review Audit (conditional)",
|
|
156
|
+
evaluationPoints: [
|
|
157
|
+
"When `.cclaw/config.yaml::sliceReview.enabled` is true: does every triggered slice (touchCount >= threshold, touchPaths match, or highRisk=true) carry a Per-Slice Review entry with BOTH a Spec-Compliance pass (plan task <-> spec criterion + edge-case notes) AND a Quality pass (diff-level naming/errors/dead code/simpler alternatives)?",
|
|
158
|
+
"Is the delegation `fulfillmentMode` recorded (`isolated` for a dispatched reviewer subagent, `role-switch` for an in-session pass) and does it match an entry in `.cclaw/state/delegation-log.json`?",
|
|
159
|
+
"On tracks listed in `sliceReview.enforceOnTracks`, are there zero missed triggered slices (doctor also surfaces this as a warning)?"
|
|
160
|
+
],
|
|
161
|
+
stopGate: false
|
|
162
|
+
},
|
|
152
163
|
{
|
|
153
164
|
title: "State-over-Interaction + Beyoncé Coverage",
|
|
154
165
|
evaluationPoints: [
|
|
@@ -177,7 +188,8 @@ export const TDD = {
|
|
|
177
188
|
{ section: "Verification Ladder", required: false, validationRule: "If present: per-slice verification tier (static, command, behavioral, human) with evidence for highest tier reached." },
|
|
178
189
|
{ section: "Coverage Targets", required: false, validationRule: "If present: per-module or per-code-type coverage thresholds with current values and measurement commands." },
|
|
179
190
|
{ section: "Test Pyramid Shape", required: false, validationRule: "If present: per-slice count of Small/Medium/Large tests added, to let reviewers verify the suite is not drifting top-heavy." },
|
|
180
|
-
{ section: "Prove-It Reproduction", required: false, validationRule: "Required for bug-fix slices: original failing reproduction test (RED without fix), passing output with fix (GREEN), and a note confirming the test fails again if the fix is reverted." }
|
|
191
|
+
{ section: "Prove-It Reproduction", required: false, validationRule: "Required for bug-fix slices: original failing reproduction test (RED without fix), passing output with fix (GREEN), and a note confirming the test fails again if the fix is reverted." },
|
|
192
|
+
{ section: "Per-Slice Review", required: false, validationRule: "When `.cclaw/config.yaml::sliceReview.enabled` is true: per triggered slice, a two-part record — Spec-Compliance (slice <-> plan task <-> spec criterion trace plus edge-case notes) and Quality (diff-focused review of naming, error handling, dead code, simpler alternatives). Each entry names the trigger (touchCount, touchPaths glob, or highRisk) and the delegation fulfillmentMode (`isolated` when a reviewer subagent was dispatched natively; `role-switch` when fulfilled in-session). Slices that did not meet any trigger may list `not triggered` instead of a full pass." }
|
|
181
193
|
],
|
|
182
194
|
batchExecutionAllowed: true
|
|
183
195
|
};
|
package/dist/doctor.js
CHANGED
|
@@ -1382,6 +1382,37 @@ export async function doctorChecks(projectRoot, options = {}) {
|
|
|
1382
1382
|
? "all test slices map to acceptance-linked tasks"
|
|
1383
1383
|
: `orphaned test slices: ${trace.orphanedTests.join(", ")}`
|
|
1384
1384
|
});
|
|
1385
|
+
// Slice-review warning (opt-in via config.sliceReview.enabled).
|
|
1386
|
+
// Fires when:
|
|
1387
|
+
// - sliceReview.enabled is true
|
|
1388
|
+
// - current track is listed in sliceReview.enforceOnTracks
|
|
1389
|
+
// - 06-tdd.md exists (so the slice loop actually started)
|
|
1390
|
+
// - artifact contains at least one slice marker (look for the tdd
|
|
1391
|
+
// "Acceptance Mapping" or any `### Slice` heading) AND the Per-Slice
|
|
1392
|
+
// Review heading is absent
|
|
1393
|
+
// Non-blocking — warnings guide the user toward adding the review
|
|
1394
|
+
// section without failing doctor.
|
|
1395
|
+
const sliceReviewConfig = parsedConfig?.sliceReview;
|
|
1396
|
+
const sliceReviewEnabled = sliceReviewConfig?.enabled === true;
|
|
1397
|
+
const sliceReviewEnforcedTracks = sliceReviewConfig?.enforceOnTracks ?? ["standard"];
|
|
1398
|
+
const sliceReviewEnforcedHere = sliceReviewEnabled && sliceReviewEnforcedTracks.includes(activeTrack);
|
|
1399
|
+
if (sliceReviewEnforcedHere && tddExists) {
|
|
1400
|
+
const tddMarkdown = await fs.readFile(path.join(artifactsDir, "06-tdd.md"), "utf8");
|
|
1401
|
+
const hasSliceSignal = /^###\s+Slice\b/im.test(tddMarkdown)
|
|
1402
|
+
|| /^##\s+Acceptance Mapping\b/im.test(tddMarkdown)
|
|
1403
|
+
|| /^##\s+RED\b/im.test(tddMarkdown);
|
|
1404
|
+
const hasReviewHeading = /^##\s+Per-Slice Review\b/im.test(tddMarkdown);
|
|
1405
|
+
const missing = hasSliceSignal && !hasReviewHeading;
|
|
1406
|
+
checks.push({
|
|
1407
|
+
name: "warning:slice_review:missing_section",
|
|
1408
|
+
ok: !missing,
|
|
1409
|
+
details: missing
|
|
1410
|
+
? `warning: sliceReview is enabled for track "${activeTrack}" and 06-tdd.md contains slice evidence but no "## Per-Slice Review" section. Add a Per-Slice Review entry for every triggered slice (touchCount >= ${sliceReviewConfig?.filesChangedThreshold ?? 5}, touchPaths match, or highRisk=true), or record "not triggered" explicitly.`
|
|
1411
|
+
: hasReviewHeading
|
|
1412
|
+
? `sliceReview section present in 06-tdd.md (track "${activeTrack}")`
|
|
1413
|
+
: `sliceReview enabled but no slice evidence yet in 06-tdd.md (track "${activeTrack}")`
|
|
1414
|
+
});
|
|
1415
|
+
}
|
|
1385
1416
|
const gateEvidence = await verifyCurrentStageGateEvidence(projectRoot, flowState);
|
|
1386
1417
|
checks.push({
|
|
1387
1418
|
name: "gates:evidence:current_stage",
|
package/dist/install.d.ts
CHANGED
|
@@ -11,7 +11,8 @@ export declare function syncCclaw(projectRoot: string): Promise<void>;
|
|
|
11
11
|
* artifacts, state, or custom config keys. Only the `version` + `flowVersion`
|
|
12
12
|
* stamps are rewritten so the on-disk config reflects the installed CLI;
|
|
13
13
|
* `promptGuardMode`, `tddEnforcement`, `gitHookGuards`, `languageRulePacks`,
|
|
14
|
-
* and `
|
|
14
|
+
* `trackHeuristics`, and `sliceReview` are preserved verbatim from the
|
|
15
|
+
* existing config.
|
|
15
16
|
*
|
|
16
17
|
* For an explicit reset, run `cclaw-cli uninstall && cclaw-cli init`
|
|
17
18
|
* (after optionally archiving the current run via `/cc-ops archive`).
|
package/dist/install.js
CHANGED
|
@@ -1139,7 +1139,8 @@ export async function syncCclaw(projectRoot) {
|
|
|
1139
1139
|
* artifacts, state, or custom config keys. Only the `version` + `flowVersion`
|
|
1140
1140
|
* stamps are rewritten so the on-disk config reflects the installed CLI;
|
|
1141
1141
|
* `promptGuardMode`, `tddEnforcement`, `gitHookGuards`, `languageRulePacks`,
|
|
1142
|
-
* and `
|
|
1142
|
+
* `trackHeuristics`, and `sliceReview` are preserved verbatim from the
|
|
1143
|
+
* existing config.
|
|
1143
1144
|
*
|
|
1144
1145
|
* For an explicit reset, run `cclaw-cli uninstall && cclaw-cli init`
|
|
1145
1146
|
* (after optionally archiving the current run via `/cc-ops archive`).
|
package/dist/types.d.ts
CHANGED
|
@@ -41,6 +41,35 @@ export interface TrackHeuristicsConfig {
|
|
|
41
41
|
/** Per-track matching rules. */
|
|
42
42
|
tracks?: Partial<Record<FlowTrack, TrackHeuristicRule>>;
|
|
43
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Opt-in plan-slice review heuristic.
|
|
46
|
+
*
|
|
47
|
+
* When enabled, the TDD stage skill is instructed to insert a
|
|
48
|
+
* `## Per-Slice Review` section into `06-tdd.md` for every plan slice
|
|
49
|
+
* whose estimated `touchCount` meets `filesChangedThreshold`, whose
|
|
50
|
+
* `touchPaths` match any `touchTriggers` glob, or whose plan row is
|
|
51
|
+
* flagged `highRisk: true`. The section records a short spec-compliance
|
|
52
|
+
* pass plus a short quality pass (delegated to the `reviewer` subagent
|
|
53
|
+
* when the harness supports native dispatch, otherwise fulfilled via
|
|
54
|
+
* an explicit in-session role switch with evidence).
|
|
55
|
+
*
|
|
56
|
+
* Track gating: `enforceOnTracks` lists the tracks where the doctor
|
|
57
|
+
* check escalates to a warning. Tracks outside this list still see
|
|
58
|
+
* the skill prose but leave the decision to the user.
|
|
59
|
+
*
|
|
60
|
+
* All fields optional; sensible defaults: disabled, threshold 5, no
|
|
61
|
+
* touch triggers, `enforceOnTracks: ["standard"]`.
|
|
62
|
+
*/
|
|
63
|
+
export interface SliceReviewConfig {
|
|
64
|
+
/** Turn the heuristic on (disabled by default). */
|
|
65
|
+
enabled?: boolean;
|
|
66
|
+
/** Minimum estimated touchCount for a slice to be eligible. */
|
|
67
|
+
filesChangedThreshold?: number;
|
|
68
|
+
/** Glob hints; any plan-task touchPath match triggers review. */
|
|
69
|
+
touchTriggers?: string[];
|
|
70
|
+
/** Tracks on which missed reviews escalate to a doctor warning. */
|
|
71
|
+
enforceOnTracks?: FlowTrack[];
|
|
72
|
+
}
|
|
44
73
|
export interface VibyConfig {
|
|
45
74
|
version: string;
|
|
46
75
|
flowVersion: string;
|
|
@@ -67,6 +96,14 @@ export interface VibyConfig {
|
|
|
67
96
|
* If omitted, cclaw uses built-in defaults.
|
|
68
97
|
*/
|
|
69
98
|
trackHeuristics?: TrackHeuristicsConfig;
|
|
99
|
+
/**
|
|
100
|
+
* Opt-in per-slice review heuristic. When enabled, the TDD skill
|
|
101
|
+
* requires a `## Per-Slice Review` section in `06-tdd.md` for slices
|
|
102
|
+
* that exceed `filesChangedThreshold` or match `touchTriggers`.
|
|
103
|
+
* Keeps obra's "fresh subagent + spec-then-quality review per task"
|
|
104
|
+
* discipline tractable without forcing it on tiny quick-track fixes.
|
|
105
|
+
*/
|
|
106
|
+
sliceReview?: SliceReviewConfig;
|
|
70
107
|
}
|
|
71
108
|
export interface TransitionRule {
|
|
72
109
|
from: FlowStage;
|