Skip to content

issue-tracker: board-sync — reconcile the local board with GitHub issues (Layer 1) - #2

Merged
SSFSKIM merged 17 commits into
mainfrom
feat/board-sync
Jul 5, 2026
Merged

issue-tracker: board-sync — reconcile the local board with GitHub issues (Layer 1)#2
SSFSKIM merged 17 commits into
mainfrom
feat/board-sync

Conversation

@SSFSKIM

@SSFSKIM SSFSKIM commented Jul 5, 2026

Copy link
Copy Markdown
Owner

Note: this fork (SSFSKIM/doperpowers) has no dev branch — origin only has main — so this PR targets main. Opened as a draft: the human review below is in progress (the repo owner is reviewing this complete diff on the PR now), not yet complete.

Who is submitting this PR? (required)

Field Value
Your model + version Claude — Opus 4.8 (main orchestrator); Sonnet (per-task implementers + reviewers); Opus (final whole-branch review)
Harness + version Claude Code (agentic CLI)
All plugins installed doperpowers 6.1.1, openai-codex, chrome-devtools-mcp (+ claude.ai MCP connectors)
Human partner who reviewed this diff Repo owner (SSFSKIM) — reviewing this draft now; not yet signed off

What problem are you trying to solve?

The issue-tracker board and a repo's GitHub issues drift apart, silently, with nothing to detect or repair it. Concretely, in a live session (the ida-solution consumer repo, 2026-07-04→05): the local board (doperpowers/issue-tracker/map.json) sat frozen at its 2026-07-03 state while the orchestrator had materialized 21 GitHub issues and re-cut priorities — the board update was a separate manual step that lagged, and a human had to notice the divergence. The drift is bidirectional and recurring: a daemon lands a ticket and the board goes done but the GitHub issue stays open; or a human closes an issue on GitHub and the board still shows it active. The only ticket↔issue link today is a (GH#NN) string parsed from the title — no structured field, so nothing can reliably reconcile the two. The issue-tracker-substrate design explicitly deferred "GitHub/GitLab sync or export"; this is that deferred work.

What does this PR change?

Adds board-sync Layer 1 (state + close-reason): a deterministic toolkit (board-meta.sh, board-link.sh, board-gh-plan.sh, board-gh-apply.sh) plus a board-sync subagent and /board-sync command that reconcile the local board with GitHub issues — applying unambiguous state changes both ways against a .sync-state.json watermark and writing everything it can't safely auto-apply to SYNC-REPORT.md instead of guessing. Two additive, backward-compatible node fields (gh, labels) carry the structured link; every board write still goes through the existing invariant-enforcing scripts.

Is this change appropriate for the core library?

