codex-orchestrator 0.1.51 → 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/CHANGELOG.md +27 -0
- package/README.md +45 -389
- package/dist/src/index.d.ts +16 -46
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +8 -24
- package/dist/src/index.js.map +1 -1
- package/dist/src/v2/acceptance-proof.d.ts +111 -0
- package/dist/src/v2/acceptance-proof.d.ts.map +1 -0
- package/dist/src/v2/acceptance-proof.js +427 -0
- package/dist/src/v2/acceptance-proof.js.map +1 -0
- package/dist/src/v2/adapters/command.d.ts.map +1 -0
- package/dist/src/v2/adapters/command.js.map +1 -0
- package/dist/src/v2/adapters/durable-atomic-file.d.ts.map +1 -0
- package/dist/src/v2/adapters/durable-atomic-file.js.map +1 -0
- package/dist/src/v2/adapters/gh-cli.d.ts.map +1 -0
- package/dist/src/v2/adapters/gh-cli.js.map +1 -0
- package/dist/src/v2/adapters/gh-issue-adapter.d.ts.map +1 -0
- package/dist/src/v2/adapters/gh-issue-adapter.js.map +1 -0
- package/dist/src/v2/adapters/gh-pull-request-adapter.d.ts.map +1 -0
- package/dist/src/v2/adapters/gh-pull-request-adapter.js.map +1 -0
- package/dist/src/v2/adapters/issues.d.ts.map +1 -0
- package/dist/src/v2/adapters/issues.js.map +1 -0
- package/dist/src/v2/adapters/mission-coordinator-lock.d.ts.map +1 -0
- package/dist/src/v2/adapters/mission-coordinator-lock.js.map +1 -0
- package/dist/src/v2/adapters/path-policy.d.ts.map +1 -0
- package/dist/src/v2/adapters/path-policy.js.map +1 -0
- package/dist/src/v2/adapters/pull-requests.d.ts.map +1 -0
- package/dist/src/v2/adapters/pull-requests.js.map +1 -0
- package/dist/src/v2/adapters/target-activity-fence.d.ts.map +1 -0
- package/dist/src/{runner → v2/adapters}/target-activity-fence.js +1 -1
- package/dist/src/v2/adapters/target-activity-fence.js.map +1 -0
- package/dist/src/{git → v2/adapters}/worktree.d.ts +1 -1
- package/dist/src/v2/adapters/worktree.d.ts.map +1 -0
- package/dist/src/{git → v2/adapters}/worktree.js +2 -2
- package/dist/src/v2/adapters/worktree.js.map +1 -0
- package/dist/src/v2/atomic-store.d.ts +36 -0
- package/dist/src/v2/atomic-store.d.ts.map +1 -0
- package/dist/src/v2/atomic-store.js +328 -0
- package/dist/src/v2/atomic-store.js.map +1 -0
- package/dist/src/v2/candidate-cli.d.ts +22 -0
- package/dist/src/v2/candidate-cli.d.ts.map +1 -0
- package/dist/src/v2/candidate-cli.js +161 -0
- package/dist/src/v2/candidate-cli.js.map +1 -0
- package/dist/src/v2/checked-change.d.ts +49 -0
- package/dist/src/v2/checked-change.d.ts.map +1 -0
- package/dist/src/v2/checked-change.js +139 -0
- package/dist/src/v2/checked-change.js.map +1 -0
- package/dist/src/v2/cli-contract.d.ts +8 -0
- package/dist/src/v2/cli-contract.d.ts.map +1 -0
- package/dist/src/v2/cli-contract.js +32 -0
- package/dist/src/v2/cli-contract.js.map +1 -0
- package/dist/src/v2/codex-process.d.ts +71 -0
- package/dist/src/v2/codex-process.d.ts.map +1 -0
- package/dist/src/v2/codex-process.js +404 -0
- package/dist/src/v2/codex-process.js.map +1 -0
- package/dist/src/v2/config.d.ts +45 -0
- package/dist/src/v2/config.d.ts.map +1 -0
- package/dist/src/v2/config.js +139 -0
- package/dist/src/v2/config.js.map +1 -0
- package/dist/src/v2/containment.d.ts +55 -0
- package/dist/src/v2/containment.d.ts.map +1 -0
- package/dist/src/v2/containment.js +370 -0
- package/dist/src/v2/containment.js.map +1 -0
- package/dist/src/v2/implementation-report.d.ts +18 -0
- package/dist/src/v2/implementation-report.d.ts.map +1 -0
- package/dist/src/v2/implementation-report.js +147 -0
- package/dist/src/v2/implementation-report.js.map +1 -0
- package/dist/src/v2/legacy-cutover.d.ts +52 -0
- package/dist/src/v2/legacy-cutover.d.ts.map +1 -0
- package/dist/src/v2/legacy-cutover.js +87 -0
- package/dist/src/v2/legacy-cutover.js.map +1 -0
- package/dist/src/v2/mobile-lease.d.ts +97 -0
- package/dist/src/v2/mobile-lease.d.ts.map +1 -0
- package/dist/src/v2/mobile-lease.js +253 -0
- package/dist/src/v2/mobile-lease.js.map +1 -0
- package/dist/src/v2/proof-report.d.ts +118 -0
- package/dist/src/v2/proof-report.d.ts.map +1 -0
- package/dist/src/v2/proof-report.js +703 -0
- package/dist/src/v2/proof-report.js.map +1 -0
- package/dist/src/v2/proof-store.d.ts +42 -0
- package/dist/src/v2/proof-store.d.ts.map +1 -0
- package/dist/src/v2/proof-store.js +180 -0
- package/dist/src/v2/proof-store.js.map +1 -0
- package/dist/src/v2/report-envelope.d.ts +4 -0
- package/dist/src/v2/report-envelope.d.ts.map +1 -0
- package/dist/src/v2/report-envelope.js +46 -0
- package/dist/src/v2/report-envelope.js.map +1 -0
- package/dist/src/v2/run-issue.d.ts +213 -0
- package/dist/src/v2/run-issue.d.ts.map +1 -0
- package/dist/src/v2/run-issue.js +906 -0
- package/dist/src/v2/run-issue.js.map +1 -0
- package/dist/src/v2/run-store.d.ts +136 -0
- package/dist/src/v2/run-store.d.ts.map +1 -0
- package/dist/src/v2/run-store.js +346 -0
- package/dist/src/v2/run-store.js.map +1 -0
- package/dist/src/v2/runtime-assets.d.ts +31 -0
- package/dist/src/v2/runtime-assets.d.ts.map +1 -0
- package/dist/src/v2/runtime-assets.js +473 -0
- package/dist/src/v2/runtime-assets.js.map +1 -0
- package/dist/src/v2/runtime.d.ts +137 -0
- package/dist/src/v2/runtime.d.ts.map +1 -0
- package/dist/src/v2/runtime.js +847 -0
- package/dist/src/v2/runtime.js.map +1 -0
- package/dist/src/v2/setup-cli.d.ts +5 -0
- package/dist/src/v2/setup-cli.d.ts.map +1 -0
- package/dist/src/v2/setup-cli.js +83 -0
- package/dist/src/v2/setup-cli.js.map +1 -0
- package/dist/src/v2/setup-runtime.d.ts +6 -0
- package/dist/src/v2/setup-runtime.d.ts.map +1 -0
- package/dist/src/v2/setup-runtime.js +213 -0
- package/dist/src/v2/setup-runtime.js.map +1 -0
- package/dist/src/v2/setup-store.d.ts +19 -0
- package/dist/src/v2/setup-store.d.ts.map +1 -0
- package/dist/src/v2/setup-store.js +208 -0
- package/dist/src/v2/setup-store.js.map +1 -0
- package/dist/src/v2/setup.d.ts +147 -0
- package/dist/src/v2/setup.d.ts.map +1 -0
- package/dist/src/v2/setup.js +529 -0
- package/dist/src/v2/setup.js.map +1 -0
- package/docs/deep-dive.md +54 -803
- package/internal-skills/acceptance-proof/SKILL.md +14 -0
- package/internal-skills/acceptance-proof/references/android.md +14 -0
- package/internal-skills/acceptance-proof/references/browser.md +13 -0
- package/internal-skills/acceptance-proof/references/ios.md +14 -0
- package/internal-skills/acceptance-proof/tools/android-lease.mjs +280 -0
- package/internal-skills/acceptance-proof/tools/ios-lease.mjs +288 -0
- package/internal-skills/agent-auto/SKILL.md +14 -0
- package/package.json +11 -18
- package/bridge-runtime.json +0 -2719
- package/dist/src/bridge-runtime.d.ts +0 -17
- package/dist/src/bridge-runtime.d.ts.map +0 -1
- package/dist/src/bridge-runtime.js +0 -170
- package/dist/src/bridge-runtime.js.map +0 -1
- package/dist/src/cli.d.ts +0 -3
- package/dist/src/cli.d.ts.map +0 -1
- package/dist/src/cli.js +0 -569
- package/dist/src/cli.js.map +0 -1
- package/dist/src/codex/command-adapter.d.ts +0 -47
- package/dist/src/codex/command-adapter.d.ts.map +0 -1
- package/dist/src/codex/command-adapter.js +0 -169
- package/dist/src/codex/command-adapter.js.map +0 -1
- package/dist/src/codex/mobile-device-guard.d.ts +0 -7
- package/dist/src/codex/mobile-device-guard.d.ts.map +0 -1
- package/dist/src/codex/mobile-device-guard.js +0 -63
- package/dist/src/codex/mobile-device-guard.js.map +0 -1
- package/dist/src/config/constants.d.ts +0 -6
- package/dist/src/config/constants.d.ts.map +0 -1
- package/dist/src/config/constants.js +0 -19
- package/dist/src/config/constants.js.map +0 -1
- package/dist/src/config/schema.d.ts +0 -234
- package/dist/src/config/schema.d.ts.map +0 -1
- package/dist/src/config/schema.js +0 -673
- package/dist/src/config/schema.js.map +0 -1
- package/dist/src/fs/durable-atomic-file.d.ts.map +0 -1
- package/dist/src/fs/durable-atomic-file.js.map +0 -1
- package/dist/src/git/base-branch.d.ts +0 -26
- package/dist/src/git/base-branch.d.ts.map +0 -1
- package/dist/src/git/base-branch.js +0 -45
- package/dist/src/git/base-branch.js.map +0 -1
- package/dist/src/git/worktree.d.ts.map +0 -1
- package/dist/src/git/worktree.js.map +0 -1
- package/dist/src/github/gh-cli.d.ts.map +0 -1
- package/dist/src/github/gh-cli.js.map +0 -1
- package/dist/src/github/gh-issue-adapter.d.ts.map +0 -1
- package/dist/src/github/gh-issue-adapter.js.map +0 -1
- package/dist/src/github/gh-pull-request-adapter.d.ts.map +0 -1
- package/dist/src/github/gh-pull-request-adapter.js.map +0 -1
- package/dist/src/github/issues.d.ts.map +0 -1
- package/dist/src/github/issues.js.map +0 -1
- package/dist/src/github/pull-requests.d.ts.map +0 -1
- package/dist/src/github/pull-requests.js.map +0 -1
- package/dist/src/package-info.d.ts +0 -6
- package/dist/src/package-info.d.ts.map +0 -1
- package/dist/src/package-info.js +0 -13
- package/dist/src/package-info.js.map +0 -1
- package/dist/src/path-policy.d.ts.map +0 -1
- package/dist/src/path-policy.js.map +0 -1
- package/dist/src/process/command.d.ts.map +0 -1
- package/dist/src/process/command.js.map +0 -1
- package/dist/src/review-handoff.d.ts +0 -3
- package/dist/src/review-handoff.d.ts.map +0 -1
- package/dist/src/review-handoff.js +0 -8
- package/dist/src/review-handoff.js.map +0 -1
- package/dist/src/runner/acceptance-proof-loop.d.ts +0 -97
- package/dist/src/runner/acceptance-proof-loop.d.ts.map +0 -1
- package/dist/src/runner/acceptance-proof-loop.js +0 -404
- package/dist/src/runner/acceptance-proof-loop.js.map +0 -1
- package/dist/src/runner/acceptance-proof-runner.d.ts +0 -24
- package/dist/src/runner/acceptance-proof-runner.d.ts.map +0 -1
- package/dist/src/runner/acceptance-proof-runner.js +0 -121
- package/dist/src/runner/acceptance-proof-runner.js.map +0 -1
- package/dist/src/runner/acceptance-proof.d.ts +0 -189
- package/dist/src/runner/acceptance-proof.d.ts.map +0 -1
- package/dist/src/runner/acceptance-proof.js +0 -594
- package/dist/src/runner/acceptance-proof.js.map +0 -1
- package/dist/src/runner/agent-attempt.d.ts +0 -105
- package/dist/src/runner/agent-attempt.d.ts.map +0 -1
- package/dist/src/runner/agent-attempt.js +0 -245
- package/dist/src/runner/agent-attempt.js.map +0 -1
- package/dist/src/runner/android-visual-proof-command.d.ts +0 -26
- package/dist/src/runner/android-visual-proof-command.d.ts.map +0 -1
- package/dist/src/runner/android-visual-proof-command.js +0 -592
- package/dist/src/runner/android-visual-proof-command.js.map +0 -1
- package/dist/src/runner/auto-visual-proof-command.d.ts +0 -15
- package/dist/src/runner/auto-visual-proof-command.d.ts.map +0 -1
- package/dist/src/runner/auto-visual-proof-command.js +0 -64
- package/dist/src/runner/auto-visual-proof-command.js.map +0 -1
- package/dist/src/runner/browser-proof-contract.d.ts +0 -134
- package/dist/src/runner/browser-proof-contract.d.ts.map +0 -1
- package/dist/src/runner/browser-proof-contract.js +0 -400
- package/dist/src/runner/browser-proof-contract.js.map +0 -1
- package/dist/src/runner/browser-visual-proof-command.d.ts +0 -101
- package/dist/src/runner/browser-visual-proof-command.d.ts.map +0 -1
- package/dist/src/runner/browser-visual-proof-command.js +0 -532
- package/dist/src/runner/browser-visual-proof-command.js.map +0 -1
- package/dist/src/runner/command-utils.d.ts +0 -15
- package/dist/src/runner/command-utils.d.ts.map +0 -1
- package/dist/src/runner/command-utils.js +0 -228
- package/dist/src/runner/command-utils.js.map +0 -1
- package/dist/src/runner/completion-report.d.ts +0 -121
- package/dist/src/runner/completion-report.d.ts.map +0 -1
- package/dist/src/runner/completion-report.js +0 -381
- package/dist/src/runner/completion-report.js.map +0 -1
- package/dist/src/runner/context-snapshot.d.ts +0 -33
- package/dist/src/runner/context-snapshot.d.ts.map +0 -1
- package/dist/src/runner/context-snapshot.js +0 -99
- package/dist/src/runner/context-snapshot.js.map +0 -1
- package/dist/src/runner/daemon-command.d.ts +0 -30
- package/dist/src/runner/daemon-command.d.ts.map +0 -1
- package/dist/src/runner/daemon-command.js +0 -262
- package/dist/src/runner/daemon-command.js.map +0 -1
- package/dist/src/runner/doctor-command.d.ts +0 -41
- package/dist/src/runner/doctor-command.d.ts.map +0 -1
- package/dist/src/runner/doctor-command.js +0 -177
- package/dist/src/runner/doctor-command.js.map +0 -1
- package/dist/src/runner/durable-run-summary.d.ts +0 -80
- package/dist/src/runner/durable-run-summary.d.ts.map +0 -1
- package/dist/src/runner/durable-run-summary.js +0 -200
- package/dist/src/runner/durable-run-summary.js.map +0 -1
- package/dist/src/runner/flutter-sdk-discovery.d.ts +0 -5
- package/dist/src/runner/flutter-sdk-discovery.d.ts.map +0 -1
- package/dist/src/runner/flutter-sdk-discovery.js +0 -103
- package/dist/src/runner/flutter-sdk-discovery.js.map +0 -1
- package/dist/src/runner/fresh-context-review.d.ts +0 -22
- package/dist/src/runner/fresh-context-review.d.ts.map +0 -1
- package/dist/src/runner/fresh-context-review.js +0 -177
- package/dist/src/runner/fresh-context-review.js.map +0 -1
- package/dist/src/runner/handoff-evidence.d.ts +0 -141
- package/dist/src/runner/handoff-evidence.d.ts.map +0 -1
- package/dist/src/runner/handoff-evidence.js +0 -543
- package/dist/src/runner/handoff-evidence.js.map +0 -1
- package/dist/src/runner/hygiene-cleanup.d.ts +0 -15
- package/dist/src/runner/hygiene-cleanup.d.ts.map +0 -1
- package/dist/src/runner/hygiene-cleanup.js +0 -25
- package/dist/src/runner/hygiene-cleanup.js.map +0 -1
- package/dist/src/runner/ios-visual-proof-command.d.ts +0 -25
- package/dist/src/runner/ios-visual-proof-command.d.ts.map +0 -1
- package/dist/src/runner/ios-visual-proof-command.js +0 -353
- package/dist/src/runner/ios-visual-proof-command.js.map +0 -1
- package/dist/src/runner/issue-state-machine.d.ts +0 -39
- package/dist/src/runner/issue-state-machine.d.ts.map +0 -1
- package/dist/src/runner/issue-state-machine.js +0 -124
- package/dist/src/runner/issue-state-machine.js.map +0 -1
- package/dist/src/runner/issue-tree.d.ts +0 -65
- package/dist/src/runner/issue-tree.d.ts.map +0 -1
- package/dist/src/runner/issue-tree.js +0 -474
- package/dist/src/runner/issue-tree.js.map +0 -1
- package/dist/src/runner/lifecycle-events.d.ts +0 -44
- package/dist/src/runner/lifecycle-events.d.ts.map +0 -1
- package/dist/src/runner/lifecycle-events.js +0 -108
- package/dist/src/runner/lifecycle-events.js.map +0 -1
- package/dist/src/runner/local-execution-session.d.ts +0 -112
- package/dist/src/runner/local-execution-session.d.ts.map +0 -1
- package/dist/src/runner/local-execution-session.js +0 -1064
- package/dist/src/runner/local-execution-session.js.map +0 -1
- package/dist/src/runner/local-state.d.ts +0 -44
- package/dist/src/runner/local-state.d.ts.map +0 -1
- package/dist/src/runner/local-state.js +0 -150
- package/dist/src/runner/local-state.js.map +0 -1
- package/dist/src/runner/mission-activation.d.ts +0 -29
- package/dist/src/runner/mission-activation.d.ts.map +0 -1
- package/dist/src/runner/mission-activation.js +0 -54
- package/dist/src/runner/mission-activation.js.map +0 -1
- package/dist/src/runner/mission-agent-broker.d.ts +0 -53
- package/dist/src/runner/mission-agent-broker.d.ts.map +0 -1
- package/dist/src/runner/mission-agent-broker.js +0 -182
- package/dist/src/runner/mission-agent-broker.js.map +0 -1
- package/dist/src/runner/mission-cancellation.d.ts +0 -77
- package/dist/src/runner/mission-cancellation.d.ts.map +0 -1
- package/dist/src/runner/mission-cancellation.js +0 -180
- package/dist/src/runner/mission-cancellation.js.map +0 -1
- package/dist/src/runner/mission-canonical-path.d.ts +0 -34
- package/dist/src/runner/mission-canonical-path.d.ts.map +0 -1
- package/dist/src/runner/mission-canonical-path.js +0 -121
- package/dist/src/runner/mission-canonical-path.js.map +0 -1
- package/dist/src/runner/mission-capability-kernel.d.ts +0 -34
- package/dist/src/runner/mission-capability-kernel.d.ts.map +0 -1
- package/dist/src/runner/mission-capability-kernel.js +0 -158
- package/dist/src/runner/mission-capability-kernel.js.map +0 -1
- package/dist/src/runner/mission-check-policy.d.ts +0 -17
- package/dist/src/runner/mission-check-policy.d.ts.map +0 -1
- package/dist/src/runner/mission-check-policy.js +0 -31
- package/dist/src/runner/mission-check-policy.js.map +0 -1
- package/dist/src/runner/mission-coordinator-lock.d.ts.map +0 -1
- package/dist/src/runner/mission-coordinator-lock.js.map +0 -1
- package/dist/src/runner/mission-deployment.d.ts +0 -21
- package/dist/src/runner/mission-deployment.d.ts.map +0 -1
- package/dist/src/runner/mission-deployment.js +0 -108
- package/dist/src/runner/mission-deployment.js.map +0 -1
- package/dist/src/runner/mission-evaluation.d.ts +0 -61
- package/dist/src/runner/mission-evaluation.d.ts.map +0 -1
- package/dist/src/runner/mission-evaluation.js +0 -183
- package/dist/src/runner/mission-evaluation.js.map +0 -1
- package/dist/src/runner/mission-executor-probe.d.ts +0 -10
- package/dist/src/runner/mission-executor-probe.d.ts.map +0 -1
- package/dist/src/runner/mission-executor-probe.js +0 -180
- package/dist/src/runner/mission-executor-probe.js.map +0 -1
- package/dist/src/runner/mission-git-contracts.d.ts +0 -75
- package/dist/src/runner/mission-git-contracts.d.ts.map +0 -1
- package/dist/src/runner/mission-git-contracts.js +0 -201
- package/dist/src/runner/mission-git-contracts.js.map +0 -1
- package/dist/src/runner/mission-git-runtime-owner-ref.d.ts +0 -13
- package/dist/src/runner/mission-git-runtime-owner-ref.d.ts.map +0 -1
- package/dist/src/runner/mission-git-runtime-owner-ref.js +0 -111
- package/dist/src/runner/mission-git-runtime-owner-ref.js.map +0 -1
- package/dist/src/runner/mission-git-transaction.d.ts +0 -97
- package/dist/src/runner/mission-git-transaction.d.ts.map +0 -1
- package/dist/src/runner/mission-git-transaction.js +0 -1009
- package/dist/src/runner/mission-git-transaction.js.map +0 -1
- package/dist/src/runner/mission-identifiers.d.ts +0 -31
- package/dist/src/runner/mission-identifiers.d.ts.map +0 -1
- package/dist/src/runner/mission-identifiers.js +0 -75
- package/dist/src/runner/mission-identifiers.js.map +0 -1
- package/dist/src/runner/mission-input-snapshot.d.ts +0 -21
- package/dist/src/runner/mission-input-snapshot.d.ts.map +0 -1
- package/dist/src/runner/mission-input-snapshot.js +0 -63
- package/dist/src/runner/mission-input-snapshot.js.map +0 -1
- package/dist/src/runner/mission-ownership.d.ts +0 -38
- package/dist/src/runner/mission-ownership.d.ts.map +0 -1
- package/dist/src/runner/mission-ownership.js +0 -88
- package/dist/src/runner/mission-ownership.js.map +0 -1
- package/dist/src/runner/mission-patch-audit.d.ts +0 -21
- package/dist/src/runner/mission-patch-audit.d.ts.map +0 -1
- package/dist/src/runner/mission-patch-audit.js +0 -186
- package/dist/src/runner/mission-patch-audit.js.map +0 -1
- package/dist/src/runner/mission-path-language.d.ts +0 -6
- package/dist/src/runner/mission-path-language.d.ts.map +0 -1
- package/dist/src/runner/mission-path-language.js +0 -106
- package/dist/src/runner/mission-path-language.js.map +0 -1
- package/dist/src/runner/mission-permit-authority.d.ts +0 -26
- package/dist/src/runner/mission-permit-authority.d.ts.map +0 -1
- package/dist/src/runner/mission-permit-authority.js +0 -145
- package/dist/src/runner/mission-permit-authority.js.map +0 -1
- package/dist/src/runner/mission-plan-parent-coordinator.d.ts +0 -87
- package/dist/src/runner/mission-plan-parent-coordinator.d.ts.map +0 -1
- package/dist/src/runner/mission-plan-parent-coordinator.js +0 -441
- package/dist/src/runner/mission-plan-parent-coordinator.js.map +0 -1
- package/dist/src/runner/mission-plan-parent.d.ts +0 -156
- package/dist/src/runner/mission-plan-parent.d.ts.map +0 -1
- package/dist/src/runner/mission-plan-parent.js +0 -589
- package/dist/src/runner/mission-plan-parent.js.map +0 -1
- package/dist/src/runner/mission-process-executor.d.ts +0 -25
- package/dist/src/runner/mission-process-executor.d.ts.map +0 -1
- package/dist/src/runner/mission-process-executor.js +0 -182
- package/dist/src/runner/mission-process-executor.js.map +0 -1
- package/dist/src/runner/mission-publication-git.d.ts +0 -21
- package/dist/src/runner/mission-publication-git.d.ts.map +0 -1
- package/dist/src/runner/mission-publication-git.js +0 -61
- package/dist/src/runner/mission-publication-git.js.map +0 -1
- package/dist/src/runner/mission-publication.d.ts +0 -192
- package/dist/src/runner/mission-publication.d.ts.map +0 -1
- package/dist/src/runner/mission-publication.js +0 -1001
- package/dist/src/runner/mission-publication.js.map +0 -1
- package/dist/src/runner/mission-quarantine-patch-executor.d.ts +0 -29
- package/dist/src/runner/mission-quarantine-patch-executor.d.ts.map +0 -1
- package/dist/src/runner/mission-quarantine-patch-executor.js +0 -121
- package/dist/src/runner/mission-quarantine-patch-executor.js.map +0 -1
- package/dist/src/runner/mission-repository-executor.d.ts +0 -54
- package/dist/src/runner/mission-repository-executor.d.ts.map +0 -1
- package/dist/src/runner/mission-repository-executor.js +0 -192
- package/dist/src/runner/mission-repository-executor.js.map +0 -1
- package/dist/src/runner/mission-repository-observer.d.ts +0 -8
- package/dist/src/runner/mission-repository-observer.d.ts.map +0 -1
- package/dist/src/runner/mission-repository-observer.js +0 -24
- package/dist/src/runner/mission-repository-observer.js.map +0 -1
- package/dist/src/runner/mission-reservations.d.ts +0 -15
- package/dist/src/runner/mission-reservations.d.ts.map +0 -1
- package/dist/src/runner/mission-reservations.js +0 -116
- package/dist/src/runner/mission-reservations.js.map +0 -1
- package/dist/src/runner/mission-resolution-loop.d.ts +0 -172
- package/dist/src/runner/mission-resolution-loop.d.ts.map +0 -1
- package/dist/src/runner/mission-resolution-loop.js +0 -318
- package/dist/src/runner/mission-resolution-loop.js.map +0 -1
- package/dist/src/runner/mission-runtime-owner.d.ts +0 -36
- package/dist/src/runner/mission-runtime-owner.d.ts.map +0 -1
- package/dist/src/runner/mission-runtime-owner.js +0 -174
- package/dist/src/runner/mission-runtime-owner.js.map +0 -1
- package/dist/src/runner/mission-safe-executor.d.ts +0 -96
- package/dist/src/runner/mission-safe-executor.d.ts.map +0 -1
- package/dist/src/runner/mission-safe-executor.js +0 -288
- package/dist/src/runner/mission-safe-executor.js.map +0 -1
- package/dist/src/runner/mission-sandbox.d.ts +0 -16
- package/dist/src/runner/mission-sandbox.d.ts.map +0 -1
- package/dist/src/runner/mission-sandbox.js +0 -91
- package/dist/src/runner/mission-sandbox.js.map +0 -1
- package/dist/src/runner/mission-scheduler.d.ts +0 -57
- package/dist/src/runner/mission-scheduler.d.ts.map +0 -1
- package/dist/src/runner/mission-scheduler.js +0 -205
- package/dist/src/runner/mission-scheduler.js.map +0 -1
- package/dist/src/runner/mission-scope-expansion.d.ts +0 -47
- package/dist/src/runner/mission-scope-expansion.d.ts.map +0 -1
- package/dist/src/runner/mission-scope-expansion.js +0 -147
- package/dist/src/runner/mission-scope-expansion.js.map +0 -1
- package/dist/src/runner/mission-state-machine.d.ts +0 -118
- package/dist/src/runner/mission-state-machine.d.ts.map +0 -1
- package/dist/src/runner/mission-state-machine.js +0 -316
- package/dist/src/runner/mission-state-machine.js.map +0 -1
- package/dist/src/runner/mission-state-store.d.ts +0 -70
- package/dist/src/runner/mission-state-store.d.ts.map +0 -1
- package/dist/src/runner/mission-state-store.js +0 -916
- package/dist/src/runner/mission-state-store.js.map +0 -1
- package/dist/src/runner/mobile-device-lease.d.ts +0 -11
- package/dist/src/runner/mobile-device-lease.d.ts.map +0 -1
- package/dist/src/runner/mobile-device-lease.js +0 -121
- package/dist/src/runner/mobile-device-lease.js.map +0 -1
- package/dist/src/runner/mobile-visual-proof-command.d.ts +0 -17
- package/dist/src/runner/mobile-visual-proof-command.d.ts.map +0 -1
- package/dist/src/runner/mobile-visual-proof-command.js +0 -168
- package/dist/src/runner/mobile-visual-proof-command.js.map +0 -1
- package/dist/src/runner/plan-auto-command.d.ts +0 -35
- package/dist/src/runner/plan-auto-command.d.ts.map +0 -1
- package/dist/src/runner/plan-auto-command.js +0 -918
- package/dist/src/runner/plan-auto-command.js.map +0 -1
- package/dist/src/runner/plan-auto-recovery.d.ts +0 -83
- package/dist/src/runner/plan-auto-recovery.d.ts.map +0 -1
- package/dist/src/runner/plan-auto-recovery.js +0 -303
- package/dist/src/runner/plan-auto-recovery.js.map +0 -1
- package/dist/src/runner/prompt.d.ts +0 -68
- package/dist/src/runner/prompt.d.ts.map +0 -1
- package/dist/src/runner/prompt.js +0 -202
- package/dist/src/runner/prompt.js.map +0 -1
- package/dist/src/runner/proof-routing.d.ts +0 -73
- package/dist/src/runner/proof-routing.d.ts.map +0 -1
- package/dist/src/runner/proof-routing.js +0 -182
- package/dist/src/runner/proof-routing.js.map +0 -1
- package/dist/src/runner/proof-strategy.d.ts +0 -21
- package/dist/src/runner/proof-strategy.d.ts.map +0 -1
- package/dist/src/runner/proof-strategy.js +0 -26
- package/dist/src/runner/proof-strategy.js.map +0 -1
- package/dist/src/runner/recovery.d.ts +0 -25
- package/dist/src/runner/recovery.d.ts.map +0 -1
- package/dist/src/runner/recovery.js +0 -89
- package/dist/src/runner/recovery.js.map +0 -1
- package/dist/src/runner/review-gate-policy.d.ts +0 -13
- package/dist/src/runner/review-gate-policy.d.ts.map +0 -1
- package/dist/src/runner/review-gate-policy.js +0 -241
- package/dist/src/runner/review-gate-policy.js.map +0 -1
- package/dist/src/runner/review-gates.d.ts +0 -28
- package/dist/src/runner/review-gates.d.ts.map +0 -1
- package/dist/src/runner/review-gates.js +0 -328
- package/dist/src/runner/review-gates.js.map +0 -1
- package/dist/src/runner/rework-policy.d.ts +0 -48
- package/dist/src/runner/rework-policy.d.ts.map +0 -1
- package/dist/src/runner/rework-policy.js +0 -150
- package/dist/src/runner/rework-policy.js.map +0 -1
- package/dist/src/runner/run-log.d.ts +0 -18
- package/dist/src/runner/run-log.d.ts.map +0 -1
- package/dist/src/runner/run-log.js +0 -53
- package/dist/src/runner/run-log.js.map +0 -1
- package/dist/src/runner/runner-handoff-decision.d.ts +0 -48
- package/dist/src/runner/runner-handoff-decision.d.ts.map +0 -1
- package/dist/src/runner/runner-handoff-decision.js +0 -93
- package/dist/src/runner/runner-handoff-decision.js.map +0 -1
- package/dist/src/runner/safety.d.ts +0 -14
- package/dist/src/runner/safety.d.ts.map +0 -1
- package/dist/src/runner/safety.js +0 -31
- package/dist/src/runner/safety.js.map +0 -1
- package/dist/src/runner/scope-isolation-policy.d.ts +0 -17
- package/dist/src/runner/scope-isolation-policy.d.ts.map +0 -1
- package/dist/src/runner/scope-isolation-policy.js +0 -82
- package/dist/src/runner/scope-isolation-policy.js.map +0 -1
- package/dist/src/runner/scoped-auto-command.d.ts +0 -90
- package/dist/src/runner/scoped-auto-command.d.ts.map +0 -1
- package/dist/src/runner/scoped-auto-command.js +0 -561
- package/dist/src/runner/scoped-auto-command.js.map +0 -1
- package/dist/src/runner/scoped-recovery.d.ts +0 -78
- package/dist/src/runner/scoped-recovery.d.ts.map +0 -1
- package/dist/src/runner/scoped-recovery.js +0 -601
- package/dist/src/runner/scoped-recovery.js.map +0 -1
- package/dist/src/runner/session-home.d.ts +0 -8
- package/dist/src/runner/session-home.d.ts.map +0 -1
- package/dist/src/runner/session-home.js +0 -18
- package/dist/src/runner/session-home.js.map +0 -1
- package/dist/src/runner/status-command.d.ts +0 -38
- package/dist/src/runner/status-command.d.ts.map +0 -1
- package/dist/src/runner/status-command.js +0 -97
- package/dist/src/runner/status-command.js.map +0 -1
- package/dist/src/runner/target-activity-fence.d.ts.map +0 -1
- package/dist/src/runner/target-activity-fence.js.map +0 -1
- package/dist/src/runner/terminal-outcome.d.ts +0 -58
- package/dist/src/runner/terminal-outcome.d.ts.map +0 -1
- package/dist/src/runner/terminal-outcome.js +0 -73
- package/dist/src/runner/terminal-outcome.js.map +0 -1
- package/dist/src/runner/visual-proof-runner.d.ts +0 -27
- package/dist/src/runner/visual-proof-runner.d.ts.map +0 -1
- package/dist/src/runner/visual-proof-runner.js +0 -379
- package/dist/src/runner/visual-proof-runner.js.map +0 -1
- package/dist/src/runner/worktree-cleanup.d.ts +0 -27
- package/dist/src/runner/worktree-cleanup.d.ts.map +0 -1
- package/dist/src/runner/worktree-cleanup.js +0 -63
- package/dist/src/runner/worktree-cleanup.js.map +0 -1
- package/dist/src/setup/codex-command-resolver.d.ts +0 -10
- package/dist/src/setup/codex-command-resolver.d.ts.map +0 -1
- package/dist/src/setup/codex-command-resolver.js +0 -91
- package/dist/src/setup/codex-command-resolver.js.map +0 -1
- package/dist/src/setup/github-label-adapter.d.ts +0 -13
- package/dist/src/setup/github-label-adapter.d.ts.map +0 -1
- package/dist/src/setup/github-label-adapter.js +0 -28
- package/dist/src/setup/github-label-adapter.js.map +0 -1
- package/dist/src/setup/labels.d.ts +0 -27
- package/dist/src/setup/labels.d.ts.map +0 -1
- package/dist/src/setup/labels.js +0 -42
- package/dist/src/setup/labels.js.map +0 -1
- package/dist/src/setup/project-config.d.ts +0 -24
- package/dist/src/setup/project-config.d.ts.map +0 -1
- package/dist/src/setup/project-config.js +0 -678
- package/dist/src/setup/project-config.js.map +0 -1
- package/dist/src/setup/prompt-sync.d.ts +0 -14
- package/dist/src/setup/prompt-sync.d.ts.map +0 -1
- package/dist/src/setup/prompt-sync.js +0 -228
- package/dist/src/setup/prompt-sync.js.map +0 -1
- package/dist/src/setup/setup-command.d.ts +0 -29
- package/dist/src/setup/setup-command.d.ts.map +0 -1
- package/dist/src/setup/setup-command.js +0 -304
- package/dist/src/setup/setup-command.js.map +0 -1
- package/dist/src/setup/skill-runtime-v2-preparation.d.ts +0 -56
- package/dist/src/setup/skill-runtime-v2-preparation.d.ts.map +0 -1
- package/dist/src/setup/skill-runtime-v2-preparation.js +0 -304
- package/dist/src/setup/skill-runtime-v2-preparation.js.map +0 -1
- package/dist/src/setup/workflows.d.ts +0 -10
- package/dist/src/setup/workflows.d.ts.map +0 -1
- package/dist/src/setup/workflows.js +0 -41
- package/dist/src/setup/workflows.js.map +0 -1
- package/prompts/setup-skill.md +0 -12
- package/prompts/workflows/acceptance-proof.md +0 -29
- package/prompts/workflows/breakdown-review.md +0 -48
- package/prompts/workflows/issue-breakdown.md +0 -155
- package/prompts/workflows/issue-tree-orchestration.md +0 -163
- package/prompts/workflows/prd.md +0 -80
- package/prompts/workflows/scoped-implementation.md +0 -129
- package/prompts/workflows/triage.md +0 -149
- /package/dist/src/{process → v2/adapters}/command.d.ts +0 -0
- /package/dist/src/{process → v2/adapters}/command.js +0 -0
- /package/dist/src/{fs → v2/adapters}/durable-atomic-file.d.ts +0 -0
- /package/dist/src/{fs → v2/adapters}/durable-atomic-file.js +0 -0
- /package/dist/src/{github → v2/adapters}/gh-cli.d.ts +0 -0
- /package/dist/src/{github → v2/adapters}/gh-cli.js +0 -0
- /package/dist/src/{github → v2/adapters}/gh-issue-adapter.d.ts +0 -0
- /package/dist/src/{github → v2/adapters}/gh-issue-adapter.js +0 -0
- /package/dist/src/{github → v2/adapters}/gh-pull-request-adapter.d.ts +0 -0
- /package/dist/src/{github → v2/adapters}/gh-pull-request-adapter.js +0 -0
- /package/dist/src/{github → v2/adapters}/issues.d.ts +0 -0
- /package/dist/src/{github → v2/adapters}/issues.js +0 -0
- /package/dist/src/{runner → v2/adapters}/mission-coordinator-lock.d.ts +0 -0
- /package/dist/src/{runner → v2/adapters}/mission-coordinator-lock.js +0 -0
- /package/dist/src/{path-policy.d.ts → v2/adapters/path-policy.d.ts} +0 -0
- /package/dist/src/{path-policy.js → v2/adapters/path-policy.js} +0 -0
- /package/dist/src/{github → v2/adapters}/pull-requests.d.ts +0 -0
- /package/dist/src/{github → v2/adapters}/pull-requests.js +0 -0
- /package/dist/src/{runner → v2/adapters}/target-activity-fence.d.ts +0 -0
|
@@ -0,0 +1,847 @@
|
|
|
1
|
+
import { constants } from 'node:fs';
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
3
|
+
import { spawn } from 'node:child_process';
|
|
4
|
+
import { lstat, mkdir, open, readFile, readdir, readlink, realpath } from 'node:fs/promises';
|
|
5
|
+
import { homedir, hostname } from 'node:os';
|
|
6
|
+
import { dirname, isAbsolute, join, posix, resolve } from 'node:path';
|
|
7
|
+
import { writeDurableAtomicFile } from './adapters/durable-atomic-file.js';
|
|
8
|
+
import { GitWorktreeManager } from './adapters/worktree.js';
|
|
9
|
+
import { defaultProcessExecutor } from './adapters/command.js';
|
|
10
|
+
import { AcceptanceProof, ProofQuiescenceError } from './acceptance-proof.js';
|
|
11
|
+
import { acquireExclusiveJsonFileLock } from './atomic-store.js';
|
|
12
|
+
import { createCheckedChangeCapabilities } from './checked-change.js';
|
|
13
|
+
import { parseAgentAutoConfig } from './config.js';
|
|
14
|
+
import { canonicalJson, containmentArgvPolicySha256, containmentCertificatePath, parseJsonWithoutDuplicateKeys, readContainmentCertificate, sha256, } from './containment.js';
|
|
15
|
+
import { FileProofRecordWriter } from './proof-store.js';
|
|
16
|
+
import { decodeAgentReportForValidation } from './report-envelope.js';
|
|
17
|
+
import { CodexProcess, ProcessQuiescenceError } from './codex-process.js';
|
|
18
|
+
import { FileAndroidLeaseVerifier, FileIosLeaseVerifier } from './mobile-lease.js';
|
|
19
|
+
import { publishRuntimeAssetSnapshot } from './runtime-assets.js';
|
|
20
|
+
import { OwnerLockSafetyError, RunIssue } from './run-issue.js';
|
|
21
|
+
import { FileRunRecordWriter } from './run-store.js';
|
|
22
|
+
export class LocalGitRunIssueAdapter {
|
|
23
|
+
executor;
|
|
24
|
+
worktrees;
|
|
25
|
+
constructor(executor = defaultProcessExecutor) {
|
|
26
|
+
this.executor = executor;
|
|
27
|
+
this.worktrees = new GitWorktreeManager(executor);
|
|
28
|
+
}
|
|
29
|
+
async getBaseSha(input) {
|
|
30
|
+
return (await this.git(['-C', input.targetRoot, 'rev-parse', input.baseBranch])).trim();
|
|
31
|
+
}
|
|
32
|
+
async createWorktree(input) {
|
|
33
|
+
await this.worktrees.createIssueWorktree({
|
|
34
|
+
targetRoot: input.targetRoot,
|
|
35
|
+
workspacePath: input.worktreePath,
|
|
36
|
+
branchName: input.branchName,
|
|
37
|
+
baseBranch: input.baseBranch,
|
|
38
|
+
requiredBaseSha: input.baseSha,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
async inspectWorktree(input) {
|
|
42
|
+
try {
|
|
43
|
+
const stat = await lstat(input.worktreePath);
|
|
44
|
+
if (stat.isSymbolicLink() || !stat.isDirectory())
|
|
45
|
+
return 'diverged';
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
if (isErrorCode(error, 'ENOENT'))
|
|
49
|
+
return 'absent';
|
|
50
|
+
throw error;
|
|
51
|
+
}
|
|
52
|
+
const [head, branch] = await Promise.all([
|
|
53
|
+
this.getHead(input.worktreePath),
|
|
54
|
+
this.git(['-C', input.worktreePath, 'branch', '--show-current']),
|
|
55
|
+
]);
|
|
56
|
+
return head === input.baseSha && branch.trim() === input.branchName ? 'matching' : 'diverged';
|
|
57
|
+
}
|
|
58
|
+
async snapshot(worktreePath) {
|
|
59
|
+
return this.snapshotWithIgnoredUntrackedRoot(worktreePath);
|
|
60
|
+
}
|
|
61
|
+
async snapshotIgnoringUntrackedRoot(worktreePath, ignoredRoot) {
|
|
62
|
+
validateRelativeRoot(ignoredRoot);
|
|
63
|
+
return this.snapshotWithIgnoredUntrackedRoot(worktreePath, ignoredRoot);
|
|
64
|
+
}
|
|
65
|
+
async fingerprintDeniedPaths(worktreePath, deniedPaths) {
|
|
66
|
+
const root = await realpath(worktreePath);
|
|
67
|
+
const entries = [];
|
|
68
|
+
for (const path of [...deniedPaths].sort()) {
|
|
69
|
+
entries.push({
|
|
70
|
+
path,
|
|
71
|
+
fingerprint: isAbsolute(path)
|
|
72
|
+
? { kind: 'external-path-not-monitored' }
|
|
73
|
+
: await fingerprintRepositoryPath(root, path),
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
return sha256(canonicalJson(entries));
|
|
77
|
+
}
|
|
78
|
+
async snapshotWithIgnoredUntrackedRoot(worktreePath, ignoredRoot) {
|
|
79
|
+
const [headSha, indexTreeSha, trackedDiff, untrackedPaths, canonicalPath, gitDirectory] = await Promise.all([
|
|
80
|
+
this.getHead(worktreePath),
|
|
81
|
+
this.getTreeSha(worktreePath),
|
|
82
|
+
this.git(['-C', worktreePath, 'diff', '--binary', 'HEAD']),
|
|
83
|
+
this.git(['-C', worktreePath, 'ls-files', '--others', '--exclude-standard', '-z']),
|
|
84
|
+
realpath(worktreePath),
|
|
85
|
+
this.git(['-C', worktreePath, 'rev-parse', '--git-dir']),
|
|
86
|
+
]);
|
|
87
|
+
const untracked = [];
|
|
88
|
+
for (const path of untrackedPaths.split('\0').filter(Boolean).sort()) {
|
|
89
|
+
if (ignoredRoot && (path === ignoredRoot || path.startsWith(`${ignoredRoot}/`)))
|
|
90
|
+
continue;
|
|
91
|
+
untracked.push({ path, sha256: sha256(await readFile(join(canonicalPath, path))) });
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
headSha,
|
|
95
|
+
indexTreeSha,
|
|
96
|
+
trackedContentSha256: sha256(trackedDiff),
|
|
97
|
+
untrackedContentSha256: sha256(canonicalJson(untracked)),
|
|
98
|
+
worktreeIdentity: sha256(canonicalJson({ canonicalPath, gitDirectory: gitDirectory.trim() })),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
listChangedFiles(worktreePath) {
|
|
102
|
+
return this.worktrees.listChangedFiles(worktreePath);
|
|
103
|
+
}
|
|
104
|
+
async stageAll(worktreePath) {
|
|
105
|
+
await this.git(['-C', worktreePath, 'add', '--all']);
|
|
106
|
+
}
|
|
107
|
+
async getTreeSha(worktreePath) {
|
|
108
|
+
return (await this.git(['-C', worktreePath, 'write-tree'])).trim();
|
|
109
|
+
}
|
|
110
|
+
async getHead(worktreePath) {
|
|
111
|
+
return this.worktrees.getHead(worktreePath);
|
|
112
|
+
}
|
|
113
|
+
async inspectHead(worktreePath) {
|
|
114
|
+
const [sha, parentSha, treeSha, message] = (await this.git([
|
|
115
|
+
'-C', worktreePath, 'show', '-s', '--format=%H%n%P%n%T%n%B', 'HEAD',
|
|
116
|
+
])).split('\n', 4);
|
|
117
|
+
if (!sha || !parentSha || !treeSha || message === undefined || parentSha.includes(' '))
|
|
118
|
+
throw new Error('HEAD commit is not a single-parent commit');
|
|
119
|
+
return { sha, parentSha, treeSha, message: message.trimEnd() };
|
|
120
|
+
}
|
|
121
|
+
async getRemoteBranchSha(worktreePath, branchName) {
|
|
122
|
+
const output = (await this.git(['-C', worktreePath, 'ls-remote', '--heads', 'origin', `refs/heads/${branchName}`])).trim();
|
|
123
|
+
if (!output)
|
|
124
|
+
return undefined;
|
|
125
|
+
const rows = output.split('\n');
|
|
126
|
+
if (rows.length !== 1)
|
|
127
|
+
throw new Error('remote branch observation is ambiguous');
|
|
128
|
+
const [sha, ref] = rows[0].split(/\s+/u);
|
|
129
|
+
if (!sha || ref !== `refs/heads/${branchName}`)
|
|
130
|
+
throw new Error('remote branch observation is invalid');
|
|
131
|
+
return sha;
|
|
132
|
+
}
|
|
133
|
+
async commit(input) {
|
|
134
|
+
await this.git([
|
|
135
|
+
'-C',
|
|
136
|
+
input.worktreePath,
|
|
137
|
+
'-c',
|
|
138
|
+
'core.hooksPath=/dev/null',
|
|
139
|
+
'-c',
|
|
140
|
+
'user.name=codex-orchestrator',
|
|
141
|
+
'-c',
|
|
142
|
+
'user.email=codex-orchestrator@users.noreply.github.com',
|
|
143
|
+
'commit',
|
|
144
|
+
'--no-verify',
|
|
145
|
+
'-m',
|
|
146
|
+
input.message,
|
|
147
|
+
]);
|
|
148
|
+
return this.getHead(input.worktreePath);
|
|
149
|
+
}
|
|
150
|
+
push(input) {
|
|
151
|
+
return this.worktrees.pushBranch(input);
|
|
152
|
+
}
|
|
153
|
+
async git(args) {
|
|
154
|
+
const result = await this.executor('git', args);
|
|
155
|
+
if (result.exitCode !== 0)
|
|
156
|
+
throw new Error(`git failed: ${result.stderr}`);
|
|
157
|
+
return result.stdout;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
export class ContainedImplementationAgent {
|
|
161
|
+
dependencies;
|
|
162
|
+
constructor(dependencies) {
|
|
163
|
+
this.dependencies = dependencies;
|
|
164
|
+
}
|
|
165
|
+
async run(input) {
|
|
166
|
+
const config = this.dependencies.config();
|
|
167
|
+
const canonicalRepository = `${config.github.owner.toLowerCase()}/${config.github.repo.toLowerCase()}`;
|
|
168
|
+
const attemptId = (this.dependencies.createAttemptId ?? randomUUID)();
|
|
169
|
+
const attempt = await prepareContainedAttempt({
|
|
170
|
+
packageRoot: this.dependencies.packageRoot,
|
|
171
|
+
orchestratorHome: this.dependencies.orchestratorHome,
|
|
172
|
+
canonicalRepository,
|
|
173
|
+
runId: input.runId,
|
|
174
|
+
attemptId,
|
|
175
|
+
skill: 'agent-auto',
|
|
176
|
+
expectedPackageVersion: this.dependencies.packageVersion,
|
|
177
|
+
});
|
|
178
|
+
const baseline = await this.dependencies.git.snapshot(input.worktreePath);
|
|
179
|
+
try {
|
|
180
|
+
const result = await (this.dependencies.process ?? new CodexProcess()).run({
|
|
181
|
+
codexPath: config.codex.command,
|
|
182
|
+
cwd: input.worktreePath,
|
|
183
|
+
schemaPath: attempt.schemaPath,
|
|
184
|
+
reportPath: attempt.reportPath,
|
|
185
|
+
toolHome: attempt.toolHome,
|
|
186
|
+
tmpDir: attempt.tmpDir,
|
|
187
|
+
safePath: this.dependencies.safePath,
|
|
188
|
+
parentCodexHome: this.dependencies.parentCodexHome,
|
|
189
|
+
parentEnv: process.env,
|
|
190
|
+
prompt: [
|
|
191
|
+
`Follow the exact skill at ${attempt.skillPath}.`,
|
|
192
|
+
`Implement issue #${input.issue.number}: ${input.issue.title}`,
|
|
193
|
+
`Implementation cycle: ${input.cycle}.`,
|
|
194
|
+
`Frozen acceptance criteria: ${canonicalJson(input.frozenCriteria)}`,
|
|
195
|
+
...(input.reworkFindings.length > 0 ? [`Repair these verified findings: ${canonicalJson(input.reworkFindings)}`] : []),
|
|
196
|
+
...(input.repairOnly ? ['Report repair only: do not modify any worktree file; emit a schema-valid implementation report for the existing change.'] : []),
|
|
197
|
+
'Do not commit, push, publish, or print credentials or local auth paths.',
|
|
198
|
+
].join('\n'),
|
|
199
|
+
timeoutMs: config.codex.timeoutMs,
|
|
200
|
+
idleTimeoutMs: config.codex.idleTimeoutMs,
|
|
201
|
+
}, input.signal);
|
|
202
|
+
if (result.kind === 'cancelled')
|
|
203
|
+
return { kind: 'cancelled' };
|
|
204
|
+
if (['spawn-failed', 'transport-failed', 'timeout', 'idle-timeout'].includes(result.kind)) {
|
|
205
|
+
return { kind: 'transport-failed', resumable: true };
|
|
206
|
+
}
|
|
207
|
+
if (result.kind !== 'completed' || result.report.kind !== 'available')
|
|
208
|
+
return { kind: 'internal-error' };
|
|
209
|
+
return {
|
|
210
|
+
kind: 'completed',
|
|
211
|
+
report: decodeAgentReportForValidation(result.report.bytes),
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
catch (error) {
|
|
215
|
+
if (!(error instanceof ProcessQuiescenceError))
|
|
216
|
+
return { kind: 'internal-error' };
|
|
217
|
+
return {
|
|
218
|
+
kind: 'safe-halt',
|
|
219
|
+
process: {
|
|
220
|
+
pid: error.pid,
|
|
221
|
+
processGroupId: error.processGroupId,
|
|
222
|
+
startedAt: (this.dependencies.now ?? (() => new Date().toISOString()))(),
|
|
223
|
+
baseline: { ...baseline },
|
|
224
|
+
},
|
|
225
|
+
waitForAbsence: () => waitForProcessGroupAbsent(error.processGroupId),
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
export class ContainedProofAgent {
|
|
231
|
+
dependencies;
|
|
232
|
+
constructor(dependencies) {
|
|
233
|
+
this.dependencies = dependencies;
|
|
234
|
+
}
|
|
235
|
+
async run(input) {
|
|
236
|
+
const config = this.dependencies.config();
|
|
237
|
+
const canonicalRepository = `${config.github.owner.toLowerCase()}/${config.github.repo.toLowerCase()}`;
|
|
238
|
+
const worktreePath = resolve(this.dependencies.targetRoot, config.runner.workspaceRoot, `issue-${input.issue.number}`);
|
|
239
|
+
const attempt = await prepareContainedAttempt({
|
|
240
|
+
packageRoot: this.dependencies.packageRoot,
|
|
241
|
+
orchestratorHome: this.dependencies.orchestratorHome,
|
|
242
|
+
canonicalRepository,
|
|
243
|
+
runId: input.runId,
|
|
244
|
+
attemptId: (this.dependencies.createAttemptId ?? randomUUID)(),
|
|
245
|
+
skill: 'acceptance-proof',
|
|
246
|
+
expectedPackageVersion: this.dependencies.packageVersion,
|
|
247
|
+
});
|
|
248
|
+
const artifactRoot = resolve(worktreePath, config.proof.artifactDir);
|
|
249
|
+
const snapshotRoot = dirname(attempt.skillPath);
|
|
250
|
+
const androidLeaseRoot = join(resolve(this.dependencies.orchestratorHome), 'v2', sha256(canonicalRepository), 'leases');
|
|
251
|
+
const androidLeaseArtifact = join(artifactRoot, input.proofId, 'android-lease.json');
|
|
252
|
+
const iosLeaseRoot = join(resolve(this.dependencies.orchestratorHome), 'v2', sha256(canonicalRepository), 'leases');
|
|
253
|
+
const iosLeaseArtifact = join(artifactRoot, input.proofId, 'ios-lease.json');
|
|
254
|
+
const iosTooling = await discoverIosTooling(this.dependencies.processExecutor, this.dependencies.iosXcrunPath);
|
|
255
|
+
const before = await artifactInventory(artifactRoot, config.proof.artifactDir);
|
|
256
|
+
try {
|
|
257
|
+
const result = await (this.dependencies.process ?? new CodexProcess()).run({
|
|
258
|
+
codexPath: config.codex.command,
|
|
259
|
+
cwd: worktreePath,
|
|
260
|
+
schemaPath: attempt.schemaPath,
|
|
261
|
+
reportPath: attempt.reportPath,
|
|
262
|
+
toolHome: attempt.toolHome,
|
|
263
|
+
tmpDir: attempt.tmpDir,
|
|
264
|
+
safePath: this.dependencies.safePath,
|
|
265
|
+
parentCodexHome: this.dependencies.parentCodexHome,
|
|
266
|
+
parentEnv: process.env,
|
|
267
|
+
prompt: [
|
|
268
|
+
`Follow the exact skill at ${attempt.skillPath}.`,
|
|
269
|
+
`Independently prove issue #${input.issue.number}.`,
|
|
270
|
+
`Frozen acceptance criteria: ${canonicalJson(input.frozenCriteria)}`,
|
|
271
|
+
`Checked change digest: ${input.checkedChangeSha256}.`,
|
|
272
|
+
`Checked changed files: ${canonicalJson(input.changedFiles)}.`,
|
|
273
|
+
`Configured check receipts: ${canonicalJson(input.checks)}.`,
|
|
274
|
+
`Write evidence only below ${config.proof.artifactDir}.`,
|
|
275
|
+
'When a frozen criterion has a browser surface, follow references/browser.md from the exact acceptance-proof skill snapshot.',
|
|
276
|
+
'When a frozen criterion has an Android surface, follow references/android.md from the exact acceptance-proof skill snapshot.',
|
|
277
|
+
`Android lease helper: ${join(snapshotRoot, 'tools', 'android-lease.mjs')}.`,
|
|
278
|
+
`Android lease root: ${androidLeaseRoot}.`,
|
|
279
|
+
`Android lease artifact: ${androidLeaseArtifact}.`,
|
|
280
|
+
`Android lease proof ID: ${input.proofId}.`,
|
|
281
|
+
`Android lease owner PID: ${process.pid}.`,
|
|
282
|
+
`Android adb path: ${this.dependencies.androidAdbPath}.`,
|
|
283
|
+
'When a frozen criterion has an iOS surface, follow references/ios.md from the exact acceptance-proof skill snapshot.',
|
|
284
|
+
`iOS lease helper: ${join(snapshotRoot, 'tools', 'ios-lease.mjs')}.`,
|
|
285
|
+
`iOS lease root: ${iosLeaseRoot}.`,
|
|
286
|
+
`iOS lease artifact: ${iosLeaseArtifact}.`,
|
|
287
|
+
`iOS lease proof ID: ${input.proofId}.`,
|
|
288
|
+
`iOS lease owner PID: ${process.pid}.`,
|
|
289
|
+
`iOS xcrun path: ${this.dependencies.iosXcrunPath}.`,
|
|
290
|
+
...(iosTooling ? [
|
|
291
|
+
`iOS runtime ID: ${iosTooling.runtimeId}.`,
|
|
292
|
+
`iOS device type ID: ${iosTooling.deviceTypeId}.`,
|
|
293
|
+
] : ['iOS Simulator tooling discovery is unavailable; return a typed tool blocker for an iOS surface.']),
|
|
294
|
+
...(input.repairOnly ? [`Proof Report repair only: ${canonicalJson(input.repairFindings)} Do not modify product or evidence files.`] : []),
|
|
295
|
+
'Do not modify product files, commit, push, publish, or print credentials or local auth paths.',
|
|
296
|
+
].join('\n'),
|
|
297
|
+
timeoutMs: config.codex.timeoutMs,
|
|
298
|
+
idleTimeoutMs: config.codex.idleTimeoutMs,
|
|
299
|
+
}, input.signal);
|
|
300
|
+
if (result.kind === 'cancelled')
|
|
301
|
+
return { kind: 'cancelled' };
|
|
302
|
+
if (['spawn-failed', 'transport-failed', 'timeout', 'idle-timeout'].includes(result.kind)) {
|
|
303
|
+
return { kind: 'transport-failed', resumable: true };
|
|
304
|
+
}
|
|
305
|
+
if (result.kind !== 'completed' || result.report.kind !== 'available')
|
|
306
|
+
return { kind: 'internal-error' };
|
|
307
|
+
const after = await artifactInventory(artifactRoot, config.proof.artifactDir);
|
|
308
|
+
return {
|
|
309
|
+
kind: 'report',
|
|
310
|
+
report: decodeAgentReportForValidation(result.report.bytes, ['visualEvidence', 'blocker']),
|
|
311
|
+
proofPhaseChangedFiles: changedArtifactPaths(before, after),
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
catch (error) {
|
|
315
|
+
if (error instanceof ProcessQuiescenceError) {
|
|
316
|
+
throw new ProofQuiescenceError(error.pid, error.processGroupId, () => waitForProcessGroupAbsent(error.processGroupId));
|
|
317
|
+
}
|
|
318
|
+
return { kind: 'internal-error' };
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
export function createV2Runtime(input) {
|
|
323
|
+
const targetRoot = resolve(input.targetRoot);
|
|
324
|
+
const orchestratorHome = resolve(input.orchestratorHome);
|
|
325
|
+
const now = input.now ?? (() => new Date().toISOString());
|
|
326
|
+
const commandExecutor = input.processExecutor ?? defaultProcessExecutor;
|
|
327
|
+
const git = input.git ?? new LocalGitRunIssueAdapter(commandExecutor);
|
|
328
|
+
const proofFreshnessGit = git;
|
|
329
|
+
const controller = new AbortController();
|
|
330
|
+
let currentConfig;
|
|
331
|
+
let runRecords;
|
|
332
|
+
const containedProcess = input.codexProcess ?? new CodexProcess();
|
|
333
|
+
const configuredAndroidAdbPath = input.androidAdbPath
|
|
334
|
+
?? process.env.ANDROID_ADB
|
|
335
|
+
?? (process.env.ANDROID_HOME ? join(process.env.ANDROID_HOME, 'platform-tools', 'adb') : undefined)
|
|
336
|
+
?? (process.env.ANDROID_SDK_ROOT ? join(process.env.ANDROID_SDK_ROOT, 'platform-tools', 'adb') : undefined)
|
|
337
|
+
?? join(homedir(), 'Library', 'Android', 'sdk', 'platform-tools', 'adb');
|
|
338
|
+
const androidAdbPath = resolve(configuredAndroidAdbPath);
|
|
339
|
+
const iosXcrunPath = resolve(input.iosXcrunPath ?? '/usr/bin/xcrun');
|
|
340
|
+
const containedDependencies = () => ({
|
|
341
|
+
config: () => requireConfig(currentConfig),
|
|
342
|
+
packageRoot: requireRuntimeString(input.packageRoot, 'packageRoot'),
|
|
343
|
+
orchestratorHome,
|
|
344
|
+
parentCodexHome: requireRuntimeString(input.parentCodexHome, 'parentCodexHome'),
|
|
345
|
+
safePath: requireRuntimeString(input.safePath, 'safePath'),
|
|
346
|
+
packageVersion: input.packageVersion,
|
|
347
|
+
process: containedProcess,
|
|
348
|
+
createAttemptId: input.createAttemptId,
|
|
349
|
+
});
|
|
350
|
+
const implementationAgent = input.implementationAgent ?? new ContainedImplementationAgent({
|
|
351
|
+
...containedDependencies(),
|
|
352
|
+
git,
|
|
353
|
+
now,
|
|
354
|
+
});
|
|
355
|
+
const proofAgent = input.proofAgent ?? new ContainedProofAgent({
|
|
356
|
+
...containedDependencies(),
|
|
357
|
+
targetRoot,
|
|
358
|
+
androidAdbPath,
|
|
359
|
+
iosXcrunPath,
|
|
360
|
+
processExecutor: commandExecutor,
|
|
361
|
+
});
|
|
362
|
+
const readConfig = async (requestedRoot) => {
|
|
363
|
+
if (resolve(requestedRoot) !== targetRoot)
|
|
364
|
+
throw new Error('runtime target root mismatch');
|
|
365
|
+
const bytes = await readRegularFile(join(targetRoot, '.codex-orchestrator', 'config.json'));
|
|
366
|
+
const config = parseAgentAutoConfig(parseJsonWithoutDuplicateKeys(bytes.toString('utf8')));
|
|
367
|
+
const path = join(targetRoot, config.runner.stateDir, 'v2', 'run-state.json');
|
|
368
|
+
if (!runRecords)
|
|
369
|
+
runRecords = new FileRunRecordWriter(path);
|
|
370
|
+
currentConfig = config;
|
|
371
|
+
return { bytes, config };
|
|
372
|
+
};
|
|
373
|
+
const records = {
|
|
374
|
+
read: async () => {
|
|
375
|
+
if (!runRecords)
|
|
376
|
+
throw new Error('run store used before config');
|
|
377
|
+
return runRecords.read();
|
|
378
|
+
},
|
|
379
|
+
compareAndSwap: async (generation, next) => {
|
|
380
|
+
if (!runRecords)
|
|
381
|
+
throw new Error('run store used before config');
|
|
382
|
+
return runRecords.compareAndSwap(generation, next);
|
|
383
|
+
},
|
|
384
|
+
};
|
|
385
|
+
const capabilities = createCheckedChangeCapabilities();
|
|
386
|
+
const proof = {
|
|
387
|
+
proveChange: async (proofInput) => {
|
|
388
|
+
const config = requireConfig(currentConfig);
|
|
389
|
+
const checked = capabilities.verifyAndRead(proofInput.checkedChange);
|
|
390
|
+
const repoKey = sha256(checked.payload.canonicalRepository);
|
|
391
|
+
const proofRecords = new FileProofRecordWriter(join(orchestratorHome, 'v2', repoKey, 'proofs'));
|
|
392
|
+
const worktreePath = resolve(targetRoot, config.runner.workspaceRoot, `issue-${checked.payload.issueNumber}`);
|
|
393
|
+
const androidLease = new FileAndroidLeaseVerifier({
|
|
394
|
+
leaseRoot: join(orchestratorHome, 'v2', repoKey, 'leases'),
|
|
395
|
+
worktreeRoot: worktreePath,
|
|
396
|
+
now: () => new Date(now()),
|
|
397
|
+
artifactRelativePathForProof: (proofId) => `${config.proof.artifactDir}/${proofId}/android-lease.json`,
|
|
398
|
+
});
|
|
399
|
+
const iosLease = new FileIosLeaseVerifier({
|
|
400
|
+
leaseRoot: join(orchestratorHome, 'v2', repoKey, 'leases'),
|
|
401
|
+
worktreeRoot: worktreePath,
|
|
402
|
+
now: () => new Date(now()),
|
|
403
|
+
artifactRelativePathForProof: (proofId) => `${config.proof.artifactDir}/${proofId}/ios-lease.json`,
|
|
404
|
+
targetController: {
|
|
405
|
+
release: (record) => releaseIosSimulator(commandExecutor, iosXcrunPath, record),
|
|
406
|
+
},
|
|
407
|
+
});
|
|
408
|
+
const acceptanceProof = new AcceptanceProof({
|
|
409
|
+
checkedChangeReader: capabilities,
|
|
410
|
+
proofRecords,
|
|
411
|
+
proofAgent,
|
|
412
|
+
inspectFreshness: async (payload) => ({
|
|
413
|
+
...await (proofFreshnessGit.snapshotIgnoringUntrackedRoot
|
|
414
|
+
? proofFreshnessGit.snapshotIgnoringUntrackedRoot(worktreePath, config.proof.artifactDir)
|
|
415
|
+
: git.snapshot(worktreePath)),
|
|
416
|
+
checkPolicySha256: sha256(canonicalJson(config.checks)),
|
|
417
|
+
}),
|
|
418
|
+
readArtifact: async (relativePath) => readRegularFile(resolve(worktreePath, relativePath)),
|
|
419
|
+
inspectArtifact: async (relativePath) => inspectRegularFile(resolve(worktreePath, relativePath)),
|
|
420
|
+
androidLease,
|
|
421
|
+
iosLease,
|
|
422
|
+
proofArtifactDir: config.proof.artifactDir,
|
|
423
|
+
createAttemptId: input.createAttemptId ?? randomUUID,
|
|
424
|
+
now,
|
|
425
|
+
signal: controller.signal,
|
|
426
|
+
});
|
|
427
|
+
return acceptanceProof.proveChange(proofInput);
|
|
428
|
+
},
|
|
429
|
+
};
|
|
430
|
+
const runner = new RunIssue({
|
|
431
|
+
readConfig,
|
|
432
|
+
validateContainment: async (config) => {
|
|
433
|
+
const certificate = await readContainmentCertificate(containmentCertificatePath(orchestratorHome));
|
|
434
|
+
if (certificate.packageVersion !== input.packageVersion)
|
|
435
|
+
throw new Error('containment package version mismatch');
|
|
436
|
+
if (certificate.argvPolicySha256 !== containmentArgvPolicySha256())
|
|
437
|
+
throw new Error('containment argv policy mismatch');
|
|
438
|
+
const version = await commandExecutor(config.codex.command, ['--version']);
|
|
439
|
+
if (version.exitCode !== 0 || version.stdout.trim() !== `codex-cli ${config.codex.requiredVersion}`) {
|
|
440
|
+
throw new Error('current Codex version does not match the containment certificate');
|
|
441
|
+
}
|
|
442
|
+
},
|
|
443
|
+
ownerLock: {
|
|
444
|
+
acquire: async ({ canonicalRepository }) => acquireOwnerLock({
|
|
445
|
+
orchestratorHome,
|
|
446
|
+
canonicalRepository,
|
|
447
|
+
bootId: input.bootId,
|
|
448
|
+
now,
|
|
449
|
+
processAlive: input.processAlive ?? processIsAlive,
|
|
450
|
+
}),
|
|
451
|
+
},
|
|
452
|
+
issues: {
|
|
453
|
+
read: async (issueNumber) => {
|
|
454
|
+
const issue = await input.issues.getIssue(issueNumber);
|
|
455
|
+
if (!issue || issue.state !== 'OPEN')
|
|
456
|
+
return issue ? {
|
|
457
|
+
number: issue.number, title: issue.title, body: issue.body, url: issue.url, state: 'CLOSED',
|
|
458
|
+
labels: issue.labels.map((label) => label.name).sort(), comments: [],
|
|
459
|
+
} : undefined;
|
|
460
|
+
const comments = await input.issues.listAllComments(issueNumber);
|
|
461
|
+
return {
|
|
462
|
+
number: issue.number,
|
|
463
|
+
title: issue.title,
|
|
464
|
+
body: issue.body,
|
|
465
|
+
url: issue.url,
|
|
466
|
+
state: 'OPEN',
|
|
467
|
+
labels: issue.labels.map((label) => label.name).sort(),
|
|
468
|
+
comments: comments.map((comment) => ({ body: comment.body, authorAssociation: comment.authorAssociation })),
|
|
469
|
+
};
|
|
470
|
+
},
|
|
471
|
+
setLabels: async (issueNumber, labels) => {
|
|
472
|
+
const current = await input.issues.getLabels(issueNumber);
|
|
473
|
+
await input.issues.updateIssue(issueNumber, {
|
|
474
|
+
addLabels: labels.filter((label) => !current.includes(label)),
|
|
475
|
+
removeLabels: current.filter((label) => !labels.includes(label)),
|
|
476
|
+
});
|
|
477
|
+
},
|
|
478
|
+
postComment: (issueNumber, body) => input.issues.postComment(issueNumber, body),
|
|
479
|
+
},
|
|
480
|
+
pullRequests: {
|
|
481
|
+
findOpen: async ({ headBranch, baseBranch }) => {
|
|
482
|
+
const matches = (await input.pullRequests.listAllByHeadBranch(headBranch))
|
|
483
|
+
.filter((pullRequest) => pullRequest.state === 'OPEN' && pullRequest.baseRefName === baseBranch);
|
|
484
|
+
if (matches.length > 1)
|
|
485
|
+
throw new Error('multiple open pull requests match publication intent');
|
|
486
|
+
const match = matches[0];
|
|
487
|
+
return match ? { url: match.url, body: match.body } : undefined;
|
|
488
|
+
},
|
|
489
|
+
createDraft: async ({ title, body, headBranch, baseBranch }) => input.pullRequests.createDraftPullRequest({ title, body, headBranch, baseBranch }),
|
|
490
|
+
},
|
|
491
|
+
git,
|
|
492
|
+
implementationAgent,
|
|
493
|
+
checks: {
|
|
494
|
+
run: async ({ command, cwd, signal }) => runShellCheck(command, cwd, signal),
|
|
495
|
+
},
|
|
496
|
+
proof,
|
|
497
|
+
checkedChangeMint: capabilities,
|
|
498
|
+
runRecords: records,
|
|
499
|
+
writeEvidence: async ({ runId, code, summary }) => {
|
|
500
|
+
const config = requireConfig(currentConfig);
|
|
501
|
+
const relativePath = `${config.runner.stateDir}/v2/evidence/${runId}.json`;
|
|
502
|
+
await writeDurableAtomicFile(resolve(targetRoot, relativePath), `${canonicalJson({ version: 1, runId, code, summary, recordedAt: now() })}\n`);
|
|
503
|
+
return { id: `evidence:${runId}:${code}`, path: relativePath };
|
|
504
|
+
},
|
|
505
|
+
packageVersion: input.packageVersion,
|
|
506
|
+
skillHashes: structuredClone(input.skillHashes),
|
|
507
|
+
createRunId: input.createRunId ?? randomUUID,
|
|
508
|
+
createProofId: input.createProofId ?? randomUUID,
|
|
509
|
+
now,
|
|
510
|
+
signal: controller.signal,
|
|
511
|
+
});
|
|
512
|
+
const onSignal = () => controller.abort();
|
|
513
|
+
process.on('SIGINT', onSignal);
|
|
514
|
+
process.on('SIGTERM', onSignal);
|
|
515
|
+
return {
|
|
516
|
+
runIssue: (runInput) => runner.runIssue(runInput),
|
|
517
|
+
abort: () => controller.abort(),
|
|
518
|
+
dispose: () => {
|
|
519
|
+
process.off('SIGINT', onSignal);
|
|
520
|
+
process.off('SIGTERM', onSignal);
|
|
521
|
+
},
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
async function acquireOwnerLock(input) {
|
|
525
|
+
const token = randomUUID();
|
|
526
|
+
const host = hostname();
|
|
527
|
+
const record = {
|
|
528
|
+
version: 1,
|
|
529
|
+
token,
|
|
530
|
+
canonicalRepository: input.canonicalRepository,
|
|
531
|
+
host,
|
|
532
|
+
bootId: input.bootId,
|
|
533
|
+
pid: process.pid,
|
|
534
|
+
acquiredAt: input.now(),
|
|
535
|
+
};
|
|
536
|
+
const repoKey = sha256(input.canonicalRepository);
|
|
537
|
+
try {
|
|
538
|
+
return await acquireExclusiveJsonFileLock({
|
|
539
|
+
path: join(input.orchestratorHome, 'v2', 'owners', `${repoKey}.lock`),
|
|
540
|
+
record,
|
|
541
|
+
token,
|
|
542
|
+
parse: parseOwnerLock,
|
|
543
|
+
tokenOf: (value) => value.token,
|
|
544
|
+
classifyExisting: (value) => value.host === host && value.bootId === input.bootId && input.processAlive(value.pid) ? 'wait' : 'block',
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
catch (error) {
|
|
548
|
+
if (error instanceof Error && /lock (?:owner|record|wait)/u.test(error.message))
|
|
549
|
+
throw new OwnerLockSafetyError(error.message);
|
|
550
|
+
throw error;
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
function parseOwnerLock(value) {
|
|
554
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
555
|
+
throw new Error('owner lock is invalid');
|
|
556
|
+
const keys = Object.keys(value).sort();
|
|
557
|
+
const expected = ['version', 'token', 'canonicalRepository', 'host', 'bootId', 'pid', 'acquiredAt'].sort();
|
|
558
|
+
if (keys.length !== expected.length || keys.some((key, index) => key !== expected[index]))
|
|
559
|
+
throw new Error('owner lock keys are invalid');
|
|
560
|
+
const record = value;
|
|
561
|
+
if (record.version !== 1 || !record.token || !record.canonicalRepository || !record.host || !record.bootId
|
|
562
|
+
|| !Number.isSafeInteger(record.pid) || record.pid <= 0 || Number.isNaN(Date.parse(record.acquiredAt))) {
|
|
563
|
+
throw new Error('owner lock fields are invalid');
|
|
564
|
+
}
|
|
565
|
+
return record;
|
|
566
|
+
}
|
|
567
|
+
async function readRegularFile(path) {
|
|
568
|
+
const handle = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW);
|
|
569
|
+
try {
|
|
570
|
+
const stat = await handle.stat();
|
|
571
|
+
if (!stat.isFile() || stat.size > 5 * 1024 * 1024)
|
|
572
|
+
throw new Error(`${path} is not a bounded regular file`);
|
|
573
|
+
return await handle.readFile();
|
|
574
|
+
}
|
|
575
|
+
finally {
|
|
576
|
+
await handle.close();
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
async function inspectRegularFile(path) {
|
|
580
|
+
const handle = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW);
|
|
581
|
+
try {
|
|
582
|
+
const metadata = await handle.stat();
|
|
583
|
+
if (!metadata.isFile() || metadata.size > 5 * 1024 * 1024)
|
|
584
|
+
throw new Error(`${path} is not a bounded regular file`);
|
|
585
|
+
return { modifiedAt: metadata.mtime.toISOString() };
|
|
586
|
+
}
|
|
587
|
+
finally {
|
|
588
|
+
await handle.close();
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
async function runShellCheck(command, cwd, signal) {
|
|
592
|
+
return new Promise((resolveCheck, rejectCheck) => {
|
|
593
|
+
const child = spawn('/bin/sh', ['-lc', command], { cwd, detached: true, stdio: ['ignore', 'pipe', 'pipe'] });
|
|
594
|
+
const chunks = [];
|
|
595
|
+
let retained = 0;
|
|
596
|
+
let settled = false;
|
|
597
|
+
let killTimer;
|
|
598
|
+
const collect = (chunk) => {
|
|
599
|
+
if (retained >= 1024 * 1024)
|
|
600
|
+
return;
|
|
601
|
+
const kept = chunk.subarray(0, 1024 * 1024 - retained);
|
|
602
|
+
chunks.push(kept);
|
|
603
|
+
retained += kept.length;
|
|
604
|
+
};
|
|
605
|
+
child.stdout.on('data', collect);
|
|
606
|
+
child.stderr.on('data', collect);
|
|
607
|
+
const terminate = () => {
|
|
608
|
+
if (!child.pid)
|
|
609
|
+
return;
|
|
610
|
+
try {
|
|
611
|
+
process.kill(-child.pid, 'SIGTERM');
|
|
612
|
+
}
|
|
613
|
+
catch { /* already absent */ }
|
|
614
|
+
killTimer = setTimeout(() => {
|
|
615
|
+
if (settled || !child.pid)
|
|
616
|
+
return;
|
|
617
|
+
try {
|
|
618
|
+
process.kill(-child.pid, 'SIGKILL');
|
|
619
|
+
}
|
|
620
|
+
catch { /* already absent */ }
|
|
621
|
+
}, 5_000);
|
|
622
|
+
killTimer.unref();
|
|
623
|
+
};
|
|
624
|
+
signal.addEventListener('abort', terminate, { once: true });
|
|
625
|
+
if (signal.aborted)
|
|
626
|
+
terminate();
|
|
627
|
+
child.once('error', (error) => {
|
|
628
|
+
settled = true;
|
|
629
|
+
signal.removeEventListener('abort', terminate);
|
|
630
|
+
if (killTimer)
|
|
631
|
+
clearTimeout(killTimer);
|
|
632
|
+
rejectCheck(error);
|
|
633
|
+
});
|
|
634
|
+
child.once('close', (code) => {
|
|
635
|
+
if (settled)
|
|
636
|
+
return;
|
|
637
|
+
settled = true;
|
|
638
|
+
signal.removeEventListener('abort', terminate);
|
|
639
|
+
if (killTimer)
|
|
640
|
+
clearTimeout(killTimer);
|
|
641
|
+
resolveCheck({ status: code === 0 ? 'passed' : 'failed', output: Buffer.concat(chunks) });
|
|
642
|
+
});
|
|
643
|
+
});
|
|
644
|
+
}
|
|
645
|
+
function requireConfig(config) {
|
|
646
|
+
if (!config)
|
|
647
|
+
throw new Error('runtime config is unavailable');
|
|
648
|
+
return config;
|
|
649
|
+
}
|
|
650
|
+
function requireRuntimeString(value, field) {
|
|
651
|
+
if (!value)
|
|
652
|
+
throw new Error(`${field} is required for contained Codex agents`);
|
|
653
|
+
return value;
|
|
654
|
+
}
|
|
655
|
+
function processIsAlive(pid) {
|
|
656
|
+
try {
|
|
657
|
+
process.kill(pid, 0);
|
|
658
|
+
return true;
|
|
659
|
+
}
|
|
660
|
+
catch (error) {
|
|
661
|
+
return typeof error === 'object' && error !== null && 'code' in error && error.code === 'EPERM';
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
export async function discoverIosTooling(executor, xcrunPath) {
|
|
665
|
+
const [runtimeResult, deviceTypeResult] = await Promise.all([
|
|
666
|
+
executor(xcrunPath, ['simctl', 'list', 'runtimes', '-j']),
|
|
667
|
+
executor(xcrunPath, ['simctl', 'list', 'devicetypes', '-j']),
|
|
668
|
+
]).catch(() => []);
|
|
669
|
+
if (!runtimeResult || !deviceTypeResult || runtimeResult.exitCode !== 0 || deviceTypeResult.exitCode !== 0)
|
|
670
|
+
return undefined;
|
|
671
|
+
try {
|
|
672
|
+
const runtimes = JSON.parse(runtimeResult.stdout).runtimes ?? [];
|
|
673
|
+
const deviceTypes = JSON.parse(deviceTypeResult.stdout).devicetypes ?? [];
|
|
674
|
+
const runtime = runtimes
|
|
675
|
+
.filter((item) => item.isAvailable !== false && typeof item.identifier === 'string'
|
|
676
|
+
&& item.identifier.startsWith('com.apple.CoreSimulator.SimRuntime.iOS-'))
|
|
677
|
+
.sort((left, right) => String(right.version ?? '').localeCompare(String(left.version ?? ''), undefined, { numeric: true }))[0];
|
|
678
|
+
const deviceType = deviceTypes
|
|
679
|
+
.filter((item) => typeof item.identifier === 'string' && item.identifier.startsWith('com.apple.CoreSimulator.SimDeviceType.iPhone-'))
|
|
680
|
+
.sort((left, right) => {
|
|
681
|
+
const leftPro = /Pro/u.test(String(left.name)) ? 0 : 1;
|
|
682
|
+
const rightPro = /Pro/u.test(String(right.name)) ? 0 : 1;
|
|
683
|
+
return leftPro - rightPro || String(right.name).localeCompare(String(left.name), undefined, { numeric: true });
|
|
684
|
+
})[0];
|
|
685
|
+
if (typeof runtime?.identifier !== 'string' || typeof deviceType?.identifier !== 'string')
|
|
686
|
+
return undefined;
|
|
687
|
+
return { runtimeId: runtime.identifier, deviceTypeId: deviceType.identifier };
|
|
688
|
+
}
|
|
689
|
+
catch {
|
|
690
|
+
return undefined;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
export async function releaseIosSimulator(executor, xcrunPath, record) {
|
|
694
|
+
if (!record.runnerCreated)
|
|
695
|
+
throw new Error('iOS release requires runner-created ownership');
|
|
696
|
+
const readDevices = async () => {
|
|
697
|
+
const result = await executor(xcrunPath, ['simctl', 'list', 'devices', '-j']);
|
|
698
|
+
if (result.exitCode !== 0)
|
|
699
|
+
throw new Error('iOS Simulator inventory failed during release');
|
|
700
|
+
const parsed = JSON.parse(result.stdout);
|
|
701
|
+
return Object.values(parsed.devices ?? {}).flat().filter((device) => device.isAvailable !== false);
|
|
702
|
+
};
|
|
703
|
+
const matches = (await readDevices()).filter((device) => device.udid === record.udid);
|
|
704
|
+
if (matches.length === 0)
|
|
705
|
+
return;
|
|
706
|
+
if (matches.length !== 1 || matches[0].name !== record.deviceName)
|
|
707
|
+
throw new Error('iOS release target identity is ambiguous');
|
|
708
|
+
if (matches[0].state === 'Booted') {
|
|
709
|
+
const shutdown = await executor(xcrunPath, ['simctl', 'shutdown', record.udid]);
|
|
710
|
+
if (shutdown.exitCode !== 0)
|
|
711
|
+
throw new Error('iOS runner-created Simulator shutdown failed');
|
|
712
|
+
}
|
|
713
|
+
const deleted = await executor(xcrunPath, ['simctl', 'delete', record.udid]);
|
|
714
|
+
if (deleted.exitCode !== 0)
|
|
715
|
+
throw new Error('iOS runner-created Simulator deletion failed');
|
|
716
|
+
if ((await readDevices()).some((device) => device.udid === record.udid)) {
|
|
717
|
+
throw new Error('iOS runner-created Simulator deletion was not confirmed');
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
async function prepareContainedAttempt(input) {
|
|
721
|
+
const runtimeRoot = join(resolve(input.orchestratorHome), 'v2', sha256(input.canonicalRepository));
|
|
722
|
+
const attemptRelativePath = `runs/${input.runId}/attempts/${input.attemptId}`;
|
|
723
|
+
const snapshot = await publishRuntimeAssetSnapshot({
|
|
724
|
+
packageRoot: resolve(input.packageRoot),
|
|
725
|
+
runtimeRoot,
|
|
726
|
+
snapshotRelativePath: `${attemptRelativePath}/snapshot`,
|
|
727
|
+
skill: input.skill,
|
|
728
|
+
});
|
|
729
|
+
if (snapshot.packageVersion !== input.expectedPackageVersion)
|
|
730
|
+
throw new Error('runtime asset package version mismatch');
|
|
731
|
+
const attemptRoot = join(runtimeRoot, attemptRelativePath);
|
|
732
|
+
const toolHome = join(attemptRoot, 'tool-home');
|
|
733
|
+
const tmpDir = join(attemptRoot, 'tmp');
|
|
734
|
+
await mkdir(toolHome, { recursive: false, mode: 0o700 }).catch((error) => {
|
|
735
|
+
if (!isErrorCode(error, 'EEXIST'))
|
|
736
|
+
throw error;
|
|
737
|
+
});
|
|
738
|
+
await mkdir(tmpDir, { recursive: false, mode: 0o700 }).catch((error) => {
|
|
739
|
+
if (!isErrorCode(error, 'EEXIST'))
|
|
740
|
+
throw error;
|
|
741
|
+
});
|
|
742
|
+
return {
|
|
743
|
+
skillPath: snapshot.skillPath,
|
|
744
|
+
schemaPath: snapshot.schemaPath,
|
|
745
|
+
reportPath: join(attemptRoot, 'report.json'),
|
|
746
|
+
toolHome,
|
|
747
|
+
tmpDir,
|
|
748
|
+
};
|
|
749
|
+
}
|
|
750
|
+
async function artifactInventory(root, logicalRoot) {
|
|
751
|
+
const output = new Map();
|
|
752
|
+
let rootStat;
|
|
753
|
+
try {
|
|
754
|
+
rootStat = await lstat(root);
|
|
755
|
+
}
|
|
756
|
+
catch (error) {
|
|
757
|
+
if (isErrorCode(error, 'ENOENT'))
|
|
758
|
+
return output;
|
|
759
|
+
throw error;
|
|
760
|
+
}
|
|
761
|
+
if (rootStat.isSymbolicLink() || !rootStat.isDirectory())
|
|
762
|
+
throw new Error('proof artifact root must be a direct directory');
|
|
763
|
+
const visit = async (directory, relative) => {
|
|
764
|
+
for (const entry of await readdir(directory, { withFileTypes: true })) {
|
|
765
|
+
const childRelative = relative ? `${relative}/${entry.name}` : entry.name;
|
|
766
|
+
const childPath = join(directory, entry.name);
|
|
767
|
+
if (entry.isSymbolicLink())
|
|
768
|
+
throw new Error('proof artifact tree contains a symlink');
|
|
769
|
+
if (entry.isDirectory())
|
|
770
|
+
await visit(childPath, childRelative);
|
|
771
|
+
else if (entry.isFile())
|
|
772
|
+
output.set(`${logicalRoot}/${childRelative}`, sha256(await readFile(childPath)));
|
|
773
|
+
else
|
|
774
|
+
throw new Error('proof artifact tree contains a special file');
|
|
775
|
+
}
|
|
776
|
+
};
|
|
777
|
+
await visit(root, '');
|
|
778
|
+
return output;
|
|
779
|
+
}
|
|
780
|
+
function changedArtifactPaths(before, after) {
|
|
781
|
+
return [...new Set([...before.keys(), ...after.keys()])]
|
|
782
|
+
.filter((path) => before.get(path) !== after.get(path))
|
|
783
|
+
.sort();
|
|
784
|
+
}
|
|
785
|
+
async function fingerprintRepositoryPath(root, relativePath) {
|
|
786
|
+
const segments = relativePath.split('/');
|
|
787
|
+
let current = root;
|
|
788
|
+
for (const [index, segment] of segments.entries()) {
|
|
789
|
+
current = join(current, segment);
|
|
790
|
+
const info = await lstat(current).catch((error) => {
|
|
791
|
+
if (isErrorCode(error, 'ENOENT') || isErrorCode(error, 'ENOTDIR'))
|
|
792
|
+
return undefined;
|
|
793
|
+
throw error;
|
|
794
|
+
});
|
|
795
|
+
if (!info)
|
|
796
|
+
return { kind: 'absent' };
|
|
797
|
+
if (info.isSymbolicLink()) {
|
|
798
|
+
return { kind: 'symlink', targetSha256: sha256(await readlink(current)), depth: index };
|
|
799
|
+
}
|
|
800
|
+
if (index < segments.length - 1 && !info.isDirectory())
|
|
801
|
+
return { kind: 'blocked-parent', depth: index };
|
|
802
|
+
if (index === segments.length - 1)
|
|
803
|
+
return fingerprintDeniedEntry(current, info);
|
|
804
|
+
}
|
|
805
|
+
return { kind: 'absent' };
|
|
806
|
+
}
|
|
807
|
+
async function fingerprintDeniedEntry(path, existingInfo) {
|
|
808
|
+
const info = existingInfo ?? await lstat(path);
|
|
809
|
+
if (info.isSymbolicLink())
|
|
810
|
+
return { kind: 'symlink', targetSha256: sha256(await readlink(path)) };
|
|
811
|
+
if (info.isFile())
|
|
812
|
+
return { kind: 'file', bytesSha256: sha256(await readFile(path)) };
|
|
813
|
+
if (!info.isDirectory())
|
|
814
|
+
return { kind: 'special' };
|
|
815
|
+
const entries = [];
|
|
816
|
+
for (const name of (await readdir(path)).sort()) {
|
|
817
|
+
entries.push({ nameSha256: sha256(name), fingerprint: await fingerprintDeniedEntry(join(path, name)) });
|
|
818
|
+
}
|
|
819
|
+
return { kind: 'directory', entries };
|
|
820
|
+
}
|
|
821
|
+
async function waitForProcessGroupAbsent(processGroupId) {
|
|
822
|
+
while (true) {
|
|
823
|
+
try {
|
|
824
|
+
process.kill(-processGroupId, 0);
|
|
825
|
+
}
|
|
826
|
+
catch (error) {
|
|
827
|
+
if (isErrorCode(error, 'ESRCH'))
|
|
828
|
+
return;
|
|
829
|
+
if (!isErrorCode(error, 'EPERM'))
|
|
830
|
+
throw error;
|
|
831
|
+
}
|
|
832
|
+
await new Promise((resolveWait) => setTimeout(resolveWait, 1_000));
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
function isErrorCode(error, code) {
|
|
836
|
+
return typeof error === 'object' && error !== null && 'code' in error && error.code === code;
|
|
837
|
+
}
|
|
838
|
+
function validateRelativeRoot(value) {
|
|
839
|
+
if (value.length === 0
|
|
840
|
+
|| value.startsWith('/')
|
|
841
|
+
|| value.includes('\\')
|
|
842
|
+
|| posix.normalize(value) !== value
|
|
843
|
+
|| value.split('/').some((segment) => segment === '' || segment === '.' || segment === '..')) {
|
|
844
|
+
throw new Error('ignored untracked root must be a normalized repository-relative path');
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
//# sourceMappingURL=runtime.js.map
|