@allocator-one/rcl 4.5.4 → 4.5.6

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 (64) hide show
  1. package/README.md +5 -4
  2. package/dist/converge/attempt-budget.d.ts +14 -0
  3. package/dist/converge/attempt-budget.js +216 -1
  4. package/dist/converge/attempt-budget.js.map +1 -1
  5. package/dist/converge/launch-guard.js +23 -6
  6. package/dist/converge/launch-guard.js.map +1 -1
  7. package/dist/converge/launch-record.d.ts +36 -0
  8. package/dist/converge/launch-record.js +9 -3
  9. package/dist/converge/launch-record.js.map +1 -1
  10. package/dist/converge/legacy-launch-health.d.ts +36 -0
  11. package/dist/converge/native-lock.d.ts +3 -1
  12. package/dist/converge/native-lock.js +4 -4
  13. package/dist/converge/native-lock.js.map +1 -1
  14. package/dist/converge/ordinary-pending-export.d.ts +3 -0
  15. package/dist/converge/ordinary-pending-export.js +64 -17
  16. package/dist/converge/ordinary-pending-export.js.map +1 -1
  17. package/dist/converge/ordinary-pending-package.d.ts +11 -0
  18. package/dist/converge/ordinary-pending-package.js +18 -4
  19. package/dist/converge/ordinary-pending-package.js.map +1 -1
  20. package/dist/converge/pending-finalization-receipt.d.ts +4 -0
  21. package/dist/converge/pending-finalization-receipt.js +102 -0
  22. package/dist/converge/pending-finalization-receipt.js.map +1 -0
  23. package/dist/converge/pending-legacy-resume.d.ts +48 -3
  24. package/dist/converge/pending-legacy-resume.js +215 -35
  25. package/dist/converge/pending-legacy-resume.js.map +1 -1
  26. package/dist/converge/pending-recovery-source.d.ts +114 -0
  27. package/dist/converge/pending-recovery-source.js +36 -1
  28. package/dist/converge/pending-recovery-source.js.map +1 -1
  29. package/dist/converge/process-identity.d.ts +51 -0
  30. package/dist/converge/process-identity.js +190 -0
  31. package/dist/converge/process-identity.js.map +1 -0
  32. package/dist/converge/recovery-launch.js +39 -17
  33. package/dist/converge/recovery-launch.js.map +1 -1
  34. package/dist/converge/recovery-state.d.ts +55 -0
  35. package/dist/converge/recovery-state.js +306 -0
  36. package/dist/converge/recovery-state.js.map +1 -0
  37. package/dist/converge/run-state.d.ts +39 -1
  38. package/dist/converge/run-state.js +246 -18
  39. package/dist/converge/run-state.js.map +1 -1
  40. package/dist/converge/semantic-state.d.ts +55 -0
  41. package/dist/converge/semantic-state.js +666 -0
  42. package/dist/converge/semantic-state.js.map +1 -0
  43. package/dist/converge/stale-report.d.ts +36 -0
  44. package/dist/dispatch/async-lane.d.ts +12 -0
  45. package/dist/dispatch/async-lane.js +98 -12
  46. package/dist/dispatch/async-lane.js.map +1 -1
  47. package/dist/evidence/claim-recovery/validation/native-state.d.ts +22 -0
  48. package/dist/evidence/claim-recovery/validation/native-state.js +91 -9
  49. package/dist/evidence/claim-recovery/validation/native-state.js.map +1 -1
  50. package/dist/evidence/claim-recovery/validation/obligations.js +2 -1
  51. package/dist/evidence/claim-recovery/validation/obligations.js.map +1 -1
  52. package/dist/evidence/claim-recovery/validation/semantic-validation.d.ts +11 -0
  53. package/dist/evidence/claim-recovery/validation/semantic-validation.js +105 -28
  54. package/dist/evidence/claim-recovery/validation/semantic-validation.js.map +1 -1
  55. package/dist/evidence/claim-recovery/validation/types.d.ts +10 -0
  56. package/dist/evidence/original-run/lock-scope.d.ts +12 -6
  57. package/dist/evidence/original-run/lock-scope.js +12 -9
  58. package/dist/evidence/original-run/lock-scope.js.map +1 -1
  59. package/dist/index.js +59 -13
  60. package/dist/index.js.map +1 -1
  61. package/dist/telemetry/recovery/files.d.ts +4 -0
  62. package/dist/telemetry/recovery/files.js +15 -5
  63. package/dist/telemetry/recovery/files.js.map +1 -1
  64. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"lock-scope.js","sourceRoot":"","sources":["../../../src/evidence/original-run/lock-scope.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lock-scope.js","sourceRoot":"","sources":["../../../src/evidence/original-run/lock-scope.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -33,7 +33,7 @@ import { originalRunReportSchema } from './telemetry/recovery/source.js';
33
33
  import { buildAssignments, detectProvider } from './roles/dispatcher.js';
34
34
  import { defaultAdapterFactory, runReviews } from './dispatch/runner.js';
35
35
  import { mergeChunkReviews } from './dispatch/merge.js';
36
- import { partitionAsyncAssignments, asyncTargetKey, resolveAsyncStoreDir, resolveExistingAsyncStoreDir, spoolAsyncCalls, launchAsyncWorkers, runAsyncWorker, collectAsyncResults, currentBranchLabel, MAX_ASYNC_CALLS_PER_ROUND, snapshotAsyncResults, consumeBoundAsyncResults, } from './dispatch/async-lane.js';
36
+ import { partitionAsyncAssignments, asyncTargetKey, resolveAsyncStoreDir, resolveExistingAsyncStoreDir, spoolAsyncCalls, launchAsyncWorkers, runAsyncWorker, collectAsyncResults, currentBranchLabel, MAX_ASYNC_CALLS_PER_ROUND, snapshotAsyncResults, snapshotAsyncHistory, consumeBoundAsyncResults, } from './dispatch/async-lane.js';
37
37
  import { evaluateCiGate } from './ci.js';
38
38
  import { resolveQuorumPolicy } from './dispatch/quorum.js';
39
39
  import { assertAdmissibleReportHealth, deriveBlockingHealth, describeBlockingHealth, ReportHealthError } from './report/blocking-health.js';
@@ -226,6 +226,7 @@ program
226
226
  .option('--head-sha <sha>', 'Exact head commit a patch file was taken from (patch files only)')
227
227
  .option('--base-sha <sha>', 'Exact base commit a patch file was taken from (patch files only)')
228
228
  .option('--expect-head-sha <sha>', 'Fail fast unless the resolved head commit equals this SHA')
229
+ .option('--expect-pr-head-sha <sha>', 'Finalize-only cycle recovery: fail unless the live pull request remains open at this current head')
229
230
  .option('--spec-source <source>', 'Where --spec came from: flag | repo_file | harness_issue:<ID>')
230
231
  .option('--converge-target <key>', 'Converge target this round belongs to (or RCL_CONVERGE_TARGET)')
231
232
  .option('--for-pr <owner/repo#N>', 'The pull request a patch-file review is evidence for (or RCL_FOR_PR): Harness verifies its head against that pull request')
@@ -237,12 +238,13 @@ program
237
238
  .option('--launch-intent <intent>', 'Guarded intent: review, stop-upstream, stop-review, or retry-delivery')
238
239
  .option('--retry-report <path>', 'Original legacy report proving an inconclusive launch; the new inputs may differ; requires --retry-reason')
239
240
  .option('--resume-pending', 'Finalize an unobservable pending legacy dispatch, then claim one fresh checkpointed retry under its target lock')
240
- .option('--finalize-pending-only', 'Finalize one authenticated ordinary pending launch without claiming or dispatching its successor')
241
+ .option('--finalize-pending-only', 'Finalize one authenticated pending launch without claiming or dispatching its successor')
241
242
  .option('--pending-native-sha256 <digest>', 'Finalize-only: exact native state digest returned by --preview-pending')
242
243
  .option('--pending-attempt-sha256 <digest>', 'Finalize-only: exact attempt state digest returned by --preview-pending')
243
- .option('--export-pending-package <path>', 'Export authenticated ordinary pending inputs to an exclusive private file without provider calls or native writes')
244
+ .option('--pending-preview-sha256 <digest>', 'Changed-head cycle finalize-only: exact preview binding returned by --preview-pending')
245
+ .option('--export-pending-package <path>', 'Export authenticated pending inputs to an exclusive private file without provider calls or native writes')
244
246
  .option('--expect-base-sha <sha>', 'Pending package export: require the resolved current base to equal this SHA')
245
- .option('--ordinary-pending-package <path>', 'Immutable ordinary pending-launch package; requires --resume-pending or --finalize-pending-only and replaces --retry-report')
247
+ .option('--ordinary-pending-package <path>', 'Immutable pending-launch package; requires --resume-pending or --finalize-pending-only and replaces --retry-report')
246
248
  .option('--preview-pending', 'Authenticate pending recovery or preview a pending package export without provider calls')
247
249
  .option('--resume-async-sha256 <hashes>', 'Comma-separated SHA-256 bindings for every legacy async result retained as historical evidence')
248
250
  .option('--retry-reason <reason>', 'Explicit bounded recovery decision for a previous failed or unknown launch; never resets caps')
@@ -1627,7 +1629,7 @@ async function runReview(target, opts) {
1627
1629
  const finalizeOnlyIgnoredReviewFlags = opts.retryReason !== undefined || opts.maxRounds !== undefined ||
1628
1630
  opts.round !== undefined || opts.attempt !== undefined || opts.post || opts.json ||
1629
1631
  opts.jsonFile !== undefined || opts.markdown !== undefined || opts.ci || opts.evidenceRequired ||
1630
- opts.forPr !== undefined || opts.role !== undefined || opts.roles !== undefined ||
1632
+ opts.role !== undefined || opts.roles !== undefined ||
1631
1633
  opts.models !== undefined || opts.secondaryModels !== undefined || opts.asyncModels !== undefined ||
1632
1634
  (opts.reviewer?.length ?? 0) > 0 || (opts.context?.length ?? 0) > 0 ||
1633
1635
  opts.spec !== undefined || opts.focus !== undefined;
@@ -1636,12 +1638,17 @@ async function runReview(target, opts) {
1636
1638
  opts.retryReport !== undefined || !opts.resumeAsyncSha256 || opts.maxAttempts === undefined ||
1637
1639
  (!opts.previewPending && (!opts.pendingNativeSha256 || !opts.pendingAttemptSha256)) ||
1638
1640
  (opts.previewPending && (opts.pendingNativeSha256 !== undefined || opts.pendingAttemptSha256 !== undefined)) ||
1641
+ (opts.expectPrHeadSha !== undefined && !opts.previewPending && !opts.pendingPreviewSha256) ||
1642
+ (opts.pendingPreviewSha256 !== undefined && opts.expectPrHeadSha === undefined) ||
1643
+ (opts.expectPrHeadSha !== undefined && opts.forPr === undefined) ||
1644
+ (opts.previewPending && opts.pendingPreviewSha256 !== undefined) ||
1639
1645
  opts.startOver || opts.boundFixRecovery || opts.attest || opts.launchIntent !== undefined ||
1640
1646
  finalizeOnlyIgnoredReviewFlags || finalizeOnlySourceFlags)) {
1641
1647
  throw new ReviewLaunchRefused('pending_finalize_incompatible', '--finalize-pending-only accepts only guarded target/head/base/config bindings, one ordinary pending package, an explicit unchanged attempt cap, retained async result digests and, for apply, both exact state digests from preview; do not combine it with review, output, evidence or retry flags.');
1642
1648
  }
1643
1649
  if (!opts.finalizePendingOnly &&
1644
- (opts.pendingNativeSha256 !== undefined || opts.pendingAttemptSha256 !== undefined)) {
1650
+ (opts.pendingNativeSha256 !== undefined || opts.pendingAttemptSha256 !== undefined ||
1651
+ opts.pendingPreviewSha256 !== undefined || opts.expectPrHeadSha !== undefined)) {
1645
1652
  throw new ReviewLaunchRefused('pending_finalize_incompatible', 'Pending native and attempt state digests apply only to --finalize-pending-only.');
1646
1653
  }
1647
1654
  if (!opts.resumePending && !opts.finalizePendingOnly &&
@@ -1704,6 +1711,14 @@ async function runReview(target, opts) {
1704
1711
  validateSha(opts.baseSha, '--base-sha');
1705
1712
  if (opts.expectHeadSha !== undefined)
1706
1713
  validateSha(opts.expectHeadSha, '--expect-head-sha');
1714
+ if (opts.expectPrHeadSha !== undefined)
1715
+ validateSha(opts.expectPrHeadSha, '--expect-pr-head-sha');
1716
+ if (opts.pendingPreviewSha256 !== undefined && !/^[a-f0-9]{64}$/.test(opts.pendingPreviewSha256)) {
1717
+ throw new ReviewLaunchRefused('pending_finalize_incompatible', '--pending-preview-sha256 must be a lowercase SHA-256 digest.');
1718
+ }
1719
+ if (opts.expectPrHeadSha !== undefined && !opts.finalizePendingOnly) {
1720
+ throw new ReviewLaunchRefused('pending_finalize_incompatible', '--expect-pr-head-sha applies only to cycle-backed --finalize-pending-only recovery.');
1721
+ }
1707
1722
  if (opts.evidenceRequired && patchTarget && opts.headSha === undefined) {
1708
1723
  throw new Error('--evidence-required needs --head-sha for a patch file: evidence must bind to the commit it reviewed.');
1709
1724
  }
@@ -1851,12 +1866,13 @@ async function executeCouncil(spinner, prepared, diff, opts, extra, preparedWork
1851
1866
  let completion;
1852
1867
  const common = await resolveGitCommonDir();
1853
1868
  if (opts.exportPendingPackage) {
1869
+ const pendingNative = await loadConvergeRunState(common, prepared.converge.target);
1854
1870
  const receipt = await exportOrdinaryPendingPackage({ gitCommonDir: common,
1855
1871
  target: prepared.converge.target, headSha: extra.target.headSha ?? '', baseSha: extra.target.baseSha ?? '',
1856
1872
  expectedBaseSha: opts.expectBaseSha, expectedRound: prepared.converge.round,
1857
1873
  guardedInput, path: opts.exportPendingPackage,
1858
1874
  preview: opts.previewPending === true, asyncStoreDir: await resolveExistingAsyncStoreDir(),
1859
- asyncTargetKey: asyncTargetKey(extra.asyncTargetLabel ?? prepared.converge.target, extra.target.kind === 'patch' ? prepared.converge.target : undefined),
1875
+ asyncTargetKey: asyncTargetKey(extra.asyncTargetLabel ?? prepared.converge.target, extra.target.kind === 'patch' ? prepared.converge.target : undefined, pendingNative?.cycle?.id),
1860
1876
  asyncDescriptors: ordinaryAsyncDescriptors });
1861
1877
  spinner.stop();
1862
1878
  console.log(JSON.stringify(receipt));
@@ -1880,19 +1896,38 @@ async function executeCouncil(spinner, prepared, diff, opts, extra, preparedWork
1880
1896
  const runtime = await createTelemetryRuntime({ rclVersion: RCL_VERSION, config, noTelemetry: opts.telemetry === false });
1881
1897
  if (!runtime.sink || runtime.level !== 'full')
1882
1898
  throw new Error('Fresh review cycles require full Harness evidence and an actor credential');
1883
- cycleRemote = createReviewCycleRemote(runtime.sink, extra.target.repo, extra.target.prNumber, extra.target.headSha ?? '');
1899
+ cycleRemote = createReviewCycleRemote(runtime.sink, extra.target.repo, extra.target.prNumber, opts.expectPrHeadSha ?? extra.target.headSha ?? '');
1884
1900
  }
1885
1901
  if (opts.resumePending || opts.finalizePendingOnly) {
1886
- const expectedAsyncSha256 = opts.resumeAsyncSha256.split(',').map(value => value.trim());
1887
- if (expectedAsyncSha256.length === 0 || expectedAsyncSha256.some(value => !/^[a-f0-9]{64}$/.test(value)) ||
1888
- new Set(expectedAsyncSha256).size !== expectedAsyncSha256.length) {
1889
- throw new ReviewLaunchRefused('pending_async_binding_invalid', 'Retained async SHA-256 bindings must be unique lowercase 64-character digests.');
1902
+ const asyncBinding = opts.resumeAsyncSha256.trim();
1903
+ const expectedAsyncSha256 = asyncBinding === 'none'
1904
+ ? [] : asyncBinding.split(',').map(value => value.trim());
1905
+ if (expectedAsyncSha256.some(value => !/^[a-f0-9]{64}$/.test(value))) {
1906
+ throw new ReviewLaunchRefused('pending_async_binding_invalid', 'Retained async bindings must be comma-separated lowercase SHA-256 digests, or "none" for an empty cycle history.');
1890
1907
  }
1891
1908
  const migrationPackage = opts.ordinaryPendingPackage === undefined ? undefined : JSON.parse((await readStable(opts.ordinaryPendingPackage)).text);
1909
+ if (opts.expectPrHeadSha !== undefined && migrationPackage?.version !== 2) {
1910
+ throw new ReviewLaunchRefused('pending_finalize_incompatible', '--expect-pr-head-sha requires a cycle-backed version-2 pending package.');
1911
+ }
1912
+ if (opts.finalizePendingOnly && opts.forPr !== undefined && migrationPackage?.version !== 2) {
1913
+ throw new ReviewLaunchRefused('pending_finalize_incompatible', '--for-pr finalize-only recovery requires a cycle-backed version-2 pending package.');
1914
+ }
1915
+ if (migrationPackage?.version !== 2 && (expectedAsyncSha256.length === 0 ||
1916
+ new Set(expectedAsyncSha256).size !== expectedAsyncSha256.length)) {
1917
+ throw new ReviewLaunchRefused('pending_async_binding_invalid', 'Ordinary retained async SHA-256 bindings must be non-empty and unique.');
1918
+ }
1919
+ if (migrationPackage?.version === 2 && opts.resumePending) {
1920
+ throw new ReviewLaunchRefused('cycle_pending_finalize_only', 'Cycle-backed packages can only terminalize the unknown original attempt. Launch a later successor normally after its terminal receipt verifies.');
1921
+ }
1892
1922
  const loadMigrationRetainedAsync = async () => {
1893
1923
  if (!migrationPackage)
1894
1924
  throw new ReviewLaunchRefused('pending_async_missing', 'An ordinary package is required.');
1895
1925
  const store = await resolveExistingAsyncStoreDir();
1926
+ if (migrationPackage.version === 2) {
1927
+ const key = asyncTargetKey(extra.asyncTargetLabel ?? prepared.converge.target, extra.target.kind === 'patch' ? prepared.converge.target : undefined, migrationPackage.cycle.id);
1928
+ const snapshot = await snapshotAsyncHistory(store, key, (migrationPackage.attemptsUsed + 1) * MAX_ASYNC_CALLS_PER_ROUND, expectedAsyncSha256);
1929
+ return snapshot.artifacts;
1930
+ }
1896
1931
  const wanted = new Map(migrationPackage.retainedAsync.map(item => [item.sha256, item]));
1897
1932
  const found = new Map();
1898
1933
  for (const name of await readdir(store)) {
@@ -1929,6 +1964,8 @@ async function executeCouncil(spinner, prepared, diff, opts, extra, preparedWork
1929
1964
  migrationPackage, maxAttempts: Number(opts.maxAttempts), maxPhysicalCalls: 1, maxAttemptsPerCell: 1,
1930
1965
  maxDurationMs: 1, validate: async () => { }, loadRetainedAsync: loadMigrationRetainedAsync,
1931
1966
  run: async () => { throw new Error('preview_must_not_run'); }, preview: true,
1967
+ cycleRemote,
1968
+ ...(opts.expectPrHeadSha === undefined ? {} : { currentPrHeadSha: opts.expectPrHeadSha }),
1932
1969
  previewMode: opts.finalizePendingOnly ? 'finalize-only' : 'combined' });
1933
1970
  spinner.stop();
1934
1971
  console.log(JSON.stringify({
@@ -1943,7 +1980,16 @@ async function executeCouncil(spinner, prepared, diff, opts, extra, preparedWork
1943
1980
  baseSha: extra.target.baseSha ?? '', pendingInputSha256: inputSha256,
1944
1981
  nativeStateSha256: opts.pendingNativeSha256, attemptStateSha256: opts.pendingAttemptSha256,
1945
1982
  retainedAsyncSha256: expectedAsyncSha256, migrationPackage,
1946
- maxAttempts: Number(opts.maxAttempts), loadRetainedAsync: loadMigrationRetainedAsync });
1983
+ maxAttempts: Number(opts.maxAttempts), cycleRemote,
1984
+ ...(opts.expectPrHeadSha === undefined ? {} : {
1985
+ currentPrHeadSha: opts.expectPrHeadSha, previewSha256: opts.pendingPreviewSha256,
1986
+ }),
1987
+ loadRetainedAsync: loadMigrationRetainedAsync,
1988
+ ...(migrationPackage.version === 2 ? { cycleHistory: {
1989
+ resolveStoreDir: resolveExistingAsyncStoreDir,
1990
+ targetKey: asyncTargetKey(extra.asyncTargetLabel ?? prepared.converge.target, extra.target.kind === 'patch' ? prepared.converge.target : undefined, migrationPackage.cycle.id),
1991
+ maxResults: (migrationPackage.attemptsUsed + 1) * MAX_ASYNC_CALLS_PER_ROUND,
1992
+ } } : {}) });
1947
1993
  spinner.stop();
1948
1994
  console.log(JSON.stringify({ mode: 'finalize-only', ...result }));
1949
1995
  return undefined;