0b93a985d6
Read dev/issues/*.md and dev/flows/*.md as kanban cards via new
/api/boards/{issues|flows}/cards endpoints. PATCH writes status back
to the frontmatter atomically (tmp + rename), POST .../launch proxies
to agent_runner_api.
- issues_source.go: scan + parse frontmatter (yaml.v3) into IssueCard.
Skips README/INDEX/AGENT_GUIDE. Malformed YAML yields parse-error
cards (no crash). Description = first 5 body lines (no full body).
- flows_source.go: same shape, distinct status->column mapping
(pending/running/done/deferred -> Pending/Running/Done/Deferred).
- frontmatter_edit.go: PatchFrontmatterField — atomic, preserves the
rest of the file byte-for-byte, inserts key if missing.
- handlers_boards.go: list + patch + launch endpoints, taxonomy 0103
enforced. Cache 30s in memory, thread-safe (mutex), invalidated on
PATCH. Launch returns 502 with suggestion when runner is down.
- main.go: SkipPaths += "/api/boards/" so the C++ frontend hits the
read endpoints without a kanban_web session.
Smoke (FN_REGISTRY_ROOT pointed at the worktree, 87 issues + 9 flows
on disk):
GET /api/boards/issues/cards -> 200, 87 cards
GET /api/boards/flows/cards -> 200, 9 cards
PATCH /api/boards/issues/cards/0119 {status:en-curso} -> 200,
file mtime changes, frontmatter rewritten, rest preserved
POST /api/boards/issues/cards/0119/launch -> 502
agent_runner_unreachable (expected, runner not yet implemented)
Tests: issues_source_test (3 cases incl. malformed + missing status),
flows_source_test (3 cases), frontmatter_edit_test (4 cases incl.
atomic rename + no tmp leftovers). Pre-existing tools_test failure
on TestExecuteTool_MoveCard_BetweenColumns_OpensHistory is unrelated
(CardHistoryResponse type assert, not touched here).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
36 lines
779 B
Go
36 lines
779 B
Go
package main
|
|
|
|
import (
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// flowsCache mirrors issuesCache but for dev/flows/*.md.
|
|
var flowsCache = &cardsCache{ttl: 30 * time.Second}
|
|
|
|
// mapFlowStatusToColumn maps flow frontmatter status -> kanban column id.
|
|
// Flows use a different vocabulary than issues.
|
|
func mapFlowStatusToColumn(status string) string {
|
|
switch strings.ToLower(strings.TrimSpace(status)) {
|
|
case "pending", "":
|
|
return "Pending"
|
|
case "running":
|
|
return "Running"
|
|
case "done":
|
|
return "Done"
|
|
case "deferred":
|
|
return "Deferred"
|
|
default:
|
|
return "Pending"
|
|
}
|
|
}
|
|
|
|
func loadFlowCards(dir string) ([]IssueCard, error) {
|
|
return loadCardsFromDir(dir, mapFlowStatusToColumn, "flow")
|
|
}
|
|
|
|
func flowsDir() string {
|
|
return filepath.Join(registryRoot(), "dev", "flows")
|
|
}
|