codex-orchestrator 2.0.19 → 2.0.21

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 (44) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +26 -1
  3. package/dist/src/v2/cli.d.ts +1 -0
  4. package/dist/src/v2/cli.d.ts.map +1 -1
  5. package/dist/src/v2/cli.js +9 -4
  6. package/dist/src/v2/cli.js.map +1 -1
  7. package/dist/src/v2/code-review-report.d.ts +3 -0
  8. package/dist/src/v2/code-review-report.d.ts.map +1 -1
  9. package/dist/src/v2/code-review-report.js +30 -1
  10. package/dist/src/v2/code-review-report.js.map +1 -1
  11. package/dist/src/v2/contained-report-operation.d.ts +1 -1
  12. package/dist/src/v2/contained-report-operation.d.ts.map +1 -1
  13. package/dist/src/v2/contained-report-operation.js +21 -5
  14. package/dist/src/v2/contained-report-operation.js.map +1 -1
  15. package/dist/src/v2/containment.d.ts.map +1 -1
  16. package/dist/src/v2/containment.js +12 -1
  17. package/dist/src/v2/containment.js.map +1 -1
  18. package/dist/src/v2/direct-delivery.d.ts +6 -1
  19. package/dist/src/v2/direct-delivery.d.ts.map +1 -1
  20. package/dist/src/v2/direct-delivery.js +30 -2
  21. package/dist/src/v2/direct-delivery.js.map +1 -1
  22. package/dist/src/v2/implementation-reviewer.d.ts +4 -2
  23. package/dist/src/v2/implementation-reviewer.d.ts.map +1 -1
  24. package/dist/src/v2/implementation-reviewer.js +36 -3
  25. package/dist/src/v2/implementation-reviewer.js.map +1 -1
  26. package/dist/src/v2/run-issue.d.ts +3 -0
  27. package/dist/src/v2/run-issue.d.ts.map +1 -1
  28. package/dist/src/v2/run-issue.js +149 -30
  29. package/dist/src/v2/run-issue.js.map +1 -1
  30. package/dist/src/v2/run-store.d.ts +1 -0
  31. package/dist/src/v2/run-store.d.ts.map +1 -1
  32. package/dist/src/v2/run-store.js +24 -3
  33. package/dist/src/v2/run-store.js.map +1 -1
  34. package/dist/src/v2/runtime.js +1 -1
  35. package/dist/src/v2/runtime.js.map +1 -1
  36. package/dist/src/v2/validation-progression.d.ts +4 -1
  37. package/dist/src/v2/validation-progression.d.ts.map +1 -1
  38. package/dist/src/v2/validation-progression.js +7 -1
  39. package/dist/src/v2/validation-progression.js.map +1 -1
  40. package/internal-workflow/manifest.json +1 -1
  41. package/internal-workflow/operations/code-review/SKILL.md +15 -1
  42. package/internal-workflow/profiles/review_coordinator.toml +1 -1
  43. package/internal-workflow/schemas/code-review-v1.json +1 -1
  44. package/package.json +1 -1
