Remove runtime KDL/specgen dependency from ward core paths #929

Closed
opened 2026-07-10 02:17:24 +00:00 by coilyco-ops · 4 comments
Member

Ward proper must completely remove any reliance on runtime KDL/specgen surfaces for product-critical behavior.

Triggering failure:

WARD_CONFIG_REF=forgejo.coilysiren.me/coilyco-flight-deck/agentic-os@main//.ward ward agent engineer coilyco-flight-deck/ward#927 --harness codex --ward-version v0.543.0
...
Incorrect Usage: flag provided but not defined: -output
ward: flag provided but not defined: -output
ward agent: note: resolving issue coilyco-flight-deck/ward#927 hit a transient failure ... forgejo: get issue coilyco-flight-deck/ward#927: exit status 1 ...

Root cause:

ward agent is resolving issues through cmd/ward/forgejo_ops.go, whose internal Forgejo client shells through ward ops forgejo ... --output json leaves. Under WARD_CONFIG_REF, those leaves are supplied by the selected runtime KDL/specgen bundle. If that bundle's generated surface does not expose the exact flags ward core assumes, core agent dispatch breaks before reservation.

That means a runtime-selected operator/specgen surface can break ward's own core product behavior. That boundary is wrong.

Policy:

  • WARD_CONFIG_REF may select operator edge surfaces and deployment KDL bundles.
  • WARD_CONFIG_REF must not be required for, or able to break, ward core behavior.
  • Ward core paths must not shell through runtime-generated KDL/specgen leaves.

Scope:

  • Remove ward agent issue resolution, broker dispatch, director heartbeat, PR merge, reaper, bootstrap, and any other product-critical path from the ward ops forgejo ... generated CLI surface.
  • Replace those internal calls with typed Go ports/clients or stable embedded Go behavior. The existing Forgejo/GitHub tracker split should be the direction: core depends on explicit tracker/forge adapters, not a runtime CLI generated from KDL.
  • Audit cmd/ward/forgejo_ops.go, broker_exec.go, dispatch broker paths, reaper paths, and any c.run(... "--output", "json") style dependency on generated ops leaves.
  • Keep operator-facing ward ops ... as an edge surface if still needed, but make it non-authoritative for ward core.
  • Ensure a bad, missing, or incompatible runtime KDL bundle cannot break ward agent --print, issue lookup, dispatch reservation, broker forwarding, or container bootstrap.
  • Update docs so WARD_CONFIG_REF is described as an edge/operator config source, not a dependency of ward core agent behavior.

Acceptance:

  • WARD_CONFIG_REF pointing at the aos bundle cannot make ward agent engineer coilyco-flight-deck/ward#927 --harness codex --ward-version v0.543.0 --print fail because an ops leaf rejects --output.
  • A malformed or incompatible runtime KDL bundle degrades only the operator edge surface it owns. Core ward agent resolution still works or fails with a core adapter error unrelated to KDL/specgen CLI shape.
  • Tests cover an incompatible selected KDL/specgen surface while ward agent --print still resolves a Forgejo issue through the core adapter.
  • Docs and docs/FEATURES.md reflect the boundary.

Related: #399, #920, #927.

Ward proper must completely remove any reliance on runtime KDL/specgen surfaces for product-critical behavior. Triggering failure: ```text WARD_CONFIG_REF=forgejo.coilysiren.me/coilyco-flight-deck/agentic-os@main//.ward ward agent engineer coilyco-flight-deck/ward#927 --harness codex --ward-version v0.543.0 ... Incorrect Usage: flag provided but not defined: -output ward: flag provided but not defined: -output ward agent: note: resolving issue coilyco-flight-deck/ward#927 hit a transient failure ... forgejo: get issue coilyco-flight-deck/ward#927: exit status 1 ... ``` Root cause: `ward agent` is resolving issues through `cmd/ward/forgejo_ops.go`, whose internal Forgejo client shells through `ward ops forgejo ... --output json` leaves. Under `WARD_CONFIG_REF`, those leaves are supplied by the selected runtime KDL/specgen bundle. If that bundle's generated surface does not expose the exact flags ward core assumes, core agent dispatch breaks before reservation. That means a runtime-selected operator/specgen surface can break ward's own core product behavior. That boundary is wrong. Policy: * `WARD_CONFIG_REF` may select operator edge surfaces and deployment KDL bundles. * `WARD_CONFIG_REF` must not be required for, or able to break, ward core behavior. * Ward core paths must not shell through runtime-generated KDL/specgen leaves. Scope: * Remove `ward agent` issue resolution, broker dispatch, director heartbeat, PR merge, reaper, bootstrap, and any other product-critical path from the `ward ops forgejo ...` generated CLI surface. * Replace those internal calls with typed Go ports/clients or stable embedded Go behavior. The existing Forgejo/GitHub tracker split should be the direction: core depends on explicit tracker/forge adapters, not a runtime CLI generated from KDL. * Audit `cmd/ward/forgejo_ops.go`, `broker_exec.go`, dispatch broker paths, reaper paths, and any `c.run(... "--output", "json")` style dependency on generated ops leaves. * Keep operator-facing `ward ops ...` as an edge surface if still needed, but make it non-authoritative for ward core. * Ensure a bad, missing, or incompatible runtime KDL bundle cannot break `ward agent --print`, issue lookup, dispatch reservation, broker forwarding, or container bootstrap. * Update docs so `WARD_CONFIG_REF` is described as an edge/operator config source, not a dependency of ward core agent behavior. Acceptance: * `WARD_CONFIG_REF` pointing at the aos bundle cannot make `ward agent engineer coilyco-flight-deck/ward#927 --harness codex --ward-version v0.543.0 --print` fail because an ops leaf rejects `--output`. * A malformed or incompatible runtime KDL bundle degrades only the operator edge surface it owns. Core `ward agent` resolution still works or fails with a core adapter error unrelated to KDL/specgen CLI shape. * Tests cover an incompatible selected KDL/specgen surface while `ward agent --print` still resolves a Forgejo issue through the core adapter. * Docs and `docs/FEATURES.md` reflect the boundary. Related: #399, #920, #927.
Author
Member

Dispatch attempt from the read-only director surface was forwarded to the host broker at 2026-07-10T02:18:55Z, but no WARD-RESERVATION comment appeared after the follow-up read.

Host log path printed by the broker: /Users/kai/.ward/agent-logs/dispatch/20260710T021855Z-director-codex-zv98-coilyco-flight-deck-ward-929.log.

This is likely the same root failure this issue is about: host-side dispatch still depends on runtime KDL/specgen-generated ops leaves, so the work cannot reliably self-dispatch until ward core stops shelling through that surface.

Dispatch attempt from the read-only director surface was forwarded to the host broker at 2026-07-10T02:18:55Z, but no WARD-RESERVATION comment appeared after the follow-up read. Host log path printed by the broker: `/Users/kai/.ward/agent-logs/dispatch/20260710T021855Z-director-codex-zv98-coilyco-flight-deck-ward-929.log`. This is likely the same root failure this issue is about: host-side dispatch still depends on runtime KDL/specgen-generated ops leaves, so the work cannot reliably self-dispatch until ward core stops shelling through that surface.
Author
Member

Temporary unstick path while this issue is open:

  • Do not run the current host dispatch broker with WARD_CONFIG_REF set. The selected runtime bundle can break the generated ward ops forgejo ... --output json leaf before reservation and before the broker can comment its own failure.
  • Do not rely on the old installed host ward if it reports allowed: example-owner. That binary has stale baked defaults.
  • From the host, run a source-built current ward binary with WARD_CONFIG_REF, WARD_READONLY, and the dispatch-broker env cleared, then dispatch directly. This bypasses the already-running director broker and uses the matching baked defaults + embedded ops surface.
  • Existing director surfaces must be restarted after the host binary/env fix. Their dispatch broker is tied to the host ward process that launched them.

A --print test from this read-only container with broker env cleared got past owner trust and issue resolution with no WARD_CONFIG_REF; it then failed only at Docker connectivity, which is expected from the surface. That supports the host-direct workaround.

Temporary unstick path while this issue is open: * Do not run the current host dispatch broker with `WARD_CONFIG_REF` set. The selected runtime bundle can break the generated `ward ops forgejo ... --output json` leaf before reservation and before the broker can comment its own failure. * Do not rely on the old installed host `ward` if it reports `allowed: example-owner`. That binary has stale baked defaults. * From the host, run a source-built current ward binary with `WARD_CONFIG_REF`, `WARD_READONLY`, and the dispatch-broker env cleared, then dispatch directly. This bypasses the already-running director broker and uses the matching baked defaults + embedded ops surface. * Existing director surfaces must be restarted after the host binary/env fix. Their dispatch broker is tied to the host ward process that launched them. A `--print` test from this read-only container with broker env cleared got past owner trust and issue resolution with no `WARD_CONFIG_REF`; it then failed only at Docker connectivity, which is expected from the surface. That supports the host-direct workaround.
Author
Member

Native-agent handoff notes from the failed director dispatch exercise. The plain bugfix remains the first priority, but the frustration also exposed product gaps that should be considered while fixing it.

Plain bugfix:

  • Ward core must not depend on runtime KDL/specgen ward ops ... leaves for issue lookup, reservation, broker dispatch, director heartbeat, reaper, bootstrap, or failure comments. Core needs typed Forgejo/GitHub tracker clients or another stable ward-owned adapter layer.

Debuggability and usability follow-ups:

  • Dispatch receipt must mean something. forwarded to host ward currently means only that the TCP request was accepted. The broker should wait briefly for one of: reservation posted, launch failed, container observed, or timeout. If it times out, return a non-zero accepted but no reservation observed result with the log path.
  • Make broker logs reachable from the TUI. A director user should not get /Users/kai/.ward/... as the only diagnostic. Add something like ward agent broker-logs --latest --tail 200, or fold dispatch logs into ward agent logs --dispatch --latest.
  • Add ward agent doctor. One command should print binary path, version, baked defaults source, trusted owners, WARD_CONFIG_REF, resolved config SHA, selected repo authority for a ref, whether ward ops forgejo issue get --output json works, Docker status, token source, broker address, and whether this surface is read-only.
  • Make ward agent ... --print boring. It should never need Docker, never create a brokered launch, and never depend on a generated ops leaf. It should be the safe diagnostic path.
  • Add config provenance to trust-gate and config failures. allowed: example-owner should also say which binary/config source produced that policy, including binary path, ward version, config source, and trusted-owner list source.
  • Baked defaults must be real. No shipped binary should default to example-owner. Use coilysiren/example as the real public placeholder path, and add tests asserting the baked default is usable.
  • Do not let failure-commenting share the failed dependency. The broker tried to explain the launch failure through the same tracker path that was broken. Failure reporting needs a minimal direct fallback.

Product principle:

  • Ward needs a clear split between the core agent control plane and operator edge surfaces. Runtime KDL can be optional edge config. It cannot sit under dispatch itself.
Native-agent handoff notes from the failed director dispatch exercise. The plain bugfix remains the first priority, but the frustration also exposed product gaps that should be considered while fixing it. Plain bugfix: * Ward core must not depend on runtime KDL/specgen `ward ops ...` leaves for issue lookup, reservation, broker dispatch, director heartbeat, reaper, bootstrap, or failure comments. Core needs typed Forgejo/GitHub tracker clients or another stable ward-owned adapter layer. Debuggability and usability follow-ups: * Dispatch receipt must mean something. `forwarded to host ward` currently means only that the TCP request was accepted. The broker should wait briefly for one of: reservation posted, launch failed, container observed, or timeout. If it times out, return a non-zero `accepted but no reservation observed` result with the log path. * Make broker logs reachable from the TUI. A director user should not get `/Users/kai/.ward/...` as the only diagnostic. Add something like `ward agent broker-logs --latest --tail 200`, or fold dispatch logs into `ward agent logs --dispatch --latest`. * Add `ward agent doctor`. One command should print binary path, version, baked defaults source, trusted owners, `WARD_CONFIG_REF`, resolved config SHA, selected repo authority for a ref, whether `ward ops forgejo issue get --output json` works, Docker status, token source, broker address, and whether this surface is read-only. * Make `ward agent ... --print` boring. It should never need Docker, never create a brokered launch, and never depend on a generated ops leaf. It should be the safe diagnostic path. * Add config provenance to trust-gate and config failures. `allowed: example-owner` should also say which binary/config source produced that policy, including binary path, ward version, config source, and trusted-owner list source. * Baked defaults must be real. No shipped binary should default to `example-owner`. Use `coilysiren/example` as the real public placeholder path, and add tests asserting the baked default is usable. * Do not let failure-commenting share the failed dependency. The broker tried to explain the launch failure through the same tracker path that was broken. Failure reporting needs a minimal direct fallback. Product principle: * Ward needs a clear split between the core agent control plane and operator edge surfaces. Runtime KDL can be optional edge config. It cannot sit under dispatch itself.
Author
Member

