Split issueForge into a git-host port and a Tracker port #634

Closed
opened 2026-07-07 21:46:53 +00:00 by coilyco-ops · 5 comments
Member

Parent epic: #633. Depends on: none. This unblocks the Trello (#636) and Shortcut (#637) tracker adapters and the Jira/Linear backlog (#638).

Context. cmd/ward/forge.go defines issueForge and a forge enum (forgeForgejo default, forgeGitHub). That single port bundles two responsibilities that are one system on Forgejo and GitHub but two systems on most other stacks: the git host (clone origin, push credentials, PR/MR) and the issue tracker (list, read, comment, close, triage). A GitHub-repo-plus-Trello-board user needs the git host to be GitHub and the issue thread to be Trello. Today that pairing is unexpressible without editing core flow.

Proposed change.

  • Extract a git-host port (call it gitHost or keep forge for it): clone base URL, push user, ref parsing, PR/MR creation. Forgejo and GitHub keep their current implementations here.
  • Extract a Tracker port: read an issue, post a comment, close, apply triage/labels, resolve an issue ref to a stable URL. Forgejo issues and GitHub issues become the first two Tracker implementations, so nothing regresses.
  • A run pairs one git host with one tracker. On Forgejo and GitHub the pair is the same system, which is the default and must stay zero-config.
  • Route the existing issueForge call sites (hostForgeClient, the agent_* files that read and comment on issues) through whichever half they actually need.

Acceptance criteria.

  • Forgejo-only and GitHub-only runs behave exactly as today, defaults unchanged, WARD_FORGE still selects the git host.
  • A test proves a git host and a tracker can be paired independently (even if the second tracker is a stub in this issue).
  • No agent_* file talks to a concrete forge directly. All issue and comment traffic goes through the Tracker port, all clone/push/PR traffic through the git-host port.
  • docs/compat-surface.md (#640) updated to show the two ports.

Notes. Shape the Tracker interface against a real second tracker (Trello, #636) so it is not designed in the abstract. Keep the method set minimal: what an agent run genuinely does to an issue, nothing more.


Milestone: foreign-stack compat. Filed from the read-only director surface (she/her), part of the release-readiness issue batch.

Parent epic: #633. **Depends on:** none. This unblocks the Trello (#636) and Shortcut (#637) tracker adapters and the Jira/Linear backlog (#638). **Context.** `cmd/ward/forge.go` defines `issueForge` and a `forge` enum (`forgeForgejo` default, `forgeGitHub`). That single port bundles two responsibilities that are one system on Forgejo and GitHub but two systems on most other stacks: the git host (clone origin, push credentials, PR/MR) and the issue tracker (list, read, comment, close, triage). A GitHub-repo-plus-Trello-board user needs the git host to be GitHub and the issue thread to be Trello. Today that pairing is unexpressible without editing core flow. **Proposed change.** - Extract a git-host port (call it `gitHost` or keep `forge` for it): clone base URL, push user, ref parsing, PR/MR creation. Forgejo and GitHub keep their current implementations here. - Extract a `Tracker` port: read an issue, post a comment, close, apply triage/labels, resolve an issue ref to a stable URL. Forgejo issues and GitHub issues become the first two `Tracker` implementations, so nothing regresses. - A run pairs one git host with one tracker. On Forgejo and GitHub the pair is the same system, which is the default and must stay zero-config. - Route the existing `issueForge` call sites (`hostForgeClient`, the `agent_*` files that read and comment on issues) through whichever half they actually need. **Acceptance criteria.** - Forgejo-only and GitHub-only runs behave exactly as today, defaults unchanged, `WARD_FORGE` still selects the git host. - A test proves a git host and a tracker can be paired independently (even if the second tracker is a stub in this issue). - No `agent_*` file talks to a concrete forge directly. All issue and comment traffic goes through the `Tracker` port, all clone/push/PR traffic through the git-host port. - `docs/compat-surface.md` (#640) updated to show the two ports. **Notes.** Shape the `Tracker` interface against a real second tracker (Trello, #636) so it is not designed in the abstract. Keep the method set minimal: what an agent run genuinely does to an issue, nothing more. --- Milestone: foreign-stack compat. Filed from the read-only director surface (she/her), part of the release-readiness issue batch.
Author
Member

Consult interrogation: this is now headless-ready. The issue has a concrete implementation target and acceptance criteria, with no remaining human decision needed before an engineer can carry it.

Consult interrogation: this is now headless-ready. The issue has a concrete implementation target and acceptance criteria, with no remaining human decision needed before an engineer can carry it.
Author
Member

WARD-RESERVATION: held 🔒

reservation details

Holder: container engineer-codex-ward-634 on host kais-macbook-pro-2.local.

Reserved by ward agent --harness codex (reserved 2026-07-09T18:29:51Z). Concurrent ward agent runs are blocked until it finishes or the reservation goes stale (1h 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#634 · branch issue-634 · harness codex · workflow pull-request
  • Run: engineer-codex-ward-634 · ward v0.493.0 · dispatched 2026-07-09T18:29:51Z
  • Comment thread: 1 included in the pre-flight read, 0 stripped (ward's own automated comments).

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

— Codex, via ward agent

<!-- ward-agent-reservation --> WARD-RESERVATION: held 🔒 <details><summary>reservation details</summary> Holder: container `engineer-codex-ward-634` on host `kais-macbook-pro-2.local`. Reserved by `ward agent --harness codex` (reserved 2026-07-09T18:29:51Z). Concurrent `ward agent` runs are blocked until it finishes or the reservation goes stale (1h 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#634` · branch `issue-634` · harness `codex` · workflow `pull-request` - **Run:** `engineer-codex-ward-634` · ward `v0.493.0` · dispatched `2026-07-09T18:29:51Z` - **Comment thread:** 1 included in the pre-flight read, 0 stripped (ward's own automated comments). - included: @coilyco-ops (2026-07-09T18:25:08Z) Static container doctrine and seed boilerplate are identical every run and omitted here (they ride ward v0.493.0). </details> </details> <!-- ward-agent-signature --> — Codex, via `ward agent`
Author
Member

WARD-OUTCOME: done

details workflow: pull-request; review summary: review gate skipped by ~/.ward/config.yaml default felt: straightforward split, one lint pass needed cleanup confidence: high surprise: golangci-lint caught the legacy helper and cyclo edge follow-ups: none
WARD-OUTCOME: done ✅ <details><summary>details</summary> workflow: pull-request; review summary: review gate skipped by ~/.ward/config.yaml default felt: straightforward split, one lint pass needed cleanup confidence: high surprise: golangci-lint caught the legacy helper and cyclo edge follow-ups: none </details>
Author
Member

WARD-RESERVATION: held 🔒

reservation details

Holder: container engineer-codex-ward-634 on host kais-macbook-pro-2.local.

Reserved by ward agent --harness codex (reserved 2026-07-09T20:12:00Z). Concurrent ward agent runs are blocked until it finishes or the reservation goes stale (1h 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#634 · branch issue-634 · harness codex · workflow direct-to-main
  • Run: engineer-codex-ward-634 · ward v0.522.0 · dispatched 2026-07-09T20:12:00Z
  • Comment thread: 2 included in the pre-flight read, 1 stripped (ward's own automated comments).

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

— Codex, via ward agent

<!-- ward-agent-reservation --> WARD-RESERVATION: held 🔒 <details><summary>reservation details</summary> Holder: container `engineer-codex-ward-634` on host `kais-macbook-pro-2.local`. Reserved by `ward agent --harness codex` (reserved 2026-07-09T20:12:00Z). Concurrent `ward agent` runs are blocked until it finishes or the reservation goes stale (1h 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#634` · branch `issue-634` · harness `codex` · workflow `direct-to-main` - **Run:** `engineer-codex-ward-634` · ward `v0.522.0` · dispatched `2026-07-09T20:12:00Z` - **Comment thread:** 2 included in the pre-flight read, 1 stripped (ward's own automated comments). - included: @coilyco-ops (2026-07-09T18:25:08Z), @coilyco-ops (2026-07-09T18:53:59Z) - stripped: @coilyco-ops (2026-07-09T18:29:53Z) Static container doctrine and seed boilerplate are identical every run and omitted here (they ride ward v0.522.0). </details> </details> <!-- ward-agent-signature --> — Codex, via `ward agent`
coilyco-ops referenced this issue from a commit 2026-07-09 20:20:44 +00:00
Author
Member

WARD-OUTCOME: done

details

workflow: direct-to-main; review summary: skipped because review gate skipped by ~/.ward/config.yaml default

Implemented the git-host and tracker split, kept Forgejo/GitHub paired by default, and landed it on main.

The implementation felt mostly mechanical after the merge conflict was resolved. The only surprise was origin/main moving while I was landing, so I merged that tip before pushing.

Confidence: high.
Follow-ups: none.

WARD-OUTCOME: done <details><summary>details</summary> workflow: direct-to-main; review summary: skipped because review gate skipped by ~/.ward/config.yaml default Implemented the git-host and tracker split, kept Forgejo/GitHub paired by default, and landed it on main. The implementation felt mostly mechanical after the merge conflict was resolved. The only surprise was origin/main moving while I was landing, so I merged that tip before pushing. Confidence: high. Follow-ups: none. </details>
Sign in to join this conversation.
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#634
No description provided.