Skip to content

Plan: GitHub Projects (board) compatibility#37

Merged
androidand merged 2 commits into
mainfrom
github-projects-compatibility
Jul 13, 2026
Merged

Plan: GitHub Projects (board) compatibility#37
androidand merged 2 commits into
mainfrom
github-projects-compatibility

Conversation

@androidand

Copy link
Copy Markdown
Owner

Spec-only PR (proposal + spec + tasks; no code yet) planning GitHub Projects (board) compatibility for specsync.

Problem

specsync projects onto GitHub Issues only. Lifecycle is emitted as a stage: label; there's no assignee handling and no ProjectV2/board awareness anywhere (github.go). For a team whose backlog is a GitHub Projects board, synced issues never show up as active work. Verified against ExopenGitHub Project #6: specsync-created ExoKit#16 was onBoard: false, status: null, assignees: [] — only a stage:active label.

Plan (opt-in, backward-compatible)

  • -project owner/number (org/user ProjectV2) on sync/pull; unset ⇒ no board behavior (unchanged).
  • Resolve project number → node id (cached); discover the Status single-select field + option ids from the project schema, name↔id maps, fail-loud on unknown status.
  • Detect membership via issue { projectItems { nodes { project { id } } } } — uniform for freshly-created (empty) and existing issues.
  • Ensure-on-board (addProjectV2ItemById), map stage → Status (updateProjectV2ItemFieldValue w/ singleSelectOptionId), assign the viewer/"me" (login→user id).
  • Never clobber: set Status/assignee only when unset or specsync-managed; never remove a board item.
  • Requires the token project scope (echoes the publish-scope fix in stable-projection-ref-key/Epic & sub-issue projection #2) — reported as a clear error.
  • Runs through gh api graphql (no Octokit dep).

Prior art

Grounded in the ExopenGitHub backlog MCP (metaverse/backlog/src), which drives this same board: node-id addressing, startup schema discovery → name↔id maps, repo#number/node-id membership index, batched aliased field mutations, two-id model (project-item id vs issue content id), and git config user.email-anchored viewer identity.

Implementation to follow in a separate PR.

🤖 Generated with Claude Code

androidand and others added 2 commits July 13, 2026 16:17
specsync is issue-only: lifecycle is a stage: label, no assignee handling,
no ProjectV2/board awareness (github.go). For teams whose backlog is a
GitHub Projects board, synced issues never appear as active work (verified:
ExoKit#16 onBoard=false/status=null/assignees=[]).

Plan an opt-in target ProjectV2: resolve number->node id, discover the
Status field/options, detect membership via issue.projectItems, ensure the
issue is on the board, map stage->Status, and assign the viewer — grounded
in the ExopenGitHub backlog MCP (metaverse/backlog) mechanisms, run through
`gh api graphql`, without clobbering human curation.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Project a synced change onto a GitHub ProjectV2 board when -project
owner/number (or $SPECSYNC_PROJECT) is set; unset keeps behavior
unchanged with zero board calls.

The new type-asserted BoardProjector capability drives everything through
`gh api graphql` via the provider's injected runner:
- resolve project node id (org first, user fallback), cached per run
- discover the Status single-select field + option ids from the schema
  (never hard-coded), mapping stage->status name with a fail-loud unknown
- detect board membership by the issue's projectItems (uniform for fresh
  and existing issues)
- ensure on board (addProjectV2ItemById), set Status
  (updateProjectV2ItemFieldValue) only when unset or specsync-managed,
  assign the viewer/"me" or a configured login only when unassigned
- classify insufficient-scope failures into a clear `project` scope message

Wired into sync and pull after the issue upsert; -dry-run previews the
board plan and issues no GraphQL. Faked-gh unit tests cover resolution,
membership, idempotency, non-clobber, viewer resolution, dry-run, and the
unconfigured no-op.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@androidand androidand merged commit 51d6b83 into main Jul 13, 2026
1 check passed
@androidand androidand deleted the github-projects-compatibility branch July 13, 2026 14:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant