@aperant/framework 0.17.0 → 0.19.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 (152) hide show
  1. package/CHANGELOG.md +152 -0
  2. package/dist/cli/commands/ci-watch.mjs +49 -2
  3. package/dist/cli/commands/ci-watch.mjs.map +1 -1
  4. package/dist/cli/commands/commit.mjs +3 -3
  5. package/dist/cli/commands/commit.mjs.map +1 -1
  6. package/dist/cli/commands/event.mjs +16 -16
  7. package/dist/cli/commands/event.mjs.map +1 -1
  8. package/dist/cli/commands/merge-integrate.mjs +3 -3
  9. package/dist/cli/commands/merge-integrate.mjs.map +1 -1
  10. package/dist/cli/commands/produce.d.mts +9 -0
  11. package/dist/cli/commands/produce.d.mts.map +1 -0
  12. package/dist/cli/commands/produce.mjs +1345 -0
  13. package/dist/cli/commands/produce.mjs.map +1 -0
  14. package/dist/cli/commands/task.d.mts +16 -1
  15. package/dist/cli/commands/task.d.mts.map +1 -1
  16. package/dist/cli/commands/task.mjs +434 -266
  17. package/dist/cli/commands/task.mjs.map +1 -1
  18. package/dist/cli/coordination/auto-emit-artifact-ready.mjs +5 -5
  19. package/dist/cli/coordination/auto-emit-artifact-ready.mjs.map +1 -1
  20. package/dist/cli/coordination/event-schema.d.mts +5 -3
  21. package/dist/cli/coordination/event-schema.d.mts.map +1 -1
  22. package/dist/cli/coordination/event-schema.mjs +245 -21
  23. package/dist/cli/coordination/event-schema.mjs.map +1 -1
  24. package/dist/cli/coordination/store.d.mts +2 -2
  25. package/dist/cli/coordination/store.mjs +4 -4
  26. package/dist/cli/coordination/store.mjs.map +1 -1
  27. package/dist/cli/dispatch.d.mts.map +1 -1
  28. package/dist/cli/dispatch.mjs +2 -0
  29. package/dist/cli/dispatch.mjs.map +1 -1
  30. package/dist/cli/help.d.mts.map +1 -1
  31. package/dist/cli/help.mjs +30 -0
  32. package/dist/cli/help.mjs.map +1 -1
  33. package/dist/cli/install/legacy-paths.d.mts.map +1 -1
  34. package/dist/cli/install/legacy-paths.mjs +2 -0
  35. package/dist/cli/install/legacy-paths.mjs.map +1 -1
  36. package/dist/cli/produce/blind-probe.d.mts +85 -0
  37. package/dist/cli/produce/blind-probe.d.mts.map +1 -0
  38. package/dist/cli/produce/blind-probe.mjs +217 -0
  39. package/dist/cli/produce/blind-probe.mjs.map +1 -0
  40. package/dist/cli/produce/claim.d.mts +188 -0
  41. package/dist/cli/produce/claim.d.mts.map +1 -0
  42. package/dist/cli/produce/claim.mjs +518 -0
  43. package/dist/cli/produce/claim.mjs.map +1 -0
  44. package/dist/cli/produce/done-gate.d.mts +87 -0
  45. package/dist/cli/produce/done-gate.d.mts.map +1 -0
  46. package/dist/cli/produce/done-gate.mjs +200 -0
  47. package/dist/cli/produce/done-gate.mjs.map +1 -0
  48. package/dist/cli/produce/events.d.mts +77 -0
  49. package/dist/cli/produce/events.d.mts.map +1 -0
  50. package/dist/cli/produce/events.mjs +126 -0
  51. package/dist/cli/produce/events.mjs.map +1 -0
  52. package/dist/cli/produce/evidence-oracle.d.mts +63 -0
  53. package/dist/cli/produce/evidence-oracle.d.mts.map +1 -0
  54. package/dist/cli/produce/evidence-oracle.mjs +122 -0
  55. package/dist/cli/produce/evidence-oracle.mjs.map +1 -0
  56. package/dist/cli/produce/ledger.d.mts +140 -0
  57. package/dist/cli/produce/ledger.d.mts.map +1 -0
  58. package/dist/cli/produce/ledger.mjs +272 -0
  59. package/dist/cli/produce/ledger.mjs.map +1 -0
  60. package/dist/cli/produce/probe-family.d.mts +53 -0
  61. package/dist/cli/produce/probe-family.d.mts.map +1 -0
  62. package/dist/cli/produce/probe-family.mjs +160 -0
  63. package/dist/cli/produce/probe-family.mjs.map +1 -0
  64. package/dist/cli/produce/projection.d.mts +55 -0
  65. package/dist/cli/produce/projection.d.mts.map +1 -0
  66. package/dist/cli/produce/projection.mjs +97 -0
  67. package/dist/cli/produce/projection.mjs.map +1 -0
  68. package/dist/cli/produce/run-id.d.mts +42 -0
  69. package/dist/cli/produce/run-id.d.mts.map +1 -0
  70. package/dist/cli/produce/run-id.mjs +79 -0
  71. package/dist/cli/produce/run-id.mjs.map +1 -0
  72. package/dist/cli/produce/saga.d.mts +180 -0
  73. package/dist/cli/produce/saga.d.mts.map +1 -0
  74. package/dist/cli/produce/saga.mjs +290 -0
  75. package/dist/cli/produce/saga.mjs.map +1 -0
  76. package/dist/cli/produce/scheduler.d.mts +165 -0
  77. package/dist/cli/produce/scheduler.d.mts.map +1 -0
  78. package/dist/cli/produce/scheduler.mjs +399 -0
  79. package/dist/cli/produce/scheduler.mjs.map +1 -0
  80. package/dist/cli/produce/setpoint.d.mts +52 -0
  81. package/dist/cli/produce/setpoint.d.mts.map +1 -0
  82. package/dist/cli/produce/setpoint.mjs +113 -0
  83. package/dist/cli/produce/setpoint.mjs.map +1 -0
  84. package/dist/cli/produce/verification-ttl.d.mts +75 -0
  85. package/dist/cli/produce/verification-ttl.d.mts.map +1 -0
  86. package/dist/cli/produce/verification-ttl.mjs +169 -0
  87. package/dist/cli/produce/verification-ttl.mjs.map +1 -0
  88. package/dist/cli/roadmap/{conductor-view.d.mts → showrunner-view.d.mts} +3 -3
  89. package/dist/cli/roadmap/showrunner-view.d.mts.map +1 -0
  90. package/dist/cli/roadmap/{conductor-view.mjs → showrunner-view.mjs} +7 -7
  91. package/dist/cli/roadmap/showrunner-view.mjs.map +1 -0
  92. package/dist/plugin/.claude-plugin/plugin.json +2 -1
  93. package/dist/plugin/skills/apt/SKILL.md +112 -38
  94. package/dist/plugin/skills/apt-debug/SKILL.md +14 -24
  95. package/dist/plugin/skills/apt-fan-out/SKILL.md +4 -4
  96. package/dist/plugin/skills/apt-handoff/SKILL.md +1 -1
  97. package/dist/plugin/skills/apt-plan/SKILL.md +5 -5
  98. package/dist/plugin/skills/apt-plan/adapters/{conductor.md → showrunner.md} +16 -16
  99. package/dist/plugin/skills/apt-produce/SKILL.md +606 -0
  100. package/dist/plugin/skills/apt-quick/SKILL.md +14 -22
  101. package/dist/plugin/skills/apt-run/SKILL.md +126 -3
  102. package/dist/plugin/skills/apt-ship/SKILL.md +2 -0
  103. package/dist/plugin/skills/apt-spar/SKILL.md +5 -3
  104. package/dist/plugin/skills/apt-watch-ci/SKILL.md +4 -4
  105. package/package.json +4 -4
  106. package/prompts/{conductor-framework-context.md → showrunner-framework-context.md} +1 -1
  107. package/prompts/{conductor-status-check.md → showrunner-status-check.md} +1 -1
  108. package/prompts/{conductor-sub-agent.md → showrunner-sub-agent.md} +6 -6
  109. package/prompts/{conductor-system.md → showrunner-system.md} +8 -8
  110. package/skills/apt/SKILL.md +112 -38
  111. package/skills/apt-debug/SKILL.md +14 -24
  112. package/skills/apt-fan-out/SKILL.md +4 -4
  113. package/skills/apt-handoff/SKILL.md +1 -1
  114. package/skills/apt-plan/SKILL.md +5 -5
  115. package/skills/apt-plan/adapters/{conductor.md → showrunner.md} +16 -16
  116. package/skills/apt-produce/SKILL.md +606 -0
  117. package/skills/apt-quick/SKILL.md +14 -22
  118. package/skills/apt-run/SKILL.md +126 -3
  119. package/skills/apt-ship/SKILL.md +2 -0
  120. package/skills/apt-spar/SKILL.md +5 -3
  121. package/skills/apt-watch-ci/SKILL.md +4 -4
  122. package/src/cli/commands/ci-watch.mjs +51 -2
  123. package/src/cli/commands/commit.mjs +3 -3
  124. package/src/cli/commands/event.mjs +16 -16
  125. package/src/cli/commands/merge-integrate.mjs +3 -3
  126. package/src/cli/commands/produce.mjs +1466 -0
  127. package/src/cli/commands/task.mjs +482 -285
  128. package/src/cli/coordination/auto-emit-artifact-ready.mjs +5 -5
  129. package/src/cli/coordination/event-schema.d.ts +4 -2
  130. package/src/cli/coordination/event-schema.mjs +276 -21
  131. package/src/cli/coordination/store.mjs +4 -4
  132. package/src/cli/dispatch.mjs +2 -0
  133. package/src/cli/help.mjs +30 -0
  134. package/src/cli/install/legacy-paths.mjs +2 -0
  135. package/src/cli/produce/blind-probe.mjs +245 -0
  136. package/src/cli/produce/claim.mjs +543 -0
  137. package/src/cli/produce/done-gate.mjs +238 -0
  138. package/src/cli/produce/events.mjs +131 -0
  139. package/src/cli/produce/evidence-oracle.mjs +133 -0
  140. package/src/cli/produce/ledger.mjs +284 -0
  141. package/src/cli/produce/probe-family.mjs +168 -0
  142. package/src/cli/produce/projection.mjs +105 -0
  143. package/src/cli/produce/run-id.mjs +84 -0
  144. package/src/cli/produce/saga.mjs +303 -0
  145. package/src/cli/produce/scheduler.mjs +423 -0
  146. package/src/cli/produce/setpoint.mjs +122 -0
  147. package/src/cli/produce/verification-ttl.mjs +191 -0
  148. package/src/cli/roadmap/showrunner-view.d.ts +10 -0
  149. package/src/cli/roadmap/{conductor-view.mjs → showrunner-view.mjs} +6 -6
  150. package/dist/cli/roadmap/conductor-view.d.mts.map +0 -1
  151. package/dist/cli/roadmap/conductor-view.mjs.map +0 -1
  152. package/src/cli/roadmap/conductor-view.d.ts +0 -10
@@ -106,6 +106,7 @@ export const LEGACY_INSTALL_PATHS = Object.freeze({
106
106
  'agents/apt-personas.md',
107
107
  'agents/apt-plan.md',
108
108
  'agents/apt-pr-review.md',
109
+ 'agents/apt-produce.md',
109
110
  'agents/apt-prototype.md',
110
111
  'agents/apt-quick.md',
111
112
  'agents/apt-release-notes.md',
@@ -151,6 +152,7 @@ export const LEGACY_INSTALL_PATHS = Object.freeze({
151
152
  'commands/apt-personas.md',
152
153
  'commands/apt-plan.md',
153
154
  'commands/apt-pr-review.md',
155
+ 'commands/apt-produce.md',
154
156
  'commands/apt-prototype.md',
155
157
  'commands/apt-quick.md',
156
158
  'commands/apt-release-notes.md',
@@ -1 +1 @@
1
- {"version":3,"file":"legacy-paths.mjs","sourceRoot":"","sources":["../../../src/cli/install/legacy-paths.mjs"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"legacy-paths.mjs","sourceRoot":"","sources":["../../../src/cli/install/legacy-paths.mjs"],"names":[],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ /** The probes/<milestone>.json path for a run + milestone. */
2
+ export function probeSetPathFor(projectDir: any, runId: any, milestoneId: any): string;
3
+ /** Read + parse a frozen probe set. Returns null when absent or malformed. */
4
+ export function readProbeSet(projectDir: any, runId: any, milestoneId: any): any;
5
+ /**
6
+ * Freeze a blind-probe set for a milestone, idempotently. REFUSES fail-closed
7
+ * when the author family equals the implementer family (a held-out probe an
8
+ * implementer authored is not held out — ID-06) or when no implementer family
9
+ * is recorded (ID-M2-02). On a FRESH freeze appends `produce.probe.frozen`
10
+ * carrying ONLY the hash + author family (never the content). A second freeze
11
+ * returns the byte-identical stored set (`reused: true`) and never re-logs.
12
+ *
13
+ * @param {string} projectDir
14
+ * @param {string} runId
15
+ * @param {string} milestoneId
16
+ * @param {{ content: unknown, authorFamily: string, implementerFamily: string }} args
17
+ * @param {Date} [now]
18
+ * @returns {{ ok: true, reused: boolean, probe_set_hash: string, author_family: string }
19
+ * | { ok: false, reason: string }}
20
+ */
21
+ export function freezeProbeSet(projectDir: string, runId: string, milestoneId: string, { content, authorFamily, implementerFamily }: {
22
+ content: unknown;
23
+ authorFamily: string;
24
+ implementerFamily: string;
25
+ }, now?: Date): {
26
+ ok: true;
27
+ reused: boolean;
28
+ probe_set_hash: string;
29
+ author_family: string;
30
+ } | {
31
+ ok: false;
32
+ reason: string;
33
+ };
34
+ /**
35
+ * Record a blind-probe RUN result. REFUSES fail-closed when the probe family
36
+ * equals the implementer family (a probe run BY the implementer family is not
37
+ * cross-family — ID-08) or when no implementer family is recorded. On
38
+ * acceptance appends `produce.probe.run {run_id, milestone_id, result,
39
+ * probe_family, head_sha}` — result/family/head_sha only, never content.
40
+ *
41
+ * @param {string} projectDir
42
+ * @param {{ runId: string, milestoneId: string, result: string, probeFamily: string, headSha: string }} args
43
+ * @returns {{ ok: true, result: string, probe_family: string, head_sha: string }
44
+ * | { ok: false, reason: string }}
45
+ */
46
+ export function recordProbeRun(projectDir: string, { runId, milestoneId, result, probeFamily, headSha }: {
47
+ runId: string;
48
+ milestoneId: string;
49
+ result: string;
50
+ probeFamily: string;
51
+ headSha: string;
52
+ }): {
53
+ ok: true;
54
+ result: string;
55
+ probe_family: string;
56
+ head_sha: string;
57
+ } | {
58
+ ok: false;
59
+ reason: string;
60
+ };
61
+ /**
62
+ * Select a DETERMINISTIC rotating sample of already-`done` milestones for blind
63
+ * re-probing against HEAD (US-6). Rotates by fewest prior probe runs first,
64
+ * then oldest last-probe-run first (a never-probed done milestone sorts first),
65
+ * then first-seen roadmap order — so two folds of the same log select the same
66
+ * sample.
67
+ *
68
+ * @param {string} projectDir
69
+ * @param {string} runId
70
+ * @param {{ sample?: number }} [opts]
71
+ * @returns {{ run_id: string, sample_size: number, selected: Array<{ milestone_id: string, title: string, probe_run_count: number, last_probe_run_at: string | null }> }}
72
+ */
73
+ export function selectSweepSample(projectDir: string, runId: string, { sample }?: {
74
+ sample?: number;
75
+ }): {
76
+ run_id: string;
77
+ sample_size: number;
78
+ selected: Array<{
79
+ milestone_id: string;
80
+ title: string;
81
+ probe_run_count: number;
82
+ last_probe_run_at: string | null;
83
+ }>;
84
+ };
85
+ //# sourceMappingURL=blind-probe.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blind-probe.d.mts","sourceRoot":"","sources":["../../../src/cli/produce/blind-probe.mjs"],"names":[],"mappings":"AA4CA,8DAA8D;AAC9D,uFAEC;AAED,8EAA8E;AAC9E,iFAQC;AAkBD;;;;;;;;;;;;;;;GAeG;AACH,2CARW,MAAM,SACN,MAAM,eACN,MAAM,gDACN;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAA;CAAE,QACrE,IAAI,GACF;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,cAAc,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,GAClF;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAgEnC;AAED;;;;;;;;;;;GAWG;AACH,2CALW,MAAM,wDACN;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC1F;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC1E;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAqBnC;AAED;;;;;;;;;;;GAWG;AACH,8CALW,MAAM,SACN,MAAM,eACN;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GACjB;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,KAAK,CAAC;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAC;QAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAA;CAAE,CA6CxK"}
@@ -0,0 +1,217 @@
1
+ /**
2
+ * @internal
3
+ * produce/blind-probe.mjs — the held-out cross-family blind-probe set (M2, AC4-6).
4
+ *
5
+ * A fixed 10–20 behavioral probe set the implementer/Showrunner NEVER sees
6
+ * (probe-blindness, US-4 / ID-06), authored + run by a provider family DISJOINT
7
+ * from the implementer's, re-run on a rotating sample of already-done milestones
8
+ * against HEAD (US-6).
9
+ *
10
+ * The probe SET is a frozen immutable artifact at
11
+ * `.aperant/produce/<run-id>/probes/<milestone>.json`, written ONCE via
12
+ * `openSync(path, 'wx')` exclusive-create — a second freeze throws EEXIST and
13
+ * returns the byte-identical stored set (mirrors setpoint.mjs::freezeSetpoint).
14
+ * Its CONTENT never enters the event log or the roadmap projection the
15
+ * Showrunner re-reads each tick (structural probe-blindness, ID-M2-03): the
16
+ * `produce.probe.frozen` event carries ONLY `{probe_set_hash, author_family}`
17
+ * and `produce.probe.run` carries ONLY `{result, probe_family, head_sha}`.
18
+ */
19
+ import { createHash } from 'node:crypto';
20
+ import { closeSync, existsSync, fsyncSync, mkdirSync, openSync, readFileSync, writeSync, } from 'node:fs';
21
+ import { join } from 'node:path';
22
+ import { appendProduceEvent, readImplementerFamily, readProduceRunEventsMatching, } from './events.mjs';
23
+ import { normalizeFamily } from './probe-family.mjs';
24
+ import { projectRoadmap } from './projection.mjs';
25
+ import { resolveRunDir } from './run-id.mjs';
26
+ /** sha256 of the canonical JSON of the probe content (the immutable hash stamp). */
27
+ function computeProbeSetHash(content) {
28
+ return createHash('sha256').update(JSON.stringify(content)).digest('hex');
29
+ }
30
+ /** The probes/<milestone>.json path for a run + milestone. */
31
+ export function probeSetPathFor(projectDir, runId, milestoneId) {
32
+ return join(resolveRunDir(projectDir, runId), 'probes', `${milestoneId}.json`);
33
+ }
34
+ /** Read + parse a frozen probe set. Returns null when absent or malformed. */
35
+ export function readProbeSet(projectDir, runId, milestoneId) {
36
+ const p = probeSetPathFor(projectDir, runId, milestoneId);
37
+ if (!existsSync(p))
38
+ return null;
39
+ try {
40
+ return JSON.parse(readFileSync(p, 'utf-8'));
41
+ }
42
+ catch {
43
+ return null;
44
+ }
45
+ }
46
+ /**
47
+ * Exclusive-create write of the frozen probe set on the FINAL path (NOT
48
+ * tmp+rename), so a SECOND write throws EEXIST — the set is immutable.
49
+ */
50
+ function writeProbeSetExclusive(probePath, probeSet) {
51
+ mkdirSync(join(probePath, '..'), { recursive: true });
52
+ const payload = `${JSON.stringify(probeSet, null, 2)}\n`;
53
+ const fd = openSync(probePath, 'wx'); // throws EEXIST when already frozen
54
+ try {
55
+ writeSync(fd, payload, 0, 'utf-8');
56
+ fsyncSync(fd);
57
+ }
58
+ finally {
59
+ closeSync(fd);
60
+ }
61
+ }
62
+ /**
63
+ * Freeze a blind-probe set for a milestone, idempotently. REFUSES fail-closed
64
+ * when the author family equals the implementer family (a held-out probe an
65
+ * implementer authored is not held out — ID-06) or when no implementer family
66
+ * is recorded (ID-M2-02). On a FRESH freeze appends `produce.probe.frozen`
67
+ * carrying ONLY the hash + author family (never the content). A second freeze
68
+ * returns the byte-identical stored set (`reused: true`) and never re-logs.
69
+ *
70
+ * @param {string} projectDir
71
+ * @param {string} runId
72
+ * @param {string} milestoneId
73
+ * @param {{ content: unknown, authorFamily: string, implementerFamily: string }} args
74
+ * @param {Date} [now]
75
+ * @returns {{ ok: true, reused: boolean, probe_set_hash: string, author_family: string }
76
+ * | { ok: false, reason: string }}
77
+ */
78
+ export function freezeProbeSet(projectDir, runId, milestoneId, { content, authorFamily, implementerFamily }, now = new Date()) {
79
+ if (!authorFamily)
80
+ return { ok: false, reason: 'no_author_family' };
81
+ if (!implementerFamily)
82
+ return { ok: false, reason: 'no_implementer_family' };
83
+ // Cross-family enforcement (normalized so claude-code === claude).
84
+ if (normalizeFamily(authorFamily) === normalizeFamily(implementerFamily))
85
+ return { ok: false, reason: 'same_family_author' };
86
+ const probePath = probeSetPathFor(projectDir, runId, milestoneId);
87
+ const existing = readProbeSet(projectDir, runId, milestoneId);
88
+ if (existing)
89
+ return {
90
+ ok: true,
91
+ reused: true,
92
+ probe_set_hash: existing.probe_set_hash,
93
+ author_family: existing.author_family,
94
+ };
95
+ const probeSetHash = computeProbeSetHash(content ?? null);
96
+ const probeSet = {
97
+ run_id: runId,
98
+ milestone_id: milestoneId,
99
+ author_family: authorFamily,
100
+ frozen_at: now.toISOString(),
101
+ probe_set_hash: probeSetHash,
102
+ // The probe CONTENT lives in the frozen file (blind to the projection) —
103
+ // it NEVER enters the event log.
104
+ probes: content ?? null,
105
+ };
106
+ try {
107
+ writeProbeSetExclusive(probePath, probeSet);
108
+ }
109
+ catch (e) {
110
+ // Lost a concurrent race — the winner's file is authoritative; re-read it
111
+ // byte-identically rather than overwriting (mirrors freezeSetpoint).
112
+ if (e && e.code === 'EEXIST') {
113
+ const winner = readProbeSet(projectDir, runId, milestoneId);
114
+ if (winner)
115
+ return {
116
+ ok: true,
117
+ reused: true,
118
+ probe_set_hash: winner.probe_set_hash,
119
+ author_family: winner.author_family,
120
+ };
121
+ }
122
+ throw e;
123
+ }
124
+ // Announce by hash + author family ONLY — never the content (ID-M2-03).
125
+ appendProduceEvent(projectDir, 'produce.probe.frozen', {
126
+ run_id: runId,
127
+ milestone_id: milestoneId,
128
+ probe_set_hash: probeSetHash,
129
+ author_family: authorFamily,
130
+ });
131
+ return { ok: true, reused: false, probe_set_hash: probeSetHash, author_family: authorFamily };
132
+ }
133
+ /**
134
+ * Record a blind-probe RUN result. REFUSES fail-closed when the probe family
135
+ * equals the implementer family (a probe run BY the implementer family is not
136
+ * cross-family — ID-08) or when no implementer family is recorded. On
137
+ * acceptance appends `produce.probe.run {run_id, milestone_id, result,
138
+ * probe_family, head_sha}` — result/family/head_sha only, never content.
139
+ *
140
+ * @param {string} projectDir
141
+ * @param {{ runId: string, milestoneId: string, result: string, probeFamily: string, headSha: string }} args
142
+ * @returns {{ ok: true, result: string, probe_family: string, head_sha: string }
143
+ * | { ok: false, reason: string }}
144
+ */
145
+ export function recordProbeRun(projectDir, { runId, milestoneId, result, probeFamily, headSha }) {
146
+ if (result !== 'pass' && result !== 'fail')
147
+ return { ok: false, reason: 'invalid_result' };
148
+ if (!probeFamily)
149
+ return { ok: false, reason: 'no_probe_family' };
150
+ if (!headSha)
151
+ return { ok: false, reason: 'no_head_sha' };
152
+ const implementerFamily = readImplementerFamily(projectDir, runId, milestoneId);
153
+ if (!implementerFamily)
154
+ return { ok: false, reason: 'no_recorded_implementer' };
155
+ if (normalizeFamily(probeFamily) === normalizeFamily(implementerFamily))
156
+ return { ok: false, reason: 'same_family_probe' };
157
+ appendProduceEvent(projectDir, 'produce.probe.run', {
158
+ run_id: runId,
159
+ milestone_id: milestoneId,
160
+ result,
161
+ probe_family: probeFamily,
162
+ head_sha: headSha,
163
+ });
164
+ return { ok: true, result, probe_family: probeFamily, head_sha: headSha };
165
+ }
166
+ /**
167
+ * Select a DETERMINISTIC rotating sample of already-`done` milestones for blind
168
+ * re-probing against HEAD (US-6). Rotates by fewest prior probe runs first,
169
+ * then oldest last-probe-run first (a never-probed done milestone sorts first),
170
+ * then first-seen roadmap order — so two folds of the same log select the same
171
+ * sample.
172
+ *
173
+ * @param {string} projectDir
174
+ * @param {string} runId
175
+ * @param {{ sample?: number }} [opts]
176
+ * @returns {{ run_id: string, sample_size: number, selected: Array<{ milestone_id: string, title: string, probe_run_count: number, last_probe_run_at: string | null }> }}
177
+ */
178
+ export function selectSweepSample(projectDir, runId, { sample = 1 } = {}) {
179
+ const roadmap = projectRoadmap(projectDir, runId);
180
+ const done = roadmap.milestones.filter((m) => m.status === 'done');
181
+ const runEvents = readProduceRunEventsMatching(projectDir, runId, (op) => op === 'produce.probe.run');
182
+ const stats = new Map();
183
+ for (const e of runEvents) {
184
+ const id = e.data && typeof e.data.milestone_id === 'string' ? e.data.milestone_id : null;
185
+ if (!id)
186
+ continue;
187
+ const s = stats.get(id) || { count: 0, last: null };
188
+ s.count += 1;
189
+ if (typeof e.t === 'string' && (s.last === null || e.t > s.last))
190
+ s.last = e.t;
191
+ stats.set(id, s);
192
+ }
193
+ const withOrder = done.map((m, idx) => {
194
+ const s = stats.get(m.id) || { count: 0, last: null };
195
+ return { milestone: m, order: idx, count: s.count, last: s.last };
196
+ });
197
+ withOrder.sort((a, b) => {
198
+ if (a.count !== b.count)
199
+ return a.count - b.count; // fewest probe runs first
200
+ // oldest last-probe-run first — a never-probed done milestone (null) sorts
201
+ // ahead of any dated one.
202
+ const al = a.last ?? '';
203
+ const bl = b.last ?? '';
204
+ if (al !== bl)
205
+ return al < bl ? -1 : 1;
206
+ return a.order - b.order; // first-seen roadmap order (stable tiebreak)
207
+ });
208
+ const n = Number.isFinite(sample) && sample > 0 ? Math.floor(sample) : 1;
209
+ const selected = withOrder.slice(0, n).map((w) => ({
210
+ milestone_id: w.milestone.id,
211
+ title: w.milestone.title,
212
+ probe_run_count: w.count,
213
+ last_probe_run_at: w.last,
214
+ }));
215
+ return { run_id: runId, sample_size: selected.length, selected };
216
+ }
217
+ //# sourceMappingURL=blind-probe.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blind-probe.mjs","sourceRoot":"","sources":["../../../src/cli/produce/blind-probe.mjs"],"names":[],"mappings":"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"}
@@ -0,0 +1,188 @@
1
+ /**
2
+ * Validate a Claim Envelope by dispatching on `envelope.profile` through the
3
+ * REGISTRY (never a hardcoded profile branch — ID-M6-02). An unknown/absent
4
+ * profile fails closed (`{ ok:false, reason:'unknown_profile' }`). Never throws.
5
+ *
6
+ * @param {Record<string, unknown>} envelope
7
+ * @param {{ profiles?: Record<string, { validate: (env: Record<string, unknown>) => { ok: boolean, reason?: string } }> }} [opts]
8
+ * @returns {{ ok: true } | { ok: false, reason: string }}
9
+ */
10
+ export function validateClaimEnvelope(envelope: Record<string, unknown>, { profiles }?: {
11
+ profiles?: Record<string, {
12
+ validate: (env: Record<string, unknown>) => {
13
+ ok: boolean;
14
+ reason?: string;
15
+ };
16
+ }>;
17
+ }): {
18
+ ok: true;
19
+ } | {
20
+ ok: false;
21
+ reason: string;
22
+ };
23
+ /**
24
+ * Mint a claim id: `<slug-of-text>-<rand>`. Reuses `slugFromOutcome` + a short
25
+ * random suffix (mirrors ledger.mjs::mintCriterionId) so two claims minted from
26
+ * the same text never collide. Falls back to the profile when text is empty.
27
+ *
28
+ * @param {string} profile
29
+ * @param {string} text
30
+ * @returns {string}
31
+ */
32
+ export function mintClaimId(profile: string, text: string): string;
33
+ /** The claims/<claim-id>.json path for a run + claim. */
34
+ export function claimPathFor(projectDir: any, runId: any, claimId: any): string;
35
+ /** Read + parse a frozen claim record. Returns null when absent or malformed. */
36
+ export function readClaim(projectDir: any, runId: any, claimId: any): any;
37
+ /**
38
+ * Freeze a Claim Envelope, idempotently. VALIDATES first (refuses to freeze an
39
+ * invalid envelope — fail-closed), computes `content_hash = sha256(envelope)`,
40
+ * writes `claims/<claim-id>.json` exclusive-create, and on a FRESH freeze appends
41
+ * `produce.claim.declared {run_id, profile, claim_id, content_hash}` (content_hash
42
+ * only — the full envelope lives in the frozen file, ID-M6-07). A second freeze
43
+ * of the same claim id returns the byte-identical stored record (`reused: true`)
44
+ * and never re-logs. The resolved `profile` (explicit arg or `envelope.profile`)
45
+ * is authoritative for validation dispatch + the stored/logged profile.
46
+ *
47
+ * @param {string} projectDir
48
+ * @param {string} runId
49
+ * @param {{ profile?: string, envelope: Record<string, unknown>, claimId?: string }} args
50
+ * @param {{ profiles?: object, now?: Date }} [opts]
51
+ * @returns {{ ok: true, reused: boolean, claim_id: string, profile: string | null, content_hash: string }
52
+ * | { ok: false, reason: string }}
53
+ */
54
+ export function freezeClaim(projectDir: string, runId: string, { profile, envelope, claimId }?: {
55
+ profile?: string;
56
+ envelope: Record<string, unknown>;
57
+ claimId?: string;
58
+ }, { profiles, now }?: {
59
+ profiles?: object;
60
+ now?: Date;
61
+ }): {
62
+ ok: true;
63
+ reused: boolean;
64
+ claim_id: string;
65
+ profile: string | null;
66
+ content_hash: string;
67
+ } | {
68
+ ok: false;
69
+ reason: string;
70
+ };
71
+ /**
72
+ * Fold the run's claim ledger from the append-only log — a SEPARATE fold parallel
73
+ * to `ledger.mjs::projectLedger` / `saga.mjs::projectSaga` (the roadmap projection
74
+ * still folds `produce.roadmap.*` ONLY, so claim ops never enter the roadmap the
75
+ * Showrunner re-reads). A `produce.claim.declared` seeds an ACTIVE claim (in
76
+ * first-seen order); a `produce.claim.expired` advances it to `expired`;
77
+ * `produce.claim.consumed` is a forensic-only event that does NOT change status.
78
+ * Deterministic — two folds of the same log yield the identical ledger.
79
+ *
80
+ * @param {string} projectDir
81
+ * @param {string} runId
82
+ * @returns {{
83
+ * run_id: string,
84
+ * claims: Array<{ claim_id: string, profile: string | null, content_hash: string | null, status: 'active' | 'expired' }>,
85
+ * active_count: number,
86
+ * expired_count: number,
87
+ * updated_at: string | null,
88
+ * }}
89
+ */
90
+ export function projectClaims(projectDir: string, runId: string): {
91
+ run_id: string;
92
+ claims: Array<{
93
+ claim_id: string;
94
+ profile: string | null;
95
+ content_hash: string | null;
96
+ status: "active" | "expired";
97
+ }>;
98
+ active_count: number;
99
+ expired_count: number;
100
+ updated_at: string | null;
101
+ };
102
+ /**
103
+ * Decide whether a claim may be consumed against a ctx (ID-M6-04, anti-corrosion).
104
+ * DETERMINISTIC (no LLM). SKIPS with a reason when: the claim is time-expired
105
+ * (`now() > expiry.expires_at` → `expired`); the claim's `revalidate_against_head`
106
+ * check no longer matches HEAD (`headCheck(check) === false` → `head_invalidated`);
107
+ * or the preconditions don't match ctx (`precondition_unmatched`). Otherwise
108
+ * `{ consume: true }`. `now` + `headCheck` are INJECTED (default now = new Date,
109
+ * default headCheck = the working-tree path-exists/grep).
110
+ *
111
+ * @param {Record<string, unknown>} claim — the claim ENVELOPE (carries expiry + preconditions).
112
+ * @param {Record<string, unknown>} [ctx]
113
+ * @param {{ now?: () => Date, headCheck?: (check: unknown) => boolean }} [deps]
114
+ * @returns {{ consume: true } | { consume: false, reason: string }}
115
+ */
116
+ export function evaluateClaimForConsumption(claim: Record<string, unknown>, ctx?: Record<string, unknown>, deps?: {
117
+ now?: () => Date;
118
+ headCheck?: (check: unknown) => boolean;
119
+ }): {
120
+ consume: true;
121
+ } | {
122
+ consume: false;
123
+ reason: string;
124
+ };
125
+ /**
126
+ * Consume the run's ACTIVE claims against a ctx (ID-M6-06 — THE M6 invariant).
127
+ * For each active claim, evaluate it; a consumable claim emits ONE bounded delta
128
+ * `{ claim_id, profile, targets: [{ kind, requirement, ref? }] }` where every
129
+ * `targets[].kind ∈ CLAIM_TARGET_KINDS` and `requirement` is derived FROM
130
+ * `resolution_verifier` — a projection DOWN. The output MUST NOT carry the claim's
131
+ * `provenance` / `negative_evidence` / `preconditions` / body (never a context
132
+ * paste). Skipped claims (expired / head_invalidated / precondition_unmatched /
133
+ * unreadable) surface under `skipped[]` with a reason. PURE — appends no event
134
+ * (the CLI records `produce.claim.consumed` per target for the forensic trail).
135
+ *
136
+ * @param {string} projectDir
137
+ * @param {string} runId
138
+ * @param {Record<string, unknown>} [ctx]
139
+ * @param {{ now?: () => Date, headCheck?: (check: unknown) => boolean }} [deps]
140
+ * @returns {{
141
+ * consumed: Array<{ claim_id: string, profile: string | null, targets: Array<{ kind: string, requirement: string, ref?: string }> }>,
142
+ * skipped: Array<{ claim_id: string, reason: string }>,
143
+ * }}
144
+ */
145
+ export function consumeClaims(projectDir: string, runId: string, ctx?: Record<string, unknown>, deps?: {
146
+ now?: () => Date;
147
+ headCheck?: (check: unknown) => boolean;
148
+ }): {
149
+ consumed: Array<{
150
+ claim_id: string;
151
+ profile: string | null;
152
+ targets: Array<{
153
+ kind: string;
154
+ requirement: string;
155
+ ref?: string;
156
+ }>;
157
+ }>;
158
+ skipped: Array<{
159
+ claim_id: string;
160
+ reason: string;
161
+ }>;
162
+ };
163
+ export namespace CLAIM_PROFILES {
164
+ namespace lesson {
165
+ export let requiredFields: string[];
166
+ export { validateLessonEnvelope as validate };
167
+ }
168
+ }
169
+ /** The closed set of consumption-delta target kinds (mirrors ALLOWED_CLAIM_TARGET_KINDS). */
170
+ export const CLAIM_TARGET_KINDS: string[];
171
+ /**
172
+ * The `lesson` profile validator (ID-M6-03). REQUIRES all 6 AC15 fields and
173
+ * REJECTS fail-closed (never throws): missing provenance; empty preconditions
174
+ * (unconditional rule — bounded-critic clamp); global/unbounded scope
175
+ * (anti-windup); missing expiry (anti-corrosion); missing negative_evidence
176
+ * field; empty resolution_verifier. Returns `{ ok:false, reason }`.
177
+ *
178
+ * @param {Record<string, unknown>} env
179
+ * @returns {{ ok: true } | { ok: false, reason: string }}
180
+ */
181
+ declare function validateLessonEnvelope(env: Record<string, unknown>): {
182
+ ok: true;
183
+ } | {
184
+ ok: false;
185
+ reason: string;
186
+ };
187
+ export {};
188
+ //# sourceMappingURL=claim.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claim.d.mts","sourceRoot":"","sources":["../../../src/cli/produce/claim.mjs"],"names":[],"mappings":"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"}