@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.
- package/CONTRIBUTING.md +26 -0
- package/LICENSE +204 -0
- package/README.md +201 -2
- package/SECURITY.md +19 -0
- package/bin/gallivant.mjs +257 -0
- package/bin/package-plugin.mjs +16 -0
- package/bin/release-live.mjs +29 -0
- package/bin/release-package.mjs +23 -0
- package/bin/session-runtime.mjs +13 -0
- package/bin/task-delivery-state.mjs +12 -0
- package/docs/README.md +70 -0
- package/docs/agent-setup.md +214 -0
- package/docs/app.md +111 -0
- package/docs/architecture.md +265 -0
- package/docs/chains.md +102 -0
- package/docs/codex-cloud.md +284 -0
- package/docs/commands.md +620 -0
- package/docs/config.md +430 -0
- package/docs/execution.md +796 -0
- package/docs/guardrails.md +311 -0
- package/docs/install.md +338 -0
- package/docs/launch.md +42 -0
- package/docs/learning.md +369 -0
- package/docs/network-recovery.md +101 -0
- package/docs/openai-agents.md +457 -0
- package/docs/prd.md +246 -0
- package/docs/preparation.md +110 -0
- package/docs/release-qualification.md +196 -0
- package/docs/releasing.md +140 -0
- package/docs/runtime-environment.md +113 -0
- package/docs/task-delivery.md +476 -0
- package/docs/tasks.md +739 -0
- package/lib/aport.mjs +95 -0
- package/lib/attribution.mjs +95 -0
- package/lib/block.mjs +89 -0
- package/lib/capabilities.mjs +3 -0
- package/lib/chains.mjs +222 -0
- package/lib/codex_cloud.mjs +160 -0
- package/lib/codex_cloud_config.mjs +20 -0
- package/lib/codex_cloud_input.mjs +49 -0
- package/lib/codex_cloud_result.mjs +74 -0
- package/lib/commands/doctor.mjs +457 -0
- package/lib/commands/init.mjs +34 -0
- package/lib/commands/learn.mjs +54 -0
- package/lib/commands/new.mjs +47 -0
- package/lib/commands/ready.mjs +45 -0
- package/lib/commands/register.mjs +195 -0
- package/lib/commands/resume.mjs +224 -0
- package/lib/commands/serve.mjs +349 -0
- package/lib/commands/start.mjs +247 -0
- package/lib/commands/start_services.mjs +22 -0
- package/lib/commands/status.mjs +150 -0
- package/lib/commands/task.mjs +73 -0
- package/lib/commands/up.mjs +228 -0
- package/lib/commands/why.mjs +143 -0
- package/lib/config.mjs +461 -0
- package/lib/context.mjs +100 -0
- package/lib/control.mjs +202 -0
- package/lib/control_contract.mjs +16 -0
- package/lib/coordinator.mjs +19 -0
- package/lib/credential.mjs +161 -0
- package/lib/daemon.mjs +156 -0
- package/lib/deliverable.mjs +357 -0
- package/lib/events.mjs +261 -0
- package/lib/executable.mjs +31 -0
- package/lib/execution.mjs +631 -0
- package/lib/execution_contract.mjs +15 -0
- package/lib/execution_input.mjs +4 -0
- package/lib/execution_io.mjs +94 -0
- package/lib/execution_journal.mjs +69 -0
- package/lib/execution_preparation.mjs +29 -0
- package/lib/execution_result.mjs +266 -0
- package/lib/fs.mjs +133 -0
- package/lib/gh.mjs +289 -0
- package/lib/git.mjs +434 -0
- package/lib/harness.mjs +521 -0
- package/lib/harness_log.mjs +432 -0
- package/lib/hash.mjs +16 -0
- package/lib/identity.mjs +98 -0
- package/lib/learning.mjs +654 -0
- package/lib/learning_contract.mjs +2 -0
- package/lib/learning_data.mjs +135 -0
- package/lib/learning_input.mjs +111 -0
- package/lib/learning_qualification.mjs +67 -0
- package/lib/learning_signer.mjs +151 -0
- package/lib/learning_store.mjs +88 -0
- package/lib/log.mjs +53 -0
- package/lib/network_diagnostics.mjs +64 -0
- package/lib/network_recovery.mjs +42 -0
- package/lib/notify.mjs +58 -0
- package/lib/openai_agents.mjs +373 -0
- package/lib/openai_agents_config.mjs +14 -0
- package/lib/openai_agents_http.mjs +87 -0
- package/lib/openai_agents_input.mjs +15 -0
- package/lib/openai_agents_sources.mjs +112 -0
- package/lib/owner_delivery.mjs +443 -0
- package/lib/plugin_package.mjs +340 -0
- package/lib/prd.mjs +635 -0
- package/lib/preparation_agents.mjs +33 -0
- package/lib/preparation_codex.mjs +212 -0
- package/lib/probe.mjs +126 -0
- package/lib/prompt.mjs +238 -0
- package/lib/provider_health.mjs +55 -0
- package/lib/public-format.mjs +31 -0
- package/lib/public_output.mjs +49 -0
- package/lib/release_package.mjs +154 -0
- package/lib/repository_files.mjs +86 -0
- package/lib/run.mjs +385 -0
- package/lib/run_log.mjs +94 -0
- package/lib/runtime-environment.mjs +87 -0
- package/lib/runtime_dependencies.mjs +15 -0
- package/lib/runtime_node.mjs +107 -0
- package/lib/runtime_state.mjs +174 -0
- package/lib/sources/index.mjs +27 -0
- package/lib/sources/prd.mjs +50 -0
- package/lib/start_contract.mjs +37 -0
- package/lib/state.mjs +246 -0
- package/lib/task_allowance.mjs +31 -0
- package/lib/task_completion.mjs +61 -0
- package/lib/task_contract.mjs +450 -0
- package/lib/task_delivery.mjs +219 -0
- package/lib/task_delivery_cancel.mjs +34 -0
- package/lib/task_delivery_contract.mjs +61 -0
- package/lib/task_delivery_mcp.mjs +40 -0
- package/lib/task_delivery_store.mjs +43 -0
- package/lib/task_delivery_view.mjs +88 -0
- package/lib/task_environment.mjs +281 -0
- package/lib/task_prepare.mjs +224 -0
- package/lib/task_store.mjs +38 -0
- package/lib/tasks.mjs +513 -0
- package/lib/tick.mjs +1635 -0
- package/lib/time.mjs +36 -0
- package/lib/tracker/assets.mjs +43 -0
- package/lib/tracker/pages.mjs +320 -0
- package/lib/tracker/runs.mjs +102 -0
- package/lib/tracker/stream.mjs +74 -0
- package/lib/tracker_process.mjs +107 -0
- package/lib/verification_sandbox.mjs +181 -0
- package/node_modules/smol-toml/LICENSE +24 -0
- package/node_modules/smol-toml/README.md +605 -0
- package/node_modules/smol-toml/dist/date.d.ts +41 -0
- package/node_modules/smol-toml/dist/date.js +156 -0
- package/node_modules/smol-toml/dist/error.d.ts +37 -0
- package/node_modules/smol-toml/dist/error.js +67 -0
- package/node_modules/smol-toml/dist/extract.js +289 -0
- package/node_modules/smol-toml/dist/index.cjs +770 -0
- package/node_modules/smol-toml/dist/index.d.ts +44 -0
- package/node_modules/smol-toml/dist/index.js +34 -0
- package/node_modules/smol-toml/dist/parse.d.ts +73 -0
- package/node_modules/smol-toml/dist/parse.js +164 -0
- package/node_modules/smol-toml/dist/primitive.js +151 -0
- package/node_modules/smol-toml/dist/stringify.d.ts +32 -0
- package/node_modules/smol-toml/dist/stringify.js +219 -0
- package/node_modules/smol-toml/dist/struct.js +156 -0
- package/node_modules/smol-toml/dist/util.d.ts +43 -0
- package/node_modules/smol-toml/dist/util.js +57 -0
- package/node_modules/smol-toml/package.json +68 -0
- package/npm-shrinkwrap.json +1823 -0
- package/package.json +105 -4
- package/templates/claude-settings.json +18 -0
- package/templates/passport.gallivant.json +83 -0
- package/templates/plugin/bundled-runtime.json +26 -0
- package/templates/plugin/schemas/mcp.schema.json +120 -0
- package/templates/plugin/schemas/plugin.schema.json +65 -0
- package/templates/plugin/task-delivery.SKILL.md +60 -0
- package/templates/prd.md +32 -0
- package/templates/tracker/tracker.css +301 -0
- package/templates/tracker/tracker.js +721 -0
package/docs/commands.md
ADDED
|
@@ -0,0 +1,620 @@
|
|
|
1
|
+
# Commands
|
|
2
|
+
|
|
3
|
+
Use `gallivant --help` (or `gallivant help`) for the installed CLI's syntax and
|
|
4
|
+
`gallivant --version` for its version. This reference covers the CLI; the
|
|
5
|
+
[task service](tasks.md), [runtime embedding](execution.md) and
|
|
6
|
+
[delivery integrations](task-delivery.md) expose the same core operations to hosts.
|
|
7
|
+
|
|
8
|
+
## Command index
|
|
9
|
+
|
|
10
|
+
| Intent | Command | Notes |
|
|
11
|
+
|---|---|---|
|
|
12
|
+
| Create config | `gallivant init` | Selected Codex or Claude installation; preserves existing config. |
|
|
13
|
+
| Check setup/connectivity | `gallivant doctor` | `--network` tests DNS/HTTPS; `--probe` is a real Claude run. |
|
|
14
|
+
| Prepare a task | `gallivant task "request"` | Uses inference; implementation requires `--run` authorization. |
|
|
15
|
+
| Inspect/continue a prepared task | `gallivant task list`, `inspect`, `answer`, `resume`, `validate`, `start` | Task IDs and exact revisions; see [task operations](#task-operations). |
|
|
16
|
+
| Create a written brief | `gallivant new NAME` | Writes a draft template in the target repository. |
|
|
17
|
+
| Validate/record readiness | `gallivant ready PRD` | `--check` is local validation without hosted recording or file changes. |
|
|
18
|
+
| Start work and services | `gallivant start [PRD]` | No PRD starts/reuses services only; `--no-open` and `--no-server` are available. |
|
|
19
|
+
| Sequence work | `gallivant chain` | Each successor waits for the previous PR to merge; never auto-merges. |
|
|
20
|
+
| Adopt/reset a PR | `gallivant register PR_URL` | Explicit registration; existing entry resets its review budget and cursor. |
|
|
21
|
+
| Run the coordinator | `gallivant up` | Foreground loop; `--once` performs one cycle. |
|
|
22
|
+
| Stop services | `gallivant down` | Leaves active agent processes running. |
|
|
23
|
+
| Inspect runs | `gallivant status` | `--all` includes finished rows; `--json` is available. |
|
|
24
|
+
| Start the dashboard | `gallivant serve` | Same service startup as `start` without a PRD; loopback only. |
|
|
25
|
+
| Diagnose a stop | `gallivant why HANDLE` | Shows state, failure and pending controls. |
|
|
26
|
+
| Continue stopped execution | `gallivant resume HANDLE` | Preserves the session; explicit changed-brief acceptance uses `--resnapshot`. |
|
|
27
|
+
| Re-evaluate PR gates | `gallivant recheck HANDLE` | No budget reset, no CI rerun, no replacement for execution recovery. |
|
|
28
|
+
| Send a correction | `gallivant say HANDLE --note "..."` | Queues same-session delivery; supported local runs can use `--interrupt`. |
|
|
29
|
+
| Stop future dispatch | `gallivant cancel HANDLE` | Requests cancellation; inspect confirmation before assuming the process stopped. |
|
|
30
|
+
| Forget tracking | `gallivant remove HANDLE` | Leaves the PR, branch, labels and checkout in place. |
|
|
31
|
+
| Collect/review lessons | `gallivant learn` | Repository-scoped collection; production application remains unqualified. See [learning commands](#learning-commands). |
|
|
32
|
+
|
|
33
|
+
A **run handle** is `<repo>#<pr>` (short name or `owner/name`), the registry ID
|
|
34
|
+
`<repo>/<prd-id>`, or a PRD path. Bare PR numbers are ambiguous and refused.
|
|
35
|
+
Task-intake commands instead use their returned **task ID and revision**; learning
|
|
36
|
+
commands use a **repository, candidate ID and revision digest**. These identities
|
|
37
|
+
are not interchangeable.
|
|
38
|
+
|
|
39
|
+
Local implementation adapters are `claude`, `codex`, `gemini`, `opencode` and
|
|
40
|
+
`goose`; `openai-agents` is hosted execution. Availability depends on the configured
|
|
41
|
+
provider/model, permissions and tested adapter capabilities, not just the command
|
|
42
|
+
name. `codex-cloud` is registered for recovery but refuses new dispatch. See the
|
|
43
|
+
[current support matrix](../README.md#harness-support), [Agents API](openai-agents.md)
|
|
44
|
+
and [Codex Cloud gate](codex-cloud.md). There is no separate cloud start command:
|
|
45
|
+
select the configured harness in the PRD or task preparation.
|
|
46
|
+
|
|
47
|
+
## `gallivant init [--harness codex|claude] [--worktrees <directory>]`
|
|
48
|
+
|
|
49
|
+
Create a private config from your authenticated GitHub login and the selected
|
|
50
|
+
installed harness (Codex by default). Creates a separate checkouts directory,
|
|
51
|
+
disables optional notifications initially, and prints the packaged template paths.
|
|
52
|
+
Existing configs are refused, never replaced. Does not change credentials, global
|
|
53
|
+
harness settings, reviewer installation or repository rules. Follow `doctor` and
|
|
54
|
+
[installation](install.md) next. `--version` prints the installed package version.
|
|
55
|
+
|
|
56
|
+
## `gallivant doctor [--send] [--probe]`
|
|
57
|
+
|
|
58
|
+
`gallivant doctor --network <https-origin> [--json]` runs standalone, bounded
|
|
59
|
+
DNS/HTTPS diagnostics without loading config or credentials. Local sign-in checks
|
|
60
|
+
do not prove API connectivity. See [network recovery](network-recovery.md).
|
|
61
|
+
|
|
62
|
+
The install checklist and the health probe, one line per check, each failure with the exact command or file that fixes it. With no config it prints a complete config built from this machine. `--send` posts a test notification. `--probe` runs a real Claude session in a temp directory and confirms a write inside is allowed and a write outside is denied. Exit code 1 while anything fails.
|
|
63
|
+
|
|
64
|
+
`doctor` prints one line per repository in `repos` naming the base branch its pull requests will target and where that answer came from,
|
|
65
|
+
so a repository whose work should go to `staging` while nothing is configured is visible before a session opens a pull
|
|
66
|
+
request against `main`. A configured base that GitHub does not have is a failure here, with the fix. See [the base
|
|
67
|
+
branch](config.md#the-base-branch).
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
## `gallivant task [prepare] "request" [--stdin] [--run] [--json]`
|
|
71
|
+
|
|
72
|
+
Prepares an isolated canonical PRD through the shared task service. Accepts
|
|
73
|
+
`--dir`, `--repo`, `--base`, `--harness`, repeated `--context` files and a retry-safe
|
|
74
|
+
`--request-id`. Material unknowns return saved questions; `task answer` resumes
|
|
75
|
+
their identity using `--revision`, `--request-id` and repeated `--answer id=text`.
|
|
76
|
+
`task inspect`, `list`, `resume`, `validate` and `start` expose the same versioned
|
|
77
|
+
operations to CLI and in-process clients. Preparation uses inference but starts
|
|
78
|
+
implementation only with explicit `--run` authorization and exact readiness.
|
|
79
|
+
Configured Claude uses tool-free preparation; Codex 0.160.0+ uses its isolated
|
|
80
|
+
preparation profile; `openai-agents` uses a text-only session with no tools or
|
|
81
|
+
execution environment. All require their configured provider/model access.
|
|
82
|
+
Gemini, OpenCode and Goose can implement ready PRDs but cannot prepare them;
|
|
83
|
+
unsupported preparation returns `TASK_PREPARATION_BOUNDARY` without fallback.
|
|
84
|
+
Codex Cloud also refuses new implementation dispatch until its environment can be
|
|
85
|
+
bound to the intended repository. See [provider setup](config.md#execution-providers).
|
|
86
|
+
|
|
87
|
+
Requests can produce code, documentation, research or other repository artifacts.
|
|
88
|
+
A natural-language task still becomes an explicit, validated delivery contract;
|
|
89
|
+
it does not require the user to write a PRD first.
|
|
90
|
+
See [task operations](tasks.md) for examples, source delivery and stopping rules.
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
### Task operations
|
|
94
|
+
|
|
95
|
+
Task state and process exit status answer different questions. The CLI exits 1
|
|
96
|
+
for a blocked task, daemon startup failure or an exception. Saved clarification
|
|
97
|
+
questions can return 0; automation must inspect `status`, `questions` and
|
|
98
|
+
`nextAction` in `--json` output before deciding that preparation is ready.
|
|
99
|
+
|
|
100
|
+
Use the ID and revision printed by the preceding operation; placeholders below
|
|
101
|
+
are not literal values. `--json` returns structured task state for automation.
|
|
102
|
+
|
|
103
|
+
| Operation | Syntax and purpose |
|
|
104
|
+
|---|---|
|
|
105
|
+
| Prepare | `gallivant task prepare "request" --dir CHECKOUT --harness NAME` creates a brief through the selected supported preparation adapter. The word `prepare` is optional. |
|
|
106
|
+
| Read stdin | `gallivant task --stdin` reads a complete piped request instead of a positional string. |
|
|
107
|
+
| List | `gallivant task list` lists saved intake tasks. |
|
|
108
|
+
| Inspect | `gallivant task inspect TASK_ID` shows current revision, questions and next action. |
|
|
109
|
+
| Answer | `gallivant task answer TASK_ID --revision N --request-id ANSWER_ID --answer 'QUESTION_ID=text'` resumes saved clarification; repeat `--answer` for multiple answers. |
|
|
110
|
+
| Resume preparation | `gallivant task resume TASK_ID --revision N` continues the saved preparation state; it is different from `gallivant resume HANDLE` for implementation. |
|
|
111
|
+
| Validate | `gallivant task validate TASK_ID --revision N` runs the shared readiness operation on the saved task. |
|
|
112
|
+
| Authorize/start | `gallivant task start TASK_ID --revision N --run` authorizes implementation for that exact ready revision. Prior authorization can make `--run` unnecessary. |
|
|
113
|
+
|
|
114
|
+
Preparation accepts `--repo`, `--base`, repeated `--context` files and `--verify`
|
|
115
|
+
commands, and a retry-safe `--request-id`. Answers may also add explicit context
|
|
116
|
+
and verification commands. `--completion-target delivery_ready|integrated` selects
|
|
117
|
+
whether the task tracks readiness or confirmed integration; neither grants merge
|
|
118
|
+
permission. `--run` on initial preparation authorizes dispatch after readiness and
|
|
119
|
+
any required answers. `--no-daemon` leaves monitoring startup to an existing host
|
|
120
|
+
or explicit coordinator. See [task operations](tasks.md) for revision conflicts,
|
|
121
|
+
uncertain dispatch, evidence and authorization rules.
|
|
122
|
+
|
|
123
|
+
## `gallivant new <name> [--harness <name>] [--dir <repo>]`
|
|
124
|
+
|
|
125
|
+
Writes `docs/prds/<name>.md` into the repository you are standing in, from the template that ships with the package.
|
|
126
|
+
Run it from anywhere inside that repository: the root comes from git, not from the current directory, so a
|
|
127
|
+
subdirectory writes to the same place as the root. The name is lowercased and dashed to what the contract's `path`
|
|
128
|
+
rule accepts, so `gallivant new "Widget Export!"` writes `docs/prds/widget-export.md`.
|
|
129
|
+
|
|
130
|
+
The `harness:` line names whichever harness your config has, so the brief cannot ask for one you have not installed.
|
|
131
|
+
`--dir` is for the case where you are not inside the target repository.
|
|
132
|
+
|
|
133
|
+
It writes one file and nothing else: no registry entry, no branch, no network. The template deliberately fails the
|
|
134
|
+
contract, because a starting point that passed it would be a starting point nobody edits. `gallivant ready <path>
|
|
135
|
+
--check` prints what is still missing.
|
|
136
|
+
|
|
137
|
+
## `gallivant ready <prd.md> [--check]`
|
|
138
|
+
|
|
139
|
+
The explicit-file entry point to the shared readiness gate. Runs every rule of [the contract](prd.md), prints the checklist, asks APort to decide readiness against a per-PRD passport built from those rules when configured, and flips `status: draft` to `ready` (recording the decision id as `aport_decision`) only on an allow. It does not commit the file. `--check` reads only the brief and its sources: it skips runtime config, credentials and hosted recording, and writes nothing. Hosted recording prints a progress message and has a 15-second request timeout. Exit code 1 while anything fails.
|
|
140
|
+
|
|
141
|
+
## `gallivant start [prd.md] [--no-daemon] [--no-server] [--no-open] [--port 8791] [--base <branch>]`
|
|
142
|
+
|
|
143
|
+
With no PRD, ensure the daemon and dashboard are running and open the dashboard.
|
|
144
|
+
With a PRD, submit that task first, then use exactly the same service startup.
|
|
145
|
+
The sequence below describes local CLI implementation. Hosted Agents execution
|
|
146
|
+
uses the same validation, snapshot, checkout and review ownership, but dispatches
|
|
147
|
+
through its transport: the coordinator verifies and publishes returned artifacts.
|
|
148
|
+
It sends no GitHub credential or local harness settings to the hosted sandbox.
|
|
149
|
+
[The execution contract](execution.md) covers durable remote dispatch and recovery.
|
|
150
|
+
Codex Cloud currently refuses new dispatch before starting work.
|
|
151
|
+
|
|
152
|
+
Local task submission:
|
|
153
|
+
|
|
154
|
+
1. Reads the PRD into a Request (see [the contract](prd.md)), which names the target repository: the checkout the file itself is in, so the PRD has to live inside the repo it describes. Runs the full contract on it and refuses on the first failing rule. There is no override flag.
|
|
155
|
+
2. Requires `status: ready`, produced by the shared readiness path (`gallivant ready` or validated task intake).
|
|
156
|
+
3. Checks the selected harness version and sign-in before cloning or dispatch. A failed check refuses startup with its setup remedy; no model call is made.
|
|
157
|
+
4. Builds the run specification: the prompt, the session id, and the argv the harness will be spawned with, including the read-only `context_paths`. This validation happens before the clone, so unsupported local permissions do not leave a new checkout. A harness that cannot grant those directories as read-only is refused here, with nothing cloned and nothing registered, so rerunning `start` after fixing the config works rather than failing on a leftover worktree.
|
|
158
|
+
5. Works out the base branch: the pull request this will open targets it, and the new branch is cut from it. `--base` wins, then the base configured for this repository in `repos`, then the repository's default branch, which is the fallback and what an operator who configures nothing gets. A `--base` is written into `repos` so it is typed once per repository. A base that GitHub does not have fails here, before anything is cloned: left to `gh pr create --base` it would fail after the run had implemented the brief and spent the budget. See [the base branch](config.md#the-base-branch).
|
|
159
|
+
6. Clones the repo into `<worktrees>/<repo>/<prd id>` (partial clone, blobs on demand) on a new branch `work/<prd id>` cut from that base, fetched first so the cut is from the current base rather than a stale local ref. Your own checkout is never touched.
|
|
160
|
+
7. Saves the daemon's own copy of the PRD and each carried `sources` file under `~/.gallivant/prds/`. Fix rounds and the completion gate read these snapshots, so a session cannot rewrite its own brief. Records where your copy lives, plus a fingerprint of the contract, for later comparison: see [editing the brief after the work has started](prd.md#editing-the-brief-after-the-work-has-started).
|
|
161
|
+
8. Copies those snapshots into the checkout at their original repository paths, creating directories as needed. The PRD is usually only in your own checkout; this copy lets the session commit it with the implementation. Copies in the session's checkout are writable and are never read back for a decision.
|
|
162
|
+
9. Starts the session detached with the PRD as its prompt, records the session id, and remembers the repo for recovery.
|
|
163
|
+
|
|
164
|
+
The entry is `running` until the daemon sees the run end. Then either a PR exists on the branch and the entry enters `pr-open`, or it stops with `no-pr`.
|
|
165
|
+
|
|
166
|
+
It also brings the daemon up in the background if one is not already running, and waits until the daemon reports
|
|
167
|
+
itself before returning. That is not a convenience: `start` opens a session that will open a pull request, and the
|
|
168
|
+
daemon is the only thing that then reads reviews, dispatches fixes and reaches ready-for-human. Without it the PR sits
|
|
169
|
+
untouched and nothing says so, which is the one failure this tool exists to prevent. `--no-daemon` skips it, for the
|
|
170
|
+
case where you are about to run `gallivant up` in the foreground yourself.
|
|
171
|
+
|
|
172
|
+
A daemon started this way is detached, so it outlives the terminal that ran `start`, and its output goes to
|
|
173
|
+
`~/.gallivant/daemon.log`. A second `start` does not add a second daemon.
|
|
174
|
+
|
|
175
|
+
The dashboard also runs detached, writes `tracker.log`, and opens in the default
|
|
176
|
+
browser. `--no-open` leaves it running without opening a tab; `--no-server` skips
|
|
177
|
+
dashboard startup and opening. These flags do not stop services already running.
|
|
178
|
+
A headless machine prints the URL. Process identity, instance, code and port are
|
|
179
|
+
checked before reusing a tracker; a port owned by another app/home is refused.
|
|
180
|
+
To change a running tracker's port, `gallivant down`, then `gallivant start --port N`.
|
|
181
|
+
If service startup fails after dispatch, the command reports the partial failure
|
|
182
|
+
with exit code 1. Retry `gallivant start` without a PRD, not the original submission.
|
|
183
|
+
|
|
184
|
+
`gallivant down` stops the verified daemon and standalone tracker. Existing agent
|
|
185
|
+
processes continue; restart monitoring with `gallivant start`. Embedded trackers
|
|
186
|
+
are owned by their host and are not stopped by this command.
|
|
187
|
+
|
|
188
|
+
## `gallivant chain [<name> [<first.md> <next.md> ...]] [--base <branch>]`
|
|
189
|
+
|
|
190
|
+
Queue at least two ready PRDs in order. All must be new tasks in one checkout of the same repository and on the same
|
|
191
|
+
resolved base. `--base` selects the base for a new chain; otherwise the repository config or default branch applies.
|
|
192
|
+
The daemon starts the first task and starts each successor only after GitHub confirms the preceding PR was merged
|
|
193
|
+
into that base. The final merge completes the chain. `ready-for-human`, a completed agent process and a local `done`
|
|
194
|
+
entry never satisfy the dependency; closing without merging stops the chain. Gallivant never merges for you.
|
|
195
|
+
|
|
196
|
+
With no arguments, lists chains. With only a name, shows that chain's milestones and current wait or stop. Queueing
|
|
197
|
+
brings the existing daemon up if needed. Independent runs continue alongside it.
|
|
198
|
+
|
|
199
|
+
| Command | Effect |
|
|
200
|
+
|---|---|
|
|
201
|
+
| `gallivant chain launch first.md next.md` | Approve the order and current brief/source fingerprints, then queue dispatch. |
|
|
202
|
+
| `gallivant chain launch --retry` | Recheck a stopped chain after its cause is resolved. |
|
|
203
|
+
| `gallivant chain launch --retry --resnapshot` | Explicitly accept updated briefs and carried sources for unstarted tasks. |
|
|
204
|
+
| `gallivant chain launch --cancel` | Stop future dispatch; preserve already started work and its review loop. |
|
|
205
|
+
|
|
206
|
+
Changed queued inputs require explicit reapproval. An ambiguous pending start is never cleared by retry because a
|
|
207
|
+
session may already have started. Recover an ordinary stopped milestone with its existing run controls; that does
|
|
208
|
+
not require a separate chain retry. See [PRD chains](chains.md) for the workflow, source preservation and recovery.
|
|
209
|
+
|
|
210
|
+
## `gallivant register <pr-url> [--harness <name>] [--session <id>] [--worktree <dir>]`
|
|
211
|
+
|
|
212
|
+
Puts a PR into the loop that Gallivant did not open, or resets one that stopped.
|
|
213
|
+
|
|
214
|
+
- With `--session` and `--worktree`, later fixes resume that session in that directory. A new local session attachment requires both values; an existing entry can reuse its recorded directory. The directory and provider session identity must match the original run. The id has to be one the chosen harness could have minted (a UUID for claude, codex and gemini, `ses_...` for opencode, `work-<uuid>` or legacy `gallivant-<uuid>` for goose), the same rule the PR block is held to: the value ends up in the harness's argv, where goose in particular derives its session file from it.
|
|
215
|
+
- Without `--session`, a compatible session recorded in the existing entry or validated PR metadata is retained. When none exists, the first fix starts a fresh session whose prompt tells it to read the PR with `gh pr view` and `gh pr diff` before changing anything.
|
|
216
|
+
- Without `--worktree`, the existing recorded checkout is reused, or a checkout is created from the PR branch at the standard path.
|
|
217
|
+
- A `--worktree` you pass is resolved to an absolute path first, so `.` means the directory you typed it in and not whatever directory the daemon happens to run in later. It is then checked before it is accepted: its `origin` must be the PR's repository and it must already be on the PR's head branch. A path that fails either check is an error, since the harness edits and pushes from that directory. It is never relocated or re-cloned for you, because a resumed session is keyed to the directory it ran in.
|
|
218
|
+
- On an entry that already exists: reason cleared, iteration reset to zero, a marked reset comment posted on the PR (so a count rebuilt from GitHub starts from zero too), cursor set to now, watching again. This is how you restart a `needs-human` PR after you fixed the conflict or answered the question. A fresh registration instead looks at the PR's whole history, so feedback already on it gets addressed.
|
|
219
|
+
- That reset comment is the reset boundary, so posting it is a precondition of the reset and not a best-effort extra. A count rebuilt from GitHub finds its marker and counts only the round comments after it; with the comment missing and `state.json` later lost, recovery reconstructs the rounds this command had just zeroed, and an entry restored at `max_iterations` stops with `iterations` on its next event having done no work in the round. If it cannot be posted, `register` refuses and changes nothing: the entry keeps its iteration, its state and its cursor, and running the same command again once GitHub answers does the whole reset in one go.
|
|
220
|
+
- A reset with a new `--harness` or `--session` makes two durable writes to GitHub, and they are ordered so a failure between them cannot leave GitHub and the registry disagreeing about which harness or session this PR belongs to. The reset comment goes first because it is safely repeatable: a count rebuilt from GitHub takes the LAST reset marker, so a second one counts as one. The identity block goes last, because that write is what a recovery reads the harness and the session out of. So a failed block write leaves a reset comment on the PR, the registry untouched, and both sides still naming the old identity; the same command run again completes the reset.
|
|
221
|
+
- Changing `--harness` without giving a new `--session` drops the inherited session and starts a fresh one on the next fix round. This also applies when both harnesses use UUIDs: a Claude session does not belong to Codex. An explicit `--session` must have the chosen harness's format and is used as supplied.
|
|
222
|
+
|
|
223
|
+
When the block names a PRD that exists on the PR's branch, the daemon's own snapshot of it is taken, exactly as recovery does, because the completion gate reads that snapshot and nothing else: without it the gate is skipped and the PR can be marked ready with no acceptance criterion evaluated. A snapshot already on disk is kept rather than replaced with the copy the session could have edited, and a PRD the branch does not carry is logged and the PR watched without a gate.
|
|
224
|
+
|
|
225
|
+
Fork PRs and closed PRs are refused. On managed `work/*` or legacy `gallivant/*` branches, the neutral recovery record is added or migrated to match the selected harness/session and PRD. Recovery after a lost `state.json` reads that record, so it must agree with the registry. A hand-made branch outside those conventions remains explicitly registered in local state; it receives no invalid recovery record and is still excluded from automatic recovery.
|
|
226
|
+
|
|
227
|
+
## `gallivant up [--once]`
|
|
228
|
+
|
|
229
|
+
The daemon. On boot it acquires `daemon.lock` before contacting GitHub and refuses to run if another daemon owns it. The lock records the PID, process start time and command; `ps` must be available to verify that identity. Its output uses a fixed locale and UTC, so a different terminal cannot mistake formatting differences for a replacement process. `daemon.json` reports health separately, so a failed health write cannot allow a second daemon. Background startup returns once ownership is published, while GitHub initialization may still be running. `down` verifies the recorded identity before sending SIGTERM, so a reused PID is not enough to stop a process. A live older daemon with a missing or unversioned identity is reported as `UNVERIFIED` and must be verified and stopped manually before restarting; its lock is never silently replaced.
|
|
230
|
+
|
|
231
|
+
It then reconciles with GitHub: for every repo in `repos`, every open PR of yours on a `work/*` (or legacy `gallivant/*`) branch with a valid block that is not in the registry is registered, with the iteration recovered by counting Gallivant's own round comments and the cursor set so old events are not replayed. The PRD snapshot is taken from the PR branch when the daemon has none. Missing checkouts are recreated from the PR branch.
|
|
232
|
+
|
|
233
|
+
A recovered entry is treated as newly asking, not as mid-conversation, and in two ways that `register` already worked this way:
|
|
234
|
+
|
|
235
|
+
- The reviewer clock is floored at `rereview_minutes` ago, so a PR whose last round comment is seven hours old is not stopped `reviewer-silent` on the very first tick. The silence accrued while no daemon was running to ask, and stopping for it tells you nothing you can act on while costing you a `register` to resume.
|
|
236
|
+
- Failing checks on the recovered head remain eligible for dispatch. Preserve the local state and run records whenever possible: recovery from PR metadata cannot reconstruct every in-flight action. A daemon exit does not discard worktree changes or necessarily stop an agent; inspect surviving runs before recovering from lost state.
|
|
237
|
+
|
|
238
|
+
The coordinator runs bounded progress and review work on separate schedules.
|
|
239
|
+
`poll_seconds` controls GitHub review and chain checks; provider progress and
|
|
240
|
+
readiness refreshes have their own bounds. A failed or pending provider/account
|
|
241
|
+
probe blocks dispatch for that scope, while independent scopes can continue.
|
|
242
|
+
Ticks do not overlap. `--once` runs a single tick and exits; normal `up` stays in
|
|
243
|
+
the foreground. Use `gallivant start` for background monitoring and the dashboard.
|
|
244
|
+
|
|
245
|
+
On a Mac the daemon runs `caffeinate -i` for its own lifetime.
|
|
246
|
+
|
|
247
|
+
## `gallivant down`
|
|
248
|
+
|
|
249
|
+
Stops the verified daemon and the standalone dashboard. Already-spawned agent
|
|
250
|
+
processes continue; the next startup recovers their recorded state. An embedded
|
|
251
|
+
dashboard remains owned by its host application. Use `gallivant start` to restart
|
|
252
|
+
services after updating the installed code. Do not start the same PRD again to
|
|
253
|
+
recover an existing task.
|
|
254
|
+
|
|
255
|
+
## `gallivant status [--all] [--json]`
|
|
256
|
+
|
|
257
|
+
```
|
|
258
|
+
gallivant daemon up since 6h ago last tick 40s ago next in 80s gh ok claude signed-in (API unchecked) codex signed-in (API unchecked)
|
|
259
|
+
|
|
260
|
+
NEEDS YOU
|
|
261
|
+
widget#142 needs-human base-conflict round 2/30 -> staging 12m ago gallivant why widget#142
|
|
262
|
+
api#31 ready green, no blocking findings, receipt accepted round 1/3 -> main 2h ago https://github.com/acme/api/pull/31
|
|
263
|
+
|
|
264
|
+
RUNNING
|
|
265
|
+
guard#88 fixing review 2201 by chatgpt... round 1/3 -> staging 3m ago
|
|
266
|
+
widget#150 waiting on reviewer, nudged once round 0/3 -> main 4m ago
|
|
267
|
+
api#44 blocked ready label write failing (3), retrying round 1/3 -> main 6m ago
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
The `-> <branch>` is the base: the branch this pull request targets, or will target once it is opened. It is on every
|
|
271
|
+
row because the question has a wrong answer that costs a whole run, and before the PR exists there is nowhere else to
|
|
272
|
+
read it.
|
|
273
|
+
|
|
274
|
+
A `ready` row says whether the completion gate accepted the receipt or never ran at all (`RECEIPT NOT CHECKED`, with the reason), because an entry with no PRD snapshot reaches ready on the checks and the reviewer alone and that is a different thing from passing the gate.
|
|
275
|
+
|
|
276
|
+
A `brief-moved` row is an entry whose brief you have edited since it started, in a way that changes what the work is or what will be checked. It sits under NEEDS YOU whatever the entry is otherwise doing, and it outranks every other label on the row, because it is the only one that says the work itself may be aimed at the wrong target: a red check or a waiting reviewer are questions about work whose brief nobody disputes. The detail names the first difference and `gallivant why` has the rest. `status` runs the comparison itself rather than reading what the last tick found, so a brief you edited thirty seconds ago shows up now rather than after the next poll. A `done` entry is never compared: there is nothing left to certify, and tidying up your briefs afterwards is not something to be warned about.
|
|
277
|
+
|
|
278
|
+
A row whose detail names a GitHub write is an entry whose tick is declining one step until that write lands, with the failures counted; see `gallivant why` below for those writes. `blocked` is the one of those to read twice: every readiness condition has already passed and only the label that says so will not write, so the label is `blocked` rather than `fixing`. The others read `fixing` or `implementing`, which is true for them, because a fix round really does follow.
|
|
279
|
+
|
|
280
|
+
Sections are in the order needs-you, running; `--all` adds done. Exit code 0 means the daemon has a verified live process identity; it does not mean every provider is healthy or every task succeeded. Exit code 1 means no verified live daemon. `--json` prints the same model, including done rows, for scripts and UIs; inspect the rows and probes rather than using the exit code as a completion gate.
|
|
281
|
+
|
|
282
|
+
Chain progress is shown alongside runs. `gallivant chain <name>` shows the full ordered plan and explains which
|
|
283
|
+
milestone or merge it is waiting for. Unstarted milestones have no agent run yet.
|
|
284
|
+
|
|
285
|
+
## `gallivant serve [--port 8791] [--no-open] [--no-daemon] [--foreground]`
|
|
286
|
+
|
|
287
|
+
Uses the same service startup as `start` without a PRD: daemon, dashboard, browser.
|
|
288
|
+
Use `--foreground` to keep the tracker attached to this terminal; Ctrl-C stops
|
|
289
|
+
that tracker, while the daemon and active agent sessions continue. For an existing
|
|
290
|
+
supervisor that manages the daemon separately, use
|
|
291
|
+
`gallivant serve --foreground --no-open --no-daemon`. The exported `serve()` and
|
|
292
|
+
`mount()` APIs retain their server-only behavior for embedding.
|
|
293
|
+
|
|
294
|
+
A local web page showing every entry and every run, with the log of a run tailing live. One place to look instead of `status`, `why` and `tail -f` in three terminals. It is meant to sit in an iframe in a dashboard, so it assumes no viewport size and never navigates the top-level window.
|
|
295
|
+
|
|
296
|
+
Three views, each with a sidebar listing everything the view holds:
|
|
297
|
+
|
|
298
|
+
- `/` every registry entry as a row, grouped needs-you, running and done the same way `gallivant status` groups them, from the same `model()`.
|
|
299
|
+
- `/run?id=<entry id>` one entry: handle, state, reason, harness, round, PR link, branch, checkout, session id, and the live log below. When the brief has changed since the run started, every difference is listed above the facts, with what to do about it: the page has room for the whole list where a `status` row has one line.
|
|
300
|
+
- `/runs` every run folder under `~/.gallivant/runs`, newest first, with its entry, start time, exit code and duration, filterable by entry. Picking one in the sidebar opens its log in the pane beside the table. The history is already on disk; this is the index over it.
|
|
301
|
+
|
|
302
|
+
The sidebar has one filter box that searches everything on the view, including fields the row does not show in full: an entry's id, reason and harness, a run's id and start time. Groups collapse, and which ones you closed is remembered per view. A filter overrides that, so a match inside a closed group still shows. `?by=harness` groups by harness instead of by state, and the choice rides along on every link, so a grouped view is a URL you can bookmark or frame.
|
|
303
|
+
|
|
304
|
+
JSON for scripts and for a dashboard's own widgets: `/api/status` (the same model `status --json` prints), `/api/runs`, `/api/run/status?id=<entry id>`, and `/api/run/output?id=<entry id>` for the log as server-sent events. `/api/run/history?id=<entry id>` serves one 400-line window of a run's log as JSON rather than as a stream, older than what the pane is showing: `?before=<line number>` asks for the window ending just before that line, and the answer says `from`, `to`, `total` and how many lines are older still. Both log routes address a run the same way and validate it the same way, so a run id that is refused by one is refused by the other. `--port` takes anything from 1 to 65535; the default is 8791.
|
|
305
|
+
|
|
306
|
+
Two things to know about it:
|
|
307
|
+
|
|
308
|
+
- **GET is read-only; run controls require a local POST.** The run page groups Recheck PR, Resume agent and Cancel task separately from the message composer and its Send message button. These enqueue one request in the existing registry; the daemon applies it after any active run settles. The write requires a loopback peer, a loopback Host matching the serving port, an exact same-origin request and a per-server CSRF token. Mounted trackers keep the host's authentication, and remote readers do not receive controls.
|
|
309
|
+
- **It binds to 127.0.0.1 and has no password.** Loopback is a local-machine boundary, not account authentication or isolation from other local processes. Do not expose it through an unauthenticated tunnel or public proxy: pages show repository state, local paths and agent output.
|
|
310
|
+
|
|
311
|
+
### Rechecking and updating a run
|
|
312
|
+
|
|
313
|
+
`needs-human` stops normal review and check processing. GitHub labels may trigger a repository's workflows, but they do not restart Gallivant. For a resolved review/CI blocker use **Recheck PR** on `/run?id=...`, or:
|
|
314
|
+
|
|
315
|
+
```sh
|
|
316
|
+
gallivant recheck agent-passport#396
|
|
317
|
+
gallivant say agent-passport#396 --note "The external blocker is resolved; continue within the approved brief."
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
Recheck returns the entry to watching without resetting its iteration count or check dispatch markers. The existing loop reads checks, review and the completion gate again. It does not rerun GitHub Actions or override a failed check. Unchanged failures stop again without spending another fixer round. To deliberately reset a spent round budget, use `register`.
|
|
321
|
+
|
|
322
|
+
An agent execution failure requires **Resume agent**, not Recheck. Recognized
|
|
323
|
+
temporary connection failures have [bounded automatic recovery](network-recovery.md);
|
|
324
|
+
status shows their next attempt. Recheck refuses to clear that failure or its
|
|
325
|
+
recovery budget. Authentication, policy and uncertain-launch failures still need
|
|
326
|
+
operator intervention. Existing stopped jobs require one explicit resume after upgrade.
|
|
327
|
+
|
|
328
|
+
**Resume agent** continues the same session on its current instructions. **Send message** and `say` deliver your correction to that session, including after an agent has finished and its PR is ready for human review. A closed or merged PR requires a follow-up PRD. Both use the existing resume path and preserve the approved brief, permissions and review budget. Local CLI resumes preserve uncommitted files and the index; the automatic base merge is deferred when the tree is dirty. The agent must inspect partial work, commit only its task changes, then fetch and merge the intended base into its task branch before rerunning verification and pushing. It must preserve unrelated edits and carried instructions, stopping if they prevent that merge. This never authorizes merging the PR or writing to its base. Replacing a changed brief or carried files still requires an explicit `resume --resnapshot`. Every existing replacement file, including ignored files absent from Git status, must match either the previous snapshot or the newly accepted bytes; conflicting session edits stop the resnapshot before any file or snapshot is replaced.
|
|
329
|
+
|
|
330
|
+
During a run, messages queue until it finishes by default. Select **Interrupt the active run to apply this message**, or use:
|
|
331
|
+
|
|
332
|
+
```sh
|
|
333
|
+
gallivant say agent-passport#396 --interrupt --note "Preserve the existing article's useful sections; improve them without turning it into a summary."
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
At the next daemon check, Gallivant records the active run's descendants, including tool helpers in separate process groups. It stops the tools and their owner, waits for the recorded live processes to exit, then resumes the same session with the message and existing files. Zombie processes cannot write and do not block delivery. Surviving process identities allow cancellation to finish after a daemon restart; if ownership cannot be verified, the request fails visibly with the message preserved and no replacement run. A descendant in a shared outside group never grants permission to stop that whole group. Partial edits may need repair. This is stop-and-resume, not live stdin streaming. A first run must emit its resumable session ID before it can be interrupted; until then the request waits safely. It never stops another entry's run.
|
|
337
|
+
|
|
338
|
+
The fixed buttons never send or discard the composer's draft. Messages are limited to 4,000 characters and one outstanding request per entry. Requests survive restarts and show queued, applying, applied or failed on the page and in `gallivant why`. The registry retains the previous 20 requests; **Last submitted message → Edit and resend** recovers a message even after another fixed action. Failed delivery restores it into an empty composer without overwriting a newer draft. A request interrupted while applying is not automatically replayed, because it might already have started a run.
|
|
339
|
+
|
|
340
|
+
A live daemon running older code is refused before a request is saved, by both the CLI and the UI. Restart it with `gallivant down && gallivant up`, then submit again; active agent runs survive that restart. The daemon must be running and its health probes must pass. CLI requests start it unless `--no-daemon` is used; the UI saves the request and waits. With the default poll interval, pickup takes up to about two minutes plus probe/GitHub response time; queued delivery also waits for the active run. After upgrading, restart the daemon and the process serving the tracker, including Command Center if mounted there, to load the new controls. No Telegram transport is implemented by these controls.
|
|
341
|
+
|
|
342
|
+
Hosted Agents uses the same task/session controls but requires a clean source
|
|
343
|
+
snapshot before implementation resumes. Commit intended unfinished edits on the
|
|
344
|
+
owned task branch first; only exact approved brief/carried-source overlays can
|
|
345
|
+
remain uncommitted. It refuses `AGENTS_DIRTY_SOURCE` rather than dropping or
|
|
346
|
+
silently uploading work. Hosted cancellation is confirmed through the provider;
|
|
347
|
+
Agents does not expose local-process interrupt. See [Agents recovery](openai-agents.md).
|
|
348
|
+
|
|
349
|
+
### Runs from other tools
|
|
350
|
+
|
|
351
|
+
A host can point the tracker at run folders it does not own, through `runSources` on the context it passes to
|
|
352
|
+
`mount`: a list of `{ label, dir }`. Command center writes the same `job.json` and `job.log` under
|
|
353
|
+
`<project>/.content-pipeline/runs/`, which is where Gallivant's runner came from, so those runs list and stream in
|
|
354
|
+
the same table with no conversion. They are listed and opened by their source label, never by a registry id, since
|
|
355
|
+
there is no registry outside Gallivant's own tree; a label that is not in the configured list reaches no directory.
|
|
356
|
+
|
|
357
|
+
### Running it inside another server
|
|
358
|
+
|
|
359
|
+
`gallivant serve` is one way to run the tracker, not the only one. The same router can be mounted inside a server you already start, so one process and one port serve both and there is no second thing to supervise:
|
|
360
|
+
|
|
361
|
+
```js
|
|
362
|
+
import { mount } from "@uchibeke/gallivant/lib/commands/serve.mjs";
|
|
363
|
+
import { makeContext } from "@uchibeke/gallivant/lib/context.mjs";
|
|
364
|
+
|
|
365
|
+
const tracker = mount(makeContext(), { base: "/gallivant" });
|
|
366
|
+
|
|
367
|
+
createServer((req, res) => {
|
|
368
|
+
if (tracker.owns(req)) return tracker.handle(req, res);
|
|
369
|
+
// ... the host's own routes
|
|
370
|
+
}).listen(8790, "127.0.0.1");
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
`owns(req)` is true for the prefix and anything under it; `handle(req, res)` serves it, including its own 404, its assets and the log stream. Every URL the pages emit is built from the mount path, so nothing is hardcoded to the root and the same code serves `/run?id=` standalone and `/gallivant/run?id=` mounted.
|
|
374
|
+
|
|
375
|
+
Two things become the host's responsibility, because a mounted router cannot enforce them:
|
|
376
|
+
|
|
377
|
+
- **The bind address.** Standalone, the tracker binds `127.0.0.1` itself and cannot be reached from another machine. Mounted, it answers wherever the host answers, so a host on `0.0.0.0` publishes the tracker too.
|
|
378
|
+
- **Auth.** Nothing in the tracker asks who is calling. A host with a sign-in should check it before handing the request over, which also gives the tracker auth it does not have on its own.
|
|
379
|
+
|
|
380
|
+
Mounting on the same origin is worth preferring for a second reason: the `--gv-*` properties below only work across the same origin, so a same-origin host can restyle the tracker to match itself.
|
|
381
|
+
|
|
382
|
+
### Embedding it in a page
|
|
383
|
+
|
|
384
|
+
`?theme=dark` or `?theme=light` on the iframe src forces the palette. Pass it from a parent that knows its own theme, because `prefers-color-scheme` inside an iframe follows the browser rather than the page that framed it, and a dark dashboard otherwise gets a light frame.
|
|
385
|
+
|
|
386
|
+
Every colour, font and spacing value in `templates/tracker/tracker.css` is a `--gv-*` custom property with a default. A page on the same origin can override them and restyle everything. A page on another origin (a host on another port is another origin) cannot reach into this document at all, whatever the properties are named, which is why the query parameter exists.
|
|
387
|
+
|
|
388
|
+
The tracker brings its own sidebar, filter and grouping, so it does not need a host's chrome around it. Give it a page or a full-height frame rather than a panel.
|
|
389
|
+
|
|
390
|
+
The log pane sends the last 400 lines when it opens and says how many earlier ones it is not showing. It reconnects on its own and resumes where it left off rather than starting again. It follows the log file rather than the harness process, so it works for a run the daemon started before its last restart, and it auto-scrolls only while you are already at the bottom.
|
|
391
|
+
|
|
392
|
+
**Reaching back.** A **load earlier lines** button above the pane fetches the previous 400 and prepends them, and keeps going back on each press until the run's first line. That is the whole run, not only what happened since you opened the page: `job.log` is written once per run and never rotated, so the file on disk holds every line between the run's start and its stop, and the button walks all of it. Your scroll position does not move when lines are inserted above it.
|
|
393
|
+
|
|
394
|
+
Why a button and not simply a bigger tail: delivering thousands of lines as individual server-sent events on open stalls the browser badly enough that it drops the connection and retries, forever. So reaching back is a plain read (`/api/run/history`) rather than a mode of the stream, one bounded window per request.
|
|
395
|
+
|
|
396
|
+
The pane keeps 2000 live rows and drops the oldest beyond that, because an unbounded stream would otherwise grow the DOM forever. Lines you loaded with the button are exempt: the budget grows by exactly what you loaded, and the rows that get dropped are the oldest **live** ones rather than the top of the pane, so a burst of new output cannot undo a press of the button. The whole log is still in the run folder either way.
|
|
397
|
+
|
|
398
|
+
### What the log pane shows
|
|
399
|
+
|
|
400
|
+
A run's `job.log` is the harness's own stream-json, one event per line, so printing it raw gave you `{"type":"assistant","message":{"content":[{"type":"tool_use",...` down the page. The pane reads each event and draws it the way command-center's runner panel draws its logs, using the same CSS class names, so the two panels look like one system:
|
|
401
|
+
|
|
402
|
+
- A tool call is the tool's name in a fixed-width column on the left and one argument beside it: whichever of `command`, `file_path`, `pattern`, `url`, `description` or `prompt` the call carried. Searches, fetches, writes, shell and subagent calls are coloured apart.
|
|
403
|
+
- Prose the model wrote reads as prose, with its markdown rendered. Inline: bold, italic, inline code and links. Blocks: a run of bullets or numbers becomes one list, a fenced block becomes one `<pre>` with its contents left exactly as typed, a GitHub-style pipe table becomes a table that scrolls sideways inside its own box rather than widening the pane, a run of `>` lines becomes one blockquote, and `---` on a line of its own becomes a rule. A heading is already its own row, so it renders as the row's text in bold rather than keeping its hashes. This matters most on the final summary, which in practice is a report with a table of what passed and fenced blocks of commands to run.
|
|
404
|
+
- Nothing inside a fence is markdown, which is the point of a fence: the inline pass reads a `*` as emphasis and would delete the asterisks from a glob or a pointer. A language tag on the fence is kept as a label and nothing else, and only when it is a plain word; no highlighter is loaded, because the CSP is `script-src 'self'`.
|
|
405
|
+
- A block the model left half-written degrades to what it holds. An unclosed fence shows the code that did arrive, marked as still open, rather than swallowing the rest of the report. A row of pipes with no `|---|` separator under it is not a table and is shown as the line it is.
|
|
406
|
+
- Tool arguments are left alone, where a `*` is a glob and an `_` is part of a filename. No markdown library: the part of CommonMark it would add is the part that never appears here, and HTML passthrough is the one thing this must not have on agent output. Nesting inside a list is an indent rather than a list inside a list, which is the deliberate limit: a tree built out of agent output fails by swallowing siblings.
|
|
407
|
+
- A tool call your guardrails blocked gets the loudest row the stylesheet has, in the failure colour, labelled `BLOCKED`, with the policy reason on it. APort's `PreToolUse` hook denies and Claude Code returns the denial as the tool's result, so this is the row that tells you a passport stopped the run from doing something, and it is not supposed to be easy to scroll past.
|
|
408
|
+
- A tool result that failed is a row in the failure colour. One that succeeded is not shown: it is what the run read, not what it did, and the whole output is in the run folder.
|
|
409
|
+
- The run's last event closes the pane with the verdict, the cost the harness reported, and the reason when it failed.
|
|
410
|
+
- A call that has not returned counts up on its own row. Claude Code sends a heartbeat every 30 seconds for a tool still running, and one `npm ci` in the run tree this was built against collected fourteen of them. They are not fourteen rows: the `Bash` row you are already looking at gains `running 4m 30s` and keeps it current, so a build sitting for six minutes says so instead of showing nothing.
|
|
411
|
+
- Anything the reader cannot place is shown as itself, verbatim. A truncated write from a killed run, a harness spilling to stderr, a runner line: they stay on screen, escaped, in monospace and marked apart from the model's prose, because an unreadable line is still evidence. They deliberately skip the markdown pass. A `*` or an `_` pair in `Error: --add-dir *cannot* be used with __proto__` is not emphasis, and reading it as emphasis deleted the characters that mattered.
|
|
412
|
+
|
|
413
|
+
Reading events is per-harness, since each CLI's stream is its own shape, and it lives in `lib/harness_log.mjs` next to the adapters in `lib/harness.mjs` that already have to know these streams to read a run's outcome.
|
|
414
|
+
|
|
415
|
+
Claude Code and Codex were read off real captured runs, so their tool calls, prose and closing lines all render. Gemini, opencode and goose read only the events their adapter's `outcome` already proves exist (the session line, assistant prose, the closing event) and fall through to raw lines for everything else, which today means their tool calls still show as JSON. Guessing at field names nobody here has captured would put a confident row on screen with an invented argument in it and nothing to mark it as invented; a raw line at least says what the harness wrote. Capture one run each and extend `lib/harness_log.mjs`.
|
|
416
|
+
|
|
417
|
+
A run from a foreign tree (`runSources`) has no harness name, so its lines go through the prose rules, which is right for command-center's own logs.
|
|
418
|
+
|
|
419
|
+
## `gallivant why <handle>`
|
|
420
|
+
|
|
421
|
+
For a stopped or running PR: state and reason, the PR and checkout paths, the base branch, the session id and the by-hand command to open it (`claude --resume <id>` or `codex resume <id>` in the checkout), the last dispatched event, the run folder and exit code, cost when the harness reports it, permission denials, the harness's final message, and any APort audit lines from the run's time window.
|
|
422
|
+
|
|
423
|
+
It also reports every merge the daemon made into this branch, with the commit and the time, because an operator reading
|
|
424
|
+
a diff they did not expect needs to know where the extra commit came from. A merge that failed is reported too, with
|
|
425
|
+
the conflict git gave and the fact that it was aborted, so the checkout is known to be clean. History is only ever
|
|
426
|
+
added to: no rebase, no force-push. See [keeping a branch on its base](config.md#keeping-a-branch-on-its-base).
|
|
427
|
+
|
|
428
|
+
When the brief has changed since the run started it prints every difference, one line each, what the completion gate is doing about it (nothing: neither brief is judged while it is in dispute) and the command that resolves it. This is where the whole difference goes, because a `status` row has space for one line of it and five changed criteria do not fit. It prints for a running entry as well as a stopped one, since you will ask `why` before the daemon's next tick has had a chance to stop anything. It also reports whether the brief was re-readied, by comparing the `aport_decision` in the frontmatter with the one recorded at `start`: a changed id means you put the edit through `gallivant ready`, which is worth knowing and is never what decides the verdict. See [editing the brief after the work has started](prd.md#editing-the-brief-after-the-work-has-started).
|
|
429
|
+
|
|
430
|
+
An entry whose tick is waiting on one GitHub write also gets a line naming that write and how many ticks it has failed, so a PR that looks idle says why it is idle. `status` says the same thing on its row. After five consecutive failures the entry stops with reason `stuck` and `last event` carries the write and GitHub's own message, which is usually a token permission: `Resource not accessible by personal access token` on a body write means the token cannot edit PR descriptions, on a label write that it cannot edit issues, and on a comment that it cannot write to the PR conversation. Fix the token, then `gallivant register <pr-url>` to resume.
|
|
431
|
+
|
|
432
|
+
The writes that can put an entry there, and what each one is holding up:
|
|
433
|
+
|
|
434
|
+
| `retry.op` | What it is holding up |
|
|
435
|
+
|---|---|
|
|
436
|
+
| `ready label removal` | a fix round for new feedback, or judging a head that just moved, while the PR still says a human may merge |
|
|
437
|
+
| `PR #<n> block write` | a start run leaving `running`, so the PR is open but not yet watched |
|
|
438
|
+
| `ready label write` | nothing: every readiness condition passed and only the label saying so will not write |
|
|
439
|
+
| `round comment` | announcing a round that is already counted. The push landed and the budget was charged for it; the PR has not been told, and until it is, the re-review has not been asked and the entry judges nothing |
|
|
440
|
+
|
|
441
|
+
`ready label write` is the one worth reading twice. The work is done and the PR is finished; what is missing is the label a person looks for. `why` says so in as many words, and `status` labels that row `blocked` rather than `fixing`, because nothing is being fixed.
|
|
442
|
+
|
|
443
|
+
`round comment` is the other one. The round it announces is already counted, so the registry is one round ahead of what the PR says, and the count on the PR is what a recovery after a lost `state.json` rebuilds from. `why` prints both numbers: which round is counted, and how many a recovery would find until the comment posts. The gap is at most one round, and it closes the moment the comment lands.
|
|
444
|
+
|
|
445
|
+
## `gallivant resume <handle> [--note "..."] [--resnapshot] [--fresh-session]`
|
|
446
|
+
|
|
447
|
+
Puts a stopped entry back to work in the session that was doing it. The handle is the id, a PRD path, or `<repo>#<pr>`,
|
|
448
|
+
the same forms `why` takes.
|
|
449
|
+
|
|
450
|
+
This exists because of a real run. A start run spent its budget and stopped before opening a pull request, so the entry
|
|
451
|
+
went to `needs-human` with reason `no-pr`. The session id, the worktree and the brief were all recorded, but `register`
|
|
452
|
+
needs a pull request to attach to, so the one case where a run dies before its PR exists had no way back.
|
|
453
|
+
|
|
454
|
+
It resumes rather than restarts: the session holds what the last run learned, so a fresh one would pay for that work
|
|
455
|
+
twice and could undo half-finished edits it knows nothing about. The prompt says why the last run stopped, because the
|
|
456
|
+
agent's memory ends mid-task and that is the one thing it cannot know. `--note` adds a line of your own, which is where
|
|
457
|
+
"the budget is now higher" belongs.
|
|
458
|
+
|
|
459
|
+
An entry with no session is refused unless durable execution state proves that the
|
|
460
|
+
initial launch was never submitted and its approved brief is available. In that
|
|
461
|
+
case, resume can safely retry the initial launch after its prerequisites are fixed.
|
|
462
|
+
Unknown submission state must be reconciled, not bypassed by a new `start`. A run
|
|
463
|
+
already in flight or still awaiting daemon settlement also blocks resume, since
|
|
464
|
+
replacing its record would lose its outcome. A missing checkout is
|
|
465
|
+
recreated from the branch first; the session's memory lives in the harness, not the directory.
|
|
466
|
+
|
|
467
|
+
When the checkout is clean, the base branch is merged in before the session carries on, which is the case that needs it most: an entry stopped
|
|
468
|
+
hours or days ago and the base has moved since. The session is told about the merge commit so it does not try to undo a
|
|
469
|
+
commit that is not its own. A merge that conflicts is aborted and the resume is refused, printing the conflict and the
|
|
470
|
+
`git merge` command that resolves it, so nothing is resumed into a checkout with conflict markers in it. See [keeping a
|
|
471
|
+
branch on its base](config.md#keeping-a-branch-on-its-base).
|
|
472
|
+
|
|
473
|
+
A dirty checkout is preserved: the resumed session is explicitly told to commit only its task changes, fetch and merge the intended base into the task branch, resolve conflicts within scope, then verify and push. Unrelated edits that prevent the merge must be reported rather than discarded or committed. This exception does not authorize merging a PR, writing to the base, rebasing or force-pushing.
|
|
474
|
+
|
|
475
|
+
So is an entry whose brief has changed, and that refusal is the opposite of what a resume usually does. The session
|
|
476
|
+
holds what the last run learned, and what it learned is the OLD brief: resuming into a changed contract would put a
|
|
477
|
+
session that believes one thing back to work while the gate judges another, and nobody would be told. The refusal names
|
|
478
|
+
every difference. `--resnapshot` is the deliberate answer to it: the edited brief becomes the one the gate judges, the
|
|
479
|
+
replacement is logged as a warning naming the file and what moved, the brief is copied into the session's checkout, and
|
|
480
|
+
the prompt tells the session what changed and to reread it rather than trust its memory. A brief that no longer passes
|
|
481
|
+
the contract, or one that has been deleted, is refused even with the flag, because neither can become the copy the gate
|
|
482
|
+
judges. An edit outside the contract needs no flag at all and says nothing to the session. See [editing the brief after
|
|
483
|
+
the work has started](prd.md#editing-the-brief-after-the-work-has-started).
|
|
484
|
+
|
|
485
|
+
The same rule covers the bytes of every carried `sources` file and changes to the manifest. `--resnapshot` records
|
|
486
|
+
the accepted files, copies them into the checkout and tells the session what moved. Remove a deleted file from the
|
|
487
|
+
manifest before accepting that deletion. A harness change is refused even with `--resnapshot`; an existing session
|
|
488
|
+
cannot move between harnesses. When resuming a ready PR, removing its ready label is a precondition of spawning work.
|
|
489
|
+
|
|
490
|
+
If timeout or interruption cannot verify the owned process tree, the task becomes `needs-human` with reason `run-stop-unverified`. Its PR labels and notification identify the stop; failed label writes retry even while the process may still be running. Inspect `gallivant why` and the daemon log, restore process inspection, and resolve any surviving owned processes before resuming. No replacement starts over an unverified writer.
|
|
491
|
+
|
|
492
|
+
The daemon comes up if it is not already running, for the same reason `start` brings it up.
|
|
493
|
+
|
|
494
|
+
`--fresh-session` is a narrow learning-revocation recovery operation: after the
|
|
495
|
+
owned run settles, replace provider memory carrying retired learned advice while
|
|
496
|
+
preserving the approved brief, checkout, PR, review progress and allowance. It
|
|
497
|
+
requires recorded learned context or its revocation, and does not reset task state
|
|
498
|
+
or bypass cancellation. See [learning recovery](learning.md).
|
|
499
|
+
|
|
500
|
+
## `gallivant recheck <handle>`
|
|
501
|
+
|
|
502
|
+
Queue a new evaluation of an existing PR's checks, review and completion gate.
|
|
503
|
+
This keeps the review budget and processed-check markers. It does not restart CI,
|
|
504
|
+
resume a failed agent or remove a cancellation fence. Execution/connectivity
|
|
505
|
+
failures require the existing recovery path or explicit `resume`. See
|
|
506
|
+
[rechecking and updating a run](#rechecking-and-updating-a-run).
|
|
507
|
+
|
|
508
|
+
## `gallivant say <handle> --note "..." [--interrupt]`
|
|
509
|
+
|
|
510
|
+
Queue instructions for the same session, including a correction after the PR is
|
|
511
|
+
ready for review. Normally delivery waits for the active run to settle.
|
|
512
|
+
`--interrupt` requests verified stop-and-resume where supported; it is not live
|
|
513
|
+
stdin streaming and hosted Agents refuses that local-process interrupt operation.
|
|
514
|
+
Messages cannot silently replace an approved brief; contract/source changes need
|
|
515
|
+
`resume --resnapshot`. Closed/merged PRs need a new task.
|
|
516
|
+
|
|
517
|
+
## `gallivant cancel <handle>`
|
|
518
|
+
|
|
519
|
+
Fence further dispatch immediately, then let the coordinator request cancellation
|
|
520
|
+
of the owned execution. A provider may leave cancellation unconfirmed; inspect
|
|
521
|
+
`why` and status before assuming work or billing has stopped. The PR, branch and
|
|
522
|
+
files are preserved. This differs from `down`, which stops monitoring services
|
|
523
|
+
while leaving active agent processes running.
|
|
524
|
+
|
|
525
|
+
Recheck, message and cancel requests are durable. Their CLI commands start the
|
|
526
|
+
daemon unless `--no-daemon` is passed; avoid resubmitting a saved request after a
|
|
527
|
+
daemon-start error. The dashboard uses the same control service and displays
|
|
528
|
+
queued, applying, applied or failed status.
|
|
529
|
+
|
|
530
|
+
## `gallivant remove <handle>`
|
|
531
|
+
|
|
532
|
+
Forgets an entry. The PR, its branch, its labels and the checkout are left as they are; `register` puts the PR back into the loop. Use it for an entry that was started against the wrong repo or that you have taken over by hand.
|
|
533
|
+
|
|
534
|
+
## Learning commands
|
|
535
|
+
|
|
536
|
+
**Current production status: collection only.** These commands expose the learning
|
|
537
|
+
workflow, but installed profiles do not qualify secure extraction or activation.
|
|
538
|
+
`setup`, `extract` and apply/approval paths refuse missing isolation prerequisites.
|
|
539
|
+
No command, hash, config switch or file mode makes candidate text trusted. Review
|
|
540
|
+
[learning](learning.md) for exact qualification, signing and recovery boundaries.
|
|
541
|
+
|
|
542
|
+
`learn reject` and `learn retire` require a nonempty `--reason`; `learn approve`
|
|
543
|
+
accepts an optional reason. Learning output is escaped JSON, with or without
|
|
544
|
+
`--json`. The CLI reports exit 1 for exceptions and an explicitly unqualified
|
|
545
|
+
`learn doctor` result. An unavailable extraction result can return exit 0 with
|
|
546
|
+
`status: "unavailable"` and `inference: false`; inspect the result, not only the
|
|
547
|
+
exit status.
|
|
548
|
+
|
|
549
|
+
All repository operations use `--repo owner/repository`. Configure `collect` before
|
|
550
|
+
inspecting local learning state. The collector reads eligible GitHub feedback;
|
|
551
|
+
it never opens embedded evidence links or runs that text as instructions.
|
|
552
|
+
|
|
553
|
+
| Command | Purpose |
|
|
554
|
+
|---|---|
|
|
555
|
+
| `gallivant learn configure --repo owner/repo --mode collect` | Enable repository-scoped collection. `off` disables it; `apply` requires qualification. |
|
|
556
|
+
| `gallivant learn --repo owner/repo [--since YYYY-MM-DD] [--until YYYY-MM-DD] [--dry-run]` | Collect historical feedback with durable continuation; `learn collect` is the explicit equivalent. Dry-run performs no learning writes or inference. |
|
|
557
|
+
| `gallivant learn doctor [--repo owner/repo]` | Report qualification and signing prerequisites. |
|
|
558
|
+
| `gallivant learn list --repo owner/repo [--status pending]` | List candidate revisions. |
|
|
559
|
+
| `gallivant learn show ID --repo owner/repo --revision SHA256` | Inspect the exact revision and evidence. |
|
|
560
|
+
| `gallivant learn revise ID --repo owner/repo --from reviewed-rule.json` | Validate data and create a new unapproved revision. |
|
|
561
|
+
| `gallivant learn reject ID --repo owner/repo --revision SHA256 --reason "..."` | Reject that exact revision. |
|
|
562
|
+
| `gallivant learn report --repo owner/repo` | Report coverage, limits and stored learning state. |
|
|
563
|
+
| `gallivant learn prune --repo owner/repo` | Remove expired retained excerpts. |
|
|
564
|
+
| `gallivant learn explain --repo owner/repo --run RUN_ID` | Inspect recorded learned-context selection and delivery for a run. |
|
|
565
|
+
| `gallivant learn setup --key-path ABSOLUTE_PATH [--ssh-keygen ABSOLUTE_PATH]` | Interactive signing-authority enrollment; requires qualified isolation. |
|
|
566
|
+
| `gallivant learn extract --repo owner/repo --learning-budget USD` | Request bounded paid candidate extraction; no production extractor is qualified in this release. |
|
|
567
|
+
| `gallivant learn approve ID --repo owner/repo --revision SHA256 [--reason "..."]` | Preview and sign an exact activation transition when qualified. No approve-all or noninteractive approval bypass exists. |
|
|
568
|
+
| `gallivant learn retire ID --repo owner/repo --revision SHA256 --reason "..."` | Request a signed retirement transition when qualified. |
|
|
569
|
+
| `gallivant learn recover --repo owner/repo` | Reconcile signed transitions and retry revocation controls; never invents or rebases approval. |
|
|
570
|
+
|
|
571
|
+
Inspection commands do not launch inference. Every candidate revision remains
|
|
572
|
+
unapproved until the exact protected signing workflow succeeds. Learning never
|
|
573
|
+
changes task permissions, budgets, acceptance gates or the human merge boundary.
|
|
574
|
+
|
|
575
|
+
## What the daemon posts on your behalf
|
|
576
|
+
|
|
577
|
+
- A round comment after every push: the text of `reviewer.rereview_comment`, `@codex review` by default, with an HTML marker so it can recognise its own comments; a marked "Completion receipt updated" comment after a round that only rewrote the receipt; a marked reset comment when `register` resets an entry.
|
|
578
|
+
- One nudge comment if the reviewer has not answered within `rereview_minutes`. It is the same text as the round comment, told apart only by its marker, so it never goes out on the tick that already posted a round: one push earns one asking of the reviewer.
|
|
579
|
+
- With `reviewer` set to null nothing asks anyone for anything: the round comment says `Pushed a fix.` and there is no nudge.
|
|
580
|
+
- The labels `status:ready-for-review` and `status:needs-attention`, created once per repo the first time it is watched. Ready means checks, reviewer and receipt gates passed; it does not mean merged or complete. Label writes remove legacy spellings and the opposite status before signalling the new state.
|
|
581
|
+
- A neutral `work-session` recovery record in the PR body. It contains a versioned base64url JSON identity, with strict decoded validation. This is transport encoding, not encryption or authorization.
|
|
582
|
+
- Nothing else. The harness posts its own thread replies during a fix run; those are recognised and never treated as events.
|
|
583
|
+
|
|
584
|
+
|
|
585
|
+
### Public formatting and compatibility
|
|
586
|
+
|
|
587
|
+
New branches use `work/<prd-id>`, receipts use a `work-attestations` JSON fence, and daemon comments use
|
|
588
|
+
neutral `work-round`, `work-nudge` and `work-reset` markers. Human follow-up can use `/fix`.
|
|
589
|
+
Legacy branches, recovery blocks, receipt fences, commands and comment markers remain readable; existing
|
|
590
|
+
branches and sessions are not renamed. Round/reset history still counts across formats, and changing only
|
|
591
|
+
a receipt's transport format or informational task ID does not constitute progress.
|
|
592
|
+
|
|
593
|
+
Recovery metadata preserves exact PRD paths, branch names and session IDs in its encoded record, including
|
|
594
|
+
old identifiers; decoding does not grant trust. Recovery still checks the actual same-repository head and
|
|
595
|
+
validated harness/session. Receipt task IDs are stable neutral tokens; the completion gate binds evaluation
|
|
596
|
+
to its own trusted task ID. Prose and evidence are not redacted or altered by format migration, and ambiguous
|
|
597
|
+
duplicate metadata or receipts must be repaired rather than silently choosing one.
|
|
598
|
+
|
|
599
|
+
Existing branch names and historical commits/comments can still expose earlier naming. Upgrading does not
|
|
600
|
+
rewrite history or rename live branches. Existing integrations that select the old status labels should move
|
|
601
|
+
to the new labels; no branded alias is written merely to keep an external label filter matching.
|
|
602
|
+
|
|
603
|
+
|
|
604
|
+
Managed pull requests use GitHub's regular review workflow. Start prompts require an ordinary PR; if a harness
|
|
605
|
+
nevertheless creates a draft, the daemon converts it to ready for review and gives the reviewer a fresh window.
|
|
606
|
+
Registering an existing PR explicitly adopts the same regular-PR policy. This presentation change does not mark
|
|
607
|
+
work complete, satisfy acceptance criteria, waive checks or review, merge the PR, or clear an unrelated stop.
|
|
608
|
+
Incomplete work remains accurately described with unmet attestations.
|
|
609
|
+
|
|
610
|
+
Daemon-authored title, body and comment writes reject the runner name case-insensitively. The daemon checks the
|
|
611
|
+
actual published PR title/body and new own-account replies before marking work ready; violations request a bounded
|
|
612
|
+
wording correction in the existing session. New commits are checked by the installed commit-message hook. Technical
|
|
613
|
+
source files, PRD basenames, local commands and existing history keep their actual names; they are not renamed or
|
|
614
|
+
rewritten to satisfy a public-text rule. Choose a truthful neutral description or another concrete evidence pointer
|
|
615
|
+
when a literal path would name the runner in PR prose.
|
|
616
|
+
|
|
617
|
+
Harnesses still invoke their own GitHub tools directly. A prompt and a later daemon check cannot promise that an
|
|
618
|
+
incorrect draft or branded phrase never appears briefly before correction. This implementation enforces daemon
|
|
619
|
+
writes and readiness, not an exclusive network publication boundary. The encoded recovery record is also not secret:
|
|
620
|
+
it can be decoded to inspect the precise existing branch/session identity.
|