ai-foreman 1.7.29 → 2.0.1
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 +1 -1
- package/dist/adapters/claude.d.ts +23 -12
- package/dist/adapters/claude.js +231 -26
- package/dist/adapters/codex.d.ts +19 -7
- package/dist/adapters/codex.js +202 -19
- package/dist/adapters/recovering.d.ts +2 -0
- package/dist/adapters/recovering.js +5 -1
- package/dist/adapters/structured.d.ts +71 -0
- package/dist/adapters/structured.js +213 -0
- package/dist/adapters/types.d.ts +85 -9
- package/dist/agentRun.d.ts +2 -0
- package/dist/agentRun.js +2 -1
- package/dist/boundedTurnEvidence.d.ts +18 -0
- package/dist/boundedTurnEvidence.js +76 -0
- package/dist/branch/currentGuard.d.ts +2 -0
- package/dist/branch/currentGuard.js +2 -0
- package/dist/branch/git.js +3 -8
- package/dist/branch/planner.js +1 -4
- package/dist/branch/runner.d.ts +2 -1
- package/dist/branch/runner.js +10 -7
- package/dist/buildAdmission.js +4 -0
- package/dist/buildApproval.d.ts +15 -0
- package/dist/buildApproval.js +28 -9
- package/dist/buildAssignment.d.ts +1 -0
- package/dist/buildAssignment.js +82 -23
- package/dist/buildInterventions.d.ts +2 -2
- package/dist/buildInterventions.js +11 -4
- package/dist/buildLaunchGate.js +3 -2
- package/dist/buildRuns.d.ts +1 -0
- package/dist/buildRuns.js +6 -1
- package/dist/builderGuidanceFollowup.js +17 -6
- package/dist/cli/doctor.js +3 -1
- package/dist/cli/manager.js +22 -20
- package/dist/cli/start.js +85 -39
- package/dist/cli/tickets.d.ts +0 -8
- package/dist/cli/tickets.js +50 -60
- package/dist/continuity.d.ts +10 -16
- package/dist/continuity.js +223 -208
- package/dist/continuityOrigin.d.ts +13 -0
- package/dist/continuityOrigin.js +91 -0
- package/dist/dispatchNotSent.d.ts +4 -0
- package/dist/dispatchNotSent.js +10 -0
- package/dist/foreman.d.ts +15 -16
- package/dist/foreman.js +70 -278
- package/dist/gitExclude.d.ts +16 -0
- package/dist/gitExclude.js +46 -0
- package/dist/graph/boundary.d.ts +1 -1
- package/dist/graph/boundary.js +1 -1
- package/dist/graph/host.js +8 -19
- package/dist/graph/manager.d.ts +1 -1
- package/dist/graph/manager.js +1 -1
- package/dist/graph/preparation.d.ts +38 -0
- package/dist/graph/preparation.js +7 -6
- package/dist/graph/semantic.d.ts +1 -0
- package/dist/graph/semantic.js +4 -1
- package/dist/graph/session.js +7 -2
- package/dist/graph/turn.d.ts +3 -4
- package/dist/graph/turn.js +29 -41
- package/dist/handoffProtocol.js +2 -2
- package/dist/handoffs.d.ts +5 -3
- package/dist/handoffs.js +92 -88
- package/dist/hostGraphApplicability.d.ts +2 -1
- package/dist/hostGraphApplicability.js +17 -19
- package/dist/hostQaAugmentation.js +21 -4
- package/dist/hostQaComparison.d.ts +21 -2
- package/dist/hostQaComparison.js +43 -29
- package/dist/hostSourcePreservation.d.ts +38 -0
- package/dist/hostSourcePreservation.js +72 -0
- package/dist/humanDecision.d.ts +7 -0
- package/dist/humanDecision.js +11 -0
- package/dist/interviews.d.ts +7 -0
- package/dist/interviews.js +18 -1
- package/dist/legacyCommunicationDisplay.d.ts +2 -0
- package/dist/legacyCommunicationDisplay.js +2 -0
- package/dist/managerPacket.js +3 -3
- package/dist/markers.d.ts +4 -3
- package/dist/markers.js +4 -20
- package/dist/observability.js +3 -8
- package/dist/probeIpc.d.ts +14 -0
- package/dist/probeIpc.js +29 -0
- package/dist/qaBuildGate.d.ts +21 -0
- package/dist/qaBuildGate.js +60 -13
- package/dist/qaBuilderCoverage.js +22 -13
- package/dist/qaBuilderEvidence.d.ts +16 -1
- package/dist/qaBuilderEvidence.js +48 -8
- package/dist/qaContractCoverage.d.ts +2 -2
- package/dist/qaContractCoverage.js +4 -9
- package/dist/qaContractDelivery.js +34 -20
- package/dist/qaCoverageAssembly.d.ts +22 -0
- package/dist/qaCoverageAssembly.js +16 -0
- package/dist/qaDeliveryJournal.d.ts +2 -0
- package/dist/qaDeliveryJournal.js +19 -0
- package/dist/qaFailureDelivery.js +97 -85
- package/dist/qaHostTransformation.d.ts +26 -0
- package/dist/qaHostTransformation.js +100 -0
- package/dist/qaPreparation.d.ts +8 -20
- package/dist/qaPreparation.js +153 -254
- package/dist/qaPreparationInputs.js +19 -0
- package/dist/qaPreparationStore.d.ts +11 -0
- package/dist/qaPreparationStore.js +44 -4
- package/dist/qaPrerequisites.d.ts +2 -1
- package/dist/qaPrerequisites.js +21 -1
- package/dist/qaProtocolV2.d.ts +15 -0
- package/dist/qaRecovery.d.ts +0 -3
- package/dist/qaRecovery.js +21 -27
- package/dist/qaReview.js +241 -406
- package/dist/qaReviewEvidence.d.ts +7 -3
- package/dist/qaReviewEvidence.js +15 -4
- package/dist/qaRuntime.js +1 -1
- package/dist/qaSnapshot.js +76 -21
- package/dist/qaStructuredResponse.d.ts +18 -0
- package/dist/qaStructuredResponse.js +81 -0
- package/dist/qaTimeline.js +2 -2
- package/dist/qaVerificationContract.d.ts +1 -2
- package/dist/qaVerificationContract.js +24 -35
- package/dist/readinessGate.js +5 -4
- package/dist/recoveryOwners.d.ts +32 -0
- package/dist/recoveryOwners.js +87 -0
- package/dist/runtimePreflight.d.ts +11 -0
- package/dist/runtimePreflight.js +77 -0
- package/dist/runtimeReadiness.js +23 -15
- package/dist/sources/sourceRegistry.d.ts +0 -3
- package/dist/sources/sourceRegistry.js +0 -42
- package/dist/statusReporter.d.ts +2 -0
- package/dist/statusReporter.js +2 -0
- package/dist/structuredCutover.d.ts +31 -0
- package/dist/structuredCutover.js +510 -0
- package/dist/structuredCutoverFiles.d.ts +10 -0
- package/dist/structuredCutoverFiles.js +181 -0
- package/dist/structuredDispatchAuthority.d.ts +22 -0
- package/dist/structuredDispatchAuthority.js +110 -0
- package/dist/structuredDispatchRecord.d.ts +29 -0
- package/dist/structuredDispatchRecord.js +36 -0
- package/dist/structuredLiveBudget.d.ts +2 -0
- package/dist/structuredLiveBudget.js +23 -0
- package/dist/structuredOperation.d.ts +18 -0
- package/dist/structuredOperation.js +279 -0
- package/dist/supervisedStart.js +35 -21
- package/dist/ticketPlanning.d.ts +1 -376
- package/dist/ticketPlanning.js +2 -49
- package/dist/ticketPopulation.d.ts +0 -3
- package/dist/ticketPopulation.js +4 -21
- package/dist/ticketPopulationPageAuthority.d.ts +13 -0
- package/dist/ticketPopulationPageAuthority.js +30 -0
- package/dist/ticketPopulationPaging.d.ts +27 -0
- package/dist/ticketPopulationPaging.js +127 -0
- package/dist/tickets/renderMarkdown.d.ts +14 -0
- package/dist/tickets/renderMarkdown.js +39 -5
- package/dist/tickets/ticketLoader.js +10 -0
- package/dist/tickets/ticketSchema.d.ts +107 -0
- package/dist/tickets/ticketSchema.js +4 -1
- package/dist/workflowDb.d.ts +116 -3
- package/dist/workflowDb.js +852 -61
- package/dist/workflowReader.d.ts +1 -0
- package/dist/workflowReader.js +9 -0
- package/package.json +23 -7
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime environment checks that must run before Rafi's main modules load.
|
|
3
|
+
* Uses only Node built-ins so it still reports clearly on an unsupported
|
|
4
|
+
* Node, where importing the CLI itself fails with an opaque SyntaxError.
|
|
5
|
+
*/
|
|
6
|
+
import { readFileSync } from "node:fs";
|
|
7
|
+
import { createRequire } from "node:module";
|
|
8
|
+
import { fileURLToPath } from "node:url";
|
|
9
|
+
const REINSTALL_FIX = "reinstall Rafi under the active Node (npm install -g @rafi-ai/cli); in a Rafi workspace run `corepack pnpm install --frozen-lockfile`";
|
|
10
|
+
function packageJson() {
|
|
11
|
+
try {
|
|
12
|
+
return JSON.parse(readFileSync(fileURLToPath(new URL("../package.json", import.meta.url)), "utf8"));
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return {};
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/** Minimal semver check for the range forms Rafi declares: "24.x", "^13.0.3", "13.0.3". */
|
|
19
|
+
export function satisfiesRange(version, range) {
|
|
20
|
+
const parse = (value) => value.replace(/^[v^~=]/, "").split(".").map(part => Number.parseInt(part, 10));
|
|
21
|
+
const [major, minor = 0, patch = 0] = parse(version);
|
|
22
|
+
const spec = range.trim();
|
|
23
|
+
if (/^\d+\.x(\.x)?$/.test(spec))
|
|
24
|
+
return major === Number.parseInt(spec, 10);
|
|
25
|
+
const [wantMajor, wantMinor = 0, wantPatch = 0] = parse(spec);
|
|
26
|
+
if (spec.startsWith("^"))
|
|
27
|
+
return major === wantMajor && (minor > wantMinor || minor === wantMinor && patch >= wantPatch);
|
|
28
|
+
return major === wantMajor && minor === wantMinor && patch === wantPatch;
|
|
29
|
+
}
|
|
30
|
+
export function checkRuntimeEnvironment() {
|
|
31
|
+
const pkg = packageJson();
|
|
32
|
+
const checks = [];
|
|
33
|
+
const nodeRange = pkg.engines?.node;
|
|
34
|
+
const nodeSupported = !nodeRange || satisfiesRange(process.versions.node, nodeRange);
|
|
35
|
+
if (nodeRange) {
|
|
36
|
+
const ok = nodeSupported;
|
|
37
|
+
checks.push({ ok, label: `node ${nodeRange}`, detail: `${process.version} (${process.execPath})`,
|
|
38
|
+
...(ok ? {} : { fix: `run Rafi with Node ${nodeRange}, e.g. \`nvm use 24\`, and reinstall it there` }) });
|
|
39
|
+
}
|
|
40
|
+
const sqliteRange = pkg.dependencies?.["better-sqlite3"];
|
|
41
|
+
const require = createRequire(import.meta.url);
|
|
42
|
+
let installed;
|
|
43
|
+
try {
|
|
44
|
+
installed = require("better-sqlite3/package.json").version;
|
|
45
|
+
}
|
|
46
|
+
catch { /* reported below */ }
|
|
47
|
+
if (sqliteRange) {
|
|
48
|
+
const ok = Boolean(installed && satisfiesRange(installed, sqliteRange));
|
|
49
|
+
checks.push({ ok, label: `better-sqlite3 ${sqliteRange}`, detail: installed ? `installed ${installed}` : "not installed",
|
|
50
|
+
...(ok ? {} : { fix: `the installed native SQLite module does not match the declared version; ${REINSTALL_FIX}` }) });
|
|
51
|
+
}
|
|
52
|
+
// Only probe the native binding on a supported Node with the declared
|
|
53
|
+
// version: under an unsupported Node the probe can abort the process
|
|
54
|
+
// (uncatchable N-API fatal error, seen on Node 18), and a mismatched module
|
|
55
|
+
// may load and then crash later (seen with 12.10 under Node 24).
|
|
56
|
+
if (nodeSupported && installed && (!sqliteRange || satisfiesRange(installed, sqliteRange))) {
|
|
57
|
+
try {
|
|
58
|
+
const Database = require("better-sqlite3");
|
|
59
|
+
new Database(":memory:").close();
|
|
60
|
+
checks.push({ ok: true, label: "native SQLite loads", detail: `Node ABI ${process.versions.modules}` });
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
64
|
+
const abi = /NODE_MODULE_VERSION (\d+)/.exec(message)?.[1];
|
|
65
|
+
checks.push({ ok: false, label: "native SQLite loads", detail: abi ? `built for Node ABI ${abi}, active Node ABI ${process.versions.modules}` : message.split("\n")[0],
|
|
66
|
+
fix: `rebuild the native module for this Node: ${REINSTALL_FIX}` });
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return checks;
|
|
70
|
+
}
|
|
71
|
+
/** Text for a failed preflight, or undefined when every check passed. */
|
|
72
|
+
export function runtimePreflightFailure(checks = checkRuntimeEnvironment()) {
|
|
73
|
+
const failed = checks.filter(check => !check.ok);
|
|
74
|
+
if (!failed.length)
|
|
75
|
+
return undefined;
|
|
76
|
+
return ["rafi: this runtime environment cannot run Rafi:", ...failed.map(check => ` - ${check.label}: ${check.detail}${check.fix ? `\n fix: ${check.fix}` : ""}`)].join("\n");
|
|
77
|
+
}
|
package/dist/runtimeReadiness.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ProbeIpcTracker } from "./probeIpc.js";
|
|
1
2
|
import { fileURLToPath } from "node:url";
|
|
2
3
|
import { cleanupReadiness } from "./readinessCleanup.js";
|
|
3
4
|
import { windowsProbeCommand } from "./windowsProbeJob.js";
|
|
@@ -150,26 +151,31 @@ async function probeRuntimeInternal(cwd, runtime, opts) {
|
|
|
150
151
|
let providerSpawnError;
|
|
151
152
|
let providerResult;
|
|
152
153
|
let startupTimer;
|
|
154
|
+
const probeMessages = new ProbeIpcTracker(tag, child.pid);
|
|
153
155
|
if (useHost) {
|
|
154
156
|
startupTimer = setTimeout(() => { startupError = new RuntimeCleanupError("Readiness helper startup timed out"); abort(); }, 15_000);
|
|
155
|
-
child.on("message",
|
|
156
|
-
if (
|
|
157
|
+
child.on("message", raw => {
|
|
158
|
+
if (settled)
|
|
159
|
+
return;
|
|
160
|
+
const message = probeMessages.accept(raw);
|
|
161
|
+
if (message === "conflict") {
|
|
162
|
+
startupError = new RuntimeCleanupError("Readiness helper sent conflicting terminal results");
|
|
163
|
+
abort();
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
if (!message)
|
|
157
167
|
return;
|
|
158
168
|
if (message.kind === "rafi-probe-result") {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
void finish(providerResult.exitCode, providerResult.signal);
|
|
166
|
-
} }, 100).unref();
|
|
167
|
-
}
|
|
169
|
+
providerResult = { exitCode: message.exitCode, signal: message.signal };
|
|
170
|
+
setTimeout(() => { if (!settled) {
|
|
171
|
+
child.stdout?.destroy();
|
|
172
|
+
child.stderr?.destroy();
|
|
173
|
+
void finish(providerResult.exitCode, providerResult.signal);
|
|
174
|
+
} }, 100).unref();
|
|
168
175
|
return;
|
|
169
176
|
}
|
|
170
177
|
if (message.kind === "rafi-probe-spawn-error") {
|
|
171
|
-
|
|
172
|
-
providerSpawnError = Object.assign(new Error(reported.message ?? "Provider could not start"), { code: reported.code });
|
|
178
|
+
providerSpawnError = Object.assign(new Error(message.message), { code: message.code ?? undefined });
|
|
173
179
|
return;
|
|
174
180
|
}
|
|
175
181
|
if (message.kind !== "rafi-probe-registered")
|
|
@@ -186,7 +192,7 @@ async function probeRuntimeInternal(cwd, runtime, opts) {
|
|
|
186
192
|
}
|
|
187
193
|
if (authority && ownedProcess)
|
|
188
194
|
journal.authorizeReadinessHelper(authority, ownedProcess, child.pid);
|
|
189
|
-
child.send("rafi-probe-authorized", error => { if (error) {
|
|
195
|
+
child.send({ version: 1, kind: "rafi-probe-authorized", id: tag, pid: child.pid }, error => { if (error) {
|
|
190
196
|
startupError = error;
|
|
191
197
|
abort();
|
|
192
198
|
} });
|
|
@@ -204,7 +210,7 @@ async function probeRuntimeInternal(cwd, runtime, opts) {
|
|
|
204
210
|
const notifySupervisor = (active) => {
|
|
205
211
|
if (process.send && process.connected && process.env.RAFI_BUILD_WORKER_RUN && child.pid) {
|
|
206
212
|
try {
|
|
207
|
-
process.send({ kind: "rafi-readiness-child", active, tag, pid: child.pid, processStart: active ? processStartIdentity(child.pid) :
|
|
213
|
+
process.send({ version: 1, kind: "rafi-readiness-child", runId: process.env.RAFI_BUILD_WORKER_RUN, generation: Number(process.env.RAFI_BUILD_WORKER_GENERATION), workerPid: process.pid, active, tag, pid: child.pid, processStart: active ? processStartIdentity(child.pid) ?? null : null }, () => { });
|
|
208
214
|
}
|
|
209
215
|
catch { /* Durable ownership survives a disconnected supervisor. */ }
|
|
210
216
|
}
|
|
@@ -253,6 +259,8 @@ async function probeRuntimeInternal(cwd, runtime, opts) {
|
|
|
253
259
|
if (settled)
|
|
254
260
|
return;
|
|
255
261
|
settled = true;
|
|
262
|
+
if (useHost && !probeMessages.terminal && !cancelled && !timedOut && !spawnError)
|
|
263
|
+
startupError ??= new RuntimeCleanupError("Readiness helper exited without a correlated terminal result");
|
|
256
264
|
if (providerResult) {
|
|
257
265
|
exitCode = providerResult.exitCode;
|
|
258
266
|
signal = providerResult.signal;
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import type { ProjectSourceEntry, ProjectSourceLocator, ProjectSourceType, SourceRegistryConfig, SourceSnapshotStorage, TicketSetupSource } from "rafi-spec";
|
|
2
|
-
export declare const SOURCE_REQUEST_START = "RAFI_SOURCE_REQUEST_START";
|
|
3
|
-
export declare const SOURCE_REQUEST_END = "RAFI_SOURCE_REQUEST_END";
|
|
4
2
|
export interface StructuredSourceRequest {
|
|
5
3
|
type?: ProjectSourceType;
|
|
6
4
|
description?: string;
|
|
@@ -38,7 +36,6 @@ export declare function removeSource(registry: SourceRegistryConfig, id: string)
|
|
|
38
36
|
export declare function discardStagedSourceCaptures(projectDir: string, original: SourceRegistryConfig, staged: SourceRegistryConfig): void;
|
|
39
37
|
/** Compatibility bridge for legacy ticket setup callers. Existing entries and versions are retained. */
|
|
40
38
|
export declare function appendLegacyTicketSources(registry: SourceRegistryConfig, sources: TicketSetupSource[]): SourceRegistryConfig;
|
|
41
|
-
export declare function extractSourceRequests(output: string): StructuredSourceRequest[];
|
|
42
39
|
/** Deterministically recognize only an entire obvious locator; all other language stays pending for agent interpretation. */
|
|
43
40
|
export declare function sourceRequestFromAnswer(answer: string, projectDir: string): StructuredSourceRequest;
|
|
44
41
|
export declare function registerSourceRequests(projectDir: string, registry: SourceRegistryConfig, requests: StructuredSourceRequest[], opts?: {
|
|
@@ -8,10 +8,7 @@ import { parse, stringify } from "yaml";
|
|
|
8
8
|
import { fetchAndSnapshotUrl, normalizePublicHttpUrl, snapshotExternalLocalFile } from "../tickets/sourceFetch.js";
|
|
9
9
|
import { fetchJiraIssues, fetchLinearIssues } from "../tickets/importer.js";
|
|
10
10
|
import { withActivityPhase } from "../activity.js";
|
|
11
|
-
import { structuredSourceRequestSchema, zodIssues } from "rafi-spec";
|
|
12
11
|
const execFileAsync = promisify(execFile);
|
|
13
|
-
export const SOURCE_REQUEST_START = "RAFI_SOURCE_REQUEST_START";
|
|
14
|
-
export const SOURCE_REQUEST_END = "RAFI_SOURCE_REQUEST_END";
|
|
15
12
|
const CONFIG_FILE = "rafi-config.yaml";
|
|
16
13
|
const DEFAULT_REGISTRY = { version: 1, snapshot_storage: "local", entries: [] };
|
|
17
14
|
export function emptySourceRegistry(storage = "local") {
|
|
@@ -138,45 +135,6 @@ export function appendLegacyTicketSources(registry, sources) {
|
|
|
138
135
|
migrateTicketSource(next, source, warnings);
|
|
139
136
|
return next;
|
|
140
137
|
}
|
|
141
|
-
export function extractSourceRequests(output) {
|
|
142
|
-
const requests = [];
|
|
143
|
-
let cursor = 0;
|
|
144
|
-
while (true) {
|
|
145
|
-
const start = output.indexOf(SOURCE_REQUEST_START, cursor);
|
|
146
|
-
if (start < 0)
|
|
147
|
-
break;
|
|
148
|
-
const end = output.indexOf(SOURCE_REQUEST_END, start + SOURCE_REQUEST_START.length);
|
|
149
|
-
if (end < 0)
|
|
150
|
-
throw new Error(`source request is missing ${SOURCE_REQUEST_END}`);
|
|
151
|
-
const body = output.slice(start + SOURCE_REQUEST_START.length, end).trim().replace(/^```(?:json)?\s*/i, "").replace(/\s*```$/, "");
|
|
152
|
-
let value;
|
|
153
|
-
try {
|
|
154
|
-
value = JSON.parse(body);
|
|
155
|
-
}
|
|
156
|
-
catch (error) {
|
|
157
|
-
throw new Error(`source request is invalid JSON: ${error instanceof Error ? error.message : String(error)}`);
|
|
158
|
-
}
|
|
159
|
-
const values = Array.isArray(value) ? value : [value];
|
|
160
|
-
for (const item of values) {
|
|
161
|
-
const parsed = structuredSourceRequestSchema.safeParse(item);
|
|
162
|
-
if (!parsed.success)
|
|
163
|
-
throw new Error(`source request contract validation failed:\n${zodIssues(parsed.error).map((issue) => `- ${issue}`).join("\n")}`);
|
|
164
|
-
requests.push(parsed.data);
|
|
165
|
-
}
|
|
166
|
-
cursor = end + SOURCE_REQUEST_END.length;
|
|
167
|
-
}
|
|
168
|
-
// Compatibility with the original single-line protocol. Preserve the complete remainder.
|
|
169
|
-
for (const match of output.matchAll(/^SOURCE_REQUEST:\s*(.+)$/gim)) {
|
|
170
|
-
const legacy = structuredSourceRequestSchema.safeParse({ description: match[1].trim() });
|
|
171
|
-
// Legacy lines are intentionally converted into the same typed contract;
|
|
172
|
-
// they remain description-only pending requests after registration, but
|
|
173
|
-
// they no longer bypass shape validation.
|
|
174
|
-
if (!legacy.success)
|
|
175
|
-
throw new Error(`legacy source request contract validation failed:\n${zodIssues(legacy.error).map((issue) => `- ${issue}`).join("\n")}`);
|
|
176
|
-
requests.push(legacy.data);
|
|
177
|
-
}
|
|
178
|
-
return requests;
|
|
179
|
-
}
|
|
180
138
|
/** Deterministically recognize only an entire obvious locator; all other language stays pending for agent interpretation. */
|
|
181
139
|
export function sourceRequestFromAnswer(answer, projectDir) {
|
|
182
140
|
const value = answer.trim();
|
package/dist/statusReporter.d.ts
CHANGED
|
@@ -74,6 +74,8 @@ export declare class RoleStatusAdapter implements BuilderAdapter {
|
|
|
74
74
|
private readonly adapter;
|
|
75
75
|
private readonly onActive;
|
|
76
76
|
private readonly onClose;
|
|
77
|
+
postConfirmedDispatch(reference: import("./adapters/types.js").ConfirmedDispatchReference): Promise<TurnResult | void>;
|
|
78
|
+
structuredDispatchRequirement(): import("./adapters/types.js").StructuredDispatchRequirement | undefined;
|
|
77
79
|
readonly agent: "claude" | "codex";
|
|
78
80
|
constructor(adapter: BuilderAdapter, onActive: (adapter: BuilderAdapter) => void, onClose: () => void);
|
|
79
81
|
contractCapabilities(): {
|
package/dist/statusReporter.js
CHANGED
|
@@ -164,6 +164,8 @@ export class RoleStatusAdapter {
|
|
|
164
164
|
adapter;
|
|
165
165
|
onActive;
|
|
166
166
|
onClose;
|
|
167
|
+
postConfirmedDispatch(reference) { return this.adapter.postConfirmedDispatch?.(reference) ?? Promise.resolve(); }
|
|
168
|
+
structuredDispatchRequirement() { return this.adapter.structuredDispatchRequirement?.(); }
|
|
167
169
|
agent;
|
|
168
170
|
constructor(adapter, onActive, onClose) {
|
|
169
171
|
this.adapter = adapter;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type Database from "better-sqlite3";
|
|
2
|
+
export declare const STRUCTURED_CUTOVER = "003_structured_communication_v2_cutover";
|
|
3
|
+
export declare const STRUCTURED_AUDIT_CLOSURE = "004_structured_communication_audit_closure";
|
|
4
|
+
export declare const STRUCTURED_CUTOVER_MATRIX_VERSION = 3;
|
|
5
|
+
export declare const STRUCTURED_CUTOVER_REASON = "structured-communication-v2-cutover";
|
|
6
|
+
export declare const STRUCTURED_AUTHORITY_TABLES: readonly string[];
|
|
7
|
+
type Row = Record<string, any>;
|
|
8
|
+
type ForeignKey = {
|
|
9
|
+
id: number;
|
|
10
|
+
seq: number;
|
|
11
|
+
table: string;
|
|
12
|
+
from: string;
|
|
13
|
+
to: string;
|
|
14
|
+
};
|
|
15
|
+
export interface CutoverOwnershipEntry {
|
|
16
|
+
table: string;
|
|
17
|
+
disposition: "retain" | "purge-owned";
|
|
18
|
+
columns: string[];
|
|
19
|
+
foreignKeys: ForeignKey[];
|
|
20
|
+
jsonColumns: string[];
|
|
21
|
+
owner: "retained-artifact" | "run-id" | "foreign-key" | "session-key" | "contract-id" | "json-run-id";
|
|
22
|
+
evidenceReferenceExtractor: "normalized-refs-with-conservative-unknown-retention";
|
|
23
|
+
deletionOrder: number | null;
|
|
24
|
+
}
|
|
25
|
+
export declare function cutoverOwnershipMatrix(db: Database.Database): CutoverOwnershipEntry[];
|
|
26
|
+
export declare function assertStructuredCutoverComplete(db: Database.Database): void;
|
|
27
|
+
/** Classification is structural; JSON spelling or merely containing a tuple key is never proof. */
|
|
28
|
+
export declare function invalidStructuredRun(db: Database.Database, run: Row, projectDir?: string): boolean;
|
|
29
|
+
/** Archive then delete only selected rows. Foreign-key closure computes child ownership and deletion order. */
|
|
30
|
+
export declare function purgeStructuredRun(db: Database.Database, runId: string, matrix: CutoverOwnershipEntry[], fileReferences?: ReadonlySet<string>): number;
|
|
31
|
+
export {};
|