cclaw-cli 3.0.0 → 4.0.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/artifact-linter/brainstorm.js +13 -2
- package/dist/artifact-linter/design.js +14 -3
- package/dist/artifact-linter/scope.js +20 -33
- package/dist/artifact-linter/shared.d.ts +48 -7
- package/dist/artifact-linter/shared.js +130 -55
- package/dist/artifact-linter.d.ts +11 -1
- package/dist/artifact-linter.js +28 -12
- package/dist/content/examples.js +8 -0
- package/dist/content/hooks.js +2 -1
- package/dist/content/review-prompts.js +3 -3
- package/dist/content/skills-elicitation.js +58 -20
- package/dist/content/skills.js +19 -6
- package/dist/content/stage-schema.js +36 -18
- package/dist/content/stages/brainstorm.js +3 -3
- package/dist/content/stages/design.js +2 -2
- package/dist/content/stages/plan.js +1 -1
- package/dist/content/stages/schema-types.d.ts +9 -0
- package/dist/content/stages/scope.js +5 -5
- package/dist/content/templates.d.ts +8 -1
- package/dist/content/templates.js +80 -18
- package/dist/gate-evidence.d.ts +25 -1
- package/dist/gate-evidence.js +34 -3
- package/dist/harness-adapters.js +8 -0
- package/dist/install.js +22 -11
- package/dist/internal/advance-stage/advance.d.ts +1 -0
- package/dist/internal/advance-stage/advance.js +5 -2
- package/package.json +1 -1
|
@@ -307,14 +307,18 @@ RECOMMENDATION: <option letter — one-line rationale tying back to premise chal
|
|
|
307
307
|
> is later dropped, keep the row and mark Priority \`DROPPED\`; if a new one is
|
|
308
308
|
> added mid-flow, append with the next free R-number — do NOT reuse numbers.
|
|
309
309
|
|
|
310
|
-
## Locked Decisions
|
|
311
|
-
|
|
|
310
|
+
## Locked Decisions
|
|
311
|
+
| ID | Decision | Why locked now | Downstream impact |
|
|
312
312
|
|---|---|---|---|
|
|
313
|
-
|
|
|
313
|
+
| D-1 | | | |
|
|
314
314
|
|
|
315
|
-
> Decision
|
|
316
|
-
>
|
|
317
|
-
>
|
|
315
|
+
> Decision IDs are stable \`D-XX\` numbers. Assign once and never renumber across
|
|
316
|
+
> scope/design/spec/plan/review/ship; downstream artifacts reference these IDs
|
|
317
|
+
> verbatim. If a decision is later dropped, keep the row and mark it
|
|
318
|
+
> \`(superseded by D-Y)\`; if a new one is added mid-flow, append with the next
|
|
319
|
+
> free D-number. Wave 22 (v4.0.0) removed the legacy LD#<sha8> hash anchor —
|
|
320
|
+
> existing artifacts with LD# anchors remain valid markdown but the linter only
|
|
321
|
+
> tracks D-XX IDs.
|
|
318
322
|
|
|
319
323
|
## In Scope / Out of Scope
|
|
320
324
|
|
|
@@ -478,7 +482,7 @@ ${MARKDOWN_CODE_FENCE}
|
|
|
478
482
|
> Default path: compact inline synthesis here. Deep/high-risk work may also write \`.cclaw/artifacts/02a-research.md\`.
|
|
479
483
|
|
|
480
484
|
## Architecture Boundaries
|
|
481
|
-
| Component | Responsibility | Requirement Refs (R#) | Decision Refs (
|
|
485
|
+
| Component | Responsibility | Requirement Refs (R#) | Decision Refs (D-XX) | Owner |
|
|
482
486
|
|---|---|---|---|---|
|
|
483
487
|
| | | | | |
|
|
484
488
|
|
|
@@ -540,11 +544,11 @@ ${MARKDOWN_CODE_FENCE}
|
|
|
540
544
|
### Interaction Edge Case Matrix
|
|
541
545
|
| Edge case | Handled? | Design response | Deferred item (if not handled) |
|
|
542
546
|
|---|---|---|---|
|
|
543
|
-
| double-click | yes/no | | None /
|
|
544
|
-
| nav-away-mid-request | yes/no | | None /
|
|
545
|
-
| 10K-result dataset | yes/no | | None /
|
|
546
|
-
| background-job abandonment | yes/no | | None /
|
|
547
|
-
| zombie connection | yes/no | | None /
|
|
547
|
+
| double-click | yes/no | | None / D-XX |
|
|
548
|
+
| nav-away-mid-request | yes/no | | None / D-XX |
|
|
549
|
+
| 10K-result dataset | yes/no | | None / D-XX |
|
|
550
|
+
| background-job abandonment | yes/no | | None / D-XX |
|
|
551
|
+
| zombie connection | yes/no | | None / D-XX |
|
|
548
552
|
|
|
549
553
|
## Security & Threat Model
|
|
550
554
|
| Boundary | Threat | Mitigation | Owner |
|
|
@@ -699,7 +703,7 @@ ${MARKDOWN_CODE_FENCE}
|
|
|
699
703
|
- Drift from upstream (or \`None\`):
|
|
700
704
|
|
|
701
705
|
## Acceptance Criteria
|
|
702
|
-
| ID | Requirement Ref (R#) | Criterion (observable/measurable/falsifiable) | Design Decision Ref (
|
|
706
|
+
| ID | Requirement Ref (R#) | Criterion (observable/measurable/falsifiable) | Design Decision Ref (D-XX) |
|
|
703
707
|
|---|---|---|---|
|
|
704
708
|
| AC-1 | R1 | | |
|
|
705
709
|
|
|
@@ -845,9 +849,9 @@ Execution rule: complete and verify each batch before starting the next batch.
|
|
|
845
849
|
- TDD checkpoint plan: RED commit/checkpoint -> GREEN commit/checkpoint -> REFACTOR commit/checkpoint (or deferred because: )
|
|
846
850
|
|
|
847
851
|
## Locked Decision Coverage
|
|
848
|
-
| Decision Ref (
|
|
852
|
+
| Decision Ref (D-XX) | Source section | Plan tasks implementing decision | Status |
|
|
849
853
|
|---|---|---|---|
|
|
850
|
-
|
|
|
854
|
+
| D-1 | 02-scope.md > Locked Decisions | T-1 | covered |
|
|
851
855
|
|
|
852
856
|
## Risk Assessment
|
|
853
857
|
| Task/Batch | Risk | Likelihood | Impact | Mitigation |
|
|
@@ -870,7 +874,7 @@ Execution rule: complete and verify each batch before starting the next batch.
|
|
|
870
874
|
- Create:
|
|
871
875
|
- Modify:
|
|
872
876
|
- Test:
|
|
873
|
-
- **Approach:** (1-3 sentences; cite design decision DD-# or
|
|
877
|
+
- **Approach:** (1-3 sentences; cite design decision DD-# or scope D-XX)
|
|
874
878
|
- **Patterns to follow:** (link existing files/modules to mirror, or \`- None applicable.\`)
|
|
875
879
|
- **Test scenarios:**
|
|
876
880
|
- Happy:
|
|
@@ -908,7 +912,7 @@ Execution rule: complete and verify each batch before starting the next batch.
|
|
|
908
912
|
- Hits: 0 (required for WAIT_FOR_CONFIRM to resolve).
|
|
909
913
|
- Scope reduction language scan:
|
|
910
914
|
- Scanned phrases: \`v1\`, \`for now\`, \`later\`, \`temporary\`, \`placeholder\`, \`mock for now\`, \`hardcoded for now\`, \`will improve later\`.
|
|
911
|
-
- Hits: 0 (required when Locked Decisions section is non-empty;
|
|
915
|
+
- Hits: 0 (required when Locked Decisions section is non-empty; reference D-XX IDs from scope).
|
|
912
916
|
|
|
913
917
|
## WAIT_FOR_CONFIRM
|
|
914
918
|
- Status: pending
|
|
@@ -1449,6 +1453,60 @@ delegate to a specialized agent or skill if the harness supports it. The primary
|
|
|
1449
1453
|
2. Provide focused context (relevant files, the specific concern)
|
|
1450
1454
|
3. Evaluate the specialist output before acting on it — do not blindly apply recommendations
|
|
1451
1455
|
`;
|
|
1456
|
+
/**
|
|
1457
|
+
* Always-on baseline rule materialized at `.cursor/rules/cclaw-guidelines.mdc`.
|
|
1458
|
+
* Independent of skill activation — kicks in even when the agent skips
|
|
1459
|
+
* loading skills. Three hard rules cover the most common Wave 22 regressions
|
|
1460
|
+
* (premature draft, premature subagent dispatch, command-line echo to chat).
|
|
1461
|
+
*/
|
|
1462
|
+
export const CURSOR_GUIDELINES_RULE_MDC = `---
|
|
1463
|
+
description: cclaw zero-install behavior baseline (always-on)
|
|
1464
|
+
globs:
|
|
1465
|
+
- "**/*"
|
|
1466
|
+
alwaysApply: true
|
|
1467
|
+
---
|
|
1468
|
+
|
|
1469
|
+
<!-- cclaw-managed-cursor-guidelines-rule -->
|
|
1470
|
+
|
|
1471
|
+
# Cclaw Baseline Guidelines
|
|
1472
|
+
|
|
1473
|
+
These three rules apply to every Cursor agent session in this project,
|
|
1474
|
+
regardless of whether stage skills loaded.
|
|
1475
|
+
|
|
1476
|
+
## 1. Q&A floor before drafting (brainstorm/scope/design)
|
|
1477
|
+
|
|
1478
|
+
Before drafting any \`.cclaw/artifacts/01-brainstorm-*.md\`,
|
|
1479
|
+
\`02-scope-*.md\`, or \`03-design-*.md\`, verify that the artifact's
|
|
1480
|
+
\`## Q&A Log\` table contains at least the floor count for the active track
|
|
1481
|
+
(see \`questionBudgetHint(track, stage).min\`). Walk the stage forcing
|
|
1482
|
+
questions one at a time via the \`AskQuestion\` tool. If you find yourself
|
|
1483
|
+
proposing a draft after 1-2 questions, STOP and continue the loop.
|
|
1484
|
+
|
|
1485
|
+
The \`qa_log_below_min\` linter rule will block \`stage-complete\` when below
|
|
1486
|
+
floor unless an explicit user stop-signal row is recorded.
|
|
1487
|
+
|
|
1488
|
+
## 2. Mandatory subagents run after Q&A approval
|
|
1489
|
+
|
|
1490
|
+
For brainstorm / scope / design, mandatory subagents (
|
|
1491
|
+
\`product-discovery\`, \`critic\`, \`planner\`, \`architect\`,
|
|
1492
|
+
\`test-author\`) run **only AFTER the user approves the elicitation
|
|
1493
|
+
outcome**, never before the Q&A loop converges. Dispatching them early
|
|
1494
|
+
preempts the user dialogue and violates the elicitation contract — the
|
|
1495
|
+
linter will block stage-complete.
|
|
1496
|
+
|
|
1497
|
+
See each stage's "Run Phase: post-elicitation" rows in the materialized
|
|
1498
|
+
Automatic Subagent Dispatch table.
|
|
1499
|
+
|
|
1500
|
+
## 3. Never echo cclaw command lines to chat
|
|
1501
|
+
|
|
1502
|
+
The user does not run cclaw helpers (\`node .cclaw/hooks/...\`) manually.
|
|
1503
|
+
NEVER paste full command lines, \`--evidence-json '{...}'\` payloads,
|
|
1504
|
+
\`--waive-delegation=...\`, or shell hash commands (\`shasum\`,
|
|
1505
|
+
\`sha256sum\`, \`Get-FileHash\`, \`certutil\`, etc.) into chat. Run the
|
|
1506
|
+
helper via the tool layer and report only the resulting summary. On
|
|
1507
|
+
failure, report a compact human-readable summary plus the helper JSON in
|
|
1508
|
+
a single fenced \`json\` block.
|
|
1509
|
+
`;
|
|
1452
1510
|
export const CURSOR_WORKFLOW_RULE_MDC = `---
|
|
1453
1511
|
description: cclaw workflow guardrails for Cursor agent sessions
|
|
1454
1512
|
globs:
|
|
@@ -1497,7 +1555,11 @@ Track-specific skips are allowed only when \`flow-state.track\` + \`skippedStage
|
|
|
1497
1555
|
## Delegation And Approvals
|
|
1498
1556
|
|
|
1499
1557
|
- Machine-only checks in design/plan/tdd/review/ship should auto-dispatch when tooling supports it.
|
|
1500
|
-
-
|
|
1558
|
+
- **For brainstorm / scope / design stages**: ask user input continuously via adaptive elicitation (one question per turn through the harness-native question tool — \`AskQuestion\` in Cursor). Walk the stage forcing-questions list one-by-one. Do NOT batch and do NOT defer to a single approval gate at the end. The \`qa_log_below_min\` linter rule will block \`stage-complete\` when below floor.
|
|
1559
|
+
- **For other stages** (spec/plan/tdd/build/review/ship): ask user input only at explicit approval gates (scope mode, plan approval, challenge resolution, ship finalization), not for routine progress updates.
|
|
1560
|
+
- If you find yourself proposing a draft after 1-2 questions in brainstorm/scope/design, STOP — go back to the forcing-questions list and continue.
|
|
1561
|
+
- Mandatory subagents in brainstorm/scope/design run only AFTER the user approves the elicitation outcome (see each stage's "Run Phase: post-elicitation" rows). Dispatching them before the Q&A loop converges violates the contract.
|
|
1562
|
+
- Never echo cclaw command lines (\`node .cclaw/hooks/...\`, \`--evidence-json '{...}'\`) to chat — the user does not run cclaw manually. Run helpers via the tool layer; report only the resulting summary.
|
|
1501
1563
|
- If harness capabilities are partial, record waiver reasons in delegation logs.
|
|
1502
1564
|
|
|
1503
1565
|
## Routing Source Of Truth
|
package/dist/gate-evidence.d.ts
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
import type { FlowState, StageGateState } from "./flow-state.js";
|
|
2
2
|
import { type FlowStage } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Structured signal for the harness UI describing the adaptive
|
|
5
|
+
* elicitation Q&A floor for the current stage. Always present on
|
|
6
|
+
* brainstorm/scope/design verifications; null on other stages.
|
|
7
|
+
*
|
|
8
|
+
* Mirrors the `evaluateQaLogFloor` linter helper. Harness can render
|
|
9
|
+
* `count / min` progress, surface stop-signal/skip-questions hints, and
|
|
10
|
+
* differentiate between blocking and advisory.
|
|
11
|
+
*/
|
|
12
|
+
export interface QaLogFloorSignal {
|
|
13
|
+
ok: boolean;
|
|
14
|
+
count: number;
|
|
15
|
+
min: number;
|
|
16
|
+
hasStopSignal: boolean;
|
|
17
|
+
liteShortCircuit: boolean;
|
|
18
|
+
skipQuestionsAdvisory: boolean;
|
|
19
|
+
blocking: boolean;
|
|
20
|
+
}
|
|
3
21
|
export interface GateEvidenceCheckResult {
|
|
4
22
|
ok: boolean;
|
|
5
23
|
stage: FlowStage;
|
|
@@ -18,6 +36,8 @@ export interface GateEvidenceCheckResult {
|
|
|
18
36
|
missingRecommended: string[];
|
|
19
37
|
/** Triggered conditional gates that are not yet passed. */
|
|
20
38
|
missingTriggeredConditional: string[];
|
|
39
|
+
/** Q&A floor signal for adaptive elicitation stages, null otherwise. */
|
|
40
|
+
qaLogFloor: QaLogFloorSignal | null;
|
|
21
41
|
}
|
|
22
42
|
export interface CompletedStagesClosureResult {
|
|
23
43
|
ok: boolean;
|
|
@@ -29,7 +49,11 @@ export interface CompletedStagesClosureResult {
|
|
|
29
49
|
blocked: string[];
|
|
30
50
|
}>;
|
|
31
51
|
}
|
|
32
|
-
export
|
|
52
|
+
export interface VerifyCurrentStageGateEvidenceOptions {
|
|
53
|
+
/** Extra stage flags propagated from the in-flight CLI args (e.g. `--skip-questions`). */
|
|
54
|
+
extraStageFlags?: string[];
|
|
55
|
+
}
|
|
56
|
+
export declare function verifyCurrentStageGateEvidence(projectRoot: string, flowState: FlowState, options?: VerifyCurrentStageGateEvidenceOptions): Promise<GateEvidenceCheckResult>;
|
|
33
57
|
export declare function verifyCompletedStagesGateClosure(flowState: FlowState): CompletedStagesClosureResult;
|
|
34
58
|
export interface GateReconciliationResult {
|
|
35
59
|
stage: FlowStage;
|
package/dist/gate-evidence.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { checkReviewSecurityNoChangeAttestation, checkReviewVerdictConsistency, extractMarkdownSectionBody, lintArtifact, validateReviewArmy } from "./artifact-linter.js";
|
|
4
|
+
import { ELICITATION_STAGES, evaluateQaLogFloor } from "./artifact-linter/shared.js";
|
|
4
5
|
import { resolveArtifactPath } from "./artifact-paths.js";
|
|
5
6
|
import { RUNTIME_ROOT } from "./constants.js";
|
|
6
7
|
import { stageSchema } from "./content/stage-schema.js";
|
|
@@ -207,7 +208,7 @@ const DESIGN_RESEARCH_REQUIRED_SECTIONS = [
|
|
|
207
208
|
"Pitfalls & Risks",
|
|
208
209
|
"Synthesis"
|
|
209
210
|
];
|
|
210
|
-
export async function verifyCurrentStageGateEvidence(projectRoot, flowState) {
|
|
211
|
+
export async function verifyCurrentStageGateEvidence(projectRoot, flowState, options = {}) {
|
|
211
212
|
const stage = flowState.currentStage;
|
|
212
213
|
const schema = stageSchema(stage, flowState.track);
|
|
213
214
|
const catalog = flowState.stageGateCatalog[stage];
|
|
@@ -283,7 +284,9 @@ export async function verifyCurrentStageGateEvidence(projectRoot, flowState) {
|
|
|
283
284
|
const artifactPresent = await currentStageArtifactExists(projectRoot, stage, flowState.track);
|
|
284
285
|
const shouldValidateArtifact = artifactPresent || catalog.passed.length > 0 || flowState.completedStages.includes(stage);
|
|
285
286
|
if (shouldValidateArtifact) {
|
|
286
|
-
const lint = await lintArtifact(projectRoot, stage, flowState.track
|
|
287
|
+
const lint = await lintArtifact(projectRoot, stage, flowState.track, {
|
|
288
|
+
extraStageFlags: options.extraStageFlags
|
|
289
|
+
});
|
|
287
290
|
if (!lint.passed) {
|
|
288
291
|
const failedRequiredFindings = lint.findings
|
|
289
292
|
.filter((finding) => finding.required && !finding.found);
|
|
@@ -444,6 +447,33 @@ export async function verifyCurrentStageGateEvidence(projectRoot, flowState) {
|
|
|
444
447
|
issues.push(`stage "${stage}" is marked completed but has blocking blocked gates: ${blockingBlocked.join(", ")}.`);
|
|
445
448
|
}
|
|
446
449
|
}
|
|
450
|
+
let qaLogFloor = null;
|
|
451
|
+
if (ELICITATION_STAGES.has(stage)) {
|
|
452
|
+
let qaLogBody = null;
|
|
453
|
+
try {
|
|
454
|
+
const stageMd = await readStageArtifactMarkdown(projectRoot, stage, flowState.track);
|
|
455
|
+
qaLogBody = stageMd
|
|
456
|
+
? extractMarkdownSectionBody(stageMd, "Q&A Log")
|
|
457
|
+
: null;
|
|
458
|
+
}
|
|
459
|
+
catch {
|
|
460
|
+
qaLogBody = null;
|
|
461
|
+
}
|
|
462
|
+
const skipQuestionsHint = flowState.interactionHints?.[stage]?.skipQuestions === true ||
|
|
463
|
+
(options.extraStageFlags ?? []).includes("--skip-questions");
|
|
464
|
+
const floor = evaluateQaLogFloor(qaLogBody, flowState.track, stage, {
|
|
465
|
+
skipQuestions: skipQuestionsHint
|
|
466
|
+
});
|
|
467
|
+
qaLogFloor = {
|
|
468
|
+
ok: floor.ok,
|
|
469
|
+
count: floor.count,
|
|
470
|
+
min: floor.min,
|
|
471
|
+
hasStopSignal: floor.hasStopSignal,
|
|
472
|
+
liteShortCircuit: floor.liteShortCircuit,
|
|
473
|
+
skipQuestionsAdvisory: floor.skipQuestionsAdvisory,
|
|
474
|
+
blocking: !floor.ok && !floor.skipQuestionsAdvisory
|
|
475
|
+
};
|
|
476
|
+
}
|
|
447
477
|
return {
|
|
448
478
|
ok: issues.length === 0,
|
|
449
479
|
stage,
|
|
@@ -457,7 +487,8 @@ export async function verifyCurrentStageGateEvidence(projectRoot, flowState) {
|
|
|
457
487
|
complete,
|
|
458
488
|
missingRequired,
|
|
459
489
|
missingRecommended,
|
|
460
|
-
missingTriggeredConditional
|
|
490
|
+
missingTriggeredConditional,
|
|
491
|
+
qaLogFloor
|
|
461
492
|
};
|
|
462
493
|
}
|
|
463
494
|
export function verifyCompletedStagesGateClosure(flowState) {
|
package/dist/harness-adapters.js
CHANGED
|
@@ -345,6 +345,14 @@ Before responding to a coding request:
|
|
|
345
345
|
2. Use \`/cc\` to start, resume, or continue the flow.
|
|
346
346
|
3. If no stage applies, respond normally.
|
|
347
347
|
|
|
348
|
+
### Cclaw Baseline (always-on)
|
|
349
|
+
|
|
350
|
+
Three rules apply to every cclaw stage in this project, regardless of which skills loaded:
|
|
351
|
+
|
|
352
|
+
1. **Q&A floor before drafting** — for brainstorm / scope / design, walk the stage forcing questions one at a time via the harness-native question tool (Claude \`AskUserQuestion\`, Cursor \`AskQuestion\`, Codex \`request_user_input\`, Gemini \`ask_user\`). The \`qa_log_below_min\` linter rule will block \`stage-complete\` when the artifact's \`## Q&A Log\` is below \`questionBudgetHint(track, stage).min\` unless an explicit user stop-signal row is recorded.
|
|
353
|
+
2. **Subagents run after Q&A approval** — mandatory subagents in brainstorm / scope / design (\`product-discovery\`, \`critic\`, \`planner\`, \`architect\`, \`test-author\`) run only AFTER the user approves the elicitation outcome. See each stage's "Run Phase: post-elicitation" rows in the materialized Automatic Subagent Dispatch table.
|
|
354
|
+
3. **No command-line echo to chat** — the user does not run cclaw helpers manually. Never paste \`node .cclaw/hooks/...\` invocations, \`--evidence-json '{...}'\` payloads, or shell hash commands (\`shasum\`, \`sha256sum\`, \`Get-FileHash\`, \`certutil\`, etc.) into chat. Run helpers via the tool layer; report only the resulting summary.
|
|
355
|
+
|
|
348
356
|
${ironLawsAgentsMdBlock()}
|
|
349
357
|
|
|
350
358
|
### Task Classification (before \`/cc\`)
|
package/dist/install.js
CHANGED
|
@@ -16,7 +16,7 @@ import { ironLawsSkillMarkdown } from "./content/iron-laws.js";
|
|
|
16
16
|
import { stageCompleteScript, startFlowScript, cancelRunScript, runHookCmdScript, delegationRecordScript, opencodePluginJs, claudeHooksJson, codexHooksJson, cursorHooksJson } from "./content/hooks.js";
|
|
17
17
|
import { nodeHookRuntimeScript } from "./content/node-hooks.js";
|
|
18
18
|
import { META_SKILL_NAME, usingCclawSkillMarkdown } from "./content/meta-skill.js";
|
|
19
|
-
import { ARTIFACT_TEMPLATES, CURSOR_WORKFLOW_RULE_MDC, RULEBOOK_MARKDOWN, buildRulesJson } from "./content/templates.js";
|
|
19
|
+
import { ARTIFACT_TEMPLATES, CURSOR_GUIDELINES_RULE_MDC, CURSOR_WORKFLOW_RULE_MDC, RULEBOOK_MARKDOWN, buildRulesJson } from "./content/templates.js";
|
|
20
20
|
import { STATE_CONTRACTS } from "./content/state-contracts.js";
|
|
21
21
|
import { REVIEW_PROMPTS } from "./content/review-prompts.js";
|
|
22
22
|
import { stageSkillFolder, stageSkillMarkdown, executingWavesSkillMarkdown } from "./content/skills.js";
|
|
@@ -37,6 +37,7 @@ import { CorruptFlowStateError, ensureRunSystem } from "./runs.js";
|
|
|
37
37
|
import { FLOW_STAGES } from "./types.js";
|
|
38
38
|
const OPENCODE_PLUGIN_REL_PATH = ".opencode/plugins/cclaw-plugin.mjs";
|
|
39
39
|
const CURSOR_RULE_REL_PATH = ".cursor/rules/cclaw-workflow.mdc";
|
|
40
|
+
const CURSOR_GUIDELINES_REL_PATH = ".cursor/rules/cclaw-guidelines.mdc";
|
|
40
41
|
const GIT_HOOK_MANAGED_MARKER = "cclaw-managed-git-hook";
|
|
41
42
|
const GIT_HOOK_RUNTIME_REL_DIR = `${RUNTIME_ROOT}/hooks/git`;
|
|
42
43
|
const INIT_SENTINEL_FILE = ".init-in-progress";
|
|
@@ -942,17 +943,22 @@ async function writeRulebook(projectRoot) {
|
|
|
942
943
|
}
|
|
943
944
|
async function writeCursorWorkflowRule(projectRoot, harnesses) {
|
|
944
945
|
const rulePath = path.join(projectRoot, CURSOR_RULE_REL_PATH);
|
|
946
|
+
const guidelinesPath = path.join(projectRoot, CURSOR_GUIDELINES_REL_PATH);
|
|
945
947
|
if (!harnesses.includes("cursor")) {
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
948
|
+
for (const target of [rulePath, guidelinesPath]) {
|
|
949
|
+
try {
|
|
950
|
+
await fs.rm(target, { force: true });
|
|
951
|
+
}
|
|
952
|
+
catch {
|
|
953
|
+
// best-effort cleanup
|
|
954
|
+
}
|
|
951
955
|
}
|
|
952
956
|
return;
|
|
953
957
|
}
|
|
954
958
|
await ensureDir(path.dirname(rulePath));
|
|
955
959
|
await writeFileSafe(rulePath, CURSOR_WORKFLOW_RULE_MDC);
|
|
960
|
+
await ensureDir(path.dirname(guidelinesPath));
|
|
961
|
+
await writeFileSafe(guidelinesPath, CURSOR_GUIDELINES_RULE_MDC);
|
|
956
962
|
}
|
|
957
963
|
async function syncDisabledHarnessArtifacts(projectRoot, harnesses) {
|
|
958
964
|
const enabled = new Set(harnesses);
|
|
@@ -1464,11 +1470,16 @@ export async function uninstallCclaw(projectRoot) {
|
|
|
1464
1470
|
}
|
|
1465
1471
|
}
|
|
1466
1472
|
await removeManagedOpenCodePluginConfig(projectRoot, OPENCODE_PLUGIN_REL_PATH);
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1473
|
+
for (const target of [
|
|
1474
|
+
path.join(projectRoot, CURSOR_RULE_REL_PATH),
|
|
1475
|
+
path.join(projectRoot, CURSOR_GUIDELINES_REL_PATH)
|
|
1476
|
+
]) {
|
|
1477
|
+
try {
|
|
1478
|
+
await fs.rm(target, { force: true });
|
|
1479
|
+
}
|
|
1480
|
+
catch {
|
|
1481
|
+
// best-effort cleanup
|
|
1482
|
+
}
|
|
1472
1483
|
}
|
|
1473
1484
|
const managedDirs = [
|
|
1474
1485
|
".claude/hooks",
|
|
@@ -35,6 +35,7 @@ interface InternalValidationReport {
|
|
|
35
35
|
export declare function hydrateReviewLoopEvidenceFromArtifact(projectRoot: string, stage: FlowStage, track: FlowState["track"], selectedGateIds: string[], evidenceByGate: Record<string, string>): Promise<void>;
|
|
36
36
|
export declare function buildValidationReport(projectRoot: string, flowState: FlowState, options?: {
|
|
37
37
|
allowBlockedReviewRoute?: boolean;
|
|
38
|
+
extraStageFlags?: string[];
|
|
38
39
|
}): Promise<InternalValidationReport>;
|
|
39
40
|
interface HarvestLearningsResult {
|
|
40
41
|
ok: boolean;
|
|
@@ -89,7 +89,9 @@ export async function hydrateReviewLoopEvidenceFromArtifact(projectRoot, stage,
|
|
|
89
89
|
}
|
|
90
90
|
export async function buildValidationReport(projectRoot, flowState, options = {}) {
|
|
91
91
|
const delegation = await checkMandatoryDelegations(projectRoot, flowState.currentStage);
|
|
92
|
-
const gates = await verifyCurrentStageGateEvidence(projectRoot, flowState
|
|
92
|
+
const gates = await verifyCurrentStageGateEvidence(projectRoot, flowState, {
|
|
93
|
+
extraStageFlags: options.extraStageFlags
|
|
94
|
+
});
|
|
93
95
|
const completedStages = verifyCompletedStagesGateClosure(flowState);
|
|
94
96
|
const blockedReviewRouteComplete = options.allowBlockedReviewRoute === true
|
|
95
97
|
&& flowState.currentStage === "review"
|
|
@@ -332,7 +334,8 @@ export async function runAdvanceStage(projectRoot, args, io) {
|
|
|
332
334
|
}
|
|
333
335
|
};
|
|
334
336
|
const validation = await buildValidationReport(projectRoot, candidateState, {
|
|
335
|
-
allowBlockedReviewRoute: blockedReviewRoute
|
|
337
|
+
allowBlockedReviewRoute: blockedReviewRoute,
|
|
338
|
+
extraStageFlags: args.skipQuestions ? ["--skip-questions"] : undefined
|
|
336
339
|
});
|
|
337
340
|
if (!validation.ok) {
|
|
338
341
|
const ledgerForDiag = await readDelegationLedger(projectRoot).catch(() => ({ entries: [] }));
|