ward agent <name> task ... should #164

Closed
opened 2026-06-18 05:34:54 +00:00 by coilysiren · 3 comments
Owner

ward agent <name> task - rough-idea-in, routed-PR-out

Original ask

  • take the task as an argument, and remove the repo, so ward agent <name> task ... 'do dishes'
  • populate the literal input into https://forgejo.coilysiren.me/coilysiren/inbox - this replaces the repo
  • be given a "find the correct repo, and then..." path instruction, so it files the issue above ^ and then is expected to file another issue immediately after in the correct repo after looking through them. that probably means we need to mount at least thin knowledge of every repo???

Resolved design (settled with Kai, 2026-06-18)

The ??? fork is closed. The cross-repo knowledge does not need new infra: every ward agent container is already handed a Forgejo token, so the agent surveys repos live via the Forgejo API rather than mounting any snapshot. Decisions:

  • Repo knowledge - live Forgejo API. No mount. List repos across the four primary orgs (coilysiren, coilyco-bridge, coilyco-flight-deck, coilyco-gaming) for name + description, then fetch a shortlisted repo's README / docs/FEATURES.md / AGENTS.md on demand. Always-fresh, no stale daily snapshot, no private file crossing into the container. (Rejected: agentic-os-kai/data/repo-registry.md / repo-digests snapshots - staleness + private-mount. Rejected: repo-recall - loopback-bound, local-only, unreachable from an ephemeral container.)
  • Output - two issues, cross-linked. The inbox issue is the intake record; the agent files a second, well-scoped issue in the correct repo and cross-links both, then closes the intake issue.
  • After routing - carry to merge. Routing is the front half; the agent then runs the normal headless work flow against the freshly-scoped child issue and carries it to a PR/merge. One command: rough idea in, PR out.
  • Surface - repo-omission on task. No new verb. Omitting owner/repo triggers ROUTE mode; passing an explicit owner/repo keeps today's DIRECT behavior.

Behavior

Invocation

  • ward agent <name> task 'do dishes' - positional instructions, no repo -> ROUTE mode. (Positional is shorthand for -i; --instructions / --instructions-file still accepted.)
  • ward agent <name> task <owner/repo> -i '...' - explicit repo -> DIRECT mode, today's behavior unchanged (file the issue in that repo, pre-flight, headless).
  • Trigger rule: ROUTE mode fires when no explicit owner/repo is given. In ROUTE mode task does not fall back to cwd git-origin inference (that inference only applies to DIRECT mode). This is the literal "remove the repo" from the original ask.
  • --print works in both modes: ROUTE --print shows the intake issue that would be filed in coilysiren/inbox + the route seed, and files/fires nothing.

