cclaw-cli 0.48.26 → 0.48.28

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.
@@ -1,4 +1,4 @@
1
- import { stageSchema } from "./stage-schema.js";
1
+ import { stagePolicyNeedles, stageSchema } from "./stage-schema.js";
2
2
  import { stageSkillFolder } from "./skills.js";
3
3
  export function stageCommandContract(stage, track = "standard") {
4
4
  const schema = stageSchema(stage, track);
@@ -17,6 +17,7 @@ export function stageCommandContract(stage, track = "standard") {
17
17
  const writeStepPaths = writes.length > 1
18
18
  ? writes.map((w) => `\`${w}\``).join(" and ")
19
19
  : `\`${primaryArtifact}\``;
20
+ const policyNeedles = stagePolicyNeedles(stage, track);
20
21
  return `# /cc-${stage}
21
22
 
22
23
  Load and follow **${skillPath}** — it contains the full checklist, examples, interaction protocol, and verification discipline.
@@ -45,6 +46,6 @@ ${gateIds}
45
46
  ${schema.exitCriteria.map((v) => `- ${v}`).join("\n")}
46
47
 
47
48
  ## Anchors
48
- ${schema.policyNeedles.map((v) => `- ${v}`).join("\n")}
49
+ ${policyNeedles.map((v) => `- ${v}`).join("\n")}
49
50
  `;
50
51
  }
@@ -1,6 +1,6 @@
1
1
  import type { FlowStage, FlowTrack, TransitionRule } from "../types.js";
2
- import type { StageAutoSubagentDispatch, StageSchema } from "./stages/schema-types.js";
3
- export type { ArtifactValidation, CrossStageTrace, ReviewSection, StageAutoSubagentDispatch, StageGate, StageSchema, StageSchemaInput } from "./stages/schema-types.js";
2
+ import type { StageComplexityTier, StageAutoSubagentDispatch, StageSchema } from "./stages/schema-types.js";
3
+ export type { ArtifactValidation, CrossStageTrace, ReviewSection, StageComplexityTier, StageExecutionModel, StagePhilosophy, StageArtifactRules, StageReviewLens, StageAutoSubagentDispatch, StageGate, StageSchemaLegacyInput, StageSchema, StageSchemaInput, StageSchemaV2Input } from "./stages/schema-types.js";
4
4
  export declare const SKILL_ENVELOPE_KINDS: readonly ["stage-output", "gate-result", "delegation-record"];
5
5
  export type SkillEnvelopeKind = (typeof SKILL_ENVELOPE_KINDS)[number];
6
6
  export interface SkillEnvelope {
@@ -18,7 +18,7 @@ export interface SkillEnvelopeValidation {
18
18
  export declare function validateSkillEnvelope(value: unknown): SkillEnvelopeValidation;
19
19
  export declare function parseSkillEnvelope(raw: string): SkillEnvelope | null;
20
20
  /** Transition guard: agents with `mode: "mandatory"` in auto-subagent dispatch for this stage. */
21
- export declare function mandatoryDelegationsForStage(stage: FlowStage): string[];
21
+ export declare function mandatoryDelegationsForStage(stage: FlowStage, complexityTier?: StageComplexityTier): string[];
22
22
  export declare function stageSchema(stage: FlowStage, track?: FlowTrack): StageSchema;
23
23
  export declare function orderedStageSchemas(track?: FlowTrack): StageSchema[];
24
24
  export declare function stageGateIds(stage: FlowStage, track?: FlowTrack): string[];
@@ -1,6 +1,7 @@
1
1
  import { FLOW_STAGES, FLOW_TRACKS, TRACK_STAGES } from "../types.js";
2
2
  import { STAGE_TO_SKILL_FOLDER } from "../constants.js";
3
3
  import { BRAINSTORM, SCOPE, DESIGN, SPEC, PLAN, TDD, REVIEW, SHIP } from "./stages/index.js";
4
+ import { stagePolicyNeedlesFromMetadata } from "./stages/_lint-metadata/index.js";
4
5
  import { tddStageForTrack } from "./stages/tdd.js";
5
6
  // ---------------------------------------------------------------------------
6
7
  // NOTE: The former QUESTION_FORMAT_SPEC / ERROR_BUDGET_SPEC exports were
@@ -15,6 +16,11 @@ export const SKILL_ENVELOPE_KINDS = [
15
16
  ];
16
17
  const FLOW_STAGE_SET = new Set(FLOW_STAGES);
17
18
  const SKILL_ENVELOPE_KIND_SET = new Set(SKILL_ENVELOPE_KINDS);
19
+ const COMPLEXITY_TIER_ORDER = {
20
+ lightweight: 0,
21
+ standard: 1,
22
+ deep: 2
23
+ };
18
24
  function asRecord(value) {
19
25
  if (!value || typeof value !== "object" || Array.isArray(value)) {
20
26
  return null;
@@ -173,6 +179,46 @@ function readsFromForTrack(readsFrom, track) {
173
179
  return stageSet.has(stage);
174
180
  });
175
181
  }
182
+ function isStageSchemaV2Input(value) {
183
+ return value.schemaShape === "v2";
184
+ }
185
+ function normalizeStageSchemaInput(value) {
186
+ if (!isStageSchemaV2Input(value)) {
187
+ return value;
188
+ }
189
+ return {
190
+ stage: value.stage,
191
+ skillFolder: value.skillFolder,
192
+ skillName: value.skillName,
193
+ skillDescription: value.skillDescription,
194
+ complexityTier: value.complexityTier,
195
+ hardGate: value.philosophy.hardGate,
196
+ ironLaw: value.philosophy.ironLaw,
197
+ purpose: value.philosophy.purpose,
198
+ whenToUse: value.philosophy.whenToUse,
199
+ whenNotToUse: value.philosophy.whenNotToUse,
200
+ interactionProtocol: value.executionModel.interactionProtocol,
201
+ process: value.executionModel.process,
202
+ requiredGates: value.executionModel.requiredGates,
203
+ requiredEvidence: value.executionModel.requiredEvidence,
204
+ inputs: value.executionModel.inputs,
205
+ requiredContext: value.executionModel.requiredContext,
206
+ researchPlaybooks: value.executionModel.researchPlaybooks,
207
+ outputs: value.reviewLens.outputs,
208
+ blockers: value.executionModel.blockers,
209
+ exitCriteria: value.executionModel.exitCriteria,
210
+ commonRationalizations: value.philosophy.commonRationalizations,
211
+ artifactFile: value.artifactRules.artifactFile,
212
+ next: value.next,
213
+ checklist: value.executionModel.checklist,
214
+ reviewSections: value.reviewLens.reviewSections,
215
+ completionStatus: value.artifactRules.completionStatus,
216
+ crossStageTrace: value.artifactRules.crossStageTrace,
217
+ artifactValidation: value.artifactRules.artifactValidation,
218
+ batchExecutionAllowed: value.batchExecutionAllowed,
219
+ trivialOverrideSections: value.artifactRules.trivialOverrideSections
220
+ };
221
+ }
176
222
  // ---------------------------------------------------------------------------
177
223
  // Stage map and accessors
178
224
  // ---------------------------------------------------------------------------
@@ -200,6 +246,7 @@ const STAGE_AUTO_SUBAGENT_DISPATCH = {
200
246
  {
201
247
  agent: "planner",
202
248
  mode: "mandatory",
249
+ requiredAtTier: "standard",
203
250
  when: "Always during scope shaping.",
204
251
  purpose: "Challenge premise, map alternatives, and produce explicit in/out contract.",
205
252
  requiresUserGate: false
@@ -209,6 +256,7 @@ const STAGE_AUTO_SUBAGENT_DISPATCH = {
209
256
  {
210
257
  agent: "planner",
211
258
  mode: "mandatory",
259
+ requiredAtTier: "standard",
212
260
  when: "Always during design lock.",
213
261
  purpose: "Stress architecture boundaries and dependency graph.",
214
262
  requiresUserGate: false
@@ -241,6 +289,7 @@ const STAGE_AUTO_SUBAGENT_DISPATCH = {
241
289
  {
242
290
  agent: "planner",
243
291
  mode: "mandatory",
292
+ requiredAtTier: "standard",
244
293
  when: "Always when producing execution slices.",
245
294
  purpose: "Create dependency-aware task graph with verification steps.",
246
295
  requiresUserGate: false
@@ -250,6 +299,7 @@ const STAGE_AUTO_SUBAGENT_DISPATCH = {
250
299
  {
251
300
  agent: "test-author",
252
301
  mode: "mandatory",
302
+ requiredAtTier: "lightweight",
253
303
  when: "Always during TDD cycle (RED phase).",
254
304
  purpose: "Produce failing RED tests only; no production writes.",
255
305
  requiresUserGate: false,
@@ -258,6 +308,7 @@ const STAGE_AUTO_SUBAGENT_DISPATCH = {
258
308
  {
259
309
  agent: "test-author",
260
310
  mode: "mandatory",
311
+ requiredAtTier: "lightweight",
261
312
  when: "Always during TDD cycle (GREEN phase).",
262
313
  purpose: "Implement minimum production changes to satisfy RED and prove full-suite GREEN.",
263
314
  requiresUserGate: false,
@@ -266,6 +317,7 @@ const STAGE_AUTO_SUBAGENT_DISPATCH = {
266
317
  {
267
318
  agent: "test-author",
268
319
  mode: "mandatory",
320
+ requiredAtTier: "lightweight",
269
321
  when: "Always during TDD cycle (REFACTOR phase).",
270
322
  purpose: "Refactor only after GREEN proof, preserving behavior and test pass state.",
271
323
  requiresUserGate: false,
@@ -283,6 +335,7 @@ const STAGE_AUTO_SUBAGENT_DISPATCH = {
283
335
  {
284
336
  agent: "reviewer",
285
337
  mode: "mandatory",
338
+ requiredAtTier: "lightweight",
286
339
  when: "Always in review stage.",
287
340
  purpose: "Layer 1 spec compliance pass plus coordination of parallel Layer 2 fan-out (correctness, performance, architecture, external-safety) with source-tagged findings.",
288
341
  requiresUserGate: false,
@@ -291,6 +344,7 @@ const STAGE_AUTO_SUBAGENT_DISPATCH = {
291
344
  {
292
345
  agent: "security-reviewer",
293
346
  mode: "mandatory",
347
+ requiredAtTier: "lightweight",
294
348
  when: "Always in review stage. Even when no trust boundaries changed, produce an explicit 'no-change' security attestation.",
295
349
  purpose: "Guarantee a dedicated security pass on every diff: auth, input validation, secrets, injection, privilege, and blast-radius review are never opt-in. MUST load the `security-audit` skill and run a pattern-based sweep across the diff scope and touched modules in addition to the per-diff Layer 2 security checklist.",
296
350
  requiresUserGate: false,
@@ -299,6 +353,7 @@ const STAGE_AUTO_SUBAGENT_DISPATCH = {
299
353
  {
300
354
  agent: "reviewer",
301
355
  mode: "mandatory",
356
+ requiredAtTier: "lightweight",
302
357
  when: "Mandatory when the diff exceeds 100 changed lines, touches more than 10 files, or modifies trust boundaries — dispatch a SECOND, independent reviewer with the adversarial-review skill loaded so the review army has at least two voices on a high-blast-radius change.",
303
358
  purpose: "Adversarial second-opinion review on large or trust-sensitive diffs. The second reviewer treats the implementation as hostile and tries to break it (hostile-user, future-maintainer, competitor lenses) instead of sympathetically explaining it.",
304
359
  requiresUserGate: false,
@@ -317,6 +372,7 @@ const STAGE_AUTO_SUBAGENT_DISPATCH = {
317
372
  {
318
373
  agent: "doc-updater",
319
374
  mode: "mandatory",
375
+ requiredAtTier: "lightweight",
320
376
  when: "Always in ship stage.",
321
377
  purpose: "Ensure release notes and docs reflect actual shipped behavior.",
322
378
  requiresUserGate: false
@@ -331,26 +387,72 @@ const STAGE_AUTO_SUBAGENT_DISPATCH = {
331
387
  ]
332
388
  };
333
389
  /** Transition guard: agents with `mode: "mandatory"` in auto-subagent dispatch for this stage. */
334
- export function mandatoryDelegationsForStage(stage) {
390
+ export function mandatoryDelegationsForStage(stage, complexityTier = "standard") {
391
+ const currentTierRank = COMPLEXITY_TIER_ORDER[complexityTier];
335
392
  return [...new Set(STAGE_AUTO_SUBAGENT_DISPATCH[stage]
336
393
  .filter((d) => d.mode === "mandatory")
394
+ .filter((d) => {
395
+ const requiredAt = d.requiredAtTier ?? "standard";
396
+ return currentTierRank >= COMPLEXITY_TIER_ORDER[requiredAt];
397
+ })
337
398
  .map((d) => d.agent))];
338
399
  }
339
400
  export function stageSchema(stage, track = "standard") {
340
- const base = stage === "tdd" ? tddStageForTrack(track) : STAGE_SCHEMA_MAP[stage];
401
+ const rawInput = stage === "tdd" ? tddStageForTrack(track) : STAGE_SCHEMA_MAP[stage];
402
+ const base = normalizeStageSchemaInput(rawInput);
341
403
  const tieredGates = tieredStageGates(stage, base.requiredGates, track);
342
404
  const tieredValidation = tieredArtifactValidation(stage, base.artifactValidation);
343
405
  const crossStageTrace = {
344
406
  ...base.crossStageTrace,
345
407
  readsFrom: readsFromForTrack(base.crossStageTrace.readsFrom, track)
346
408
  };
409
+ const complexityTier = base.complexityTier ?? "standard";
410
+ const mandatoryDelegations = mandatoryDelegationsForStage(stage, complexityTier);
411
+ const philosophy = {
412
+ hardGate: base.hardGate,
413
+ ironLaw: base.ironLaw,
414
+ purpose: base.purpose,
415
+ whenToUse: base.whenToUse,
416
+ whenNotToUse: base.whenNotToUse,
417
+ commonRationalizations: base.commonRationalizations
418
+ };
419
+ const executionModel = {
420
+ interactionProtocol: base.interactionProtocol,
421
+ process: base.process,
422
+ checklist: base.checklist,
423
+ requiredGates: tieredGates,
424
+ requiredEvidence: base.requiredEvidence,
425
+ inputs: base.inputs,
426
+ requiredContext: base.requiredContext,
427
+ researchPlaybooks: base.researchPlaybooks,
428
+ blockers: base.blockers,
429
+ exitCriteria: base.exitCriteria
430
+ };
431
+ const artifactRules = {
432
+ artifactFile: base.artifactFile,
433
+ completionStatus: base.completionStatus,
434
+ crossStageTrace,
435
+ artifactValidation: tieredValidation,
436
+ trivialOverrideSections: base.trivialOverrideSections
437
+ };
438
+ const reviewLens = {
439
+ outputs: base.outputs,
440
+ reviewSections: base.reviewSections,
441
+ mandatoryDelegations
442
+ };
347
443
  return {
348
444
  ...base,
445
+ schemaShape: "v2",
446
+ complexityTier,
447
+ philosophy,
448
+ executionModel,
449
+ artifactRules,
450
+ reviewLens,
349
451
  skillFolder: STAGE_TO_SKILL_FOLDER[stage],
350
452
  crossStageTrace,
351
453
  requiredGates: tieredGates,
352
454
  artifactValidation: tieredValidation,
353
- mandatoryDelegations: mandatoryDelegationsForStage(stage)
455
+ mandatoryDelegations
354
456
  };
355
457
  }
356
458
  export function orderedStageSchemas(track = "standard") {
@@ -403,7 +505,7 @@ export function buildTransitionRules() {
403
505
  return rules;
404
506
  }
405
507
  export function stagePolicyNeedles(stage, track = "standard") {
406
- return stageSchema(stage, track).policyNeedles;
508
+ return stagePolicyNeedlesFromMetadata(stage, track);
407
509
  }
408
510
  export function stageAutoSubagentDispatch(stage) {
409
511
  return STAGE_AUTO_SUBAGENT_DISPATCH[stage];
@@ -0,0 +1,2 @@
1
+ import type { FlowStage, FlowTrack } from "../../../types.js";
2
+ export declare function stagePolicyNeedlesFromMetadata(stage: FlowStage, track?: FlowTrack): string[];
@@ -0,0 +1,79 @@
1
+ import { SHIP_FINALIZATION_MODES } from "../../../constants.js";
2
+ const STAGE_POLICY_NEEDLES = {
3
+ brainstorm: [
4
+ "Explore project context",
5
+ "One question at a time",
6
+ "2-3 architecturally distinct approaches",
7
+ "State what is being approved",
8
+ "Self-review before handoff",
9
+ "Do NOT implement, scaffold, or modify behavior"
10
+ ],
11
+ scope: [
12
+ "Scope mode",
13
+ "In Scope",
14
+ "Out of Scope",
15
+ "Discretion Areas",
16
+ "NOT in scope",
17
+ "Premise Challenge",
18
+ "Locked Decisions"
19
+ ],
20
+ design: [
21
+ "Parallel Research Fleet",
22
+ "Architecture",
23
+ "Data Flow",
24
+ "Failure Modes and Mitigation",
25
+ "Performance Budget",
26
+ "One issue at a time"
27
+ ],
28
+ spec: ["Acceptance Criteria", "Constraints", "Testability", "approved spec", "Edge Cases"],
29
+ plan: [
30
+ "WAIT_FOR_CONFIRM",
31
+ "Task Graph",
32
+ "Dependency Batches",
33
+ "Acceptance Mapping",
34
+ "verification steps",
35
+ "Locked Decision Coverage"
36
+ ],
37
+ tdd: [
38
+ "RED",
39
+ "GREEN",
40
+ "REFACTOR",
41
+ "failing test",
42
+ "full test suite",
43
+ "acceptance criteria",
44
+ "traceable to plan slice"
45
+ ],
46
+ review: [
47
+ "Layer 1",
48
+ "Layer 2",
49
+ "Critical",
50
+ "Review Army",
51
+ "Ready to Ship",
52
+ "ROUTE_BACK_TO_TDD",
53
+ "One issue at a time"
54
+ ],
55
+ ship: [
56
+ "Pre-Ship Checks",
57
+ "Release Notes",
58
+ "Rollback Plan",
59
+ ...SHIP_FINALIZATION_MODES
60
+ ]
61
+ };
62
+ function quickTrackText(value) {
63
+ return value
64
+ .replace(/\btask from the plan\b/giu, "acceptance criterion from the spec")
65
+ .replace(/\bplan task ID\b/giu, "acceptance criterion ID")
66
+ .replace(/\bplan task\b/giu, "acceptance criterion")
67
+ .replace(/\bplan row\b/giu, "acceptance row")
68
+ .replace(/\bplan slice\b/giu, "acceptance slice")
69
+ .replace(/\bplan artifact\b/giu, "spec artifact")
70
+ .replace(/\btraceable to plan slice\b/giu, "traceable to acceptance criterion")
71
+ .replace(/05-plan\.md/gu, "04-spec.md");
72
+ }
73
+ export function stagePolicyNeedlesFromMetadata(stage, track = "standard") {
74
+ const needles = STAGE_POLICY_NEEDLES[stage];
75
+ if (stage === "tdd" && track === "quick") {
76
+ return needles.map(quickTrackText);
77
+ }
78
+ return [...needles];
79
+ }