Skip to content

GitHub Projects adapter

Transport for work-tracking when hoen.yamlwork_tracking.backend: github_projects. Field meanings: shared-fields.md. Per-plan docs use slim ## Tracking (Plan ID, Board item = tracking issue, Work type) — never paste PVTF_… IDs into plans.

Scope: org vs user projects

Project owner Token
Organization Fine-grained PAT (Org → Projects: Read and write) or classic project
User Classic PAT project only

Prefer org-owned projects + fine-grained PAT.

hoen.yaml board keys

board:
  name: Example Platform Board
  url: https://github.com/orgs/<org>/projects/<n>
  owner_type: org          # org | user
  owner: "<org>"
  project_number: <n>
  # project_id: PVT_…       # optional; auto-resolved
  # fields:                 # optional; store after bootstrap
  #   status_summary: PVTF_…

Field bootstrap

Create the shared custom fields once when permitted:

gh project field-create <n> --owner <org> --name "Status summary" --data-type TEXT
gh project field-create <n> --owner <org> --name "Phase detail"   --data-type TEXT

Default name map (FORMAT / write script): Status summary ← progress_headline, Phase detail ← current_plan_phase, Status ← status, Estimate ← effort_total. If create fails: refresh the issue body via sync-issue-progress.mjs, note deferred board fields, retry next sync. Persist field IDs in hoen.yaml when resolved.

Enable Status summary on the board view (UI view → Fields) so 👀 shows on cards without stuffing numbers into the issue title. Card-field display is not API-scriptable.

Auth

Fine-grained PAT (org projects): Projects Read/write; repo Metadata Read; Issues Read/write; Contents Read only if using gh issue create (else REST create).

gh auth refresh -h github.com -s project

If gh cannot auth: ask before using API + token from a file/env. Otherwise encourage the user to paste a Progress block into the tracking issue:

node library/skills/work-tracking/scripts/format-sync.mjs \
  --input path/to/plan.effort.json --paste-md --plan-doc path/to/plan.md

(Remote plan link from git remote get-url origin. Optional: --map github JSON for field names if they also edit Projects fields by hand.)

Agent sandboxes often fail DNS to api.github.com while an interactive terminal works — re-run there; format-github-sync.mjs retries transient DNS errors.

Sync (prefer orchestrator)

Two surfaces: issue body ## Progress + Projects custom fields. Refresh both.

node library/skills/work-tracking/scripts/sync-from-hoen.mjs \
  --input path/to/plan.effort.json --issue N --dry-run

Or separately: sync-issue-progress.mjs + format-github-sync.mjs (transport writes). Payload preview without writing: format-sync.mjs --map github.

Recipes

gh issue create --repo <org>/<repo> --title "<short title>" --body-file body.md
gh project item-add <n> --owner <org> --url <issue-url> --format json
# Field writes: prefer format-github-sync.mjs (resolves IDs by name)