@uchibeke/gallivant 0.0.0-stage → 0.2.0

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 (168) hide show
  1. package/CONTRIBUTING.md +26 -0
  2. package/LICENSE +204 -0
  3. package/README.md +201 -2
  4. package/SECURITY.md +19 -0
  5. package/bin/gallivant.mjs +257 -0
  6. package/bin/package-plugin.mjs +16 -0
  7. package/bin/release-live.mjs +29 -0
  8. package/bin/release-package.mjs +23 -0
  9. package/bin/session-runtime.mjs +13 -0
  10. package/bin/task-delivery-state.mjs +12 -0
  11. package/docs/README.md +70 -0
  12. package/docs/agent-setup.md +214 -0
  13. package/docs/app.md +111 -0
  14. package/docs/architecture.md +265 -0
  15. package/docs/chains.md +102 -0
  16. package/docs/codex-cloud.md +284 -0
  17. package/docs/commands.md +620 -0
  18. package/docs/config.md +430 -0
  19. package/docs/execution.md +796 -0
  20. package/docs/guardrails.md +311 -0
  21. package/docs/install.md +338 -0
  22. package/docs/launch.md +42 -0
  23. package/docs/learning.md +369 -0
  24. package/docs/network-recovery.md +101 -0
  25. package/docs/openai-agents.md +457 -0
  26. package/docs/prd.md +246 -0
  27. package/docs/preparation.md +110 -0
  28. package/docs/release-qualification.md +196 -0
  29. package/docs/releasing.md +140 -0
  30. package/docs/runtime-environment.md +113 -0
  31. package/docs/task-delivery.md +476 -0
  32. package/docs/tasks.md +739 -0
  33. package/lib/aport.mjs +95 -0
  34. package/lib/attribution.mjs +95 -0
  35. package/lib/block.mjs +89 -0
  36. package/lib/capabilities.mjs +3 -0
  37. package/lib/chains.mjs +222 -0
  38. package/lib/codex_cloud.mjs +160 -0
  39. package/lib/codex_cloud_config.mjs +20 -0
  40. package/lib/codex_cloud_input.mjs +49 -0
  41. package/lib/codex_cloud_result.mjs +74 -0
  42. package/lib/commands/doctor.mjs +457 -0
  43. package/lib/commands/init.mjs +34 -0
  44. package/lib/commands/learn.mjs +54 -0
  45. package/lib/commands/new.mjs +47 -0
  46. package/lib/commands/ready.mjs +45 -0
  47. package/lib/commands/register.mjs +195 -0
  48. package/lib/commands/resume.mjs +224 -0
  49. package/lib/commands/serve.mjs +349 -0
  50. package/lib/commands/start.mjs +247 -0
  51. package/lib/commands/start_services.mjs +22 -0
  52. package/lib/commands/status.mjs +150 -0
  53. package/lib/commands/task.mjs +73 -0
  54. package/lib/commands/up.mjs +228 -0
  55. package/lib/commands/why.mjs +143 -0
  56. package/lib/config.mjs +461 -0
  57. package/lib/context.mjs +100 -0
  58. package/lib/control.mjs +202 -0
  59. package/lib/control_contract.mjs +16 -0
  60. package/lib/coordinator.mjs +19 -0
  61. package/lib/credential.mjs +161 -0
  62. package/lib/daemon.mjs +156 -0
  63. package/lib/deliverable.mjs +357 -0
  64. package/lib/events.mjs +261 -0
  65. package/lib/executable.mjs +31 -0
  66. package/lib/execution.mjs +631 -0
  67. package/lib/execution_contract.mjs +15 -0
  68. package/lib/execution_input.mjs +4 -0
  69. package/lib/execution_io.mjs +94 -0
  70. package/lib/execution_journal.mjs +69 -0
  71. package/lib/execution_preparation.mjs +29 -0
  72. package/lib/execution_result.mjs +266 -0
  73. package/lib/fs.mjs +133 -0
  74. package/lib/gh.mjs +289 -0
  75. package/lib/git.mjs +434 -0
  76. package/lib/harness.mjs +521 -0
  77. package/lib/harness_log.mjs +432 -0
  78. package/lib/hash.mjs +16 -0
  79. package/lib/identity.mjs +98 -0
  80. package/lib/learning.mjs +654 -0
  81. package/lib/learning_contract.mjs +2 -0
  82. package/lib/learning_data.mjs +135 -0
  83. package/lib/learning_input.mjs +111 -0
  84. package/lib/learning_qualification.mjs +67 -0
  85. package/lib/learning_signer.mjs +151 -0
  86. package/lib/learning_store.mjs +88 -0
  87. package/lib/log.mjs +53 -0
  88. package/lib/network_diagnostics.mjs +64 -0
  89. package/lib/network_recovery.mjs +42 -0
  90. package/lib/notify.mjs +58 -0
  91. package/lib/openai_agents.mjs +373 -0
  92. package/lib/openai_agents_config.mjs +14 -0
  93. package/lib/openai_agents_http.mjs +87 -0
  94. package/lib/openai_agents_input.mjs +15 -0
  95. package/lib/openai_agents_sources.mjs +112 -0
  96. package/lib/owner_delivery.mjs +443 -0
  97. package/lib/plugin_package.mjs +340 -0
  98. package/lib/prd.mjs +635 -0
  99. package/lib/preparation_agents.mjs +33 -0
  100. package/lib/preparation_codex.mjs +212 -0
  101. package/lib/probe.mjs +126 -0
  102. package/lib/prompt.mjs +238 -0
  103. package/lib/provider_health.mjs +55 -0
  104. package/lib/public-format.mjs +31 -0
  105. package/lib/public_output.mjs +49 -0
  106. package/lib/release_package.mjs +154 -0
  107. package/lib/repository_files.mjs +86 -0
  108. package/lib/run.mjs +385 -0
  109. package/lib/run_log.mjs +94 -0
  110. package/lib/runtime-environment.mjs +87 -0
  111. package/lib/runtime_dependencies.mjs +15 -0
  112. package/lib/runtime_node.mjs +107 -0
  113. package/lib/runtime_state.mjs +174 -0
  114. package/lib/sources/index.mjs +27 -0
  115. package/lib/sources/prd.mjs +50 -0
  116. package/lib/start_contract.mjs +37 -0
  117. package/lib/state.mjs +246 -0
  118. package/lib/task_allowance.mjs +31 -0
  119. package/lib/task_completion.mjs +61 -0
  120. package/lib/task_contract.mjs +450 -0
  121. package/lib/task_delivery.mjs +219 -0
  122. package/lib/task_delivery_cancel.mjs +34 -0
  123. package/lib/task_delivery_contract.mjs +61 -0
  124. package/lib/task_delivery_mcp.mjs +40 -0
  125. package/lib/task_delivery_store.mjs +43 -0
  126. package/lib/task_delivery_view.mjs +88 -0
  127. package/lib/task_environment.mjs +281 -0
  128. package/lib/task_prepare.mjs +224 -0
  129. package/lib/task_store.mjs +38 -0
  130. package/lib/tasks.mjs +513 -0
  131. package/lib/tick.mjs +1635 -0
  132. package/lib/time.mjs +36 -0
  133. package/lib/tracker/assets.mjs +43 -0
  134. package/lib/tracker/pages.mjs +320 -0
  135. package/lib/tracker/runs.mjs +102 -0
  136. package/lib/tracker/stream.mjs +74 -0
  137. package/lib/tracker_process.mjs +107 -0
  138. package/lib/verification_sandbox.mjs +181 -0
  139. package/node_modules/smol-toml/LICENSE +24 -0
  140. package/node_modules/smol-toml/README.md +605 -0
  141. package/node_modules/smol-toml/dist/date.d.ts +41 -0
  142. package/node_modules/smol-toml/dist/date.js +156 -0
  143. package/node_modules/smol-toml/dist/error.d.ts +37 -0
  144. package/node_modules/smol-toml/dist/error.js +67 -0
  145. package/node_modules/smol-toml/dist/extract.js +289 -0
  146. package/node_modules/smol-toml/dist/index.cjs +770 -0
  147. package/node_modules/smol-toml/dist/index.d.ts +44 -0
  148. package/node_modules/smol-toml/dist/index.js +34 -0
  149. package/node_modules/smol-toml/dist/parse.d.ts +73 -0
  150. package/node_modules/smol-toml/dist/parse.js +164 -0
  151. package/node_modules/smol-toml/dist/primitive.js +151 -0
  152. package/node_modules/smol-toml/dist/stringify.d.ts +32 -0
  153. package/node_modules/smol-toml/dist/stringify.js +219 -0
  154. package/node_modules/smol-toml/dist/struct.js +156 -0
  155. package/node_modules/smol-toml/dist/util.d.ts +43 -0
  156. package/node_modules/smol-toml/dist/util.js +57 -0
  157. package/node_modules/smol-toml/package.json +68 -0
  158. package/npm-shrinkwrap.json +1823 -0
  159. package/package.json +105 -4
  160. package/templates/claude-settings.json +18 -0
  161. package/templates/passport.gallivant.json +83 -0
  162. package/templates/plugin/bundled-runtime.json +26 -0
  163. package/templates/plugin/schemas/mcp.schema.json +120 -0
  164. package/templates/plugin/schemas/plugin.schema.json +65 -0
  165. package/templates/plugin/task-delivery.SKILL.md +60 -0
  166. package/templates/prd.md +32 -0
  167. package/templates/tracker/tracker.css +301 -0
  168. package/templates/tracker/tracker.js +721 -0
@@ -0,0 +1,457 @@
1
+ # Hosted task sessions through OpenAI Agents API
2
+
3
+ Use `openai-agents` to run repository tasks through the managed Codex Agents API
4
+ in an OpenAI-hosted sandbox. The adapter supports natural-language preparation
5
+ and implementation, including research or documentation delivered as repository
6
+ files. It is separate from local `codex` and the unavailable `codex-cloud`
7
+ adapter. Account eligibility and full live lifecycle qualification are distinct
8
+ from the implemented capability; see the evidence section below.
9
+
10
+ The coordinator still runs on your machine or an explicitly provisioned server;
11
+ it must stay awake and online to verify artifacts, publish and advance reviews.
12
+ This adapter is not a hosted Gallivant service. The
13
+ existing task service, coordinator, dispatch journal, PR writer and review rules
14
+ remain the owners of work. Node 22+, local Git/gh for publication, and Agents REST
15
+ beta `OpenAI-Beta: agents=v1` are required. No OpenAI SDK or local Codex binary is
16
+ used by this transport. The REST schema was checked against official documentation
17
+ on 2026-10-06; beta compatibility must be rechecked before upgrading.
18
+
19
+ Follow [installation](install.md#hosted-agents-api-instead-of-a-local-cli) for the
20
+ complete source/package setup and a hosted-only config. `init --harness` currently
21
+ sets up only the local `codex` or `claude` path. Add this explicit account to your
22
+ existing config's `harness` object:
23
+
24
+ ```json
25
+ {
26
+ "harness": {
27
+ "openai-agents": {
28
+ "account": "my-service-account",
29
+ "organization": "org-selected",
30
+ "project": "proj-selected",
31
+ "api_key_file": "/private/operator/agents-key",
32
+ "model": "YOUR_AUTHORIZED_MODEL",
33
+ "environment": "openai_hosted",
34
+ "container_size": "small",
35
+ "network": { "access": "disabled" },
36
+ "allowance": { "remainingUsd": 1, "reservedUsd": 0.2 }
37
+ }
38
+ }
39
+ }
40
+ ```
41
+
42
+ Retain your existing repository, credential, identity, reviewer, verification and
43
+ permission settings. Put the API key in a private file, or supply `OPENAI_API_KEY`
44
+ to the coordinator. It needs `api.agents.read`, `api.agents.write` and
45
+ `api.responses.write` in the selected organization/project. A ChatGPT subscription
46
+ is separate from API inference and hosted compute billing. The account probe
47
+ retrieves the exact model and lists sessions; this verifies read visibility, not
48
+ inference entitlement, sufficient credits or successful hosted setup. Actual
49
+ session/environment/turn results are the evidence for those capabilities.
50
+
51
+ Select the authorized model explicitly; there is no remote model fallback. The
52
+ container size is explicit. If dependencies need outbound access, use
53
+ `network.access: restricted` with 1–100 exact `allowed_domains`. An optional
54
+ `environment_template_id` selects a preconfigured template, whose existence is
55
+ checked. Templates save configuration, not a previous filesystem. Python 3 and
56
+ Git must be present for the portable snapshot helper; a failed setup command
57
+ prevents implementation from starting. API and GitHub credentials remain outside
58
+ the sandbox; the adapter sends no service credentials or inherited environment.
59
+ The coordinator's existing scoped GitHub credential publishes the artifacts.
60
+ Optional `packages` contains explicit `system`, `python` and `npm` package arrays;
61
+ pin required versions and select the network domains their installation needs.
62
+
63
+ Local mandatory hooks, workspace-write/auto-review guarantees and private
64
+ read-only `context_paths` are not provided by hosted execution. Configuration or
65
+ dispatch refuses them explicitly. Select a backend that enforces required policy;
66
+ a completion receipt does not implement pre-action policy enforcement. Project
67
+ sources cannot contain private configuration paths, symlinks, submodules, special
68
+ files or portable path aliases. Refusal preserves the brief and start claim.
69
+
70
+ ## Task and command use
71
+
72
+ A ready PRD selects `harness: openai-agents`. Use the existing commands:
73
+
74
+ ```sh
75
+ gallivant doctor
76
+ gallivant start docs/prds/my-task.md --base main
77
+ gallivant status
78
+ gallivant why owner/repo/my-task
79
+ gallivant resume owner/repo/my-task --note 'Apply this authorized correction'
80
+ ```
81
+
82
+ `start` also ensures the daemon/dashboard and opens a browser. For plain-language
83
+ entry, prepare and inspect a brief first, then follow the returned next action:
84
+
85
+ ```sh
86
+ gallivant task "Document the existing test commands in CONTRIBUTING.md. Change documentation only." \
87
+ --harness openai-agents --verify 'git diff --check'
88
+ # Add --run to authorize implementation once the brief passes readiness.
89
+ ```
90
+
91
+ Natural-language intake uses the selected provider's versioned preparation
92
+ capability through the shared execution service for drafting, questions and
93
+ repairs. The task service owns deterministic validation/readiness and explicit
94
+ implementation authorization. Native preparation creates a fresh session with
95
+ `environment: {type: "none"}`, `tools: []` and `multi_agent.enabled: false`.
96
+ The API requires initial input for conversation-only sessions. The bounded
97
+ selected context is sent with those explicit restrictions in the same creation
98
+ request; the returned effective configuration is checked before adopting output.
99
+ Lost creation replies recover by task/account/dispatch metadata and never resend
100
+ the input. The live qualification caught this requirement on 2026-10-08; an empty
101
+ creation request returns HTTP 400 even though hosted coding sessions allow it.
102
+ Only the owned root's completed final answer can become a draft; tool calls,
103
+ delegated output and changed account/model settings are refused. It reuses the
104
+ normal durable execution receipts, cancellation, logs and lost-ack recovery.
105
+ Preparation does not need Git, a hosted filesystem or a local verification sandbox.
106
+ Implementation retains its existing hosted environment and sandbox requirements.
107
+ API/model access and live task qualification remain separate from this boundary's
108
+ authority. There is no automatic provider switch. A hand-authored approved PRD
109
+ still uses the explicit `ready`/`start` path above. No selection changes global
110
+ defaults. The same implementation task, branch, PR and
111
+ session are used for review fixes, stale heads, receipt repair and base reconciliation, within
112
+ the existing iteration limits. Each round sends the coordinator's current exact
113
+ input head and saved brief/source snapshots. The remote repository contains that
114
+ verified revision's files and modes, plus carried files, rather than Git history;
115
+ its sandbox-local initial commit is a snapshot commit. Publication always checks
116
+ the original input head on the coordinator.
117
+ Source snapshots accept Git SHA-1 and SHA-256 repositories: the exact HEAD must
118
+ contain 40 or 64 hexadecimal characters, and every tree blob uses that same
119
+ repository object-ID width. File-content hashes remain SHA-256 in both formats.
120
+ Hosted resume refuses ordinary modified, staged, deleted, renamed or untracked
121
+ files with `AGENTS_DIRTY_SOURCE` before merge, task reopening or paid dispatch.
122
+ Commit the intended unfinished edits on the owned task branch, then resume the
123
+ same session. Only the approved brief and declared carried-source overlays may
124
+ remain uncommitted; their bytes must match the accepted snapshots. Initial and
125
+ review dispatch use the same source check, and preparation rechecks both status
126
+ and HEAD before accepting the portable snapshot. No unfinished file is discarded
127
+ or silently uploaded.
128
+ The task CLI (`gallivant task 'Implement the approved request' --harness openai-agents`)
129
+ uses the managed preparation capability described above. [The shared intake
130
+ workflow](tasks.md) retains the selected provider for preparation, clarification
131
+ and repairs; a different selection requires an explicit operator choice. Local
132
+ Codex preparation uses its separately qualified native boundary. Neither path's
133
+ preparation evidence establishes hosted implementation or review-loop completion.
134
+
135
+ The shared execution boundary also exposes scoped question answers:
136
+
137
+ ```js
138
+ const execution = context.executionFor(taskId, "openai-agents");
139
+ await execution.respond({
140
+ operationId: "answer-unique-id", authorized: true,
141
+ sessionId: recordedSession, turnId: recordedRootTurn,
142
+ callId: currentAskOperatorCall, answer: "Use the approved value"
143
+ });
144
+ ```
145
+
146
+ Only the pending `ask_operator` function is supported. The caller must authorize
147
+ the answer and use the current task/session/turn/call identities. Arbitrary
148
+ function requests and browser approvals are refused. Answers use the documented
149
+ idempotency header and never create another implementation turn. After a timeout
150
+ or lost answer reply, explicitly repeat `execution.respond` with the identical
151
+ authorized input and operation ID. The adapter subscribes before retrieving the
152
+ owned session/root and resends the saved answer/key only while that exact
153
+ `ask_operator` call remains pending. If it is no longer pending, paginated root
154
+ items must contain the matching function call and successful, identical output
155
+ before acceptance is recorded; missing or conflicting proof stays ambiguous
156
+ without sending input. A saved acknowledgement survives stream cleanup or a
157
+ coordinator checkpoint failure. Changed answer bytes, arbitrary tools, foreign
158
+ roots/accounts and stopped sessions are refused. This follows the documented
159
+ [function recovery](https://developers.openai.com/api/docs/guides/agents-api/tools/functions)
160
+ and [submission retry](https://developers.openai.com/api/docs/guides/agents-api/sessions)
161
+ boundaries. This structured interface is available to existing clients;
162
+ there is no terminal question waiter or arbitrary shell executor.
163
+
164
+ ## Progress, recovery and controls
165
+
166
+ This adapter supports cancellation, but **not interruption**. A message or resume
167
+ request queued during active work waits for that execution to finish before the
168
+ coordinator continues the saved session. `--interrupt` is refused for this
169
+ provider. Cancellation fences further dispatch and requires remote confirmation;
170
+ it is not an interrupt-and-resume shortcut. The pending `ask_operator` response
171
+ interface described above is separate from queued correction messages.
172
+
173
+ Only the single coordinator performs provider I/O. Tracker/status reads saved
174
+ state. Existing `execution.deadlineMs`, `progressMs`, concurrency and capped
175
+ backoff apply (defaults: 20 seconds per operation, 10 seconds between polls,
176
+ maximum 5 minutes backoff). A stream connects before each send/reconciliation,
177
+ buffers while authoritative session/root-turn/items are read, and closes within
178
+ the bounded operation. Closing a stream never cancels work. Root turns alone
179
+ settle implementation; idle sessions and subagent events cannot report success.
180
+ Saved items restore output by item ID. Final text replaces partial text. Journals
181
+ label potentially lost intermediate deltas. Webhooks are not configured; periodic
182
+ polling performs recovery without depending on delivery notifications.
183
+
184
+ State lives in the existing `runs/<task>/execution.json`, `agents.json`, per-run
185
+ `events.jsonl`, `job.json`, `job.log`, `result.json` and `verification.json` layout.
186
+ Initial task ownership is registered before dispatch, so a launcher's lost reply
187
+ remains discoverable by the same coordinator after restart.
188
+ Session/environment/dispatch intent is flushed before sending input; turn IDs are
189
+ persisted before launch acknowledgement. Lost replies reconcile the saved key and
190
+ pre-send turn set; unknown acceptance never starts another paid implementation.
191
+ Creation without a recoverable root remains explicitly ambiguous and needs an
192
+ operator to inspect the saved session. Do not delete state to force a retry.
193
+
194
+ `Retry-After` accepts non-negative seconds or an HTTP date, with delays bounded
195
+ by the existing five-minute retry limit. Past dates and malformed headers use
196
+ normal exponential backoff; invalid transport delays cannot erase a saved retry
197
+ deadline. Restart preserves that deadline before another poll or cancellation
198
+ attempt. The supported header forms follow
199
+ [HTTP Semantics](https://www.rfc-editor.org/rfc/rfc9110.html#section-10.2.3).
200
+ Three consecutive reconciliation or unresolved launch attempts open a circuit;
201
+ creation recovered before any input send requires explicit inspection. Failed sessions stop
202
+ reconnecting. Repair credentials/throttling/configuration and explicitly authorize
203
+ `transport.resetRecovery` for a still-viable session. A saved authentication error
204
+ requires a fresh read-only check of the owned session and root turn with the
205
+ current credential before the retry block is cleared. If the session identity
206
+ is still unknown, the check uses the session listing needed for launch recovery.
207
+ It does not require model-catalog access or authorize new inference. A failed or
208
+ timed-out check preserves that block and
209
+ does not consume a reset receipt. Recovery then observes the same owned session
210
+ and root turn; it never resends input or creates a replacement. Replaying the
211
+ same successful reset cannot replenish its retry allowance. The operator control
212
+ reports recovery only after observing a known provider state; prior acceptance
213
+ alone cannot turn an unresolved observation into success. Ownership, policy,
214
+ protocol, cancellation and terminal refusals remain enforced. Failed or expired sessions
215
+ require saved artifact recovery and explicit replacement-session authorization;
216
+ automatic replacement is not supported, and no old filesystem survival is claimed.
217
+
218
+ The owned checkout is registered before source delivery or remote input preparation.
219
+ A source symlink/submodule, oversized snapshot, changed head or preparation failure
220
+ leaves a `needs-human` task with reason `launch-preparation`, its saved brief and
221
+ checkout intact, and a versioned `initial_dispatch` marked `unsubmitted`. Repair
222
+ the repository or prerequisites and run `gallivant resume <task-id>`; the tracker
223
+ Resume action uses the same transition. A proven first-dispatch refusal follows
224
+ this path with reason `dispatch-refused`. Resume rechecks full native/API readiness
225
+ and contract/source validation, restores missing approved inputs without replacing
226
+ unfinished edits, and submits the original operation from the current verified
227
+ revision and full approved brief. This is the first provider implementation, so no
228
+ prior session is claimed. Older initial refusals can use their private
229
+ `dispatchRefusals` proof. A stopped task, existing execution intent/run, foreign
230
+ operation or ambiguous acceptance cannot use this transition. After dispatch starts,
231
+ the marker is `dispatching`; only reconciliation may recover a lost reply, and an
232
+ accepted launch clears the marker. Ordinary later resumes retain the same session.
233
+
234
+ Cancellation sends `agent.session.input.cancel` only after confirming the owned
235
+ root is the session's single active root. HTTP acceptance is distinguished from
236
+ confirmed cancellation. Cancel, timeout and exhausted allowance fence future
237
+ paid dispatch; late artifacts remain quarantined. Session deletion is a separate
238
+ explicit transport operation and refuses before terminal state and saved results.
239
+ The adapter does not automatically delete sessions needed for review continuity.
240
+
241
+ Reservations are estimates and a local allowance fence, not enforceable provider
242
+ spend caps. Observed token usage is saved; USD cost is unknown until API and hosted
243
+ compute charges are reconciled. Unknown cost retains its reservation and is never
244
+ zero. No output-token or hard USD limit is invented for this beta interface.
245
+
246
+ ## Files and limits
247
+
248
+ The source snapshot contains immutable Git blobs with SHA-256 hashes and verified
249
+ carried documents. Expanded input is limited to 10 MiB; compressed inline input is
250
+ limited by the 5 MiB per-file limit and a conservative 3 MiB request limit. Larger
251
+ sources fail explicitly; this version does not silently truncate or upload to an
252
+ unscoped external store. Outputs are regular UTF-8 text changes, up to 100 files
253
+ and a 1 MiB manifest. Mode changes and binary output need a future documented
254
+ transport and are explicitly unsupported. Snapshot helper output and artifact
255
+ metadata are tested separately from provider-shaped REST fixtures.
256
+ Unchanged approved brief/carried files are included in the artifact manifest so
257
+ the PR writer commits those files from a fresh checkout. Later receipt-only rounds
258
+ deliver the same verified files and preserve the code head when no code changed.
259
+
260
+ The agent writes PR title/body and test records, then runs the supplied helper to
261
+ publish `/workspace/outputs/result.json`. Artifacts are selected by exact session,
262
+ environment, completed root turn and path. Paging uses `after` in ascending order:
263
+ 100 entries per page, at most 20 pages and 1 MiB response/history. Stream buffers
264
+ are bounded to 100 events/64 KiB. No truncated page or result authorizes publication.
265
+ The adapter verifies content/base hashes and safe paths, and the existing PR writer
266
+ rechecks branch ownership, base/head, aliases, modes and approved tests on the
267
+ actual applied revision before pushing. Agent-reported tests are retained as such;
268
+ coordinator-executed verification remains authoritative for PR publication.
269
+
270
+ Malformed JSON, unsafe/private paths, wrong source heads, hash mismatches and
271
+ portable aliases in a downloaded immutable artifact stop collection once. The
272
+ adapter saves its rejected bytes and hash in the private mode-0600
273
+ `<run>-rejected-artifact.json` cache, referenced by `agents.json`. These bytes are
274
+ untrusted inspection data; they never enter the checkout, public logs or PR writer.
275
+ The shared `result-application.json` checkpoint records
276
+ `result-collection-validation`, and the task enters `needs-human` with reason
277
+ `result-verification`. Provider root status, session, PR and observed/unknown cost
278
+ remain intact. Polling, restart and PR recheck cannot redownload or accept that
279
+ artifact. Inspect the checkpoint and private cache, then explicitly resume for a
280
+ corrected result in the same session. Rejected artifacts do not qualify session
281
+ deletion. Missing delivery, HTTP throttling/authentication, interrupted downloads
282
+ and local persistence failures remain unresolved and retryable after repair.
283
+
284
+ The coordinator executes every nonempty Verify list in an OS sandbox, including
285
+ scripts changed by hosted results and their child processes. Install a dedicated
286
+ Node 22+ runtime with npm and use macOS with `/usr/bin/sandbox-exec` plus
287
+ `/System/Library/Sandbox/Profiles/dyld-support.sb` and the installed Command Line
288
+ Tools used by `/usr/bin/git`, or Linux with `/usr/bin/bwrap`
289
+ and enabled unprivileged user/PID/network namespaces. System tools, the running
290
+ Node binary and its npm package are readable; only the checkout and a private
291
+ temporary profile are writable. For a custom Node prefix, Linux supplies the
292
+ normal `npm` entry point as a link to its read-only CLI module; it does not grant
293
+ the broader bin directory. Readiness opens the selected prefix's executable npm
294
+ launcher inside the boundary, so a missing or unreadable entry point fails before
295
+ hosted work. The native custom-prefix regression executes `npm test` through it.
296
+ Git Verify commands receive a separate read-only
297
+ `GIT_DIR` with the exact current commit, its tree/blob objects and a reconstructed
298
+ index. `git diff --check`, status and current-HEAD reads work in normal and linked
299
+ checkouts; coordinator Git config, hooks, remotes, reflogs, alternate stores and
300
+ ancestor history remain absent. The view is bounded to 10,000 objects/16 MiB and
301
+ 20 seconds, and removed with the temporary profile on every exit. Commands that
302
+ require other refs or history must use another approved check. Coordinator
303
+ journals, private host files and host network access remain inaccessible.
304
+ Arbitrary inherited PATH entries are removed; provision dependencies in the
305
+ checkout before Verify runs.
306
+ Network-dependent tests and unsupported tools fail rather than widen access.
307
+
308
+ Doctor's `openai-agents readiness` check exercises that native enforcement in
309
+ disposable directories, including actual Git reads and denied index writes
310
+ against a trusted empty commit before a checkout exists, before checking API
311
+ read access. Start refuses unsupported hosts before cloning or saving task
312
+ snapshots. Review dispatch and
313
+ manual resume recheck before recreating or merging the checkout, and the managed
314
+ transport checks again before sending a new implementation or correction.
315
+ If that final local check refuses before any provider request, the shared boundary
316
+ releases the unsubmitted intent and reservation, preserves the prior root/session
317
+ and records a bounded private `dispatchRefusals` entry. Start/review dispatch stops
318
+ with `dispatch-refused`; repair host/input prerequisites and explicitly resume,
319
+ or retry the identical authorized operation through the shared service. No new
320
+ session was launched by the refusal. Once a transport operation or provider
321
+ request exists, lost replies remain acceptance-unknown and cannot use this release.
322
+ Manual resume runs the full native/API readiness check before accepting an
323
+ edited brief or carried sources or reopening the entry. Expired credentials,
324
+ revoked project/model visibility and unsupported hosts leave those saved inputs
325
+ and task/session ownership unchanged. API read readiness still does not attest
326
+ to inference or hosted setup access.
327
+ Provider health and preparation records retain the native enforcement evidence;
328
+ they still label model inference and hosted setup as unverified until dispatch.
329
+ Repair the named OS/runtime requirement and explicitly resume the existing task.
330
+ Sandbox failure does not stop read-only progress, cancellation or saved artifact
331
+ recovery, and creates no automatic replacement session. Scratch profiles are
332
+ removed after successful, failed and aborted readiness checks.
333
+
334
+ A five-second native enforcement probe runs before any repository code. Failure
335
+ blocks publication once with `verification-sandbox-unavailable`; inspect
336
+ `result-application.json` and `verification.json`, repair the host sandbox/runtime,
337
+ and explicitly resume the same task. Saved artifacts and the applied code are
338
+ retained. Each command records sandbox provenance alongside its head, exit and
339
+ output. An interrupted verification or older `verified` checkpoint without that
340
+ provenance cannot push or silently replay commands. Already published results
341
+ remain read-only recovery records. See [the shared boundary](execution.md) for
342
+ runtime grants and cleanup. Native macOS enforcement tests are distinct from
343
+ provider-shaped fixtures; Linux namespace support requires the same native suite
344
+ on the selected Linux host. Neither is live Agents API qualification.
345
+
346
+ Immutable published artifacts survive sandbox expiry, but not session deletion.
347
+ Downloaded results are saved in `runs/<task>/<run>-artifacts.json` and the canonical
348
+ per-run result before settlement. Preserve that directory independently of log
349
+ retention. Restore it with the matching execution state/package version; artifact
350
+ collection does not require a surviving sandbox. Never delete a session before
351
+ saving its results. Sensitive raw logs and campaign ledgers stay outside Git.
352
+
353
+ ## Repeatable verification and live evidence
354
+
355
+ From the source checkout, offline verification makes no model calls:
356
+
357
+ ```sh
358
+ npm test
359
+ npm run lint
360
+ npm run test:execution-backends
361
+ npm run test:openai-agents
362
+ git diff --check
363
+ ```
364
+
365
+ The focused suite uses provider-shaped REST responses through the real adapter and
366
+ shared lifecycle boundary. It covers success/failure, root/subagent distinction,
367
+ required actions, reordered output, lost replies, paging, artifacts, expiry,
368
+ cancellation, account isolation, retry circuits, binary input and sandbox output.
369
+ Fixture evidence does not certify live access.
370
+
371
+ `npm run test:openai-agents:live` performs a nonpaid preflight and returns unverified
372
+ when prerequisites are absent. For paid G8 qualification, supply a private existing
373
+ configuration home, approved tiny disposable-repository PRD, explicit repository
374
+ allow-list and the shared private campaign ledger:
375
+
376
+ ```sh
377
+ export OPENAI_AGENTS_LIVE_HOME=/private/operator/test-home
378
+ export OPENAI_AGENTS_LIVE_PRD=/private/operator/disposable/docs/prds/tiny.md
379
+ export OPENAI_AGENTS_LIVE_REPO=authorized-owner/disposable-repo
380
+ export OPENAI_AGENTS_CAMPAIGN_LEDGER=/private/operator/campaign.json
381
+ npm run test:openai-agents:live
382
+ npm run test:openai-agents:live -- --execute --phase=implementation
383
+ # Reconcile observed API plus hosted-compute cost in the ledger before correction.
384
+ export OPENAI_AGENTS_LIVE_CORRECTION='The forced CI/review finding and approved fix'
385
+ npm run test:openai-agents:live -- --execute --phase=correction
386
+ ```
387
+
388
+ The ledger schema is `{version:1, limitUsd:10, remainingUsd, reservationUsd,
389
+ turnSeconds, pricing:{url,checkedAt}, attempts:[]}`. Reserve from the aggregate
390
+ campaign across milestones, use official pricing checked within 24 hours and a
391
+ positive deadline at most 120 seconds. Previous attempts must have observed USD
392
+ cost before another paid phase. Reservations and phase intents persist before
393
+ launch. This command does not buy credits, change models or repeat a dispatched
394
+ phase. A failed/unknown phase requires recovery of the saved task rather than a
395
+ new campaign launch. Stop the daemon for that private test home first: the campaign
396
+ claims the same daemon lock and uses the existing coordinator with its authenticated
397
+ GitHub login. Its settlement-only observation publishes the authorized run without
398
+ automatically dispatching another paid review or queued resume. Configure the approved brief and existing verification so
399
+ its tests establish a concrete file behavior; the correction should reproduce a
400
+ real failing CI assertion or trusted review finding. Correction refuses before
401
+ reserving or dispatching unless the existing review rules derive a real finding
402
+ on the current local/remote head; it records that finding with the phase evidence.
403
+ Each command reconstructs the
404
+ context; the campaign also recreates the coordinator while observing the turn.
405
+ `agents-live-evidence.json` records files/artifacts, tests, head, same PR/session,
406
+ turn/environment IDs, restart and observed usage. It remains unverified until both
407
+ phases pass. Installed plugin/browser qualification belongs to the later release
408
+ milestone; no plugin or browser surface is required for this REST adapter.
409
+
410
+ The 2026-10-06 implementation audit recorded missing live credentials/configuration;
411
+ that is historical evidence, not a diagnosis of your current account. The later
412
+ preparation-only live result described above does not qualify hosted implementation,
413
+ publication and review correction. Use the exact prerequisites above to record
414
+ those phases; fixture passes alone are not end-to-end qualification.
415
+
416
+ The original M5/M6 integration handoff points to
417
+ [`aporthq/agent-passport#417`](https://github.com/aporthq/agent-passport/pull/417),
418
+ merged on 2026-10-09. Its canonical brief is
419
+ `docs/prds/aport-task-delivery-workflow-integration.md` in that repository, with
420
+ job identity `aporthq/agent-passport/aport-task-delivery-workflow-integration`.
421
+ The handoff required pinning the portable artifact's version, commit, integrity
422
+ and exports and connecting APort authentication, regional storage and UI to the
423
+ shared task service/coordinator. A merged integration PR alone does not establish
424
+ installed-host qualification or a deployed public service. Preserve the existing
425
+ T0–T9 evidence and release gates; do not create a
426
+ second runner or another foundation job. Missing API and installed-host evidence
427
+ remain separate unmet gates.
428
+
429
+ Official contracts: [overview](https://developers.openai.com/api/docs/guides/agents-api/overview),
430
+ [quickstart and permissions](https://developers.openai.com/api/docs/guides/agents-api/quickstart),
431
+ [sessions and idempotency](https://developers.openai.com/api/docs/guides/agents-api/sessions),
432
+ [events/recovery](https://developers.openai.com/api/docs/guides/agents-api/sessions/events),
433
+ [hosted setup](https://developers.openai.com/api/docs/guides/agents-api/environments/openai-hosted),
434
+ [files and artifacts](https://developers.openai.com/api/docs/guides/agents-api/environments/files).
435
+
436
+ ### Privileged Linux verification hosts
437
+
438
+ The native verification probe remains mandatory before implementation or publication.
439
+ Rootless Linux uses Bubblewrap's user namespace. A root coordinator creates private
440
+ mount, PID, network, IPC and UTS namespaces directly, drops held and inheritable
441
+ capabilities, and uses no-new-privileges. The probe checks both the initial process
442
+ and a child after exec, in addition to denied filesystem access, read-only Git and
443
+ network isolation. There is no unsandboxed fallback. A nonzero capability bounding
444
+ set alone is not held authority; permitted/effective/inheritable/ambient sets must
445
+ all be zero and no-new-privileges must remain enabled.
446
+
447
+ Cloudflare preview rejected the nested-user-namespace `/proc` mount but passed the
448
+ private namespace variant. Both root and rootless variants also passed in the
449
+ actual Linux runtime image locally; removing capability dropping made the real
450
+ isolation regression fail. Run `GALLIVANT_NATIVE_SANDBOX_TEST=1 node --test
451
+ test/verification-linux.test.mjs` inside a namespace-capable Linux image. A Linux
452
+ container that cannot provide these boundaries must fail qualification. This is
453
+ not evidence of a completed remote task or a host-plugin installation.
454
+
455
+ The [Bubblewrap security model](https://github.com/containers/bubblewrap#sandbox-security)
456
+ and [Cloudflare container process boundary](https://developers.cloudflare.com/containers/api/durable-object-container/#exec)
457
+ explain why changing user IDs alone is insufficient.