/** * One-shot markdown backlog import. * * Sibling of `watch-markdown-backlog.ts` but runs ONE sweep and exits. Use * this when you want to bootstrap or refresh the DB from `plans/**` without * leaving a long-running file watcher in place — particularly important * during agent sessions, because the watcher's upsert overwrites * `markdown_backlog_items.status` from frontmatter on every sweep and would * clobber `claim_task` / `complete_task` state. * * Until the DB → markdown export side ships (see follow-up task), the * convention is: * - Edit `.md` files to author / refine intent. * - Run this script when you want the changes in the DB. * - Let agents drive runtime status via MCP tools BETWEEN syncs. * * Env: * - DATABASE_URL (required) * - MARKDOWN_BACKLOG_WORKSPACE_ID — UUID of the target workspace (required) * - MARKDOWN_BACKLOG_REPO_ROOT — absolute path to repo root (default: * walk up from this script looking for `pnpm-workspace.yaml`, then fall * back to cwd). The walk is necessary because `pnpm --filter @tasks/database` * sets cwd to `packages/database`, NOT the repo root, and a naive cwd * resolution would scan a non-existent `packages/database/plans/` * directory — and then proceed to delete every "stale" row because * it found zero files. */ import { existsSync } from "node:fs"; import { dirname, join, resolve } from "node:path"; import { fileURLToPath } from "node:url"; import { db } from "../client"; import { syncMarkdownBacklogScan } from "../markdown-backlog/sync"; function findRepoRootByMarker(start: string): string | null { let dir = start; for (let i = 0; i < 10; i++) { if (existsSync(join(dir, "pnpm-workspace.yaml"))) return dir; const parent = dirname(dir); if (parent === dir) return null; dir = parent; } return null; } function resolveRepoRoot(): string { const envOverride = process.env.MARKDOWN_BACKLOG_REPO_ROOT?.trim(); if (envOverride && envOverride.length > 0) return resolve(envOverride); const fileDir = dirname(fileURLToPath(import.meta.url)); const fromFile = findRepoRootByMarker(fileDir); if (fromFile) return fromFile; const fromCwd = findRepoRootByMarker(process.cwd()); if (fromCwd) return fromCwd; return resolve(process.cwd()); } const workspaceId = process.env.MARKDOWN_BACKLOG_WORKSPACE_ID?.trim(); const repoRootAbs = resolveRepoRoot(); if (!workspaceId) { console.error( "[import-markdown-backlog] Set MARKDOWN_BACKLOG_WORKSPACE_ID to your workspace UUID.", ); process.exit(1); } void (async () => { try { const result = await syncMarkdownBacklogScan(db, { workspaceId, repoRootAbs, }); console.log( `[import-markdown-backlog] done — scanned ${result.scannedFiles} files, upserted ${result.upsertedRows} rows, deleted ${result.deletedRows} stale rows. Repo root: ${repoRootAbs}`, ); process.exit(0); } catch (e) { console.error("[import-markdown-backlog] sync failed:", e); process.exit(1); } })();