@allocator-one/rcl 4.5.13 → 4.5.14
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 +2 -0
- package/dist/converge/launch-guard.d.ts +28 -1
- package/dist/converge/launch-guard.js +113 -4
- package/dist/converge/launch-guard.js.map +1 -1
- package/dist/dispatch/journaled-council.d.ts +56 -0
- package/dist/dispatch/journaled-council.js +158 -0
- package/dist/dispatch/journaled-council.js.map +1 -0
- package/dist/index.js +66 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -49,7 +49,7 @@ import { DEFAULT_CONVERGE_ATTEMPT_CAP, claimConvergeAttempt, ConvergeAttemptBudg
|
|
|
49
49
|
import { DEFAULT_CONVERGE_ROUND_CAP, HARD_CONVERGE_ROUND_CAP, processRoundReport, recordVerdicts, findingGatingReason, ConvergeRoundCapError, ConvergeRunStateError, } from './converge/run-state.js';
|
|
50
50
|
import { applyRoundGap, previewRoundGap } from './converge/round-gap.js';
|
|
51
51
|
import { withNativeTarget } from './converge/target-ownership.js';
|
|
52
|
-
import { guardReviewLaunch, ReviewLaunchRefused } from './converge/launch-guard.js';
|
|
52
|
+
import { guardReviewLaunch, ReviewCouncilInterrupted, ReviewLaunchRefused } from './converge/launch-guard.js';
|
|
53
53
|
import { selectCurrentRecoveredProduction } from './converge/recovered-production.js';
|
|
54
54
|
import { createBoundFixRecovery } from './converge/bound-fix-recovery.js';
|
|
55
55
|
import { openReadSink } from './telemetry/read-sink.js';
|
|
@@ -87,7 +87,8 @@ import { exportOrdinaryPendingPackage, retainOrdinaryLaunchInputs } from './conv
|
|
|
87
87
|
import { capturePreparedCouncil } from './dispatch/capture-council.js';
|
|
88
88
|
import { executeCapturedOriginal } from './dispatch/original-execution.js';
|
|
89
89
|
import { resolveFinalizedAsyncExecution } from './dispatch/checkpoint-async-store.js';
|
|
90
|
-
import { exportCheckpointProof } from './dispatch/checkpoint.js';
|
|
90
|
+
import { CheckpointJournal, checkpointPath, exportCheckpointProof } from './dispatch/checkpoint.js';
|
|
91
|
+
import { runJournaledCouncil } from './dispatch/journaled-council.js';
|
|
91
92
|
import { captureAggregationInputs, AGGREGATION_ALGORITHM } from './report/aggregation-inputs.js';
|
|
92
93
|
import { decodeSupplementalAsync } from './report/supplemental-async.js';
|
|
93
94
|
import { projectCheckpointReport } from './report/checkpoint-projection.js';
|
|
@@ -253,6 +254,7 @@ program
|
|
|
253
254
|
.option('--resume-async-sha256 <hashes>', 'Comma-separated SHA-256 bindings for every legacy async result retained as historical evidence')
|
|
254
255
|
.option('--retry-reason <reason>', 'Explicit bounded recovery decision for a previous failed or unknown launch; never resets caps')
|
|
255
256
|
.option('--max-attempts <n>', 'Guarded convergence: explicitly authorized attempt cap (omitting preserves the cap)')
|
|
257
|
+
.option('--max-slice-minutes <n>', 'Guarded convergence: start no new reviewer call after N minutes; running calls finish, then exit 5. Rerunning the same command resumes without a new attempt')
|
|
256
258
|
.option('--max-rounds <n>', 'Guarded convergence: explicitly authorized round cap (2–99; omitting preserves the cap)')
|
|
257
259
|
.option('--no-telemetry', 'Do not deliver this review as evidence to Harness')
|
|
258
260
|
.option('--evidence-required', 'Exit 4 unless Harness acknowledged the evidence (spools first; retry with rcl telemetry flush)')
|
|
@@ -1763,8 +1765,11 @@ async function runReview(target, opts) {
|
|
|
1763
1765
|
catch { /* Startup delivery remains best-effort for legacy reviews. */ }
|
|
1764
1766
|
}
|
|
1765
1767
|
if (!opts.guardedConverge && (opts.launchIntent !== undefined || opts.retryReason !== undefined || opts.retryReport !== undefined ||
|
|
1766
|
-
opts.maxAttempts !== undefined || opts.maxRounds !== undefined)) {
|
|
1767
|
-
throw new ReviewLaunchRefused('guard_required', 'Launch intent, retry reason
|
|
1768
|
+
opts.maxAttempts !== undefined || opts.maxRounds !== undefined || opts.maxSliceMinutes !== undefined)) {
|
|
1769
|
+
throw new ReviewLaunchRefused('guard_required', 'Launch intent, retry reason, launch caps and slice budgets require --guarded-converge.');
|
|
1770
|
+
}
|
|
1771
|
+
if (opts.maxSliceMinutes !== undefined && (!/^[1-9]\d{0,3}$/.test(opts.maxSliceMinutes) || Number(opts.maxSliceMinutes) > 1440)) {
|
|
1772
|
+
throw new ReviewLaunchRefused('invalid_slice_budget', '--max-slice-minutes must be a whole number of minutes from 1 to 1440.');
|
|
1768
1773
|
}
|
|
1769
1774
|
if (opts.guardedConverge) {
|
|
1770
1775
|
const converge = resolveConvergeContext(opts, reviewConvergeEnvironment(opts));
|
|
@@ -1912,7 +1917,8 @@ async function runReview(target, opts) {
|
|
|
1912
1917
|
console.error(err);
|
|
1913
1918
|
}
|
|
1914
1919
|
process.exitCode = opts.guardedConverge && (err instanceof ConvergeAttemptBudgetExceededError || err instanceof ConvergeRoundCapError)
|
|
1915
|
-
? 2 : opts.guardedConverge && (err instanceof ConvergeAttemptStateError || err instanceof ConvergeRunStateError) ? 3
|
|
1920
|
+
? 2 : opts.guardedConverge && (err instanceof ConvergeAttemptStateError || err instanceof ConvergeRunStateError) ? 3
|
|
1921
|
+
: opts.guardedConverge && err instanceof ReviewCouncilInterrupted ? 5 : 1;
|
|
1916
1922
|
}
|
|
1917
1923
|
}
|
|
1918
1924
|
/**
|
|
@@ -2218,10 +2224,38 @@ async function executeCouncil(spinner, prepared, diff, opts, extra, preparedWork
|
|
|
2218
2224
|
}
|
|
2219
2225
|
return result.completion;
|
|
2220
2226
|
}
|
|
2227
|
+
// Journal the ordinary council so an interrupted process resumes without
|
|
2228
|
+
// repeating successful calls (RCL-80). Without an exact head and base, or
|
|
2229
|
+
// inputs beyond the capture limits, dispatch stays unjournaled.
|
|
2230
|
+
let ordinaryPlan;
|
|
2231
|
+
if (/^[a-f0-9]{40}$/.test(extra.target.headSha ?? '') && /^[a-f0-9]{40}$/.test(extra.target.baseSha ?? '')) {
|
|
2232
|
+
try {
|
|
2233
|
+
ordinaryPlan = capturePreparedCouncil({ target: prepared.converge.target,
|
|
2234
|
+
headSha: extra.target.headSha, mergeBaseSha: extra.target.baseSha, diff, assignments,
|
|
2235
|
+
lanes: assignments.map(item => assignmentLane(item.model, prepared.coreModels, prepared.explicit)),
|
|
2236
|
+
chunks, prompts, config, specBytes: prepared.specContent ?? '', contextDocs,
|
|
2237
|
+
compatibility: { parser: { name: 'findings-json', version: 1 }, aggregation: AGGREGATION_ALGORITHM } }).plan;
|
|
2238
|
+
}
|
|
2239
|
+
catch (error) {
|
|
2240
|
+
process.stderr.write(`Council journal unavailable (${scrubText(String(error), 200)}); an interrupted run cannot resume.\n`);
|
|
2241
|
+
}
|
|
2242
|
+
}
|
|
2243
|
+
const journalPlan = ordinaryPlan;
|
|
2244
|
+
if (opts.maxSliceMinutes !== undefined && !journalPlan) {
|
|
2245
|
+
throw new ReviewLaunchRefused('slice_budget_unavailable', '--max-slice-minutes needs a journaled council (an exact head and base within the capture limits); rerun without it.');
|
|
2246
|
+
}
|
|
2221
2247
|
const claim = await guardReviewLaunch({
|
|
2222
2248
|
gitCommonDir: await resolveGitCommonDir(),
|
|
2223
2249
|
target: prepared.converge.target,
|
|
2224
2250
|
startOver: opts.startOver, cycleRemote,
|
|
2251
|
+
...(journalPlan ? { ordinaryCheckpoint: { exists: async (namespace) => {
|
|
2252
|
+
try {
|
|
2253
|
+
return !!await CheckpointJournal.openRead(checkpointPath(common, prepared.converge.target, namespace), journalPlan);
|
|
2254
|
+
}
|
|
2255
|
+
catch {
|
|
2256
|
+
return false;
|
|
2257
|
+
}
|
|
2258
|
+
} } } : {}),
|
|
2225
2259
|
boundFixRecovery,
|
|
2226
2260
|
recoverySource: prepared.converge.recovery_source,
|
|
2227
2261
|
headSha: extra.target.headSha ?? '',
|
|
@@ -2263,8 +2297,10 @@ async function executeCouncil(spinner, prepared, diff, opts, extra, preparedWork
|
|
|
2263
2297
|
if (boundFixRecovery)
|
|
2264
2298
|
process.stderr.write(`Bound fix recovery verified from run ${boundFixRecovery.runId}; attempt ${claim.attempt} retains the existing review history.\n`);
|
|
2265
2299
|
},
|
|
2266
|
-
run: async (converge) => {
|
|
2267
|
-
|
|
2300
|
+
run: async (converge, ownership, _original, checkpoint) => {
|
|
2301
|
+
if (checkpoint?.resumed)
|
|
2302
|
+
process.stderr.write(`Resuming the interrupted council of attempt ${converge.attempt}; journaled calls are not repeated.\n`);
|
|
2303
|
+
const guardedCompletion = await executeCouncil(spinner, { ...prepared, converge }, diff, { ...opts, guardedConverge: false, exclusiveOutputs: true }, { ...extra, ...(checkpoint && journalPlan ? { ordinaryCheckpoint: { ...checkpoint, ownership, plan: journalPlan } } : {}) }, work);
|
|
2268
2304
|
if (!guardedCompletion)
|
|
2269
2305
|
throw new Error('guarded_launch_missing_completion');
|
|
2270
2306
|
completion = guardedCompletion;
|
|
@@ -2289,7 +2325,7 @@ async function executeCouncil(spinner, prepared, diff, opts, extra, preparedWork
|
|
|
2289
2325
|
let asyncStoreDir;
|
|
2290
2326
|
let asyncKey;
|
|
2291
2327
|
let asyncLaunched = 0;
|
|
2292
|
-
if (!extra.pendingResume &&
|
|
2328
|
+
if (!extra.pendingResume && !extra.ordinaryCheckpoint?.resumed &&
|
|
2293
2329
|
asyncTargetLabel !== undefined &&
|
|
2294
2330
|
(asyncAssignments.length > 0 || (config.asyncModels?.length ?? 0) > 0)) {
|
|
2295
2331
|
try {
|
|
@@ -2396,8 +2432,8 @@ async function executeCouncil(spinner, prepared, diff, opts, extra, preparedWork
|
|
|
2396
2432
|
policy: { version: 1, fraction: config.quorumFraction ?? DEFAULT_QUORUM_FRACTION } });
|
|
2397
2433
|
chunkReviews = pendingProjection.seatReviews.map(seat => structuredClone(seat.review));
|
|
2398
2434
|
}
|
|
2399
|
-
else
|
|
2400
|
-
|
|
2435
|
+
else {
|
|
2436
|
+
const ordinaryRunner = {
|
|
2401
2437
|
// Fall back to the shared constants, never to inline literals:
|
|
2402
2438
|
// duplicated defaults drift (this read 120_000 after the default
|
|
2403
2439
|
// moved to 600_000).
|
|
@@ -2418,7 +2454,26 @@ async function executeCouncil(spinner, prepared, diff, opts, extra, preparedWork
|
|
|
2418
2454
|
blocking: chunkAssignments.map((ca) => assignmentLane(ca.assignment.model, prepared.coreModels, prepared.explicit) === 'blocking'),
|
|
2419
2455
|
},
|
|
2420
2456
|
onReviewComplete: (review) => progress.complete(review),
|
|
2421
|
-
}
|
|
2457
|
+
};
|
|
2458
|
+
const checkpoint = extra.ordinaryCheckpoint;
|
|
2459
|
+
if (checkpoint) {
|
|
2460
|
+
const open = { commonDir: await resolveGitCommonDir(), namespace: checkpoint.namespace,
|
|
2461
|
+
plan: checkpoint.plan, ownership: checkpoint.ownership };
|
|
2462
|
+
const journal = await (checkpoint.resumed ? CheckpointJournal.openWrite(open) : CheckpointJournal.create(open));
|
|
2463
|
+
const sliceEndsAt = opts.maxSliceMinutes === undefined ? undefined : Date.now() + Number(opts.maxSliceMinutes) * 60_000;
|
|
2464
|
+
const journaled = await runJournaledCouncil({ journal, ownership: checkpoint.ownership,
|
|
2465
|
+
assignments: chunkAssignments.map((ca) => ca.assignment), prompts, runner: ordinaryRunner,
|
|
2466
|
+
...(sliceEndsAt === undefined ? {} : { admit: () => Date.now() < sliceEndsAt }) });
|
|
2467
|
+
if (journaled.retained > 0)
|
|
2468
|
+
process.stderr.write(`Reused ${journaled.retained} journaled call(s) from the interrupted council.\n`);
|
|
2469
|
+
if (journaled.interrupted) {
|
|
2470
|
+
throw new ReviewCouncilInterrupted(journaled.reviews.filter(review => review.status !== 'canceled').length, totalCalls);
|
|
2471
|
+
}
|
|
2472
|
+
chunkReviews = journaled.reviews;
|
|
2473
|
+
}
|
|
2474
|
+
else
|
|
2475
|
+
chunkReviews = await runReviews(chunkAssignments.map((ca) => ca.assignment), prompts, ordinaryRunner);
|
|
2476
|
+
}
|
|
2422
2477
|
}
|
|
2423
2478
|
finally {
|
|
2424
2479
|
progress.stop();
|