@@ -5,6 +5,7 @@ import { canonicalJson, containsCredentialEvidence, containsHostIdentityEvidence
5
5
  import { findDeniedPathMatch } from './adapters/path-policy.js';
6
6
  import { adoptActiveAttempt, confirmActiveAttemptCleanup, createActiveAttempt, launchActiveAttempt, observeActiveAttempt, } from './active-attempt.js';
7
7
  import { validateImplementationReport } from './implementation-report.js';
8
+ import { COMPLETE_REVIEW_COVERAGE, validateReviewContext } from './code-review-report.js';
8
9
  import { validateCompletedReport } from './contained-report-operation.js';
9
10
  import { directReviewCandidateTargetFingerprint, projectTerminalDirectReview, } from './direct-delivery.js';
10
11
  import { MAX_REVIEW_PATCH_BYTES } from './implementation-reviewer.js';
@@ -17,6 +18,11 @@ import { createIssueDeliveryAuthority } from './delivery-authority.js';
17
18
  import { claimComment, claimRunId, freezeCriteria, historicalClaimCounts, isClaimMarkerComment, isExactClaimMarkerLine, isAdoptableAttempt, observedHistoricalClaimKeys, outcomeEvidenceBytes, publicOutcome, publicIssueSnapshot, refreshClaimedIssueSnapshot, snapshotIssue, sameInspectionIdentity, sameStrings, semanticChangesMatch, } from './run-state-projections.js';
18
19
  import { applyValidationTransition, nextValidationTransition, projectValidationFeedbackActivation, projectValidationProofPassed, projectValidationProofStart, projectValidationRepair, projectValidationReviewApproved, projectValidationReviewNeedsWork, projectValidationReviewReportRepair, projectValidationReviewTransportRetry, } from './validation-progression.js';
19
20
  import { settleCommentEffect, settleCommitEffect, settleCleanupEffect, settleDraftPullRequestEffect, settleLabelsEffect, settlePushEffect, } from './pending-effect-settlement.js';
21
+ class ReviewTargetCredentialError extends Error {
22
+ constructor() {
23
+ super('Review target contains potential credential material; remove real credentials or use explicit dummy session tokens.');
24
+ }
25
+ }
20
26
  export class OwnerLockSafetyError extends Error {
21
27
  }
22
28
  export class OwnerLockContentionError extends Error {
@@ -925,12 +931,14 @@ export class RunIssue {
925
931
  let active;
926
932
  try {
927
933
  assertPositiveInteger(input.issueNumber, 'issueNumber');
934
+ if (input.retryProofRunId !== undefined)
935
+ assertUuid(input.retryProofRunId);
928
936
  const targetRoot = resolve(input.targetRoot);
929
937
  const initialConfig = await this.readStrictConfig(targetRoot);
930
938
  const canonicalRepository = `${initialConfig.config.github.owner.toLowerCase()}/${initialConfig.config.github.repo.toLowerCase()}`;
931
939
  const preflightState = await this.dependencies.runRecords.inspect();
932
940
  if (preflightState.status === 'unsupported')
933
- return { status: 'state-schema-unsupported' };
941
+ return { status: 'state-schema-unsupported', ...(preflightState.reason ? { reason: preflightState.reason } : {}) };
934
942
  try {
935
943
  owner = await this.dependencies.ownerLock.acquire({ canonicalRepository, targetRoot });
936
944
  }
@@ -961,11 +969,11 @@ export class RunIssue {
961
969
  return await this.preClaimCancelled(input.issueNumber);
962
970
  let authoritativeState = await this.dependencies.runRecords.inspect();
963
971
  if (authoritativeState.status === 'unsupported')
964
- return { status: 'state-schema-unsupported' };
972
+ return { status: 'state-schema-unsupported', ...(authoritativeState.reason ? { reason: authoritativeState.reason } : {}) };
965
973
  if (!sameInspectionIdentity(preflightState, authoritativeState)) {
966
974
  const stableState = await this.dependencies.runRecords.inspect();
967
975
  if (stableState.status === 'unsupported')
968
- return { status: 'state-schema-unsupported' };
976
+ return { status: 'state-schema-unsupported', ...(stableState.reason ? { reason: stableState.reason } : {}) };
969
977
  if (!sameInspectionIdentity(authoritativeState, stableState)) {
970
978
  return { status: 'requeued', reason: 'state-changed' };
971
979
  }
@@ -1003,6 +1011,13 @@ export class RunIssue {
1003
1011
  if (matchingRuns.length > 1)
1004
1012
  return await this.preClaimInternal('ambiguous-run-state', input.issueNumber);
1005
1013
  const existing = matchingRuns[0];
1014
+ if (input.retryProofRunId !== undefined && (existing?.runId !== input.retryProofRunId
1015
+ || existing.terminalOutcome?.status !== 'internal-error'
1016
+ || existing.terminalOutcome.code !== 'acceptance-proof-internal-failure')) {
1017
+ const reason = 'Proof retry requires the exact run with a terminal Acceptance Proof internal failure.';
1018
+ const evidence = await this.dependencies.writeEvidence({ runId: `issue-${input.issueNumber}`, code: 'proof-retry-not-eligible', summary: reason });
1019
+ return { status: 'not-eligible', reason, evidencePath: evidence.path };
1020
+ }
1006
1021
  let issueSnapshot;
1007
1022
  let frozenCriteria;
1008
1023
  let runId;
@@ -1065,6 +1080,23 @@ export class RunIssue {
1065
1080
  return reconciled;
1066
1081
  active = reconciled.active;
1067
1082
  }
1083
+ if (input.retryProofRunId !== undefined) {
1084
+ try {
1085
+ const recovered = await this.retryTerminalProof(active, config);
1086
+ if ('status' in recovered)
1087
+ return recovered;
1088
+ active = recovered.active;
1089
+ }
1090
+ catch {
1091
+ // Recovery uncertainty must not replace the terminal outcome that authorizes this retry.
1092
+ try {
1093
+ return await this.invokedFailure(active, 'acceptance-proof-retry-validation-retryable', 'Proof retry validation or its state transition could not be confirmed; inspect durable state before retrying.');
1094
+ }
1095
+ catch {
1096
+ return publicOutcome(active.record.terminalOutcome);
1097
+ }
1098
+ }
1099
+ }
1068
1100
  if (active.record.terminalOutcome) {
1069
1101
  if (active.record.terminalOutcome.status !== 'review-ready') {
1070
1102
  return publicOutcome(active.record.terminalOutcome);
@@ -1413,6 +1445,11 @@ export class RunIssue {
1413
1445
  reviewScope = await this.reviewValidationScope(active, frozenCriteria, checkPolicy.checks, config.deny.readPaths);
1414
1446
  }
1415
1447
  catch (error) {
1448
+ if (error instanceof ReviewTargetCredentialError) {
1449
+ return this.terminal(active, { status: 'blocked', kind: 'safety', resumable: false, blocker: {
1450
+ kind: 'safety', summary: error.message, attempted: ['Inspect exact candidate diff for credential material.'], resumable: false,
1451
+ } }, 'review-target-credential-evidence');
1452
+ }
1416
1453
  return this.invokedFailure(active, 'review-target-unavailable', error instanceof Error ? error.message : undefined);
1417
1454
  }
1418
1455
  const configuredChecks = Object.entries(reviewScope.checks);
@@ -1731,6 +1768,57 @@ export class RunIssue {
1731
1768
  }
1732
1769
  }
1733
1770
  }
1771
+ async retryTerminalProof(active, config) {
1772
+ const reject = async (reason) => {
1773
+ const evidence = await this.dependencies.writeEvidence({ runId: active.record.runId, code: 'proof-retry-not-eligible', summary: reason });
1774
+ return { status: 'not-eligible', reason, evidencePath: evidence.path };
1775
+ };
1776
+ const record = active.record;
1777
+ const candidate = this.dependencies.git.candidateV2;
1778
+ if (record.lifecycle !== 'internal-error' || record.terminalOutcome?.status !== 'internal-error'
1779
+ || record.terminalOutcome.code !== 'acceptance-proof-internal-failure'
1780
+ || !record.deliveryAuthority || !record.candidateBinding || !record.implementationResult || !candidate
1781
+ || record.pendingEffect || record.activeAttempt || record.candidateMaterialization || record.proofReceipt
1782
+ || record.reviewFeedback?.activeBatch) {
1783
+ return reject('Proof retry requires a quiescent, unpublished candidate without passed proof or pending effects.');
1784
+ }
1785
+ if (!await this.authorized(active, config))
1786
+ return reject('The existing trusted issue claim must still authorize execution.');
1787
+ if (await this.dependencies.pullRequests.findOpen({ headBranch: record.branchName, baseBranch: config.github.baseBranch })) {
1788
+ return reject('Proof retry cannot reopen a run with an open pull request.');
1789
+ }
1790
+ await this.dependencies.verifyWorkflowGeneration(record.workflowGeneration);
1791
+ const worktree = await this.dependencies.git.inspectWorktree({
1792
+ worktreePath: record.worktreePath, branchName: record.branchName, baseSha: expectedImplementationHead(record),
1793
+ });
1794
+ if (worktree !== 'matching')
1795
+ return reject('The existing issue worktree identity or HEAD has changed.');
1796
+ const pin = await candidate.inspectPin(record.candidateBinding);
1797
+ if (pin.kind === 'failed')
1798
+ return this.mapCandidateFailure(active, pin.code);
1799
+ if (pin.value !== 'matching')
1800
+ return reject('The immutable candidate pin is missing or diverged.');
1801
+ let directReview = record.directReview;
1802
+ if (directReview) {
1803
+ if (directReview.status !== 'terminal' || directReview.review.disposition !== 'active') {
1804
+ return reject('The retained Review cannot resume validation of this candidate.');
1805
+ }
1806
+ const { terminalCode: _code, terminalOutcome: _outcome, ...retained } = structuredClone(directReview);
1807
+ directReview = { ...retained, status: 'active' };
1808
+ }
1809
+ if (!await this.authorized(active, config))
1810
+ return reject('Issue execution authority changed during proof retry validation.');
1811
+ await this.dependencies.writeEvidence({
1812
+ runId: record.runId, code: 'acceptance-proof-retry-authorized',
1813
+ summary: canonicalJson({ previousOutcome: record.terminalOutcome, previousProofId: record.proofId ?? null,
1814
+ candidateBindingId: record.candidateBinding.bindingId, cycle: record.cycle }),
1815
+ });
1816
+ return { active: await this.persist(active, {
1817
+ lifecycle: 'checking', terminalOutcome: undefined, outcomeEvidenceId: undefined,
1818
+ checks: [], checkedChangeSha256: undefined, proofId: undefined, proofExecution: undefined, proofReceipt: undefined,
1819
+ ...(directReview ? { directReview } : {}),
1820
+ }) };
1821
+ }
1734
1822
  async initializeClaimedRun(active, issue) {
1735
1823
  if (active.record.lifecycle !== 'claimed'
1736
1824
  || active.record.activeAttempt
@@ -2514,9 +2602,10 @@ export class RunIssue {
2514
2602
  if (!binding)
2515
2603
  throw new Error('review scope requires candidate identity');
2516
2604
  const completeDiff = await this.dependencies.git.diffTrees(active.record.worktreePath, active.record.baseSha, binding.candidateTreeSha);
2605
+ if (containsCredentialEvidence(completeDiff.patch))
2606
+ throw new ReviewTargetCredentialError();
2517
2607
  if (completeDiff.changedFiles.length === 0 || completeDiff.patch.trim().length === 0
2518
2608
  || Buffer.byteLength(completeDiff.patch, 'utf8') > MAX_REVIEW_PATCH_BYTES
2519
- || containsCredentialEvidence(completeDiff.patch)
2520
2609
  || completeDiff.changedFiles.some((path) => findDeniedPathMatch(path, deniedPaths))) {
2521
2610
  throw new Error('exact complete Review target is unavailable');
2522
2611
  }
@@ -2597,32 +2686,42 @@ export class RunIssue {
2597
2686
  reviewScope = suppliedScope ?? await this.reviewValidationScope(active, frozenCriteria, resolveIssueCheckPolicy(active.record.issueSnapshot.body, config.checks).checks, config.deny.readPaths);
2598
2687
  }
2599
2688
  catch (error) {
2689
+ if (error instanceof ReviewTargetCredentialError) {
2690
+ return this.terminal(active, { status: 'blocked', kind: 'safety', resumable: false, blocker: {
2691
+ kind: 'safety', summary: error.message, attempted: ['Inspect exact candidate diff for credential material.'], resumable: false,
2692
+ } }, 'review-target-credential-evidence');
2693
+ }
2600
2694
  return this.invokedFailure(active, 'review-scope-unavailable', error instanceof Error ? error.message : undefined);
2601
2695
  }
2602
2696
  let reportRepair;
2603
2697
  const retainedAttempt = active.record.activeAttempt;
2604
2698
  const retainedReview = active.record.directReview;
2605
- if (retainedReview?.review.reportRepairs && retainedAttempt?.stage === 'adopted' && retainedAttempt.result) {
2606
- const stored = await this.dependencies.inspectAttemptResult(retainedAttempt.resultPath);
2607
- if (!stored || stored.sha256 !== retainedAttempt.result.sha256) {
2699
+ if (retainedReview?.review.reportRepairs) {
2700
+ const original = retainedReview.review.reportCorrection
2701
+ ?? (retainedAttempt?.stage === 'adopted' ? retainedAttempt.result : undefined);
2702
+ if (!original)
2703
+ return this.terminal(active, { status: 'internal-error', code: 'review-report-correction-result-missing' });
2704
+ const stored = await this.dependencies.inspectAttemptResult(original.path);
2705
+ if (!stored || stored.sha256 !== original.sha256) {
2608
2706
  return this.invokedFailure(active, 'direct-review-report-result-unavailable', 'The exact malformed Review result is not currently observable; report-only recovery remains fenced.');
2609
2707
  }
2610
- const validation = validateCompletedReport('code-review', retainedAttempt.attemptId, stored.bytes, {
2611
- operation: 'code-review',
2612
- targetRevision: retainedReview.targetRevision,
2613
- targetFingerprint: retainedReview.targetFingerprint,
2614
- reviewerSessionId: retainedReview.review.reviewerSessionId,
2615
- previousFindingIds: [
2616
- ...retainedReview.review.defects.filter((defect) => defect.status === 'fixed').map((defect) => defect.id),
2617
- ...retainedReview.repairFindings.filter((finding) => finding.status === 'fixed').map((finding) => finding.id),
2618
- ].sort(),
2619
- requiredCoverage: reviewScope.mode === 'complete' ? [
2620
- 'candidate-proof-binding', 'correctness', 'duplicate-ownership', 'maintainability',
2621
- 'repository-standards', 'requirements', 'tests', 'zero-legacy',
2622
- ] : [],
2623
- requireAllReviewers: reviewScope.mode === 'complete',
2624
- requireReviewerEvidence: true,
2625
- });
2708
+ if (retainedReview.review.reportRepairs >= 2) {
2709
+ return this.terminal(active, { status: 'blocked', kind: 'external', resumable: false, blocker: {
2710
+ kind: 'external', resumable: false, summary: 'Review report correction limit reached; retained candidate and report require operator recovery.',
2711
+ attempted: ['Preserved the candidate, checks, proof and retained report without launching another reviewer.'],
2712
+ } });
2713
+ }
2714
+ let context;
2715
+ try {
2716
+ context = validateReviewContext(retainedReview.review.validationContext);
2717
+ if (context.targetRevision !== retainedReview.targetRevision || context.targetFingerprint !== retainedReview.targetFingerprint
2718
+ || context.reviewerSessionId !== retainedReview.review.reviewerSessionId)
2719
+ throw new Error('review context drift');
2720
+ }
2721
+ catch {
2722
+ return this.terminal(active, { status: 'internal-error', code: 'review-validation-context-missing' });
2723
+ }
2724
+ const validation = validateCompletedReport('code-review', retainedAttempt?.attemptId ?? active.record.runId, stored.bytes, context);
2626
2725
  if (validation.status !== 'invalid' || !validation.repairInput) {
2627
2726
  return this.terminal(active, { status: 'blocked', kind: 'safety', resumable: false }, 'direct-review-retained-result-diverged');
2628
2727
  }
@@ -2631,7 +2730,12 @@ export class RunIssue {
2631
2730
  originalReportBytes: Buffer.from(validation.repairInput.originalReportBytes),
2632
2731
  diagnostic: validation.findings[0] ?? 'review report is invalid',
2633
2732
  };
2634
- active = await this.clearAttempt(active);
2733
+ if (!retainedReview.review.reportCorrection) {
2734
+ active = await this.persist(active, { directReview: { ...retainedReview,
2735
+ review: { ...retainedReview.review, reportCorrection: original } } });
2736
+ }
2737
+ if (retainedAttempt?.stage === 'adopted')
2738
+ active = await this.clearAttempt(active);
2635
2739
  }
2636
2740
  while (true) {
2637
2741
  const directReview = active.record.directReview;
@@ -2701,10 +2805,7 @@ export class RunIssue {
2701
2805
  frozenCriteria: reviewScope.criteria,
2702
2806
  deliveryAuthority: structuredClone(active.record.deliveryAuthority),
2703
2807
  defects: structuredClone(directReview.review.defects),
2704
- reviewFocus: [
2705
- 'candidate-proof-binding', 'correctness', 'duplicate-ownership', 'maintainability',
2706
- 'repository-standards', 'requirements', 'tests', 'zero-legacy',
2707
- ],
2808
+ reviewFocus: [...COMPLETE_REVIEW_COVERAGE],
2708
2809
  workflowGeneration: structuredClone(active.record.workflowGeneration),
2709
2810
  repairOnly: reportRepair !== undefined,
2710
2811
  originalReportSha256: reportRepair?.originalReportSha256 ?? null,
@@ -2714,6 +2815,12 @@ export class RunIssue {
2714
2815
  onPrepared: async (invocation) => {
2715
2816
  if (!active.record.directReview)
2716
2817
  throw new Error('direct review disappeared before prepare');
2818
+ const validationContext = validateReviewContext(invocation.validationContext);
2819
+ if (validationContext.targetFingerprint !== directReview.targetFingerprint || validationContext.targetRevision !== directReview.targetRevision
2820
+ || validationContext.reviewerSessionId !== reviewerSessionId)
2821
+ throw new Error('review validation context drift');
2822
+ active = await this.persist(active, { directReview: { ...active.record.directReview,
2823
+ review: { ...active.record.directReview.review, validationContext } } });
2717
2824
  if (invocation.attemptId !== active.record.activeAttempt?.attemptId
2718
2825
  || invocation.operation !== 'code-review'
2719
2826
  || invocation.reviewerSessionId !== reviewerSessionId)
@@ -2759,6 +2866,8 @@ export class RunIssue {
2759
2866
  completeReview.review.defects = structuredClone(result.report.defects);
2760
2867
  completeReview.review.reviewerSessionId = this.dependencies.createReviewSessionId();
2761
2868
  completeReview.review.reportRepairs = 0;
2869
+ delete completeReview.review.validationContext;
2870
+ delete completeReview.review.reportCorrection;
2762
2871
  completeReview.review.transportRetries = 0;
2763
2872
  active = await this.persist(settledExecution.active, {
2764
2873
  lifecycle: 'checking',
@@ -2819,7 +2928,15 @@ export class RunIssue {
2819
2928
  const current = active.record.directReview;
2820
2929
  if (!current)
2821
2930
  return this.terminal(active, { status: 'internal-error', code: 'direct-review-result-orphaned' });
2822
- active = await this.adoptValidationTransition(active, result.originalReportSha256, projectValidationReviewReportRepair(active.record));
2931
+ active = await this.adoptValidationTransition(active, result.originalReportSha256, projectValidationReviewReportRepair(active.record, { path: active.record.activeAttempt.resultPath, sha256: result.originalReportSha256 }));
2932
+ if (active.record.directReview.review.reportRepairs >= 2) {
2933
+ const repeated = reportRepair?.originalReportSha256 === result.originalReportSha256;
2934
+ return this.terminal(active, { status: 'blocked', kind: 'external', resumable: false, blocker: {
2935
+ kind: 'external', resumable: false,
2936
+ summary: `Review report correction failed${repeated ? ' without changing the report' : ''}: ${result.diagnostic}. Candidate and evidence are retained.`,
2937
+ attempted: ['Reviewed the candidate and attempted one report-only correction.'],
2938
+ } });
2939
+ }
2823
2940
  return this.invokedFailure(active, 'direct-review-report-retryable', 'The review report was malformed; a later bounded invocation may retry the same immutable candidate.');
2824
2941
  }
2825
2942
  if (result.kind === 'transport-failed') {
@@ -3352,7 +3469,9 @@ function terminalReportSnapshot(record, outcome) {
3352
3469
  : outcome.status === 'blocked'
3353
3470
  ? outcome.resumable
3354
3471
  ? 'Resolve the stated blocker, then rerun the same issue.'
3355
- : 'Provide the missing decision or authority in this issue before continuing.'
3472
+ : outcome.kind === 'external'
3473
+ ? 'Inspect the retained report and Runner diagnostics, correct the reported condition, then explicitly retry the retained work.'
3474
+ : 'Provide the missing decision or authority in this issue before continuing.'
3356
3475
  : outcome.status === 'internal-error'
3357
3476
  ? 'Inspect the package-owned evidence for the code above, correct the runner condition, and retry the same issue.'
3358
3477
  : 'Re-add the authorization label and rerun the same issue if the work should continue.';