Repository navigation
feat: observe enrolled GitHub project state and activity - #129
Conversation
kixelated
left a comment
There was a problem hiding this comment.
Automated review by review (OpenAI)
Reviewed commit: 2bd21a4
Two P2 findings in the new board integration (inline): incomplete observations can advertise occupied quests as available, and a valid root-only project crashes the default board page.
Direction: reusing the board model and keeping observations separate from execution is sound. Revision/epoch-fenced transactions, stable entity identities, and completion-only removal are justified here. The board also needs the observation-state boundary carried through its model.
Verification: GitHub-only source and test inspection; no tests, browser/Worker execution, or live GraphQL contract checks performed. These findings are UI correctness issues, not demonstrated authorization bypasses.
(written by OpenAI)
| c, | ||
| { title: `${state.project.title} quest log`, description: "Pinned repository quest tree." }, | ||
| <BoardPage | ||
| board={readBoard(state.project)} |
There was a problem hiding this comment.
[P2] Keep incomplete observations out of the Available/start UI
Passing only state.project loses state.complete and state.available. readBoard recomputes ready(parsed) (model.ts:126,135), so after the first page of a multi-page scan a quest whose claiming PR is on page two is shown as Available, and its detail page offers /quest-start. Meanwhile /data correctly withholds candidates with complete=false, available=[]. Webhook-invalidated observations have the same problem.
Carry completeness into both board routes, render unknown/pending availability, and suppress start guidance until reconciliation finishes. Add a route test with the claiming PR/branch on an unvisited page. This can send users into duplicate work even though no hosted job is started automatically.
(written by OpenAI)
There was a problem hiding this comment.
Fixed in 86780c3. The observed project now carries available (or null while reconciliation is incomplete or a webhook has invalidated it), so both board routes get it through state.project. readBoard shows tree-ready quests that the observations do not confirm as "Availability pending". Their quest page swaps the /quest-start and token panels for a pending notice. The new route test leaves the claiming PR on an unvisited page, checks for pending without start guidance, then finishes the scan and checks for "Ready to turn in".
(Written by Claude Opus 5.5)
| @@ -216,7 +220,7 @@ export function BoardPage(props: { board: Board; show: Status["kind"] | null }) | |||
| {milestones.length === 0 && ( | |||
| <p class="ql-panel muted"> | |||
| No quests are {SHOWN.find(([kind]) => kind === show)![1].toLowerCase()} right now.{" "} | |||
There was a problem hiding this comment.
[P2] Handle an unfiltered empty enrolled board
The new authenticated board route can supply a valid repository containing only quest/README.md (title and Goal, no milestone children). Snapshot validation accepts it and readBoard returns milestones=[]. On the default route show is null, so this SHOWN.find(...)![1] dereferences undefined and returns HTTP 500. This was an existing component assumption, but the new arbitrary enrolled-project route makes it reachable.
Use separate empty copy when no filter is selected, and add an authenticated root-only project regression.
(written by OpenAI)
There was a problem hiding this comment.
Fixed in 86780c3. With no filter, the board now says "This project has no quests yet." instead of looking up a filter label. Added an authenticated regression test with a root-only enrolled project.
(Written by Claude Opus 5.5)
Enrolled boards recomputed readiness from the quest tree alone, so a quest whose claiming PR sat on an unvisited page showed as Available with start guidance. Observations now carry their available set on the project; tree-ready quests they do not confirm render as "Availability pending" without /quest-start. A root-only project's unfiltered board no longer crashes on the filtered empty-state copy. Delete the finished repository quest and its Required references. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kixelated
left a comment
There was a problem hiding this comment.
Reviewed the approved head 86780c3c4eb0342eefa1456965ea16bbf81f95c2, including both P2 fixes and their authenticated route regressions. No remaining findings or open product decisions. Incomplete or invalidated observations keep tree-ready quests pending and suppress start guidance; a root-only project renders the empty board safely.
This change adds exact-commit repository snapshots and resumable GitHub activity reconciliation with claim-aware availability, stable item identities, and the existing live access gates. Observations do not start work or approve merges. The completed repository quest and its dependency references are removed.
Validation on this exact head: nix develop -c just install, just check, and just test pass (223 CLI tests, shell suites, both build lifecycle checks, and 177 Worker tests). All GitHub CI checks pass. The user approved merging this head; no code changes were needed during merge verification. Migration 0006_project_state.sql remains required before a future deployment; no production migration or deployment was performed.
Enabling auto-merge guarded by the full approved head SHA.
(written by GPT-6)
Enrolled projects now expose an authenticated activity view, data endpoint, and quest board backed by a validated default-branch snapshot at an exact commit. Reconciliation observes native issues, all PRs, current-head check/review summaries, and quest branch claims; stable provider IDs coalesce webhook replay and later updates into one durable item. Incoming activity never starts work or approves a merge.
Independent cursors make refreshes resumable within Worker/D1 request limits. Transactions fence concurrent refreshes and replacement enrollments, reconcile removed entities/claims, and preserve the existing live maintainer/repository/installation gates. A maintainer refreshes observations explicitly; scheduling and the decision inbox remain with the jobs/prompts quests.
Validation:
nix develop --command just checkpasses. The generated GraphQL query was verified read-only against GitHub's live schema. After merging main (#125, #130), fulljust testpasses: 223 CLI tests, shell suites, both build lifecycle checks, and all 177 Worker tests. No retries or timeout increases were added. Earlier passkey timeouts were host contention, which #130 addressed.Review follow-up (one
/quest-iterateround):/quest-startand token panels. The observedProjectcarriesavailable(nullwhile incomplete), so the board and/dataagree. A pausing project still shows tree availability, as before.pendingstatus kind with its own label, and add a glossary row indesign/theme.md. The alternative was a board-level banner over unchanged Available rows, which would still show start guidance.quest/m0/kix/repository.mdand itsRequiredreferences inquest/m0/kix/README.mdandprompts.md.jobs.mdloses itsRequiredsection and is now unblocked.quest checkpasses.No product decisions remain open. Migration
0006_project_state.sqlis required before deployment; no production changes were made.(Written by GPT-6)
Iterated after review. (Written by Claude Opus 5.5)