@uchibeke/gallivant 0.2.0 → 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.
- package/README.md +120 -60
- package/SECURITY.md +9 -0
- package/bin/gallivant.mjs +41 -14
- package/bin/promote-bitbucket.mjs +40 -0
- package/bin/task-pr.mjs +9 -0
- package/bin/task-review.mjs +15 -0
- package/docs/README.md +6 -2
- package/docs/agent-setup.md +55 -41
- package/docs/architecture.md +11 -3
- package/docs/bitbucket-promotion.md +69 -0
- package/docs/bitbucket-review.md +330 -0
- package/docs/chains.md +30 -1
- package/docs/codex-cloud.md +7 -0
- package/docs/codex-review.md +50 -0
- package/docs/commands.md +103 -14
- package/docs/config.md +45 -13
- package/docs/execution.md +1 -1
- package/docs/first-party-review.md +266 -0
- package/docs/git-hosts.md +294 -0
- package/docs/guardrails.md +56 -0
- package/docs/install.md +137 -67
- package/docs/launch.md +7 -4
- package/docs/network-recovery.md +9 -0
- package/docs/openai-agents.md +3 -2
- package/docs/prd.md +23 -2
- package/docs/preparation.md +2 -2
- package/docs/release-qualification.md +1 -1
- package/docs/releasing.md +46 -22
- package/docs/task-delivery.md +5 -5
- package/docs/task-profiles.md +537 -0
- package/docs/tasks.md +59 -197
- package/lib/attribution.mjs +7 -3
- package/lib/block.mjs +10 -1
- package/lib/chains.mjs +101 -30
- package/lib/codex_cloud.mjs +2 -1
- package/lib/codex_cloud_input.mjs +15 -6
- package/lib/codex_cloud_result.mjs +1 -1
- package/lib/commands/doctor.mjs +22 -453
- package/lib/commands/init.mjs +281 -28
- package/lib/commands/register.mjs +81 -13
- package/lib/commands/resume.mjs +5 -1
- package/lib/commands/review.mjs +66 -0
- package/lib/commands/serve.mjs +8 -0
- package/lib/commands/start.mjs +30 -11
- package/lib/commands/status.mjs +18 -2
- package/lib/commands/task.mjs +9 -1
- package/lib/commands/up.mjs +19 -11
- package/lib/commands/why.mjs +7 -3
- package/lib/config.mjs +42 -9
- package/lib/context.mjs +28 -21
- package/lib/control.mjs +21 -6
- package/lib/credential.mjs +20 -14
- package/lib/deliverable.mjs +2 -0
- package/lib/events.mjs +96 -53
- package/lib/execution.mjs +132 -11
- package/lib/execution_preparation.mjs +16 -1
- package/lib/execution_result.mjs +26 -5
- package/lib/first_party_review.mjs +618 -0
- package/lib/fs.mjs +10 -3
- package/lib/gh.mjs +144 -56
- package/lib/git.mjs +133 -32
- package/lib/git_diff.mjs +121 -0
- package/lib/harness.mjs +14 -10
- package/lib/host_contract.mjs +71 -0
- package/lib/host_definitions.mjs +22 -0
- package/lib/hosts/bitbucket.mjs +553 -0
- package/lib/hosts/bitbucket_contract.mjs +57 -0
- package/lib/hosts/bitbucket_credential.mjs +62 -0
- package/lib/hosts/bitbucket_review.mjs +44 -0
- package/lib/hosts/bitbucket_review_producer.mjs +50 -0
- package/lib/hosts/github.mjs +57 -0
- package/lib/hosts/github_contract.mjs +27 -0
- package/lib/hosts/github_doctor.mjs +482 -0
- package/lib/hosts/github_review_summary.mjs +38 -0
- package/lib/hosts/transport_doctor.mjs +35 -0
- package/lib/hosts.mjs +130 -0
- package/lib/learning_qualification.mjs +1 -1
- package/lib/notify.mjs +1 -1
- package/lib/openai_agents_input.mjs +7 -2
- package/lib/openai_agents_sources.mjs +16 -8
- package/lib/plugin_package.mjs +13 -1
- package/lib/pr_operation.mjs +41 -0
- package/lib/prd.mjs +18 -3
- package/lib/preparation_codex.mjs +6 -1
- package/lib/probe.mjs +6 -4
- package/lib/process.mjs +24 -0
- package/lib/promotion.mjs +132 -0
- package/lib/promotion_git.mjs +63 -0
- package/lib/prompt.mjs +16 -13
- package/lib/provider_health.mjs +14 -3
- package/lib/repository.mjs +68 -0
- package/lib/repository_preflight.mjs +11 -0
- package/lib/review_evaluation.mjs +25 -0
- package/lib/review_evidence.mjs +500 -0
- package/lib/review_history.mjs +73 -0
- package/lib/review_image.mjs +145 -0
- package/lib/review_link.mjs +12 -0
- package/lib/review_policy.mjs +132 -0
- package/lib/review_policy_contract.mjs +18 -0
- package/lib/review_state.mjs +13 -0
- package/lib/review_visual.mjs +94 -0
- package/lib/runtime-environment.mjs +6 -0
- package/lib/runtime_node.mjs +3 -2
- package/lib/runtime_state.mjs +39 -5
- package/lib/sources/prd.mjs +6 -3
- package/lib/state.mjs +137 -24
- package/lib/task_completion.mjs +7 -3
- package/lib/task_contract.mjs +201 -27
- package/lib/task_delivery.mjs +9 -2
- package/lib/task_delivery_contract.mjs +13 -9
- package/lib/task_delivery_view.mjs +18 -2
- package/lib/task_environment.mjs +13 -1
- package/lib/task_limits.mjs +13 -0
- package/lib/task_model_config.mjs +99 -0
- package/lib/task_model_route.mjs +243 -0
- package/lib/task_prepare.mjs +21 -8
- package/lib/task_profile.mjs +1875 -0
- package/lib/task_repository_context.mjs +65 -0
- package/lib/tasks.mjs +252 -51
- package/lib/tick.mjs +373 -98
- package/lib/time.mjs +1 -0
- package/lib/tracker/pages.mjs +19 -5
- package/lib/tracker/review.mjs +21 -0
- package/lib/tracker_process.mjs +8 -1
- package/lib/verification_sandbox.mjs +2 -1
- package/lib/work_artifacts.mjs +79 -0
- package/npm-shrinkwrap.json +12 -3
- package/package.json +9 -3
- package/templates/plugin/task-delivery.SKILL.md +17 -10
- package/templates/plugin/task-intake-contract.json +18 -0
- package/templates/plugin/task-profile-requests.mjs +1448 -0
- package/templates/tracker/tracker.css +3 -0
- package/templates/tracker/tracker.js +38 -0
package/README.md
CHANGED
|
@@ -2,86 +2,105 @@
|
|
|
2
2
|
|
|
3
3
|
**Give an agent a task. Let the review loop run. Go outside.**
|
|
4
4
|
|
|
5
|
-
Gallivant turns repository
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
what gets merged.**
|
|
9
|
-
|
|
10
|
-
Use it for code, documentation, research or content that belongs in a GitHub
|
|
11
|
-
repository. Start with a plain-language request or a written brief.
|
|
5
|
+
Gallivant turns a repository task into a reviewed pull request. It runs a coding
|
|
6
|
+
agent in a separate checkout, opens the PR, watches CI and reviewer feedback, and
|
|
7
|
+
continues the same session until the PR is ready for you. You decide what merges.
|
|
12
8
|
|
|
13
9
|
```text
|
|
14
10
|
Your task → agent works → PR → review + CI → fixes → ready for you
|
|
15
11
|
↑___________|
|
|
16
12
|
```
|
|
17
13
|
|
|
18
|
-
##
|
|
19
|
-
|
|
20
|
-
You need **macOS or Linux, Node 22+, Git, GitHub CLI and jq**. For your first run,
|
|
21
|
-
use signed-in **Codex CLI 0.160.0+** or **Claude Code 2.1.263+**. Provider usage is
|
|
22
|
-
billed to your own account. [Full prerequisites](docs/install.md).
|
|
14
|
+
## Set up in one command
|
|
23
15
|
|
|
24
|
-
|
|
25
|
-
version is available, install it with `npm install -g @uchibeke/gallivant`. If the package
|
|
26
|
-
is not published yet, install from source:
|
|
16
|
+
Run this inside the Git checkout you want to work in:
|
|
27
17
|
|
|
28
18
|
```sh
|
|
29
|
-
|
|
30
|
-
cd gallivant
|
|
31
|
-
npm ci --ignore-scripts
|
|
32
|
-
npm link
|
|
33
|
-
gallivant --version
|
|
19
|
+
npx --yes @uchibeke/gallivant init --harness codex # or: --harness claude
|
|
34
20
|
```
|
|
35
21
|
|
|
36
|
-
|
|
22
|
+
The setup flow below requires **0.2.1 or newer**. `npx` runs npm's latest published
|
|
23
|
+
version. Changes merged on `main` become available through npm after a
|
|
24
|
+
[versioned release](docs/releasing.md); check the registry with
|
|
25
|
+
`npm view @uchibeke/gallivant version`.
|
|
37
26
|
|
|
38
|
-
|
|
27
|
+
`init` writes a private config at `~/.gallivant/config.json`, records this
|
|
28
|
+
repository, creates a separate directory for task checkouts, and ends with the
|
|
29
|
+
same report as `gallivant doctor`: one line per check and the exact fix for each
|
|
30
|
+
failing one. Run it again in another repository to add that repository; nothing
|
|
31
|
+
else in the config changes.
|
|
39
32
|
|
|
40
|
-
|
|
41
|
-
gh auth status
|
|
42
|
-
codex login status # use Claude sign-in if you choose Claude
|
|
43
|
-
gallivant init --harness codex # or --harness claude
|
|
44
|
-
gallivant doctor
|
|
45
|
-
```
|
|
33
|
+
Before you run it you need:
|
|
46
34
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
35
|
+
| Prerequisite | Check | If it fails |
|
|
36
|
+
| --- | --- | --- |
|
|
37
|
+
| macOS or Linux, Node 22+, Git, jq | `node --version`, `git --version`, `jq --version` | install from your package manager |
|
|
38
|
+
| GitHub CLI signed in | `gh auth status` | `gh auth login` |
|
|
39
|
+
| Codex CLI 0.160.0+ signed in | `codex login status` | `codex login` |
|
|
40
|
+
| or Claude Code 2.1.263+ signed in | `claude auth status` | `claude auth login` |
|
|
51
41
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
42
|
+
A signed-out `gh` or harness stops `init` before it writes anything, and the
|
|
43
|
+
message repeats the login command above. `init` never asks for passwords, tokens
|
|
44
|
+
or browser cookies; sign in with each tool's own flow. Inference is billed to
|
|
45
|
+
your own provider account.
|
|
55
46
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
configuration, verification and the points where your input is required.
|
|
47
|
+
`npx` downloads and runs the package on demand. Nothing is installed globally
|
|
48
|
+
and no `gallivant` command is added to your PATH. If you want one:
|
|
59
49
|
|
|
60
|
-
|
|
50
|
+
```sh
|
|
51
|
+
npm install -g @uchibeke/gallivant
|
|
52
|
+
```
|
|
61
53
|
|
|
62
|
-
|
|
63
|
-
|
|
54
|
+
The rest of this page writes `gallivant`. With `npx`, read that as
|
|
55
|
+
`npx --yes @uchibeke/gallivant`. Contributors who want to run from a source
|
|
56
|
+
checkout: see [installing from source](docs/install.md#install-from-source).
|
|
57
|
+
|
|
58
|
+
## Finish what setup cannot do for you
|
|
59
|
+
|
|
60
|
+
`doctor` names these. `init` does not do them, because each needs a decision
|
|
61
|
+
from you or an account with a third party.
|
|
62
|
+
|
|
63
|
+
- **Reviewer.** The default loop waits for the Codex GitHub review integration
|
|
64
|
+
(`chatgpt-codex-connector[bot]`). Enable it on the repository, configure
|
|
65
|
+
another reviewer, or opt into a [qualified first-party reviewer](docs/first-party-review.md).
|
|
66
|
+
Explicit legacy no-review needs both `"reviewer": null` and `review.legacy_no_review: true`. Without one of these, the first PR waits for a review
|
|
67
|
+
that never arrives. See [the reviewer key](docs/config.md#the-reviewer-object).
|
|
68
|
+
- **Branch protection.** `doctor` prints the `gh api` call that creates a
|
|
69
|
+
ruleset blocking direct and force pushes to the default branch. Run it
|
|
70
|
+
yourself. Setup never changes repository settings.
|
|
71
|
+
- **Harness guardrails.** The APort hook for Claude or Codex is installed by its
|
|
72
|
+
own `npx @aporthq/aport-agent-guardrails` command, and Codex asks you to trust
|
|
73
|
+
the hook inside its own interface. Setup does not install hooks.
|
|
74
|
+
[Guardrails](docs/guardrails.md) explains what each control covers.
|
|
75
|
+
- **Spend.** Defaults are 30 fix rounds per PR and a 5 USD per-run cap that
|
|
76
|
+
only Claude enforces natively. Review [limits](docs/config.md) before
|
|
77
|
+
unattended work.
|
|
78
|
+
|
|
79
|
+
## Run a first task
|
|
64
80
|
|
|
65
81
|
```sh
|
|
66
|
-
cd /path/to/your/repository
|
|
67
82
|
gallivant task "Document how to run the existing tests in CONTRIBUTING.md. Use the commands already defined in the repository. Change documentation only." \
|
|
68
|
-
--harness codex --verify 'git diff --check'
|
|
83
|
+
--harness codex --verify 'git diff --check'
|
|
84
|
+
# Review the draft, then substitute its returned task ID and revision:
|
|
85
|
+
gallivant task start TASK_ID --revision REVISION --run
|
|
69
86
|
gallivant start
|
|
70
87
|
```
|
|
71
88
|
|
|
72
|
-
`task`
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
89
|
+
`task` uses your harness to prepare a brief, which is a paid inference call,
|
|
90
|
+
and may ask you questions. Review the draft and answer any questions, then use
|
|
91
|
+
its printed `Next` action to approve that revision with `task start --run`.
|
|
92
|
+
Preparation always returns for review, even if its command includes `--run`.
|
|
93
|
+
The agent then works in a clone under `~/.gallivant-worktrees`,
|
|
94
|
+
pushes a branch, opens a PR against the default branch, and the daemon watches CI
|
|
95
|
+
and the reviewer, sending each round of feedback back to the same session.
|
|
96
|
+
`gallivant start` opens the dashboard at **http://127.0.0.1:8791** and keeps
|
|
97
|
+
the daemon running; closing the browser does not stop the work.
|
|
98
|
+
|
|
99
|
+
Expected outcome: a PR with a small CONTRIBUTING.md change and a completion
|
|
100
|
+
receipt in its body, and `gallivant status` showing the entry as **ready** once
|
|
101
|
+
checks, reviewer and the acceptance gate pass. You review and merge. Missing
|
|
102
|
+
access, failing checks or an exhausted round allowance produce an inspectable
|
|
103
|
+
stop instead; `gallivant why <handle>` explains it.
|
|
85
104
|
|
|
86
105
|
### Bring a written brief
|
|
87
106
|
|
|
@@ -96,6 +115,20 @@ gallivant start docs/prds/add-csv-export.md
|
|
|
96
115
|
You do not have to write a PRD yourself. Both entry points use a validated brief
|
|
97
116
|
and the same review loop. [Writing briefs](docs/prd.md) · [Task commands](docs/tasks.md).
|
|
98
117
|
|
|
118
|
+
## How the review loop runs
|
|
119
|
+
|
|
120
|
+
1. The agent implements the brief, runs the brief's verification commands and
|
|
121
|
+
opens the PR.
|
|
122
|
+
2. Each tick (every two minutes by default) the daemon reads CI and reviewer
|
|
123
|
+
state. A blocking review or a failing check starts a fix round in the same
|
|
124
|
+
agent session, and the fix is pushed to the same PR.
|
|
125
|
+
3. Rounds stop at `max_iterations` (60 by default), when the reviewer stays
|
|
126
|
+
silent for `stall_hours`, or when a run exceeds its timeout. Every stop is
|
|
127
|
+
recorded with a reason you can read with `gallivant why`.
|
|
128
|
+
4. **Ready** means the configured checks, reviewer and acceptance gate passed.
|
|
129
|
+
Nothing merges automatically. Natural-language tasks stop at a review
|
|
130
|
+
handoff by default; choose `integrated` to keep watching until you merge.
|
|
131
|
+
|
|
99
132
|
## While it works
|
|
100
133
|
|
|
101
134
|
| What you need | Action |
|
|
@@ -128,6 +161,9 @@ base. You can plan longer work while retaining the merge decision.
|
|
|
128
161
|
|
|
129
162
|
## Harness support
|
|
130
163
|
|
|
164
|
+
`init --harness` accepts `codex` and `claude`. Other adapters are configured by
|
|
165
|
+
hand in `config.json`; see [configuration](docs/config.md#execution-providers).
|
|
166
|
+
|
|
131
167
|
| Harness (`harness` key) | Runs on | Prepare requests | Implementation status |
|
|
132
168
|
| --- | --- | --- | --- |
|
|
133
169
|
| Claude Code (`claude`) | Your host | Yes | Recommended; live usage evidence |
|
|
@@ -177,7 +213,7 @@ for the installed version's flags.
|
|
|
177
213
|
daemon, including when execution is hosted. Gallivant is not a managed service.
|
|
178
214
|
- **Your accounts pay for inference.** Subscriptions and API credits differ.
|
|
179
215
|
There is no automatic provider fallback. Review [limits](docs/config.md) before
|
|
180
|
-
unattended work; the default review allowance is
|
|
216
|
+
unattended work; the default review allowance is 60 rounds.
|
|
181
217
|
- **Your permissions apply.** Scope GitHub access to the required repositories.
|
|
182
218
|
Harness permissions, OS sandboxing and optional APort checks are different
|
|
183
219
|
controls. [Security boundaries](docs/guardrails.md).
|
|
@@ -190,9 +226,25 @@ for the installed version's flags.
|
|
|
190
226
|
|
|
191
227
|
## Documentation
|
|
192
228
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
229
|
+
| Need | Guide |
|
|
230
|
+
| --- | --- |
|
|
231
|
+
| Install and run your first task | [Getting started](docs/install.md) |
|
|
232
|
+
| Start from a request, answer questions, inspect results | [Natural-language tasks](docs/tasks.md) |
|
|
233
|
+
| Select the typed delivery profile and planner route for a request | [Typed delivery profiles](docs/task-profiles.md) |
|
|
234
|
+
| Write a brief or define noncoding acceptance checks | [PRD contract](docs/prd.md) |
|
|
235
|
+
| Use API-backed hosted execution | [OpenAI Agents](docs/openai-agents.md) |
|
|
236
|
+
| Dashboard messages, controls and recovery | [Dashboard](docs/app.md) · [Commands](docs/commands.md) |
|
|
237
|
+
| Models, credentials, limits and notifications | [Configuration](docs/config.md) |
|
|
238
|
+
| Plan sequential work | [Chains](docs/chains.md) |
|
|
239
|
+
| Embed task delivery in another application | [Task-delivery package](docs/task-delivery.md) |
|
|
240
|
+
| Understand internals or recorded qualification | [Documentation index](docs/README.md) |
|
|
241
|
+
| Set up from an agent | [Agent setup](docs/agent-setup.md) |
|
|
242
|
+
| Release, contribute or report a vulnerability | [Releasing](docs/releasing.md) · [Contributing](CONTRIBUTING.md) · [Security](SECURITY.md) |
|
|
243
|
+
|
|
244
|
+
**Asking a coding agent to set this up?** Give it the
|
|
245
|
+
[setup-agent instructions](docs/agent-setup.md). They cover inspection, the
|
|
246
|
+
`npx` command, the points where your login or decision is required, and what a
|
|
247
|
+
setup run may not do on its own.
|
|
196
248
|
|
|
197
249
|
Embedding the same workflow in another application? See
|
|
198
250
|
[task delivery](docs/task-delivery.md). Installing this CLI does not deploy a
|
|
@@ -200,3 +252,11 @@ hosted service or publish a chat plugin.
|
|
|
200
252
|
|
|
201
253
|
[Contributing](CONTRIBUTING.md) · [Security reports](SECURITY.md) ·
|
|
202
254
|
[Releasing](docs/releasing.md) · [Apache-2.0 license](LICENSE)
|
|
255
|
+
|
|
256
|
+
## Bitbucket Cloud
|
|
257
|
+
|
|
258
|
+
Bitbucket Cloud tasks support the same independent local Codex review service as GitHub. The adapter captures an exact same-repository PR comparison through Bitbucket's commit, diffstat, merge-base and source APIs, then the shared service divides large evidence into bounded jobs. Activation still requires a successful live route qualification; until that and the disposable private/public review matrix pass, keep an existing run's explicit legacy no-review policy. A prior public disposable run qualified PR publication and receipt acceptance only, not semantic review. See the [setup, activation limits and troubleshooting guide](docs/bitbucket-review.md). Bitbucket-only setup needs no GitHub sign-in and does not install a pipeline or alter repository settings.
|
|
259
|
+
|
|
260
|
+
## First-party review (opt-in)
|
|
261
|
+
|
|
262
|
+
New tasks can pin `external-required`, `first-party-required`, or `both-required`. Repositories with the configured external reviewer retain their existing default. First-party review requires a separately qualified restricted route; it never claims Git-host bot approval. GitHub and Bitbucket Cloud are the only evidence adapters currently implemented. See [selection, qualification and migration](docs/first-party-review.md) and the [current live qualification gap](docs/audit/first-party-review.md). Existing no-review runs keep that requirement until the audited policy command changes them and disclose the absence of semantic review.
|
package/SECURITY.md
CHANGED
|
@@ -17,3 +17,12 @@ they need. Automatic approval is not equivalent to an operating-system sandbox.
|
|
|
17
17
|
The [OpenAI Agents API adapter](docs/openai-agents.md) keeps service credentials
|
|
18
18
|
on the coordinator and publishes returned artifacts through that coordinator.
|
|
19
19
|
Its hosted execution controls differ from local harness hooks and sandboxes.
|
|
20
|
+
|
|
21
|
+
## Bitbucket reviewer isolation
|
|
22
|
+
|
|
23
|
+
Use a separate reviewer account and keep its publication credential outside the
|
|
24
|
+
coding process's filesystem and environment access. A private file readable by
|
|
25
|
+
the coding identity does not provide isolation. The review model receives the
|
|
26
|
+
prepared diff and a read-only checkout; an operator publishes its exact-head
|
|
27
|
+
verdict. See [reviewer setup](docs/bitbucket-review.md#independent-local-codex-reviewer).
|
|
28
|
+
Bitbucket dispatch remains disabled pending live qualification.
|
package/bin/gallivant.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// CLI entry. Parses arguments, builds the context, calls one command. No logic lives here.
|
|
3
|
+
import { reviewCommand } from "../lib/commands/review.mjs";
|
|
3
4
|
import { acquireCliMutation } from "../lib/daemon.mjs";
|
|
4
5
|
import { parseArgs } from "node:util";
|
|
5
6
|
import { makeContext } from "../lib/context.mjs";
|
|
@@ -15,7 +16,7 @@ import { newPrd } from "../lib/commands/new.mjs";
|
|
|
15
16
|
import { resume } from "../lib/commands/resume.mjs";
|
|
16
17
|
import { startServices } from "../lib/commands/start_services.mjs";
|
|
17
18
|
import { trackerPort, stopTracker } from "../lib/tracker_process.mjs";
|
|
18
|
-
import { init } from "../lib/commands/init.mjs";
|
|
19
|
+
import { init, renderInit } from "../lib/commands/init.mjs";
|
|
19
20
|
import { VERSION } from "../lib/fs.mjs";
|
|
20
21
|
import { hasConfig } from "../lib/config.mjs";
|
|
21
22
|
import { resolveHandle } from "../lib/state.mjs";
|
|
@@ -28,8 +29,9 @@ import { safeDisplay } from "../lib/learning_data.mjs";
|
|
|
28
29
|
|
|
29
30
|
const HELP = `gallivant: give an agent a task, let the review loop run, go outside.
|
|
30
31
|
|
|
31
|
-
gallivant init [--harness codex|claude] [--worktrees <directory>]
|
|
32
|
-
|
|
32
|
+
gallivant init [--harness codex|claude] [--worktrees <directory>] [--host-config <json>] [--base <branch>]
|
|
33
|
+
set up the repository you are in: private config, this repo in repos,
|
|
34
|
+
then doctor's report. Safe to repeat; never signs in or overwrites settings
|
|
33
35
|
gallivant --version print the installed version
|
|
34
36
|
gallivant doctor [--send] [--probe] install checklist and health probe
|
|
35
37
|
gallivant doctor --network <https-origin> [--json] bounded DNS/HTTPS diagnosis
|
|
@@ -50,15 +52,18 @@ const HELP = `gallivant: give an agent a task, let the review loop run, go outsi
|
|
|
50
52
|
write a starting PRD into docs/prds/ of the repo you are in
|
|
51
53
|
gallivant task [prepare] "<request>" [--stdin] [--dir <checkout>] [--repo <owner/repo>]
|
|
52
54
|
[--base <branch>] [--harness <name>] [--context <file>] [--request-id <id>] [--run] [--json]
|
|
53
|
-
[--completion-target delivery_ready|integrated] [--
|
|
54
|
-
|
|
55
|
+
[--completion-target delivery_ready|integrated] [--delivery pull_request] [--route harness|model]
|
|
56
|
+
[--verify <command>] [--no-daemon]
|
|
57
|
+
prepare an isolated brief for review; approve later with task start --run
|
|
58
|
+
--delivery selects the typed delivery profile (the only delivery authority);
|
|
59
|
+
--route drafts through the connected harness or the operator's bounded model route
|
|
55
60
|
Claude, Codex and OpenAI Agents support isolated preparation.
|
|
56
61
|
Other local harnesses use written PRDs; Codex Cloud dispatch is unavailable
|
|
57
62
|
gallivant task answer <task-id> --revision <n> --request-id <answer-id> --answer <question-id=text>
|
|
58
63
|
resume saved questions; --answer, --context and --verify may repeat
|
|
59
64
|
gallivant task inspect <task-id> [--json] | task list [--json]
|
|
60
65
|
gallivant task resume|validate|start <task-id> --revision <n> [--run] [--no-daemon] [--json]
|
|
61
|
-
shared versioned operations; start
|
|
66
|
+
shared versioned operations; start --run approves the reviewed revision
|
|
62
67
|
gallivant ready <prd.md> [--check] check the PRD against the contract; flip it to ready when it passes
|
|
63
68
|
gallivant start [prd.md] [--no-daemon] [--no-server] [--no-open] [--port 8791] [--base <branch>]
|
|
64
69
|
start the daemon and dashboard, then open it; optionally start a ready PRD
|
|
@@ -66,6 +71,7 @@ const HELP = `gallivant: give an agent a task, let the review loop run, go outsi
|
|
|
66
71
|
gallivant register <pr-url> [--harness <name>] [--session <id>] [--worktree <dir>]
|
|
67
72
|
watch a hand-made PR; on an existing entry, reset it
|
|
68
73
|
gallivant chain <name> <prd1.md> <prd2.md> ... [--base <branch>]
|
|
74
|
+
gallivant chain <name> --after <pr-url|handle> <next.md> ...
|
|
69
75
|
queue ready PRDs; each starts after the previous PR is merged
|
|
70
76
|
gallivant chain [<name>] [--cancel | --retry [--resnapshot]]
|
|
71
77
|
inspect chains, stop future work, or retry after fixing a blocker
|
|
@@ -80,6 +86,15 @@ const HELP = `gallivant: give an agent a task, let the review loop run, go outsi
|
|
|
80
86
|
--resnapshot makes an edited brief the one the gate judges
|
|
81
87
|
--fresh-session replaces retired learned memory after settlement
|
|
82
88
|
gallivant recheck <handle> queue a PR recheck without resetting its budget
|
|
89
|
+
gallivant review retry <handle> --reason <text>
|
|
90
|
+
retry confirmed incomplete or coordinator-cancelled review; retain pieces and limits
|
|
91
|
+
gallivant review qualify --repo <owner/repo> [--capability text|image] [--run [--wait] [--retry --reason <text>]]
|
|
92
|
+
inspect qualification; --run launches a bounded probe; --wait records its exit before returning
|
|
93
|
+
gallivant review status <handle> show pinned policy, owned verdict and unresolved review evidence
|
|
94
|
+
gallivant review policy <handle> --mode external-required|first-party-required|both-required --reason "..."
|
|
95
|
+
explicitly replace policy and re-evaluate the current head
|
|
96
|
+
gallivant review dispute <handle> --finding <id> --reason "..."
|
|
97
|
+
record a dispute for a person; never accepts the author's own dispute
|
|
83
98
|
gallivant cancel <handle> stop further dispatch; request provider cancellation
|
|
84
99
|
gallivant say <handle> --note "..." [--interrupt]
|
|
85
100
|
send an update in the same session; --interrupt stops the active run first
|
|
@@ -93,15 +108,17 @@ const OPTIONS = {
|
|
|
93
108
|
send: { type: "boolean" }, probe: { type: "boolean" }, help: { type: "boolean", short: "h" }, version: { type: "boolean", short: "v" },
|
|
94
109
|
"no-server": { type: "boolean" }, "no-open": { type: "boolean" }, foreground: { type: "boolean" }, worktrees: { type: "string" },
|
|
95
110
|
"no-daemon": { type: "boolean" }, note: { type: "string" }, resnapshot: { type: "boolean" }, "fresh-session": { type: "boolean" }, interrupt: { type: "boolean" },
|
|
96
|
-
base: { type: "string" }, harness: { type: "string" }, session: { type: "string" }, worktree: { type: "string" }, dir: { type: "string" }, port: { type: "string" },
|
|
97
|
-
cancel: { type: "boolean" }, retry: { type: "boolean" },
|
|
111
|
+
base: { type: "string" }, after: { type: "string" }, harness: { type: "string" }, session: { type: "string" }, worktree: { type: "string" }, dir: { type: "string" }, port: { type: "string" },
|
|
112
|
+
cancel: { type: "boolean" }, retry: { type: "boolean" }, wait: { type: "boolean" },
|
|
98
113
|
run: { type: "boolean" }, stdin: { type: "boolean" }, repo: { type: "string" }, revision: { type: "string" },
|
|
99
114
|
"request-id": { type: "string" }, context: { type: "string", multiple: true },
|
|
100
|
-
"completion-target": { type: "string" },
|
|
115
|
+
"completion-target": { type: "string" }, delivery: { type: "string" }, route: { type: "string" },
|
|
101
116
|
answer: { type: "string", multiple: true }, verify: { type: "string", multiple: true },
|
|
102
117
|
since: { type: "string" }, until: { type: "string" }, "dry-run": { type: "boolean" },
|
|
103
118
|
mode: { type: "string" }, status: { type: "string" }, from: { type: "string" }, reason: { type: "string" },
|
|
119
|
+
"host-config": { type: "string" },
|
|
104
120
|
"key-path": { type: "string" }, "ssh-keygen": { type: "string" }, "learning-budget": { type: "string" },
|
|
121
|
+
finding: { type: "string" }, capability: { type: "string" },
|
|
105
122
|
};
|
|
106
123
|
|
|
107
124
|
async function dispatch(argv) {
|
|
@@ -110,10 +127,14 @@ async function dispatch(argv) {
|
|
|
110
127
|
const [cmd, arg] = positionals;
|
|
111
128
|
if (values.version) { console.log(VERSION); return 0; }
|
|
112
129
|
if (values.help || !cmd || cmd === "help") { console.log(HELP); return 0; }
|
|
130
|
+
if (values.after !== undefined && (cmd !== "chain" || !values.after.trim())) throw new Error("--after requires a registered PR URL or handle when queuing a new chain");
|
|
113
131
|
if (cmd === "init") {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
132
|
+
if (arg) throw new Error("init takes no positional argument; run it from inside the target checkout");
|
|
133
|
+
const r = await init({ harness: values.harness, worktrees: values.worktrees, hostConfig: values["host-config"], base: values.base });
|
|
134
|
+
const report = renderDoctor(r.doctor);
|
|
135
|
+
console.log(renderInit(r, report));
|
|
136
|
+
// Doctor's exit code, so a script or an agent reading only the status knows whether setup still has open items.
|
|
137
|
+
return report.exitCode;
|
|
117
138
|
}
|
|
118
139
|
if (values.foreground && cmd !== "serve") throw new Error("--foreground is available only with serve");
|
|
119
140
|
if (values.foreground && values["no-server"]) throw new Error("--foreground cannot be combined with --no-server");
|
|
@@ -161,7 +182,7 @@ async function dispatch(argv) {
|
|
|
161
182
|
}
|
|
162
183
|
}
|
|
163
184
|
const ctx = makeContext();
|
|
164
|
-
const mutating = ["start", "resume", "register", "remove", "recheck", "say", "cancel"].includes(cmd) || cmd === "chain" && (positionals.length > 2 || values.cancel || values.retry);
|
|
185
|
+
const mutating = ["start", "resume", "register", "remove", "recheck", "say", "cancel"].includes(cmd) || cmd === "review" && arg !== "status" || cmd === "chain" && (positionals.length > 2 || values.cancel || values.retry);
|
|
165
186
|
const owner = mutating ? acquireCliMutation(ctx.home) : null;
|
|
166
187
|
try {
|
|
167
188
|
if (cmd === "recheck" || cmd === "say" || cmd === "cancel") {
|
|
@@ -176,6 +197,11 @@ async function dispatch(argv) {
|
|
|
176
197
|
return 0;
|
|
177
198
|
}
|
|
178
199
|
switch (cmd) {
|
|
200
|
+
case "review": {
|
|
201
|
+
const result = await reviewCommand(ctx, { action: arg, handle: positionals[2], repo: values.repo, mode: values.mode, reason: values.reason, finding: values.finding, run: values.run, capability: values.capability, retry: values.retry, wait: values.wait });
|
|
202
|
+
console.log(JSON.stringify(result, null, 2));
|
|
203
|
+
return result.qualified === false ? 1 : 0;
|
|
204
|
+
}
|
|
179
205
|
case "chain": {
|
|
180
206
|
const paths = positionals.slice(2);
|
|
181
207
|
const operation = paths.length > 0 || values.retry;
|
|
@@ -184,7 +210,8 @@ async function dispatch(argv) {
|
|
|
184
210
|
if (values.retry && paths.length) throw new Error("--retry uses the existing plan; do not pass PRD paths");
|
|
185
211
|
if ((values.cancel || values.retry) && !arg) throw new Error("a chain name is required");
|
|
186
212
|
if (values.base && !paths.length) throw new Error("--base is set when queuing a new chain");
|
|
187
|
-
if (paths.length)
|
|
213
|
+
if (values.after && (!paths.length || values.retry || values.cancel)) throw new Error("--after is set only when queuing a new chain with ready PRD paths");
|
|
214
|
+
if (paths.length) await queueChain(ctx, { name: arg, paths, base: values.base, after: values.after });
|
|
188
215
|
else if (values.cancel) cancelChain(ctx, arg);
|
|
189
216
|
else if (values.retry) await retryChain(ctx, { name: arg, resnapshot: values.resnapshot });
|
|
190
217
|
console.log(renderChains(ctx, arg));
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { parseArgs } from "node:util";
|
|
3
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
4
|
+
import { makeContext } from "../lib/context.mjs";
|
|
5
|
+
import { promote } from "../lib/promotion.mjs";
|
|
6
|
+
import { makePromotionTransfer } from "../lib/promotion_git.mjs";
|
|
7
|
+
|
|
8
|
+
const help = `Usage: npm run promote:bitbucket -- --github-pr URL --bitbucket-repo bitbucket.org/workspace/repo [--bitbucket-pr N] [--base main] [--branch name] [--out plan.json]
|
|
9
|
+
Default: read-only dry run. Inspect the plan, then add --apply --expected-plan DIGEST.
|
|
10
|
+
Merged sources use retained exact acceptance. If the reported base changed, --accepted-plan plan.json supplies an optional archived-base fallback.
|
|
11
|
+
No force push, merge or deployment. See docs/bitbucket-promotion.md.`;
|
|
12
|
+
let transfer;
|
|
13
|
+
try {
|
|
14
|
+
const { values } = parseArgs({ options: {
|
|
15
|
+
"github-pr": { type: "string" }, "bitbucket-repo": { type: "string" }, "bitbucket-pr": { type: "string" },
|
|
16
|
+
base: { type: "string" }, branch: { type: "string" }, out: { type: "string" }, "accepted-plan": { type: "string" },
|
|
17
|
+
apply: { type: "boolean", default: false }, "expected-plan": { type: "string" }, help: { type: "boolean", short: "h" },
|
|
18
|
+
} });
|
|
19
|
+
if (values.help) console.log(help);
|
|
20
|
+
else {
|
|
21
|
+
if (!values["github-pr"] || !values["bitbucket-repo"]) throw new Error(help);
|
|
22
|
+
if (values.apply && values.out) throw new Error("--out saves a dry-run plan only; omit it when applying");
|
|
23
|
+
let acceptedPlan;
|
|
24
|
+
if (values["accepted-plan"]) {
|
|
25
|
+
const text = await readFile(values["accepted-plan"], "utf8");
|
|
26
|
+
if (Buffer.byteLength(text) > 1_048_576) throw new Error("Accepted plan is oversized");
|
|
27
|
+
acceptedPlan = JSON.parse(text);
|
|
28
|
+
}
|
|
29
|
+
const ctx = makeContext({ readOnly: true });
|
|
30
|
+
transfer = await makePromotionTransfer(ctx);
|
|
31
|
+
const result = await promote(ctx, {
|
|
32
|
+
githubPr: values["github-pr"], bitbucketRepo: values["bitbucket-repo"],
|
|
33
|
+
...(values["bitbucket-pr"] !== undefined ? { bitbucketPr: Number(values["bitbucket-pr"]) } : {}),
|
|
34
|
+
branch: values.branch, base: values.base, acceptedPlan, apply: values.apply, expectedPlan: values["expected-plan"],
|
|
35
|
+
}, transfer);
|
|
36
|
+
if (values.out) await writeFile(values.out, `${JSON.stringify(result.plan, null, 2)}\n`, { flag: "wx", mode: 0o600 });
|
|
37
|
+
console.log(JSON.stringify(result, null, 2));
|
|
38
|
+
}
|
|
39
|
+
} catch (error) { console.error(error.message); process.exitCode = 1; }
|
|
40
|
+
finally { await transfer?.close(); }
|
package/bin/task-pr.mjs
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { prOperation } from "../lib/pr_operation.mjs";
|
|
3
|
+
try {
|
|
4
|
+
const result = await prOperation(process.argv.slice(2));
|
|
5
|
+
console.log(typeof result === "string" ? result : JSON.stringify(result, null, 2));
|
|
6
|
+
} catch (error) {
|
|
7
|
+
console.error(error.message);
|
|
8
|
+
process.exitCode = 1;
|
|
9
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { parseArgs } from "node:util";
|
|
3
|
+
import { readFileSync } from "node:fs";
|
|
4
|
+
import { makeBitbucketReviewProducer } from "../lib/hosts/bitbucket_review_producer.mjs";
|
|
5
|
+
try {
|
|
6
|
+
const { values, positionals } = parseArgs({ allowPositionals: true, options: Object.fromEntries(["config", "url", "input", "result"].map(key => [key, { type: "string" }])) });
|
|
7
|
+
if (positionals.length !== 1 || !["prepare", "publish"].includes(positionals[0]) || !values.config || !values.url) throw new Error("Use task-review prepare|publish --config <private-reviewer-config> --url <exact-PR-URL> [--input <prepared-json> --result <verdict-json>]");
|
|
8
|
+
const json = path => JSON.parse(readFileSync(path, "utf8"));
|
|
9
|
+
const producer = makeBitbucketReviewProducer({ config: json(values.config) });
|
|
10
|
+
const result = positionals[0] === "prepare" ? await producer.prepare(values.url) : await producer.publish(values.url, json(values.input), json(values.result));
|
|
11
|
+
console.log(JSON.stringify(result, null, 2));
|
|
12
|
+
} catch (error) {
|
|
13
|
+
console.error(error.message);
|
|
14
|
+
process.exitCode = 1;
|
|
15
|
+
}
|
package/docs/README.md
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
# Documentation
|
|
2
2
|
|
|
3
|
-
Start with [installation and your first run](install.md)
|
|
4
|
-
|
|
3
|
+
Start with [installation and your first run](install.md): inside the target
|
|
4
|
+
checkout, `npx --yes @uchibeke/gallivant init --harness codex` (or
|
|
5
|
+
`--harness claude`) writes the config, records the repository and prints the
|
|
6
|
+
setup report. Then choose how to describe the work. [Natural-language tasks](tasks.md) prepare a reviewable brief
|
|
5
7
|
from your request; [hand-authored PRDs](prd.md) let you write that brief directly.
|
|
6
8
|
Both use the same validation, execution, GitHub review and completion workflow.
|
|
7
9
|
Code, research and documentation can all be delivered as verifiable repository
|
|
@@ -15,9 +17,11 @@ requirements and checks.
|
|
|
15
17
|
| Install, configure access and complete a first task | [Getting started](install.md) |
|
|
16
18
|
| Ask an agent to inspect, install and verify setup | [Agent setup](agent-setup.md) |
|
|
17
19
|
| Describe work, answer questions, inspect a draft and authorize execution | [Natural-language tasks](tasks.md) |
|
|
20
|
+
| Choose the typed delivery profile, planner route and review a prepared task | [Typed delivery profiles](task-profiles.md) |
|
|
18
21
|
| Write a brief with acceptance criteria, source files and verification commands | [PRD contract](prd.md) |
|
|
19
22
|
| Find commands, monitor progress, message or resume a run | [Commands](commands.md) |
|
|
20
23
|
| Configure repositories, credentials, harnesses and execution limits | [Configuration](config.md) |
|
|
24
|
+
| Request and verify Codex reviews against the current commit | [Codex review procedure](codex-review.md) |
|
|
21
25
|
| Use the local dashboard and understand product boundaries | [Application](app.md) |
|
|
22
26
|
| Run coding work on an API-backed hosted environment | [OpenAI Agents API](openai-agents.md) |
|
|
23
27
|
| Understand the unavailable Codex Cloud dispatch and its required qualification | [Codex Cloud](codex-cloud.md) |
|