fn-9.4 flowctl integration lib
Description
Create flowctl integration library for spawning and parsing output.
File
src/lib/flowctl.ts
Functions
// Find flowctl path (bundled or .flow/bin)
// Note: async due to filesystem checks during path resolution
async function getFlowctlPath(): Promise<string>
// Run flowctl command, parse JSON output
async function flowctl<T>(args: string[]): Promise<T>
// List commands (return minimal types matching flowctl output)
async function getEpics(): Promise<EpicListItem[]> // id, title, status, tasks (count), done (count)
async function getTasks(epicId: string): Promise<TaskListItem[]> // id, epic, title, status, priority, depends_on
async function getReadyTasks(epicId: string): Promise<ReadyResponse> // ready/in_progress/blocked TaskSummary arrays
// Detail commands (return full types via flowctl show)
async function getEpic(epicId: string): Promise<Epic>
async function getTask(taskId: string): Promise<Task>
async function getTaskSpec(taskId: string): Promise<string>
flowctl location (for npm-distributed TUI)
Search order:
.flow/bin/flowctl (installed via /flow-next:setup)
./plugins/flow-next/scripts/flowctl (repo-local plugin checkout)
flowctl or flowctl.py on PATH
- Error with message: "flowctl not found. Run
/flow-next:setup or ensure flow-next plugin is installed."
Invocation
flowctl.py is a Python script with shebang. Invoke via:
Bun.spawn(['python3', flowctlPath, ...args])
// OR if shebang works:
Bun.spawn([flowctlPath, ...args])
Detect which works and cache the method.
Error handling
- Parse JSON errors gracefully
- Return typed error objects
- Handle non-zero exit codes
Acceptance
Done summary
- Added
src/lib/flowctl.ts with path resolution and JSON command runner
- Searches .flow/bin, plugins dir, repo root (via .git/HEAD), then PATH
- Helper functions: getEpics, getTasks, getTaskSpec, getReadyTasks, getEpic, getTask
- FlowctlError class with command, exit code, stderr context
Why:
- TUI needs to invoke flowctl commands and parse results
- Path resolution handles running from subdirectories
Verification:
- 32 tests pass including integration tests with real flowctl
- Lint clean (oxlint)
Evidence
- Commits: 54a450cc6f6f1d6d2aaa4f46eed3dec2a134d788
- Tests: bun test
- PRs:
1---2name: 136-fn-94-2b528cba3description: fn-9.4 flowctl integration lib4---5# fn-9.4 flowctl integration lib67## Description89Create flowctl integration library for spawning and parsing output.1011### File1213`src/lib/flowctl.ts`1415### Functions1617```typescript18// Find flowctl path (bundled or .flow/bin)19// Note: async due to filesystem checks during path resolution20async function getFlowctlPath(): Promise<string>2122// Run flowctl command, parse JSON output23async function flowctl<T>(args: string[]): Promise<T>2425// List commands (return minimal types matching flowctl output)26async function getEpics(): Promise<EpicListItem[]> // id, title, status, tasks (count), done (count)27async function getTasks(epicId: string): Promise<TaskListItem[]> // id, epic, title, status, priority, depends_on28async function getReadyTasks(epicId: string): Promise<ReadyResponse> // ready/in_progress/blocked TaskSummary arrays2930// Detail commands (return full types via flowctl show)31async function getEpic(epicId: string): Promise<Epic>32async function getTask(taskId: string): Promise<Task>33async function getTaskSpec(taskId: string): Promise<string>34```3536### flowctl location (for npm-distributed TUI)3738Search order:391. `.flow/bin/flowctl` (installed via `/flow-next:setup`)402. `./plugins/flow-next/scripts/flowctl` (repo-local plugin checkout)413. `flowctl` or `flowctl.py` on PATH424. Error with message: "flowctl not found. Run `/flow-next:setup` or ensure flow-next plugin is installed."4344### Invocation4546flowctl.py is a Python script with shebang. Invoke via:47```typescript48Bun.spawn(['python3', flowctlPath, ...args])49// OR if shebang works:50Bun.spawn([flowctlPath, ...args])51```5253Detect which works and cache the method.5455### Error handling5657- Parse JSON errors gracefully58- Return typed error objects59- Handle non-zero exit codes60## Acceptance61- [ ] `getFlowctlPath()` finds flowctl or throws helpful error62- [ ] `flowctl(['epics', '--json'])` returns parsed JSON63- [ ] `getTasks('fn-1')` returns Task[] matching types64- [ ] `getTaskSpec('fn-1.1')` returns markdown string65- [ ] Errors include context (command, exit code, stderr)66## Done summary67- Added `src/lib/flowctl.ts` with path resolution and JSON command runner68- Searches .flow/bin, plugins dir, repo root (via .git/HEAD), then PATH69- Helper functions: getEpics, getTasks, getTaskSpec, getReadyTasks, getEpic, getTask70- FlowctlError class with command, exit code, stderr context7172Why:73- TUI needs to invoke flowctl commands and parse results74- Path resolution handles running from subdirectories7576Verification:77- 32 tests pass including integration tests with real flowctl78- Lint clean (oxlint)79## Evidence80- Commits: 54a450cc6f6f1d6d2aaa4f46eed3dec2a134d78881- Tests: bun test82- PRs: