@markstanden/opencode-test-container 0.0.0-stage → 0.1.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 (121) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +263 -2
  3. package/container/Containerfile +24 -0
  4. package/container/README.md +29 -0
  5. package/dist/adapters/opencode/events.d.ts +90 -0
  6. package/dist/adapters/opencode/events.js +213 -0
  7. package/dist/adapters/opencode/runtime.d.ts +87 -0
  8. package/dist/adapters/opencode/runtime.js +136 -0
  9. package/dist/adapters/podman/container.d.ts +62 -0
  10. package/dist/adapters/podman/container.js +119 -0
  11. package/dist/adapters/podman/image.d.ts +50 -0
  12. package/dist/adapters/podman/image.js +124 -0
  13. package/dist/adapters/process.d.ts +38 -0
  14. package/dist/adapters/process.js +71 -0
  15. package/dist/campaign/assess.d.ts +45 -0
  16. package/dist/campaign/assess.js +208 -0
  17. package/dist/campaign/close.d.ts +17 -0
  18. package/dist/campaign/close.js +112 -0
  19. package/dist/campaign/evidence-guard.d.ts +24 -0
  20. package/dist/campaign/evidence-guard.js +49 -0
  21. package/dist/campaign/freeze.d.ts +94 -0
  22. package/dist/campaign/freeze.js +297 -0
  23. package/dist/campaign/inventory.d.ts +62 -0
  24. package/dist/campaign/inventory.js +192 -0
  25. package/dist/campaign/judge.d.ts +209 -0
  26. package/dist/campaign/judge.js +1285 -0
  27. package/dist/campaign/ledger.d.ts +64 -0
  28. package/dist/campaign/ledger.js +149 -0
  29. package/dist/campaign/prepare.d.ts +129 -0
  30. package/dist/campaign/prepare.js +483 -0
  31. package/dist/campaign/primary.d.ts +96 -0
  32. package/dist/campaign/primary.js +189 -0
  33. package/dist/campaign/run.d.ts +151 -0
  34. package/dist/campaign/run.js +562 -0
  35. package/dist/campaign/status.d.ts +76 -0
  36. package/dist/campaign/status.js +237 -0
  37. package/dist/cli/otc.d.ts +51 -0
  38. package/dist/cli/otc.js +435 -0
  39. package/dist/contracts/canonical.d.ts +21 -0
  40. package/dist/contracts/canonical.js +44 -0
  41. package/dist/contracts/types.d.ts +261 -0
  42. package/dist/contracts/types.js +9 -0
  43. package/dist/contracts/validate.d.ts +72 -0
  44. package/dist/contracts/validate.js +1021 -0
  45. package/dist/contracts/version.d.ts +44 -0
  46. package/dist/contracts/version.js +147 -0
  47. package/dist/evaluators/docs/analysis/accounting.d.ts +140 -0
  48. package/dist/evaluators/docs/analysis/accounting.js +237 -0
  49. package/dist/evaluators/docs/analysis/blinding.d.ts +40 -0
  50. package/dist/evaluators/docs/analysis/blinding.js +80 -0
  51. package/dist/evaluators/docs/analysis/bounds.d.ts +40 -0
  52. package/dist/evaluators/docs/analysis/bounds.js +31 -0
  53. package/dist/evaluators/docs/analysis/budget.d.ts +137 -0
  54. package/dist/evaluators/docs/analysis/budget.js +305 -0
  55. package/dist/evaluators/docs/analysis/closure.d.ts +175 -0
  56. package/dist/evaluators/docs/analysis/closure.js +251 -0
  57. package/dist/evaluators/docs/analysis/decision.d.ts +59 -0
  58. package/dist/evaluators/docs/analysis/decision.js +161 -0
  59. package/dist/evaluators/docs/analysis/freeze.d.ts +201 -0
  60. package/dist/evaluators/docs/analysis/freeze.js +395 -0
  61. package/dist/evaluators/docs/analysis/guardrails.d.ts +51 -0
  62. package/dist/evaluators/docs/analysis/guardrails.js +194 -0
  63. package/dist/evaluators/docs/analysis/journal.d.ts +150 -0
  64. package/dist/evaluators/docs/analysis/journal.js +475 -0
  65. package/dist/evaluators/docs/analysis/ledger.d.ts +78 -0
  66. package/dist/evaluators/docs/analysis/ledger.js +145 -0
  67. package/dist/evaluators/docs/analysis/measures.d.ts +302 -0
  68. package/dist/evaluators/docs/analysis/measures.js +1069 -0
  69. package/dist/evaluators/docs/analysis/model.d.ts +236 -0
  70. package/dist/evaluators/docs/analysis/model.js +740 -0
  71. package/dist/evaluators/docs/analysis/pairing.d.ts +68 -0
  72. package/dist/evaluators/docs/analysis/pairing.js +95 -0
  73. package/dist/evaluators/docs/analysis/records.d.ts +229 -0
  74. package/dist/evaluators/docs/analysis/records.js +935 -0
  75. package/dist/evaluators/docs/analysis/recovery.d.ts +225 -0
  76. package/dist/evaluators/docs/analysis/recovery.js +507 -0
  77. package/dist/evaluators/docs/analysis/render.d.ts +235 -0
  78. package/dist/evaluators/docs/analysis/render.js +566 -0
  79. package/dist/evaluators/docs/analysis/replay.d.ts +15 -0
  80. package/dist/evaluators/docs/analysis/replay.js +1272 -0
  81. package/dist/evaluators/docs/analysis/screening/inventory.d.ts +136 -0
  82. package/dist/evaluators/docs/analysis/screening/inventory.js +307 -0
  83. package/dist/evaluators/docs/analysis/screening/noteVersion.d.ts +15 -0
  84. package/dist/evaluators/docs/analysis/screening/noteVersion.js +46 -0
  85. package/dist/evaluators/docs/analysis/screening/reconcile.d.ts +38 -0
  86. package/dist/evaluators/docs/analysis/screening/reconcile.js +40 -0
  87. package/dist/evaluators/docs/analysis/screening/rules.d.ts +163 -0
  88. package/dist/evaluators/docs/analysis/screening/rules.js +330 -0
  89. package/dist/evaluators/docs/analysis/screening/scan.d.ts +72 -0
  90. package/dist/evaluators/docs/analysis/screening/scan.js +362 -0
  91. package/dist/evaluators/docs/analysis/selector.d.ts +68 -0
  92. package/dist/evaluators/docs/analysis/selector.js +123 -0
  93. package/dist/evaluators/docs/assess.d.ts +129 -0
  94. package/dist/evaluators/docs/assess.js +433 -0
  95. package/dist/evaluators/docs/campaign.d.ts +133 -0
  96. package/dist/evaluators/docs/campaign.js +222 -0
  97. package/dist/evaluators/docs/index.d.ts +25 -0
  98. package/dist/evaluators/docs/index.js +25 -0
  99. package/dist/evaluators/docs/journal.d.ts +150 -0
  100. package/dist/evaluators/docs/journal.js +475 -0
  101. package/dist/evaluators/docs/scoring.d.ts +367 -0
  102. package/dist/evaluators/docs/scoring.js +662 -0
  103. package/dist/evaluators/skills/assess.d.ts +94 -0
  104. package/dist/evaluators/skills/assess.js +207 -0
  105. package/dist/index.d.ts +46 -0
  106. package/dist/index.js +29 -0
  107. package/dist/legacy/prod014.d.ts +86 -0
  108. package/dist/legacy/prod014.js +209 -0
  109. package/dist/reporting/report.d.ts +79 -0
  110. package/dist/reporting/report.js +242 -0
  111. package/docs/architecture.md +106 -0
  112. package/docs/capability-matrix.md +84 -0
  113. package/docs/offline-rehearsal.md +75 -0
  114. package/docs/parity-record.md +81 -0
  115. package/docs/pr-description.md +103 -0
  116. package/docs/schema.md +97 -0
  117. package/examples/skills/README.md +13 -0
  118. package/examples/skills/campaign.json +73 -0
  119. package/examples/skills/skills/otel-helper/SKILL.md +10 -0
  120. package/examples/skills/suite.json +29 -0
  121. package/package.json +45 -5
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Structural parsing of the campaign attempt ledger.
3
+ *
4
+ * The ledger is the durable record of what a campaign authorised and launched.
5
+ * It is read as data at a trust boundary: one JSON object per line, with the
6
+ * fields the runner writes. A malformed, truncated or ambiguous ledger never
7
+ * authorises spend — a caller must treat anything but `open`/`closed` with a
8
+ * clean event list as a refusal, not as an empty ledger.
9
+ */
10
+ /** One structurally valid ledger event. */
11
+ export interface LedgerEvent {
12
+ /** Event timestamp, or null when the line carried none. */
13
+ at: string | null;
14
+ /** The recorded event name. */
15
+ event: string;
16
+ /** The trial stamp, when the event names one. */
17
+ stamp: string | null;
18
+ /** The scheduled slot number, when the event names one. */
19
+ slot: number | null;
20
+ /** The attempt id, when the event names one. */
21
+ attemptId: string | null;
22
+ /** The pair id, when the event names one. */
23
+ pairId: string | null;
24
+ /** The arm id, when the event names one. */
25
+ arm: string | null;
26
+ /** The campaign id, when the event names one. */
27
+ campaign: string | null;
28
+ }
29
+ /** The explicit state of one ledger read. */
30
+ export type LedgerState = "missing" | "malformed" | "open" | "closed";
31
+ /** The result of reading a ledger. */
32
+ export interface LedgerParse {
33
+ /** The explicit state; only `open` and `closed` are trustworthy. */
34
+ state: LedgerState;
35
+ /** Every structurally valid event, in file order. */
36
+ events: LedgerEvent[];
37
+ /** Every reason the ledger cannot be trusted, never silently dropped. */
38
+ problems: string[];
39
+ /** The close timestamp, when the ledger records a valid close. */
40
+ closedAt: string | null;
41
+ }
42
+ /**
43
+ * Parse a whole ledger.
44
+ *
45
+ * A blank line is ignored; any other unreadable line makes the ledger
46
+ * `malformed`, because a partial read cannot prove what spend was authorised.
47
+ * A `campaign-closed` event closes the ledger only when every line parsed.
48
+ * @param text The ledger bytes, or undefined when the file is absent.
49
+ * @returns The state, the valid events and every problem.
50
+ */
51
+ export declare function parseCampaignLedger(text: string | undefined): LedgerParse;
52
+ /**
53
+ * Whether a parsed ledger permits a new launch or judge call. Only a clean
54
+ * `open` ledger does; `missing` is refused by campaign policy, not by this
55
+ * predicate, so the caller can distinguish "no campaign yet" from "closed".
56
+ * @param ledger The parse result.
57
+ * @returns True only for a clean open ledger.
58
+ */
59
+ export declare function isOpenLedger(ledger: LedgerParse): boolean;
60
+ /** One scheduled stamp's observed events. */
61
+ export interface StampEvents {
62
+ /** Events naming this stamp, in file order. */
63
+ events: LedgerEvent[];
64
+ /** Trial launch events. */
65
+ launches: number;
66
+ /** Judge launch events. */
67
+ judgeLaunches: number;
68
+ /** Whether a slot-blocked event exists. */
69
+ blocked: boolean;
70
+ /** Whether a slot-complete event exists. */
71
+ complete: boolean;
72
+ }
73
+ /**
74
+ * Group ledger events by stamp, keeping unknown stamps visible.
75
+ * @param events The parsed events.
76
+ * @returns Per-stamp events and the stamps the ledger mentions.
77
+ */
78
+ export declare function eventsByStamp(events: readonly LedgerEvent[]): Map<string, StampEvents>;
@@ -0,0 +1,145 @@
1
+ /**
2
+ * Structural parsing of the campaign attempt ledger.
3
+ *
4
+ * The ledger is the durable record of what a campaign authorised and launched.
5
+ * It is read as data at a trust boundary: one JSON object per line, with the
6
+ * fields the runner writes. A malformed, truncated or ambiguous ledger never
7
+ * authorises spend — a caller must treat anything but `open`/`closed` with a
8
+ * clean event list as a refusal, not as an empty ledger.
9
+ */
10
+ /** Whether a value is a plain JSON object. */
11
+ function isRecord(value) {
12
+ return typeof value === "object" && value !== null && !Array.isArray(value);
13
+ }
14
+ /** A nonblank string, or null. */
15
+ function stringOrNull(value) {
16
+ return typeof value === "string" && value.trim() !== "" ? value : null;
17
+ }
18
+ /** A positive integer, or null. */
19
+ function slotOrNull(value) {
20
+ return typeof value === "number" && Number.isInteger(value) && value >= 1
21
+ ? value
22
+ : null;
23
+ }
24
+ /**
25
+ * Parse one ledger line.
26
+ * @param line The raw line, without its newline.
27
+ * @param index The zero-based line index, for problem messages.
28
+ * @returns The event, or a problem.
29
+ */
30
+ function eventOf(line, index) {
31
+ let value;
32
+ try {
33
+ value = JSON.parse(line);
34
+ }
35
+ catch {
36
+ return { problem: `ledger line ${String(index + 1)} is not JSON` };
37
+ }
38
+ if (!isRecord(value)) {
39
+ return {
40
+ problem: `ledger line ${String(index + 1)} is not a JSON object`,
41
+ };
42
+ }
43
+ const event = stringOrNull(value.event);
44
+ if (event === null) {
45
+ return {
46
+ problem: `ledger line ${String(index + 1)} has no event name`,
47
+ };
48
+ }
49
+ return {
50
+ event: {
51
+ at: stringOrNull(value.at),
52
+ event,
53
+ stamp: stringOrNull(value.stamp),
54
+ slot: slotOrNull(value.slot),
55
+ attemptId: stringOrNull(value.attemptId),
56
+ pairId: stringOrNull(value.pairId),
57
+ arm: stringOrNull(value.arm),
58
+ campaign: stringOrNull(value.campaign),
59
+ },
60
+ };
61
+ }
62
+ /**
63
+ * Parse a whole ledger.
64
+ *
65
+ * A blank line is ignored; any other unreadable line makes the ledger
66
+ * `malformed`, because a partial read cannot prove what spend was authorised.
67
+ * A `campaign-closed` event closes the ledger only when every line parsed.
68
+ * @param text The ledger bytes, or undefined when the file is absent.
69
+ * @returns The state, the valid events and every problem.
70
+ */
71
+ export function parseCampaignLedger(text) {
72
+ if (text === undefined) {
73
+ return {
74
+ state: "missing",
75
+ events: [],
76
+ problems: ["attempt ledger is missing"],
77
+ closedAt: null,
78
+ };
79
+ }
80
+ const events = [];
81
+ const problems = [];
82
+ for (const [index, raw] of text.split("\n").entries()) {
83
+ const line = raw.trim();
84
+ if (line === "")
85
+ continue;
86
+ const parsed = eventOf(line, index);
87
+ if (parsed.event !== undefined)
88
+ events.push(parsed.event);
89
+ if (parsed.problem !== undefined)
90
+ problems.push(parsed.problem);
91
+ }
92
+ if (problems.length > 0) {
93
+ return { state: "malformed", events, problems, closedAt: null };
94
+ }
95
+ const close = events.find((event) => event.event === "campaign-closed");
96
+ if (close !== undefined) {
97
+ return {
98
+ state: "closed",
99
+ events,
100
+ problems: [],
101
+ closedAt: close.at,
102
+ };
103
+ }
104
+ return { state: "open", events, problems: [], closedAt: null };
105
+ }
106
+ /**
107
+ * Whether a parsed ledger permits a new launch or judge call. Only a clean
108
+ * `open` ledger does; `missing` is refused by campaign policy, not by this
109
+ * predicate, so the caller can distinguish "no campaign yet" from "closed".
110
+ * @param ledger The parse result.
111
+ * @returns True only for a clean open ledger.
112
+ */
113
+ export function isOpenLedger(ledger) {
114
+ return ledger.state === "open";
115
+ }
116
+ /**
117
+ * Group ledger events by stamp, keeping unknown stamps visible.
118
+ * @param events The parsed events.
119
+ * @returns Per-stamp events and the stamps the ledger mentions.
120
+ */
121
+ export function eventsByStamp(events) {
122
+ const grouped = new Map();
123
+ for (const event of events) {
124
+ if (event.stamp === null)
125
+ continue;
126
+ const entry = grouped.get(event.stamp) ?? {
127
+ events: [],
128
+ launches: 0,
129
+ judgeLaunches: 0,
130
+ blocked: false,
131
+ complete: false,
132
+ };
133
+ entry.events.push(event);
134
+ if (event.event === "launch")
135
+ entry.launches += 1;
136
+ if (event.event === "judge-launch")
137
+ entry.judgeLaunches += 1;
138
+ if (event.event === "slot-blocked")
139
+ entry.blocked = true;
140
+ if (event.event === "slot-complete")
141
+ entry.complete = true;
142
+ grouped.set(event.stamp, entry);
143
+ }
144
+ return grouped;
145
+ }
@@ -0,0 +1,302 @@
1
+ /**
2
+ * Recording and retrieval opportunity measures for a productivity screen.
3
+ *
4
+ * The frozen utility answers "what did the trial document". These measures
5
+ * answer two different questions that utility does not: was a durable finding
6
+ * recorded through the plugin into the appropriate lake, and was an existing
7
+ * note retrieved and actually applied to the work. They are pure functions
8
+ * over loaded evidence: a missing journal, a missing judgement and an
9
+ * unattributable read each stay explicit and never become a zero or a pass.
10
+ */
11
+ import type { DocumentationOutcome } from "../scoring.ts";
12
+ import type { AccountingCounts } from "./accounting.ts";
13
+ import type { SlotSpec } from "./model.ts";
14
+ import type { TrialRecord } from "./records.ts";
15
+ /** The measurement declaration schema version this module parses. */
16
+ export declare const MEASURES_SCHEMA_VERSION = 1;
17
+ /** One retrieval opportunity's declared note and assessed facts. */
18
+ export interface RetrievalDeclaration {
19
+ /** The lake-relative path of the seeded note. */
20
+ note: string;
21
+ /** The lake the note belongs to; identity is not optional for credit. */
22
+ lake: string;
23
+ /** The preservation facts the note's correction must keep, when any. */
24
+ facts: string[];
25
+ }
26
+ /** The declared eligible scenarios for each opportunity measure. */
27
+ export interface MeasureDeclarations {
28
+ /** Scenarios counted in the unprompted-recording denominator. */
29
+ recording: string[];
30
+ /** Scenarios counted in the unprompted-retrieval denominator. */
31
+ retrieval: Record<string, RetrievalDeclaration>;
32
+ }
33
+ /** The outcome of parsing a measurement declaration. */
34
+ export interface MeasureDeclarationParse {
35
+ /** The validated declarations, when the input is usable. */
36
+ declarations?: MeasureDeclarations;
37
+ /** Every shape problem, so a malformed declaration is visible. */
38
+ problems: string[];
39
+ }
40
+ /** One journal operation, from the plugin's own operation journal. */
41
+ export interface DocsOperation {
42
+ /** The recorded completion status. */
43
+ status: string;
44
+ /** Whether the served result says the operation succeeded. */
45
+ success: boolean | null;
46
+ /** The delivery surface (native, twin, or Code Mode twin). */
47
+ surface: string;
48
+ /** The operation's verb. */
49
+ verb: "add" | "read" | "search" | "check" | "help" | "unknown";
50
+ /** The typed target of a read or add, when present. */
51
+ target: string | null;
52
+ /** The lake the completed operation reports, when present. */
53
+ lake: string | null;
54
+ /** The lake-relative path the completed operation reports, when present. */
55
+ path: string | null;
56
+ /** The raw journal line, for the receipt/evidence trail. */
57
+ line: string;
58
+ }
59
+ /** The recording measure for one trial. */
60
+ export interface RecordingMeasure {
61
+ /** Whether the scenario is in the recording denominator. */
62
+ eligible: boolean;
63
+ /** The deterministic disposition of any write. */
64
+ disposition: "verified-write" | "gate-blocked" | "filesystem-only" | "tool-error" | "no-write" | "unknown" | "not-run" | "not-eligible";
65
+ /** Whether a verified useful plugin-mediated write landed. */
66
+ success: boolean;
67
+ /** The semantic outcome, when the judge recorded one. */
68
+ outcome: DocumentationOutcome | null;
69
+ /** The recorded gate status, when readable. */
70
+ gate: string | null;
71
+ /** Completed add operations, rendered for evidence. */
72
+ writes: string[];
73
+ /** Supporting evidence lines. */
74
+ evidence: string[];
75
+ }
76
+ /** The retrieval measure for one trial. */
77
+ export interface RetrievalMeasure {
78
+ /** Whether the scenario is in the retrieval denominator. */
79
+ eligible: boolean;
80
+ /** The resolved state: applied, miss, unknown, not run or not eligible. */
81
+ state: "applied" | "miss" | "unknown" | "not-run" | "not-eligible";
82
+ /** Whether an attributable completed read of the declared note exists. */
83
+ read: boolean;
84
+ /** The judge's recorded retrieval state, when present. */
85
+ judgeState: string | null;
86
+ /** The declared target note. */
87
+ note: string | null;
88
+ /** The attributable read operation lines. */
89
+ trace: string[];
90
+ /** Supporting evidence lines. */
91
+ evidence: string[];
92
+ }
93
+ /** One trial's measures. */
94
+ export interface TrialMeasures {
95
+ /** The trial stamp. */
96
+ stamp: string;
97
+ /** The scenario. */
98
+ scenario: string;
99
+ /** The arm. */
100
+ arm: string;
101
+ /** The recording measure. */
102
+ recording: RecordingMeasure;
103
+ /** The retrieval measure. */
104
+ retrieval: RetrievalMeasure;
105
+ }
106
+ /** One arm's opportunity counts. */
107
+ export interface ArmMeasureSummary {
108
+ /** Recording out of the planned four. */
109
+ recording: {
110
+ planned: number;
111
+ success: number;
112
+ miss: number;
113
+ unknown: number;
114
+ notRun: number;
115
+ dispositions: Record<string, number>;
116
+ };
117
+ /** Retrieval out of the planned five. */
118
+ retrieval: {
119
+ planned: number;
120
+ applied: number;
121
+ miss: number;
122
+ unknown: number;
123
+ notRun: number;
124
+ states: Record<string, number>;
125
+ };
126
+ }
127
+ /** The campaign measures block published in analysis.json. */
128
+ export interface MeasuresReport {
129
+ /** Whether the declaration was loaded and usable. */
130
+ status: "available" | "missing" | "malformed";
131
+ /** SHA-256 of the declaration bytes, when available. */
132
+ declarationSha256: string | null;
133
+ /** Per-arm opportunity counts. */
134
+ arms: Record<string, ArmMeasureSummary>;
135
+ /** Every trial's measure, eligible or not. */
136
+ trials: TrialMeasures[];
137
+ /** The personal-trial screen, kept separate from the utility threshold. */
138
+ personalTrial: PersonalTrialDecision;
139
+ }
140
+ /** The personal-trial screen's decision. */
141
+ export interface PersonalTrialDecision {
142
+ /** The screen's recommendation. */
143
+ recommendation: "personal-trial" | "no-promotion" | "inconclusive";
144
+ /** Every criterion and how it was decided. */
145
+ reasons: string[];
146
+ /** The analyser's utility-threshold limb, labelled as one component. */
147
+ utilityThreshold: {
148
+ component: "utility-threshold";
149
+ status: string;
150
+ lead: number | null;
151
+ interval: {
152
+ low: number;
153
+ high: number;
154
+ } | null;
155
+ note: string;
156
+ };
157
+ }
158
+ /** One paired scenario's control and candidate documented outcomes. */
159
+ export interface PairedOutcome {
160
+ /** The declared pair id. */
161
+ pairId: string;
162
+ /** The control arm's outcomes in this pair. */
163
+ control: DocumentationOutcome[];
164
+ /** The candidate arm's outcomes in this pair. */
165
+ candidate: DocumentationOutcome[];
166
+ }
167
+ /** A criterion's decision. */
168
+ interface Criterion {
169
+ /** The criterion outcome. */
170
+ status: "pass" | "fail" | "inconclusive";
171
+ /** Supporting reasons. */
172
+ reasons: string[];
173
+ }
174
+ /**
175
+ * Parse and validate the measurement declaration. The declaration is data:
176
+ * every problem is collected instead of throwing.
177
+ * @param value The parsed `measurement.json` value.
178
+ * @returns The declarations or the collected problems.
179
+ */
180
+ export declare function parseMeasureDeclarations(value: unknown): MeasureDeclarationParse;
181
+ /**
182
+ * Parse the plugin journal lines into operations, keeping unreadable lines
183
+ * explicit.
184
+ * @param lines The raw journal lines.
185
+ * @returns The operations and any parse problems.
186
+ */
187
+ export declare function parseOperations(lines: readonly string[]): {
188
+ operations: DocsOperation[];
189
+ problems: string[];
190
+ };
191
+ /**
192
+ * Whether an operation names the declared note path exactly. A suffix match is
193
+ * deliberately not accepted: `shared/db/pool.md` is a different file from
194
+ * `db/pool.md`.
195
+ * @param operation The journal operation.
196
+ * @param declaration The declared note.
197
+ * @returns True when the operation's reported path or target is the note.
198
+ */
199
+ export declare function operationMatchesNotePath(operation: DocsOperation, declaration: RetrievalDeclaration): boolean;
200
+ /**
201
+ * Whether an operation's reported lake matches the declaration. A declaration
202
+ * without a lake accepts only an exact path; a declared lake must match.
203
+ * @param operation The journal operation.
204
+ * @param declaration The declared note.
205
+ * @returns True when the lake identity is satisfied.
206
+ */
207
+ export declare function operationMatchesNoteLake(operation: DocsOperation, declaration: RetrievalDeclaration): boolean;
208
+ /** One lake document the trial's writes report names. */
209
+ export interface ChangedLakeDocument {
210
+ /** The lake the change landed in. */
211
+ lake: string;
212
+ /** The lake-relative path. */
213
+ path: string;
214
+ /** The change kind, when the report names one. */
215
+ kind: "added" | "modified" | "removed" | "unknown";
216
+ }
217
+ /**
218
+ * Read the changed lake documents from a trial's writes report.
219
+ *
220
+ * Only `lakes/<lake>/<path>` entries are documents; a work-file change never
221
+ * makes a documentation write verified. An unreadable report is a problem, not
222
+ * an empty change set.
223
+ * @param writes The recorded writes report.
224
+ * @param writes.state The report's explicit load state.
225
+ * @param writes.text The report's text.
226
+ * @returns The changed documents and any parse problem.
227
+ */
228
+ export declare function changedLakeDocuments(writes: {
229
+ state: string;
230
+ text: string;
231
+ }): {
232
+ documents: ChangedLakeDocument[];
233
+ problem: string | null;
234
+ };
235
+ /**
236
+ * Whether a completed plugin write targets exactly one changed document.
237
+ * @param operation The completed add operation.
238
+ * @param document The evidenced changed document.
239
+ * @returns True when lake and relative path agree.
240
+ */
241
+ export declare function operationMatchesChangedDocument(operation: DocsOperation, document: ChangedLakeDocument): boolean;
242
+ /**
243
+ * Measure one trial against the declared opportunities.
244
+ * @param record The loaded trial record.
245
+ * @param declarations The validated declarations.
246
+ * @param arm The declared arm id.
247
+ * @returns The trial measures.
248
+ */
249
+ export declare function measureTrial(record: TrialRecord, declarations: MeasureDeclarations, arm: string): TrialMeasures;
250
+ /**
251
+ * Summarise the measures per arm.
252
+ * @param trials The trial measures.
253
+ * @param planned The frozen slots.
254
+ * @param declarations The validated declarations.
255
+ * @returns The per-arm counts.
256
+ */
257
+ export declare function summariseMeasures(trials: readonly TrialMeasures[], planned: readonly SlotSpec[], declarations: MeasureDeclarations): Record<string, ArmMeasureSummary>;
258
+ /**
259
+ * The paired scenario criterion: a misleading outcome that appears only on the
260
+ * candidate side of a pair defeats promotion, even when the aggregate counts
261
+ * are equal. A pair where the candidate is not misleading, or both sides are,
262
+ * is not candidate-specific.
263
+ * @param pairs The complete paired outcomes.
264
+ * @returns The criterion.
265
+ */
266
+ export declare function pairedMisleadingCriterion(pairs: readonly PairedOutcome[]): Criterion;
267
+ /**
268
+ * The personal-trial screen. The utility threshold is one component; the
269
+ * opportunity counts and quality checks decide the recommendation alongside
270
+ * it.
271
+ * @param controlArm The control arm id.
272
+ * @param candidateArm The candidate arm id.
273
+ * @param measures The per-arm opportunity summaries.
274
+ * @param counts The per-arm accounting counts.
275
+ * @param guardrails The candidate arm's aggregate guardrail status and detail.
276
+ * @param guardrails.status The aggregate status (clean, breached, unresolved).
277
+ * @param guardrails.detail The guardrail evidence.
278
+ * @param coverage The assessment-coverage limb.
279
+ * @param coverage.status The limb's status.
280
+ * @param coverage.detail The limb's reason.
281
+ * @param utilityThreshold The analyser's utility-threshold limb.
282
+ * @param utilityThreshold.status The limb's status.
283
+ * @param utilityThreshold.lead The assessed lead.
284
+ * @param utilityThreshold.interval The full-population interval.
285
+ * @param pairs The complete paired scenario outcomes, when available.
286
+ * @returns The recommendation and every criterion's reason.
287
+ */
288
+ export declare function personalTrialDecision(controlArm: string, candidateArm: string, measures: Record<string, ArmMeasureSummary>, counts: Record<string, AccountingCounts>, guardrails: {
289
+ status: string;
290
+ detail: string;
291
+ }, coverage: {
292
+ status: string;
293
+ detail: string;
294
+ }, utilityThreshold: {
295
+ status: string;
296
+ lead: number | null;
297
+ interval: {
298
+ low: number;
299
+ high: number;
300
+ } | null;
301
+ }, pairs?: readonly PairedOutcome[]): PersonalTrialDecision;
302
+ export {};