cclaw-cli 7.7.1 → 8.1.1
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/README.md +211 -134
- package/dist/artifact-frontmatter.d.ts +51 -0
- package/dist/artifact-frontmatter.js +131 -0
- package/dist/artifact-paths.d.ts +7 -27
- package/dist/artifact-paths.js +20 -249
- package/dist/cancel.d.ts +16 -0
- package/dist/cancel.js +66 -0
- package/dist/cli.d.ts +2 -27
- package/dist/cli.js +107 -511
- package/dist/compound.d.ts +26 -0
- package/dist/compound.js +96 -0
- package/dist/config.d.ts +14 -51
- package/dist/config.js +23 -359
- package/dist/constants.d.ts +11 -18
- package/dist/constants.js +19 -106
- package/dist/content/antipatterns.d.ts +1 -0
- package/dist/content/antipatterns.js +109 -0
- package/dist/content/artifact-templates.d.ts +10 -0
- package/dist/content/artifact-templates.js +550 -0
- package/dist/content/cancel-command.d.ts +2 -2
- package/dist/content/cancel-command.js +25 -17
- package/dist/content/core-agents.d.ts +9 -233
- package/dist/content/core-agents.js +39 -768
- package/dist/content/decision-protocol.d.ts +1 -12
- package/dist/content/decision-protocol.js +27 -20
- package/dist/content/examples.d.ts +8 -42
- package/dist/content/examples.js +293 -425
- package/dist/content/idea-command.d.ts +2 -0
- package/dist/content/idea-command.js +38 -0
- package/dist/content/iron-laws.d.ts +4 -138
- package/dist/content/iron-laws.js +18 -197
- package/dist/content/meta-skill.d.ts +1 -3
- package/dist/content/meta-skill.js +57 -134
- package/dist/content/node-hooks.d.ts +12 -8
- package/dist/content/node-hooks.js +188 -838
- package/dist/content/recovery.d.ts +8 -0
- package/dist/content/recovery.js +179 -0
- package/dist/content/reference-patterns.d.ts +4 -13
- package/dist/content/reference-patterns.js +260 -389
- package/dist/content/research-playbooks.d.ts +8 -8
- package/dist/content/research-playbooks.js +108 -121
- package/dist/content/review-loop.d.ts +6 -192
- package/dist/content/review-loop.js +29 -731
- package/dist/content/skills.d.ts +8 -38
- package/dist/content/skills.js +681 -732
- package/dist/content/specialist-prompts/architect.d.ts +1 -0
- package/dist/content/specialist-prompts/architect.js +225 -0
- package/dist/content/specialist-prompts/brainstormer.d.ts +1 -0
- package/dist/content/specialist-prompts/brainstormer.js +168 -0
- package/dist/content/specialist-prompts/index.d.ts +2 -0
- package/dist/content/specialist-prompts/index.js +14 -0
- package/dist/content/specialist-prompts/planner.d.ts +1 -0
- package/dist/content/specialist-prompts/planner.js +182 -0
- package/dist/content/specialist-prompts/reviewer.d.ts +1 -0
- package/dist/content/specialist-prompts/reviewer.js +193 -0
- package/dist/content/specialist-prompts/security-reviewer.d.ts +1 -0
- package/dist/content/specialist-prompts/security-reviewer.js +133 -0
- package/dist/content/specialist-prompts/slice-builder.d.ts +1 -0
- package/dist/content/specialist-prompts/slice-builder.js +232 -0
- package/dist/content/stage-playbooks.d.ts +8 -0
- package/dist/content/stage-playbooks.js +404 -0
- package/dist/content/start-command.d.ts +2 -12
- package/dist/content/start-command.js +221 -207
- package/dist/flow-state.d.ts +21 -178
- package/dist/flow-state.js +67 -170
- package/dist/fs-utils.d.ts +6 -26
- package/dist/fs-utils.js +29 -162
- package/dist/gitignore.d.ts +2 -1
- package/dist/gitignore.js +51 -34
- package/dist/harness-detect.d.ts +10 -0
- package/dist/harness-detect.js +29 -0
- package/dist/harness-prompt.d.ts +26 -0
- package/dist/harness-prompt.js +142 -0
- package/dist/install.d.ts +35 -15
- package/dist/install.js +238 -1347
- package/dist/knowledge-store.d.ts +19 -163
- package/dist/knowledge-store.js +56 -590
- package/dist/logger.d.ts +8 -3
- package/dist/logger.js +13 -4
- package/dist/orchestrator-routing.d.ts +29 -0
- package/dist/orchestrator-routing.js +156 -0
- package/dist/run-persistence.d.ts +7 -118
- package/dist/run-persistence.js +29 -845
- package/dist/runtime/run-hook.entry.d.ts +1 -3
- package/dist/runtime/run-hook.entry.js +19 -4
- package/dist/runtime/run-hook.mjs +13 -1024
- package/dist/types.d.ts +25 -261
- package/dist/types.js +8 -36
- package/package.json +6 -3
- package/dist/artifact-linter/brainstorm.d.ts +0 -2
- package/dist/artifact-linter/brainstorm.js +0 -353
- package/dist/artifact-linter/design.d.ts +0 -18
- package/dist/artifact-linter/design.js +0 -444
- package/dist/artifact-linter/findings-dedup.d.ts +0 -56
- package/dist/artifact-linter/findings-dedup.js +0 -232
- package/dist/artifact-linter/plan.d.ts +0 -2
- package/dist/artifact-linter/plan.js +0 -826
- package/dist/artifact-linter/review-army.d.ts +0 -49
- package/dist/artifact-linter/review-army.js +0 -520
- package/dist/artifact-linter/review.d.ts +0 -2
- package/dist/artifact-linter/review.js +0 -113
- package/dist/artifact-linter/scope.d.ts +0 -2
- package/dist/artifact-linter/scope.js +0 -158
- package/dist/artifact-linter/shared.d.ts +0 -637
- package/dist/artifact-linter/shared.js +0 -2163
- package/dist/artifact-linter/ship.d.ts +0 -2
- package/dist/artifact-linter/ship.js +0 -250
- package/dist/artifact-linter/spec.d.ts +0 -2
- package/dist/artifact-linter/spec.js +0 -176
- package/dist/artifact-linter/tdd.d.ts +0 -118
- package/dist/artifact-linter/tdd.js +0 -1404
- package/dist/artifact-linter.d.ts +0 -15
- package/dist/artifact-linter.js +0 -517
- package/dist/codex-feature-flag.d.ts +0 -58
- package/dist/codex-feature-flag.js +0 -193
- package/dist/content/closeout-guidance.d.ts +0 -14
- package/dist/content/closeout-guidance.js +0 -44
- package/dist/content/diff-command.d.ts +0 -1
- package/dist/content/diff-command.js +0 -43
- package/dist/content/harness-doc.d.ts +0 -1
- package/dist/content/harness-doc.js +0 -65
- package/dist/content/hook-events.d.ts +0 -9
- package/dist/content/hook-events.js +0 -23
- package/dist/content/hook-manifest.d.ts +0 -81
- package/dist/content/hook-manifest.js +0 -156
- package/dist/content/hooks.d.ts +0 -11
- package/dist/content/hooks.js +0 -1972
- package/dist/content/idea.d.ts +0 -60
- package/dist/content/idea.js +0 -416
- package/dist/content/language-policy.d.ts +0 -2
- package/dist/content/language-policy.js +0 -13
- package/dist/content/learnings.d.ts +0 -6
- package/dist/content/learnings.js +0 -141
- package/dist/content/observe.d.ts +0 -19
- package/dist/content/observe.js +0 -86
- package/dist/content/opencode-plugin.d.ts +0 -1
- package/dist/content/opencode-plugin.js +0 -635
- package/dist/content/review-prompts.d.ts +0 -1
- package/dist/content/review-prompts.js +0 -104
- package/dist/content/runtime-shared-snippets.d.ts +0 -8
- package/dist/content/runtime-shared-snippets.js +0 -80
- package/dist/content/session-hooks.d.ts +0 -7
- package/dist/content/session-hooks.js +0 -107
- package/dist/content/skills-elicitation.d.ts +0 -1
- package/dist/content/skills-elicitation.js +0 -167
- package/dist/content/stage-command.d.ts +0 -2
- package/dist/content/stage-command.js +0 -17
- package/dist/content/stage-schema.d.ts +0 -117
- package/dist/content/stage-schema.js +0 -955
- package/dist/content/stages/_lint-metadata/index.d.ts +0 -2
- package/dist/content/stages/_lint-metadata/index.js +0 -97
- package/dist/content/stages/brainstorm.d.ts +0 -2
- package/dist/content/stages/brainstorm.js +0 -184
- package/dist/content/stages/design.d.ts +0 -2
- package/dist/content/stages/design.js +0 -288
- package/dist/content/stages/index.d.ts +0 -8
- package/dist/content/stages/index.js +0 -11
- package/dist/content/stages/plan.d.ts +0 -2
- package/dist/content/stages/plan.js +0 -191
- package/dist/content/stages/review.d.ts +0 -2
- package/dist/content/stages/review.js +0 -240
- package/dist/content/stages/schema-types.d.ts +0 -203
- package/dist/content/stages/schema-types.js +0 -1
- package/dist/content/stages/scope.d.ts +0 -2
- package/dist/content/stages/scope.js +0 -254
- package/dist/content/stages/ship.d.ts +0 -2
- package/dist/content/stages/ship.js +0 -159
- package/dist/content/stages/spec.d.ts +0 -2
- package/dist/content/stages/spec.js +0 -170
- package/dist/content/stages/tdd.d.ts +0 -4
- package/dist/content/stages/tdd.js +0 -273
- package/dist/content/state-contracts.d.ts +0 -1
- package/dist/content/state-contracts.js +0 -63
- package/dist/content/status-command.d.ts +0 -4
- package/dist/content/status-command.js +0 -109
- package/dist/content/subagent-context-skills.d.ts +0 -4
- package/dist/content/subagent-context-skills.js +0 -279
- package/dist/content/subagents.d.ts +0 -3
- package/dist/content/subagents.js +0 -997
- package/dist/content/templates.d.ts +0 -26
- package/dist/content/templates.js +0 -1692
- package/dist/content/track-render-context.d.ts +0 -18
- package/dist/content/track-render-context.js +0 -53
- package/dist/content/tree-command.d.ts +0 -1
- package/dist/content/tree-command.js +0 -64
- package/dist/content/utility-skills.d.ts +0 -30
- package/dist/content/utility-skills.js +0 -160
- package/dist/content/view-command.d.ts +0 -2
- package/dist/content/view-command.js +0 -92
- package/dist/delegation.d.ts +0 -649
- package/dist/delegation.js +0 -1539
- package/dist/early-loop.d.ts +0 -70
- package/dist/early-loop.js +0 -302
- package/dist/execution-topology.d.ts +0 -44
- package/dist/execution-topology.js +0 -95
- package/dist/gate-evidence.d.ts +0 -85
- package/dist/gate-evidence.js +0 -631
- package/dist/harness-adapters.d.ts +0 -151
- package/dist/harness-adapters.js +0 -756
- package/dist/harness-selection.d.ts +0 -31
- package/dist/harness-selection.js +0 -214
- package/dist/hook-schema.d.ts +0 -6
- package/dist/hook-schema.js +0 -114
- package/dist/hook-schemas/claude-hooks.v1.json +0 -10
- package/dist/hook-schemas/codex-hooks.v1.json +0 -10
- package/dist/hook-schemas/cursor-hooks.v1.json +0 -13
- package/dist/init-detect.d.ts +0 -2
- package/dist/init-detect.js +0 -50
- package/dist/internal/advance-stage/advance.d.ts +0 -89
- package/dist/internal/advance-stage/advance.js +0 -655
- package/dist/internal/advance-stage/cancel-run.d.ts +0 -8
- package/dist/internal/advance-stage/cancel-run.js +0 -19
- package/dist/internal/advance-stage/flow-state-coercion.d.ts +0 -3
- package/dist/internal/advance-stage/flow-state-coercion.js +0 -81
- package/dist/internal/advance-stage/helpers.d.ts +0 -14
- package/dist/internal/advance-stage/helpers.js +0 -145
- package/dist/internal/advance-stage/hook.d.ts +0 -8
- package/dist/internal/advance-stage/hook.js +0 -40
- package/dist/internal/advance-stage/parsers.d.ts +0 -72
- package/dist/internal/advance-stage/parsers.js +0 -357
- package/dist/internal/advance-stage/proactive-delegation-trace.d.ts +0 -24
- package/dist/internal/advance-stage/proactive-delegation-trace.js +0 -56
- package/dist/internal/advance-stage/review-loop.d.ts +0 -16
- package/dist/internal/advance-stage/review-loop.js +0 -199
- package/dist/internal/advance-stage/rewind.d.ts +0 -14
- package/dist/internal/advance-stage/rewind.js +0 -108
- package/dist/internal/advance-stage/start-flow.d.ts +0 -13
- package/dist/internal/advance-stage/start-flow.js +0 -241
- package/dist/internal/advance-stage/verify.d.ts +0 -21
- package/dist/internal/advance-stage/verify.js +0 -185
- package/dist/internal/advance-stage.d.ts +0 -7
- package/dist/internal/advance-stage.js +0 -138
- package/dist/internal/cohesion-contract-stub.d.ts +0 -24
- package/dist/internal/cohesion-contract-stub.js +0 -148
- package/dist/internal/compound-readiness.d.ts +0 -23
- package/dist/internal/compound-readiness.js +0 -102
- package/dist/internal/detect-public-api-changes.d.ts +0 -5
- package/dist/internal/detect-public-api-changes.js +0 -45
- package/dist/internal/detect-supply-chain-changes.d.ts +0 -6
- package/dist/internal/detect-supply-chain-changes.js +0 -138
- package/dist/internal/early-loop-status.d.ts +0 -7
- package/dist/internal/early-loop-status.js +0 -93
- package/dist/internal/envelope-validate.d.ts +0 -7
- package/dist/internal/envelope-validate.js +0 -66
- package/dist/internal/flow-state-repair.d.ts +0 -20
- package/dist/internal/flow-state-repair.js +0 -104
- package/dist/internal/plan-split-waves.d.ts +0 -190
- package/dist/internal/plan-split-waves.js +0 -764
- package/dist/internal/runtime-integrity.d.ts +0 -7
- package/dist/internal/runtime-integrity.js +0 -268
- package/dist/internal/slice-commit.d.ts +0 -7
- package/dist/internal/slice-commit.js +0 -619
- package/dist/internal/tdd-loop-status.d.ts +0 -14
- package/dist/internal/tdd-loop-status.js +0 -68
- package/dist/internal/tdd-red-evidence.d.ts +0 -7
- package/dist/internal/tdd-red-evidence.js +0 -153
- package/dist/internal/waiver-grant.d.ts +0 -62
- package/dist/internal/waiver-grant.js +0 -294
- package/dist/internal/wave-status.d.ts +0 -74
- package/dist/internal/wave-status.js +0 -506
- package/dist/managed-resources.d.ts +0 -53
- package/dist/managed-resources.js +0 -313
- package/dist/policy.d.ts +0 -10
- package/dist/policy.js +0 -167
- package/dist/retro-gate.d.ts +0 -9
- package/dist/retro-gate.js +0 -47
- package/dist/run-archive.d.ts +0 -61
- package/dist/run-archive.js +0 -391
- package/dist/runs.d.ts +0 -2
- package/dist/runs.js +0 -2
- package/dist/stack-detection.d.ts +0 -116
- package/dist/stack-detection.js +0 -489
- package/dist/streaming/event-stream.d.ts +0 -31
- package/dist/streaming/event-stream.js +0 -114
- package/dist/tdd-cycle.d.ts +0 -107
- package/dist/tdd-cycle.js +0 -289
- package/dist/tdd-verification-evidence.d.ts +0 -17
- package/dist/tdd-verification-evidence.js +0 -122
- package/dist/track-heuristics.d.ts +0 -27
- package/dist/track-heuristics.js +0 -154
- package/dist/util/slice-id.d.ts +0 -58
- package/dist/util/slice-id.js +0 -89
- package/dist/worktree-manager.d.ts +0 -20
- package/dist/worktree-manager.js +0 -108
|
@@ -1,353 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs/promises";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { checkCriticPredictionsContract, evaluateInvestigationTrace, evaluateQaLogFloor, sectionBodyByName, validateApproachesTaxonomy, headingLineIndex, meaningfulLineCount, getMarkdownTableRows, parseShortCircuitStatus, validateCalibratedSelfReview, markdownFieldRegex } from "./shared.js";
|
|
4
|
-
import { readFlowState } from "../run-persistence.js";
|
|
5
|
-
export async function lintBrainstormStage(ctx) {
|
|
6
|
-
const { projectRoot, track, raw, absFile, sections, findings, parsedFrontmatter, brainstormShortCircuitBody, brainstormShortCircuitActivated, staleDiagramAuditEnabled, isTrivialOverride } = ctx;
|
|
7
|
-
evaluateInvestigationTrace(ctx, "Q&A Log");
|
|
8
|
-
const qaLogBody = sectionBodyByName(sections, "Q&A Log");
|
|
9
|
-
const qaLogRows = qaLogBody ? getMarkdownTableRows(qaLogBody) : [];
|
|
10
|
-
const qaLogOk = qaLogBody !== null && qaLogRows.length > 0;
|
|
11
|
-
findings.push({
|
|
12
|
-
section: "qa_log_missing",
|
|
13
|
-
required: false,
|
|
14
|
-
rule: "[P2] qa_log_missing — Q&A Log empty — confirm you actually had a dialogue with the user, not a draft from memory.",
|
|
15
|
-
found: qaLogOk,
|
|
16
|
-
details: qaLogOk
|
|
17
|
-
? `Q&A Log contains ${qaLogRows.length} data row(s).`
|
|
18
|
-
: qaLogBody === null
|
|
19
|
-
? "Missing `## Q&A Log` section."
|
|
20
|
-
: "Q&A Log is present but has zero data rows."
|
|
21
|
-
});
|
|
22
|
-
if (!brainstormShortCircuitActivated) {
|
|
23
|
-
const skipQuestions = ctx.activeStageFlags.includes("--skip-questions");
|
|
24
|
-
const floor = evaluateQaLogFloor(qaLogBody, track, "brainstorm", { discoveryMode: ctx.discoveryMode, skipQuestions });
|
|
25
|
-
findings.push({
|
|
26
|
-
section: "qa_log_unconverged",
|
|
27
|
-
required: !floor.skipQuestionsAdvisory,
|
|
28
|
-
rule: "[P1] qa_log_unconverged — Q&A Log has not converged for this stage. Continue elicitation until every forcing-question topic id is tagged with `[topic:<id>]` on at least one row, the last 2 rows produce no decision-changing impact (Ralph-Loop), or an explicit user stop-signal row is appended.",
|
|
29
|
-
found: floor.ok,
|
|
30
|
-
details: floor.details
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
// Brainstorm Iron Law: "NO ARTIFACT IS COMPLETE WITHOUT AN EXPLICITLY
|
|
34
|
-
// APPROVED DIRECTION — SILENCE IS NOT APPROVAL." Previously this was
|
|
35
|
-
// prose-only — nothing failed when the Selected Direction section
|
|
36
|
-
// omitted an approval marker, or when the Approaches table collapsed
|
|
37
|
-
// to a single row (defeating the "2-3 distinct approaches" gate).
|
|
38
|
-
const tierBody = sectionBodyByName(sections, "Approach Tier");
|
|
39
|
-
if (tierBody !== null) {
|
|
40
|
-
// Token vocabulary covers `lite`, `Lightweight`, `Standard`, and
|
|
41
|
-
// `Deep` (case-insensitive). A line that lists ≥2 distinct tokens is
|
|
42
|
-
// the unfilled template placeholder (`Tier: lite | standard | deep`)
|
|
43
|
-
// and must not silently pass; we look for at least one decision line
|
|
44
|
-
// with exactly one token, while ignoring placeholder lines.
|
|
45
|
-
const cleanedLines = tierBody
|
|
46
|
-
.split("\n")
|
|
47
|
-
.map((line) => line.replace(/[*_`]/gu, ""));
|
|
48
|
-
const lineTokenCounts = cleanedLines.map((line) => {
|
|
49
|
-
const tokens = line.match(/\b(?:lite|lightweight|light|standard|deep)\b/giu) ?? [];
|
|
50
|
-
return new Set(tokens.map((token) => token.toLowerCase())).size;
|
|
51
|
-
});
|
|
52
|
-
const hasDecisionLine = lineTokenCounts.some((count) => count === 1);
|
|
53
|
-
const hasPlaceholderLine = lineTokenCounts.some((count) => count >= 2);
|
|
54
|
-
const ok = hasDecisionLine;
|
|
55
|
-
findings.push({
|
|
56
|
-
section: "Approach Tier Classification",
|
|
57
|
-
required: false,
|
|
58
|
-
rule: "Approach Tier must explicitly classify depth as one of `lite` (a.k.a. `Lightweight`), `Standard`, or `Deep`.",
|
|
59
|
-
found: ok,
|
|
60
|
-
details: ok
|
|
61
|
-
? "Approach Tier includes a single recognized depth token."
|
|
62
|
-
: hasPlaceholderLine
|
|
63
|
-
? "Approach Tier still lists multiple tier tokens (template placeholder); pick exactly one of `lite`/`Lightweight`, `Standard`, or `Deep`."
|
|
64
|
-
: "Approach Tier is missing a recognized depth token (`lite`/`Lightweight`, `Standard`, or `Deep`)."
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
const approachesBody = sectionBodyByName(sections, "Approaches");
|
|
68
|
-
if (approachesBody !== null) {
|
|
69
|
-
const approachesTaxonomy = validateApproachesTaxonomy(approachesBody);
|
|
70
|
-
findings.push({
|
|
71
|
-
section: "Distinct Approaches Enforcement",
|
|
72
|
-
required: true,
|
|
73
|
-
rule: "Approaches section must document at least 2 distinct approaches so the Iron Law comparison is meaningful.",
|
|
74
|
-
found: approachesTaxonomy.rowCount >= 2,
|
|
75
|
-
details: approachesTaxonomy.rowCount >= 2
|
|
76
|
-
? `Detected ${approachesTaxonomy.rowCount} approach row(s).`
|
|
77
|
-
: `Detected ${approachesTaxonomy.rowCount} approach row(s); at least 2 required.`
|
|
78
|
-
});
|
|
79
|
-
findings.push({
|
|
80
|
-
section: "Approaches Role/Upside Taxonomy",
|
|
81
|
-
required: false,
|
|
82
|
-
rule: "Approaches table must use canonical Role and Upside enum values.",
|
|
83
|
-
found: approachesTaxonomy.roleUpsideOk,
|
|
84
|
-
details: approachesTaxonomy.details
|
|
85
|
-
});
|
|
86
|
-
findings.push({
|
|
87
|
-
section: "Challenger Alternative Enforcement",
|
|
88
|
-
required: false,
|
|
89
|
-
rule: "Approaches must include one challenger option with explicit high/higher upside.",
|
|
90
|
-
found: approachesTaxonomy.challengerOk,
|
|
91
|
-
details: approachesTaxonomy.details
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
const reactionIndex = headingLineIndex(raw, "Approach Reaction");
|
|
95
|
-
const directionIndex = headingLineIndex(raw, "Selected Direction");
|
|
96
|
-
if (directionIndex >= 0 && !brainstormShortCircuitActivated) {
|
|
97
|
-
const orderOk = reactionIndex >= 0 && reactionIndex < directionIndex;
|
|
98
|
-
findings.push({
|
|
99
|
-
section: "Approach Reaction Ordering",
|
|
100
|
-
required: false,
|
|
101
|
-
rule: "Approach Reaction must appear before Selected Direction (propose -> react -> recommend).",
|
|
102
|
-
found: orderOk,
|
|
103
|
-
details: orderOk
|
|
104
|
-
? "Approach Reaction appears before Selected Direction."
|
|
105
|
-
: "Approach Reaction must be present before Selected Direction."
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
const directionBody = sectionBodyByName(sections, "Selected Direction");
|
|
109
|
-
if (directionBody !== null) {
|
|
110
|
-
const approvalMarker = /\bapprov(?:ed|al)\b/iu.test(directionBody);
|
|
111
|
-
findings.push({
|
|
112
|
-
section: "Direction Approval Marker",
|
|
113
|
-
required: true,
|
|
114
|
-
rule: "Selected Direction section must state an explicit approval marker (for example `Approval: approved` or `Approved by: user`).",
|
|
115
|
-
found: approvalMarker,
|
|
116
|
-
details: approvalMarker
|
|
117
|
-
? "Approval marker present in Selected Direction."
|
|
118
|
-
: "No explicit `approved`/`approval` marker found in Selected Direction."
|
|
119
|
-
});
|
|
120
|
-
if (!brainstormShortCircuitActivated) {
|
|
121
|
-
const reactionBody = sectionBodyByName(sections, "Approach Reaction");
|
|
122
|
-
const reactionTrace = /\b(?:reaction|feedback|concern(?:s)?)\b/iu.test(directionBody) ||
|
|
123
|
-
(reactionIndex >= 0 && reactionIndex < directionIndex && meaningfulLineCount(reactionBody ?? "") > 0);
|
|
124
|
-
findings.push({
|
|
125
|
-
section: "Direction Reaction Trace",
|
|
126
|
-
required: true,
|
|
127
|
-
rule: "Selected Direction must be traceable to a prior Approach Reaction section or explicitly reference user reaction/feedback/concerns.",
|
|
128
|
-
found: reactionTrace,
|
|
129
|
-
details: reactionTrace
|
|
130
|
-
? "Selected Direction is traceable to prior user reaction."
|
|
131
|
-
: "Selected Direction is not traceable to user reaction. Add `## Approach Reaction` before it, or mention the user's reaction/concerns in the rationale."
|
|
132
|
-
});
|
|
133
|
-
// Track-aware handoff: standard track goes to `scope`; medium track
|
|
134
|
-
// goes directly to `spec`; the quick track skips brainstorm entirely.
|
|
135
|
-
// We accept either canonical successor token plus a generic
|
|
136
|
-
// `next-stage` / `handoff` phrase to preserve i18n flexibility.
|
|
137
|
-
const handoffTrace = /(?:`(?:scope|spec)`|\bscope\b|\bspec\b|next[-\s_]stage|next stage|\bhandoff\b|hand[-\s]off)/iu.test(directionBody);
|
|
138
|
-
findings.push({
|
|
139
|
-
section: "Direction Next-Stage Handoff",
|
|
140
|
-
required: true,
|
|
141
|
-
rule: "Selected Direction must record the track-aware next-stage handoff (mention `scope` for standard, `spec` for medium, or include a `Next-stage handoff:` line).",
|
|
142
|
-
found: handoffTrace,
|
|
143
|
-
details: handoffTrace
|
|
144
|
-
? "Selected Direction names the next-stage handoff."
|
|
145
|
-
: "Selected Direction is missing a next-stage handoff token. Mention `scope` (standard) or `spec` (medium), or add a `Next-stage handoff:` line so downstream stages can trace the contract."
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
const shortCircuitBody = brainstormShortCircuitBody;
|
|
150
|
-
if (shortCircuitBody !== null) {
|
|
151
|
-
const statusValue = parseShortCircuitStatus(shortCircuitBody);
|
|
152
|
-
const hasStatus = statusValue.length > 0;
|
|
153
|
-
findings.push({
|
|
154
|
-
section: "Short-Circuit Status",
|
|
155
|
-
required: false,
|
|
156
|
-
rule: "Short-Circuit Decision must include a `Status:` line (`activated` or `bypassed`).",
|
|
157
|
-
found: hasStatus,
|
|
158
|
-
details: hasStatus
|
|
159
|
-
? `Short-circuit status declared as "${statusValue}".`
|
|
160
|
-
: "Short-Circuit Decision is missing a `Status:` line."
|
|
161
|
-
});
|
|
162
|
-
if (brainstormShortCircuitActivated) {
|
|
163
|
-
const artifactLines = meaningfulLineCount(raw);
|
|
164
|
-
const withinStubLimit = artifactLines <= 30;
|
|
165
|
-
const hasScopeHandoff = /\bscope\b/iu.test(shortCircuitBody);
|
|
166
|
-
findings.push({
|
|
167
|
-
section: "Short-Circuit Stub Size",
|
|
168
|
-
required: true,
|
|
169
|
-
rule: "When short-circuit is activated, brainstorm artifact must remain a <=30 meaningful-line stub.",
|
|
170
|
-
found: withinStubLimit,
|
|
171
|
-
details: withinStubLimit
|
|
172
|
-
? `Short-circuit stub size within limit (${artifactLines} meaningful lines).`
|
|
173
|
-
: `Short-circuit stub too large (${artifactLines} meaningful lines); expected <= 30.`
|
|
174
|
-
});
|
|
175
|
-
findings.push({
|
|
176
|
-
section: "Short-Circuit Scope Handoff",
|
|
177
|
-
required: true,
|
|
178
|
-
rule: "When short-circuit is activated, the section must explicitly hand off to scope.",
|
|
179
|
-
found: hasScopeHandoff,
|
|
180
|
-
details: hasScopeHandoff
|
|
181
|
-
? "Short-circuit section includes explicit scope handoff."
|
|
182
|
-
: "Short-circuit section is missing explicit scope handoff guidance."
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
const selfReviewBody = sectionBodyByName(sections, "Self-Review Notes");
|
|
187
|
-
if (selfReviewBody !== null) {
|
|
188
|
-
const selfReview = validateCalibratedSelfReview(selfReviewBody);
|
|
189
|
-
findings.push({
|
|
190
|
-
section: "Calibrated Self-Review Format",
|
|
191
|
-
required: false,
|
|
192
|
-
rule: "When Self-Review Notes are present, they must use the calibrated review prompt output shape.",
|
|
193
|
-
found: selfReview.ok,
|
|
194
|
-
details: selfReview.details
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
const criticPredictions = checkCriticPredictionsContract(sections);
|
|
198
|
-
if (criticPredictions !== null) {
|
|
199
|
-
findings.push({
|
|
200
|
-
section: "critic.predictions_missing",
|
|
201
|
-
required: false,
|
|
202
|
-
rule: "[P2] critic.predictions_missing — pre-commitment predictions block missing or empty",
|
|
203
|
-
found: criticPredictions.found,
|
|
204
|
-
details: criticPredictions.details
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
// Universal structural checks (Layer 2.1). Each fires only when the
|
|
208
|
-
// matching section is present so legacy fixtures keep their current
|
|
209
|
-
// shape, while artifacts emitted from the v3 template have to satisfy
|
|
210
|
-
// them. Content is never inspected — only the shape required by the
|
|
211
|
-
// reference patterns (gstack mode, forcing questions, premise list,
|
|
212
|
-
// approach detail cards, anti-sycophancy stamp).
|
|
213
|
-
const modeBody = sectionBodyByName(sections, "Mode Block");
|
|
214
|
-
if (modeBody !== null) {
|
|
215
|
-
const modeTokens = ["STARTUP", "BUILDER", "ENGINEERING", "OPS", "RESEARCH"];
|
|
216
|
-
const modeRegex = markdownFieldRegex("Mode", modeTokens.join("|"), "u");
|
|
217
|
-
const tokenMatches = new Set();
|
|
218
|
-
const lineRegex = new RegExp(modeRegex.source, "gu");
|
|
219
|
-
for (const match of modeBody.matchAll(lineRegex)) {
|
|
220
|
-
const token = (match[0].match(/STARTUP|BUILDER|ENGINEERING|OPS|RESEARCH/u) ?? [""])[0];
|
|
221
|
-
if (token)
|
|
222
|
-
tokenMatches.add(token);
|
|
223
|
-
}
|
|
224
|
-
const placeholderLine = modeBody
|
|
225
|
-
.split("\n")
|
|
226
|
-
.find((line) => /\bMode\b\s*[*_]{0,2}\s*:/iu.test(line) && (line.match(/STARTUP|BUILDER|ENGINEERING|OPS|RESEARCH/giu) ?? []).length >= 2);
|
|
227
|
-
const isPlaceholder = Boolean(placeholderLine);
|
|
228
|
-
const ok = tokenMatches.size === 1 && !isPlaceholder;
|
|
229
|
-
findings.push({
|
|
230
|
-
section: "Mode Block Token",
|
|
231
|
-
required: false,
|
|
232
|
-
rule: "Mode Block must declare exactly one mode token: STARTUP, BUILDER, ENGINEERING, OPS, or RESEARCH.",
|
|
233
|
-
found: ok,
|
|
234
|
-
details: ok
|
|
235
|
-
? `Recognized mode token detected: ${[...tokenMatches][0] ?? ""}.`
|
|
236
|
-
: isPlaceholder
|
|
237
|
-
? "Mode Block still lists multiple mode tokens (template placeholder); pick exactly one of STARTUP/BUILDER/ENGINEERING/OPS/RESEARCH."
|
|
238
|
-
: "Mode Block is missing a recognized mode token (STARTUP/BUILDER/ENGINEERING/OPS/RESEARCH)."
|
|
239
|
-
});
|
|
240
|
-
}
|
|
241
|
-
// Approach Detail Cards: structural sub-section under Approaches, one
|
|
242
|
-
// bullet block per approach with the canonical fields.
|
|
243
|
-
const approachCardsRegex = /####\s+APPROACH\s+[A-Z]\b[\s\S]*?(?:^-\s*Summary:[\s\S]*?^-\s*Effort:[\s\S]*?^-\s*Risk:[\s\S]*?^-\s*Pros:[\s\S]*?^-\s*Cons:[\s\S]*?^-\s*Reuses:)/gimu;
|
|
244
|
-
const matches = raw.match(approachCardsRegex);
|
|
245
|
-
const cardCount = matches ? matches.length : 0;
|
|
246
|
-
if (/####\s+APPROACH\s+[A-Z]\b/iu.test(raw) ||
|
|
247
|
-
/^RECOMMENDATION:/imu.test(raw)) {
|
|
248
|
-
findings.push({
|
|
249
|
-
section: "Approach Detail Cards",
|
|
250
|
-
required: false,
|
|
251
|
-
rule: "Approach Detail Cards must include ≥2 `#### APPROACH <letter>` blocks each with Summary/Effort/Risk/Pros/Cons/Reuses.",
|
|
252
|
-
found: cardCount >= 2,
|
|
253
|
-
details: cardCount >= 2
|
|
254
|
-
? `Detected ${cardCount} valid approach detail card(s).`
|
|
255
|
-
: `Detected ${cardCount} valid approach detail card(s); at least 2 required with all fields present.`
|
|
256
|
-
});
|
|
257
|
-
const recommendationLine = raw.match(/^RECOMMENDATION:\s*(.+)$/imu);
|
|
258
|
-
const hasRecommendation = recommendationLine !== null && recommendationLine[1] !== undefined && recommendationLine[1].trim().length > 0;
|
|
259
|
-
findings.push({
|
|
260
|
-
section: "Approach Recommendation Marker",
|
|
261
|
-
required: false,
|
|
262
|
-
rule: "Approach Detail Cards must conclude with a single `RECOMMENDATION:` line citing the chosen letter and rationale.",
|
|
263
|
-
found: hasRecommendation,
|
|
264
|
-
details: hasRecommendation
|
|
265
|
-
? "Recommendation marker present."
|
|
266
|
-
: "Missing or empty `RECOMMENDATION:` line after approach detail cards."
|
|
267
|
-
});
|
|
268
|
-
}
|
|
269
|
-
const outsideVoiceBody = sectionBodyByName(sections, "Outside Voice");
|
|
270
|
-
if (outsideVoiceBody !== null) {
|
|
271
|
-
const required = ["source:", "prompt:", "tension:", "resolution:"];
|
|
272
|
-
const missing = required.filter((key) => !new RegExp(`(?:^|\\n)\\s*-?\\s*${key.replace(":", "\\s*:")}`, "iu").test(outsideVoiceBody));
|
|
273
|
-
const optedOut = /\bnot used\b|\bn\/a\b|\bnone\b/iu.test(outsideVoiceBody);
|
|
274
|
-
findings.push({
|
|
275
|
-
section: "Outside Voice Slot Shape",
|
|
276
|
-
required: false,
|
|
277
|
-
rule: "Outside Voice section must either declare opt-out (`not used`/`none`) or include `source:`, `prompt:`, `tension:`, `resolution:`.",
|
|
278
|
-
found: optedOut || missing.length === 0,
|
|
279
|
-
details: optedOut || missing.length === 0
|
|
280
|
-
? "Outside Voice slot is well-formed."
|
|
281
|
-
: `Outside Voice section is missing field(s): ${missing.join(", ")}.`
|
|
282
|
-
});
|
|
283
|
-
}
|
|
284
|
-
let ideaHint = {};
|
|
285
|
-
try {
|
|
286
|
-
const flowState = await readFlowState(projectRoot);
|
|
287
|
-
const hint = flowState.interactionHints?.brainstorm;
|
|
288
|
-
if (hint) {
|
|
289
|
-
ideaHint = {
|
|
290
|
-
fromIdeaArtifact: hint.fromIdeaArtifact,
|
|
291
|
-
fromIdeaCandidateId: hint.fromIdeaCandidateId
|
|
292
|
-
};
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
catch {
|
|
296
|
-
ideaHint = {};
|
|
297
|
-
}
|
|
298
|
-
if (ideaHint.fromIdeaArtifact) {
|
|
299
|
-
const carryBody = sectionBodyByName(sections, "Idea Evidence Carry-forward");
|
|
300
|
-
const hasSection = carryBody !== null && meaningfulLineCount(carryBody) > 0;
|
|
301
|
-
const sourceCited = hasSection &&
|
|
302
|
-
carryBody.includes(ideaHint.fromIdeaArtifact);
|
|
303
|
-
const candidateCited = ideaHint.fromIdeaCandidateId
|
|
304
|
-
? hasSection && carryBody.toUpperCase().includes(ideaHint.fromIdeaCandidateId.toUpperCase())
|
|
305
|
-
: true;
|
|
306
|
-
const ok = hasSection && sourceCited && candidateCited;
|
|
307
|
-
findings.push({
|
|
308
|
-
section: "brainstorm.idea_evidence_carry_forward",
|
|
309
|
-
required: true,
|
|
310
|
-
rule: "[P1] brainstorm.idea_evidence_carry_forward — when `flow-state.interactionHints.brainstorm.fromIdeaArtifact` is set, the brainstorm artifact MUST include `## Idea Evidence Carry-forward` citing the idea artifact path and chosen `I-#`. Reuse divergent + critique + rank work from `/cc-ideate` as the `baseline` Approach; only newly generate the higher-upside challenger row(s).",
|
|
311
|
-
found: ok,
|
|
312
|
-
details: ok
|
|
313
|
-
? `Idea Evidence Carry-forward cites ${ideaHint.fromIdeaArtifact}${ideaHint.fromIdeaCandidateId ? ` (${ideaHint.fromIdeaCandidateId})` : ""}.`
|
|
314
|
-
: !hasSection
|
|
315
|
-
? `Brainstorm started from /cc-ideate (artifact ${ideaHint.fromIdeaArtifact}${ideaHint.fromIdeaCandidateId ? `, candidate ${ideaHint.fromIdeaCandidateId}` : ""}) but \`## Idea Evidence Carry-forward\` is missing or empty.`
|
|
316
|
-
: !sourceCited
|
|
317
|
-
? `\`## Idea Evidence Carry-forward\` does not cite the source idea artifact path \`${ideaHint.fromIdeaArtifact}\`.`
|
|
318
|
-
: `\`## Idea Evidence Carry-forward\` does not cite the chosen candidate id \`${ideaHint.fromIdeaCandidateId ?? ""}\`.`
|
|
319
|
-
});
|
|
320
|
-
}
|
|
321
|
-
const wavePlansDir = path.join(projectRoot, ".cclaw", "wave-plans");
|
|
322
|
-
let wavePlanEntries = [];
|
|
323
|
-
try {
|
|
324
|
-
wavePlanEntries = (await fs.readdir(wavePlansDir))
|
|
325
|
-
.filter((entry) => entry !== ".gitkeep" && !entry.startsWith("."));
|
|
326
|
-
}
|
|
327
|
-
catch {
|
|
328
|
-
wavePlanEntries = [];
|
|
329
|
-
}
|
|
330
|
-
const multiWaveDetected = wavePlanEntries.length >= 2;
|
|
331
|
-
if (multiWaveDetected) {
|
|
332
|
-
const carryForwardBody = sectionBodyByName(sections, "Wave Carry-forward");
|
|
333
|
-
const hasCarryForwardSection = carryForwardBody !== null;
|
|
334
|
-
const hasCarryForwardContent = carryForwardBody !== null && meaningfulLineCount(carryForwardBody) > 0;
|
|
335
|
-
const hasDriftAuditMarkers = carryForwardBody !== null &&
|
|
336
|
-
/\bcarrying\s+forward\b/iu.test(carryForwardBody) &&
|
|
337
|
-
/\bdrift\s+detected\b/iu.test(carryForwardBody);
|
|
338
|
-
const waveDriftAddressed = hasCarryForwardSection && hasCarryForwardContent && hasDriftAuditMarkers;
|
|
339
|
-
findings.push({
|
|
340
|
-
section: "wave.drift_unaddressed",
|
|
341
|
-
required: false,
|
|
342
|
-
rule: "[P1] wave.drift_unaddressed — when `.cclaw/wave-plans/` has >=2 entries, brainstorm must include `## Wave Carry-forward` with carry-forward and drift audit markers.",
|
|
343
|
-
found: waveDriftAddressed,
|
|
344
|
-
details: waveDriftAddressed
|
|
345
|
-
? `Multi-wave context detected (${wavePlanEntries.length} wave-plan entries); Wave Carry-forward audit is present.`
|
|
346
|
-
: !hasCarryForwardSection
|
|
347
|
-
? "Multi-wave context detected but `## Wave Carry-forward` section is missing."
|
|
348
|
-
: !hasCarryForwardContent
|
|
349
|
-
? "`## Wave Carry-forward` exists but has no meaningful content."
|
|
350
|
-
: "Wave Carry-forward section must include both `Carrying forward` and `Drift detected` markers."
|
|
351
|
-
});
|
|
352
|
-
}
|
|
353
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { type StageLintContext } from "./shared.js";
|
|
2
|
-
export interface CodebaseInvestigationFileRef {
|
|
3
|
-
/** Filename to stat (parenthetical suffix already stripped). */
|
|
4
|
-
filename: string;
|
|
5
|
-
/** Raw cell content, useful for diagnostic messages. */
|
|
6
|
-
raw: string;
|
|
7
|
-
/** When true, the audit treats this row as a "new file, no baseline". */
|
|
8
|
-
newFile: boolean;
|
|
9
|
-
/**
|
|
10
|
-
* When true, the audit skips this row entirely (suffix `(skip)`,
|
|
11
|
-
* `(deleted)`, `(stub)`, leading `#`, or a `skip:` token in the
|
|
12
|
-
* Notes column).
|
|
13
|
-
*/
|
|
14
|
-
skip: boolean;
|
|
15
|
-
}
|
|
16
|
-
export declare function normalizeCodebaseInvestigationFileRef(value: string, notesCell: string): CodebaseInvestigationFileRef | null;
|
|
17
|
-
export declare function collectCodebaseInvestigationFiles(sectionBody: string): CodebaseInvestigationFileRef[];
|
|
18
|
-
export declare function lintDesignStage(ctx: StageLintContext): Promise<void>;
|