cclaw-cli 8.1.2 → 8.2.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/README.md +41 -23
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -1
- package/dist/content/artifact-templates.d.ts +1 -1
- package/dist/content/artifact-templates.js +83 -2
- package/dist/content/node-hooks.js +80 -27
- package/dist/content/skills.js +301 -13
- package/dist/content/specialist-prompts/architect.d.ts +1 -1
- package/dist/content/specialist-prompts/architect.js +30 -6
- package/dist/content/specialist-prompts/brainstormer.d.ts +1 -1
- package/dist/content/specialist-prompts/brainstormer.js +31 -8
- package/dist/content/specialist-prompts/planner.d.ts +1 -1
- package/dist/content/specialist-prompts/planner.js +81 -12
- package/dist/content/specialist-prompts/reviewer.d.ts +1 -1
- package/dist/content/specialist-prompts/reviewer.js +43 -6
- package/dist/content/specialist-prompts/security-reviewer.d.ts +1 -1
- package/dist/content/specialist-prompts/security-reviewer.js +31 -6
- package/dist/content/specialist-prompts/slice-builder.d.ts +1 -1
- package/dist/content/specialist-prompts/slice-builder.js +79 -10
- package/dist/content/start-command.js +187 -158
- package/dist/flow-state.d.ts +38 -6
- package/dist/flow-state.js +125 -6
- package/dist/run-persistence.d.ts +11 -4
- package/dist/run-persistence.js +18 -7
- package/dist/types.d.ts +32 -1
- package/dist/types.js +14 -0
- package/package.json +1 -1
package/dist/flow-state.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { type AcceptanceCriterionState, type BuildProfile, type DiscoverySpecialistId, type FlowStage } from "./types.js";
|
|
2
|
-
export declare const FLOW_STATE_SCHEMA_VERSION =
|
|
3
|
-
|
|
1
|
+
import { type AcMode, type AcceptanceCriterionState, type BuildProfile, type DiscoverySpecialistId, type FlowStage, type RoutingClass, type TriageDecision } from "./types.js";
|
|
2
|
+
export declare const FLOW_STATE_SCHEMA_VERSION = 3;
|
|
3
|
+
/** v8.0–v8.1 schema. Auto-migrated to v3 on read. */
|
|
4
|
+
export declare const LEGACY_V8_FLOW_STATE_SCHEMA_VERSION = 2;
|
|
5
|
+
export interface FlowStateV82 {
|
|
4
6
|
schemaVersion: typeof FLOW_STATE_SCHEMA_VERSION;
|
|
5
7
|
currentSlug: string | null;
|
|
6
8
|
currentStage: FlowStage | null;
|
|
@@ -10,13 +12,43 @@ export interface FlowStateV8 {
|
|
|
10
12
|
reviewIterations: number;
|
|
11
13
|
securityFlag: boolean;
|
|
12
14
|
buildProfile?: BuildProfile;
|
|
15
|
+
/**
|
|
16
|
+
* Triage decision for the active flow. Null while no flow is running.
|
|
17
|
+
* Persisted so resume never re-prompts the user.
|
|
18
|
+
*/
|
|
19
|
+
triage: TriageDecision | null;
|
|
13
20
|
}
|
|
14
|
-
export type FlowState =
|
|
21
|
+
export type FlowState = FlowStateV82;
|
|
22
|
+
/** @deprecated alias preserved for v8.1 import sites. Use {@link FlowStateV82}. */
|
|
23
|
+
export type FlowStateV8 = FlowStateV82;
|
|
15
24
|
export declare class LegacyFlowStateError extends Error {
|
|
16
25
|
readonly observedSchemaVersion: unknown;
|
|
17
26
|
constructor(message: string, observedSchemaVersion: unknown);
|
|
18
27
|
}
|
|
19
28
|
export declare function isFlowStage(value: unknown): value is FlowStage;
|
|
29
|
+
export declare function isRoutingClass(value: unknown): value is RoutingClass;
|
|
30
|
+
export declare function isAcMode(value: unknown): value is AcMode;
|
|
20
31
|
export declare function isDiscoverySpecialist(value: unknown): value is DiscoverySpecialistId;
|
|
21
|
-
export declare function
|
|
22
|
-
|
|
32
|
+
export declare function createInitialFlowState(nowIso?: string): FlowStateV82;
|
|
33
|
+
/** @deprecated kept for source-level compatibility with v8.1 imports. */
|
|
34
|
+
export declare const createInitialFlowStateV8: typeof createInitialFlowState;
|
|
35
|
+
/**
|
|
36
|
+
* Validate a flow-state object. Throws on hard schema errors.
|
|
37
|
+
*
|
|
38
|
+
* v8.2 (schemaVersion=3) is the current shape. v8.0–v8.1 (schemaVersion=2)
|
|
39
|
+
* states are auto-migrated forward in {@link readMigratedFlowState}; this
|
|
40
|
+
* assertion expects the migrated shape.
|
|
41
|
+
*/
|
|
42
|
+
export declare function assertFlowStateV82(value: unknown): asserts value is FlowStateV82;
|
|
43
|
+
/** @deprecated alias preserved for v8.1 import sites. Use {@link assertFlowStateV82}. */
|
|
44
|
+
export declare const assertFlowStateV8: typeof assertFlowStateV82;
|
|
45
|
+
/** Older v7.x schema marker — used only for the hard-stop migration error. */
|
|
46
|
+
export declare const PRE_V8_LEGACY_SCHEMA_VERSIONS: Set<string | number | undefined>;
|
|
47
|
+
/**
|
|
48
|
+
* Migrate any in-memory flow-state value to the current schemaVersion.
|
|
49
|
+
*
|
|
50
|
+
* Returns the migrated object. The caller is expected to write it back to
|
|
51
|
+
* disk before any further mutation. Throws {@link LegacyFlowStateError} if
|
|
52
|
+
* the input is from a pre-v8 release (schemaVersion 1 or unset).
|
|
53
|
+
*/
|
|
54
|
+
export declare function migrateFlowState(value: unknown): FlowStateV82;
|
package/dist/flow-state.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { FLOW_STAGES } from "./types.js";
|
|
2
|
-
export const FLOW_STATE_SCHEMA_VERSION =
|
|
1
|
+
import { AC_MODES, FLOW_STAGES, ROUTING_CLASSES } from "./types.js";
|
|
2
|
+
export const FLOW_STATE_SCHEMA_VERSION = 3;
|
|
3
|
+
/** v8.0–v8.1 schema. Auto-migrated to v3 on read. */
|
|
4
|
+
export const LEGACY_V8_FLOW_STATE_SCHEMA_VERSION = 2;
|
|
3
5
|
export class LegacyFlowStateError extends Error {
|
|
4
6
|
observedSchemaVersion;
|
|
5
7
|
constructor(message, observedSchemaVersion) {
|
|
@@ -11,10 +13,16 @@ export class LegacyFlowStateError extends Error {
|
|
|
11
13
|
export function isFlowStage(value) {
|
|
12
14
|
return typeof value === "string" && FLOW_STAGES.includes(value);
|
|
13
15
|
}
|
|
16
|
+
export function isRoutingClass(value) {
|
|
17
|
+
return typeof value === "string" && ROUTING_CLASSES.includes(value);
|
|
18
|
+
}
|
|
19
|
+
export function isAcMode(value) {
|
|
20
|
+
return typeof value === "string" && AC_MODES.includes(value);
|
|
21
|
+
}
|
|
14
22
|
export function isDiscoverySpecialist(value) {
|
|
15
23
|
return value === "brainstormer" || value === "architect" || value === "planner";
|
|
16
24
|
}
|
|
17
|
-
export function
|
|
25
|
+
export function createInitialFlowState(nowIso = new Date().toISOString()) {
|
|
18
26
|
return {
|
|
19
27
|
schemaVersion: FLOW_STATE_SCHEMA_VERSION,
|
|
20
28
|
currentSlug: null,
|
|
@@ -23,7 +31,38 @@ export function createInitialFlowStateV8(nowIso = new Date().toISOString()) {
|
|
|
23
31
|
lastSpecialist: null,
|
|
24
32
|
startedAt: nowIso,
|
|
25
33
|
reviewIterations: 0,
|
|
26
|
-
securityFlag: false
|
|
34
|
+
securityFlag: false,
|
|
35
|
+
triage: null
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/** @deprecated kept for source-level compatibility with v8.1 imports. */
|
|
39
|
+
export const createInitialFlowStateV8 = createInitialFlowState;
|
|
40
|
+
/**
|
|
41
|
+
* Infer a TriageDecision for a v2 (pre-8.2) state being migrated forward.
|
|
42
|
+
*
|
|
43
|
+
* v2 states never recorded a triage. To preserve their behaviour we map
|
|
44
|
+
* them to `strict` AC mode (they relied on per-AC TDD), with complexity
|
|
45
|
+
* inferred from the AC count and security flag.
|
|
46
|
+
*/
|
|
47
|
+
function inferTriageFromLegacy(state) {
|
|
48
|
+
const acCount = state.ac.length;
|
|
49
|
+
let complexity;
|
|
50
|
+
if (state.securityFlag || acCount > 5) {
|
|
51
|
+
complexity = "large-risky";
|
|
52
|
+
}
|
|
53
|
+
else if (acCount > 0) {
|
|
54
|
+
complexity = "small-medium";
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
complexity = "small-medium";
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
complexity,
|
|
61
|
+
acMode: "strict",
|
|
62
|
+
path: ["plan", "build", "review", "ship"],
|
|
63
|
+
rationale: "Auto-migrated from cclaw 8.0/8.1 flow-state (no triage recorded; preserved as strict).",
|
|
64
|
+
decidedAt: state.startedAt,
|
|
65
|
+
userOverrode: false
|
|
27
66
|
};
|
|
28
67
|
}
|
|
29
68
|
function assertAcArray(value) {
|
|
@@ -51,12 +90,46 @@ function assertAcArray(value) {
|
|
|
51
90
|
}
|
|
52
91
|
}
|
|
53
92
|
}
|
|
54
|
-
|
|
93
|
+
function assertTriageOrNull(value) {
|
|
94
|
+
if (value === null)
|
|
95
|
+
return;
|
|
96
|
+
if (typeof value !== "object")
|
|
97
|
+
throw new Error("flow-state.triage must be an object or null");
|
|
98
|
+
const triage = value;
|
|
99
|
+
if (!isRoutingClass(triage.complexity)) {
|
|
100
|
+
throw new Error(`Invalid triage.complexity: ${String(triage.complexity)}`);
|
|
101
|
+
}
|
|
102
|
+
if (!isAcMode(triage.acMode)) {
|
|
103
|
+
throw new Error(`Invalid triage.acMode: ${String(triage.acMode)}`);
|
|
104
|
+
}
|
|
105
|
+
if (!Array.isArray(triage.path)) {
|
|
106
|
+
throw new Error("triage.path must be an array of stage names");
|
|
107
|
+
}
|
|
108
|
+
for (const stage of triage.path) {
|
|
109
|
+
if (!isFlowStage(stage))
|
|
110
|
+
throw new Error(`Invalid triage.path stage: ${String(stage)}`);
|
|
111
|
+
}
|
|
112
|
+
if (typeof triage.rationale !== "string")
|
|
113
|
+
throw new Error("triage.rationale must be a string");
|
|
114
|
+
if (typeof triage.decidedAt !== "string")
|
|
115
|
+
throw new Error("triage.decidedAt must be a string");
|
|
116
|
+
if (typeof triage.userOverrode !== "boolean") {
|
|
117
|
+
throw new Error("triage.userOverrode must be a boolean");
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Validate a flow-state object. Throws on hard schema errors.
|
|
122
|
+
*
|
|
123
|
+
* v8.2 (schemaVersion=3) is the current shape. v8.0–v8.1 (schemaVersion=2)
|
|
124
|
+
* states are auto-migrated forward in {@link readMigratedFlowState}; this
|
|
125
|
+
* assertion expects the migrated shape.
|
|
126
|
+
*/
|
|
127
|
+
export function assertFlowStateV82(value) {
|
|
55
128
|
if (typeof value !== "object" || value === null)
|
|
56
129
|
throw new Error("flow-state must be an object");
|
|
57
130
|
const state = value;
|
|
58
131
|
if (state.schemaVersion !== FLOW_STATE_SCHEMA_VERSION) {
|
|
59
|
-
throw new LegacyFlowStateError(
|
|
132
|
+
throw new LegacyFlowStateError(`Unsupported flow-state schema (saw ${String(state.schemaVersion)}, expected ${FLOW_STATE_SCHEMA_VERSION}). Run cclaw upgrade or delete .cclaw/state/flow-state.json to start fresh.`, state.schemaVersion);
|
|
60
133
|
}
|
|
61
134
|
if (state.currentSlug !== null && state.currentSlug !== undefined && typeof state.currentSlug !== "string") {
|
|
62
135
|
throw new Error("flow-state.currentSlug must be a string or null");
|
|
@@ -79,4 +152,50 @@ export function assertFlowStateV8(value) {
|
|
|
79
152
|
if (state.buildProfile !== undefined && state.buildProfile !== "default" && state.buildProfile !== "bootstrap") {
|
|
80
153
|
throw new Error(`Invalid buildProfile: ${String(state.buildProfile)}`);
|
|
81
154
|
}
|
|
155
|
+
assertTriageOrNull(state.triage);
|
|
156
|
+
}
|
|
157
|
+
/** @deprecated alias preserved for v8.1 import sites. Use {@link assertFlowStateV82}. */
|
|
158
|
+
export const assertFlowStateV8 = assertFlowStateV82;
|
|
159
|
+
/** Older v7.x schema marker — used only for the hard-stop migration error. */
|
|
160
|
+
export const PRE_V8_LEGACY_SCHEMA_VERSIONS = new Set([1, "1", "1.0", undefined]);
|
|
161
|
+
/**
|
|
162
|
+
* Migrate any in-memory flow-state value to the current schemaVersion.
|
|
163
|
+
*
|
|
164
|
+
* Returns the migrated object. The caller is expected to write it back to
|
|
165
|
+
* disk before any further mutation. Throws {@link LegacyFlowStateError} if
|
|
166
|
+
* the input is from a pre-v8 release (schemaVersion 1 or unset).
|
|
167
|
+
*/
|
|
168
|
+
export function migrateFlowState(value) {
|
|
169
|
+
if (typeof value !== "object" || value === null) {
|
|
170
|
+
throw new Error("flow-state must be an object");
|
|
171
|
+
}
|
|
172
|
+
const raw = value;
|
|
173
|
+
if (raw.schemaVersion === FLOW_STATE_SCHEMA_VERSION) {
|
|
174
|
+
assertFlowStateV82(raw);
|
|
175
|
+
return raw;
|
|
176
|
+
}
|
|
177
|
+
if (raw.schemaVersion === LEGACY_V8_FLOW_STATE_SCHEMA_VERSION) {
|
|
178
|
+
const migrated = migrateFromV2(raw);
|
|
179
|
+
assertFlowStateV82(migrated);
|
|
180
|
+
return migrated;
|
|
181
|
+
}
|
|
182
|
+
throw new LegacyFlowStateError(`Unsupported flow-state schema. cclaw v8.2 only migrates from schemaVersion 2 (v8.0/v8.1). Saw ${String(raw.schemaVersion)}. Delete .cclaw/state/flow-state.json to start fresh.`, raw.schemaVersion);
|
|
183
|
+
}
|
|
184
|
+
function migrateFromV2(raw) {
|
|
185
|
+
const ac = raw.ac ?? [];
|
|
186
|
+
const securityFlag = Boolean(raw.securityFlag);
|
|
187
|
+
const startedAt = typeof raw.startedAt === "string" ? raw.startedAt : new Date().toISOString();
|
|
188
|
+
const triage = raw.currentSlug ? inferTriageFromLegacy({ ac, securityFlag, startedAt }) : null;
|
|
189
|
+
return {
|
|
190
|
+
schemaVersion: FLOW_STATE_SCHEMA_VERSION,
|
|
191
|
+
currentSlug: raw.currentSlug ?? null,
|
|
192
|
+
currentStage: raw.currentStage ?? null,
|
|
193
|
+
ac,
|
|
194
|
+
lastSpecialist: raw.lastSpecialist ?? null,
|
|
195
|
+
startedAt,
|
|
196
|
+
reviewIterations: typeof raw.reviewIterations === "number" ? raw.reviewIterations : 0,
|
|
197
|
+
securityFlag,
|
|
198
|
+
buildProfile: raw.buildProfile,
|
|
199
|
+
triage
|
|
200
|
+
};
|
|
82
201
|
}
|
|
@@ -1,7 +1,14 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type FlowStateV82 } from "./flow-state.js";
|
|
2
2
|
export declare function flowStatePath(projectRoot: string): string;
|
|
3
3
|
export declare function ensureRunSystem(projectRoot: string): Promise<void>;
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Read and validate flow-state.json.
|
|
6
|
+
*
|
|
7
|
+
* v8.0/v8.1 (schemaVersion=2) states are silently auto-migrated to v8.2
|
|
8
|
+
* (schemaVersion=3) and rewritten to disk so subsequent reads are O(1).
|
|
9
|
+
* v7.x states throw `LegacyFlowStateError` exactly as before.
|
|
10
|
+
*/
|
|
11
|
+
export declare function readFlowState(projectRoot: string): Promise<FlowStateV82>;
|
|
12
|
+
export declare function writeFlowState(projectRoot: string, state: FlowStateV82): Promise<void>;
|
|
6
13
|
export declare function resetFlowState(projectRoot: string): Promise<void>;
|
|
7
|
-
export declare function patchFlowState(projectRoot: string, patch: Partial<
|
|
14
|
+
export declare function patchFlowState(projectRoot: string, patch: Partial<FlowStateV82>): Promise<FlowStateV82>;
|
package/dist/run-persistence.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { FLOW_STATE_REL_PATH, RUNTIME_ROOT } from "./constants.js";
|
|
4
|
-
import {
|
|
4
|
+
import { assertFlowStateV82, createInitialFlowState, migrateFlowState } from "./flow-state.js";
|
|
5
5
|
import { ensureDir, exists, writeFileSafe } from "./fs-utils.js";
|
|
6
6
|
export function flowStatePath(projectRoot) {
|
|
7
7
|
return path.join(projectRoot, FLOW_STATE_REL_PATH);
|
|
@@ -10,27 +10,38 @@ export async function ensureRunSystem(projectRoot) {
|
|
|
10
10
|
await ensureDir(path.join(projectRoot, RUNTIME_ROOT, "state"));
|
|
11
11
|
const statePath = flowStatePath(projectRoot);
|
|
12
12
|
if (!(await exists(statePath))) {
|
|
13
|
-
await writeFlowState(projectRoot,
|
|
13
|
+
await writeFlowState(projectRoot, createInitialFlowState());
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* Read and validate flow-state.json.
|
|
18
|
+
*
|
|
19
|
+
* v8.0/v8.1 (schemaVersion=2) states are silently auto-migrated to v8.2
|
|
20
|
+
* (schemaVersion=3) and rewritten to disk so subsequent reads are O(1).
|
|
21
|
+
* v7.x states throw `LegacyFlowStateError` exactly as before.
|
|
22
|
+
*/
|
|
16
23
|
export async function readFlowState(projectRoot) {
|
|
17
24
|
const statePath = flowStatePath(projectRoot);
|
|
18
25
|
if (!(await exists(statePath))) {
|
|
19
|
-
const initial =
|
|
26
|
+
const initial = createInitialFlowState();
|
|
20
27
|
await writeFlowState(projectRoot, initial);
|
|
21
28
|
return initial;
|
|
22
29
|
}
|
|
23
30
|
const raw = await fs.readFile(statePath, "utf8");
|
|
24
31
|
const parsed = JSON.parse(raw);
|
|
25
|
-
|
|
26
|
-
|
|
32
|
+
const migrated = migrateFlowState(parsed);
|
|
33
|
+
// If migration reshaped the on-disk file, persist the upgrade.
|
|
34
|
+
if (parsed.schemaVersion !== migrated.schemaVersion) {
|
|
35
|
+
await writeFlowState(projectRoot, migrated);
|
|
36
|
+
}
|
|
37
|
+
return migrated;
|
|
27
38
|
}
|
|
28
39
|
export async function writeFlowState(projectRoot, state) {
|
|
29
|
-
|
|
40
|
+
assertFlowStateV82(state);
|
|
30
41
|
await writeFileSafe(flowStatePath(projectRoot), `${JSON.stringify(state, null, 2)}\n`);
|
|
31
42
|
}
|
|
32
43
|
export async function resetFlowState(projectRoot) {
|
|
33
|
-
await writeFlowState(projectRoot,
|
|
44
|
+
await writeFlowState(projectRoot, createInitialFlowState());
|
|
34
45
|
}
|
|
35
46
|
export async function patchFlowState(projectRoot, patch) {
|
|
36
47
|
const current = await readFlowState(projectRoot);
|
package/dist/types.d.ts
CHANGED
|
@@ -25,7 +25,38 @@ export interface AcceptanceCriterionState {
|
|
|
25
25
|
phases?: Partial<Record<TddPhase, TddPhaseRecord>>;
|
|
26
26
|
}
|
|
27
27
|
export type BuildProfile = "default" | "bootstrap";
|
|
28
|
-
export
|
|
28
|
+
export declare const ROUTING_CLASSES: readonly ["trivial", "small-medium", "large-risky"];
|
|
29
|
+
export type RoutingClass = (typeof ROUTING_CLASSES)[number];
|
|
30
|
+
/**
|
|
31
|
+
* AC traceability and TDD enforcement modes (v8.2+).
|
|
32
|
+
*
|
|
33
|
+
* - `inline`: trivial change. No AC table, no commit hook, optional tests.
|
|
34
|
+
* - `soft`: small/medium feature work. Bullet-list testable conditions in
|
|
35
|
+
* `plan.md` (no AC IDs); commit-helper does not block; one TDD cycle per
|
|
36
|
+
* feature is enough. Default for small/medium routing.
|
|
37
|
+
* - `strict`: large/risky / security-flagged. AC IDs with commit trace,
|
|
38
|
+
* ship gate, RED → GREEN → REFACTOR per AC. Same as v8.1 behaviour.
|
|
39
|
+
*
|
|
40
|
+
* Selected at the triage gate; user can override.
|
|
41
|
+
*/
|
|
42
|
+
export declare const AC_MODES: readonly ["inline", "soft", "strict"];
|
|
43
|
+
export type AcMode = (typeof AC_MODES)[number];
|
|
44
|
+
/**
|
|
45
|
+
* Decision recorded at the triage gate that opens every new flow.
|
|
46
|
+
* Persisted in flow-state.json so resumes never re-trigger triage.
|
|
47
|
+
*/
|
|
48
|
+
export interface TriageDecision {
|
|
49
|
+
complexity: RoutingClass;
|
|
50
|
+
acMode: AcMode;
|
|
51
|
+
/** Stages the orchestrator promised to run, in order. Empty for trivial. */
|
|
52
|
+
path: FlowStage[];
|
|
53
|
+
/** Why this complexity was chosen. One short sentence. */
|
|
54
|
+
rationale: string;
|
|
55
|
+
/** ISO timestamp when triage was recorded. */
|
|
56
|
+
decidedAt: string;
|
|
57
|
+
/** Did the user override the orchestrator's recommendation? */
|
|
58
|
+
userOverrode: boolean;
|
|
59
|
+
}
|
|
29
60
|
export interface CliContext {
|
|
30
61
|
cwd: string;
|
|
31
62
|
stdout: NodeJS.WriteStream;
|
package/dist/types.js
CHANGED
|
@@ -7,3 +7,17 @@ export const SPECIALISTS = [
|
|
|
7
7
|
"security-reviewer",
|
|
8
8
|
"slice-builder"
|
|
9
9
|
];
|
|
10
|
+
export const ROUTING_CLASSES = ["trivial", "small-medium", "large-risky"];
|
|
11
|
+
/**
|
|
12
|
+
* AC traceability and TDD enforcement modes (v8.2+).
|
|
13
|
+
*
|
|
14
|
+
* - `inline`: trivial change. No AC table, no commit hook, optional tests.
|
|
15
|
+
* - `soft`: small/medium feature work. Bullet-list testable conditions in
|
|
16
|
+
* `plan.md` (no AC IDs); commit-helper does not block; one TDD cycle per
|
|
17
|
+
* feature is enough. Default for small/medium routing.
|
|
18
|
+
* - `strict`: large/risky / security-flagged. AC IDs with commit trace,
|
|
19
|
+
* ship gate, RED → GREEN → REFACTOR per AC. Same as v8.1 behaviour.
|
|
20
|
+
*
|
|
21
|
+
* Selected at the triage gate; user can override.
|
|
22
|
+
*/
|
|
23
|
+
export const AC_MODES = ["inline", "soft", "strict"];
|