warded dispatch: transient issue-resolve failure surfaces as a bare 'exit status 3' with no cause and no retry #497

Closed
opened 2026-07-02 02:26:14 +00:00 by coilysiren · 4 comments
Owner

Observed (2026-07-02, director surface session, dispatch broker path)

Probing dispatchability with warded <ref> --print through the dispatch broker:

  • coilysiren/website#57 - fails: resolve issue coilysiren/website#57: forgejo: get issue coilysiren/website#57: exit status 3
  • coilyco-bridge/lore#2 - fails the same way
  • coilysiren/coilysiren#15, coilyco-bridge/atlas#11, coilyco-bridge/agentic-os-hardware#22 - all forward fine

So the failure is repo-level, not owner-level: the same owners resolve for sibling repos. Both issues exist and are readable with the container's coilyco-ops token (ward ops forgejo issue view returns them), so this is specific to whatever credential or trust surface host ward resolves issues with on the dispatch path. lore is private-context so a visibility gap is plausible there, but website hosts a P1 (coilysiren/website#59, broken coily-trailer prepare-commit-msg hook) that is currently unreachable from the dispatch surface.

Why filed, not dispatched

The investigation is host-side (host ward's forgejo credential / trust config), which a container engineer cannot reach, and the ward lane is saturated by the milestone-7 burndown (#492). Deliberately not dispatching an engineer.

Suggested next step

From the host: ward agent coilysiren/website#59 --print and compare the forgejo credential host ward resolves against the repo's visibility. If website/lore are intentionally outside the dispatch trust surface, the refusal should say so instead of a bare exit status 3 (adjacent: cli-guard#484).


Filed by the director surface session (claude-linux-68cc49ef38c1-bc38-she-her) while dispatching non-colliding cross-org work during the burndown.

## Observed (2026-07-02, director surface session, dispatch broker path) Probing dispatchability with `warded <ref> --print` through the dispatch broker: * `coilysiren/website#57` - fails: `resolve issue coilysiren/website#57: forgejo: get issue coilysiren/website#57: exit status 3` * `coilyco-bridge/lore#2` - fails the same way * `coilysiren/coilysiren#15`, `coilyco-bridge/atlas#11`, `coilyco-bridge/agentic-os-hardware#22` - all forward fine So the failure is repo-level, not owner-level: the same owners resolve for sibling repos. Both issues exist and are readable with the container's coilyco-ops token (`ward ops forgejo issue view` returns them), so this is specific to whatever credential or trust surface host ward resolves issues with on the dispatch path. lore is private-context so a visibility gap is plausible there, but website hosts a P1 (coilysiren/website#59, broken coily-trailer prepare-commit-msg hook) that is currently unreachable from the dispatch surface. ## Why filed, not dispatched The investigation is host-side (host ward's forgejo credential / trust config), which a container engineer cannot reach, and the ward lane is saturated by the milestone-7 burndown (#492). Deliberately not dispatching an engineer. ## Suggested next step From the host: `ward agent coilysiren/website#59 --print` and compare the forgejo credential host ward resolves against the repo's visibility. If website/lore are intentionally outside the dispatch trust surface, the refusal should say so instead of a bare exit status 3 (adjacent: cli-guard#484). --- Filed by the director surface session (claude-linux-68cc49ef38c1-bc38-she-her) while dispatching non-colliding cross-org work during the burndown.
coilysiren changed title from warded dispatch: issue resolve fails (exit status 3) for coilysiren/website and coilyco-bridge/lore while sibling repos under the same owners resolve to warded dispatch: transient issue-resolve failure surfaces as a bare 'exit status 3' with no cause and no retry 2026-07-02 02:34:11 +00:00
Author
Owner

Correction after retest (same session, ~10 minutes later)

Retesting the exact refs that failed: coilysiren/website#57 and coilyco-bridge/lore#2 both resolve and forward cleanly now, as do website#59, website#2, and lore#1. The failure was transient, not repo-level - the original title's diagnosis was wrong (repo metadata also disproves the visibility theory: lore is private but website is public).

What remains of this issue, reframed by the retest:

  • transient - the dispatch resolve path failed twice in one probe batch and succeeded on every later attempt, so whatever failed (forgejo API hiccup, token fetch race, rate pressure from a rapid probe series) recovered on its own.
  • bare error - the operator-facing failure is forgejo: get issue <ref>: exit status 3 with no cause attached. A director session read that as a hard per-repo wall and wrongly skipped two repos (one holding P1 website#59, since dispatched).
  • no retry - a single transient subprocess failure kills the dispatch instead of retrying the resolve once.

Suggested shape: attach the underlying forgejo error to the message, and retry the resolve once before failing. Downgrade-to-P3 candidate.


Correction by the director surface session (claude-linux-68cc49ef38c1-bc38-she-her).

## Correction after retest (same session, ~10 minutes later) Retesting the exact refs that failed: `coilysiren/website#57` and `coilyco-bridge/lore#2` both resolve and forward cleanly now, as do `website#59`, `website#2`, and `lore#1`. The failure was **transient, not repo-level** - the original title's diagnosis was wrong (repo metadata also disproves the visibility theory: lore is private but website is public). What remains of this issue, reframed by the retest: * transient - the dispatch resolve path failed twice in one probe batch and succeeded on every later attempt, so whatever failed (forgejo API hiccup, token fetch race, rate pressure from a rapid probe series) recovered on its own. * bare error - the operator-facing failure is `forgejo: get issue <ref>: exit status 3` with no cause attached. A director session read that as a hard per-repo wall and wrongly skipped two repos (one holding P1 website#59, since dispatched). * no retry - a single transient subprocess failure kills the dispatch instead of retrying the resolve once. Suggested shape: attach the underlying forgejo error to the message, and retry the resolve once before failing. Downgrade-to-P3 candidate. --- Correction by the director surface session (claude-linux-68cc49ef38c1-bc38-she-her).
Member

Cleared consult→headless (2026-07-07). The retest already collapsed this to a clear two-part code fix on the dispatch resolve path: attach the underlying forgejo error to the message, and retry the resolve once before failing. The transient cause self-recovered, so no host-side decision remains. Dispatching.

Cleared consult→headless (2026-07-07). The retest already collapsed this to a clear two-part code fix on the dispatch resolve path: attach the underlying forgejo error to the message, and retry the resolve once before failing. The transient cause self-recovered, so no host-side decision remains. Dispatching.
Member

🔒 Reserved by ward agent --driver claude — container engineer-claude-ward-497 on host KAI-DESKTOP-TOWER is carrying this issue (reserved 2026-07-07T22:46:44Z). Concurrent ward agent runs are blocked until it finishes or the reservation goes stale (2h0m0s TTL); --force overrides.

Do not comment on or edit this issue to steer the run while it is reserved. The engineer seeded the body once at launch and never re-reads it, so a comment or edit reaches only human readers, never the running engineer. A correction goes to a new issue, dispatched fresh — that is the only channel that reaches a run in flight. Where the forge supports it, ward locks this conversation to make that a road-block rather than a convention (ward#494).

run seed context — what this run is carrying (ward#609)
  • Resolved: coilyco-flight-deck/ward#497 · branch issue-497 · driver claude · workflow direct-main
  • Run: engineer-claude-ward-497 · ward v0.422.0 · dispatched 2026-07-07T22:46:44Z
  • Comment thread: 2 included in the pre-flight read, 0 stripped (ward's own automated comments).

Issue body as seeded:

## Observed (2026-07-02, director surface session, dispatch broker path)

Probing dispatchability with `warded <ref> --print` through the dispatch broker:

* `coilysiren/website#57` - fails: `resolve issue coilysiren/website#57: forgejo: get issue coilysiren/website#57: exit status 3`
* `coilyco-bridge/lore#2` - fails the same way
* `coilysiren/coilysiren#15`, `coilyco-bridge/atlas#11`, `coilyco-bridge/agentic-os-hardware#22` - all forward fine

So the failure is repo-level, not owner-level: the same owners resolve for sibling repos. Both issues exist and are readable with the container's coilyco-ops token (`ward ops forgejo issue view` returns them), so this is specific to whatever credential or trust surface host ward resolves issues with on the dispatch path. lore is private-context so a visibility gap is plausible there, but website hosts a P1 (coilysiren/website#59, broken coily-trailer prepare-commit-msg hook) that is currently unreachable from the dispatch surface.

## Why filed, not dispatched

The investigation is host-side (host ward's forgejo credential / trust config), which a container engineer cannot reach, and the ward lane is saturated by the milestone-7 burndown (#492). Deliberately not dispatching an engineer.

## Suggested next step

From the host: `ward agent coilysiren/website#59 --print` and compare the forgejo credential host ward resolves against the repo's visibility. If website/lore are intentionally outside the dispatch trust surface, the refusal should say so instead of a bare exit status 3 (adjacent: cli-guard#484).

---
Filed by the director surface session (claude-linux-68cc49ef38c1-bc38-she-her) while dispatching non-colliding cross-org work during the burndown.

Static container doctrine and seed boilerplate are identical every run and omitted here (they ride ward v0.422.0).

— Claude (she/her), via ward agent

<!-- ward-agent-reservation --> 🔒 Reserved by `ward agent --driver claude` — container `engineer-claude-ward-497` on host `KAI-DESKTOP-TOWER` is carrying this issue (reserved 2026-07-07T22:46:44Z). Concurrent `ward agent` runs are blocked until it finishes or the reservation goes stale (2h0m0s TTL); `--force` overrides. **Do not comment on or edit this issue to steer the run while it is reserved.** The engineer seeded the body once at launch and never re-reads it, so a comment or edit reaches only human readers, never the running engineer. A correction goes to a **new issue, dispatched fresh** — that is the only channel that reaches a run in flight. Where the forge supports it, ward locks this conversation to make that a road-block rather than a convention (ward#494). <details><summary>run seed context — what this run is carrying (ward#609)</summary> - **Resolved:** `coilyco-flight-deck/ward#497` · branch `issue-497` · driver `claude` · workflow `direct-main` - **Run:** `engineer-claude-ward-497` · ward `v0.422.0` · dispatched `2026-07-07T22:46:44Z` - **Comment thread:** 2 included in the pre-flight read, 0 stripped (ward's own automated comments). - included: @coilysiren (2026-07-02T02:34:11Z), @coilyco-ops (2026-07-07T22:46:03Z) **Issue body as seeded:** ``` ## Observed (2026-07-02, director surface session, dispatch broker path) Probing dispatchability with `warded <ref> --print` through the dispatch broker: * `coilysiren/website#57` - fails: `resolve issue coilysiren/website#57: forgejo: get issue coilysiren/website#57: exit status 3` * `coilyco-bridge/lore#2` - fails the same way * `coilysiren/coilysiren#15`, `coilyco-bridge/atlas#11`, `coilyco-bridge/agentic-os-hardware#22` - all forward fine So the failure is repo-level, not owner-level: the same owners resolve for sibling repos. Both issues exist and are readable with the container's coilyco-ops token (`ward ops forgejo issue view` returns them), so this is specific to whatever credential or trust surface host ward resolves issues with on the dispatch path. lore is private-context so a visibility gap is plausible there, but website hosts a P1 (coilysiren/website#59, broken coily-trailer prepare-commit-msg hook) that is currently unreachable from the dispatch surface. ## Why filed, not dispatched The investigation is host-side (host ward's forgejo credential / trust config), which a container engineer cannot reach, and the ward lane is saturated by the milestone-7 burndown (#492). Deliberately not dispatching an engineer. ## Suggested next step From the host: `ward agent coilysiren/website#59 --print` and compare the forgejo credential host ward resolves against the repo's visibility. If website/lore are intentionally outside the dispatch trust surface, the refusal should say so instead of a bare exit status 3 (adjacent: cli-guard#484). --- Filed by the director surface session (claude-linux-68cc49ef38c1-bc38-she-her) while dispatching non-colliding cross-org work during the burndown. ``` Static container doctrine and seed boilerplate are identical every run and omitted here (they ride ward v0.422.0). </details> <!-- ward-agent-signature --> — Claude (she/her), via `ward agent`
Member

WARD-OUTCOME: done - resolve seam now retries a transient forge blip and surfaces a permanent 4xx instead of a bare exit-status-3

Went smoothly, and most of the work was reading before writing. The surprise was that half of this issue was already half-fixed: ward#596 had landed foldOpsStderr, so the cause is no longer swallowed as long as the ops subprocess writes an envelope. That reframed my job from "surface the cause" to "add the retry and classify transient-vs-permanent off the now-folded cause".

The one thing that fought back was the exit code itself. cli-guard collapses every non-2xx into a single UpstreamFailed exit 3 - a 502, an unreachable API, and a genuine 403 all look identical at the code level. So the classifier has to read the HTTP status out of the folded envelope text rather than the exit code, which is a touch fragile: it leans on the runtime's arrow-NNN and gh's HTTP-NNN shapes. If either format drifts, an ambiguous error biases to retry (the safe direction), but a genuine 403 would then cost ~4s of pointless retries before surfacing.

Confidence is high on the mechanics (unit-covered: classifier plus the retry loop with a stubbed sleep). Lower on the original field report - the reporter saw website#57 and lore#2 fail consistently, which reads more like a permanent 403 visibility gap than a transient blip. If so, this change makes that case legible (it will now name the 403 and skip the retry) but does not grant the host token access - that host-side credential/trust question is still open and is the real next step the reporter suggested. Worth a follow-up if those two repos should sit inside the dispatch trust surface.

WARD-OUTCOME: done - resolve seam now retries a transient forge blip and surfaces a permanent 4xx instead of a bare exit-status-3 Went smoothly, and most of the work was reading before writing. The surprise was that half of this issue was already half-fixed: ward#596 had landed foldOpsStderr, so the cause is no longer swallowed as long as the ops subprocess writes an envelope. That reframed my job from "surface the cause" to "add the retry and classify transient-vs-permanent off the now-folded cause". The one thing that fought back was the exit code itself. cli-guard collapses every non-2xx into a single UpstreamFailed exit 3 - a 502, an unreachable API, and a genuine 403 all look identical at the code level. So the classifier has to read the HTTP status out of the folded envelope text rather than the exit code, which is a touch fragile: it leans on the runtime's arrow-NNN and gh's HTTP-NNN shapes. If either format drifts, an ambiguous error biases to retry (the safe direction), but a genuine 403 would then cost ~4s of pointless retries before surfacing. Confidence is high on the mechanics (unit-covered: classifier plus the retry loop with a stubbed sleep). Lower on the original field report - the reporter saw website#57 and lore#2 fail consistently, which reads more like a permanent 403 visibility gap than a transient blip. If so, this change makes that case legible (it will now name the 403 and skip the retry) but does not grant the host token access - that host-side credential/trust question is still open and is the real next step the reporter suggested. Worth a follow-up if those two repos should sit inside the dispatch trust surface.
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#497
No description provided.