ROUTE flow

  1. File intake. ward files the literal instructions into coilysiren/inbox (a trusted primary-org owner, so ward agent already accepts it). Title from the first line (existing taskTitle); body = instructions + provenance footer Filed by ward agent task (unrouted intake).. Apply a routing/unrouted label if it exists in the repo.
  2. Route. An agent survey picks the single best-fit repo from the live Forgejo API (descriptions first, then README/FEATURES/AGENTS for the shortlist). Read-only.
  3. Consult exit. If no repo clearly fits, or several are plausible and the choice is genuinely ambiguous, the agent does not guess: it comments the candidate set + reasoning on the intake issue and stops. This mirrors the existing pre-flight NO-GO/consult posture (ward#147, ward#149) - fail-closed to "a human decides."
  4. Refile. In the chosen repo, file a new, well-scoped issue: clear title, restated/expanded body, acceptance criteria, and a Routed from coilysiren/inbox#N provenance line.
  5. Cross-link + close intake. Comment Routed to <owner/repo>#M - <url> on the intake issue, then close it. Work continues in the child.
  6. Carry. Run the standard headless work flow against the child issue end-to-end (branch, implement, PR, merge), closing the child on merge.

Orchestration (implementation note, not a hard contract)

The forks above are the behavioral contract. The orchestration shape is an internal, reversible choice for the implementer. Recommended path, reusing existing machinery end-to-end:

  1. Host: ward files the intake issue (plain Forgejo API write).
  2. Host: run the route survey as a one-shot pre-flight-style agent call (the same host self-assessment slot claude/goose already have - agent.go ~L423). It returns structured {repo, title, body, confidence} or {consult, reason}. Read-only, low-risk on the host.
  3. Host: on consult/low-confidence -> comment on intake, stop (same exit as a NO-GO).
  4. Host: ward files the child issue, comments the cross-link on intake, closes intake (plain API writes - no agent needed).
  5. Host: launch the standard headless carry container against owner/repo#M, fresh-cloning exactly the right repo. Zero new container logic; the carry is the existing flow.

Alternatives if host-side routing is undesirable: (a) single container that clones the intake repo, then git clones the chosen repo in-container and works there; (b) a two-container chain (container A routes + refiles + emits the child ref, ward then spins the standard carry container B). Both reach the same behavior.

Parity caveat (ward#148)

Host-side routing leans on the host self-assessment slot, which today exists for claude + goose but not codex + qwen (agent.go ~L423-426). For codex/qwen, either route in-container (alternative b above) or have ROUTE mode require an explicit repo until parity lands. Track under the ward#148 parity umbrella.

Acceptance

  • ward agent claude task 'add a dark-mode toggle to the dashboard' (no repo) files an intake issue in coilysiren/inbox, routes to the correct repo, files a scoped child issue there, cross-links + closes the intake, and carries the child to a PR.
  • ward agent claude task coilyco-flight-deck/ward -i '...' behaves exactly as today (DIRECT mode, no routing).
  • An unroutable/ambiguous task leaves the intake issue open with a consult comment and launches no carry.
  • --print in ROUTE mode files and fires nothing.
  • Parity covered (codex/qwen) or explicitly deferred to ward#148.
# `ward agent <name> task` - rough-idea-in, routed-PR-out ## Original ask - take the task as an argument, and remove the repo, so `ward agent <name> task ... 'do dishes'` - populate the literal input into https://forgejo.coilysiren.me/coilysiren/inbox - this replaces the repo - be given a "find the correct repo, and then..." path instruction, so it files the issue above ^ and then is expected to file another issue immediately after in the correct repo after looking through them. that probably means we need to mount at least thin knowledge of every repo??? ## Resolved design (settled with Kai, 2026-06-18) The `???` fork is closed. The cross-repo knowledge does **not** need new infra: every `ward agent` container is already handed a Forgejo token, so the agent surveys repos **live via the Forgejo API** rather than mounting any snapshot. Decisions: - **Repo knowledge - live Forgejo API.** No mount. List repos across the four primary orgs (`coilysiren`, `coilyco-bridge`, `coilyco-flight-deck`, `coilyco-gaming`) for name + description, then fetch a shortlisted repo's `README` / `docs/FEATURES.md` / `AGENTS.md` on demand. Always-fresh, no stale daily snapshot, no private file crossing into the container. (Rejected: `agentic-os-kai/data/repo-registry.md` / `repo-digests` snapshots - staleness + private-mount. Rejected: `repo-recall` - loopback-bound, local-only, unreachable from an ephemeral container.) - **Output - two issues, cross-linked.** The inbox issue is the intake record; the agent files a second, well-scoped issue in the correct repo and cross-links both, then closes the intake issue. - **After routing - carry to merge.** Routing is the front half; the agent then runs the normal headless work flow against the freshly-scoped child issue and carries it to a PR/merge. One command: rough idea in, PR out. - **Surface - repo-omission on `task`.** No new verb. Omitting `owner/repo` triggers ROUTE mode; passing an explicit `owner/repo` keeps today's DIRECT behavior. ## Behavior ### Invocation - `ward agent <name> task 'do dishes'` - positional instructions, **no repo** -> ROUTE mode. (Positional is shorthand for `-i`; `--instructions` / `--instructions-file` still accepted.) - `ward agent <name> task <owner/repo> -i '...'` - explicit repo -> DIRECT mode, today's behavior unchanged (file the issue in that repo, pre-flight, headless). - Trigger rule: ROUTE mode fires when **no explicit `owner/repo` is given**. In ROUTE mode `task` does **not** fall back to cwd git-origin inference (that inference only applies to DIRECT mode). This is the literal "remove the repo" from the original ask. - `--print` works in both modes: ROUTE `--print` shows the intake issue that would be filed in `coilysiren/inbox` + the route seed, and files/fires nothing. ### ROUTE flow 1. **File intake.** ward files the literal instructions into `coilysiren/inbox` (a trusted primary-org owner, so `ward agent` already accepts it). Title from the first line (existing `taskTitle`); body = instructions + provenance footer `Filed by `ward agent <name> task` (unrouted intake).`. Apply a `routing`/`unrouted` label if it exists in the repo. 2. **Route.** An agent survey picks the single best-fit repo from the live Forgejo API (descriptions first, then README/FEATURES/AGENTS for the shortlist). Read-only. 3. **Consult exit.** If no repo clearly fits, or several are plausible and the choice is genuinely ambiguous, the agent does **not** guess: it comments the candidate set + reasoning on the intake issue and stops. This mirrors the existing pre-flight NO-GO/consult posture (ward#147, ward#149) - fail-closed to "a human decides." 4. **Refile.** In the chosen repo, file a new, well-scoped issue: clear title, restated/expanded body, acceptance criteria, and a `Routed from coilysiren/inbox#N` provenance line. 5. **Cross-link + close intake.** Comment `Routed to <owner/repo>#M - <url>` on the intake issue, then close it. Work continues in the child. 6. **Carry.** Run the standard headless work flow against the child issue end-to-end (branch, implement, PR, merge), closing the child on merge. ## Orchestration (implementation note, not a hard contract) The forks above are the behavioral contract. The orchestration shape is an internal, reversible choice for the implementer. Recommended path, reusing existing machinery end-to-end: 1. Host: ward files the intake issue (plain Forgejo API write). 2. Host: run the **route survey as a one-shot pre-flight-style agent call** (the same host self-assessment slot `claude`/`goose` already have - agent.go ~L423). It returns structured `{repo, title, body, confidence}` or `{consult, reason}`. Read-only, low-risk on the host. 3. Host: on consult/low-confidence -> comment on intake, stop (same exit as a NO-GO). 4. Host: ward files the child issue, comments the cross-link on intake, closes intake (plain API writes - no agent needed). 5. Host: launch the **standard headless carry container against `owner/repo#M`**, fresh-cloning exactly the right repo. Zero new container logic; the carry is the existing flow. Alternatives if host-side routing is undesirable: (a) single container that clones the intake repo, then `git clone`s the chosen repo in-container and works there; (b) a two-container chain (container A routes + refiles + emits the child ref, ward then spins the standard carry container B). Both reach the same behavior. ## Parity caveat (ward#148) Host-side routing leans on the host self-assessment slot, which today exists for `claude` + `goose` but not `codex` + `qwen` (agent.go ~L423-426). For codex/qwen, either route in-container (alternative b above) or have ROUTE mode require an explicit repo until parity lands. Track under the ward#148 parity umbrella. ## Acceptance - `ward agent claude task 'add a dark-mode toggle to the dashboard'` (no repo) files an intake issue in `coilysiren/inbox`, routes to the correct repo, files a scoped child issue there, cross-links + closes the intake, and carries the child to a PR. - `ward agent claude task coilyco-flight-deck/ward -i '...'` behaves exactly as today (DIRECT mode, no routing). - An unroutable/ambiguous task leaves the intake issue open with a consult comment and launches no carry. - `--print` in ROUTE mode files and fires nothing. - Parity covered (codex/qwen) or explicitly deferred to ward#148.
Author
Owner

🛫 ward pre-flight: NO-GO

ward agent claude headless ran a pre-flight feasibility read on this issue before detaching a fire-and-forget run, and the agent judged it NO-GO - it should not be carried unattended until a human weighs in.

the third requirement (cross-repo "find the correct repo" flow + mounting per-repo knowledge) is an undecided design fork the issue itself flags with question marks - a human should settle the approach before an unattended run.

No container was launched. Review the issue (clarify the scope, resolve the unknown, or split it), then re-dispatch - ward agent claude headless <ref> --no-preflight skips this gate once you've decided it's good to go.

full pre-flight read

The first two bullets are crisp and implementable in ward: take the task literally as an argument, drop the repo param, and blind-file the text into coilysiren/inbox. The third bullet is the wall - it's openly unresolved in the issue itself ("that probably means we need to mount at least thin knowledge of every repo???"), which is a real design fork about how an agent acquires cross-repo knowledge and how the "find the correct repo, then file again" flow should behave. That isn't reversible mechanical work I can default my way through; the wrong shape (e.g. how repo knowledge gets mounted, what "correct repo" inference means) is costly to undo and the author plainly hasn't decided it. I could land bullets 1-2 alone, but the issue reads as one coupled feature, so shipping half unattended risks merging a design the author may not want.

NO-GO: the third requirement (cross-repo "find the correct repo" flow + mounting per-repo knowledge) is an undecided design fork the issue itself flags with question marks - a human should settle the approach before an unattended run.


Posted automatically by ward agent claude headless pre-flight (ward#147, ward#149).

— Claude (she/her), via ward agent

### 🛫 ward pre-flight: NO-GO `ward agent claude headless` ran a pre-flight feasibility read on this issue before detaching a fire-and-forget run, and the agent judged it **NO-GO** - it should not be carried unattended until a human weighs in. > the third requirement (cross-repo "find the correct repo" flow + mounting per-repo knowledge) is an undecided design fork the issue itself flags with question marks - a human should settle the approach before an unattended run. No container was launched. Review the issue (clarify the scope, resolve the unknown, or split it), then re-dispatch - `ward agent claude headless <ref> --no-preflight` skips this gate once you've decided it's good to go. <details><summary>full pre-flight read</summary> The first two bullets are crisp and implementable in ward: take the task literally as an argument, drop the repo param, and blind-file the text into `coilysiren/inbox`. The third bullet is the wall - it's openly unresolved in the issue itself ("that probably means we need to mount at least thin knowledge of every repo???"), which is a real design fork about how an agent acquires cross-repo knowledge and how the "find the correct repo, then file again" flow should behave. That isn't reversible mechanical work I can default my way through; the wrong shape (e.g. how repo knowledge gets mounted, what "correct repo" inference means) is costly to undo and the author plainly hasn't decided it. I could land bullets 1-2 alone, but the issue reads as one coupled feature, so shipping half unattended risks merging a design the author may not want. NO-GO: the third requirement (cross-repo "find the correct repo" flow + mounting per-repo knowledge) is an undecided design fork the issue itself flags with question marks - a human should settle the approach before an unattended run. </details> --- Posted automatically by `ward agent claude headless` pre-flight (ward#147, ward#149). <!-- ward-agent-signature --> — Claude (she/her), via `ward agent`
Author
Owner

Dug into this with Kai. The pre-flight NO-GO was fair: bullet 3's "find the correct repo / mount thin knowledge of every repo???" was a real undecided fork.

Resolved it - the key finding is that the cross-repo knowledge needs no new infra: every ward agent container already holds a Forgejo token, so the agent surveys repos live via the Forgejo API instead of mounting any snapshot. coilysiren is already a trusted primary-org owner, so coilysiren/inbox is a valid target with no allowlist change.

Four forks settled (full spec now in the body): live Forgejo API for repo knowledge, two cross-linked issues (intake + scoped child), carry-to-merge after routing, and repo-omission on task as the trigger (no new verb). Orchestration recommendation is host-side route survey -> ward files the child + closes intake -> standard headless carry container, reusing existing machinery end-to-end. One parity caveat tracked against ward#148 (codex/qwen lack the host self-assessment slot).

Ready to dispatch now - a fresh pre-flight should GO on this.

  • claude-macos-kais-macbook-pro-be41-she-her
Dug into this with Kai. The pre-flight NO-GO was fair: bullet 3's "find the correct repo / mount thin knowledge of every repo???" was a real undecided fork. Resolved it - the key finding is that the cross-repo knowledge needs **no new infra**: every `ward agent` container already holds a Forgejo token, so the agent surveys repos **live via the Forgejo API** instead of mounting any snapshot. `coilysiren` is already a trusted primary-org owner, so `coilysiren/inbox` is a valid target with no allowlist change. Four forks settled (full spec now in the body): live Forgejo API for repo knowledge, two cross-linked issues (intake + scoped child), carry-to-merge after routing, and repo-omission on `task` as the trigger (no new verb). Orchestration recommendation is host-side route survey -> ward files the child + closes intake -> standard headless carry container, reusing existing machinery end-to-end. One parity caveat tracked against ward#148 (codex/qwen lack the host self-assessment slot). Ready to dispatch now - a fresh pre-flight should GO on this. - claude-macos-kais-macbook-pro-be41-she-her
Member

🔒 Reserved by ward agent claude — container ward-ward-issue-164-claude-53b317af on host kais-macbook-pro.local is carrying this issue (reserved 2026-06-18T07:59:31Z). Concurrent ward agent runs are blocked until it finishes or the reservation goes stale (2h0m0s TTL); --force overrides.

— Claude (she/her), via ward agent

<!-- ward-agent-reservation --> 🔒 Reserved by `ward agent claude` — container `ward-ward-issue-164-claude-53b317af` on host `kais-macbook-pro.local` is carrying this issue (reserved 2026-06-18T07:59:31Z). Concurrent `ward agent` runs are blocked until it finishes or the reservation goes stale (2h0m0s TTL); `--force` overrides. <!-- ward-agent-signature --> — Claude (she/her), via `ward agent`
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
coilyco-flight-deck/ward#164
No description provided.