Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 1x 1x 1x 1x 1x 1x 1x | import * as path from "node:path" import { loadPlanningPayloadFromSqliteDetailed, sqliteDbExists, } from "./load-from-sqlite.js" import { sortByIdAsc } from "./domain/sort-by-id.js" import { allSelectedVersionIds } from "./domain/version-filter.js" import type { EpicSummary } from "./load-epics.js" import type { SprintSummary } from "./load-sprints.js" import type { VersionSummary } from "./load-versions.js" import type { UserStory } from "./domain/types.js" export type PlanningPayload = { versions: VersionSummary[] epics: EpicSummary[] sprints: SprintSummary[] stories: UserStory[] } export type PlanningLoadResult = | { ok: true; payload: PlanningPayload } | { ok: false; error: string } function sqliteRequiredMessage(packageRoot: string): string { return ( `Meridian: .meridian/meridian.db not found under ${packageRoot}.\n` + "Run: python3 .agent/scripts/meridian_delivery.py bootstrap" ) } /** v10+: delivery data comes only from SQLite — no docs/us fallback. */ export function loadPlanningPayloadDetailed( docsRoot: string, packageRoot?: string, ): PlanningLoadResult { const pkg = packageRoot ?? path.dirname(docsRoot) if (!sqliteDbExists(pkg)) { return { ok: false, error: sqliteRequiredMessage(pkg) } } const fromDb = loadPlanningPayloadFromSqliteDetailed(pkg) if (fromDb.error || !fromDb.payload) { return { ok: false, error: fromDb.error ?? "Meridian: SQLite planning export failed.", } } if (fromDb.payload.stories.length === 0) { return { ok: false, error: "Meridian: meridian.db has zero user stories." } } return { ok: true, payload: fromDb.payload } } /** Throws if SQLite load fails — use loadPlanningPayloadDetailed when UI needs error text. */ export function loadPlanningPayload(docsRoot: string, packageRoot?: string): PlanningPayload { const result = loadPlanningPayloadDetailed(docsRoot, packageRoot) if (!result.ok) { throw new Error(result.error) } return result.payload } /** Lists sorted by id (v0, v4-S2, EPIC-05); version chips default to all selected. */ export function planningPayloadForListViews( payload: PlanningPayload, ): PlanningPayload & { defaultVersions: string[] } { const versions = sortByIdAsc(payload.versions) return { ...payload, versions, sprints: sortByIdAsc(payload.sprints), epics: sortByIdAsc(payload.epics), defaultVersions: allSelectedVersionIds(versions.map((v) => v.id)), } } export function planningPayloadForVersionsView(payload: PlanningPayload): PlanningPayload { return { ...payload, versions: sortByIdAsc(payload.versions), } } |