Native PR-workflow tools (merge/status/rerun) gated by ward's embedded permission system #1075

Merged
coilysiren merged 1 commit from issue-1067 into main 2026-07-10 18:49:57 +00:00
Member

closes #1067

ward.workflow: pull-requests-and-merge

PR-workflow management (merge, per-PR combined CI status, Actions run status, rerun) now lives as compiled ward code with zero runtime KDL-specgen dependency, so a stripped or rolled-back .ward/ bundle cannot disable a director's merge lane again (infrastructure#538).

What landed

  • ward agent pr status|merge|runs|rerun - native verbs on ward's core Forgejo client. On a read-only director surface they forward through the host dispatch broker (new pr-status / pr-merge / ci-runs / ci-rerun actions); the host re-checks the permission gate before touching the forge. Elsewhere they run in-process.
  • Embedded merge authority - a merge-authority grant in the shipped role presets KDL (mirrored into roleassets/), keyed to the workflow-mode model: director merges under pull-requests and pull-requests-and-merge, engineer self-merges under pull-requests-and-merge only, patch-only/direct-main withhold merge from everyone. Status/runs need read; rerun needs engineering or project-management; unknown roles are denied fail-closed.
  • Merge safety - the merge pins the checked head commit, re-runs the live required-status gate, and confirms with the merged-state check (GET /pulls/{index}/merge).
  • Rerun forge gap - the live Forgejo API has no rerun operation (agentic-os#434); the native tool tries the API leaf and degrades loudly with the manual retrigger fallback, so the capability's durable home is ward and it starts working the day the forge ships the endpoint.
  • Bundle-absent reachability - the ward agent smart-defaults guard exempts the pr meta verb, so these tools work with WARD_CONFIG_REF unset (verified live in a container with no bundle).
  • Two live-API fixes caught during verification: Forgejo marshals per-context commit status under status (not state), which made the day-old directorMergeStatusGate refuse every merge on the live forge - effectiveState() now reads either field; and /actions/runs ignores limit unless page rides along.

Acceptance

  • Verified live with the specgen bundle absent: runs/status reads, advisor/qa denials, owner-scope refusals, loud rerun gap error.
  • Role x mode gating covered by ward exec test (TestPRWorkflowMergeAuthorityMatrix, TestPRWorkflowReadAndRerunGates, fake-forge merge round-trips including the brokered path).

Docs: docs/agent-pr-workflow.md, FEATURES entry, surface operating-context note.

closes #1067 ward.workflow: pull-requests-and-merge PR-workflow management (merge, per-PR combined CI status, Actions run status, rerun) now lives as compiled ward code with zero runtime KDL-specgen dependency, so a stripped or rolled-back `.ward/` bundle cannot disable a director's merge lane again (infrastructure#538). ## What landed - **`ward agent pr status|merge|runs|rerun`** - native verbs on ward's core Forgejo client. On a read-only director surface they forward through the host dispatch broker (new `pr-status` / `pr-merge` / `ci-runs` / `ci-rerun` actions); the host re-checks the permission gate before touching the forge. Elsewhere they run in-process. - **Embedded merge authority** - a `merge-authority` grant in the shipped role presets KDL (mirrored into `roleassets/`), keyed to the workflow-mode model: director merges under `pull-requests` and `pull-requests-and-merge`, engineer self-merges under `pull-requests-and-merge` only, `patch-only`/`direct-main` withhold merge from everyone. Status/runs need `read`; rerun needs `engineering` or `project-management`; unknown roles are denied fail-closed. - **Merge safety** - the merge pins the checked head commit, re-runs the live required-status gate, and confirms with the merged-state check (`GET /pulls/{index}/merge`). - **Rerun forge gap** - the live Forgejo API has no rerun operation (agentic-os#434); the native tool tries the API leaf and degrades loudly with the manual retrigger fallback, so the capability's durable home is ward and it starts working the day the forge ships the endpoint. - **Bundle-absent reachability** - the `ward agent` smart-defaults guard exempts the `pr` meta verb, so these tools work with `WARD_CONFIG_REF` unset (verified live in a container with no bundle). - **Two live-API fixes caught during verification**: Forgejo marshals per-context commit status under `status` (not `state`), which made the day-old `directorMergeStatusGate` refuse every merge on the live forge - `effectiveState()` now reads either field; and `/actions/runs` ignores `limit` unless `page` rides along. ## Acceptance - Verified live with the specgen bundle absent: runs/status reads, advisor/qa denials, owner-scope refusals, loud rerun gap error. - Role x mode gating covered by `ward exec test` (`TestPRWorkflowMergeAuthorityMatrix`, `TestPRWorkflowReadAndRerunGates`, fake-forge merge round-trips including the brokered path). Docs: `docs/agent-pr-workflow.md`, FEATURES entry, surface operating-context note.
feat(agent): native PR-workflow tools gated by embedded role x workflow permissions
All checks were successful
test / test (pull_request) Successful in 28s
927b1b0ef7
PR-workflow management (merge, per-PR combined CI status, Actions run
status, rerun) is a foundational ward-scale capability, so it now lives
as compiled ward code with zero runtime KDL-specgen dependency
(ward#1067, infrastructure#538):

- ward agent pr status|merge|runs|rerun run on ward's core Forgejo
  client; on a read-only director surface they forward through the host
  dispatch broker (new pr-status/pr-merge/ci-runs/ci-rerun actions) and
  the host re-checks the permission gate before touching the forge.
- Merge authority is embedded product data: a merge-authority grant in
  the shipped role presets KDL, keyed to the workflow-mode model - the
  director merges under pull-requests and pull-requests-and-merge, the
  engineer self-merges under pull-requests-and-merge only, patch-only
  and direct-main withhold merge from everyone. Status/runs need read;
  rerun needs engineering or project-management. Unknown roles are
  denied fail-closed.
- The merge tool pins the checked head commit, re-runs the live
  required-status gate, and confirms with the merged-state check
  (GET /pulls/{index}/merge).
- rerun degrades loudly on the agentic-os#434 forge gap (no rerun API
  leaf on current Forgejo) instead of pretending a specgen leaf could
  have served it; the compiled client starts working the day the forge
  ships the endpoint.
- The ward agent smart-defaults guard exempts the pr meta verb so the
  tools stay reachable with the coilyco .ward/ bundle absent or rolled
  back - the exact coupling the 2026-07-10 permissions rollback exposed.
- Fix a live-API mismatch in the day-old director merge status gate:
  Forgejo marshals per-context commit status under 'status', not
  'state', so the gate refused every merge on the live forge;
  effectiveState() now reads whichever field the forge populated.
- Fix the Actions run list paging quirk: the forge ignores limit unless
  page rides along.

Verified live against forgejo.coilysiren.me with WARD_CONFIG_REF unset:
runs/status reads, role denials for advisor/qa, owner-scope refusals,
and the loud rerun gap error. Merge paths are pinned by fake-forge
tests covering the role x mode matrix per the acceptance criteria.
Sign in to join this conversation.
No description provided.