Restart handoff from the read-only director surface. Kai says the broken dispatch path is fixed and she needs to restart the surface.

Current state to carry forward:

  • #929 is the core blocker issue: remove runtime KDL/specgen dependency from ward core paths. It is labeled P0/headless. Earlier dispatch attempts were broker-accepted but did not reserve because the broken path was still active. Native agent should re-dispatch or continue from the fixed state.
  • #930 tracks using coilysiren/example as ward's real public placeholder/default example repo. It is labeled P1/headless. Dispatch was attempted before the fix and also broker-accepted without reservation. Re-dispatch after restart.
  • #927 tracks a natural TUI surface for broker/dispatch logs. It is labeled P1/headless. Dispatch was attempted before the fix and did not reserve. Re-dispatch after restart.
  • #923 generated ward-kdl docs deletion has PR #925 open.
  • #924 docs shrink has PR #928 open.
  • #905 has comments about the release asset race and preferred fix: order the Forgejo release workflow so binaries are uploaded/verified before a release is selectable as latest.
  • agentic-os#399 was patched by Kai for repo-authority; the remaining noted gap was making WARD_CONFIG_REF=forgejo.coilysiren.me/coilyco-flight-deck/agentic-os@main//.ward global in shell setup.

Important lessons from the failed dispatch exercise:

  • forwarded to host ward was only a broker receipt, not proof of reservation or launch.
  • Runtime KDL/specgen must not sit under ward core dispatch.
  • Failure reporting must not depend on the same tracker/ops path that failed.
  • A restart is required because director-surface dispatch broker state is tied to the host ward process that launched it.

Suggested first actions after restart:

  1. Verify a fresh ward agent engineer coilyco-flight-deck/ward#929 --harness codex --print no longer fails on --output or example-owner.
  2. Re-dispatch #929 first.
  3. Then re-dispatch #927 and #930.
  4. Inspect/merge the already-open docs PRs #925 and #928 if their checks are green.
Restart handoff from the read-only director surface. Kai says the broken dispatch path is fixed and she needs to restart the surface. Current state to carry forward: * #929 is the core blocker issue: remove runtime KDL/specgen dependency from ward core paths. It is labeled P0/headless. Earlier dispatch attempts were broker-accepted but did not reserve because the broken path was still active. Native agent should re-dispatch or continue from the fixed state. * #930 tracks using `coilysiren/example` as ward's real public placeholder/default example repo. It is labeled P1/headless. Dispatch was attempted before the fix and also broker-accepted without reservation. Re-dispatch after restart. * #927 tracks a natural TUI surface for broker/dispatch logs. It is labeled P1/headless. Dispatch was attempted before the fix and did not reserve. Re-dispatch after restart. * #923 generated ward-kdl docs deletion has PR #925 open. * #924 docs shrink has PR #928 open. * #905 has comments about the release asset race and preferred fix: order the Forgejo release workflow so binaries are uploaded/verified before a release is selectable as latest. * agentic-os#399 was patched by Kai for `repo-authority`; the remaining noted gap was making `WARD_CONFIG_REF=forgejo.coilysiren.me/coilyco-flight-deck/agentic-os@main//.ward` global in shell setup. Important lessons from the failed dispatch exercise: * `forwarded to host ward` was only a broker receipt, not proof of reservation or launch. * Runtime KDL/specgen must not sit under ward core dispatch. * Failure reporting must not depend on the same tracker/ops path that failed. * A restart is required because director-surface dispatch broker state is tied to the host ward process that launched it. Suggested first actions after restart: 1. Verify a fresh `ward agent engineer coilyco-flight-deck/ward#929 --harness codex --print` no longer fails on `--output` or `example-owner`. 2. Re-dispatch #929 first. 3. Then re-dispatch #927 and #930. 4. Inspect/merge the already-open docs PRs #925 and #928 if their checks are green.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
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#929
No description provided.