@uchibeke/gallivant 0.2.1 → 0.3.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 (129) hide show
  1. package/README.md +38 -16
  2. package/SECURITY.md +9 -0
  3. package/bin/gallivant.mjs +33 -10
  4. package/bin/promote-bitbucket.mjs +40 -0
  5. package/bin/task-pr.mjs +9 -0
  6. package/bin/task-review.mjs +15 -0
  7. package/docs/README.md +2 -0
  8. package/docs/architecture.md +11 -3
  9. package/docs/bitbucket-promotion.md +69 -0
  10. package/docs/bitbucket-review.md +330 -0
  11. package/docs/chains.md +30 -1
  12. package/docs/codex-cloud.md +7 -0
  13. package/docs/codex-review.md +50 -0
  14. package/docs/commands.md +65 -5
  15. package/docs/config.md +35 -10
  16. package/docs/first-party-review.md +266 -0
  17. package/docs/git-hosts.md +294 -0
  18. package/docs/guardrails.md +56 -0
  19. package/docs/install.md +18 -8
  20. package/docs/network-recovery.md +9 -0
  21. package/docs/openai-agents.md +2 -1
  22. package/docs/prd.md +23 -2
  23. package/docs/preparation.md +1 -1
  24. package/docs/release-qualification.md +1 -1
  25. package/docs/releasing.md +17 -2
  26. package/docs/task-delivery.md +4 -4
  27. package/docs/task-profiles.md +537 -0
  28. package/docs/tasks.md +59 -197
  29. package/lib/attribution.mjs +7 -3
  30. package/lib/block.mjs +10 -1
  31. package/lib/chains.mjs +101 -30
  32. package/lib/codex_cloud.mjs +2 -1
  33. package/lib/codex_cloud_input.mjs +15 -6
  34. package/lib/codex_cloud_result.mjs +1 -1
  35. package/lib/commands/doctor.mjs +22 -462
  36. package/lib/commands/init.mjs +72 -30
  37. package/lib/commands/register.mjs +25 -11
  38. package/lib/commands/resume.mjs +5 -1
  39. package/lib/commands/review.mjs +66 -0
  40. package/lib/commands/serve.mjs +8 -0
  41. package/lib/commands/start.mjs +30 -11
  42. package/lib/commands/status.mjs +18 -2
  43. package/lib/commands/task.mjs +9 -1
  44. package/lib/commands/up.mjs +19 -11
  45. package/lib/commands/why.mjs +7 -3
  46. package/lib/config.mjs +42 -9
  47. package/lib/context.mjs +23 -18
  48. package/lib/control.mjs +21 -6
  49. package/lib/credential.mjs +20 -14
  50. package/lib/deliverable.mjs +2 -0
  51. package/lib/events.mjs +96 -53
  52. package/lib/execution.mjs +48 -3
  53. package/lib/execution_preparation.mjs +16 -1
  54. package/lib/execution_result.mjs +26 -5
  55. package/lib/first_party_review.mjs +618 -0
  56. package/lib/gh.mjs +144 -56
  57. package/lib/git.mjs +133 -32
  58. package/lib/git_diff.mjs +121 -0
  59. package/lib/harness.mjs +14 -10
  60. package/lib/host_contract.mjs +71 -0
  61. package/lib/host_definitions.mjs +22 -0
  62. package/lib/hosts/bitbucket.mjs +553 -0
  63. package/lib/hosts/bitbucket_contract.mjs +57 -0
  64. package/lib/hosts/bitbucket_credential.mjs +62 -0
  65. package/lib/hosts/bitbucket_review.mjs +44 -0
  66. package/lib/hosts/bitbucket_review_producer.mjs +50 -0
  67. package/lib/hosts/github.mjs +57 -0
  68. package/lib/hosts/github_contract.mjs +27 -0
  69. package/lib/hosts/github_doctor.mjs +482 -0
  70. package/lib/hosts/github_review_summary.mjs +38 -0
  71. package/lib/hosts/transport_doctor.mjs +35 -0
  72. package/lib/hosts.mjs +130 -0
  73. package/lib/learning_qualification.mjs +1 -1
  74. package/lib/notify.mjs +1 -1
  75. package/lib/openai_agents_input.mjs +7 -2
  76. package/lib/openai_agents_sources.mjs +16 -8
  77. package/lib/plugin_package.mjs +13 -1
  78. package/lib/pr_operation.mjs +41 -0
  79. package/lib/prd.mjs +18 -3
  80. package/lib/preparation_codex.mjs +6 -1
  81. package/lib/probe.mjs +6 -4
  82. package/lib/process.mjs +24 -0
  83. package/lib/promotion.mjs +132 -0
  84. package/lib/promotion_git.mjs +63 -0
  85. package/lib/prompt.mjs +16 -13
  86. package/lib/provider_health.mjs +14 -3
  87. package/lib/repository.mjs +68 -0
  88. package/lib/repository_preflight.mjs +11 -0
  89. package/lib/review_evaluation.mjs +25 -0
  90. package/lib/review_evidence.mjs +500 -0
  91. package/lib/review_history.mjs +73 -0
  92. package/lib/review_image.mjs +145 -0
  93. package/lib/review_link.mjs +12 -0
  94. package/lib/review_policy.mjs +132 -0
  95. package/lib/review_policy_contract.mjs +18 -0
  96. package/lib/review_state.mjs +13 -0
  97. package/lib/review_visual.mjs +94 -0
  98. package/lib/runtime-environment.mjs +6 -0
  99. package/lib/runtime_node.mjs +3 -2
  100. package/lib/runtime_state.mjs +39 -5
  101. package/lib/sources/prd.mjs +6 -3
  102. package/lib/state.mjs +137 -24
  103. package/lib/task_completion.mjs +7 -3
  104. package/lib/task_contract.mjs +201 -27
  105. package/lib/task_delivery.mjs +9 -2
  106. package/lib/task_delivery_contract.mjs +13 -9
  107. package/lib/task_delivery_view.mjs +18 -2
  108. package/lib/task_environment.mjs +13 -1
  109. package/lib/task_limits.mjs +13 -0
  110. package/lib/task_model_config.mjs +99 -0
  111. package/lib/task_model_route.mjs +243 -0
  112. package/lib/task_prepare.mjs +21 -8
  113. package/lib/task_profile.mjs +1875 -0
  114. package/lib/task_repository_context.mjs +65 -0
  115. package/lib/tasks.mjs +252 -51
  116. package/lib/tick.mjs +353 -97
  117. package/lib/time.mjs +1 -0
  118. package/lib/tracker/pages.mjs +19 -5
  119. package/lib/tracker/review.mjs +21 -0
  120. package/lib/tracker_process.mjs +8 -1
  121. package/lib/verification_sandbox.mjs +2 -1
  122. package/lib/work_artifacts.mjs +79 -0
  123. package/npm-shrinkwrap.json +12 -3
  124. package/package.json +9 -3
  125. package/templates/plugin/task-delivery.SKILL.md +17 -10
  126. package/templates/plugin/task-intake-contract.json +18 -0
  127. package/templates/plugin/task-profile-requests.mjs +1448 -0
  128. package/templates/tracker/tracker.css +3 -0
  129. package/templates/tracker/tracker.js +38 -0
