The app now displays its own live backlog instead of fixtures. First end of the sync loop — the tap-root (#1) grows list reads and a read path through the Electron main process. - @commitea/core: client gains `listIssues` (paginated, PRs excluded) and `listMilestones`; a `lifecycle-v0` mapper (closed→done, labelled/milestoned→triage, bare→diagnosis — steeping/review await event inference in P1-5). +10 unit tests. - main: gitea bridge over IPC (token stays in main, never the renderer); config from env / .env.local; gated off under COMMITEA_E2E so the committed e2e stays on fixtures. Preload exposes the typed bridge. - renderer: useBacklog() reconciles once on mount; issuesToBoardColumns shapes real issues into The pot. Board takes optional real columns + a loading state, falling back to demo fixtures when unconfigured. Verified: 14 e2e green (fixture mode) + a gated live spec that launches against the real repo — the board renders the actual 25 open + 9 closed issues (screenshot). SQLite mirror + reconcile-on-a-timer + lifecycle event inference are the next slices (#2/#3/#5). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
33 lines
1.2 KiB
TypeScript
33 lines
1.2 KiB
TypeScript
/**
|
|
* Lifecycle inference, v0 — the coarse column an issue sits in, derived from
|
|
* *only* what a single issues-list read gives us (state, labels, milestone).
|
|
*
|
|
* The real five-column inference (P1-5) needs the issue timeline: first
|
|
* branch/commit ref → Steeping, PR opened → In review, PR merged → Deploy.
|
|
* Until that lands, v0 can only place three columns honestly; `steeping` and
|
|
* `review` stay empty rather than guess. Board renders all five columns and
|
|
* fills the middle two once the event stream is available.
|
|
*/
|
|
|
|
import type { GiteaIssue } from '../gitea/types.js'
|
|
|
|
export type LifecycleColumn = 'diagnosis' | 'triage' | 'steeping' | 'review' | 'done'
|
|
|
|
export const LIFECYCLE_COLUMNS: readonly LifecycleColumn[] = [
|
|
'diagnosis',
|
|
'triage',
|
|
'steeping',
|
|
'review',
|
|
'done',
|
|
]
|
|
|
|
/**
|
|
* Closed → done. Open with any human intent applied (a label or a milestone)
|
|
* → triage. Open and bare → diagnosis. Never returns steeping/review in v0.
|
|
*/
|
|
export function inferColumnV0(issue: Pick<GiteaIssue, 'state' | 'labels' | 'milestone'>): LifecycleColumn {
|
|
if (issue.state === 'closed') return 'done'
|
|
const hasIntent = issue.labels.length > 0 || issue.milestone !== null
|
|
return hasIntent ? 'triage' : 'diagnosis'
|
|
}
|