cclaw-cli 0.55.2 → 1.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.
Files changed (72) hide show
  1. package/README.md +3 -3
  2. package/dist/artifact-linter/brainstorm.js +45 -1
  3. package/dist/artifact-linter/design.js +32 -1
  4. package/dist/artifact-linter/plan.js +22 -1
  5. package/dist/artifact-linter/review.js +35 -1
  6. package/dist/artifact-linter/scope.js +19 -9
  7. package/dist/artifact-linter/shared.d.ts +11 -10
  8. package/dist/artifact-linter/shared.js +70 -41
  9. package/dist/artifact-linter/ship.js +36 -0
  10. package/dist/artifact-linter/spec.js +23 -1
  11. package/dist/artifact-linter/tdd.js +74 -0
  12. package/dist/artifact-linter.d.ts +1 -1
  13. package/dist/constants.d.ts +1 -1
  14. package/dist/constants.js +1 -0
  15. package/dist/content/closeout-guidance.d.ts +1 -1
  16. package/dist/content/closeout-guidance.js +10 -11
  17. package/dist/content/core-agents.d.ts +35 -36
  18. package/dist/content/core-agents.js +189 -99
  19. package/dist/content/diff-command.js +1 -1
  20. package/dist/content/examples.d.ts +0 -3
  21. package/dist/content/examples.js +197 -752
  22. package/dist/content/idea.d.ts +60 -0
  23. package/dist/content/idea.js +404 -0
  24. package/dist/content/learnings.d.ts +2 -4
  25. package/dist/content/learnings.js +10 -26
  26. package/dist/content/node-hooks.js +131 -97
  27. package/dist/content/opencode-plugin.js +12 -26
  28. package/dist/content/reference-patterns.js +2 -2
  29. package/dist/content/runtime-shared-snippets.d.ts +8 -0
  30. package/dist/content/runtime-shared-snippets.js +80 -0
  31. package/dist/content/session-hooks.js +1 -1
  32. package/dist/content/skills.d.ts +1 -0
  33. package/dist/content/skills.js +50 -0
  34. package/dist/content/stage-schema.js +107 -63
  35. package/dist/content/stages/review.js +8 -8
  36. package/dist/content/stages/schema-types.d.ts +2 -2
  37. package/dist/content/stages/scope.js +1 -1
  38. package/dist/content/stages/ship.js +1 -1
  39. package/dist/content/status-command.js +3 -3
  40. package/dist/content/subagent-context-skills.js +156 -1
  41. package/dist/content/subagents.d.ts +0 -5
  42. package/dist/content/subagents.js +12 -82
  43. package/dist/content/templates.js +87 -6
  44. package/dist/content/utility-skills.js +26 -97
  45. package/dist/flow-state.d.ts +5 -6
  46. package/dist/flow-state.js +4 -6
  47. package/dist/gate-evidence.d.ts +0 -31
  48. package/dist/gate-evidence.js +3 -181
  49. package/dist/harness-adapters.js +1 -1
  50. package/dist/install.js +38 -4
  51. package/dist/internal/advance-stage/advance.js +0 -1
  52. package/dist/internal/advance-stage/review-loop.js +1 -10
  53. package/dist/knowledge-store.d.ts +2 -20
  54. package/dist/knowledge-store.js +43 -57
  55. package/dist/policy.js +3 -3
  56. package/dist/retro-gate.js +8 -90
  57. package/dist/run-archive.js +1 -4
  58. package/dist/run-persistence.js +14 -109
  59. package/dist/runtime/run-hook.entry.d.ts +3 -0
  60. package/dist/runtime/run-hook.entry.js +5 -0
  61. package/dist/runtime/run-hook.mjs +9477 -0
  62. package/package.json +4 -2
  63. package/dist/content/hook-inline-snippets.d.ts +0 -96
  64. package/dist/content/hook-inline-snippets.js +0 -515
  65. package/dist/content/idea-command.d.ts +0 -8
  66. package/dist/content/idea-command.js +0 -322
  67. package/dist/content/idea-frames.d.ts +0 -31
  68. package/dist/content/idea-frames.js +0 -140
  69. package/dist/content/idea-ranking.d.ts +0 -25
  70. package/dist/content/idea-ranking.js +0 -65
  71. package/dist/trace-matrix.d.ts +0 -27
  72. package/dist/trace-matrix.js +0 -226
@@ -6,14 +6,12 @@ import { readConfig } from "./config.js";
6
6
  import { RUNTIME_ROOT } from "./constants.js";
7
7
  import { stageSchema } from "./content/stage-schema.js";
8
8
  import { readDelegationLedger } from "./delegation.js";
9
- import { ensureDir, exists, writeFileSafe } from "./fs-utils.js";
9
+ import { exists } from "./fs-utils.js";
10
10
  import { computeEarlyLoopStatus, isEarlyLoopStage, normalizeEarlyLoopMaxIterations } from "./early-loop.js";
11
11
  import { detectPublicApiChanges } from "./internal/detect-public-api-changes.js";
12
12
  import { readFlowState, writeFlowState } from "./runs.js";
13
13
  import { parseTddCycleLog, validateTddCycleOrder } from "./tdd-cycle.js";
14
14
  import { validateTddVerificationEvidence } from "./tdd-verification-evidence.js";
15
- import { buildTraceMatrix } from "./trace-matrix.js";
16
- import { FLOW_STAGES } from "./types.js";
17
15
  async function currentStageArtifactExists(projectRoot, stage, track) {
18
16
  const resolved = await resolveArtifactPath(stage, {
19
17
  projectRoot,
@@ -107,8 +105,7 @@ async function discoverRealTestCommands(projectRoot) {
107
105
  return unique(commands);
108
106
  }
109
107
  async function verifyDiscoveredCommandEvidence(projectRoot, stage, gateId, flowState) {
110
- if (!(stage === "tdd" && gateId === "tdd_verified_before_complete") &&
111
- !(stage === "review" && gateId === "review_trace_matrix_clean")) {
108
+ if (!(stage === "tdd" && gateId === "tdd_verified_before_complete")) {
112
109
  return null;
113
110
  }
114
111
  const commands = await discoverRealTestCommands(projectRoot);
@@ -207,8 +204,6 @@ async function readEarlyLoopGateSnapshot(projectRoot, flowState) {
207
204
  };
208
205
  }
209
206
  }
210
- const RECONCILIATION_NOTICES_FILE = "reconciliation-notices.json";
211
- const RECONCILIATION_NOTICES_SCHEMA_VERSION = 1;
212
207
  const DESIGN_RESEARCH_REQUIRED_SECTIONS = [
213
208
  "Stack Analysis",
214
209
  "Features & Patterns",
@@ -216,123 +211,6 @@ const DESIGN_RESEARCH_REQUIRED_SECTIONS = [
216
211
  "Pitfalls & Risks",
217
212
  "Synthesis"
218
213
  ];
219
- export const RECONCILIATION_NOTICES_REL_PATH = `${RUNTIME_ROOT}/state/${RECONCILIATION_NOTICES_FILE}`;
220
- function isFlowStageValue(value) {
221
- return typeof value === "string" && FLOW_STAGES.includes(value);
222
- }
223
- function reconciliationNoticesPath(projectRoot) {
224
- return path.join(projectRoot, RUNTIME_ROOT, "state", RECONCILIATION_NOTICES_FILE);
225
- }
226
- function defaultReconciliationNoticesPayload() {
227
- return {
228
- schemaVersion: RECONCILIATION_NOTICES_SCHEMA_VERSION,
229
- notices: [],
230
- parseOk: true,
231
- schemaOk: true
232
- };
233
- }
234
- function sanitizeReconciliationNotice(raw) {
235
- if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
236
- return null;
237
- }
238
- const typed = raw;
239
- if (typeof typed.id !== "string" ||
240
- typeof typed.runId !== "string" ||
241
- !isFlowStageValue(typed.stage) ||
242
- typeof typed.gateId !== "string" ||
243
- typeof typed.reason !== "string" ||
244
- typeof typed.demotedAt !== "string") {
245
- return null;
246
- }
247
- const kind = typed.kind === "closeout_substate_demotion"
248
- ? "closeout_substate_demotion"
249
- : "gate_demotion";
250
- let payload;
251
- if (kind === "closeout_substate_demotion" && typed.payload && typeof typed.payload === "object" && !Array.isArray(typed.payload)) {
252
- const payloadTyped = typed.payload;
253
- if (typeof payloadTyped.previous === "string" &&
254
- typeof payloadTyped.next === "string" &&
255
- typeof payloadTyped.reason === "string") {
256
- payload = {
257
- previous: payloadTyped.previous,
258
- next: payloadTyped.next,
259
- reason: payloadTyped.reason
260
- };
261
- }
262
- }
263
- return {
264
- id: typed.id,
265
- runId: typed.runId,
266
- stage: typed.stage,
267
- gateId: typed.gateId,
268
- reason: typed.reason,
269
- demotedAt: typed.demotedAt,
270
- kind,
271
- payload
272
- };
273
- }
274
- export async function readReconciliationNotices(projectRoot) {
275
- const filePath = reconciliationNoticesPath(projectRoot);
276
- if (!(await exists(filePath))) {
277
- return defaultReconciliationNoticesPayload();
278
- }
279
- try {
280
- const raw = JSON.parse(await fs.readFile(filePath, "utf8"));
281
- const schemaOk = raw.schemaVersion === RECONCILIATION_NOTICES_SCHEMA_VERSION;
282
- const notices = Array.isArray(raw.notices)
283
- ? raw.notices
284
- .map((value) => sanitizeReconciliationNotice(value))
285
- .filter((value) => value !== null)
286
- : [];
287
- return {
288
- schemaVersion: RECONCILIATION_NOTICES_SCHEMA_VERSION,
289
- notices,
290
- parseOk: true,
291
- schemaOk
292
- };
293
- }
294
- catch {
295
- return {
296
- ...defaultReconciliationNoticesPayload(),
297
- parseOk: false,
298
- schemaOk: false
299
- };
300
- }
301
- }
302
- async function writeReconciliationNotices(projectRoot, payload) {
303
- const filePath = reconciliationNoticesPath(projectRoot);
304
- await ensureDir(path.dirname(filePath));
305
- await writeFileSafe(filePath, `${JSON.stringify({
306
- schemaVersion: RECONCILIATION_NOTICES_SCHEMA_VERSION,
307
- notices: payload.notices
308
- }, null, 2)}\n`, { mode: 0o600 });
309
- }
310
- export function classifyReconciliationNotices(flowState, notices) {
311
- const activeBlocked = [];
312
- const currentStageBlocked = [];
313
- const unsynced = [];
314
- const staleRun = [];
315
- for (const notice of notices) {
316
- if (notice.runId !== flowState.activeRunId) {
317
- staleRun.push(notice);
318
- continue;
319
- }
320
- if (notice.kind === "closeout_substate_demotion") {
321
- continue;
322
- }
323
- const stageCatalog = flowState.stageGateCatalog[notice.stage];
324
- const blocked = stageCatalog.blocked.includes(notice.gateId);
325
- if (!blocked) {
326
- unsynced.push(notice);
327
- continue;
328
- }
329
- activeBlocked.push(notice);
330
- if (notice.stage === flowState.currentStage) {
331
- currentStageBlocked.push(notice);
332
- }
333
- }
334
- return { activeBlocked, currentStageBlocked, unsynced, staleRun };
335
- }
336
214
  export async function verifyCurrentStageGateEvidence(projectRoot, flowState) {
337
215
  const stage = flowState.currentStage;
338
216
  const schema = stageSchema(stage, flowState.track);
@@ -448,23 +326,6 @@ export async function verifyCurrentStageGateEvidence(projectRoot, flowState) {
448
326
  if (!securityAttestation.ok) {
449
327
  issues.push(`review security attestation failed: ${securityAttestation.errors.join("; ")}`);
450
328
  }
451
- const traceGateRequired = schema.requiredGates.some((gate) => gate.id === "review_trace_matrix_clean" && gate.tier === "required");
452
- if (traceGateRequired) {
453
- const trace = await buildTraceMatrix(projectRoot);
454
- const traceIssues = [];
455
- if (trace.orphanedCriteria.length > 0) {
456
- traceIssues.push(`orphaned criteria: ${trace.orphanedCriteria.join(", ")}`);
457
- }
458
- if (trace.orphanedTasks.length > 0) {
459
- traceIssues.push(`orphaned tasks: ${trace.orphanedTasks.join(", ")}`);
460
- }
461
- if (trace.orphanedTests.length > 0) {
462
- traceIssues.push(`orphaned tests: ${trace.orphanedTests.join(", ")}`);
463
- }
464
- if (traceIssues.length > 0) {
465
- issues.push(`review trace-matrix gate blocked (review_trace_matrix_clean): ${traceIssues.join("; ")}.`);
466
- }
467
- }
468
329
  }
469
330
  if (stage === "design") {
470
331
  const researchGateRequired = schema.requiredGates.some((gate) => gate.id === "design_research_complete" && gate.tier === "required");
@@ -739,47 +600,8 @@ export function reconcileCurrentStageGateCatalog(flowState) {
739
600
  export async function reconcileAndWriteCurrentStageGateCatalog(projectRoot) {
740
601
  const state = await readFlowState(projectRoot);
741
602
  const { nextState, reconciliation } = reconcileCurrentStageGateCatalog(state);
742
- const effectiveState = reconciliation.changed ? nextState : state;
743
603
  if (reconciliation.changed) {
744
- await writeFlowState(projectRoot, effectiveState);
745
- }
746
- const noticesPayload = await readReconciliationNotices(projectRoot);
747
- let noticesChanged = false;
748
- const noticeBuckets = classifyReconciliationNotices(effectiveState, noticesPayload.notices);
749
- if (noticeBuckets.unsynced.length > 0 || noticeBuckets.staleRun.length > 0) {
750
- const dropIds = new Set([...noticeBuckets.unsynced, ...noticeBuckets.staleRun].map((notice) => notice.id));
751
- noticesPayload.notices = noticesPayload.notices.filter((notice) => !dropIds.has(notice.id));
752
- noticesChanged = true;
753
- }
754
- if (reconciliation.demotedGateIds.length > 0) {
755
- const existing = new Set(noticesPayload.notices.map((notice) => `${notice.runId}:${notice.stage}:${notice.gateId}:${notice.kind ?? "gate_demotion"}`));
756
- for (const gateId of reconciliation.demotedGateIds) {
757
- const dedupeKey = `${effectiveState.activeRunId}:${reconciliation.stage}:${gateId}:gate_demotion`;
758
- if (existing.has(dedupeKey)) {
759
- continue;
760
- }
761
- const ts = new Date().toISOString();
762
- noticesPayload.notices.push({
763
- id: `${dedupeKey}:${ts}`,
764
- runId: effectiveState.activeRunId,
765
- stage: reconciliation.stage,
766
- gateId,
767
- reason: "demoted from passed to blocked during gate reconciliation (missing evidence)",
768
- demotedAt: ts,
769
- kind: "gate_demotion"
770
- });
771
- existing.add(dedupeKey);
772
- noticesChanged = true;
773
- }
774
- }
775
- if (noticesChanged) {
776
- noticesPayload.notices.sort((a, b) => {
777
- if (a.demotedAt === b.demotedAt) {
778
- return a.id.localeCompare(b.id);
779
- }
780
- return a.demotedAt.localeCompare(b.demotedAt);
781
- });
782
- await writeReconciliationNotices(projectRoot, noticesPayload);
604
+ await writeFlowState(projectRoot, nextState);
783
605
  }
784
606
  return {
785
607
  ...reconciliation,
@@ -378,7 +378,7 @@ When in doubt, prefer **non-trivial** — the quick track is opt-in and only saf
378
378
  Knowledge capture and curation run automatically as part of stage completion
379
379
  protocols via the internal \`learnings\` skill — no user-facing command.
380
380
  Reusable entries land in \`.cclaw/knowledge.jsonl\` as strict JSONL with
381
- \`type\`, \`trigger\`, \`action\`, and \`origin_run\` metadata.
381
+ \`type\`, \`trigger\`, \`action\`, \`confidence\`, \`stage\`, and \`origin_stage\` metadata.
382
382
 
383
383
  **Stage order:** brainstorm > scope > design > spec > plan > tdd > review > ship, then closeout: retro > compound > archive. Use \`/cc\` to keep moving through normal work and post-ship closeout; use \`/cc-cancel\` for cancelled/abandoned runs. Gates must pass before handoff.
384
384
 
package/dist/install.js CHANGED
@@ -6,7 +6,7 @@ import { CCLAW_VERSION, FLOW_VERSION, REQUIRED_DIRS, RUNTIME_ROOT } from "./cons
6
6
  import { writeConfig, createDefaultConfig, readConfig, configPath, detectLanguageRulePacks, detectAdvancedKeys } from "./config.js";
7
7
  import { learnSkillMarkdown } from "./content/learnings.js";
8
8
  import { stageCommandShimMarkdown } from "./content/stage-command.js";
9
- import { ideaCommandContract, ideaCommandSkillMarkdown } from "./content/idea-command.js";
9
+ import { ideaCommandContract, ideaCommandSkillMarkdown } from "./content/idea.js";
10
10
  import { startCommandContract, startCommandSkillMarkdown } from "./content/start-command.js";
11
11
  import { viewCommandContract, viewCommandSkillMarkdown } from "./content/view-command.js";
12
12
  import { cancelCommandContract, cancelCommandSkillMarkdown } from "./content/cancel-command.js";
@@ -19,7 +19,7 @@ import { META_SKILL_NAME, usingCclawSkillMarkdown } from "./content/meta-skill.j
19
19
  import { ARTIFACT_TEMPLATES, 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
- import { stageSkillFolder, stageSkillMarkdown } from "./content/skills.js";
22
+ import { stageSkillFolder, stageSkillMarkdown, executingWavesSkillMarkdown } from "./content/skills.js";
23
23
  import { LANGUAGE_RULE_PACK_DIR, LANGUAGE_RULE_PACK_FILES, LANGUAGE_RULE_PACK_GENERATORS, LEGACY_LANGUAGE_RULE_PACK_FOLDERS } from "./content/utility-skills.js";
24
24
  import { RESEARCH_PLAYBOOKS } from "./content/research-playbooks.js";
25
25
  import { SUBAGENT_CONTEXT_SKILLS } from "./content/subagent-context-skills.js";
@@ -470,6 +470,9 @@ async function writeArtifactTemplates(projectRoot) {
470
470
  await writeFileSafe(runtimePath(projectRoot, "templates", "state-contracts", fileName), content);
471
471
  }));
472
472
  }
473
+ async function writeWavePlansScaffold(projectRoot) {
474
+ await writeFileSafe(runtimePath(projectRoot, "wave-plans", ".gitkeep"), "");
475
+ }
473
476
  async function writeSkills(projectRoot, config) {
474
477
  const skillTrack = config?.defaultTrack ?? "standard";
475
478
  for (const stage of FLOW_STAGES) {
@@ -486,6 +489,7 @@ async function writeSkills(projectRoot, config) {
486
489
  await writeFileSafe(runtimePath(projectRoot, "skills", "parallel-dispatch", "SKILL.md"), parallelAgentsSkill());
487
490
  await writeFileSafe(runtimePath(projectRoot, "skills", "session", "SKILL.md"), sessionHooksSkillMarkdown());
488
491
  await writeFileSafe(runtimePath(projectRoot, "skills", "iron-laws", "SKILL.md"), ironLawsSkillMarkdown());
492
+ await writeFileSafe(runtimePath(projectRoot, "skills", "executing-waves", "SKILL.md"), executingWavesSkillMarkdown());
489
493
  await writeFileSafe(runtimePath(projectRoot, "skills", META_SKILL_NAME, "SKILL.md"), usingCclawSkillMarkdown());
490
494
  // In-thread research procedures (no YAML frontmatter, not delegated personas).
491
495
  for (const [fileName, markdown] of Object.entries(RESEARCH_PLAYBOOKS)) {
@@ -897,6 +901,33 @@ async function writeMergedHookJson(projectRoot, hookFilePath, generatedJson) {
897
901
  }
898
902
  await writeFileSafe(hookFilePath, `${JSON.stringify(mergedDoc, null, 2)}\n`);
899
903
  }
904
+ async function readBundledRunHookRuntimeScript(options) {
905
+ const bundleUrl = new URL("./runtime/run-hook.mjs", import.meta.url);
906
+ try {
907
+ await fs.stat(bundleUrl);
908
+ }
909
+ catch {
910
+ return null;
911
+ }
912
+ try {
913
+ const moduleUrl = `${bundleUrl.href}?ts=${Date.now()}`;
914
+ const loaded = await import(moduleUrl);
915
+ const factory = typeof loaded.buildRunHookRuntimeScript === "function"
916
+ ? loaded.buildRunHookRuntimeScript
917
+ : typeof loaded.default === "function"
918
+ ? loaded.default
919
+ : null;
920
+ if (!factory)
921
+ return null;
922
+ const script = factory(options);
923
+ if (typeof script !== "string")
924
+ return null;
925
+ return script.trim().length > 0 ? script : null;
926
+ }
927
+ catch {
928
+ return null;
929
+ }
930
+ }
900
931
  async function writeHooks(projectRoot, config) {
901
932
  const harnesses = config.harnesses;
902
933
  const hooksDir = runtimePath(projectRoot, "hooks");
@@ -911,14 +942,16 @@ async function writeHooks(projectRoot, config) {
911
942
  await writeFileSafe(path.join(hooksDir, "stage-complete.mjs"), stageCompleteScript());
912
943
  await writeFileSafe(path.join(hooksDir, "start-flow.mjs"), startFlowScript());
913
944
  await writeFileSafe(path.join(hooksDir, "cancel-run.mjs"), cancelRunScript());
914
- await writeFileSafe(path.join(hooksDir, "run-hook.mjs"), nodeHookRuntimeScript({
945
+ const hookRuntimeOptions = {
915
946
  strictness: effectiveStrictness,
916
947
  tddTestPathPatterns: config.tdd?.testPathPatterns ?? config.tddTestGlobs,
917
948
  tddProductionPathPatterns: config.tdd?.productionPathPatterns,
918
949
  compoundRecurrenceThreshold: config.compound?.recurrenceThreshold,
919
950
  earlyLoopEnabled: config.earlyLoop?.enabled,
920
951
  earlyLoopMaxIterations: config.earlyLoop?.maxIterations
921
- }));
952
+ };
953
+ const bundledHookRuntime = await readBundledRunHookRuntimeScript(hookRuntimeOptions);
954
+ await writeFileSafe(path.join(hooksDir, "run-hook.mjs"), bundledHookRuntime ?? nodeHookRuntimeScript(hookRuntimeOptions));
922
955
  await writeFileSafe(path.join(hooksDir, "run-hook.cmd"), runHookCmdScript());
923
956
  await writeFileSafe(path.join(hooksDir, "delegation-record.mjs"), delegationRecordScript());
924
957
  const opencodePluginSource = opencodePluginJs();
@@ -1196,6 +1229,7 @@ async function materializeRuntime(projectRoot, config, forceStateReset, operatio
1196
1229
  writeEntryCommands(projectRoot),
1197
1230
  writeSkills(projectRoot, config),
1198
1231
  writeArtifactTemplates(projectRoot),
1232
+ writeWavePlansScaffold(projectRoot),
1199
1233
  writeRulebook(projectRoot)
1200
1234
  ]);
1201
1235
  await writeState(projectRoot, config, forceStateReset);
@@ -168,7 +168,6 @@ export async function harvestStageLearnings(projectRoot, stage, track) {
168
168
  const appendResult = await appendKnowledge(projectRoot, parsed.entries, {
169
169
  stage,
170
170
  originStage: stage,
171
- originRun: null,
172
171
  project: path.basename(projectRoot)
173
172
  });
174
173
  if (appendResult.invalid > 0) {
@@ -1,5 +1,5 @@
1
1
  import { SHIP_FINALIZATION_MODES } from "../../constants.js";
2
- import { PASS_STATUS_PATTERN, TEST_COMMAND_HINT_PATTERN, validateTddVerificationEvidence } from "../../tdd-verification-evidence.js";
2
+ import { validateTddVerificationEvidence } from "../../tdd-verification-evidence.js";
3
3
  import { asRecord } from "./helpers.js";
4
4
  export const AUTO_REVIEW_LOOP_GATE_BY_STAGE = {
5
5
  design: "design_architecture_locked"
@@ -134,15 +134,6 @@ export function validateUserApprovalEvidence(evidence) {
134
134
  // guaranteed to carry the structural breadcrumbs downstream tooling
135
135
  // expects. Previously only `tdd:tdd_verified_before_complete` was checked.
136
136
  const GATE_EVIDENCE_VALIDATORS = {
137
- "review:review_trace_matrix_clean": (evidence) => {
138
- if (!TEST_COMMAND_HINT_PATTERN.test(evidence)) {
139
- return "must include the fresh verification command that was run before ship handoff (for example `npm test`, `pytest`, `go test`, or equivalent).";
140
- }
141
- if (!PASS_STATUS_PATTERN.test(evidence)) {
142
- return "must include explicit success status (for example `PASS` or `GREEN`).";
143
- }
144
- return null;
145
- },
146
137
  "ship:ship_finalization_executed": (evidence) => {
147
138
  if (!SHIP_FINALIZATION_MODE_PATTERN.test(evidence)) {
148
139
  return `must name the finalization mode that ran (for example ${SHIP_FINALIZATION_MODE_HINT}).`;
@@ -2,8 +2,6 @@ import { type FlowStage } from "./types.js";
2
2
  export type KnowledgeEntryType = "rule" | "pattern" | "lesson" | "compound";
3
3
  export type KnowledgeEntryConfidence = "high" | "medium" | "low";
4
4
  export type KnowledgeEntrySeverity = "critical" | "important" | "suggestion";
5
- export type KnowledgeEntryUniversality = "project" | "personal" | "universal";
6
- export type KnowledgeEntryMaturity = "raw" | "lifted-to-rule" | "lifted-to-enforcement";
7
5
  export type KnowledgeEntrySource = "stage" | "retro" | "compound" | "idea" | "manual";
8
6
  export interface KnowledgeEntry {
9
7
  type: KnowledgeEntryType;
@@ -11,20 +9,14 @@ export interface KnowledgeEntry {
11
9
  action: string;
12
10
  confidence: KnowledgeEntryConfidence;
13
11
  severity?: KnowledgeEntrySeverity;
14
- domain: string | null;
15
12
  stage: FlowStage | null;
16
13
  origin_stage: FlowStage | null;
17
- origin_run: string | null;
18
14
  frequency: number;
19
- universality: KnowledgeEntryUniversality;
20
- maturity: KnowledgeEntryMaturity;
21
15
  created: string;
22
16
  first_seen_ts: string;
23
17
  last_seen_ts: string;
24
18
  project: string | null;
25
19
  source?: KnowledgeEntrySource | null;
26
- supersedes?: string[];
27
- superseded_by?: string;
28
20
  }
29
21
  export interface KnowledgeSeedEntry {
30
22
  type: KnowledgeEntryType;
@@ -32,25 +24,18 @@ export interface KnowledgeSeedEntry {
32
24
  action: string;
33
25
  confidence: KnowledgeEntryConfidence;
34
26
  severity?: KnowledgeEntrySeverity;
35
- domain?: string | null;
36
27
  stage?: FlowStage | null;
37
28
  origin_stage?: FlowStage | null;
38
- origin_run?: string | null;
39
29
  frequency?: number;
40
- universality?: KnowledgeEntryUniversality;
41
- maturity?: KnowledgeEntryMaturity;
42
30
  created?: string;
43
31
  first_seen_ts?: string;
44
32
  last_seen_ts?: string;
45
33
  project?: string | null;
46
34
  source?: KnowledgeEntrySource | null;
47
- supersedes?: string[];
48
- superseded_by?: string;
49
35
  }
50
36
  export interface AppendKnowledgeDefaults {
51
37
  stage?: FlowStage | null;
52
38
  originStage?: FlowStage | null;
53
- originRun?: string | null;
54
39
  project?: string | null;
55
40
  source?: KnowledgeEntrySource | null;
56
41
  nowIso?: string;
@@ -98,8 +83,6 @@ export interface CompoundReadinessCluster {
98
83
  lastSeenTs: string;
99
84
  /** Entry types observed (rule/pattern/lesson/compound). */
100
85
  types: KnowledgeEntryType[];
101
- /** Distinct maturity values observed across the cluster. */
102
- maturity: KnowledgeEntryMaturity[];
103
86
  }
104
87
  export interface CompoundReadiness {
105
88
  schemaVersion: 2;
@@ -167,9 +150,8 @@ export declare function effectiveCompoundThreshold(baseThreshold: number, archiv
167
150
  *
168
151
  * Clustering key: `(type, normalizeText(trigger), normalizeText(action))`
169
152
  * which mirrors the compound readiness clustering in runtime state.
170
- * Entries with `maturity === "lifted-to-enforcement"` or `superseded_by`
171
- * are excluded they were already promoted/replaced and should not re-appear
172
- * as ready.
153
+ * The readiness surface intentionally stays simple: no maturity/supersede
154
+ * suppression logic in this pass.
173
155
  */
174
156
  export declare function computeCompoundReadiness(entries: KnowledgeEntry[], options?: ComputeCompoundReadinessOptions): CompoundReadiness;
175
157
  export declare function validateKnowledgeEntry(entry: unknown): {