Argued yes — it extends existing core issue-tracker infrastructure (the board every doperpowers user's orchestrator already owns), is general-purpose (any repo that tracks work as GitHub issues), and the only third-party surface is GitHub via gh, which the issue-tracker skill already references ("If the repo tracks work on GitHub, file the GH issue…"). It is not a new domain skill or a new third-party integration. That said, this is the maintainer's call — flagging it explicitly rather than assuming.

What alternatives did you consider?

From the design Decision Log (docs/doperpowers/specs/2026-07-05-board-sync-design.md):

  • Mechanics — chose a deterministic toolkit + thin-judgment subagent over a freehand agent editing map.json (bypasses the script-enforced invariants; unsafe/unauditable on cron) and over a pure script with no agent (can't judge ambiguous close-reason mapping / conflicts).
  • Direction — chose bidirectional reconcile against a last-sync watermark over pure one-way (neither direction alone suffices: completions need board→GH, staleness needs GH→board).
  • Conflict policy — chose report-only over board-wins / GH-wins (both silently discard a human's or a daemon's intent).
  • Linkage — chose a structured gh node field + one-time title backfill over parsing (GH#NN) every run (fragile) or a separate mapping file (dual-maintenance).

Does this PR contain multiple unrelated changes?

No. One coherent feature (board↔GitHub state sync, Layer 1), delivered as a sequenced set of commits that build on each other (schema field → writers → diff → apply → agent → docs). Layers 2 (labels) and 3 (edges) are deliberately out of scope, tracked as their own future plans.

Existing PRs

  • I have reviewed all open AND closed PRs for duplicates or prior art
  • Related PRs: none found. (Searched open + closed for board / issue-tracker / sync; the "sync"-named PRs are all unrelated — dependency uv.sync, requirements docs, codex-plugin sync, package-version sync, fork-from-upstream sync. None reconcile the issue board with GitHub.)

Environment tested

Harness Harness version Model Model version/ID
Claude Code agentic CLI (this session) Claude Opus 4.8 (orchestrator) + Sonnet (workers) claude-opus-4-8 / claude-sonnet

Tests are hermetic (no network): a throwaway git repo, GitHub JSON fed via --gh-json fixtures, --dry-run/--no-github on the apply path. Both suites pass on macOS (Darwin 24.4.0): tests/issue-tracker/test-board-gh-sync.sh (28 board-sync assertions) and tests/issue-tracker/test-board-scripts.sh (no regression). shellcheck -x on the four new scripts shows only the repo-baseline SC1091 (sourced _lib.sh not followed).

New harness support (required if this PR adds a new harness)

N/A — this PR adds no harness support. It adds board-sync scripts + a subagent/command to the existing issue-tracker skill.

Evaluation

This is toolkit/infrastructure (bash + inline python3 + a subagent prompt), not behavior-shaping skill prose, so the "N eval sessions / react-todo acceptance" framing doesn't apply directly. The relevant evaluation is the subagent-driven-development review process, which measurably earned correctness the plan had glossed — the per-task and final reviews caught and fixed four material bugs, all on the automated path where no human watches, each reproduced before fixing:

  1. Watermark refresh re-walked map.json, so a filtered plan stamped held-back tickets as synced → made plan-driven (plan emits an agree list; apply refreshes only {applied} ∪ {agree}).
  2. The agent ran board-gh-plan.sh bare, which under a non-TTY subagent shell reads empty stdin and sees zero issues → the agent now fetches gh explicitly via --gh-json, and the script was hardened so a bare call defaults to gh.
  3. The not_planned GH→board branch lacked a reachability gate, emitting an auto done → wontfix that the state machine rejects and that crashed the unattended apply mid-loop → gated to a reported conflict.
  4. board-link.sh --backfill skipped its log.jsonl audit entry → fixed.

Rigor

  • If this is a skills change: I used doperpowers:writing-skills… — N/A (no behavior-shaping skill-prose change; this is toolkit + a subagent def).
  • This change was tested adversarially, not just on the happy path — reviews specifically probed filtered plans, non-TTY stdin, terminal-state transitions, injection surface (gh/ticket data → gh/board-transition.sh/JSON), and the read-only guarantee of the plan step. A final whole-branch review found and reproduced a Critical illegal-transition bug before merge.
  • I did not modify carefully-tuned content (Red Flags table, rationalizations, "human partner" language) without extensive evals — none of that content was touched.

Human review

  • A human has reviewed the COMPLETE proposed diff before submission — in progress. Opened as a draft precisely so the repo owner can review the full diff here before it moves to "ready." Not checking this box until they have.

SSFSKIM added 17 commits July 5, 2026 07:31
@SSFSKIM
SSFSKIM marked this pull request as ready for review July 5, 2026 13:18
@SSFSKIM

SSFSKIM commented Jul 5, 2026

Copy link
Copy Markdown
Owner Author

Review gates passed before merge:

  • Per-task reviews (Sonnet, spec + quality) on every task — all fixes re-verified.
  • Opus whole-branch review — found & reproduced a Critical (not_planned GH→board emitted an auto done → wontfix that crashed the unattended apply); fixed via a done-reachability gate + regression test, plus TTY-footgun hardening and cleanups.
  • Codex (gpt-5.5, xhigh) independent whole-branch review — confirmed reconcile correctness, injection safety, atomicity; surfaced 3 Important, all fixed: --no-github no longer watermarks skipped board→gh actions; board-reconcile.sh now surfaces pending SYNC-REPORT.md conflicts (spec §5 promise the plan had missed); agent uses a per-run mktemp -d.

Both hermetic suites green (28+ board-sync assertions + existing toolkit, no regression); shellcheck baseline-clean. Human partner (repo owner) authorized the merge after the review pass.

@SSFSKIM
SSFSKIM merged commit 7b6876e into main Jul 5, 2026
@SSFSKIM
SSFSKIM deleted the feat/board-sync branch July 5, 2026 13:23
SSFSKIM added a commit that referenced this pull request Jul 10, 2026
Two-tier trust (review #1, human design call): developer feedback — the
server-resolved role snapshot in TRIAGE_TRUSTED_ROLES (default admin), or
a stripped .env #TRIAGE_DEV_CODE body prefix — is read as instruction
(R1/R4 waived: dev ideas can be born ready-for-agent, labeled
source:dev-feedback); user feedback keeps the conservative gate, residual
risk explicitly accepted in the Decision Log. The dev code is stripped
before the body reaches the prompt or ticket so it never leaks into a
public issue.

The rest of the review, all fixed:
- #2 R2 requires a REAL file citation (path-shaped after :line strip;
  unknown:12 no longer counts)
- #3 R3 scans risk SYMBOLS (assertStudentAccess, supabaseAdmin, RLS,
  generate-plan layout fns, past_exam_problems, SUPABASE_SERVICE_ROLE_KEY)
  in addition to paths
- #4 claim issues a lease token; writeback is lease-conditional (late
  writeback after reclaim throws instead of clobbering); reclaim window
  validated at config load; second idempotency check right before
  registerTicket
- #5 findExisting fails closed on gh search errors
- #6 ticket body temp files: mkdtemp dir, mode 0600, removed in finally
- #7 TRIAGE_ENABLED checked before config parsing
- #8 spec drift fixed (feedback-dispatch.ts references, two-kill-switches)

p86 DDL note gains triage_lease UUID. New src/trust.ts. 91 tests green,
tsc clean.
SSFSKIM added a commit that referenced this pull request Jul 31, 2026
… (simplicity audit #2)

Drop the Iron Law block, letter-vs-spirit clause, and 5-step gate
pseudo-code; keep the evidence table's non-obvious rows. Replace two
rigid definitions with the principles they approximated: freshness =
no relevant change since the evidence was produced (not message
boundaries), scope = verification proportional to the claim (not
always the full command).
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