@@ -0,0 +1,294 @@
1
+ # Git host boundary
2
+
3
+ For a GitHub review mirror that delivers through Bitbucket, see the [explicit branch promotion workflow](bitbucket-promotion.md). It preserves reviewed commits and uses the existing host/review services.
4
+
5
+ `github.com` supports task dispatch. Bitbucket's explicit no-reviewer path
6
+ completed live local Codex tasks through PR publication and receipt acceptance
7
+ on disposable public and private repositories, but its coding session could
8
+ read the selected merge-capable token file. General Bitbucket dispatch remains
9
+ unqualified while credential isolation is repaired. Independent Bitbucket
10
+ review and clean Linux installation also remain unvalidated. Other hosts remain
11
+ unsupported. The synthetic adapter in
12
+ `test/git-host.test.mjs` is an offline contract fixture, not a supported host.
13
+
14
+ `lib/host_definitions.mjs` owns the static host catalogue. `lib/hosts.mjs` binds
15
+ its declarations to Node transport implementations. Portable views and task
16
+ profiles read the same declarations without importing Node or credential code. It is independent of both the harness
17
+ registry and execution transports. Shared code obtains `hostApi(context)` and
18
+ selects a repository for dispatch through `context.hosts.select(...)`. Setup and
19
+ transport tools use `inspect(...)` or `inspectRemote(...)`; these do not qualify
20
+ the host for dispatch. The old `context.gh`
21
+ property is retained as an integration/test compatibility seam. New lifecycle
22
+ code must not use it. GitHub CLI commands, wire normalization, prompt commands,
23
+ learning endpoints and rulesets belong to `lib/gh.mjs`, `lib/hosts/github.mjs`
24
+ and the GitHub diagnostics feature module.
25
+
26
+ ## Identity and compatibility
27
+
28
+ `repository.mjs` parses HTTPS, HTTP (historical GitHub input, upgraded before use),
29
+ scp-style SSH and `ssh://` input. It rejects ambiguous authorities, ports,
30
+ queries, fragments, encoded path characters, traversal and unsupported schemes.
31
+ It never embeds rejected input in errors. HTTPS userinfo is discarded; it is
32
+ never a credential source. Canonical records contain `host`, `path`,
33
+ `remoteIdentity` (`host/owner/repository`) and `key`.
34
+
35
+ The historical GitHub key remains `owner/repository`; another qualified host's
36
+ key is `host/owner/repository`. Entry IDs, worktree paths and run folder names
37
+ include that key. Existing GitHub IDs, branch prefixes, cursors, receipt hashes,
38
+ PR metadata and chain ownership tokens are read without rewriting them.
39
+ Review/inline/comment IDs keep their old cursor keys, such as `review:42`.
40
+ A short handle still works when it identifies exactly one entry. Ambiguity
41
+ requires `host/owner/repository#number`. Contradictory saved identities and duplicate
42
+ PR ownership stop with a backup/reconciliation instruction; no automatic
43
+ migration, cursor reset or redispatch repairs them.
44
+
45
+ ## Adapter declaration
46
+
47
+ Each registry declaration supplies:
48
+
49
+ | Field | Contract |
50
+ | --- | --- |
51
+ | `host`, `id` | Canonical authority and stable completion-evidence adapter ID |
52
+ | `capabilities` | Required evidence and optional decoration, separately declared |
53
+ | `credential(config, repository)` | Resolve current API/HTTPS authorization for the bound host; never cache at daemon boot |
54
+ | `remote(repository)` | Verified clone URL, protocol, host and repository path |
55
+ | `create(options)` | Repository/API operations with injected transport and credentials |
56
+ | `parsePr(url)`, `prUrl(repository, number)` | Strict PR routing and canonical UI links |
57
+ | `prompts` | Host-specific create, inspect, CI-log and receipt-edit instructions |
58
+ | `dataContract` | `host-records-v1` |
59
+
60
+ Required capabilities are `pullRequests`, `reviews`, `comments`, `checks`,
61
+ `diff`, `mergeProof` and `recovery`. Missing required capabilities fail closed.
62
+ `labels` is optional: an adapter without labels does not block readiness.
63
+ GitHub retains its existing retry semantics for label writes. Learning and
64
+ ruleset operations are GitHub features, not mandatory adapter methods.
65
+
66
+ Repository operations cover branch/default-branch and permission reads, exact
67
+ ref/ancestry proof, file reads, PR view/list/diff, review/comment pages, comments,
68
+ body/title/recovery writes, ready-for-review and idempotent publication.
69
+ `fileAtStrict` distinguishes a missing file from inaccessible or incomplete
70
+ content. The shared chain engine requires the exact merge commit to be an
71
+ ancestor of the intended base; a closed PR never authorizes a successor.
72
+
73
+ First-party review additionally requires `reviewEvidence(repo, pr, head, base,
74
+ maxBytes)`: complete diff and before/after changed-file content, including
75
+ deletions, bound to exact head, base and merge-base IDs. Qualification and
76
+ reconciliation refuse adapters without this operation before launching a
77
+ first-party reviewer or reusing its clearance. External-only and explicit
78
+ no-reviewer policies do not require this method. Evidence reads and policy/dispute label writes
79
+ use the same repository registry and credential binding as other lifecycle
80
+ operations. Review jobs and verdicts remain coordinator-owned.
81
+
82
+ ## Domain records and completeness
83
+
84
+ Every normalized record carries `source` (host and adapter), `actor` (login and
85
+ bot flag), `eventId`, `headSha`, `createdAt` and `updatedAt`. Unknown optional
86
+ values are explicit nulls. Review/comment records also carry `at`, `reviewId`
87
+ and `replyTo`. Their original numeric `id` remains stable for saved cursors.
88
+ CI records expose `outcome: passed | failed | pending`, name, URL and optional
89
+ run ID. Wire-specific CI classification exists only in the adapter.
90
+
91
+ PRs retain the established domain field names (`headRefOid`, `headRefName`,
92
+ `baseRefName`, `state`, `mergeCommit`, `mergedAt`, `statusCheckRollup`, body,
93
+ author and URL). These are contract fields, not permission to import a host
94
+ client. The GitHub adapter keeps legacy event aliases for existing consumers;
95
+ the review engine accepts the canonical actor, head and timestamp fields too.
96
+
97
+ A list is either a complete array or `{ items, complete: true }`. Incomplete
98
+ pages, absent CI, rate limits, authentication failures and unreadable diffs
99
+ throw before a readiness decision. GitHub pagination uses bounded subprocess
100
+ output; PR list/check limits are refused at their cap. Shared retries preserve
101
+ cursors, dispatch ownership and the last known decision. Optional decorations
102
+ never supply review, CI or merge evidence. The shared loop has one reviewer
103
+ verdict and one CI outcome predicate for every qualified host.
104
+
105
+ ## Transport and provider binding
106
+
107
+ The shared Git layer clones with native `git clone --filter=blob:none`. The
108
+ GitHub policy converts accepted GitHub SSH/HTTP inputs to verified HTTPS; no
109
+ shared Git method constructs a GitHub URL. Existing fetch, base selection,
110
+ operator commit identity, isolated configuration and push behavior remain.
111
+ Origin and push destinations are checked against the repository identity before
112
+ credentialed network operations.
113
+
114
+ The HTTPS helper reads Git's requested protocol, host and repository path before
115
+ returning the bound token. It resets repository credential helpers, refuses
116
+ redirects and receives secrets only through environment variables. Clone URLs,
117
+ argv, committed files and public diagnostics contain no token. A run clears
118
+ inherited API tokens and SSH channels. Bitbucket supports an explicitly selected
119
+ SSH key for coordinator Git operations; an SSH key alone cannot authorize the PR
120
+ API. The coordinator may clone and push over selected SSH or HTTPS. The coding
121
+ session receives neither the repository API token nor the SSH key. Its bounded
122
+ checkout mailbox requests validated push and PR operations from the coordinator.
123
+ Coordinator Git disables checkout hooks before using a privileged credential.
124
+ Setup never grants a sandbox extra key paths.
125
+ GitHub resolution order remains configured token file, daemon environment,
126
+ then `gh auth token`, with explicit-file failure refusing fallback. Resolution
127
+ happens for each operation so reauthentication works without restarting.
128
+
129
+ Providers declare `repositoryAccess`: `local-worktree`, `snapshot`, or
130
+ `bound-host` with allowed authorities. The shared pre-dispatch check enforces it
131
+ before clone or paid preparation. A local-worktree provider needs no adapter
132
+ change to use another qualified host. No host-by-harness switch table exists.
133
+
134
+ ## Regression evidence
135
+
136
+ `test/git-host.test.mjs` exercises canonical identity, saved state, collisions,
137
+ normalized feedback, provider access, native clone, token isolation, failure
138
+ preservation and a synthetic host through readiness and chain merge proof.
139
+ `test/git-host-architecture.test.mjs` rejects direct host CLI/API imports or
140
+ prompt commands and a second host-specific review/CI branch in shared modules.
141
+ The existing review, recovery, receipt, chain and execution suites retain
142
+ coverage for bounded retries and idempotent writes. All these tests are offline
143
+ and make no model calls.
144
+
145
+
146
+ ## Bitbucket Cloud setup
147
+
148
+ Configure credentials explicitly in `git_hosts["bitbucket.org"]`. Existing
149
+ `github_token_file` resolution is unchanged and is never tried for Bitbucket.
150
+ No `gh` installation or GitHub sign-in is required for a Bitbucket-only config.
151
+ Use an Atlassian account API token; repository access tokens are not required.
152
+ Request `read:repository:bitbucket`, `write:repository:bitbucket`,
153
+ `read:pullrequest:bitbucket` and `write:pullrequest:bitbucket`, limited to the
154
+ selected workspace where available. Reads do not prove write scopes: diagnostics
155
+ report them as unknown until the corresponding write, which surfaces permission
156
+ errors and never silently switches credentials.
157
+
158
+ ```json
159
+ {
160
+ "git_hosts": {
161
+ "bitbucket.org": {
162
+ "api": {
163
+ "email": "operator@example.com",
164
+ "token_file": "~/.config/repository-access/bitbucket-api-token"
165
+ },
166
+ "git": { "transport": "https" }
167
+ }
168
+ },
169
+ "repos": [{ "repo": "bitbucket.org/workspace/repository", "base": "release/v2" }]
170
+ }
171
+ ```
172
+
173
+ Keep the existing harness, operator identity, worktrees and other config settings.
174
+ Token files must be private (`chmod 600`). HTTPS Git uses the selected API token
175
+ unless `git.token_file` explicitly selects a separate private token file. Git's
176
+ helper returns the token only for HTTPS on `bitbucket.org` and the exact repository;
177
+ it uses the account-token Git username `x-bitbucket-api-token-auth`. API requests
178
+ use account email plus token over HTTPS to `api.bitbucket.org`, with redirects
179
+ refused. API and Git authorization may differ, but the base commit observed through
180
+ Git must match the API repository and base.
181
+
182
+ For SSH, use this `git` block instead:
183
+
184
+ ```json
185
+ {
186
+ "transport": "ssh",
187
+ "ssh_key": "~/.config/repository-access/bitbucket-key",
188
+ "known_hosts": "~/.config/repository-access/bitbucket-known-hosts"
189
+ }
190
+ ```
191
+
192
+ Select an unencrypted dedicated key that the coordinator can read, with mode 600.
193
+ No SSH agent or global SSH configuration is used. The dedicated known-hosts file
194
+ must contain only `ssh.bitbucket.org` entries matching Atlassian's published
195
+ SHA256 fingerprints. Get candidate public keys from `https://bitbucket.org/site/ssh`,
196
+ select the `ssh.bitbucket.org` lines and independently check their fingerprints
197
+ against [Atlassian's SSH host-key documentation](https://support.atlassian.com/bitbucket-cloud/docs/configure-ssh-and-two-step-verification/).
198
+ Do not accept an unverified `ssh-keyscan` result. A host-key rotation stops access
199
+ until the published pins and selected file are reviewed. Strict verification is
200
+ always enabled. Existing `git@bitbucket.org:workspace/repo.git` origins and the
201
+ new `git@ssh.bitbucket.org:workspace/repo.git` origins resolve to one Cloud identity;
202
+ clones use the new endpoint described in [Atlassian's SSH migration notice](https://developer.atlassian.com/cloud/bitbucket/changelog/).
203
+ Self-hosted servers, custom SSH aliases and alternate ports are unsupported.
204
+
205
+ Run `init` from the checkout to bind the API repository UUID and workspace UUID
206
+ under the host's `repositories` map, or run `doctor` for read-only diagnostics.
207
+ Setup checks repository access, the selected base, effective account push role,
208
+ PR reads, comments when a PR exists, branch restrictions where visible, and native
209
+ Git access to the same base. The account role comes from the
210
+ [authenticated user's repository permissions](https://developer.atlassian.com/cloud/bitbucket/rest/api-group-repositories/#api-user-workspaces-workspace-permissions-repositories-get),
211
+ filtered by repository UUID, using repository read scope without workspace-admin access.
212
+ An archive flag, if supplied, is enforced; the Cloud
213
+ repository schema does not currently expose that flag consistently, so absence
214
+ is reported as unknown. A missing API credential reports missing PR/comment
215
+ capability even when an SSH key is configured. A successful transport check is
216
+ followed by an explicit failed dispatch check. No paid model probe is needed for
217
+ this milestone, and `init` does not recommend starting a task on an unqualified host.
218
+
219
+ API credentials are reread for every operation. A changed email, account UUID on
220
+ successive permission reads, repository UUID,
221
+ workspace UUID, canonical slug or API clone target stops access. Restore the
222
+ previous binding, or inspect the new identity and explicitly edit the binding;
223
+ setup never silently migrates a renamed or transferred repository.
224
+
225
+ ## Bitbucket evidence and publication bounds
226
+
227
+ `lib/hosts/bitbucket.mjs` owns API shape and pagination differences. PR snapshots
228
+ include source/destination UUIDs, branches and commits, draft state, host state
229
+ (`OPEN`, `MERGED`, `DECLINED` or `SUPERSEDED`), title/description, diff, comments,
230
+ reviewer participants, tasks and statuses tied to the current head. Declined and
231
+ superseded PRs normalize to `CLOSED`, preserving `hostState`. UUID-based actor
232
+ identity avoids nickname ambiguity. These observations do not qualify reviewer
233
+ trust, CI policy, recovery or merge proof for dispatch.
234
+ Build statuses use the [documented commit link](https://developer.atlassian.com/cloud/bitbucket/rest/api-group-commit-statuses/#api-repositories-workspace-repo-slug-commit-commit-statuses-get)
235
+ to confirm the queried repository and head; missing or mismatched links stop the snapshot.
236
+ PR list responses omit reviewer and participant collections. Bounded list results
237
+ are expanded through repository-scoped PR detail reads before normalization;
238
+ preflight also reads the selected PR's details before checking comment access.
239
+ Missing or inaccessible detail records stop the operation, and a failed read after
240
+ publication preserves the unresolved write until reconciliation succeeds.
241
+
242
+ Reads are bounded to 100 pages and 10,000 items per collection, 4 MiB per JSON
243
+ response, a diff smaller than 16 MiB, and 20 seconds per request. Missing fields,
244
+ cycles, changed filters, size inconsistencies, rate limits, foreign pagination,
245
+ redirects and changed PR identity/head during a snapshot produce explicit errors.
246
+ The documented diff redirect is allowed only into the same repository's diff
247
+ endpoint. Failures never become empty reviews or successful checks.
248
+
249
+ Publication uses the existing public-text validator, exact repository UUIDs and
250
+ source/base names. It checks PRs in all states before every publication, updates one matching open PR,
251
+ and refuses forks, closed predecessors, conflicting bases or duplicate ownership.
252
+ Writes address immutable workspace/repository UUIDs so a concurrent slug change
253
+ cannot redirect a write into a replacement repository. Every write is
254
+ followed by reconciliation, including timeouts after acceptance. An unresolved
255
+ create remains blocked in that adapter instance until a matching PR is observed;
256
+ a restart still reads before any write. Concurrent publication in one instance
257
+ is refused. There is no fork creation, merge, force push or repository-settings API.
258
+ Comments are never automatically retried after an uncertain write.
259
+
260
+ Offline coverage: `test/bitbucket.test.mjs`, `test/bitbucket-fixture.mjs` and
261
+ `test/host-transport-contract.test.mjs`. The shared contract assertions run against
262
+ both production adapters with injected wire responses. No fixture test calls a
263
+ model or writes to a live repository. Live review-loop qualification remains a
264
+ separate milestone.
265
+
266
+ API references: [repositories](https://developer.atlassian.com/cloud/bitbucket/rest/api-group-repositories/),
267
+ [pull requests](https://developer.atlassian.com/cloud/bitbucket/rest/api-group-pullrequests/),
268
+ and [account-token authentication](https://support.atlassian.com/bitbucket-cloud/docs/using-api-tokens/).
269
+
270
+ ## Review-loop implementation and ship gate
271
+
272
+ The [Bitbucket review guide](bitbucket-review.md) supersedes transport-only setup
273
+ examples for reviewer/trust/check policy. `init --host-config <json> --base <branch>`
274
+ can bootstrap an empty config, with an explicit reviewer (or `null`) and stable
275
+ trusted UUIDs. The adapter now implements review normalization, required task
276
+ blockers, recovery operations and merge ancestry. The explicit no-reviewer
277
+ dispatch path has [disposable live observations](audit/bitbucket-review-qualification.md),
278
+ but credential isolation failed; independent review and clean Linux installation
279
+ remain unvalidated. Do not enable general dispatch from these observations.
280
+
281
+ `prView` may include `feedback: { complete: true, headSha, reviews, inline, comments }`.
282
+ The shared loop consumes this one coherent snapshot; adapters without it retain
283
+ the previous collection methods. Strict records declare `headBinding: "exact"`
284
+ and an explicit `verdict`; PR-wide required tasks declare `required: true` and
285
+ `headBinding: "pull-request"`. Stable `sequence` values disambiguate verdicts that
286
+ share a timestamp. `strictIdentity` requests recorded branch/base/head and terminal
287
+ merge checks. These are domain contract fields, not host-name branches in the
288
+ scheduler. GitHub's historical event keys and review interpretation are retained.
289
+
290
+ A future GitLab adapter must implement the same complete records, explicit policy,
291
+ strict URL/credential binding, publication, file reads, and merge proof. Add its
292
+ static definition/implementation and shared-contract tests, then qualify it live
293
+ with a compatible provider. Until then GitLab and unregistered hosts fail before
294
+ dispatch. Host, harness and inference provider remain separate configuration axes.
@@ -309,3 +309,59 @@ that a tool call was denied. The historical findings are linked below.
309
309
  ## Follow-ups filed against APort
310
310
 
311
311
  The historical [decision record](https://github.com/uchibeke/gallivant/blob/main/docs/audit/DECISIONS.md) lists: multi-file `apply_patch` in the Codex hook, `git push` refspec parsing, control-plane paths blocked by default, a non-interactive local passport install, and a Repository Guard slice that blocks pushes rather than reporting merges.
312
+
313
+ ## Reviewer authority
314
+
315
+ The opt-in first-party reviewer uses the restricted native preparation boundary in a fresh session with supplied evidence only. Image jobs additionally require their own capability qualification and a verified coordinator-created copy. Its profile denies tools, escalation, delegation and tool network access; setup/start verify effective native policy and require a live qualification record. A private HOME or a prompt alone is not sufficient. The model cannot write task policy, state, files, Git refs, PRs or approvals. The coordinator validates exact-input structured output; public agent text is never an independent host actor. Unknown or partial output fails closed. See [review isolation, evidence and monetary limitations](first-party-review.md) and [unmet live qualification](audit/first-party-review.md). Review grants no merge or deployment authority.
316
+
317
+ Repository identity, credential transport and PR evidence are defined by the
318
+ [Git host contract](git-hosts.md). GitHub and Bitbucket Cloud can dispatch;
319
+ Bitbucket's live no-reviewer path has been qualified on a disposable public
320
+ repository. Independent Bitbucket review remains unvalidated. Existing IDs and
321
+ chain ownership are retained without a state migration.
322
+
323
+ ## Independent Bitbucket reviewer credentials
324
+
325
+ Coding sessions receive only their repository-bound coding credential. Reviewer
326
+ credentials belong on an isolated reviewer machine, OS account, or container.
327
+ The independent publisher accepts only the configured stable actor and prepared
328
+ exact head; a successful Pipeline without a posted verdict is silence.
329
+ See [reviewer isolation and publication](bitbucket-review.md#independent-local-codex-reviewer).
330
+ Setup never installs a pipeline, creates a token, or authorizes inference.
331
+
332
+ ## Keep working artifacts out of pull requests
333
+
334
+ Every local harness receives the same publication policy and generated `commit-msg` hook. The hook examines the
335
+ NUL-delimited staged file list and rejects task scratch directories, conventional work logs, audit/evidence notes,
336
+ and carried task inputs. Removing those files is allowed; preserve any carried files locally because the brief and
337
+ snapshot checks still need them. The hook is refreshed at start and on every resumed/fix run. Hosted file results
338
+ are checked before writing them, and the coordinator checks the complete remote PR diff before expensive first-party review and before readiness, even when the optional output-content scan is disabled. An unreadable or malformed diff is retried and
339
+ never treated as clean. A prohibited file schedules a normal corrective round with its exact path.
340
+
341
+ Requested audit reports, screenshots and other evidence are still valid deliverables. The operator names exact
342
+ paths in the approved brief's [`publish_files`](prd.md) list. The coordinator uses its saved snapshot, never a
343
+ session-edited whitelist. Before upgrading or restarting the daemon for existing runs, review retained deliverables in reserved directories.
344
+ The operator must name their exact paths in `publish_files` and accept the updated saved brief through the usual
345
+ `resume --resnapshot` flow at a safe resume boundary. Do not edit a running session's snapshot or grandfather all
346
+ existing files. Without those prior approved exceptions, the new guard will request cleanup instead of readiness.
347
+
348
+ Use a temporary directory outside the repository for scratch files. Runner command/session logs remain in task
349
+ storage; concise verification results belong in the PR receipt. Keep durable release/rollback instructions in the
350
+ project docs without appending a running execution diary. This policy does not inspect arbitrary prose or provide
351
+ an isolation boundary: an agent with Git credentials can bypass local hooks and push, but reserved work-artifact
352
+ paths will not pass the coordinator's readiness check. A clean check is cached only for its exact head, base and approved policy, so review polls do not repeatedly fetch
353
+ the diff. Normal rechecks also inspect legacy ready entries; no PR is automatically rewritten.
354
+
355
+ First-party reviewers receive carried text inputs from the coordinator's immutable `readSource` snapshots, with
356
+ content digests in their private evidence. They do not fetch those files from remote HEAD or the mutable session
357
+ checkout. These inputs follow the existing capture, per-job input and review-job caps; missing or oversized input
358
+ is reported explicitly, never silently omitted. Keep source context concise: it accompanies each source/visual
359
+ review piece and the final synthesis. The complete brief plus private source context and review metadata must fit the
360
+ configured per-job input cap (at most 100,000 serialized UTF-8 bytes). Larger private sources must be narrowed or
361
+ split into separately approved tasks; do not commit them as a workaround. Required image evidence remains in Git at its approved output paths.
362
+
363
+ `openai-agents` transports all approved inputs privately with their original hashes, but only explicit output overlays
364
+ are forced into a result. Verification permits private inputs to remain untracked or unstaged only while their bytes
365
+ and modes exactly match the coordinator snapshots. Editing, staging, deleting or substituting them fails publication.
366
+ Codex Cloud's Git-only input transport cannot provide this privacy for new/changed inputs and refuses before commit
367
+ or push; its dispatch is separately unavailable until repository binding is qualified. See [codex-cloud.md](codex-cloud.md).
package/docs/install.md CHANGED
@@ -49,10 +49,10 @@ cd /path/to/your/repository
49
49
  npx --yes @uchibeke/gallivant init --harness codex # or: --harness claude
50
50
  ```
51
51
 
52
- This setup flow requires **0.2.1 or newer**. On 2026-10-20, npm's `latest` was
53
- still 0.2.0: its `init` creates the config only, so repository registration and
54
- `doctor` must be done separately. A maintainer must [publish 0.2.1](releasing.md)
55
- before the command above provides the flow below; setup does not publish it.
52
+ This setup flow requires **0.2.1 or newer**. Check npm's current release with
53
+ `npm view @uchibeke/gallivant version`. Source changes on `main` reach this
54
+ command through a [versioned release](releasing.md); setup itself does not publish
55
+ a package.
56
56
 
57
57
  `npx` downloads the published `@uchibeke/gallivant` package into npm's cache and
58
58
  runs its `gallivant` command. Nothing is installed globally, no `gallivant`
@@ -302,7 +302,7 @@ bypassed. See [guardrails.md](guardrails.md#codex-git-writes-need-automatic-appr
302
302
  ## 9. First task
303
303
 
304
304
  Before dispatch, confirm the repository, target branch, permitted changes and
305
- spending limits. The default `max_iterations` is 30 automatic fix rounds;
305
+ spending limits. The default `max_iterations` is 60 automatic fix rounds;
306
306
  `max_budget_usd` defaults to 5 and gives Claude a native per-run dollar cap.
307
307
  Other local harnesses do not enforce an equivalent dollar cap. Use your provider's
308
308
  spend controls and review [budget semantics](config.md) before unattended work.
@@ -331,9 +331,9 @@ gallivant task start TASK_ID --revision REVISION --run
331
331
  gallivant start
332
332
  ```
333
333
 
334
- Alternatively, add `--run` to the original `task` request to authorize
335
- implementation as soon as preparation and any clarifications succeed. The task
336
- service starts the daemon; `gallivant start` with no path also opens the dashboard.
334
+ Preparation always returns for review, including when the original request
335
+ contains `--run`. Approve the visible ready revision with the separate start
336
+ command above. The task service starts the daemon; `gallivant start` with no path also opens the dashboard.
337
337
  Read [task operations](tasks.md) for selected context, revisions, recovery and costs.
338
338
 
339
339
  ### From a written brief
@@ -396,3 +396,13 @@ Watch `gallivant status` after the start run ends: the entry moves from `impleme
396
396
  | `<worktrees>/<repo>/<prd>` | one partial clone per PRD; durable until you delete it |
397
397
 
398
398
  Override the home directory with `GALLIVANT_HOME` to run a second instance.
399
+
400
+ ## Bitbucket-only first run
401
+
402
+ Bitbucket setup uses Node, Git, a selected local harness, an account API token,
403
+ and explicit reviewer or no-reviewer policy. It does not require `gh` sign-in.
404
+ Follow the [first-run commands](bitbucket-review.md#first-setup-including-a-checkout-with-no-existing-configuration),
405
+ including separate SSH and API credentials when using SSH Git. Setup checks
406
+ transport access; a live public repository run has reached ready with explicit
407
+ no-reviewer policy. Independent review and a clean Linux installation have not
408
+ been qualified. Check `gallivant doctor` before starting your own repository.
@@ -1,5 +1,14 @@
1
1
  # Network failures and recovery
2
2
 
3
+ The coordinator normally retains a successful local provider health check for
4
+ five minutes, so a long coordinator cycle does not immediately expire it. A due,
5
+ pending, failed or timed-out check still fences dispatch. An explicit
6
+ `execution.progressMs` setting controls this interval and remains authoritative.
7
+ Provider readiness refreshes on its own timer while a long coordinator cycle
8
+ is still processing. A pending or failed refresh continues to block dispatch.
9
+ Messages and resume requests remain queued while a readiness check is pending;
10
+ an actual failed check still reports failure for the operator to repair.
11
+
3
12
  `ENOTFOUND` means a hostname lookup failed. `EAI_AGAIN` indicates a temporary
4
13
  resolver failure. Neither proves that a provider is down, credentials expired,
5
14
  or APort denied a tool call. DNS can affect one hostname while other sites work.
@@ -85,7 +85,8 @@ entry, prepare and inspect a brief first, then follow the returned next action:
85
85
  ```sh
86
86
  gallivant task "Document the existing test commands in CONTRIBUTING.md. Change documentation only." \
87
87
  --harness openai-agents --verify 'git diff --check'
88
- # Add --run to authorize implementation once the brief passes readiness.
88
+ # Review the ready draft, then substitute its returned task ID and revision:
89
+ gallivant task start TASK_ID --revision REVISION --run
89
90
  ```
90
91
 
91
92
  Natural-language intake uses the selected provider's versioned preparation
package/docs/prd.md CHANGED
@@ -76,6 +76,27 @@ These keys beyond `status` and `harness` are read if present:
76
76
  editing a document it was handed, and the list is part of the contract: adding or removing a file stops the entry
77
77
  the way an edited criterion does. See [config.md](config.md#files-a-brief-carries-sources) for how it differs from
78
78
  `context_paths`.
79
+ - `publish_files` is an optional list of **exact output files** that would otherwise match the task-artifact policy:
80
+
81
+ ```yaml
82
+ publish_files:
83
+ - docs/audit/requested-security-report.md
84
+ - docs/evidence/export-dialog.png
85
+ ```
86
+
87
+ Use it only for reports, evidence or carried documents the operator explicitly wants in the PR. It does not list
88
+ ordinary implementation files or tests. No globs, directories, absolute paths or more than 100 entries are accepted.
89
+ The saved, approved brief supplies these exceptions; editing the session's copy cannot grant permission. Changing
90
+ the list changes the contract and uses the normal `prd-changed` repair/approval flow.
91
+
92
+ Task work logs, session transcripts, scratch files, audit chronology and review/handoff notes belong outside Git.
93
+ Create scratch space with `mktemp -d`; put concise verification results in the PR receipt. Keep lasting project
94
+ documentation and release/rollback instructions concise. The commit hook and final remote PR-diff check reject
95
+ conventional work-artifact paths (including `docs/audit/`, `docs/evidence/`, `docs/verification/`, `WORK_LOG.md`,
96
+ `NOTES.md`, and carried `sources`) unless listed here. Deletions remain allowed so an existing PR can be cleaned.
97
+ Required image evidence must remain committed at its explicitly approved paths; deleting it would invalidate review.
98
+ This is a path hygiene check, not a semantic content scanner: do not rename work logs to evade it.
99
+
79
100
  - `context_paths` gives this one brief read access to directories outside its checkout, added to whatever
80
101
  `config.json` already lists rather than replacing it. Comma-separated, or a `[a, b]` list:
81
102
 
@@ -128,7 +149,7 @@ file in your checkout are two files, and until this existed nothing compared the
128
149
  the run finished against criteria nobody was asking for and the PR arrived satisfying a document that had changed.
129
150
 
130
151
  So the two are compared, and what happens depends on what you changed. The comparison is in the contract's own terms:
131
- the acceptance criteria, Verify commands, `harness`, `context_paths`, `sources`,
152
+ the acceptance criteria, Verify commands, `harness`, `context_paths`, `sources`, `publish_files`,
132
153
  and the **Coordinator delivery contract** when present. The ownership section
133
154
  keeps a natural-language publication instruction separate from provider work.
134
155
  It is validated and fingerprinted too; malformed edits cannot be silently ignored.
@@ -138,7 +159,7 @@ request bytes remain exact.
138
159
  | What you changed | What happens |
139
160
  |---|---|
140
161
  | Anything outside those contract fields: the Problem prose, a reworded story, a new Out of scope bullet | Nothing stops. The snapshot follows your edit so later prompts carry your current wording, the log says it happened, and you are not told. Stopping a run to ask about a typo fix would be worse than useless. |
141
- | A criterion, a Verify command, the harness, `context_paths`, `sources` or coordinator delivery ownership | The entry stops with `prd-changed` before the gate runs, and `gallivant why` names each difference. |
162
+ | A criterion, a Verify command, the harness, `context_paths`, `sources`, `publish_files` or coordinator delivery ownership | The entry stops with `prd-changed` before the gate runs, and `gallivant why` names each difference. |
142
163
  | The ORDER of two criteria, without changing a word of either | Also `prd-changed`. Criteria are numbered by position, and the receipt on the open PR attests `ac-1` and `ac-2` by those numbers, so swapping two of them leaves the receipt attesting each criterion with the other's evidence. |
143
164
  | The file no longer passes the contract | `prd-illegal`. Fix the file and `gallivant ready` it again; it cannot become the brief the gate judges as it stands. |
144
165
  | The file is gone from your checkout | `prd-gone`. Restore it, or `gallivant remove` the entry. |
@@ -16,7 +16,7 @@ Preparation and implementation are separate capabilities:
16
16
  | Claude Code | Tools disabled | Local checkout |
17
17
  | Codex | Isolated native profile, Codex 0.160.0+ | Local checkout |
18
18
  | OpenAI Agents API | Text only, no tools or environment | Hosted sandbox |
19
- | Gemini CLI, OpenCode, Goose | Unavailable; use `new` → `ready` → `start` | Local checkout |
19
+ | Gemini CLI, OpenCode, Goose | Unavailable through the harness; the configured [model route](task-profiles.md#planner-routes) can draft, or use `new` → `ready` → `start` | Local checkout |
20
20
  | Codex Cloud | Unavailable | New dispatch blocked on environment/repository verification |
21
21
 
22
22
  An adapter's presence does not prove the configured account can use its selected
@@ -16,7 +16,7 @@ the accessible actual demo recording URL. Do not substitute generated images.
16
16
 
17
17
  ```sh
18
18
  npm run release:preflight -- --config "$PACKAGE_CONFIG" --setup "$SETUP_EVIDENCE"
19
- npm run release:package -- --config "$PACKAGE_CONFIG" --out "$RELEASE_DIR" --core-version 0.2.0 --source-commit "$SOURCE_COMMIT" --deployment "$DEPLOYMENT_RECORD" --evidence "$LIVE_EVIDENCE"
19
+ npm run release:package -- --config "$PACKAGE_CONFIG" --out "$RELEASE_DIR" --core-version 0.3.0 --source-commit "$SOURCE_COMMIT" --deployment "$DEPLOYMENT_RECORD" --evidence "$LIVE_EVIDENCE"
20
20
  npm run release:validate -- --out "$RELEASE_DIR"
21
21
  ```
22
22
 
package/docs/releasing.md CHANGED
@@ -81,10 +81,25 @@ GitHub release. Until then, use the documented CI bootstrap credential route.
81
81
 
82
82
  ## Release a version
83
83
 
84
+ Merging a PR to `main` does not bump the version, create a tag or publish a
85
+ package. There is no scheduled release or automatic version-bump PR. Prepare a
86
+ version-bump PR, wait for its checks, merge it, then trigger the workflow and
87
+ approve the protected `npm` environment. A newer source checkout with an already
88
+ published version cannot refresh that npm version: the tag and tarball guards
89
+ deliberately require the original commit and bytes.
90
+
84
91
  Update the version with `npm version patch --no-git-tag-version` (or `minor`),
85
92
  which updates `package.json` and `npm-shrinkwrap.json`. Include release notes in
86
93
  the PR and merge it after CI passes. Do not bump the version for a retry.
87
94
 
95
+ Update `CORE_VERSION` in `lib/task_delivery_contract.mjs` to the same version.
96
+ For a minor release, review and update its pre-1.0 compatibility window, the
97
+ handshake tests and the packaging examples in [task delivery](task-delivery.md)
98
+ and [release qualification](release-qualification.md). Other minor versions
99
+ require explicit migration; keep the exact artifact pin and wire-schema guards.
100
+ Run the full portability suite, including plugin packaging and release assembly,
101
+ before publishing: the npm install smoke alone does not exercise those builders.
102
+
88
103
  The workflow follows the guardrails repository's pattern: validate the release
89
104
  ref, test before publishing, and permit recovery without replacing published
90
105
  versions. This single-package project does not need its multi-registry dispatcher.
@@ -93,8 +108,8 @@ Choose one trigger:
93
108
 
94
109
  ```sh
95
110
  # From an up-to-date main checkout; replace the example with package.json's version.
96
- git tag -a v0.2.1 -m 'Release 0.2.1'
97
- git push origin v0.2.1
111
+ git tag -a v0.3.0 -m 'Release 0.3.0'
112
+ git push origin v0.3.0
98
113
 
99
114
  # Or dispatch against main; the workflow uses main's package version.
100
115
  gh workflow run release.yml --repo uchibeke/gallivant --ref main
@@ -19,7 +19,7 @@ runner.
19
19
 
20
20
  ## Installed exports
21
21
 
22
- Core `0.2.0`, task schema `1`, execution schema `1`, operation schema `1`.
22
+ Core `0.3.0`, task schema `1`, execution schema `1`, operation schema `1`.
23
23
  The candidate digest comes from the emitted `runtime.json`/`manifest.json`;
24
24
  pin the artifact produced from the eventual human-merged commit, not this branch.
25
25
 
@@ -218,7 +218,7 @@ Before wake-up, migrate/pin the exact runtime artifact. Supply the emitted
218
218
  The coordinator refuses a different active-job digest. Compatible patches keep
219
219
  task/provider/brief identities; drain jobs before staging a different artifact.
220
220
  No running code is silently upgraded. The public API's pre-1.0 compatibility
221
- window is `0.2.x`, with operation/task/execution wire schemas all `1`; other
221
+ window is `0.3.x`, with operation/task/execution wire schemas all `1`; other
222
222
  versions need migration.
223
223
 
224
224
  The portable contracts/views/wake envelope have no Node dependencies. The complete
@@ -267,9 +267,9 @@ changes and remain development fixtures:
267
267
  npm ci --ignore-scripts
268
268
  node bin/package-plugin.mjs --config /private/aport-package.json --validate-public
269
269
  npm run package:plugin -- --config /private/aport-package.json --out /private/candidate \
270
- --core-version 0.2.0 --source-commit <40-character-merged-commit>
270
+ --core-version 0.3.0 --source-commit <40-character-merged-commit>
271
271
  # For development only, add --internal; keep fixture:true in the config.
272
- npm install --ignore-scripts --prefix /private/candidate-runtime /private/candidate/uchibeke-gallivant-0.2.0.tgz
272
+ npm install --ignore-scripts --prefix /private/candidate-runtime /private/candidate/uchibeke-gallivant-0.3.0.tgz
273
273
  node /private/candidate-runtime/node_modules/@uchibeke/gallivant/bin/task-delivery-state.mjs check \
274
274
  --home /durable/preview --manifest /private/candidate/runtime.json
275
275
  node /private/previous-runtime/node_modules/@uchibeke/gallivant/bin/task-delivery-state.mjs backup \