Add a governed extension surface to the issues API, starting with issue progress #35

Open AtlantisPleb opened this 5h ago

Outcome

The Issues API keeps exact GitHub parity while growing OpenAgents-specific fields in a way a client — human or agent — can discover mechanically: here are the fields GitHub has, and here are the fields we added.

Background

An audit (2026-08-22) found that "in progress" exists only as a per-project board column: ProjectItem.values["Status"] with hardcoded columns To Do / In Progress / Done, scoped to one project, never synced to the issue, and invisible to the Issues API. Meanwhile the shared status component already ships an unused :started shape (progress arc, blue tint) that renders the moment real data arrives. Agents currently have no machine-readable way to tell which open issues are in progress short of walking every project board.

Design

One namespaced extension object per resource, plus a published field index.

  • Every /api/v3 issue response gains a top-level openagents object alongside the GitHub fields. GitHub clients ignore unknown keys; OpenAgents-aware clients read issue.openagents.*. Nothing existing moves or changes shape.
  • The first entry is progress: issue.openagents.progress with values "to_do" | "in_progress" | "done" (snake_case, like GitHub's own enums). It is derived by default: an issue is in_progress when it sits in a matching column on any board the viewer can read, so projects stop being the only source of truth without forcing a second write path. A direct set through the extension field may come later.
  • Discovery is mechanical, not tribal:
    • GET /api/v3 (root document) lists every extension field with its type, enum values, owning version, and a doc URL.
    • Each response carries an X-OpenAgents-Extensions: progress header naming which extensions are populated, so an agent can branch without hardcoding.
  • Filter parity extends the same way: GET /repos/{owner}/{repo}/issues?progress=in_progress filters through the same derivation, following the bounded-pagination contract from #5.

Governance rules for every future extension field (this issue establishes them):

  1. Lives under the openagents namespace; never mutates a GitHub-shaped key.
  2. Enumerated in the root document before any client is expected to use it.
  3. Carries a test pinning its JSON shape, like every other API contract in this repository.
  4. Derivations state their sources explicitly (which boards, whose visibility).

Work

  • Add the openagents object to issue JSON (IssueJSON), empty rather than absent when no extension applies, so the key's presence is itself discoverable.
  • Implement progress derivation across readable project items, with visibility honored exactly as list endpoints do.
  • Root-document endpoint listing extension fields; header on issue responses.
  • progress= filter on the issue index within the pagination contract.
  • Drive Circle.issue_status :started from the derived value so the UI arc lights up wherever rows render.
  • Contract tests for JSON shape, filter behavior, visibility, and the root document; update the CLI's issue schema.

Acceptance criteria

  • A GitHub-shaped client sees byte-compatible issue responses (only an additional object).
  • An agent fetching the API root can enumerate progress and its enum without reading prose.
  • ?progress=in_progress agrees with what the UI shows as started.
  • Private-board membership never leaks into a viewer's derived progress.

Verification

Controller tests for shape, filter, and authorization; a root-document test asserting the field index; mix precommit.

  1. AtlantisPleb opened this issue 5h ago
Sign in with GitHub to comment on this issue.