@fabricorg/cli 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/bin/fabric.ts","../src/commands/agents/index.ts","../src/lib/client.ts","../src/lib/config.ts","../src/lib/output.ts","../src/lib/context.ts","../src/commands/auth/keys.ts","../src/commands/auth/login.ts","../src/commands/auth/logout.ts","../src/commands/auth/whoami.ts","../src/commands/chats/index.ts","../src/commands/completion/index.ts","../src/commands/ctx/index.ts","../src/commands/features/index.ts","../src/commands/frames/index.ts","../src/commands/instructions/index.ts","../src/lib/instructions/apply.ts","../src/lib/instructions/paths.ts","../src/lib/instructions/safe-write.ts","../src/lib/instructions/bundle.ts","../src/lib/instructions/hook.ts","../src/lib/instructions/lock.ts","../src/lib/instructions/manifest.ts","../src/lib/instructions/plan.ts","../src/commands/mcp/index.ts","../src/commands/orgs/index.ts","../src/commands/projects/index.ts","../src/commands/prompts/index.ts","../src/commands/reports/index.ts","../src/commands/skills/index.ts","../src/commands/workflows/index.ts","../src/commands/workspaces/index.ts"],"sourcesContent":["/**\n * @fabricorg/cli — fabric command\n *\n * Usage: fabric <command> [subcommand] [options]\n *\n * Exit codes:\n * 0 success\n * 1 general failure\n * 2 invalid usage / bad arguments\n * 3 auth failure\n * 4 not found\n * 5 forbidden\n * 6 rate limited\n * 7 validation error\n */\n\nimport { Command } from \"commander\";\nimport { buildAgentsCommand } from \"../commands/agents/index.js\";\nimport { buildKeysCommand } from \"../commands/auth/keys.js\";\nimport { buildLoginCommand } from \"../commands/auth/login.js\";\nimport { buildLogoutCommand } from \"../commands/auth/logout.js\";\nimport { buildWhoamiCommand } from \"../commands/auth/whoami.js\";\nimport { buildChatsCommand } from \"../commands/chats/index.js\";\nimport { buildCompletionCommand } from \"../commands/completion/index.js\";\nimport { buildCtxCommand } from \"../commands/ctx/index.js\";\nimport { buildFeaturesCommand } from \"../commands/features/index.js\";\nimport { buildFramesCommand } from \"../commands/frames/index.js\";\nimport { buildInstructionsCommand } from \"../commands/instructions/index.js\";\nimport { buildMcpCommand } from \"../commands/mcp/index.js\";\nimport { buildOrgsCommand } from \"../commands/orgs/index.js\";\nimport { buildProjectsCommand } from \"../commands/projects/index.js\";\nimport { buildPromptsCommand } from \"../commands/prompts/index.js\";\nimport { buildReportsCommand } from \"../commands/reports/index.js\";\nimport { buildSkillsCommand } from \"../commands/skills/index.js\";\nimport { buildWorkflowsCommand } from \"../commands/workflows/index.js\";\nimport { buildWorkspacesCommand } from \"../commands/workspaces/index.js\";\nimport { getConfigPath } from \"../lib/config.js\";\n\nconst program = new Command();\n\nprogram\n\t.name(\"fabric\")\n\t.description(\"Fabric AI platform CLI\")\n\t.version(\"0.1.0\")\n\t.option(\n\t\t\"--format <format>\",\n\t\t\"Output format: table|json|yaml|csv\",\n\t\tprocess.env.FABRIC_FORMAT ?? \"table\",\n\t);\n\n// ---------------------------------------------------------------------------\n// fabric auth\n// ---------------------------------------------------------------------------\nconst auth = new Command(\"auth\").description(\n\t\"Authenticate and manage API keys\",\n);\nauth.addCommand(buildLoginCommand());\nauth.addCommand(buildLogoutCommand());\nauth.addCommand(buildWhoamiCommand());\nauth.addCommand(buildKeysCommand());\nprogram.addCommand(auth);\n\n// ---------------------------------------------------------------------------\n// fabric ctx\n// ---------------------------------------------------------------------------\nprogram.addCommand(buildCtxCommand());\n\n// ---------------------------------------------------------------------------\n// fabric orgs\n// ---------------------------------------------------------------------------\nprogram.addCommand(buildOrgsCommand());\n\n// ---------------------------------------------------------------------------\n// fabric projects\n// ---------------------------------------------------------------------------\nprogram.addCommand(buildProjectsCommand());\n\n// ---------------------------------------------------------------------------\n// fabric features\n// ---------------------------------------------------------------------------\nprogram.addCommand(buildFeaturesCommand());\n\n// ---------------------------------------------------------------------------\n// fabric workflows\n// ---------------------------------------------------------------------------\nprogram.addCommand(buildWorkflowsCommand());\n\n// ---------------------------------------------------------------------------\n// fabric prompts\n// ---------------------------------------------------------------------------\nprogram.addCommand(buildPromptsCommand());\n\n// ---------------------------------------------------------------------------\n// fabric agents\n// ---------------------------------------------------------------------------\nprogram.addCommand(buildAgentsCommand());\n\n// ---------------------------------------------------------------------------\n// fabric skills\n// ---------------------------------------------------------------------------\nprogram.addCommand(buildSkillsCommand());\n\n// ---------------------------------------------------------------------------\n// fabric instructions\n// ---------------------------------------------------------------------------\nprogram.addCommand(buildInstructionsCommand());\n\n// ---------------------------------------------------------------------------\n// fabric mcp\n// ---------------------------------------------------------------------------\nprogram.addCommand(buildMcpCommand());\n\n// ---------------------------------------------------------------------------\n// fabric frames\n// ---------------------------------------------------------------------------\nprogram.addCommand(buildFramesCommand());\n\n// ---------------------------------------------------------------------------\n// fabric workspaces\n// ---------------------------------------------------------------------------\nprogram.addCommand(buildWorkspacesCommand());\n\n// ---------------------------------------------------------------------------\n// fabric chats\n// ---------------------------------------------------------------------------\nprogram.addCommand(buildChatsCommand());\n\n// ---------------------------------------------------------------------------\n// fabric reports\n// ---------------------------------------------------------------------------\nprogram.addCommand(buildReportsCommand());\n\n// ---------------------------------------------------------------------------\n// fabric completion\n// ---------------------------------------------------------------------------\nprogram.addCommand(buildCompletionCommand());\n\n// ---------------------------------------------------------------------------\n// fabric config\n// ---------------------------------------------------------------------------\nconst config = new Command(\"config\").description(\"Show CLI configuration\");\nconfig\n\t.command(\"path\")\n\t.description(\"Print the path to the config file\")\n\t.action(() => {\n\t\tprocess.stdout.write(`${getConfigPath()}\\n`);\n\t});\nprogram.addCommand(config);\n\n// ---------------------------------------------------------------------------\n// Global error handler — structured JSON for --format json\n// ---------------------------------------------------------------------------\nprocess.on(\"unhandledRejection\", (reason) => {\n\tconst message = reason instanceof Error ? reason.message : String(reason);\n\tif (process.env.FABRIC_FORMAT === \"json\") {\n\t\tprocess.stderr.write(\n\t\t\tJSON.stringify({ error: { message, code: \"UNHANDLED_ERROR\" } }) +\n\t\t\t\t\"\\n\",\n\t\t);\n\t} else {\n\t\tprocess.stderr.write(`✗ ${message}\\n`);\n\t}\n\tprocess.exit(1);\n});\n\nprogram.parse(process.argv);\n","/**\n * fabric agents\n *\n * fabric agents list List agents\n * fabric agents show <id> Show agent details\n */\n\nimport type { FabricAgent } from \"@fabricorg/sdk\";\nimport { Command } from \"commander\";\nimport { getClient } from \"../../lib/client.js\";\nimport { resolveContext } from \"../../lib/context.js\";\nimport { printError, printOutput, printRecord } from \"../../lib/output.js\";\n\nexport function buildAgentsCommand(): Command {\n\tconst agents = new Command(\"agents\").description(\"Manage agents\");\n\n\t// -- list ----------------------------------------------------------------\n\tagents\n\t\t.command(\"list\")\n\t\t.description(\"List agents\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--status <status>\", \"Filter: ACTIVE|INACTIVE|DEPRECATED\")\n\t\t.option(\"--limit <n>\", \"Max results\", \"50\")\n\t\t.option(\n\t\t\t\"--format <format>\",\n\t\t\t\"Output format: table|json|yaml|csv\",\n\t\t\t\"table\",\n\t\t)\n\t\t.option(\"-q, --quiet\", \"Print IDs only\")\n\t\t.action(\n\t\t\tasync (opts: {\n\t\t\t\torg?: string;\n\t\t\t\tpersonal?: boolean;\n\t\t\t\tstatus?: string;\n\t\t\t\tlimit: string;\n\t\t\t\tformat: string;\n\t\t\t\tquiet?: boolean;\n\t\t\t}) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet list: FabricAgent[];\n\t\t\t\ttry {\n\t\t\t\t\tlist = await client.agents.list({\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t\tstatus: opts.status as\n\t\t\t\t\t\t\t| FabricAgent[\"status\"]\n\t\t\t\t\t\t\t| undefined,\n\t\t\t\t\t\tlimit: Number(opts.limit),\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tif (opts.quiet) {\n\t\t\t\t\tfor (const a of list) {\n\t\t\t\t\t\tprocess.stdout.write(`${a.id}\\n`);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintOutput(list, {\n\t\t\t\t\tformat: opts.format as \"table\" | \"json\" | \"yaml\" | \"csv\",\n\t\t\t\t\tcolumns: [\n\t\t\t\t\t\t\"id\",\n\t\t\t\t\t\t\"name\",\n\t\t\t\t\t\t\"displayName\",\n\t\t\t\t\t\t\"framework\",\n\t\t\t\t\t\t\"status\",\n\t\t\t\t\t\t\"createdAt\",\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\t// -- show ----------------------------------------------------------------\n\tagents\n\t\t.command(\"show <id>\")\n\t\t.description(\"Show agent details\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tid: string,\n\t\t\t\topts: { org?: string; personal?: boolean; format: string },\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet agent: FabricAgent;\n\t\t\t\ttry {\n\t\t\t\t\tagent = await client.agents.get(id, {\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(agent, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintRecord({\n\t\t\t\t\tID: agent.id,\n\t\t\t\t\t\"Agent ID\": agent.agentId,\n\t\t\t\t\tName: agent.name,\n\t\t\t\t\t\"Display name\": agent.displayName,\n\t\t\t\t\tFramework: agent.framework,\n\t\t\t\t\tStatus: agent.status,\n\t\t\t\t\t\"Deployment URL\": agent.deploymentUrl ?? \"(none)\",\n\t\t\t\t\tCreated: agent.createdAt.slice(0, 10),\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\t// -- execute -------------------------------------------------------------\n\tagents\n\t\t.command(\"execute <id>\")\n\t\t.description(\"Execute an agent\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--input <json>\", 'Input JSON (e.g. \\'{\"key\":\"value\"}\\')')\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tid: string,\n\t\t\t\topts: {\n\t\t\t\t\torg?: string;\n\t\t\t\t\tpersonal?: boolean;\n\t\t\t\t\tinput?: string;\n\t\t\t\t\tformat: string;\n\t\t\t\t},\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\n\t\t\t\tlet inputObj: Record<string, unknown> = {};\n\t\t\t\tif (opts.input) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tinputObj = JSON.parse(opts.input);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tprintError(\"--input must be valid JSON\", 2);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tlet result: import(\"@fabricorg/sdk\").FabricAgentExecution;\n\t\t\t\ttry {\n\t\t\t\t\tresult = await client.agents.execute(id, {\n\t\t\t\t\t\tinput: inputObj,\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(result, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintRecord({\n\t\t\t\t\t\"Task ID\": result.taskId,\n\t\t\t\t\t\"Workflow ID\": result.workflowId,\n\t\t\t\t\t\"Run ID\": result.runId ?? \"(pending)\",\n\t\t\t\t\tStatus: result.status,\n\t\t\t\t\t...(result.warning ? { Warning: result.warning } : {}),\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\treturn agents;\n}\n","/**\n * Returns a configured FabricClient for CLI commands.\n * Exits with a clear error if no API key is available.\n */\n\nimport { FabricAuthError, FabricClient } from \"@fabricorg/sdk\";\nimport { getApiKey, getBaseUrl } from \"./config.js\";\nimport { printError } from \"./output.js\";\n\nexport interface ClientOverrides {\n\t/**\n\t * Retry policy. The SDK's default retries twice, and its timeout is PER\n\t * ATTEMPT, so a \"5 second\" call can really take about 15.75 seconds with\n\t * backoff. Session-hook mode turns retries off so its own deadline is the\n\t * only bound that matters.\n\t */\n\tretry?: { maxRetries: number };\n\t/**\n\t * Per-request timeout. The SDK sets this on the CLIENT, not per call, so\n\t * a command that must answer fast — the session-start instructions check\n\t * — builds its own client rather than reaching for a per-call option that\n\t * does not exist.\n\t */\n\ttimeoutMs?: number;\n}\n\nexport function getClient(overrides: ClientOverrides = {}): FabricClient {\n\tconst apiKey = getApiKey();\n\n\tif (!apiKey) {\n\t\tprintError(\n\t\t\t\"Not authenticated. Run:\\n fabric auth login --key <api-key>\",\n\t\t\t3,\n\t\t);\n\t}\n\n\ttry {\n\t\treturn new FabricClient({\n\t\t\tapiKey,\n\t\t\tbaseUrl: getBaseUrl(),\n\t\t\t...(overrides.timeoutMs !== undefined\n\t\t\t\t? { timeoutMs: overrides.timeoutMs }\n\t\t\t\t: {}),\n\t\t\t...(overrides.retry !== undefined\n\t\t\t\t? { retry: overrides.retry }\n\t\t\t\t: {}),\n\t\t});\n\t} catch (err: unknown) {\n\t\tif (err instanceof FabricAuthError) {\n\t\t\tprintError(err.message, 3);\n\t\t}\n\t\tthrow err;\n\t}\n}\n","/**\n * Config storage for @fabricorg/cli\n *\n * Persists to XDG_CONFIG_HOME/fabricai/config.json (Linux/macOS)\n * or %APPDATA%\\fabricai\\config.json (Windows).\n *\n * The API key is stored as-is in the config file with 0600 permissions.\n * Future: migrate to system keychain.\n */\n\nimport Conf from \"conf\";\n\ninterface CliConfig {\n\t/** Active profile name */\n\tactiveProfile: string;\n\tprofiles: Record<string, ProfileConfig>;\n\t/** Default output format */\n\tdefaultFormat: \"table\" | \"json\" | \"yaml\" | \"csv\";\n}\n\ninterface ProfileConfig {\n\t/** API key for this profile */\n\tapiKey?: string;\n\t/** Override base URL (e.g. for self-hosted) */\n\tbaseUrl?: string;\n\t/** Default context for commands */\n\tdefaultContext?: ContextConfig;\n}\n\nexport type ContextConfig =\n\t| { type: \"personal\" }\n\t| { type: \"org\"; slug: string };\n\nconst DEFAULTS: CliConfig = {\n\tactiveProfile: \"default\",\n\tprofiles: {},\n\tdefaultFormat: \"table\",\n};\n\nlet _store: Conf<CliConfig> | undefined;\n\nfunction getStore(): Conf<CliConfig> {\n\tif (!_store) {\n\t\t_store = new Conf<CliConfig>({\n\t\t\tprojectName: \"fabricai\",\n\t\t\tdefaults: DEFAULTS,\n\t\t});\n\t}\n\treturn _store;\n}\n\nfunction getConfig(): CliConfig {\n\treturn getStore().store;\n}\n\nfunction getActiveProfile(): ProfileConfig {\n\tconst cfg = getConfig();\n\treturn cfg.profiles[cfg.activeProfile] ?? {};\n}\n\nexport function getApiKey(): string | undefined {\n\t// Env var takes precedence over stored config\n\tif (process.env.FABRIC_API_KEY) {\n\t\treturn process.env.FABRIC_API_KEY;\n\t}\n\treturn getActiveProfile().apiKey;\n}\n\nexport function getBaseUrl(): string | undefined {\n\tif (process.env.FABRIC_BASE_URL) {\n\t\treturn process.env.FABRIC_BASE_URL;\n\t}\n\treturn getActiveProfile().baseUrl;\n}\n\nexport function getDefaultContext(): ContextConfig | undefined {\n\t// Env var takes precedence\n\tif (process.env.FABRIC_ORG) {\n\t\treturn { type: \"org\", slug: process.env.FABRIC_ORG };\n\t}\n\tif (process.env.FABRIC_PERSONAL === \"1\") {\n\t\treturn { type: \"personal\" };\n\t}\n\treturn getActiveProfile().defaultContext;\n}\n\nexport function getOutputFormat(): \"table\" | \"json\" | \"yaml\" | \"csv\" {\n\tif (\n\t\tprocess.env.FABRIC_FORMAT === \"json\" ||\n\t\tprocess.env.FABRIC_FORMAT === \"yaml\" ||\n\t\tprocess.env.FABRIC_FORMAT === \"csv\"\n\t) {\n\t\treturn process.env.FABRIC_FORMAT as \"json\" | \"yaml\" | \"csv\";\n\t}\n\treturn getConfig().defaultFormat;\n}\n\nexport function saveApiKey(apiKey: string, profile = \"default\"): void {\n\tconst store = getStore();\n\tconst profiles = store.get(\"profiles\") as CliConfig[\"profiles\"];\n\tstore.set(\"profiles\", {\n\t\t...profiles,\n\t\t[profile]: { ...(profiles[profile] ?? {}), apiKey },\n\t});\n\tstore.set(\"activeProfile\", profile);\n}\n\nexport function clearApiKey(profile = \"default\"): void {\n\tconst store = getStore();\n\tconst profiles = store.get(\"profiles\") as CliConfig[\"profiles\"];\n\tconst { apiKey: _, ...rest } = profiles[profile] ?? {};\n\tstore.set(\"profiles\", { ...profiles, [profile]: rest });\n}\n\nexport function saveDefaultContext(ctx: ContextConfig, profile?: string): void {\n\tconst store = getStore();\n\tconst active = profile ?? (store.get(\"activeProfile\") as string);\n\tconst profiles = store.get(\"profiles\") as CliConfig[\"profiles\"];\n\tstore.set(\"profiles\", {\n\t\t...profiles,\n\t\t[active]: { ...(profiles[active] ?? {}), defaultContext: ctx },\n\t});\n}\n\nexport function getConfigPath(): string {\n\treturn getStore().path;\n}\n","/**\n * Output formatting for @fabricorg/cli\n *\n * Supports: table (default), json, yaml, csv, quiet (IDs only)\n */\n\nimport Table from \"cli-table3\";\nimport { getOutputFormat } from \"./config.js\";\n\ntype OutputFormat = \"table\" | \"json\" | \"yaml\" | \"csv\" | \"quiet\";\n\nexport interface OutputOptions {\n\tformat?: OutputFormat;\n\t/** Column names to include in table/csv output (in order) */\n\tcolumns?: string[];\n\t/** Key to use for --quiet / IDs-only output */\n\tidKey?: string;\n}\n\n/** Print data to stdout in the selected format. */\nexport function printOutput(data: unknown, opts: OutputOptions = {}): void {\n\tconst format = opts.format ?? (getOutputFormat() as OutputFormat);\n\n\tif (format === \"json\") {\n\t\tprocess.stdout.write(`${JSON.stringify(data, null, 2)}\\n`);\n\t\treturn;\n\t}\n\n\tif (format === \"yaml\") {\n\t\tprocess.stdout.write(`${toYaml(data)}\\n`);\n\t\treturn;\n\t}\n\n\tif (format === \"quiet\") {\n\t\tconst rows = Array.isArray(data) ? data : [data];\n\t\tconst key = opts.idKey ?? \"id\";\n\t\tfor (const row of rows) {\n\t\t\tconst val = (row as Record<string, unknown>)[key];\n\t\t\tif (val !== undefined) {\n\t\t\t\tprocess.stdout.write(`${String(val)}\\n`);\n\t\t\t}\n\t\t}\n\t\treturn;\n\t}\n\n\tif (format === \"csv\") {\n\t\tconst rows = Array.isArray(data) ? data : [data];\n\t\tif (rows.length === 0) {\n\t\t\treturn;\n\t\t}\n\t\tconst cols = opts.columns ?? Object.keys(rows[0] as object);\n\t\tprocess.stdout.write(`${cols.map(csvEscape).join(\",\")}\\n`);\n\t\tfor (const row of rows) {\n\t\t\tprocess.stdout.write(\n\t\t\t\t`${cols\n\t\t\t\t\t.map((c) =>\n\t\t\t\t\t\tcsvEscape(\n\t\t\t\t\t\t\tString((row as Record<string, unknown>)[c] ?? \"\"),\n\t\t\t\t\t\t),\n\t\t\t\t\t)\n\t\t\t\t\t.join(\",\")}\\n`,\n\t\t\t);\n\t\t}\n\t\treturn;\n\t}\n\n\t// Default: table\n\tconst rows = Array.isArray(data) ? data : [data];\n\tif (rows.length === 0) {\n\t\tprocess.stdout.write(\"(no results)\\n\");\n\t\treturn;\n\t}\n\tconst cols = opts.columns ?? Object.keys(rows[0] as object);\n\tconst table = new Table({ head: cols, style: { head: [\"cyan\"] } });\n\tfor (const row of rows) {\n\t\ttable.push(\n\t\t\tcols.map((c) => formatCell((row as Record<string, unknown>)[c])),\n\t\t);\n\t}\n\tprocess.stdout.write(`${table.toString()}\\n`);\n}\n\n/** Print a single key-value object as aligned pairs */\nexport function printRecord(\n\tdata: Record<string, unknown>,\n\topts: OutputOptions = {},\n): void {\n\tconst format = opts.format ?? (getOutputFormat() as OutputFormat);\n\tif (format === \"json\") {\n\t\tprintOutput(data, opts);\n\t\treturn;\n\t}\n\tif (format === \"yaml\") {\n\t\tprintOutput(data, opts);\n\t\treturn;\n\t}\n\tconst table = new Table({ style: { head: [\"cyan\"] } });\n\tfor (const [key, val] of Object.entries(data)) {\n\t\ttable.push({ [key]: formatCell(val) });\n\t}\n\tprocess.stdout.write(`${table.toString()}\\n`);\n}\n\n/** Print a success message to stdout */\nexport function printSuccess(message: string): void {\n\tprocess.stdout.write(`✓ ${message}\\n`);\n}\n\n/** Print an error message to stderr and exit with given code */\nexport function printError(message: string, exitCode = 1): never {\n\tprocess.stderr.write(`✗ ${message}\\n`);\n\tprocess.exit(exitCode);\n}\n\n/** Print a warning to stderr (no exit) */\nexport function printWarning(message: string): void {\n\tprocess.stderr.write(`⚠ ${message}\\n`);\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction formatCell(val: unknown): string {\n\tif (val === null || val === undefined) {\n\t\treturn \"\";\n\t}\n\tif (typeof val === \"boolean\") {\n\t\treturn val ? \"yes\" : \"no\";\n\t}\n\tif (typeof val === \"object\") {\n\t\treturn JSON.stringify(val);\n\t}\n\tconst s = String(val);\n\t// Truncate ISO dates to just the date portion for readability in tables\n\tif (/^\\d{4}-\\d{2}-\\d{2}T/.test(s)) {\n\t\treturn s.slice(0, 10);\n\t}\n\treturn s;\n}\n\nfunction csvEscape(s: string): string {\n\tif (s.includes(\",\") || s.includes('\"') || s.includes(\"\\n\")) {\n\t\treturn `\"${s.replace(/\"/g, '\"\"')}\"`;\n\t}\n\treturn s;\n}\n\n/** Minimal YAML serializer (no dependencies) */\nfunction toYaml(val: unknown, indent = 0): string {\n\tconst pad = \" \".repeat(indent);\n\tif (val === null || val === undefined) {\n\t\treturn \"~\";\n\t}\n\tif (typeof val === \"boolean\" || typeof val === \"number\") {\n\t\treturn String(val);\n\t}\n\tif (typeof val === \"string\") {\n\t\tif (val.includes(\"\\n\") || val.includes(\":\") || val.includes('\"')) {\n\t\t\treturn `\"${val.replace(/\"/g, '\\\\\"')}\"`;\n\t\t}\n\t\treturn val;\n\t}\n\tif (Array.isArray(val)) {\n\t\tif (val.length === 0) {\n\t\t\treturn \"[]\";\n\t\t}\n\t\treturn val\n\t\t\t.map((item) => `${pad}- ${toYaml(item, indent + 1)}`)\n\t\t\t.join(\"\\n\");\n\t}\n\tif (typeof val === \"object\") {\n\t\tconst entries = Object.entries(val as Record<string, unknown>);\n\t\tif (entries.length === 0) {\n\t\t\treturn \"{}\";\n\t\t}\n\t\treturn entries\n\t\t\t.map(([k, v]) => {\n\t\t\t\tconst valStr = toYaml(v, indent + 1);\n\t\t\t\tconst isMultiline = valStr.includes(\"\\n\");\n\t\t\t\treturn isMultiline\n\t\t\t\t\t? `${pad}${k}:\\n${valStr}`\n\t\t\t\t\t: `${pad}${k}: ${valStr}`;\n\t\t\t})\n\t\t\t.join(\"\\n\");\n\t}\n\treturn String(val);\n}\n","/**\n * Context resolution for @fabricorg/cli\n *\n * Every resource command runs inside exactly one organization. Personal context\n * is gone (Fizzy #1875, PO-9): the flag, the environment variable and the\n * stored default that selected it are retired here.\n *\n * The stored shape still PARSES a personal default, and that is deliberate.\n * Configs written by earlier versions have one on disk, and a client that\n * crashed on its own config file would be a worse failure than the one being\n * fixed. It is read, recognised, and refused with a message that says how to\n * replace it — never silently treated as \"no default\", which would send the\n * user hunting for a setting they can see is set.\n */\n\nimport type { ContextConfig } from \"./config.js\";\nimport { getDefaultContext } from \"./config.js\";\nimport { printError } from \"./output.js\";\n\nexport interface ResolvedContext {\n\ttype: \"org\";\n\tslug: string;\n}\n\n/**\n * The same resolution as `resolveContext`, as a VALUE instead of an exit.\n *\n * `resolveContext` calls `printError`, which calls `process.exit` — correct\n * for a command a person is watching, and fatal to the session-start hook\n * contract in `commands/instructions`, which must never exit non-zero for\n * any reason. `process.exit` cannot be caught by the `try/catch` that owns\n * that contract, so a stored personal default (or a stale\n * `FABRIC_PERSONAL=1`) took the whole process down with code 2 before the\n * boundary ever saw it.\n *\n * `resolveContext` below is a thin exiting wrapper over it, so the two cannot\n * drift.\n */\ntype ContextResolution =\n\t| { ok: true; context: ResolvedContext | undefined }\n\t| { ok: false; message: string; exitCode: number };\n\nconst PERSONAL_RETIRED_HINT =\n\t\"selects personal context, which no longer exists — every command runs inside an organization.\\n\" +\n\t\"Name one with --org <slug>, or set a default with:\\n fabric ctx use org <slug>\";\n\nfunction tryResolveContext(\n\tpersonal: boolean | undefined,\n\torg: string | undefined,\n\trequired = true,\n): ContextResolution {\n\tif (personal) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\tmessage: `--personal ${PERSONAL_RETIRED_HINT}`,\n\t\t\texitCode: 2,\n\t\t};\n\t}\n\tif (org) {\n\t\treturn { ok: true, context: { type: \"org\", slug: org } };\n\t}\n\n\tconst stored: ContextConfig | undefined = getDefaultContext();\n\tif (stored?.type === \"personal\") {\n\t\tconst source =\n\t\t\tprocess.env.FABRIC_PERSONAL === \"1\"\n\t\t\t\t? \"FABRIC_PERSONAL=1\"\n\t\t\t\t: \"Your stored default context\";\n\t\treturn {\n\t\t\tok: false,\n\t\t\tmessage: `${source} ${PERSONAL_RETIRED_HINT}`,\n\t\t\texitCode: 2,\n\t\t};\n\t}\n\tif (stored?.type === \"org\") {\n\t\treturn { ok: true, context: { type: \"org\", slug: stored.slug } };\n\t}\n\n\tif (required) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\tmessage:\n\t\t\t\t\"Context is required. Use --org <slug>, or set a default with:\\n fabric ctx use org <slug>\",\n\t\t\texitCode: 2,\n\t\t};\n\t}\n\n\treturn { ok: true, context: undefined };\n}\n\n/**\n * Resolves tenant context from CLI flags, env vars, or stored default.\n * Exits with code 2 when context is ambiguous or names a retired one.\n *\n * A thin wrapper over `tryResolveContext`, which holds the actual rules —\n * see there for why the non-exiting form exists.\n *\n * @param personal - value of the retired --personal flag\n * @param org - value of --org flag\n * @param required - if false, returns undefined when context is unset (for auth commands)\n */\nexport function resolveContext(\n\tpersonal: boolean | undefined,\n\torg: string | undefined,\n\trequired = true,\n): ResolvedContext | undefined {\n\tconst resolution = tryResolveContext(personal, org, required);\n\tif (!resolution.ok) {\n\t\tprintError(resolution.message, resolution.exitCode);\n\t}\n\treturn resolution.context;\n}\n","/**\n * fabric auth keys\n *\n * fabric auth keys list\n * fabric auth keys create --name \"CI deploy\" --scopes workflows:run,agents:read\n * fabric auth keys revoke <id>\n */\n\nimport { Command } from \"commander\";\nimport { getClient } from \"../../lib/client.js\";\nimport { printError, printOutput, printSuccess } from \"../../lib/output.js\";\n\nexport function buildKeysCommand(): Command {\n\tconst keys = new Command(\"keys\").description(\"Manage API keys\");\n\n\t// -- list ----------------------------------------------------------------\n\tkeys.command(\"list\")\n\t\t.description(\"List your API keys\")\n\t\t.option(\n\t\t\t\"--format <format>\",\n\t\t\t\"Output format: table|json|yaml|csv\",\n\t\t\t\"table\",\n\t\t)\n\t\t.action(async (opts: { format: string }) => {\n\t\t\tconst client = getClient();\n\t\t\tlet list: Awaited<ReturnType<typeof client.auth.listKeys>>;\n\t\t\ttry {\n\t\t\t\tlist = await client.auth.listKeys();\n\t\t\t} catch (err: unknown) {\n\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t}\n\t\t\tprintOutput(list, {\n\t\t\t\tformat: opts.format as \"table\" | \"json\" | \"yaml\" | \"csv\",\n\t\t\t\tcolumns: [\n\t\t\t\t\t\"id\",\n\t\t\t\t\t\"name\",\n\t\t\t\t\t\"keyPrefix\",\n\t\t\t\t\t\"scopes\",\n\t\t\t\t\t\"lastUsedAt\",\n\t\t\t\t\t\"expiresAt\",\n\t\t\t\t\t\"createdAt\",\n\t\t\t\t],\n\t\t\t});\n\t\t});\n\n\t// -- create --------------------------------------------------------------\n\tkeys.command(\"create\")\n\t\t.description(\"Create a new API key (raw key shown only once)\")\n\t\t.requiredOption(\"-n, --name <name>\", \"Key name\")\n\t\t.option(\n\t\t\t\"-s, --scopes <scopes>\",\n\t\t\t\"Comma-separated scopes (e.g. projects:read,workflows:run)\",\n\t\t\t\"orgs:read\",\n\t\t)\n\t\t.option(\n\t\t\t\"-e, --expires <days>\",\n\t\t\t\"Days until expiry (1–365, omit for no expiry)\",\n\t\t)\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (opts: {\n\t\t\t\tname: string;\n\t\t\t\tscopes: string;\n\t\t\t\texpires?: string;\n\t\t\t\tformat: string;\n\t\t\t}) => {\n\t\t\t\tconst client = getClient();\n\t\t\t\tconst scopes = opts.scopes.split(\",\").map((s) => s.trim());\n\t\t\t\tconst expiresInDays = opts.expires\n\t\t\t\t\t? Number.parseInt(opts.expires, 10)\n\t\t\t\t\t: undefined;\n\n\t\t\t\tif (\n\t\t\t\t\texpiresInDays !== undefined &&\n\t\t\t\t\tNumber.isNaN(expiresInDays)\n\t\t\t\t) {\n\t\t\t\t\tprintError(\"--expires must be a number\", 2);\n\t\t\t\t}\n\n\t\t\t\tlet created: Awaited<ReturnType<typeof client.auth.createKey>>;\n\t\t\t\ttry {\n\t\t\t\t\tcreated = await client.auth.createKey({\n\t\t\t\t\t\tname: opts.name,\n\t\t\t\t\t\tscopes,\n\t\t\t\t\t\texpiresInDays,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(created, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprocess.stdout.write(\"\\n\");\n\t\t\t\tprintSuccess(`API key created: ${created.name}`);\n\t\t\t\tprocess.stdout.write(`\\n Key: ${created.rawKey}\\n`);\n\t\t\t\tprocess.stdout.write(` Prefix: ${created.keyPrefix}\\n`);\n\t\t\t\tprocess.stdout.write(\n\t\t\t\t\t` Scopes: ${created.scopes.join(\", \")}\\n`,\n\t\t\t\t);\n\t\t\t\tif (created.expiresAt) {\n\t\t\t\t\tprocess.stdout.write(\n\t\t\t\t\t\t` Expires: ${String(created.expiresAt).slice(0, 10)}\\n`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tprocess.stdout.write(\n\t\t\t\t\t\"\\n ⚠ Store this key now — it will never be shown again.\\n\\n\",\n\t\t\t\t);\n\t\t\t},\n\t\t);\n\n\t// -- revoke --------------------------------------------------------------\n\tkeys.command(\"revoke <id>\")\n\t\t.description(\"Permanently revoke an API key\")\n\t\t.action(async (id: string) => {\n\t\t\tconst client = getClient();\n\t\t\ttry {\n\t\t\t\tawait client.auth.revokeKey(id);\n\t\t\t} catch (err: unknown) {\n\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t}\n\t\t\tprintSuccess(`API key ${id} revoked.`);\n\t\t});\n\n\treturn keys;\n}\n","/**\n * fabric auth login\n *\n * Stores an API key for subsequent commands.\n *\n * fabric auth login --key fab_...\n * fabric auth login (prompts interactively)\n */\n\nimport * as readline from \"node:readline\";\nimport { FabricClient } from \"@fabricorg/sdk\";\nimport { Command } from \"commander\";\nimport { getBaseUrl, saveApiKey } from \"../../lib/config.js\";\nimport { printError, printSuccess } from \"../../lib/output.js\";\n\nasync function promptApiKey(): Promise<string> {\n\tconst rl = readline.createInterface({\n\t\tinput: process.stdin,\n\t\toutput: process.stdout,\n\t});\n\n\treturn new Promise((resolve) => {\n\t\t// Don't echo the key\n\t\tprocess.stdout.write(\"Fabric API Key: \");\n\t\tprocess.stdin.resume();\n\t\tprocess.stdin.setEncoding(\"utf8\");\n\n\t\tlet key = \"\";\n\t\tprocess.stdin.once(\"data\", (chunk) => {\n\t\t\tkey = String(chunk).trim();\n\t\t\tprocess.stdout.write(\"\\n\");\n\t\t\trl.close();\n\t\t\tresolve(key);\n\t\t});\n\t});\n}\n\nexport function buildLoginCommand(): Command {\n\treturn new Command(\"login\")\n\t\t.description(\"Authenticate with a Fabric API key\")\n\t\t.option(\"-k, --key <api-key>\", \"API key (fab_... or org_...)\")\n\t\t.option(\"--base-url <url>\", \"Override the Fabric base URL\")\n\t\t.action(async (opts: { key?: string; baseUrl?: string }) => {\n\t\t\tlet apiKey = opts.key?.trim();\n\n\t\t\tif (!apiKey) {\n\t\t\t\tapiKey = await promptApiKey();\n\t\t\t}\n\n\t\t\tif (!apiKey) {\n\t\t\t\tprintError(\"API key is required\", 2);\n\t\t\t}\n\n\t\t\tif (!apiKey.startsWith(\"fab_\") && !apiKey.startsWith(\"org_\")) {\n\t\t\t\tprintError(\n\t\t\t\t\t\"Invalid API key format. Keys must start with fab_ or org_\",\n\t\t\t\t\t2,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Verify the key works before saving\n\t\t\tconst baseUrl = opts.baseUrl ?? getBaseUrl();\n\t\t\tconst client = new FabricClient({ apiKey, baseUrl });\n\n\t\t\tlet name: string;\n\t\t\tlet email: string;\n\t\t\ttry {\n\t\t\t\tconst me = await client.auth.whoami();\n\t\t\t\tname = me.user.name ?? me.user.email;\n\t\t\t\temail = me.user.email;\n\t\t\t} catch {\n\t\t\t\tprintError(\n\t\t\t\t\t\"Authentication failed. Check that the key is valid and not expired.\",\n\t\t\t\t\t3,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tsaveApiKey(apiKey);\n\t\t\tprintSuccess(`Authenticated as ${name} (${email})`);\n\t\t});\n}\n","/**\n * fabric auth logout\n * Removes the stored API key from config.\n */\n\nimport { Command } from \"commander\";\nimport { clearApiKey, getApiKey } from \"../../lib/config.js\";\nimport { printSuccess, printWarning } from \"../../lib/output.js\";\n\nexport function buildLogoutCommand(): Command {\n\treturn new Command(\"logout\")\n\t\t.description(\"Remove stored API key\")\n\t\t.action(() => {\n\t\t\tif (!getApiKey()) {\n\t\t\t\tprintWarning(\"No API key stored — already logged out.\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tclearApiKey();\n\t\t\tprintSuccess(\"Logged out. API key removed.\");\n\t\t});\n}\n","/**\n * fabric auth whoami\n * Prints the authenticated identity and org memberships.\n */\n\nimport { Command } from \"commander\";\nimport { getClient } from \"../../lib/client.js\";\nimport { printError, printOutput, printRecord } from \"../../lib/output.js\";\n\nexport function buildWhoamiCommand(): Command {\n\treturn new Command(\"whoami\")\n\t\t.description(\"Show current authentication and identity\")\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(async (opts: { format: string }) => {\n\t\t\tconst client = getClient();\n\n\t\t\tlet me: Awaited<ReturnType<typeof client.auth.whoami>>;\n\t\t\ttry {\n\t\t\t\tme = await client.auth.whoami();\n\t\t\t} catch (err: unknown) {\n\t\t\t\tprintError((err as Error).message ?? \"Request failed\", 3);\n\t\t\t}\n\n\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\n\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\tprintOutput(me, { format: fmt });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Human-readable\n\t\t\tprintRecord({\n\t\t\t\tUser: me.user.name ?? \"(no name)\",\n\t\t\t\tEmail: me.user.email,\n\t\t\t\tRole: me.user.role,\n\t\t\t\t\"Key type\": me.keyType,\n\t\t\t\t\"Key prefix\": me.keyPrefix,\n\t\t\t\tScopes: me.scopes.join(\", \"),\n\t\t\t\t\"Orgs count\": String(me.orgs.length),\n\t\t\t\t\"Member since\": me.user.createdAt.slice(0, 10),\n\t\t\t});\n\n\t\t\tif (me.orgs.length > 0) {\n\t\t\t\tprocess.stdout.write(\"\\nOrganizations:\\n\");\n\t\t\t\tprintOutput(me.orgs, {\n\t\t\t\t\tformat: \"table\",\n\t\t\t\t\tcolumns: [\"name\", \"slug\", \"role\", \"joinedAt\"],\n\t\t\t\t});\n\t\t\t}\n\t\t});\n}\n","/**\n * fabric chats\n *\n * fabric chats list List AI chat sessions\n * fabric chats show <id> Show chat details\n */\n\nimport type { FabricChat } from \"@fabricorg/sdk\";\nimport { Command } from \"commander\";\nimport { getClient } from \"../../lib/client.js\";\nimport { resolveContext } from \"../../lib/context.js\";\nimport { printError, printOutput, printRecord } from \"../../lib/output.js\";\n\nexport function buildChatsCommand(): Command {\n\tconst chats = new Command(\"chats\").description(\"Manage AI chat sessions\");\n\n\tchats\n\t\t.command(\"list\")\n\t\t.description(\"List AI chat sessions\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--limit <n>\", \"Max results (default 20)\", \"20\")\n\t\t.option(\n\t\t\t\"--format <format>\",\n\t\t\t\"Output format: table|json|yaml|csv\",\n\t\t\t\"table\",\n\t\t)\n\t\t.option(\"-q, --quiet\", \"Print IDs only\")\n\t\t.action(\n\t\t\tasync (opts: {\n\t\t\t\torg?: string;\n\t\t\t\tpersonal?: boolean;\n\t\t\t\tlimit: string;\n\t\t\t\tformat: string;\n\t\t\t\tquiet?: boolean;\n\t\t\t}) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet list: FabricChat[];\n\t\t\t\ttry {\n\t\t\t\t\tlist = await client.chats.list({\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t\tlimit: Number(opts.limit),\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tif (opts.quiet) {\n\t\t\t\t\tfor (const c of list) {\n\t\t\t\t\t\tprocess.stdout.write(`${c.id}\\n`);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintOutput(list, {\n\t\t\t\t\tformat: opts.format as \"table\" | \"json\" | \"yaml\" | \"csv\",\n\t\t\t\t\tcolumns: [\"id\", \"title\", \"updatedAt\"],\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\tchats\n\t\t.command(\"show <id>\")\n\t\t.description(\"Show chat details\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tid: string,\n\t\t\t\topts: { org?: string; personal?: boolean; format: string },\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet chat: FabricChat;\n\t\t\t\ttry {\n\t\t\t\t\tchat = await client.chats.get(id, {\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(chat, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintRecord({\n\t\t\t\t\tID: chat.id,\n\t\t\t\t\tTitle: chat.title ?? \"(untitled)\",\n\t\t\t\t\tUpdated: chat.updatedAt.slice(0, 16).replace(\"T\", \" \"),\n\t\t\t\t\tCreated: chat.createdAt.slice(0, 10),\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\treturn chats;\n}\n","/**\n * fabric completion\n *\n * fabric completion bash Output bash completion script\n * fabric completion zsh Output zsh completion script\n * fabric completion fish Output fish completion script\n */\n\nimport { Command } from \"commander\";\n\nconst BASH_COMPLETION = `\n# fabric bash completion\n_fabric_completion() {\n local cur prev words cword\n _init_completion || return\n\n local commands=\"auth ctx orgs projects features workflows prompts agents skills mcp frames workspaces chats reports config completion\"\n\n case \"$prev\" in\n fabric)\n COMPREPLY=($(compgen -W \"$commands\" -- \"$cur\"))\n return ;;\n auth)\n COMPREPLY=($(compgen -W \"login logout whoami keys\" -- \"$cur\"))\n return ;;\n keys)\n COMPREPLY=($(compgen -W \"list create revoke\" -- \"$cur\"))\n return ;;\n ctx)\n COMPREPLY=($(compgen -W \"current use\" -- \"$cur\"))\n return ;;\n orgs)\n COMPREPLY=($(compgen -W \"list show\" -- \"$cur\"))\n return ;;\n projects)\n COMPREPLY=($(compgen -W \"list show create update\" -- \"$cur\"))\n return ;;\n features)\n COMPREPLY=($(compgen -W \"list show create update tasks\" -- \"$cur\"))\n return ;;\n workflows)\n COMPREPLY=($(compgen -W \"list show trigger status\" -- \"$cur\"))\n return ;;\n prompts)\n COMPREPLY=($(compgen -W \"list get create update\" -- \"$cur\"))\n return ;;\n agents)\n COMPREPLY=($(compgen -W \"list show execute\" -- \"$cur\"))\n return ;;\n skills)\n COMPREPLY=($(compgen -W \"list show\" -- \"$cur\"))\n return ;;\n mcp)\n COMPREPLY=($(compgen -W \"servers configs\" -- \"$cur\"))\n return ;;\n configs)\n COMPREPLY=($(compgen -W \"list show delete\" -- \"$cur\"))\n return ;;\n frames)\n COMPREPLY=($(compgen -W \"list show\" -- \"$cur\"))\n return ;;\n workspaces)\n COMPREPLY=($(compgen -W \"list show\" -- \"$cur\"))\n return ;;\n chats)\n COMPREPLY=($(compgen -W \"list show\" -- \"$cur\"))\n return ;;\n reports)\n COMPREPLY=($(compgen -W \"templates executions\" -- \"$cur\"))\n return ;;\n templates)\n COMPREPLY=($(compgen -W \"list show\" -- \"$cur\"))\n return ;;\n executions)\n COMPREPLY=($(compgen -W \"list\" -- \"$cur\"))\n return ;;\n completion)\n COMPREPLY=($(compgen -W \"bash zsh fish\" -- \"$cur\"))\n return ;;\n esac\n\n COMPREPLY=($(compgen -W \"--format --org --personal --quiet --help\" -- \"$cur\"))\n}\n\ncomplete -F _fabric_completion fabric\n`.trim();\n\nconst ZSH_COMPLETION = `\n#compdef fabric\n\n_fabric() {\n local state\n\n _arguments \\\\\n '--format[Output format]:format:(table json yaml csv)' \\\\\n '--version[Show version]' \\\\\n '--help[Show help]' \\\\\n '1: :->command' \\\\\n '*: :->args'\n\n case $state in\n command)\n local commands=(\n 'auth:Authenticate and manage API keys'\n 'ctx:Manage active context'\n 'orgs:List organizations'\n 'projects:Manage projects'\n 'features:Manage project features'\n 'workflows:Manage workflows'\n 'prompts:Manage prompts'\n 'agents:Manage agents'\n 'skills:Browse skills'\n 'mcp:Manage MCP servers and configs'\n 'frames:Manage AI-generated frames'\n 'workspaces:Manage workspaces'\n 'chats:View AI chat history'\n 'reports:Manage reports'\n 'config:Show CLI configuration'\n 'completion:Output shell completion script'\n )\n _describe 'command' commands\n ;;\n args)\n case $words[2] in\n auth)\n local subcmds=('login:Log in' 'logout:Log out' 'whoami:Show current user' 'keys:Manage API keys')\n _describe 'subcommand' subcmds ;;\n projects)\n local subcmds=('list:List projects' 'show:Show project' 'create:Create project' 'update:Update project')\n _describe 'subcommand' subcmds ;;\n features)\n local subcmds=('list:List features' 'show:Show feature' 'create:Create feature' 'update:Update feature' 'tasks:List tasks')\n _describe 'subcommand' subcmds ;;\n workflows)\n local subcmds=('list:List workflows' 'show:Show workflow' 'trigger:Trigger workflow' 'status:Check status')\n _describe 'subcommand' subcmds ;;\n prompts)\n local subcmds=('list:List prompts' 'get:Get prompt' 'create:Create prompt' 'update:Update prompt')\n _describe 'subcommand' subcmds ;;\n agents)\n local subcmds=('list:List agents' 'show:Show agent' 'execute:Execute agent')\n _describe 'subcommand' subcmds ;;\n mcp)\n local subcmds=('servers:List MCP servers' 'configs:Manage MCP configs')\n _describe 'subcommand' subcmds ;;\n frames)\n local subcmds=('list:List frames' 'show:Show frame')\n _describe 'subcommand' subcmds ;;\n workspaces)\n local subcmds=('list:List workspaces' 'show:Show workspace')\n _describe 'subcommand' subcmds ;;\n skills)\n local subcmds=('list:List skills' 'show:Show skill')\n _describe 'subcommand' subcmds ;;\n chats)\n local subcmds=('list:List chats' 'show:Show chat')\n _describe 'subcommand' subcmds ;;\n reports)\n local subcmds=('templates:Manage report templates' 'executions:List report executions')\n _describe 'subcommand' subcmds ;;\n completion)\n local subcmds=('bash:Bash completion' 'zsh:Zsh completion' 'fish:Fish completion')\n _describe 'subcommand' subcmds ;;\n esac ;;\n esac\n}\n\n_fabric \"$@\"\n`.trim();\n\nconst FISH_COMPLETION = `\n# fabric fish completion\nset -l fabric_commands auth ctx orgs projects features workflows prompts agents skills mcp frames workspaces chats reports config completion\n\ncomplete -c fabric -f\n\n# Top-level commands\ncomplete -c fabric -n '__fish_use_subcommand' -a auth -d 'Authenticate and manage API keys'\ncomplete -c fabric -n '__fish_use_subcommand' -a ctx -d 'Manage active context'\ncomplete -c fabric -n '__fish_use_subcommand' -a orgs -d 'List organizations'\ncomplete -c fabric -n '__fish_use_subcommand' -a projects -d 'Manage projects'\ncomplete -c fabric -n '__fish_use_subcommand' -a features -d 'Manage project features'\ncomplete -c fabric -n '__fish_use_subcommand' -a workflows -d 'Manage workflows'\ncomplete -c fabric -n '__fish_use_subcommand' -a prompts -d 'Manage prompts'\ncomplete -c fabric -n '__fish_use_subcommand' -a agents -d 'Manage agents'\ncomplete -c fabric -n '__fish_use_subcommand' -a skills -d 'Browse skills'\ncomplete -c fabric -n '__fish_use_subcommand' -a mcp -d 'Manage MCP servers and configs'\ncomplete -c fabric -n '__fish_use_subcommand' -a frames -d 'Manage AI-generated frames'\ncomplete -c fabric -n '__fish_use_subcommand' -a workspaces -d 'Manage workspaces'\ncomplete -c fabric -n '__fish_use_subcommand' -a chats -d 'View AI chat history'\ncomplete -c fabric -n '__fish_use_subcommand' -a reports -d 'Manage reports'\ncomplete -c fabric -n '__fish_use_subcommand' -a config -d 'Show CLI configuration'\ncomplete -c fabric -n '__fish_use_subcommand' -a completion -d 'Output shell completion script'\n\n# Subcommands\ncomplete -c fabric -n '__fish_seen_subcommand_from auth' -a 'login logout whoami keys'\ncomplete -c fabric -n '__fish_seen_subcommand_from ctx' -a 'current use'\ncomplete -c fabric -n '__fish_seen_subcommand_from orgs' -a 'list show'\ncomplete -c fabric -n '__fish_seen_subcommand_from projects' -a 'list show create update'\ncomplete -c fabric -n '__fish_seen_subcommand_from features' -a 'list show create update tasks'\ncomplete -c fabric -n '__fish_seen_subcommand_from workflows' -a 'list show trigger status'\ncomplete -c fabric -n '__fish_seen_subcommand_from prompts' -a 'list get create update'\ncomplete -c fabric -n '__fish_seen_subcommand_from agents' -a 'list show execute'\ncomplete -c fabric -n '__fish_seen_subcommand_from skills' -a 'list show'\ncomplete -c fabric -n '__fish_seen_subcommand_from mcp' -a 'servers configs'\ncomplete -c fabric -n '__fish_seen_subcommand_from configs' -a 'list show delete'\ncomplete -c fabric -n '__fish_seen_subcommand_from frames' -a 'list show'\ncomplete -c fabric -n '__fish_seen_subcommand_from workspaces' -a 'list show'\ncomplete -c fabric -n '__fish_seen_subcommand_from chats' -a 'list show'\ncomplete -c fabric -n '__fish_seen_subcommand_from reports' -a 'templates executions'\ncomplete -c fabric -n '__fish_seen_subcommand_from templates' -a 'list show'\ncomplete -c fabric -n '__fish_seen_subcommand_from executions' -a 'list'\ncomplete -c fabric -n '__fish_seen_subcommand_from completion' -a 'bash zsh fish'\n\n# Common flags\ncomplete -c fabric -l format -d 'Output format' -a 'table json yaml csv'\ncomplete -c fabric -l org -d 'Organization context' -r\ncomplete -c fabric -l personal -d 'Personal context'\ncomplete -c fabric -s q -l quiet -d 'Quiet output'\ncomplete -c fabric -l help -d 'Show help'\n`.trim();\n\nexport function buildCompletionCommand(): Command {\n\tconst completion = new Command(\"completion\").description(\n\t\t\"Output shell completion script\",\n\t);\n\n\tcompletion\n\t\t.command(\"bash\")\n\t\t.description(\"Output bash completion script\")\n\t\t.action(() => {\n\t\t\tprocess.stdout.write(`${BASH_COMPLETION}\\n`);\n\t\t\tprocess.stderr.write(\n\t\t\t\t'# Add to ~/.bashrc:\\n# eval \"$(fabric completion bash)\"\\n',\n\t\t\t);\n\t\t});\n\n\tcompletion\n\t\t.command(\"zsh\")\n\t\t.description(\"Output zsh completion script\")\n\t\t.action(() => {\n\t\t\tprocess.stdout.write(`${ZSH_COMPLETION}\\n`);\n\t\t\tprocess.stderr.write(\n\t\t\t\t'# Add to ~/.zshrc:\\n# eval \"$(fabric completion zsh)\"\\n',\n\t\t\t);\n\t\t});\n\n\tcompletion\n\t\t.command(\"fish\")\n\t\t.description(\"Output fish completion script\")\n\t\t.action(() => {\n\t\t\tprocess.stdout.write(`${FISH_COMPLETION}\\n`);\n\t\t\tprocess.stderr.write(\n\t\t\t\t\"# Save to ~/.config/fish/completions/fabric.fish\\n\",\n\t\t\t);\n\t\t});\n\n\treturn completion;\n}\n","/**\n * fabric ctx\n *\n * fabric ctx current Show active context\n * fabric ctx use org <slug> Set an org as default\n *\n * `use personal` is retired (Fizzy #1875, PO-9). It is still REGISTERED rather\n * than deleted, so someone who types it — or has it in a script — is told what\n * replaced it instead of meeting \"unknown command\". A config written by an\n * earlier version can still hold a personal default; `current` reports it as\n * needing replacing rather than printing it as if it still worked.\n */\n\nimport { Command } from \"commander\";\nimport { getDefaultContext, saveDefaultContext } from \"../../lib/config.js\";\nimport { printError, printSuccess, printWarning } from \"../../lib/output.js\";\n\nexport function buildCtxCommand(): Command {\n\tconst ctx = new Command(\"ctx\").description(\n\t\t\"Manage the organization commands run in\",\n\t);\n\n\t// -- current ------------------------------------------------------------\n\tctx.command(\"current\")\n\t\t.description(\"Show the active default context\")\n\t\t.action(() => {\n\t\t\tconst stored = getDefaultContext();\n\t\t\tif (!stored) {\n\t\t\t\tprintWarning(\n\t\t\t\t\t\"No default context set. Use --org <slug> on each command, or run:\\n fabric ctx use org <slug>\",\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (stored.type === \"personal\") {\n\t\t\t\t// Reported, not hidden: it is set, the user can see it is set,\n\t\t\t\t// and saying \"none\" would send them looking for a setting that\n\t\t\t\t// is right there.\n\t\t\t\tprintWarning(\n\t\t\t\t\t\"Context: personal — retired, and no command will accept it.\\nReplace it with:\\n fabric ctx use org <slug>\",\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tprocess.stdout.write(`Context: org:${stored.slug}\\n`);\n\t\t});\n\n\t// -- use ----------------------------------------------------------------\n\tconst use = new Command(\"use\").description(\n\t\t\"Set the default organization for commands\",\n\t);\n\n\tuse.command(\"personal\")\n\t\t.description(\"Retired — context is organization-only\")\n\t\t.action(() => {\n\t\t\tprintError(\n\t\t\t\t\"Personal context no longer exists — every command runs inside an organization.\\nSet one with:\\n fabric ctx use org <slug>\",\n\t\t\t\t2,\n\t\t\t);\n\t\t});\n\n\tuse.command(\"org <slug>\")\n\t\t.description(\"Use an org context by default\")\n\t\t.action((slug: string) => {\n\t\t\tsaveDefaultContext({ type: \"org\", slug });\n\t\t\tprintSuccess(`Default context set to: org:${slug}`);\n\t\t});\n\n\tctx.addCommand(use);\n\n\treturn ctx;\n}\n","/**\n * fabric features\n *\n * fabric features list --project <id> List features in a project\n * fabric features show --project <id> <id> Show feature details\n * fabric features create --project <id> <title> Create a feature\n */\n\nimport type { FabricFeature } from \"@fabricorg/sdk\";\nimport { Command } from \"commander\";\nimport { getClient } from \"../../lib/client.js\";\nimport { resolveContext } from \"../../lib/context.js\";\nimport {\n\tprintError,\n\tprintOutput,\n\tprintRecord,\n\tprintSuccess,\n} from \"../../lib/output.js\";\n\nexport function buildFeaturesCommand(): Command {\n\tconst features = new Command(\"features\").description(\n\t\t\"Manage project features\",\n\t);\n\n\t// -- list ----------------------------------------------------------------\n\tfeatures\n\t\t.command(\"list\")\n\t\t.description(\"List features in a project\")\n\t\t.requiredOption(\"-p, --project <id>\", \"Project ID\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\n\t\t\t\"--priority <priority>\",\n\t\t\t\"Filter: P0_CRITICAL|P1_HIGH|P2_MEDIUM|P3_LOW\",\n\t\t)\n\t\t.option(\"--search <query>\", \"Search by title\")\n\t\t.option(\"--limit <n>\", \"Max results (default 50)\", \"50\")\n\t\t.option(\n\t\t\t\"--format <format>\",\n\t\t\t\"Output format: table|json|yaml|csv\",\n\t\t\t\"table\",\n\t\t)\n\t\t.option(\"-q, --quiet\", \"Print IDs only\")\n\t\t.action(\n\t\t\tasync (opts: {\n\t\t\t\tproject: string;\n\t\t\t\torg?: string;\n\t\t\t\tpersonal?: boolean;\n\t\t\t\tpriority?: string;\n\t\t\t\tsearch?: string;\n\t\t\t\tlimit: string;\n\t\t\t\tformat: string;\n\t\t\t\tquiet?: boolean;\n\t\t\t}) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet list: FabricFeature[];\n\t\t\t\ttry {\n\t\t\t\t\tlist = await client.projects.listFeatures(opts.project, {\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t\tpriority: opts.priority as\n\t\t\t\t\t\t\t| FabricFeature[\"priority\"]\n\t\t\t\t\t\t\t| undefined,\n\t\t\t\t\t\tsearch: opts.search,\n\t\t\t\t\t\tlimit: Number(opts.limit),\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tif (opts.quiet) {\n\t\t\t\t\tfor (const f of list) {\n\t\t\t\t\t\tprocess.stdout.write(`${f.id}\\n`);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintOutput(list, {\n\t\t\t\t\tformat: opts.format as \"table\" | \"json\" | \"yaml\" | \"csv\",\n\t\t\t\t\tcolumns: [\"identifier\", \"title\", \"priority\", \"createdAt\"],\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\t// -- show ----------------------------------------------------------------\n\tfeatures\n\t\t.command(\"show <id>\")\n\t\t.description(\"Show feature details\")\n\t\t.requiredOption(\"-p, --project <projectId>\", \"Project ID\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tid: string,\n\t\t\t\topts: {\n\t\t\t\t\tproject: string;\n\t\t\t\t\torg?: string;\n\t\t\t\t\tpersonal?: boolean;\n\t\t\t\t\tformat: string;\n\t\t\t\t},\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet feature: FabricFeature;\n\t\t\t\ttry {\n\t\t\t\t\tfeature = await client.projects.getFeature(\n\t\t\t\t\t\topts.project,\n\t\t\t\t\t\tid,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(feature, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintRecord({\n\t\t\t\t\tID: feature.id,\n\t\t\t\t\tIdentifier: feature.identifier,\n\t\t\t\t\tTitle: feature.title,\n\t\t\t\t\tPriority: feature.priority,\n\t\t\t\t\tDescription: feature.description ?? \"(none)\",\n\t\t\t\t\t\"Acceptance Criteria\":\n\t\t\t\t\t\tfeature.acceptanceCriteria ?? \"(none)\",\n\t\t\t\t\tProject: feature.projectId,\n\t\t\t\t\tAssignee: feature.assigneeId ?? \"(none)\",\n\t\t\t\t\tCreated: feature.createdAt.slice(0, 10),\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\t// -- create --------------------------------------------------------------\n\tfeatures\n\t\t.command(\"create <title>\")\n\t\t.description(\"Create a feature in a project\")\n\t\t.requiredOption(\"-p, --project <projectId>\", \"Project ID\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"-d, --description <text>\", \"Feature description\")\n\t\t.option(\n\t\t\t\"--priority <priority>\",\n\t\t\t\"Priority: P0_CRITICAL|P1_HIGH|P2_MEDIUM|P3_LOW (default: P2_MEDIUM)\",\n\t\t)\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\ttitle: string,\n\t\t\t\topts: {\n\t\t\t\t\tproject: string;\n\t\t\t\t\torg?: string;\n\t\t\t\t\tpersonal?: boolean;\n\t\t\t\t\tdescription?: string;\n\t\t\t\t\tpriority?: string;\n\t\t\t\t\tformat: string;\n\t\t\t\t},\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet feature: FabricFeature;\n\t\t\t\ttry {\n\t\t\t\t\tfeature = await client.projects.createFeature(\n\t\t\t\t\t\topts.project,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttitle,\n\t\t\t\t\t\t\tdescription: opts.description,\n\t\t\t\t\t\t\tpriority: opts.priority as\n\t\t\t\t\t\t\t\t| FabricFeature[\"priority\"]\n\t\t\t\t\t\t\t\t| undefined,\n\t\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(feature, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintSuccess(`Feature ${feature.identifier} created`);\n\t\t\t\tprintRecord({\n\t\t\t\t\tID: feature.id,\n\t\t\t\t\tIdentifier: feature.identifier,\n\t\t\t\t\tTitle: feature.title,\n\t\t\t\t\tPriority: feature.priority,\n\t\t\t\t\tProject: feature.projectId,\n\t\t\t\t\tCreated: feature.createdAt.slice(0, 10),\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\t// -- tasks ---------------------------------------------------------------\n\tfeatures\n\t\t.command(\"tasks\")\n\t\t.description(\"List tasks (sub-items) for a feature\")\n\t\t.requiredOption(\"-p, --project <projectId>\", \"Project ID\")\n\t\t.requiredOption(\"-f, --feature <featureId>\", \"Feature ID\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\n\t\t\t\"--format <format>\",\n\t\t\t\"Output format: table|json|yaml|csv\",\n\t\t\t\"table\",\n\t\t)\n\t\t.option(\"-q, --quiet\", \"Print IDs only\")\n\t\t.action(\n\t\t\tasync (opts: {\n\t\t\t\tproject: string;\n\t\t\t\tfeature: string;\n\t\t\t\torg?: string;\n\t\t\t\tpersonal?: boolean;\n\t\t\t\tformat: string;\n\t\t\t\tquiet?: boolean;\n\t\t\t}) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet tasks: import(\"@fabricorg/sdk\").FabricTask[];\n\t\t\t\ttry {\n\t\t\t\t\ttasks = await client.projects.listTasks(\n\t\t\t\t\t\topts.project,\n\t\t\t\t\t\topts.feature,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tif (opts.quiet) {\n\t\t\t\t\tfor (const t of tasks) {\n\t\t\t\t\t\tprocess.stdout.write(`${t.id}\\n`);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintOutput(tasks, {\n\t\t\t\t\tformat: opts.format as \"table\" | \"json\" | \"yaml\" | \"csv\",\n\t\t\t\t\tcolumns: [\n\t\t\t\t\t\t\"identifier\",\n\t\t\t\t\t\t\"title\",\n\t\t\t\t\t\t\"status\",\n\t\t\t\t\t\t\"estimatedHours\",\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\t// -- update --------------------------------------------------------------\n\tfeatures\n\t\t.command(\"update <id>\")\n\t\t.description(\"Update a feature\")\n\t\t.requiredOption(\"-p, --project <projectId>\", \"Project ID\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--title <title>\", \"New title\")\n\t\t.option(\"-d, --description <text>\", \"New description\")\n\t\t.option(\n\t\t\t\"--priority <priority>\",\n\t\t\t\"Priority: P0_CRITICAL|P1_HIGH|P2_MEDIUM|P3_LOW\",\n\t\t)\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tid: string,\n\t\t\t\topts: {\n\t\t\t\t\tproject: string;\n\t\t\t\t\torg?: string;\n\t\t\t\t\tpersonal?: boolean;\n\t\t\t\t\ttitle?: string;\n\t\t\t\t\tdescription?: string;\n\t\t\t\t\tpriority?: string;\n\t\t\t\t\tformat: string;\n\t\t\t\t},\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet feature: FabricFeature;\n\t\t\t\ttry {\n\t\t\t\t\tfeature = await client.projects.updateFeature(\n\t\t\t\t\t\topts.project,\n\t\t\t\t\t\tid,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttitle: opts.title,\n\t\t\t\t\t\t\tdescription: opts.description,\n\t\t\t\t\t\t\tpriority: opts.priority as\n\t\t\t\t\t\t\t\t| FabricFeature[\"priority\"]\n\t\t\t\t\t\t\t\t| undefined,\n\t\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(feature, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintRecord({\n\t\t\t\t\tID: feature.id,\n\t\t\t\t\tIdentifier: feature.identifier,\n\t\t\t\t\tTitle: feature.title,\n\t\t\t\t\tPriority: feature.priority,\n\t\t\t\t\tUpdated: feature.updatedAt.slice(0, 10),\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\treturn features;\n}\n","/**\n * fabric frames\n *\n * fabric frames list List frames and slideshows\n * fabric frames show <id> Show frame details\n */\n\nimport type { FabricFrame } from \"@fabricorg/sdk\";\nimport { Command } from \"commander\";\nimport { getClient } from \"../../lib/client.js\";\nimport { resolveContext } from \"../../lib/context.js\";\nimport { printError, printOutput, printRecord } from \"../../lib/output.js\";\n\nexport function buildFramesCommand(): Command {\n\tconst frames = new Command(\"frames\").description(\n\t\t\"Manage AI-generated frames and slideshows\",\n\t);\n\n\t// -- list ----------------------------------------------------------------\n\tframes\n\t\t.command(\"list\")\n\t\t.description(\"List frames and slideshows\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--limit <n>\", \"Max results (default 50)\", \"50\")\n\t\t.option(\n\t\t\t\"--format <format>\",\n\t\t\t\"Output format: table|json|yaml|csv\",\n\t\t\t\"table\",\n\t\t)\n\t\t.option(\"-q, --quiet\", \"Print IDs only\")\n\t\t.action(\n\t\t\tasync (opts: {\n\t\t\t\torg?: string;\n\t\t\t\tpersonal?: boolean;\n\t\t\t\tlimit: string;\n\t\t\t\tformat: string;\n\t\t\t\tquiet?: boolean;\n\t\t\t}) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet list: FabricFrame[];\n\t\t\t\ttry {\n\t\t\t\t\tlist = await client.frames.list({\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t\tlimit: Number(opts.limit),\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tif (opts.quiet) {\n\t\t\t\t\tfor (const f of list) {\n\t\t\t\t\t\tprocess.stdout.write(`${f.id}\\n`);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintOutput(list, {\n\t\t\t\t\tformat: opts.format as \"table\" | \"json\" | \"yaml\" | \"csv\",\n\t\t\t\t\tcolumns: [\n\t\t\t\t\t\t\"id\",\n\t\t\t\t\t\t\"title\",\n\t\t\t\t\t\t\"fileType\",\n\t\t\t\t\t\t\"status\",\n\t\t\t\t\t\t\"isPublic\",\n\t\t\t\t\t\t\"updatedAt\",\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\t// -- show ----------------------------------------------------------------\n\tframes\n\t\t.command(\"show <id>\")\n\t\t.description(\"Show frame details\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tid: string,\n\t\t\t\topts: { org?: string; personal?: boolean; format: string },\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet frame: FabricFrame;\n\t\t\t\ttry {\n\t\t\t\t\tframe = await client.frames.get(id, {\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(frame, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintRecord({\n\t\t\t\t\tID: frame.id,\n\t\t\t\t\tTitle: frame.title,\n\t\t\t\t\tKind: frame.kind ?? \"(none)\",\n\t\t\t\t\t\"File Type\": frame.fileType,\n\t\t\t\t\tStatus: frame.status,\n\t\t\t\t\tPublic: frame.isPublic ? \"yes\" : \"no\",\n\t\t\t\t\t\"Share Token\": frame.shareToken ?? \"(none)\",\n\t\t\t\t\tDescription: frame.description ?? \"(none)\",\n\t\t\t\t\tUpdated: frame.updatedAt.slice(0, 10),\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\treturn frames;\n}\n","/**\n * fabric instructions\n *\n * fabric instructions check --project <id> Is the local copy current?\n * fabric instructions sync --project <id> Make it current.\n * fabric instructions init --project <id> --tool claude-code\n * Write the session hook, then sync.\n *\n * The first file-writing commands in this CLI. Everything that touches the\n * filesystem lives in `lib/instructions/` as small testable modules; this\n * file is argument parsing, the sequence, and the words a developer reads.\n *\n * `--hook` is the contract that makes this safe to run at session start: it\n * NEVER exits non-zero, it has ONE absolute deadline covering every request\n * it makes, and it never prints more than it has to. A coding session that\n * cannot start because Fabric is unreachable would be a far worse failure\n * than instructions that are one version stale.\n */\nimport path from \"node:path\";\nimport type { FabricClient, PublishedInstructions } from \"@fabricorg/sdk\";\nimport { Command } from \"commander\";\nimport { getClient } from \"../../lib/client.js\";\nimport { getApiKey, getConfigPath } from \"../../lib/config.js\";\nimport { applyPlan } from \"../../lib/instructions/apply.js\";\nimport { extractBundle, fetchBundle } from \"../../lib/instructions/bundle.js\";\nimport {\n\tassertKeyStaysOutside,\n\tbuildHookCommand,\n\tCLAUDE_SETTINGS_RELATIVE_PATH,\n\tmergeSessionStartHook,\n} from \"../../lib/instructions/hook.js\";\nimport {\n\ttype InstructionsLock,\n\tLOCK_DIRECTORY,\n\tlockPath,\n\treadLock,\n\twriteLock,\n} from \"../../lib/instructions/lock.js\";\nimport {\n\tassertValidManifest,\n\tmaxArchiveBytes,\n} from \"../../lib/instructions/manifest.js\";\nimport {\n\tcomputeSyncPlan,\n\tnextLock,\n\ttype SyncPlan,\n\tverifyLedger,\n} from \"../../lib/instructions/plan.js\";\nimport {\n\tresolveDestinationRoot,\n\tresolveExistingRoot,\n} from \"../../lib/instructions/safe-write.js\";\nimport { printOutput } from \"../../lib/output.js\";\n\n/**\n * The whole of hook mode, end to end, including the bundle download.\n *\n * One ABSOLUTE deadline rather than one per request. The SDK's timeout is\n * per attempt and it retries twice by default, so three \"5 second\" calls\n * plus backoff is about 15.75 seconds — past the point where Claude Code\n * kills the hook itself, possibly mid-write. Retries are off in hook mode\n * and this bound covers everything.\n */\nconst HOOK_DEADLINE_MS = 10_000;\n\n/** A manual check: no writes, so one short request and no more. */\nconst CHECK_TIMEOUT_MS = 5_000;\n\n/** A manual sync may wait longer for the manifest, but not indefinitely. */\nconst SYNC_TIMEOUT_MS = 15_000;\n\n/** The archive, when a person is waiting rather than a session start. */\nconst BUNDLE_TIMEOUT_MS = 60_000;\n\n/**\n * A failure that already knows which documented exit code it is\n * (`src/bin/fabric.ts`). Errors from the SDK are translated into one of\n * these at the boundary so the command bodies can just throw.\n */\nclass CliFailure extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\treadonly exitCode: number,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"CliFailure\";\n\t}\n}\n\ninterface CommonOptions {\n\tproject: string;\n\tdest?: string;\n\torg?: string;\n\thook?: boolean;\n\t/**\n\t * Declared for `--help` and read through `optsWithGlobals()`, never off\n\t * this object: Commander stores a flag both a parent and a subcommand\n\t * declare on the parent.\n\t */\n\tformat?: string;\n}\n\ntype OutputFormat = \"text\" | \"json\";\n\nexport function buildInstructionsCommand(): Command {\n\tconst instructions = new Command(\"instructions\").description(\n\t\t\"Keep a checkout current with a project's published coding instructions\",\n\t);\n\n\tinstructions\n\t\t.command(\"check\")\n\t\t.description(\n\t\t\t\"Report whether the local copy is behind the published one\",\n\t\t)\n\t\t.requiredOption(\"--project <id>\", \"Project ID\")\n\t\t.option(\"--dest <dir>\", \"Destination directory (default: cwd)\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\n\t\t\t\"--verify\",\n\t\t\t\"Also hash the local files against the lock and report any that drifted\",\n\t\t)\n\t\t.option(\n\t\t\t\"--hook\",\n\t\t\t\"Session-hook mode: plain text, never fails, never blocks a session\",\n\t\t)\n\t\t// No default: a default here would shadow the program-level --format,\n\t\t// which is where `FABRIC_FORMAT` enters.\n\t\t.option(\"--format <format>\", \"Output format: text|json\")\n\t\t.action(async function (\n\t\t\tthis: Command,\n\t\t\topts: CommonOptions & { verify?: boolean },\n\t\t) {\n\t\t\tawait run(opts, \"check\", () => runCheck(opts, formatFor(this)));\n\t\t});\n\n\tinstructions\n\t\t.command(\"sync\")\n\t\t.description(\n\t\t\t\"Write the published coding instructions into the checkout\",\n\t\t)\n\t\t.requiredOption(\"--project <id>\", \"Project ID\")\n\t\t.option(\"--dest <dir>\", \"Destination directory (default: cwd)\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--dry-run\", \"Print the plan and write nothing\")\n\t\t.option(\n\t\t\t\"--hook\",\n\t\t\t\"Session-hook mode: plain text, never fails, never blocks a session\",\n\t\t)\n\t\t.option(\"--format <format>\", \"Output format: text|json\")\n\t\t.action(async function (\n\t\t\tthis: Command,\n\t\t\topts: CommonOptions & { dryRun?: boolean },\n\t\t) {\n\t\t\tawait run(opts, \"sync\", () => runSync(opts, formatFor(this)));\n\t\t});\n\n\tinstructions\n\t\t.command(\"init\")\n\t\t.description(\n\t\t\t\"Write a SessionStart hook for a coding tool and take the first copy\",\n\t\t)\n\t\t.requiredOption(\"--project <id>\", \"Project ID\")\n\t\t.requiredOption(\n\t\t\t\"--tool <tool>\",\n\t\t\t\"Coding tool to configure: claude-code\",\n\t\t)\n\t\t.option(\"--dest <dir>\", \"Destination directory (default: cwd)\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\n\t\t\t\"--apply\",\n\t\t\t\"Let the hook apply changes instead of only reporting them\",\n\t\t)\n\t\t.option(\"--format <format>\", \"Output format: text|json\")\n\t\t.action(async function (\n\t\t\tthis: Command,\n\t\t\topts: CommonOptions & { tool: string; apply?: boolean },\n\t\t) {\n\t\t\t// Never hook mode: `init` is run by a person, so its failures\n\t\t\t// are real failures with real exit codes.\n\t\t\tawait run({ ...opts, hook: false }, \"init\", () =>\n\t\t\t\trunInit(opts, formatFor(this)),\n\t\t\t);\n\t\t});\n\n\treturn instructions;\n}\n\n// ---------------------------------------------------------------------------\n// Output format\n// ---------------------------------------------------------------------------\n\n/**\n * The format this invocation should print in: `json`, or text.\n *\n * One reader, `optsWithGlobals()`, because Commander has already done the\n * resolving. The root command declares `--format` with a default of\n * `FABRIC_FORMAT ?? \"table\"`, these commands declare their own, and\n * `optsWithGlobals` merges them with the command's own value winning. Reading\n * `FABRIC_FORMAT` again here undid that: `FABRIC_FORMAT=json fabric --format\n * table instructions check` printed JSON at the very moment the flag said not\n * to (review round 2, finding 10).\n *\n * Anything that is not `json` prints text. `table`, `yaml` and `csv` are real\n * values elsewhere in this CLI and these commands have no such shape — one\n * paragraph or one JSON object — so they degrade rather than fail. Refusing\n * them here would also be a promise this cannot keep: when a parent and a\n * subcommand declare the same flag, Commander stores the value on the ROOT,\n * so `fabric instructions check --format yaml` never arrives as a local\n * option at all.\n */\nfunction formatFor(command: Command): OutputFormat {\n\tconst resolved = command.optsWithGlobals() as { format?: string };\n\treturn resolved.format === \"json\" ? \"json\" : \"text\";\n}\n\n// ---------------------------------------------------------------------------\n// The never-fail boundary\n// ---------------------------------------------------------------------------\n\n/**\n * One place where every failure is turned into either an exit code or, under\n * `--hook`, a single line on stderr and a zero exit.\n *\n * \"Every\" is literal: network, auth, HTTP, timeout, a bad lock file, a\n * refused path, a retired context default. Nothing inside may call\n * `process.exit` itself — `printError` does, and `process.exit` cannot be\n * caught here, which is why these commands build their own client rather than\n * reaching for the exiting helpers the other commands use, and why they read\n * no stored context at all.\n */\nasync function run(\n\topts: { hook?: boolean },\n\tverb: string,\n\tbody: () => Promise<void>,\n): Promise<void> {\n\ttry {\n\t\tif (opts.hook) {\n\t\t\tawait withDeadline(HOOK_DEADLINE_MS, body);\n\t\t} else {\n\t\t\tawait body();\n\t\t}\n\t} catch (error) {\n\t\tconst message = describeError(error);\n\t\tif (opts.hook) {\n\t\t\tprocess.stderr.write(\n\t\t\t\t`fabric: coding instructions ${verb} skipped: ${message}\\n`,\n\t\t\t);\n\t\t\tprocess.exit(0);\n\t\t}\n\t\tprocess.stderr.write(`✗ ${message}\\n`);\n\t\tprocess.exit(error instanceof CliFailure ? error.exitCode : 1);\n\t}\n}\n\n/**\n * The absolute bound on hook mode.\n *\n * A race rather than a chain of per-request timeouts: the guarantee has to\n * hold whatever the SDK, the runtime or a wedged socket does, and only the\n * caller can promise that. The losing work is abandoned rather than awaited,\n * which is safe because the boundary above exits the process immediately\n * afterwards.\n */\nasync function withDeadline(\n\ttotalMs: number,\n\tbody: () => Promise<void>,\n): Promise<void> {\n\tconst controller = new AbortController();\n\tlet timer: NodeJS.Timeout | undefined;\n\tconst deadline = new Promise<never>((_resolve, reject) => {\n\t\ttimer = setTimeout(() => {\n\t\t\tcontroller.abort();\n\t\t\treject(\n\t\t\t\tnew Error(\n\t\t\t\t\t`gave up after ${totalMs}ms so the session is not held up`,\n\t\t\t\t),\n\t\t\t);\n\t\t}, totalMs);\n\t});\n\tactiveDeadline = controller.signal;\n\ttry {\n\t\tawait Promise.race([body(), deadline]);\n\t} finally {\n\t\tactiveDeadline = undefined;\n\t\tif (timer) {\n\t\t\tclearTimeout(timer);\n\t\t}\n\t}\n}\n\n/**\n * The deadline signal in force, if any, so the bundle download can be\n * cancelled by the same clock that bounds the command. Module state rather\n * than a threaded parameter because every command body is single-shot within\n * one process.\n */\nlet activeDeadline: AbortSignal | undefined;\n\nfunction describeError(error: unknown): string {\n\tif (error instanceof Error) {\n\t\t// Collapsed to one line: under `--hook` this lands in a terminal\n\t\t// banner and, on Claude Code, in the agent's context.\n\t\treturn error.message.replace(/\\s*\\n\\s*/g, \" \");\n\t}\n\treturn String(error);\n}\n\n/**\n * SDK errors carry an HTTP status; the CLI's documented exit codes do not\n * come from it automatically. Mapped once, here.\n */\nfunction asCliFailure(error: unknown): CliFailure {\n\tif (error instanceof CliFailure) {\n\t\treturn error;\n\t}\n\tconst status = (error as { status?: number }).status;\n\tconst message = error instanceof Error ? error.message : String(error);\n\tswitch (status) {\n\t\tcase 401:\n\t\t\treturn new CliFailure(message, 3);\n\t\tcase 403:\n\t\t\treturn new CliFailure(message, 5);\n\t\tcase 404:\n\t\t\treturn new CliFailure(message, 4);\n\t\tcase 429:\n\t\t\treturn new CliFailure(message, 6);\n\t\tcase 400:\n\t\tcase 422:\n\t\t\treturn new CliFailure(message, 7);\n\t\tdefault:\n\t\t\treturn new CliFailure(message, 1);\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Shared steps\n// ---------------------------------------------------------------------------\n\nfunction destinationOf(opts: { dest?: string }): string {\n\treturn path.resolve(opts.dest ?? process.cwd());\n}\n\n/**\n * A client that throws instead of exiting, and that never retries in hook\n * mode.\n *\n * `getClient` calls `printError`, which exits with code 3 — correct for every\n * other command and fatal to the `--hook` contract, which must never exit\n * non-zero for any reason.\n */\nfunction instructionsClient(\n\topts: { hook?: boolean },\n\ttimeoutMs: number,\n): FabricClient {\n\tif (!getApiKey()) {\n\t\tthrow new CliFailure(\n\t\t\t\"Not authenticated. Run: fabric auth login --key <api-key>\",\n\t\t\t3,\n\t\t);\n\t}\n\t// `withoutContext()`: the SDK constructor adopts `FABRIC_ORG` /\n\t// `FABRIC_PERSONAL` and injects them into every URL that does not name a\n\t// context. On a project-authoritative surface that ambient default is not\n\t// a default, it is a contradiction waiting to be refused — see\n\t// `orgSlugFor`.\n\treturn getClient(\n\t\topts.hook\n\t\t\t? {\n\t\t\t\t\ttimeoutMs: Math.min(timeoutMs, HOOK_DEADLINE_MS),\n\t\t\t\t\tretry: { maxRetries: 0 },\n\t\t\t\t}\n\t\t\t: { timeoutMs },\n\t).withoutContext();\n}\n\n/**\n * The org slug to send: the one on the command line, or none at all.\n *\n * These commands are PROJECT-AUTHORITATIVE — the project decides which\n * organization it is in, and the route resolves that from the project itself.\n * Sending a stored default context (or `FABRIC_ORG`) turned that resolution\n * into a contradiction for anyone whose default is not the project's host\n * organization, and the clearest case is the one the route exists to support:\n * an invited guest, whose own default organization is never the one hosting a\n * project they were invited to. Their request carried `?org=<their own org>`,\n * the route compared it with the project's, and refused.\n *\n * So the ambient default is not consulted here and the client is built\n * without one. `--org` remains available for the caller who wants the request\n * bound explicitly; an explicit slug that disagrees with the project is still\n * a 404, which is the point of passing it.\n */\nfunction orgSlugFor(opts: CommonOptions): string | undefined {\n\treturn opts.org;\n}\n\nasync function fetchPublished(\n\tclient: FabricClient,\n\topts: CommonOptions,\n\tsinceDigest?: string,\n): Promise<PublishedInstructions> {\n\tconst org = orgSlugFor(opts);\n\tlet published: PublishedInstructions;\n\ttry {\n\t\tpublished = await client.instructions.getPublished(opts.project, {\n\t\t\torg,\n\t\t\tsinceDigest,\n\t\t});\n\t} catch (error) {\n\t\tthrow asCliFailure(error);\n\t}\n\tassertHookMayAct(opts, published);\n\treturn published;\n}\n\n/**\n * A hook may not act on a project whose instructions come from git.\n *\n * Asserted on EVERY response rather than on the first one, because a command\n * can make two calls: a delta answer, and then — when the local tree has\n * drifted — a full refetch. Checking only the first meant a project switched\n * to `REPOSITORY` between the two was planned, downloaded and applied by a\n * hook, which is the second writer `init` refuses to create.\n *\n * `init` refuses such a project outright; a person running `sync` or `check`\n * by hand is unaffected, because for someone without access to that\n * repository a download is the only way to read the instructions at all.\n */\nfunction assertHookMayAct(\n\topts: { hook?: boolean },\n\tpublished: PublishedInstructions,\n): void {\n\tif (opts.hook && published.sourceOfTruth === \"REPOSITORY\") {\n\t\tthrow new CliFailure(\n\t\t\t\"this project's instructions now come from a git repository; run `fabric instructions init` again or remove the hook\",\n\t\t\t4,\n\t\t);\n\t}\n}\n\n/**\n * The lock, refused when it belongs to a different project.\n *\n * A lock is a per-destination file and a destination holds one project's\n * tree. `sync --project B` in a directory synced from project A would\n * otherwise send A's digest, receive B's manifest, and then use A's ledger to\n * decide what to delete — classifying every A-only file as \"the sync wrote\n * this, remove it\". Equal digests across the two could even report \"up to\n * date\" for a tree that holds the wrong project's instructions entirely.\n */\nasync function readLockForProject(\n\tdestination: string,\n\tprojectId: string,\n): Promise<InstructionsLock | null> {\n\tconst lock = await readLock(destination);\n\tif (lock !== null && lock.projectId !== projectId) {\n\t\tthrow new CliFailure(\n\t\t\t`${lockPath(destination)} belongs to project ${lock.projectId}, not ${projectId}. Use a different --dest, or remove that lock if this directory should now follow ${projectId}.`,\n\t\t\t7,\n\t\t);\n\t}\n\treturn lock;\n}\n\nfunction line(text: string): void {\n\tprocess.stdout.write(`${text}\\n`);\n}\n\nfunction listPaths(label: string, paths: string[]): void {\n\tif (paths.length === 0) {\n\t\treturn;\n\t}\n\tline(` ${label}:`);\n\tfor (const p of paths) {\n\t\tline(` ${p}`);\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// check\n// ---------------------------------------------------------------------------\n\nasync function runCheck(\n\topts: CommonOptions & { verify?: boolean },\n\tformat: OutputFormat,\n): Promise<void> {\n\tconst destination = destinationOf(opts);\n\t// Canonical, but NOT created: `check` is informational and must not make a\n\t// directory as a side effect. Every guarded read resolves against this,\n\t// and a literal path would refuse legitimately — `/tmp` is a symlink on\n\t// macOS, so the string a user passes and the directory they mean differ.\n\tconst root = await resolveExistingRoot(destination);\n\tconst lock = await readLockForProject(destination, opts.project);\n\tconst client = instructionsClient(opts, CHECK_TIMEOUT_MS);\n\tconst published = await fetchPublished(client, opts, lock?.digest);\n\n\t// Deliberately NOT validated against `assertValidManifest`: `check`\n\t// writes nothing, so a skewed manifest here can only produce a less\n\t// useful report, and refusing would make the informational command the\n\t// fragile one. `sync` validates before it can act on it.\n\n\t// Off by default, and that is the trade rather than an oversight: this is\n\t// the command a session start runs, one request and no local reads. With\n\t// `--verify` it also hashes every file the lock names, which is what\n\t// answers \"is my checkout still what was published\" as opposed to \"has\n\t// the published version moved\". `sync` always does this.\n\tconst drifted =\n\t\topts.verify && lock !== null ? await verifyLedger({ root, lock }) : [];\n\n\tif (format === \"json\") {\n\t\tprintOutput(\n\t\t\t{\n\t\t\t\tprojectId: opts.project,\n\t\t\t\tdestination,\n\t\t\t\tsynced: lock !== null,\n\t\t\t\tlocalDigest: lock?.digest ?? null,\n\t\t\t\tverified: Boolean(opts.verify),\n\t\t\t\tdrifted,\n\t\t\t\t...published,\n\t\t\t},\n\t\t\t{ format: \"json\" },\n\t\t);\n\t\treturn;\n\t}\n\n\treportPublishedState(opts, destination, lock, published);\n\n\t// The common tail. Every text-mode branch returns through here, because\n\t// `--verify` promises to report local drift and three of those branches\n\t// used to return before saying a word about it.\n\tif (opts.verify) {\n\t\treportDrift(opts, destination, drifted);\n\t}\n}\n\n/** What the server said about the published snapshot, in text. */\nfunction reportPublishedState(\n\topts: CommonOptions,\n\tdestination: string,\n\tlock: InstructionsLock | null,\n\tpublished: PublishedInstructions,\n): void {\n\tif (!published.published) {\n\t\tline(\"This project has no published coding instructions yet.\");\n\t\treturn;\n\t}\n\n\tconst version = published.snapshot?.version;\n\n\tif (!lock) {\n\t\tline(\n\t\t\t`Coding instructions have not been synced into ${destination} yet (published version ${version}, ${published.snapshot?.fileCount} files).`,\n\t\t);\n\t\tline(\n\t\t\t`Run \\`fabric instructions sync --project ${opts.project}\\` to take a copy.`,\n\t\t);\n\t\treturn;\n\t}\n\n\tif (published.unchanged) {\n\t\t// \"the published version has not moved\" — NOT \"your files are\n\t\t// correct\". Without `--verify` nothing local has been read at all, and\n\t\t// saying \"up to date\" invited exactly the wrong conclusion.\n\t\tline(`Published coding instructions unchanged (version ${version}).`);\n\t\treturn;\n\t}\n\n\tif (published.changes === null || published.changes === undefined) {\n\t\tline(\n\t\t\t`Coding instructions changed, and the version in ${destination} is not one the server still recognises, so what changed cannot be listed. A full sync is needed (published version ${version}).`,\n\t\t);\n\t\tline(\n\t\t\t`Run \\`fabric instructions sync --project ${opts.project}\\` to apply.`,\n\t\t);\n\t\treturn;\n\t}\n\n\tconst { added, changed, removed } = published.changes;\n\tline(\n\t\t`Coding instructions updated: ${added.length} added, ${changed.length} changed, ${removed.length} removed (version ${version}).`,\n\t);\n\tlistPaths(\"added\", added);\n\tlistPaths(\"changed\", changed);\n\tlistPaths(\"removed\", removed);\n\tline(\n\t\t`Run \\`fabric instructions sync --project ${opts.project}\\` to apply.`,\n\t);\n}\n\n/** What `--verify` found, in the two places the report can end. */\nfunction reportDrift(\n\topts: CommonOptions,\n\tdestination: string,\n\tdrifted: string[],\n): void {\n\tif (drifted.length === 0) {\n\t\tline(`Every file in ${destination} matches the lock.`);\n\t\treturn;\n\t}\n\tline(`${drifted.length} local file(s) no longer match the lock:`);\n\tlistPaths(\"drifted\", drifted);\n\tline(\n\t\t`Run \\`fabric instructions sync --project ${opts.project}\\` to put them back.`,\n\t);\n}\n\n// ---------------------------------------------------------------------------\n// sync\n// ---------------------------------------------------------------------------\n\nasync function runSync(\n\topts: CommonOptions & { dryRun?: boolean },\n\tformat: OutputFormat,\n): Promise<void> {\n\tconst result = await syncOnce(opts);\n\tif (format === \"json\") {\n\t\tprintOutput(result, { format: \"json\" });\n\t\treturn;\n\t}\n\treportSync(result, opts);\n}\n\ninterface SyncOutcome {\n\tprojectId: string;\n\tdestination: string;\n\tpublished: boolean;\n\tunchanged: boolean;\n\tdryRun: boolean;\n\tversion: number | null;\n\tdigest: string | null;\n\tadded: string[];\n\tupdated: string[];\n\treplaced: string[];\n\tremoved: string[];\n\tkeptModified: string[];\n\t/**\n\t * Paths the lock still names under an old spelling that the manifest now\n\t * spells differently. Reported rather than removed: on a case-insensitive\n\t * filesystem they ARE the file the sync just wrote.\n\t */\n\tkeptRenamed: string[];\n\t/**\n\t * Paths the lock claimed that the working tree no longer matched, when the\n\t * published snapshot itself had not moved. Non-empty means this run\n\t * repaired local drift rather than applying a new version.\n\t */\n\tdrifted: string[];\n\tverified: number;\n\tlockPath: string;\n}\n\nfunction emptyOutcome(\n\topts: CommonOptions & { dryRun?: boolean },\n\tdestination: string,\n): SyncOutcome {\n\treturn {\n\t\tprojectId: opts.project,\n\t\tdestination,\n\t\tpublished: true,\n\t\tunchanged: false,\n\t\tdryRun: Boolean(opts.dryRun),\n\t\tversion: null,\n\t\tdigest: null,\n\t\tadded: [],\n\t\tupdated: [],\n\t\treplaced: [],\n\t\tremoved: [],\n\t\tkeptModified: [],\n\t\tkeptRenamed: [],\n\t\tdrifted: [],\n\t\tverified: 0,\n\t\tlockPath: lockPath(destination),\n\t};\n}\n\nasync function syncOnce(\n\topts: CommonOptions & { dryRun?: boolean },\n): Promise<SyncOutcome> {\n\t// Canonical from here on: every write resolves against this, so a\n\t// symlinked `--dest` (or `/tmp` on macOS) is decided once rather than at\n\t// each write.\n\tconst root = await resolveDestinationRoot(destinationOf(opts));\n\tconst outcome = emptyOutcome(opts, root);\n\n\tconst lock = await readLockForProject(root, opts.project);\n\tconst client = instructionsClient(opts, SYNC_TIMEOUT_MS);\n\tlet published = await fetchPublished(client, opts, lock?.digest);\n\n\t// The repository-source refusal lives in `fetchPublished`, so the drift\n\t// refetch below inherits it rather than trusting the first answer.\n\n\tif (!published.published || !published.snapshot) {\n\t\t// A real failure for a person who asked for a copy; the `--hook`\n\t\t// boundary turns it into one quiet line for a session start.\n\t\tthrow new CliFailure(\n\t\t\t\"This project has no published coding instructions yet.\",\n\t\t\t4,\n\t\t);\n\t}\n\n\toutcome.version = published.snapshot.version;\n\toutcome.digest = published.snapshot.digest;\n\n\tif (published.unchanged) {\n\t\t// \"Unchanged\" is the SERVER's answer about the SNAPSHOT, and it says\n\t\t// nothing about the checkout. Accepting it as \"nothing to do\" let an\n\t\t// edited, deleted or chmod-ed instruction file stay that way until\n\t\t// some later publication happened to move the digest — so a tampered\n\t\t// tree reported success indefinitely. The ledger is the local half of\n\t\t// the question, and hashing it is the price of a command that applies\n\t\t// things.\n\t\tconst drifted = lock === null ? [] : await verifyLedger({ root, lock });\n\t\tif (drifted.length === 0) {\n\t\t\toutcome.unchanged = true;\n\t\t\treturn outcome;\n\t\t}\n\n\t\toutcome.drifted = drifted;\n\t\t// The first call answered with a delta and therefore carries no\n\t\t// manifest. Ask again without a base digest: the plan needs the whole\n\t\t// published list to put the tree back.\n\t\tpublished = await fetchPublished(client, opts);\n\t\tif (!published.published || !published.snapshot) {\n\t\t\tthrow new CliFailure(\n\t\t\t\t\"This project has no published coding instructions yet.\",\n\t\t\t\t4,\n\t\t\t);\n\t\t}\n\t\toutcome.version = published.snapshot.version;\n\t\toutcome.digest = published.snapshot.digest;\n\t}\n\n\t// An absent manifest is a refusal, never an empty one. `[]` means\n\t// \"delete everything the lock names\", so a version-skewed or truncated\n\t// response was one step from emptying the tree and writing a ledger that\n\t// agreed with it.\n\tconst manifest = assertValidManifest({\n\t\tmanifest: published.manifest,\n\t\tsnapshot: published.snapshot,\n\t});\n\n\tconst plan = await computeSyncPlan({ destination: root, manifest, lock });\n\tfillPlanPaths(outcome, plan);\n\n\tif (opts.dryRun) {\n\t\t// The plan is computable from the manifest alone, so a dry run\n\t\t// downloads nothing at all.\n\t\treturn outcome;\n\t}\n\n\tlet contents = new Map<string, Uint8Array>();\n\tif (plan.writes.length > 0) {\n\t\tconst org = orgSlugFor(opts);\n\t\tlet download: { url: string };\n\t\ttry {\n\t\t\tdownload = await client.instructions.createDownloadUrl(\n\t\t\t\topts.project,\n\t\t\t\t{ org },\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tthrow asCliFailure(error);\n\t\t}\n\t\tconst sizes = new Map(\n\t\t\tmanifest.map((entry) => [entry.path, entry.size] as const),\n\t\t);\n\t\tconst archive = await fetchBundle(download.url, {\n\t\t\ttimeoutMs: opts.hook ? HOOK_DEADLINE_MS : BUNDLE_TIMEOUT_MS,\n\t\t\t// Bounded by what this manifest says it holds, not by what the\n\t\t\t// response claims. The manifest has already been checked against\n\t\t\t// the published snapshot limits, so this is a number the client\n\t\t\t// decided.\n\t\t\tmaxBytes: maxArchiveBytes(manifest),\n\t\t\t// In hook mode the same clock that bounds the command bounds the\n\t\t\t// download, rather than a second independent budget after it.\n\t\t\tsignal: activeDeadline,\n\t\t});\n\t\tcontents = extractBundle(\n\t\t\tarchive,\n\t\t\tplan.writes.map((entry) => ({\n\t\t\t\tpath: entry.path,\n\t\t\t\tsize: sizes.get(entry.path) ?? -1,\n\t\t\t})),\n\t\t);\n\t}\n\n\tconst applied = await applyPlan({ root, plan, contents });\n\t// What actually happened, not what was planned: a delete whose file was\n\t// edited between planning and the unlink is reported as kept, because that\n\t// is what it is.\n\toutcome.removed = applied.deleted;\n\toutcome.keptModified = [\n\t\t...outcome.keptModified,\n\t\t...applied.keptModified,\n\t].sort();\n\n\t// Last, and only now: a lock written before the files would claim\n\t// ownership of paths that are not there, and the next run would delete\n\t// whatever the developer had in their place.\n\tconst lockToWrite: InstructionsLock = nextLock({\n\t\tprojectId: opts.project,\n\t\tsnapshot: {\n\t\t\tid: published.snapshot.id,\n\t\t\tversion: published.snapshot.version,\n\t\t\tdigest: published.snapshot.digest,\n\t\t},\n\t\tmanifest,\n\t});\n\tawait writeLock(root, lockToWrite);\n\n\treturn outcome;\n}\n\nfunction fillPlanPaths(outcome: SyncOutcome, plan: SyncPlan): void {\n\toutcome.added = plan.entries\n\t\t.filter((entry) => entry.action === \"added\")\n\t\t.map((entry) => entry.path);\n\toutcome.updated = plan.entries\n\t\t.filter((entry) => entry.action === \"updated\")\n\t\t.map((entry) => entry.path);\n\toutcome.replaced = plan.entries\n\t\t.filter((entry) => entry.action === \"replaced\")\n\t\t.map((entry) => entry.path);\n\toutcome.removed = plan.deletes.map((entry) => entry.path);\n\toutcome.keptModified = plan.keptModified.map((entry) => entry.path);\n\toutcome.keptRenamed = plan.keptRenamed.map((entry) => entry.path);\n\toutcome.verified = plan.verified.length;\n}\n\nfunction reportSync(\n\toutcome: SyncOutcome,\n\topts: CommonOptions & { dryRun?: boolean },\n): void {\n\tif (outcome.unchanged) {\n\t\tline(\n\t\t\t`Coding instructions are up to date (version ${outcome.version}).`,\n\t\t);\n\t\treturn;\n\t}\n\n\tconst total =\n\t\toutcome.added.length +\n\t\toutcome.updated.length +\n\t\toutcome.replaced.length +\n\t\toutcome.removed.length;\n\tif (outcome.drifted.length > 0) {\n\t\tline(\n\t\t\t`Coding instructions version ${outcome.version} is still the published one, but ${outcome.drifted.length} local file(s) no longer match it:`,\n\t\t);\n\t\tlistPaths(\"drifted\", outcome.drifted);\n\t}\n\n\tconst prefix = opts.dryRun ? \"Would apply\" : \"Applied\";\n\tline(\n\t\t`${prefix} coding instructions version ${outcome.version}: ${outcome.added.length} added, ${outcome.updated.length} updated, ${outcome.replaced.length} replaced, ${outcome.removed.length} removed (${outcome.verified} already current).`,\n\t);\n\tlistPaths(\"added\", outcome.added);\n\tlistPaths(\"updated\", outcome.updated);\n\tlistPaths(\"replaced local edits\", outcome.replaced);\n\tlistPaths(\"removed\", outcome.removed);\n\tlistPaths(\"kept, modified locally\", outcome.keptModified);\n\tlistPaths(\"kept, renamed in the published snapshot\", outcome.keptRenamed);\n\tif (!opts.dryRun) {\n\t\tline(`Lock: ${outcome.lockPath}`);\n\t}\n\tif (\n\t\ttotal === 0 &&\n\t\toutcome.keptModified.length === 0 &&\n\t\toutcome.keptRenamed.length === 0\n\t) {\n\t\tline(`Everything in ${outcome.destination} already matched.`);\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// init\n// ---------------------------------------------------------------------------\n\nasync function runInit(\n\topts: CommonOptions & { tool: string; apply?: boolean },\n\tformat: OutputFormat,\n): Promise<void> {\n\tif (opts.tool !== \"claude-code\") {\n\t\tthrow new CliFailure(\n\t\t\t`Unsupported tool \"${opts.tool}\". Only --tool claude-code is supported today; other tools follow.`,\n\t\t\t2,\n\t\t);\n\t}\n\n\tconst root = await resolveDestinationRoot(destinationOf(opts));\n\n\t// Two local preconditions, both answered before any network call: a lock\n\t// that belongs to another project, and a credential file that would end\n\t// up inside the checkout. Neither needs the server to decide, and making\n\t// a reader wait on a request to learn about them is backwards.\n\tawait readLockForProject(root, opts.project);\n\ttry {\n\t\tawait assertKeyStaysOutside(root, getConfigPath());\n\t} catch (error) {\n\t\tthrow new CliFailure(describeError(error), 7);\n\t}\n\n\tconst client = instructionsClient(opts, SYNC_TIMEOUT_MS);\n\tconst published = await fetchPublished(client, opts);\n\n\tif (published.sourceOfTruth === \"REPOSITORY\") {\n\t\t// A sync hook on a repository-backed project would fight `git pull`:\n\t\t// the files arrive through the repository, and two writers with no\n\t\t// merge between them is worse than one.\n\t\tthrow new CliFailure(\n\t\t\t\"This project's coding instructions come from its repository, so they arrive with `git pull`. A session hook would fight it; nothing was written.\",\n\t\t\t7,\n\t\t);\n\t}\n\n\tconst command = buildHookCommand(\n\t\topts.project,\n\t\tBoolean(opts.apply),\n\t\topts.org,\n\t);\n\tconst merged = await mergeSessionStartHook({\n\t\troot,\n\t\tprojectId: opts.project,\n\t\tcommand,\n\t});\n\n\tconst outcome = published.published\n\t\t? // A second manifest call, deliberately: the one above answered \"may\n\t\t\t// a hook be installed for this project at all\", and this one is the\n\t\t\t// sync's own — it carries the lock's digest and is the call the\n\t\t\t// hook will make from now on.\n\t\t\tawait syncOnce({ ...opts, hook: false })\n\t\t: null;\n\n\tif (format === \"json\") {\n\t\tprintOutput(\n\t\t\t{\n\t\t\t\tprojectId: opts.project,\n\t\t\t\tdestination: root,\n\t\t\t\tsettingsPath: merged.settingsPath,\n\t\t\t\thookCommand: merged.command,\n\t\t\t\tcreatedSettingsFile: merged.createdFile,\n\t\t\t\treplacedHooks: merged.replacedCount,\n\t\t\t\tsync: outcome,\n\t\t\t},\n\t\t\t{ format: \"json\" },\n\t\t);\n\t\treturn;\n\t}\n\n\tline(\n\t\tmerged.replacedCount > 0\n\t\t\t? `Updated the SessionStart hook in ${merged.settingsPath}.`\n\t\t\t: `Added a SessionStart hook to ${merged.settingsPath}.`,\n\t);\n\tline(` ${command}`);\n\tline(\n\t\topts.apply\n\t\t\t? \" It applies changes at session start.\"\n\t\t\t: \" It only reports changes; add --apply to init to have it apply them.\",\n\t);\n\n\tif (outcome === null) {\n\t\tline(\n\t\t\t\"This project has nothing published yet, so there is nothing to copy — the hook will pick it up once there is.\",\n\t\t);\n\t} else {\n\t\tline(\"\");\n\t\treportSync(outcome, opts);\n\t}\n\n\tline(\"\");\n\tline(\n\t\t`${CLAUDE_SETTINGS_RELATIVE_PATH} and ${LOCK_DIRECTORY}/ are local to this machine. If this repository does not ignore them already, add them to your own ignore rules — this command does not edit .gitignore.`,\n\t);\n}\n","/**\n * Turning a plan into files, with two rules that decide the shape of\n * everything below.\n *\n * First: verify every byte before writing any byte. Each entry's sha256 is\n * checked against the manifest up front, so a corrupt or tampered archive\n * aborts with nothing written at all, rather than half a tree of good files\n * and one bad one. The caller then does not rewrite the lock, so the next run\n * plans from the last known-good state.\n *\n * Second: every write goes through `safe-write.ts` — the same writer the\n * lock and the Claude Code settings file use. Symlink refusal, canonical\n * containment, exclusive temp creation and the pre-rename recheck all live\n * there, so there is exactly one implementation of \"may this land here\".\n */\nimport { createHash } from \"node:crypto\";\nimport { chmod } from \"node:fs/promises\";\nimport { describeRejection } from \"./paths.js\";\nimport type { PlanEntry, SyncPlan } from \"./plan.js\";\nimport {\n\tassertWritableTarget,\n\tdeleteFileSafely,\n\tisAllowedMode,\n\tpermissionBits,\n\twriteFileSafely,\n} from \"./safe-write.js\";\n\nexport interface ApplyResult {\n\twritten: string[];\n\tdeleted: string[];\n\t/** Paths whose mode was corrected without rewriting their bytes. */\n\tremoded: string[];\n\t/**\n\t * Paths the plan meant to delete that no longer matched the hash it\n\t * decided on — someone edited them between planning and now, so they were\n\t * left where they are.\n\t */\n\tkeptModified: string[];\n}\n\nexport interface ApplyInput {\n\t/** An already-canonical destination from `resolveDestinationRoot`. */\n\troot: string;\n\tplan: SyncPlan;\n\t/** Extracted archive entries, keyed by the manifest path. */\n\tcontents: Map<string, Uint8Array>;\n}\n\nexport async function applyPlan(input: ApplyInput): Promise<ApplyResult> {\n\tconst { root, plan, contents } = input;\n\n\t// ---- Phase 1: prove the whole plan before touching the tree ----------\n\t//\n\t// EVERY path the plan names, including the ones it does not intend to\n\t// write. A `verified` entry is one whose local bytes already match, and a\n\t// symlink pointing at those bytes used to reach exactly that verdict: no\n\t// write, no check, and a lock written over a path that is not a file.\n\t// This runs before the platform and mode short-circuits further down for\n\t// the same reason — a check that only some plans reach is not a check.\n\tfor (const entry of [\n\t\t...plan.writes,\n\t\t...plan.verified,\n\t\t...plan.deletes,\n\t\t...plan.keptRenamed,\n\t]) {\n\t\tconst check = await assertWritableTarget(root, entry.path);\n\t\tif (!check.ok) {\n\t\t\tthrow new Error(\n\t\t\t\t`Refusing to sync: ${describeRejection(check)}. Nothing was written.`,\n\t\t\t);\n\t\t}\n\t}\n\n\tfor (const entry of plan.writes) {\n\t\tif (!isAllowedMode(entry.mode)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Refusing to sync: ${entry.path} asks for file mode ${(entry.mode ?? 0).toString(8)}, and only 644 and 755 are accepted. Nothing was written.`,\n\t\t\t);\n\t\t}\n\t\tconst bytes = contents.get(entry.path);\n\t\tif (!bytes) {\n\t\t\tthrow new Error(\n\t\t\t\t`The downloaded bundle is missing ${entry.path}. Nothing was written.`,\n\t\t\t);\n\t\t}\n\t\tconst actual = createHash(\"sha256\").update(bytes).digest(\"hex\");\n\t\tif (actual !== entry.sha256) {\n\t\t\tthrow new Error(\n\t\t\t\t`Checksum mismatch for ${entry.path}: the published snapshot expects ${entry.sha256} and the downloaded bundle contains ${actual}. Nothing was written.`,\n\t\t\t);\n\t\t}\n\t}\n\n\t// ---- Phase 2: apply --------------------------------------------------\n\tconst written: string[] = [];\n\tconst deleted: string[] = [];\n\tconst remoded: string[] = [];\n\tconst keptModified: string[] = [];\n\n\tfor (const entry of plan.writes) {\n\t\t// Non-null: phase 1 refused the whole plan if any byte was missing.\n\t\tconst bytes = contents.get(entry.path) as Uint8Array;\n\t\tawait writeFileSafely({\n\t\t\troot,\n\t\t\trelativePath: entry.path,\n\t\t\tbytes,\n\t\t\tmode: entry.mode ?? null,\n\t\t});\n\t\twritten.push(entry.path);\n\t}\n\n\t// A file whose bytes already match still has to carry the published\n\t// mode: a script that arrives non-executable is as broken as one that\n\t// arrives with the wrong contents, and `verified` would otherwise never\n\t// fix it.\n\tfor (const entry of plan.verified) {\n\t\tif (await applyMode(root, entry)) {\n\t\t\tremoded.push(entry.path);\n\t\t}\n\t}\n\n\tfor (const entry of plan.deletes) {\n\t\t// The hash the plan decided on travels with the unlink. Planning ran\n\t\t// before the download, the extraction and every write above, and an\n\t\t// editor saving in that window would otherwise have its work deleted\n\t\t// on the strength of a hash that no longer describes the file.\n\t\tif (entry.sha256 === undefined) {\n\t\t\tthrow new Error(\n\t\t\t\t`Refusing to delete ${entry.path}: the plan carries no hash for it.`,\n\t\t\t);\n\t\t}\n\t\tconst outcome = await deleteFileSafely(root, entry.path, entry.sha256);\n\t\tif (outcome === \"deleted\") {\n\t\t\tdeleted.push(entry.path);\n\t\t} else if (outcome === \"modified\") {\n\t\t\tkeptModified.push(entry.path);\n\t\t}\n\t}\n\t// Directories are deliberately left behind. An empty directory is\n\t// harmless; removing one races with anything the developer put in it.\n\n\treturn { written, deleted, remoded, keptModified };\n}\n\n/** Returns true when a mode was actually applied. */\nasync function applyMode(root: string, entry: PlanEntry): Promise<boolean> {\n\tconst bits = permissionBits(entry.mode);\n\tif (bits === null || process.platform === \"win32\") {\n\t\treturn false;\n\t}\n\tif (!isAllowedMode(entry.mode)) {\n\t\tthrow new Error(\n\t\t\t`Refusing to sync: ${entry.path} asks for file mode ${(entry.mode ?? 0).toString(8)}, and only 644 and 755 are accepted.`,\n\t\t);\n\t}\n\t// The same guard the writes use: a `chmod` is a mutation too, and phase 1\n\t// proving this path was a regular file does not make it one now.\n\tconst check = await assertWritableTarget(root, entry.path);\n\tif (!check.ok) {\n\t\tthrow new Error(`Refusing to sync: ${describeRejection(check)}.`);\n\t}\n\ttry {\n\t\tawait chmod(check.path, bits);\n\t\treturn true;\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n\t\t\treturn false;\n\t\t}\n\t\tthrow error;\n\t}\n}\n","/**\n * Path safety for the file-writing half of this CLI.\n *\n * The paths this module guards arrive from a server response and from a zip\n * archive, and they are about to become filesystem writes on a developer's\n * machine. That makes the check local: the server validates paths on upload,\n * but a client that trusts a remote path list has moved the decision to the\n * wrong side of the wire. Nothing here asks the network anything.\n *\n * Three layers, and they answer different questions:\n *\n * `checkRelativePath` is this STRING safe to turn into a write?\n * `isReservedPath` is this path one this feature refuses to own?\n * `collisionKey` do two safe strings name the same file anyway?\n *\n * The filesystem half — symlinks, canonical containment, atomic writes —\n * lives in `safe-write.ts`, because it needs a resolved destination root and\n * these functions deliberately do not.\n */\n\ntype PathRejectReason =\n\t| \"empty\"\n\t| \"absolute\"\n\t| \"traversal\"\n\t| \"backslash\"\n\t| \"control_char\"\n\t| \"trailing_separator\"\n\t| \"trailing_dot_or_space\"\n\t| \"reserved_device_name\"\n\t| \"alternate_data_stream\"\n\t| \"reserved_path\"\n\t| \"not_a_regular_file\"\n\t| \"escapes_destination\"\n\t| \"symlink\"\n\t| \"not_a_directory\"\n\t| \"collision\";\n\nexport interface PathRejection {\n\tok: false;\n\treason: PathRejectReason;\n\t/** The offending path, as given, or the link that was in the way. */\n\tdetail: string;\n}\n\nexport type PathCheck = { ok: true; path: string } | PathRejection;\n\nconst DRIVE_LETTER = /^[A-Za-z]:/;\n\n/**\n * Names Windows resolves to a device rather than a file, with or without an\n * extension: `NUL`, `nul.txt` and `CON.md` all reach the device. Writing the\n * tree on Windows would silently discard those files; worse, a manifest could\n * use one to make a write look like it happened.\n */\nconst RESERVED_DEVICE_NAME = /^(?:CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])(?:\\.|$)/i;\n\n/**\n * Paths this feature refuses to write or delete, whatever a manifest or a\n * lock says.\n *\n * `.git` is the obvious one: a lock is a plain JSON file inside the checkout,\n * so anything that can edit it could otherwise name `.git/config` — a file\n * whose current hash is easy to know — and have the next sync unlink it.\n * `.fabric` is here because the lock lives there and must never be able to\n * authorise its own deletion or replacement through the manifest path.\n */\nconst RESERVED_ROOTS = [\".git\", \".fabric\"] as const;\n\n/**\n * Single files this feature refuses to own, as opposed to whole roots.\n *\n * `.claude/settings.local.json` is the file `init` itself writes. Instruction\n * files legitimately live elsewhere under `.claude/` — skills, commands — so\n * reserving the whole root would refuse the feature's own content; reserving\n * this one path stops a published manifest from overwriting the session hook\n * that was just installed, and stops the resulting lock from later\n * authorising its deletion.\n */\nconst RESERVED_EXACT_PATHS = [\".claude/settings.local.json\"] as const;\n\n/**\n * NUL and friends, found by character code rather than by a regular\n * expression.\n *\n * A character class cannot say this here. Written as unicode escapes, the\n * formatter rewrites each escape into the character it names, which puts\n * a literal NUL byte in this source file and makes git treat it as binary.\n * A loop says the same thing and stays readable in a diff.\n */\nfunction hasControlCharacter(input: string): boolean {\n\tfor (let index = 0; index < input.length; index++) {\n\t\tconst code = input.charCodeAt(index);\n\t\tif (code <= 0x1f || code === 0x7f) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Is this manifest/archive path safe to turn into a write inside a\n * destination? String-level only — see `safe-write.ts` for the filesystem\n * half.\n */\nexport function checkRelativePath(input: string): PathCheck {\n\tif (input.length === 0) {\n\t\treturn { ok: false, reason: \"empty\", detail: input };\n\t}\n\tif (hasControlCharacter(input)) {\n\t\treturn { ok: false, reason: \"control_char\", detail: input };\n\t}\n\tif (input.includes(\"\\\\\")) {\n\t\treturn { ok: false, reason: \"backslash\", detail: input };\n\t}\n\tif (input.startsWith(\"/\") || DRIVE_LETTER.test(input)) {\n\t\treturn { ok: false, reason: \"absolute\", detail: input };\n\t}\n\tif (input.endsWith(\"/\")) {\n\t\treturn { ok: false, reason: \"trailing_separator\", detail: input };\n\t}\n\tconst segments = input.split(\"/\");\n\tif (segments.some((s) => s.length === 0)) {\n\t\t// An empty segment means `a//b` or a leading slash already refused\n\t\t// above; either way the string is not the path it appears to be.\n\t\treturn { ok: false, reason: \"empty\", detail: input };\n\t}\n\tif (segments.some((s) => s === \".\" || s === \"..\")) {\n\t\treturn { ok: false, reason: \"traversal\", detail: input };\n\t}\n\tfor (const segment of segments) {\n\t\t// Windows strips a trailing dot or space from a name, so `a.md.` and\n\t\t// `a.md ` both open `a.md`. Two manifest entries that differ only\n\t\t// there would be two writes to one file, with the lock claiming both.\n\t\tif (/[. ]$/.test(segment)) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\treason: \"trailing_dot_or_space\",\n\t\t\t\tdetail: input,\n\t\t\t};\n\t\t}\n\t\tif (RESERVED_DEVICE_NAME.test(segment)) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\treason: \"reserved_device_name\",\n\t\t\t\tdetail: input,\n\t\t\t};\n\t\t}\n\t\t// `a.md:stream` addresses an NTFS alternate data stream on `a.md`,\n\t\t// which is a write to a file the manifest never named.\n\t\tif (segment.includes(\":\")) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\treason: \"alternate_data_stream\",\n\t\t\t\tdetail: input,\n\t\t\t};\n\t\t}\n\t}\n\treturn { ok: true, path: input };\n}\n\n/**\n * Is this a path this feature refuses to own, whoever asked?\n *\n * Applied to manifest entries AND to lock entries, on writes AND on deletes:\n * the lock is the thing being defended against here, so checking only what\n * the server sent would miss the case entirely.\n */\nexport function isReservedPath(input: string): boolean {\n\tconst first = input.split(\"/\")[0]?.toLowerCase();\n\tif (RESERVED_ROOTS.some((root) => first === root)) {\n\t\treturn true;\n\t}\n\t// Compared by collision key, not by string: on a case-insensitive\n\t// filesystem `.claude/Settings.Local.json` is the same file, and a\n\t// manifest that spells it differently must not slip past.\n\tconst key = collisionKey(input);\n\treturn RESERVED_EXACT_PATHS.some(\n\t\t(reserved) => collisionKey(reserved) === key,\n\t);\n}\n\n/**\n * A key two paths share when the filesystem would treat them as one file.\n *\n * macOS stores names in a normalised form and compares case-insensitively,\n * so `café.md` written as NFC and as NFD are one file with two spellings,\n * and `README.md`/`readme.md` are one file. The server's own collision check\n * catches ordinary case variants; it does not catch Unicode normalisation.\n *\n * Deliberately conservative and platform-independent: a manifest that would\n * collide on macOS is refused on Linux too, because the alternative is a\n * tree that syncs cleanly for one developer and silently loses a file for\n * the next.\n */\nexport function collisionKey(input: string): string {\n\treturn input.normalize(\"NFC\").toLowerCase();\n}\n\n/**\n * The first pair of manifest/lock paths that name the same file, or null.\n */\nexport function findCollision(\n\tpaths: readonly string[],\n): { first: string; second: string } | null {\n\tconst seen = new Map<string, string>();\n\tfor (const candidate of paths) {\n\t\tconst key = collisionKey(candidate);\n\t\tconst previous = seen.get(key);\n\t\tif (previous !== undefined) {\n\t\t\treturn { first: previous, second: candidate };\n\t\t}\n\t\tseen.set(key, candidate);\n\t}\n\treturn null;\n}\n\n/** A one-line reason a reader can act on. */\nexport function describeRejection(rejection: PathRejection): string {\n\tswitch (rejection.reason) {\n\t\tcase \"empty\":\n\t\t\treturn `empty or malformed path (${JSON.stringify(rejection.detail)})`;\n\t\tcase \"absolute\":\n\t\t\treturn `absolute path refused: ${rejection.detail}`;\n\t\tcase \"traversal\":\n\t\t\treturn `path traversal refused: ${rejection.detail}`;\n\t\tcase \"backslash\":\n\t\t\treturn `backslash in path refused: ${rejection.detail}`;\n\t\tcase \"control_char\":\n\t\t\treturn `control character in path refused: ${JSON.stringify(rejection.detail)}`;\n\t\tcase \"trailing_separator\":\n\t\t\treturn `path names a directory, not a file: ${rejection.detail}`;\n\t\tcase \"trailing_dot_or_space\":\n\t\t\treturn `path segment ending in a dot or space refused: ${rejection.detail}`;\n\t\tcase \"reserved_device_name\":\n\t\t\treturn `reserved device name refused: ${rejection.detail}`;\n\t\tcase \"alternate_data_stream\":\n\t\t\treturn `colon in path refused: ${rejection.detail}`;\n\t\tcase \"reserved_path\":\n\t\t\treturn `this tool never writes or deletes ${RESERVED_ROOTS.join(\", \")} or ${RESERVED_EXACT_PATHS.join(\", \")}: ${rejection.detail}`;\n\t\tcase \"not_a_regular_file\":\n\t\t\treturn `path is not a regular file: ${rejection.detail}`;\n\t\tcase \"escapes_destination\":\n\t\t\treturn `path resolves outside the destination: ${rejection.detail}`;\n\t\tcase \"symlink\":\n\t\t\t// \"follow\", not \"write through\": the same guard now runs for reads\n\t\t\t// — the ledger check and the planner both go through it — and a\n\t\t\t// read-only `check --verify` should not talk about writing.\n\t\t\treturn `refusing to follow a symlink: ${rejection.detail}`;\n\t\tcase \"not_a_directory\":\n\t\t\treturn `a path component is not a directory: ${rejection.detail}`;\n\t\tcase \"collision\":\n\t\t\treturn `two paths name the same file on a case- or Unicode-insensitive filesystem: ${rejection.detail}`;\n\t}\n}\n","/**\n * The one writer every file this feature creates goes through — instruction\n * files, the lock, and the Claude Code settings file alike.\n *\n * It exists because there were three writers before and only one of them was\n * guarded. `.claude -> ..` or `.fabric -> ..` in a checkout turned `init` and\n * `sync` into writes outside the destination, because the hook and the lock\n * never asked the question the instruction files did. A guard that only some\n * writes call is not a guard.\n *\n * What every write proves first:\n *\n * 1. The destination is canonicalised once with `realpath`. Lexical\n * resolution is not enough — `/tmp` is a symlink on macOS, so the\n * literal string a user passes and the directory they mean are\n * routinely different, and containment has to be decided on the real\n * one. The destination itself is resolved rather than refused for that\n * reason; everything BELOW it is held to the stricter rule.\n * 2. No segment between the root and the file is a symlink. Checked with\n * `lstat`, from the first child down to and including the target.\n * 3. The deepest existing ancestor's `realpath` is still inside the root.\n * Layer 2 answers \"is this a link\"; this answers \"did anything else —\n * a bind mount, a replaced directory — move it\".\n * 4. The temp file is created with `wx` and an unpredictable name, so a\n * pre-planted file is an error rather than a file we write through.\n * 5. The parent is re-checked immediately before `rename`, closing the\n * window between the walk and the write.\n *\n * Bytes are preserved exactly: no newline conversion, no re-encoding. The\n * server hashes these files and so does the next sync.\n */\nimport { createHash, randomBytes } from \"node:crypto\";\nimport type { Stats } from \"node:fs\";\nimport type { FileHandle } from \"node:fs/promises\";\nimport {\n\tlstat,\n\tmkdir,\n\topen,\n\treadFile,\n\trealpath,\n\trename,\n\tunlink,\n} from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { describeRejection, type PathCheck } from \"./paths.js\";\n\n/**\n * The modes a published file may carry.\n *\n * The server derives exactly these two from an upload, so anything else is a\n * malformed or hostile manifest rather than a file that needs it. An\n * allow-list rather than a mask, because masking with `0o7777` preserves\n * setuid, setgid, sticky and every write bit — a manifest asking for `04777`\n * would have been honoured.\n */\nconst ALLOWED_MODES = new Set([0o644, 0o755]);\n\nexport function isAllowedMode(mode: number | null | undefined): boolean {\n\tif (mode === null || mode === undefined) {\n\t\treturn true;\n\t}\n\tif (!Number.isInteger(mode) || mode < 0) {\n\t\treturn false;\n\t}\n\t// A manifest records the full `st_mode` (`0o100644`), so compare on the\n\t// permission bits and require the file-type bits to be a regular file or\n\t// absent.\n\tconst type = mode & 0o170000;\n\tif (type !== 0 && type !== 0o100000) {\n\t\treturn false;\n\t}\n\treturn ALLOWED_MODES.has(mode & 0o7777);\n}\n\n/** The permission bits to apply, or null when none were published. */\nexport function permissionBits(mode: number | null | undefined): number | null {\n\tif (mode === null || mode === undefined) {\n\t\treturn null;\n\t}\n\treturn mode & 0o7777;\n}\n\n/**\n * Canonicalise the destination once, for every subsequent check to resolve\n * against. Created if missing: `--dest` naming a directory that does not\n * exist yet is an ordinary first sync.\n */\nexport async function resolveDestinationRoot(\n\tdestination: string,\n): Promise<string> {\n\tawait mkdir(destination, { recursive: true });\n\treturn realpath(destination);\n}\n\n/**\n * Where a relative path lands under an already-canonical root, or why it may\n * not land at all. `relativePath` must already have passed\n * `checkRelativePath`.\n */\nexport async function assertSafeTarget(\n\troot: string,\n\trelativePath: string,\n): Promise<PathCheck> {\n\tconst target = path.resolve(root, relativePath);\n\tif (target === root || !target.startsWith(root + path.sep)) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\treason: \"escapes_destination\",\n\t\t\tdetail: relativePath,\n\t\t};\n\t}\n\n\tconst segments = relativePath.split(\"/\");\n\tlet current = root;\n\tlet deepestExisting = root;\n\tfor (const [index, segment] of segments.entries()) {\n\t\tcurrent = path.join(current, segment);\n\t\tconst stats = await lstatOrNull(current);\n\t\tif (stats === null) {\n\t\t\t// Everything below here is about to be created, and a path that\n\t\t\t// does not exist cannot be a link to somewhere else.\n\t\t\tbreak;\n\t\t}\n\t\tif (stats.isSymbolicLink()) {\n\t\t\treturn { ok: false, reason: \"symlink\", detail: current };\n\t\t}\n\t\t// An ANCESTOR that is not a directory. `lstat` on anything below it\n\t\t// answers ENOTDIR, which used to read as \"absent\" — so a regular file\n\t\t// at `z` let `z/child.md` pass the whole-plan preflight and fail in\n\t\t// `makeParents` after earlier entries had already been written.\n\t\tif (index < segments.length - 1 && !stats.isDirectory()) {\n\t\t\treturn { ok: false, reason: \"not_a_directory\", detail: current };\n\t\t}\n\t\tdeepestExisting = current;\n\t}\n\n\t// Layer 3. `lstat` said no component IS a link; this says the components\n\t// still resolve where they appeared to.\n\tif (deepestExisting !== root) {\n\t\tconst canonical = await realpath(deepestExisting).catch(() => null);\n\t\tif (\n\t\t\tcanonical !== null &&\n\t\t\tcanonical !== root &&\n\t\t\t!canonical.startsWith(root + path.sep)\n\t\t) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\treason: \"escapes_destination\",\n\t\t\t\tdetail: relativePath,\n\t\t\t};\n\t\t}\n\t}\n\n\treturn { ok: true, path: target };\n}\n\n/**\n * `assertSafeTarget`, plus: whatever is already at the final path must be an\n * ordinary file.\n *\n * `assertSafeTarget` answers \"may this land here\" — no symlinked component,\n * nothing resolving outside the root. It does not answer \"is the thing\n * already there a file\". A directory at a manifest path passed it, and the\n * eventual `rename` refused, but only after earlier entries in the same plan\n * had already been written. A fifo, socket or device node would be opened and\n * written through. Both are now refusals, and the caller runs this over EVERY\n * manifest and delete path before it mutates anything.\n */\nexport async function assertWritableTarget(\n\troot: string,\n\trelativePath: string,\n): Promise<PathCheck> {\n\tconst check = await assertSafeTarget(root, relativePath);\n\tif (!check.ok) {\n\t\treturn check;\n\t}\n\tconst stats = await lstatOrNull(check.path);\n\tif (stats === null) {\n\t\treturn check;\n\t}\n\tif (stats.isSymbolicLink()) {\n\t\treturn { ok: false, reason: \"symlink\", detail: check.path };\n\t}\n\tif (!stats.isFile()) {\n\t\treturn { ok: false, reason: \"not_a_regular_file\", detail: check.path };\n\t}\n\treturn check;\n}\n\n/**\n * Read a file under an already-canonical root, through the same guard every\n * write goes through, or `null` when it is not there.\n *\n * READS need the walk as much as writes do. The ledger check and the planner\n * used to `path.join` and `lstat` directly, which meant a lock path of\n * `../outside` read outside the destination, and an ancestor replaced by a\n * symlink was followed to wherever it pointed — hashing, and possibly loading\n * into memory, a file this tool has no business opening. A refusal is the\n * answer in both cases, not a hash.\n */\nexport async function readFileSafely(\n\troot: string,\n\trelativePath: string,\n): Promise<{ bytes: Uint8Array; mode: number } | null> {\n\tconst check = await assertWritableTarget(root, relativePath);\n\tif (!check.ok) {\n\t\tthrow new Error(`Refusing to sync: ${describeRejection(check)}.`);\n\t}\n\tconst stats = await lstatOrNull(check.path);\n\tif (stats === null) {\n\t\treturn null;\n\t}\n\ttry {\n\t\treturn { bytes: await readFile(check.path), mode: stats.mode };\n\t} catch (error) {\n\t\t// Removed between the `lstat` and the `open`: absent is the honest\n\t\t// answer, and the caller plans to write it.\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n\t\t\treturn null;\n\t\t}\n\t\tthrow error;\n\t}\n}\n\n/**\n * The canonical form of a destination that must NOT be created.\n *\n * `resolveDestinationRoot` makes the directory, which is right for a sync and\n * wrong for `check`, an informational command. A destination that does not\n * exist has no lock either, so the literal resolved path is a fine answer.\n */\nexport async function resolveExistingRoot(\n\tdestination: string,\n): Promise<string> {\n\treturn realpath(destination).catch(() => path.resolve(destination));\n}\n\n/**\n * Create every missing parent directory of `relativePath`, one segment at a\n * time, refusing a symlink at each step.\n *\n * `mkdir(..., { recursive: true })` cannot be used for this: it follows an\n * existing symlinked component silently, which is the whole thing being\n * defended against.\n */\nasync function makeParents(root: string, relativePath: string): Promise<void> {\n\tconst segments = relativePath.split(\"/\").slice(0, -1);\n\tlet current = root;\n\tfor (const segment of segments) {\n\t\tcurrent = path.join(current, segment);\n\t\tconst stats = await lstatOrNull(current);\n\t\tif (stats === null) {\n\t\t\tawait mkdir(current).catch(async (error: NodeJS.ErrnoException) => {\n\t\t\t\t// A concurrent writer got there first. Re-check what landed\n\t\t\t\t// rather than assuming it is a directory.\n\t\t\t\tif (error.code !== \"EEXIST\") {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\tconst raced = await lstatOrNull(current);\n\t\t\t\tif (raced?.isSymbolicLink()) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Refusing to sync: ${describeRejection({ ok: false, reason: \"symlink\", detail: current })}.`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tif (stats.isSymbolicLink()) {\n\t\t\tthrow new Error(\n\t\t\t\t`Refusing to sync: ${describeRejection({ ok: false, reason: \"symlink\", detail: current })}.`,\n\t\t\t);\n\t\t}\n\t\tif (!stats.isDirectory()) {\n\t\t\tthrow new Error(\n\t\t\t\t`Refusing to sync: ${describeRejection({ ok: false, reason: \"not_a_directory\", detail: current })}.`,\n\t\t\t);\n\t\t}\n\t}\n}\n\n/**\n * Write one file atomically under an already-canonical root.\n *\n * `relativePath` must have passed `checkRelativePath` and any policy check\n * the caller owns (reserved paths, collisions) BEFORE this is called — this\n * function enforces the filesystem invariants, not the feature's rules.\n */\nexport async function writeFileSafely(input: {\n\troot: string;\n\trelativePath: string;\n\tbytes: Uint8Array;\n\tmode?: number | null;\n}): Promise<void> {\n\tconst check = await assertSafeTarget(input.root, input.relativePath);\n\tif (!check.ok) {\n\t\tthrow new Error(`Refusing to sync: ${describeRejection(check)}.`);\n\t}\n\tif (!isAllowedMode(input.mode)) {\n\t\tthrow new Error(\n\t\t\t`Refusing to sync: ${input.relativePath} asks for file mode ${(input.mode ?? 0).toString(8)}, and only 644 and 755 are accepted.`,\n\t\t);\n\t}\n\n\tawait makeParents(input.root, input.relativePath);\n\n\tconst target = check.path;\n\tconst directory = path.dirname(target);\n\t// The identity of the directory we are about to create the temp file in.\n\t// Cleanup below unlinks BY PATH, and a path no longer names the same\n\t// directory once something has swapped it; unlinking then would delete a\n\t// stranger's file and leave the real temp behind. Node has no\n\t// handle-relative unlink, so the next best thing is to refuse to clean up\n\t// through a path that has moved.\n\tconst directoryBefore = await lstatOrNull(directory);\n\t// Unpredictable, so a pre-planted temp file cannot be waiting for us, and\n\t// `wx` so creating one that already exists is an error rather than a\n\t// write through whatever is there.\n\tconst temporary = path.join(\n\t\tdirectory,\n\t\t`.${path.basename(target)}.${randomBytes(8).toString(\"hex\")}.tmp`,\n\t);\n\n\tlet handle: FileHandle | null = null;\n\ttry {\n\t\thandle = await open(temporary, \"wx\", 0o600);\n\t\tawait handle.writeFile(input.bytes);\n\t\tconst bits = permissionBits(input.mode);\n\t\tif (bits !== null && process.platform !== \"win32\") {\n\t\t\tawait handle.chmod(bits);\n\t\t}\n\t\tawait handle.close();\n\t\thandle = null;\n\n\t\t// The walk above happened before the file was written. Re-check the\n\t\t// parent now, so a directory swapped for a link in between cannot\n\t\t// receive the rename.\n\t\tconst parentStats = await lstatOrNull(directory);\n\t\tif (parentStats === null || parentStats.isSymbolicLink()) {\n\t\t\tthrow new Error(\n\t\t\t\t`Refusing to sync: ${describeRejection({ ok: false, reason: \"symlink\", detail: directory })}.`,\n\t\t\t);\n\t\t}\n\t\tconst targetStats = await lstatOrNull(target);\n\t\tif (targetStats?.isSymbolicLink()) {\n\t\t\tthrow new Error(\n\t\t\t\t`Refusing to sync: ${describeRejection({ ok: false, reason: \"symlink\", detail: target })}.`,\n\t\t\t);\n\t\t}\n\n\t\tawait rename(temporary, target);\n\t} catch (error) {\n\t\tawait handle?.close().catch(() => {});\n\t\tif (await isSameDirectory(directory, directoryBefore)) {\n\t\t\tawait unlink(temporary).catch(() => {});\n\t\t}\n\t\tthrow error;\n\t}\n}\n\n/** Does this path still name the directory we checked earlier? */\nasync function isSameDirectory(\n\tdirectory: string,\n\tbefore: Stats | null,\n): Promise<boolean> {\n\tif (before === null) {\n\t\treturn false;\n\t}\n\tconst now = await lstatOrNull(directory);\n\treturn now !== null && now.dev === before.dev && now.ino === before.ino;\n}\n\nexport type DeleteOutcome = \"deleted\" | \"missing\" | \"modified\";\n\n/**\n * Remove one file under an already-canonical root — but only if it is still\n * the file the caller decided to remove.\n *\n * The plan hashes a departed file during planning, and a download, an\n * extraction and every write happen between then and here. An unconditional\n * `unlink` therefore deleted whatever was at that path by the time it ran,\n * including an edit the developer had saved in the meantime. The expected\n * hash travels with the request and is checked against the bytes on disk\n * immediately before the unlink; a file that no longer matches is left alone\n * and reported as kept.\n *\n * Residual, stated rather than hidden: a write landing between that hash and\n * the `unlink` is still lost. Node offers no way to unlink a specific inode,\n * so closing it entirely would need handle-relative syscalls the runtime does\n * not expose. Concurrent mutation of the destination by the same user during\n * a sync is out of scope for this tool.\n */\nexport async function deleteFileSafely(\n\troot: string,\n\trelativePath: string,\n\texpectedSha256: string,\n): Promise<DeleteOutcome> {\n\tconst check = await assertSafeTarget(root, relativePath);\n\tif (!check.ok) {\n\t\tthrow new Error(`Refusing to sync: ${describeRejection(check)}.`);\n\t}\n\n\tconst stats = await lstatOrNull(check.path);\n\tif (stats === null) {\n\t\treturn \"missing\";\n\t}\n\tif (stats.isSymbolicLink()) {\n\t\tthrow new Error(\n\t\t\t`Refusing to sync: ${describeRejection({ ok: false, reason: \"symlink\", detail: check.path })}.`,\n\t\t);\n\t}\n\tif (!stats.isFile()) {\n\t\tthrow new Error(\n\t\t\t`Refusing to sync: ${describeRejection({ ok: false, reason: \"not_a_regular_file\", detail: check.path })}.`,\n\t\t);\n\t}\n\n\tlet actual: string;\n\ttry {\n\t\tactual = createHash(\"sha256\")\n\t\t\t.update(await readFile(check.path))\n\t\t\t.digest(\"hex\");\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n\t\t\treturn \"missing\";\n\t\t}\n\t\tthrow error;\n\t}\n\tif (actual !== expectedSha256) {\n\t\treturn \"modified\";\n\t}\n\n\ttry {\n\t\tawait unlink(check.path);\n\t\treturn \"deleted\";\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n\t\t\treturn \"missing\";\n\t\t}\n\t\tthrow error;\n\t}\n}\n\n/**\n * `lstat`, with ONLY `ENOENT` meaning \"nothing there\".\n *\n * `ENOTDIR` used to be folded in here, and it does not mean the same thing at\n * all: it means an ancestor exists and is not a directory. Reading it as\n * \"absent\" is what let a regular file at `z` pass the preflight for\n * `z/child.md`. Callers that walk a path check the ancestors themselves; this\n * one lets the error through so nothing can mistake the two again.\n */\nasync function lstatOrNull(target: string) {\n\ttry {\n\t\treturn await lstat(target);\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n\t\t\treturn null;\n\t\t}\n\t\tthrow error;\n\t}\n}\n\n/**\n * Does `candidate` sit inside `root` once both are resolved as far as the\n * filesystem allows?\n *\n * Used for the credential check in `hook.ts`, where the question is about a\n * path that may not exist yet and whose ancestors may be links. Lexical\n * comparison answered it wrongly in both directions: a config file reached\n * through a symlink into the checkout looked outside it, and a destination\n * under a symlinked parent looked like a mismatch.\n */\nexport async function resolvesInside(\n\troot: string,\n\tcandidate: string,\n): Promise<boolean> {\n\tconst canonicalRoot = await realpath(root).catch(() => path.resolve(root));\n\tconst canonicalCandidate = await realpathDeepest(candidate);\n\treturn (\n\t\tcanonicalCandidate === canonicalRoot ||\n\t\tcanonicalCandidate.startsWith(canonicalRoot + path.sep)\n\t);\n}\n\n/**\n * `realpath` of the deepest existing ancestor, with the not-yet-existing tail\n * appended. `realpath` throws on a missing path, and a config file that has\n * not been written yet still has an answer worth having.\n */\nasync function realpathDeepest(candidate: string): Promise<string> {\n\tconst absolute = path.resolve(candidate);\n\tconst tail: string[] = [];\n\tlet current = absolute;\n\tfor (;;) {\n\t\tconst resolved = await realpath(current).catch(() => null);\n\t\tif (resolved !== null) {\n\t\t\treturn tail.length === 0 ? resolved : path.join(resolved, ...tail);\n\t\t}\n\t\tconst parent = path.dirname(current);\n\t\tif (parent === current) {\n\t\t\treturn absolute;\n\t\t}\n\t\ttail.unshift(path.basename(current));\n\t\tcurrent = parent;\n\t}\n}\n","/**\n * Fetching and unpacking the published bundle.\n *\n * The archive is held in memory and never written to disk as an archive. A\n * temp zip on disk would be one more thing to clean up after an interrupted\n * run — but \"in memory\" only works while the size is bounded by something the\n * CLIENT decided, which is what `maxBytes` is. The response body is read in\n * chunks and abandoned the moment it exceeds that; `arrayBuffer()` buffered\n * whatever the server sent before anything could look at it, so a malformed\n * or hostile response sized the allocation itself.\n *\n * Only the paths the plan asked for are extracted, and the manifest's own\n * sizes bound the decompression. The filter is the only place that runs\n * before `fflate` allocates, so per-entry and aggregate limits belong there\n * rather than after the fact: the sha256 check in `apply.ts` catches\n * substituted CONTENT, but it runs on bytes that have already been\n * decompressed into memory.\n */\nimport { unzipSync } from \"fflate\";\n\nexport interface FetchBundleOptions {\n\t/** Per-attempt budget when no shared signal is supplied. */\n\ttimeoutMs: number;\n\t/**\n\t * The most compressed bytes worth reading, from `maxArchiveBytes`. A\n\t * declared `Content-Length` above it is refused before the body is read;\n\t * a body that grows past it is abandoned mid-stream.\n\t */\n\tmaxBytes: number;\n\t/**\n\t * A deadline owned by the caller. In hook mode one signal covers the\n\t * manifest call and this download together, so the whole command has a\n\t * single absolute bound rather than one per request.\n\t */\n\tsignal?: AbortSignal;\n\t/** Injectable for tests; defaults to the global fetch. */\n\tfetchImpl?: typeof fetch;\n}\n\nexport async function fetchBundle(\n\turl: string,\n\toptions: FetchBundleOptions,\n): Promise<Uint8Array> {\n\tconst fetchImpl = options.fetchImpl ?? fetch;\n\tconst controller = new AbortController();\n\tconst timer = setTimeout(() => controller.abort(), options.timeoutMs);\n\tconst onExternalAbort = () => controller.abort();\n\toptions.signal?.addEventListener(\"abort\", onExternalAbort, { once: true });\n\tif (options.signal?.aborted) {\n\t\tcontroller.abort();\n\t}\n\ttry {\n\t\tconst response = await fetchImpl(url, { signal: controller.signal });\n\t\tif (!response.ok) {\n\t\t\tthrow new Error(\n\t\t\t\t`Downloading the coding-instructions bundle failed with HTTP ${response.status}.`,\n\t\t\t);\n\t\t}\n\n\t\tconst declared = Number(response.headers.get(\"content-length\"));\n\t\tif (Number.isFinite(declared) && declared > options.maxBytes) {\n\t\t\tthrow new Error(\n\t\t\t\t`The coding-instructions bundle declares ${declared} bytes and this snapshot's manifest allows at most ${options.maxBytes}. Nothing was written.`,\n\t\t\t);\n\t\t}\n\n\t\treturn await readBounded(response, options.maxBytes);\n\t} catch (error) {\n\t\tif (error instanceof Error && error.name === \"AbortError\") {\n\t\t\tthrow new Error(\n\t\t\t\t`Downloading the coding-instructions bundle timed out after ${options.timeoutMs}ms.`,\n\t\t\t);\n\t\t}\n\t\tthrow error;\n\t} finally {\n\t\tclearTimeout(timer);\n\t\toptions.signal?.removeEventListener(\"abort\", onExternalAbort);\n\t}\n}\n\n/**\n * Read a response body, refusing it the moment it passes `maxBytes`.\n *\n * The cap is compared against bytes ALREADY RECEIVED, so the refusal costs at\n * most one chunk beyond it rather than the whole body. A response with no\n * readable stream — an older polyfill, a test double built from a string —\n * falls back to `arrayBuffer()` and is length-checked after the fact, which\n * is the best available answer when the body cannot be consumed in pieces.\n */\nasync function readBounded(\n\tresponse: Response,\n\tmaxBytes: number,\n): Promise<Uint8Array> {\n\tconst body = response.body;\n\tif (!body) {\n\t\tconst bytes = new Uint8Array(await response.arrayBuffer());\n\t\tif (bytes.length > maxBytes) {\n\t\t\tthrow new Error(\n\t\t\t\t`The coding-instructions bundle is larger than the ${maxBytes} bytes this snapshot's manifest allows. Nothing was written.`,\n\t\t\t);\n\t\t}\n\t\treturn bytes;\n\t}\n\n\tconst reader = body.getReader();\n\tconst chunks: Uint8Array[] = [];\n\tlet total = 0;\n\ttry {\n\t\tfor (;;) {\n\t\t\tconst { done, value } = await reader.read();\n\t\t\tif (done) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (!value) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\ttotal += value.length;\n\t\t\tif (total > maxBytes) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`The coding-instructions bundle is larger than the ${maxBytes} bytes this snapshot's manifest allows. Nothing was written.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tchunks.push(value);\n\t\t}\n\t} finally {\n\t\tawait reader.cancel().catch(() => {});\n\t}\n\n\tconst archive = new Uint8Array(total);\n\tlet offset = 0;\n\tfor (const chunk of chunks) {\n\t\tarchive.set(chunk, offset);\n\t\toffset += chunk.length;\n\t}\n\treturn archive;\n}\n\nexport interface WantedEntry {\n\tpath: string;\n\t/** The manifest's size for this path, in bytes. */\n\tsize: number;\n}\n\n/**\n * Extract exactly the wanted paths, within exactly the wanted sizes.\n *\n * A zip entry name is matched literally against the manifest path. Nothing\n * here normalises, joins or resolves anything — a name that does not appear\n * in `wanted` is simply not returned, so an archive carrying `../../etc/x`\n * cannot reach the filesystem even before the path guard sees it.\n *\n * Three bounds, all enforced inside the filter so a hostile archive is\n * refused before it is decompressed:\n *\n * - a name the manifest does not list is skipped;\n * - an entry whose declared original size is not the manifest's size for\n * that path is refused (a zip bomb declaring 4 GB for a 200-byte file\n * never gets allocated);\n * - a second entry with a wanted name is refused rather than allowed to\n * win, which is what \"last one wins\" would otherwise let it do.\n */\nexport function extractBundle(\n\tarchive: Uint8Array,\n\twanted: Iterable<WantedEntry>,\n): Map<string, Uint8Array> {\n\tconst sizes = new Map<string, number>();\n\tfor (const entry of wanted) {\n\t\tsizes.set(entry.path, entry.size);\n\t}\n\tif (sizes.size === 0) {\n\t\treturn new Map();\n\t}\n\n\tconst seen = new Set<string>();\n\tconst unzipped = unzipSync(archive, {\n\t\tfilter: (file) => {\n\t\t\tconst expected = sizes.get(file.name);\n\t\t\tif (expected === undefined) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (seen.has(file.name)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`The downloaded bundle contains ${file.name} more than once. Nothing was written.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tseen.add(file.name);\n\t\t\tif (\n\t\t\t\tfile.originalSize !== undefined &&\n\t\t\t\tfile.originalSize !== expected\n\t\t\t) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`The downloaded bundle declares ${file.originalSize} bytes for ${file.name} and the manifest says ${expected}. Nothing was written.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\t});\n\n\tconst contents = new Map<string, Uint8Array>();\n\tfor (const [name, bytes] of Object.entries(unzipped)) {\n\t\tconst expected = sizes.get(name);\n\t\tif (expected === undefined) {\n\t\t\tcontinue;\n\t\t}\n\t\t// The declared size is a claim; this is the measurement.\n\t\tif (bytes.length !== expected) {\n\t\t\tthrow new Error(\n\t\t\t\t`The downloaded bundle holds ${bytes.length} bytes for ${name} and the manifest says ${expected}. Nothing was written.`,\n\t\t\t);\n\t\t}\n\t\tcontents.set(name, bytes);\n\t}\n\treturn contents;\n}\n","/**\n * The Claude Code SessionStart hook that keeps a checkout current.\n *\n * Written into `.claude/settings.local.json` and NEVER `settings.json`. The\n * local file is per-developer and normally untracked; the shared one is\n * committed, and a hook committed into a repository runs on everybody's\n * machine with whatever credentials they happen to have.\n *\n * The command never carries the key. It names a project and nothing else —\n * the CLI reads its credential from `FABRIC_API_KEY` or from the per-user\n * config file, both outside the repository. `assertKeyStaysOutside` is what\n * makes that a guarantee rather than a habit, and it compares REAL paths:\n * a config directory reached through a symlink into the checkout is inside\n * it however the string is spelled.\n *\n * `matcher` is deliberately omitted so the hook runs on startup, resume,\n * clear and compact alike: a session resumed after a pull is exactly when the\n * published version is most likely to have moved.\n */\nimport { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { resolvesInside, writeFileSafely } from \"./safe-write.js\";\n\nexport const CLAUDE_SETTINGS_RELATIVE_PATH = path.join(\n\t\".claude\",\n\t\"settings.local.json\",\n);\n\n/** The same path in the POSIX spelling the guarded writer expects. */\nconst CLAUDE_SETTINGS_POSIX_PATH = \".claude/settings.local.json\";\n\n/** Seconds. Long enough for a cold start plus one manifest call, short enough to be invisible. */\nconst HOOK_TIMEOUT_SECONDS = 15;\n\n/** The subcommands a hook this tool wrote may name. */\nconst HOOK_SUBCOMMANDS = new Set([\"check\", \"sync\"]);\n\ninterface CommandHook {\n\ttype: \"command\";\n\tcommand: string;\n\ttimeout?: number;\n\t[key: string]: unknown;\n}\n\ninterface HookGroup {\n\tmatcher?: string;\n\thooks: CommandHook[];\n\t[key: string]: unknown;\n}\n\nexport interface MergeHookResult {\n\tsettingsPath: string;\n\tcommand: string;\n\t/** True when the settings file did not exist before. */\n\tcreatedFile: boolean;\n\t/** How many existing Fabric hooks for this project were replaced or dropped. */\n\treplacedCount: number;\n}\n\n/**\n * The command the session hook runs.\n *\n * An explicit `--org` is carried through when `init` was given one. These\n * commands do not consult a stored default context, so a slug that was\n * supplied once on the command line has nowhere else to live — leaving it out\n * would install a hook that binds differently from the `init` that created\n * it. It still never carries the key.\n */\nexport function buildHookCommand(\n\tprojectId: string,\n\tapply: boolean,\n\torg?: string,\n): string {\n\tconst verb = apply ? \"sync\" : \"check\";\n\tconst context = org ? ` --org ${org}` : \"\";\n\treturn `fabric instructions ${verb} --project ${projectId}${context} --hook`;\n}\n\n/**\n * Would writing this hook put the API key inside the repository?\n *\n * The hook itself carries no key, so the only way one lands in the tree is\n * the CLI's own config file being stored there — which happens when\n * `XDG_CONFIG_HOME` or `APPDATA` points inside the checkout, including\n * through a symlink. Refuse rather than write a hook whose credential source\n * a `git add -A` would commit.\n */\nexport async function assertKeyStaysOutside(\n\tdestination: string,\n\tconfigPath: string,\n): Promise<void> {\n\tif (await resolvesInside(destination, configPath)) {\n\t\tthrow new Error(\n\t\t\t`The CLI stores its API key at ${configPath}, which resolves inside ${destination}. Writing a session hook here would leave a live credential in the repository. Move the CLI config outside the project (set XDG_CONFIG_HOME) or export FABRIC_API_KEY instead, then run this again.`,\n\t\t);\n\t}\n}\n\n/**\n * Add — or replace — the Fabric SessionStart hook for one project.\n *\n * Idempotent by project id, and idempotent across a file that already has\n * duplicates: EVERY matching entry is removed and exactly one is written\n * back. Matching is on parsed argv tokens, not on a substring — `--project\n * abc` must not match `--project abc-extra`, and `--project=abc` is the same\n * request written differently. Every other key in the file, and every other\n * hook, is preserved exactly.\n */\nexport async function mergeSessionStartHook(input: {\n\t/** An already-canonical destination from `resolveDestinationRoot`. */\n\troot: string;\n\tprojectId: string;\n\tcommand: string;\n}): Promise<MergeHookResult> {\n\tconst settingsPath = path.join(input.root, CLAUDE_SETTINGS_RELATIVE_PATH);\n\n\tlet existingRaw: string | null = null;\n\ttry {\n\t\texistingRaw = await readFile(settingsPath, \"utf8\");\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tlet settings: Record<string, unknown> = {};\n\tif (existingRaw !== null && existingRaw.trim().length > 0) {\n\t\tlet parsed: unknown;\n\t\ttry {\n\t\t\tparsed = JSON.parse(existingRaw);\n\t\t} catch {\n\t\t\t// Refused, never rewritten: this file is the developer's own, and\n\t\t\t// a JSON error in it is nearly always a half-finished edit rather\n\t\t\t// than something to discard.\n\t\t\tthrow new Error(\n\t\t\t\t`${settingsPath} is not valid JSON. Fix or remove it, then run this again — it was left untouched.`,\n\t\t\t);\n\t\t}\n\t\tif (\n\t\t\ttypeof parsed !== \"object\" ||\n\t\t\tparsed === null ||\n\t\t\tArray.isArray(parsed)\n\t\t) {\n\t\t\tthrow new Error(\n\t\t\t\t`${settingsPath} does not contain a JSON object. It was left untouched.`,\n\t\t\t);\n\t\t}\n\t\tsettings = parsed as Record<string, unknown>;\n\t}\n\n\t// Every nested shape is checked before anything is rebuilt. Top-level JSON\n\t// was refused carefully and these were not: `{\"hooks\": [\"custom\"]}` or a\n\t// `SessionStart` that is not an array used to be replaced with a\n\t// freshly-built hooks object, discarding whatever the developer had. A\n\t// shape this tool does not understand is no more ours to normalise than a\n\t// half-finished edit is.\n\tif (settings.hooks !== undefined && !isRecord(settings.hooks)) {\n\t\tthrow refuseShape(settingsPath, '\"hooks\" is not an object');\n\t}\n\tconst hooks = isRecord(settings.hooks) ? { ...settings.hooks } : {};\n\tif (\n\t\thooks.SessionStart !== undefined &&\n\t\t!Array.isArray(hooks.SessionStart)\n\t) {\n\t\tthrow refuseShape(settingsPath, '\"hooks.SessionStart\" is not an array');\n\t}\n\tconst rawGroups = Array.isArray(hooks.SessionStart)\n\t\t? hooks.SessionStart\n\t\t: [];\n\tfor (const [index, group] of rawGroups.entries()) {\n\t\tif (!isRecord(group)) {\n\t\t\tthrow refuseShape(\n\t\t\t\tsettingsPath,\n\t\t\t\t`\"hooks.SessionStart[${index}]\" is not an object`,\n\t\t\t);\n\t\t}\n\t\tif (group.hooks !== undefined && !Array.isArray(group.hooks)) {\n\t\t\tthrow refuseShape(\n\t\t\t\tsettingsPath,\n\t\t\t\t`\"hooks.SessionStart[${index}].hooks\" is not an array`,\n\t\t\t);\n\t\t}\n\t}\n\tconst sessionStart: HookGroup[] = (rawGroups as HookGroup[]).map(\n\t\t(group) => ({\n\t\t\t...group,\n\t\t\thooks: Array.isArray(group?.hooks) ? [...group.hooks] : [],\n\t\t}),\n\t);\n\n\tconst replacement: CommandHook = {\n\t\ttype: \"command\",\n\t\tcommand: input.command,\n\t\ttimeout: HOOK_TIMEOUT_SECONDS,\n\t};\n\n\t// Remove EVERY entry for this project first, then add one back. Replacing\n\t// in place and stopping at the first match left duplicates behind, and a\n\t// file that has accumulated two of our hooks should come out with one.\n\tlet replacedCount = 0;\n\tconst pruned: HookGroup[] = [];\n\tfor (const group of sessionStart) {\n\t\tconst kept = group.hooks.filter(\n\t\t\t(hook) => !isFabricHookFor(hook, input.projectId),\n\t\t);\n\t\tconst removed = group.hooks.length - kept.length;\n\t\treplacedCount += removed;\n\t\t// A group we emptied held nothing but our own hook; leaving\n\t\t// `{hooks: []}` behind would accumulate one husk per run. A group\n\t\t// that was ALREADY empty is somebody else's and is kept untouched,\n\t\t// which is why this turns on `removed` rather than on length alone.\n\t\tif (kept.length === 0 && removed > 0) {\n\t\t\tcontinue;\n\t\t}\n\t\tpruned.push({ ...group, hooks: kept });\n\t}\n\n\tpruned.push({ hooks: [replacement] });\n\n\tconst next = {\n\t\t...settings,\n\t\thooks: { ...hooks, SessionStart: pruned },\n\t};\n\n\tawait writeFileSafely({\n\t\troot: input.root,\n\t\trelativePath: CLAUDE_SETTINGS_POSIX_PATH,\n\t\tbytes: new TextEncoder().encode(\n\t\t\t`${JSON.stringify(next, null, 2).replace(/\\r\\n/g, \"\\n\")}\\n`,\n\t\t),\n\t});\n\n\treturn {\n\t\tsettingsPath,\n\t\tcommand: input.command,\n\t\tcreatedFile: existingRaw === null,\n\t\treplacedCount,\n\t};\n}\n\n/**\n * Is this hook one this tool wrote for this project?\n *\n * Token-exact. The command is split on whitespace — every command this tool\n * generates is a plain, unquoted argv line, so a command that needs shell\n * quoting to parse is by definition not ours.\n */\nfunction isFabricHookFor(hook: unknown, projectId: string): boolean {\n\tif (!isRecord(hook) || typeof hook.command !== \"string\") {\n\t\treturn false;\n\t}\n\tconst tokens = hook.command.trim().split(/\\s+/);\n\tif (tokens[0] !== \"fabric\" || tokens[1] !== \"instructions\") {\n\t\treturn false;\n\t}\n\tif (tokens[2] === undefined || !HOOK_SUBCOMMANDS.has(tokens[2])) {\n\t\treturn false;\n\t}\n\treturn readProjectToken(tokens) === projectId;\n}\n\n/**\n * The `--project` value, from either `--project X` or `--project=X`, and only\n * when the command names exactly one.\n *\n * `fabric instructions check --project other --project target --hook` is a\n * command Commander resolves to `target`, while reading the first occurrence\n * answers `other`. Either reading makes this matcher wrong about somebody's\n * hook: merging for `other` would delete a hook that syncs `target`, and\n * merging for `target` would leave that entry behind and add a second. A\n * command this tool did not write is not this tool's to rewrite, so an\n * ambiguous one is left exactly as it is.\n */\nfunction readProjectToken(tokens: string[]): string | null {\n\tlet found: string | null = null;\n\tlet occurrences = 0;\n\tfor (let index = 3; index < tokens.length; index++) {\n\t\tconst token = tokens[index] as string;\n\t\tif (token === \"--project\") {\n\t\t\toccurrences++;\n\t\t\tfound = tokens[index + 1] ?? null;\n\t\t\tcontinue;\n\t\t}\n\t\tif (token.startsWith(\"--project=\")) {\n\t\t\toccurrences++;\n\t\t\tfound = token.slice(\"--project=\".length);\n\t\t}\n\t}\n\treturn occurrences === 1 ? found : null;\n}\n\n/** The same refusal shape as an unparseable file: say what, and touch nothing. */\nfunction refuseShape(settingsPath: string, what: string): Error {\n\treturn new Error(\n\t\t`${settingsPath} has a shape this tool does not recognise: ${what}. Fix or remove it, then run this again — it was left untouched.`,\n\t);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","/**\n * `<dest>/.fabric/instructions.lock` — what the last sync wrote.\n *\n * ## What the lock is, and what it is not\n *\n * It is a CONTENT LEDGER: a list of paths with the hash each one had when\n * this tool last wrote it. It is the only reason the sync may delete\n * anything — a path must be in the ledger AND still hash to what the ledger\n * recorded before it can be removed.\n *\n * It is NOT authenticated. It is a plain JSON file inside the checkout, so\n * anything that can write there can write it. That bounds what a tampered\n * lock can do rather than preventing it: an attacker who can already edit\n * files in the tree can make the next sync delete a file whose CURRENT\n * content hash they name correctly. They cannot make it write anywhere new,\n * because writes come from the server manifest, and they cannot name\n * `.git/**` or `.fabric/**` at all (`isReservedPath`). Closing the rest\n * needs a ledger stored outside the checkout, which is a larger change than\n * this feature.\n *\n * The lock is rewritten LAST, after every write has succeeded. A ledger\n * naming files that are not there would authorise deleting whatever is in\n * their place on the next run.\n */\nimport { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { writeFileSafely } from \"./safe-write.js\";\n\nexport const LOCK_DIRECTORY = \".fabric\";\nexport const LOCK_FILENAME = \"instructions.lock\";\n\n/** Bumped only if the shape below changes incompatibly. */\nexport const LOCK_VERSION = 1;\n\n/** The lock's own path, relative to the destination — never from a manifest. */\nconst LOCK_RELATIVE_PATH = `${LOCK_DIRECTORY}/${LOCK_FILENAME}`;\n\nconst SHA256_HEX = /^[0-9a-f]{64}$/;\n\ninterface LockFileEntry {\n\tsha256: string;\n\t/** POSIX mode as published, or null when the snapshot recorded none. */\n\tmode: number | null;\n}\n\nexport interface InstructionsLock {\n\tversion: number;\n\tprojectId: string;\n\tsnapshotId: string;\n\tsnapshotVersion: number;\n\tdigest: string;\n\t/** ISO 8601 timestamp of the sync that wrote this lock. */\n\tsyncedAt: string;\n\t/** Every path that sync wrote or verified — the manifest at that time. */\n\tfiles: Record<string, LockFileEntry>;\n}\n\nexport function lockPath(destination: string): string {\n\treturn path.join(destination, LOCK_DIRECTORY, LOCK_FILENAME);\n}\n\n/**\n * The lock, or `null` when this tree has never been synced.\n *\n * A lock that exists but does not validate is an ERROR and never a `null`.\n * Treating a damaged ledger as \"never synced\" would orphan every file the\n * previous sync wrote and hide the damage; the caller stops and says so.\n */\nexport async function readLock(\n\tdestination: string,\n): Promise<InstructionsLock | null> {\n\tconst file = lockPath(destination);\n\tlet raw: string;\n\ttry {\n\t\traw = await readFile(file, \"utf8\");\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n\t\t\treturn null;\n\t\t}\n\t\tthrow error;\n\t}\n\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch {\n\t\tthrow new Error(\n\t\t\t`${file} is unreadable: it is not valid JSON. Delete it to start from a clean sync.`,\n\t\t);\n\t}\n\tconst problem = lockProblem(parsed);\n\tif (problem !== null) {\n\t\tthrow new Error(\n\t\t\t`${file} is unreadable: ${problem}. Delete it to start from a clean sync.`,\n\t\t);\n\t}\n\treturn parsed as InstructionsLock;\n}\n\n/** Pretty JSON with LF endings and a trailing newline, so a diff of it reads. */\nfunction serializeLock(lock: InstructionsLock): string {\n\treturn `${JSON.stringify(lock, null, 2).replace(/\\r\\n/g, \"\\n\")}\\n`;\n}\n\n/**\n * Write the lock through the same guarded writer as every instruction file.\n * `root` is an already-canonical destination from `resolveDestinationRoot`:\n * a `.fabric -> ..` symlink is how the lock write used to escape the tree.\n */\nexport async function writeLock(\n\troot: string,\n\tlock: InstructionsLock,\n): Promise<void> {\n\tawait writeFileSafely({\n\t\troot,\n\t\trelativePath: LOCK_RELATIVE_PATH,\n\t\tbytes: new TextEncoder().encode(serializeLock(lock)),\n\t});\n}\n\n/**\n * Why this value is not a lock, or `null` when it is one.\n *\n * Every field is checked, including `version`: a future lock this build does\n * not understand must stop the run rather than be half-read.\n */\nfunction lockProblem(value: unknown): string | null {\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n\t\treturn \"it is not a JSON object\";\n\t}\n\tconst candidate = value as Record<string, unknown>;\n\n\tif (candidate.version !== LOCK_VERSION) {\n\t\treturn `its version is ${JSON.stringify(candidate.version)} and this build writes version ${LOCK_VERSION}`;\n\t}\n\tfor (const field of [\n\t\t\"projectId\",\n\t\t\"snapshotId\",\n\t\t\"digest\",\n\t\t\"syncedAt\",\n\t] as const) {\n\t\tconst actual = candidate[field];\n\t\tif (typeof actual !== \"string\" || actual.length === 0) {\n\t\t\treturn `its \"${field}\" is not a non-empty string`;\n\t\t}\n\t}\n\tif (\n\t\ttypeof candidate.snapshotVersion !== \"number\" ||\n\t\t!Number.isInteger(candidate.snapshotVersion) ||\n\t\tcandidate.snapshotVersion < 0\n\t) {\n\t\treturn 'its \"snapshotVersion\" is not a non-negative integer';\n\t}\n\tif (\n\t\ttypeof candidate.files !== \"object\" ||\n\t\tcandidate.files === null ||\n\t\tArray.isArray(candidate.files)\n\t) {\n\t\treturn 'its \"files\" is not an object';\n\t}\n\n\tfor (const [filePath, entry] of Object.entries(\n\t\tcandidate.files as Record<string, unknown>,\n\t)) {\n\t\tif (\n\t\t\ttypeof entry !== \"object\" ||\n\t\t\tentry === null ||\n\t\t\tArray.isArray(entry)\n\t\t) {\n\t\t\treturn `its entry for ${JSON.stringify(filePath)} is not an object`;\n\t\t}\n\t\tconst record = entry as Record<string, unknown>;\n\t\tif (\n\t\t\ttypeof record.sha256 !== \"string\" ||\n\t\t\t!SHA256_HEX.test(record.sha256)\n\t\t) {\n\t\t\treturn `its entry for ${JSON.stringify(filePath)} has no 64-character hex sha256`;\n\t\t}\n\t\tif (\n\t\t\trecord.mode !== null &&\n\t\t\t(typeof record.mode !== \"number\" ||\n\t\t\t\t!Number.isInteger(record.mode) ||\n\t\t\t\trecord.mode < 0)\n\t\t) {\n\t\t\treturn `its entry for ${JSON.stringify(filePath)} has a mode that is neither null nor a non-negative integer`;\n\t\t}\n\t}\n\treturn null;\n}\n","/**\n * Deciding whether a server response is a manifest at all.\n *\n * An absent manifest used to become `[]`, and an empty manifest means\n * \"delete everything the lock names\". A version-skewed server, a truncated\n * proxy response or a field rename was therefore one step away from wiping\n * the tree and writing an empty ledger. A manifest is now either complete\n * and self-consistent or it is a refusal.\n *\n * Three independent things are checked, because each catches a different\n * failure:\n *\n * - every ENTRY is well-formed, and no two name the same file;\n * - the COUNT matches the snapshot's own `fileCount`, which catches a\n * truncated list that is otherwise perfectly well-formed;\n * - the DIGEST recomputed from the entries matches the snapshot's, which\n * catches a list that is the right length and the wrong content.\n *\n * The digest recipe is the server's (`packages/instructions/src/manifest.ts`):\n * sha256 over `path\\0sha256\\n` lines sorted by path. It is reimplemented\n * here rather than imported because `@repo/instructions` is a private\n * workspace package and this one is published to npm.\n */\nimport { createHash } from \"node:crypto\";\nimport type { InstructionManifestEntry } from \"@fabricorg/sdk\";\nimport {\n\tcheckRelativePath,\n\tdescribeRejection,\n\tfindCollision,\n\tisReservedPath,\n} from \"./paths.js\";\nimport { isAllowedMode } from \"./safe-write.js\";\n\nconst SHA256_HEX = /^[0-9a-f]{64}$/;\n\n/**\n * What a published snapshot can legitimately be.\n *\n * Mirrors `SNAPSHOT_LIMITS` in `packages/instructions/src/limits.ts`, which\n * bounds what publishing will ACCEPT; these bound what a client will act on.\n * Reimplemented rather than imported for the same reason the digest recipe is:\n * that package is private and this one is published to npm.\n *\n * The point is memory, not policy. Before this, `fileCount` and the per-entry\n * sizes were checked against each other but never against an absolute, so a\n * manifest claiming a million files of 4 GB each was internally consistent and\n * sized the download bound off its own claim.\n *\n * `maxPathBytes` and `maxDepth` are deliberately LOOSER than the server's 512\n * and 32: a client that refuses what the server would happily publish breaks\n * the moment those limits are raised, and 1024 bytes across 5000 files is\n * still bounded. Everything else matches exactly.\n */\nconst MANIFEST_LIMITS = {\n\tmaxFiles: 5000,\n\tmaxTotalBytes: 52_428_800,\n\tmaxFileBytes: 5_242_880,\n\tmaxPathBytes: 1024,\n\tmaxDepth: 64,\n} as const;\n\n/**\n * Per-entry zip framing, in bytes, before the path itself.\n *\n * A zip carries each file twice in structure: a 30-byte local header and a\n * 46-byte central-directory header, each followed by the name, plus optional\n * extra fields and a data descriptor. 512 is generous for all of it, and\n * generous is the right direction — this is a ceiling on what will be\n * DOWNLOADED, and a bound that is too tight refuses a snapshot the server\n * considers perfectly valid.\n */\nconst ZIP_ENTRY_OVERHEAD_BYTES = 512;\n\n/**\n * The largest archive worth downloading for this manifest.\n *\n * A flat slack was wrong: zip framing grows with the number of entries and\n * the length of their names, so a legitimate snapshot of 5000 empty files\n * with 200-byte paths needs about 2.4 MB of pure structure and could not be\n * synced at all. The bound now scales the way the format does.\n */\nexport function maxArchiveBytes(\n\tentries: ReadonlyArray<{ path: string; size: number }>,\n): number {\n\tlet total = 1_048_576;\n\tfor (const entry of entries) {\n\t\ttotal +=\n\t\t\tentry.size +\n\t\t\tZIP_ENTRY_OVERHEAD_BYTES +\n\t\t\t2 * Buffer.byteLength(entry.path, \"utf8\");\n\t}\n\treturn total;\n}\n\n/**\n * The snapshot digest, computed the way the server computes it.\n *\n * Keep in step with `computeSnapshotDigest` in `@repo/instructions`. A\n * divergence here turns every sync into a refusal, which is the safe\n * direction but still a break.\n */\nexport function computeSnapshotDigest(\n\tentries: ReadonlyArray<{ path: string; sha256: string }>,\n): string {\n\tconst lines = [...entries]\n\t\t.sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0))\n\t\t.map((entry) => `${entry.path}\\0${entry.sha256}\\n`)\n\t\t.join(\"\");\n\treturn createHash(\"sha256\")\n\t\t.update(Buffer.from(lines, \"utf8\"))\n\t\t.digest(\"hex\");\n}\n\n/**\n * Validate a published manifest, or explain why it is not one.\n *\n * Throws rather than returning a result: every caller's only response to a\n * bad manifest is to stop, and under `--hook` the message becomes the one\n * line a developer sees.\n */\nexport function assertValidManifest(input: {\n\tmanifest: unknown;\n\tsnapshot: { digest: string; fileCount: number; version: number };\n}): InstructionManifestEntry[] {\n\tconst { manifest, snapshot } = input;\n\n\tif (!Array.isArray(manifest)) {\n\t\tthrow new Error(\n\t\t\t`The server described version ${snapshot.version} as published but sent no file manifest. Nothing was changed.`,\n\t\t);\n\t}\n\n\tif (manifest.length > MANIFEST_LIMITS.maxFiles) {\n\t\tthrow new Error(\n\t\t\t`The manifest for version ${snapshot.version} lists ${manifest.length} files and a published snapshot holds at most ${MANIFEST_LIMITS.maxFiles}. Nothing was changed.`,\n\t\t);\n\t}\n\n\tconst entries: InstructionManifestEntry[] = [];\n\tfor (const raw of manifest) {\n\t\tentries.push(validateEntry(raw));\n\t}\n\n\tconst totalBytes = entries.reduce((total, entry) => total + entry.size, 0);\n\tif (totalBytes > MANIFEST_LIMITS.maxTotalBytes) {\n\t\tthrow new Error(\n\t\t\t`The manifest for version ${snapshot.version} describes ${totalBytes} bytes and a published snapshot holds at most ${MANIFEST_LIMITS.maxTotalBytes}. Nothing was changed.`,\n\t\t);\n\t}\n\n\tconst collision = findCollision(entries.map((entry) => entry.path));\n\tif (collision !== null) {\n\t\tthrow new Error(\n\t\t\t`Refusing to sync: ${describeRejection({\n\t\t\t\tok: false,\n\t\t\t\treason: \"collision\",\n\t\t\t\tdetail: `${collision.first} and ${collision.second}`,\n\t\t\t})}.`,\n\t\t);\n\t}\n\n\tif (entries.length !== snapshot.fileCount) {\n\t\tthrow new Error(\n\t\t\t`The manifest for version ${snapshot.version} lists ${entries.length} files and the snapshot says ${snapshot.fileCount}. Nothing was changed.`,\n\t\t);\n\t}\n\n\tconst recomputed = computeSnapshotDigest(entries);\n\tif (recomputed !== snapshot.digest) {\n\t\tthrow new Error(\n\t\t\t`The manifest for version ${snapshot.version} does not match its own digest (${snapshot.digest}); it hashes to ${recomputed}. Nothing was changed.`,\n\t\t);\n\t}\n\n\treturn entries;\n}\n\nfunction validateEntry(raw: unknown): InstructionManifestEntry {\n\tif (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) {\n\t\tthrow new Error(\n\t\t\t\"The server sent a manifest entry that is not an object. Nothing was changed.\",\n\t\t);\n\t}\n\tconst entry = raw as Record<string, unknown>;\n\n\tif (typeof entry.path !== \"string\") {\n\t\tthrow new Error(\n\t\t\t\"The server sent a manifest entry with no path. Nothing was changed.\",\n\t\t);\n\t}\n\tconst check = checkRelativePath(entry.path);\n\tif (!check.ok) {\n\t\tthrow new Error(\n\t\t\t`Refusing to sync: ${describeRejection(check)}. The published snapshot names a path this tool will not write.`,\n\t\t);\n\t}\n\tconst pathBytes = Buffer.byteLength(entry.path, \"utf8\");\n\tif (pathBytes > MANIFEST_LIMITS.maxPathBytes) {\n\t\tthrow new Error(\n\t\t\t`The manifest entry for ${entry.path.slice(0, 80)}… has a ${pathBytes}-byte path and at most ${MANIFEST_LIMITS.maxPathBytes} is accepted. Nothing was changed.`,\n\t\t);\n\t}\n\tif (entry.path.split(\"/\").length > MANIFEST_LIMITS.maxDepth) {\n\t\tthrow new Error(\n\t\t\t`The manifest entry for ${entry.path} is nested deeper than ${MANIFEST_LIMITS.maxDepth} directories. Nothing was changed.`,\n\t\t);\n\t}\n\tif (isReservedPath(entry.path)) {\n\t\tthrow new Error(\n\t\t\t`Refusing to sync: ${describeRejection({\n\t\t\t\tok: false,\n\t\t\t\treason: \"reserved_path\",\n\t\t\t\tdetail: entry.path,\n\t\t\t})}.`,\n\t\t);\n\t}\n\tif (typeof entry.sha256 !== \"string\" || !SHA256_HEX.test(entry.sha256)) {\n\t\tthrow new Error(\n\t\t\t`The manifest entry for ${entry.path} has no 64-character hex sha256. Nothing was changed.`,\n\t\t);\n\t}\n\tif (\n\t\ttypeof entry.size !== \"number\" ||\n\t\t!Number.isInteger(entry.size) ||\n\t\tentry.size < 0\n\t) {\n\t\tthrow new Error(\n\t\t\t`The manifest entry for ${entry.path} has no non-negative integer size. Nothing was changed.`,\n\t\t);\n\t}\n\tif (entry.size > MANIFEST_LIMITS.maxFileBytes) {\n\t\tthrow new Error(\n\t\t\t`The manifest entry for ${entry.path} declares ${entry.size} bytes and a published file holds at most ${MANIFEST_LIMITS.maxFileBytes}. Nothing was changed.`,\n\t\t);\n\t}\n\tif (\n\t\tentry.mode !== null &&\n\t\t(typeof entry.mode !== \"number\" || !Number.isInteger(entry.mode))\n\t) {\n\t\tthrow new Error(\n\t\t\t`The manifest entry for ${entry.path} has a mode that is neither null nor an integer. Nothing was changed.`,\n\t\t);\n\t}\n\tif (!isAllowedMode(entry.mode as number | null)) {\n\t\tthrow new Error(\n\t\t\t`Refusing to sync: ${entry.path} asks for file mode ${((entry.mode as number) ?? 0).toString(8)}, and only 644 and 755 are accepted.`,\n\t\t);\n\t}\n\n\treturn {\n\t\tpath: entry.path,\n\t\tsha256: entry.sha256,\n\t\tsize: entry.size,\n\t\tmode: entry.mode as number | null,\n\t\tkind: (entry.kind ?? \"OTHER\") as InstructionManifestEntry[\"kind\"],\n\t};\n}\n","/**\n * What a sync would do, decided against the LOCAL TREE and not only the lock.\n *\n * The lock says what the last sync wrote; the working tree says what is\n * actually there now. Planning from the lock alone gets both interesting\n * cases wrong — a file the developer edited since the sync would be silently\n * overwritten with no notice, and a file they deleted would never come back\n * because the lock still claims it is present. So every path is hashed.\n *\n * Seven outcomes, and the distinctions between them are the whole point:\n *\n * verified local bytes already equal the published bytes — no write\n * added nothing local — a new file\n * updated local matches the lock, so this is the sync's own file\n * moving forward\n * replaced local matches neither the lock nor the manifest — local\n * edits are about to be overwritten, and the report says so\n * deleted gone from the manifest, and local still matches the lock,\n * so the sync wrote it and may remove it\n * kept-modified gone from the manifest, but local differs from the lock —\n * the developer changed it, so it stays\n * kept-renamed gone from the manifest under this spelling, but the\n * manifest names the same physical file another way — the\n * write for the new spelling is the update, so the old one\n * must not be unlinked afterwards\n *\n * A path absent from the lock is never deleted, whatever it is — and a\n * reserved path (`.git/`, `.fabric/`, the tool's own Claude settings file) is\n * refused outright wherever it appears, because the lock is an unauthenticated\n * file in the checkout (see `lock.ts`) and those are the paths a tampered one\n * would most want to name.\n */\nimport { createHash } from \"node:crypto\";\nimport type { InstructionManifestEntry } from \"@fabricorg/sdk\";\nimport { type InstructionsLock, LOCK_VERSION } from \"./lock.js\";\nimport {\n\tcheckRelativePath,\n\tcollisionKey,\n\tdescribeRejection,\n\tfindCollision,\n\tisReservedPath,\n} from \"./paths.js\";\nimport { readFileSafely } from \"./safe-write.js\";\n\ntype PlanAction =\n\t| \"verified\"\n\t| \"added\"\n\t| \"updated\"\n\t| \"replaced\"\n\t| \"deleted\"\n\t| \"kept-modified\"\n\t| \"kept-renamed\";\n\nexport interface PlanEntry {\n\tpath: string;\n\taction: PlanAction;\n\t/** The published hash, for everything the manifest still carries. */\n\tsha256?: string;\n\tmode?: number | null;\n}\n\nexport interface SyncPlan {\n\tentries: PlanEntry[];\n\t/** Entries whose bytes must be fetched and written. */\n\twrites: PlanEntry[];\n\t/** Entries to unlink. Always a subset of the previous lock. */\n\tdeletes: PlanEntry[];\n\tverified: PlanEntry[];\n\tkeptModified: PlanEntry[];\n\t/**\n\t * Lock paths that are the same physical file as a manifest path under a\n\t * different spelling. Never deleted; reported so the old spelling is not\n\t * a surprise on the filesystems where it survives.\n\t */\n\tkeptRenamed: PlanEntry[];\n}\n\n/**\n * Hex sha256 of a local file, or `null` when nothing is there.\n *\n * Every read goes through `readFileSafely`, the same guarded walk the writes\n * use: no symlinked component anywhere on the way down, nothing resolving\n * outside the destination, a regular file or nothing at all. A link pointing\n * at a file that happens to hold the published bytes used to hash EQUAL and\n * become `verified` — no write, no check, and a lock written over a path that\n * is not a file.\n */\nasync function hashLocalFile(\n\troot: string,\n\trelativePath: string,\n): Promise<string | null> {\n\tconst read = await readFileSafely(root, relativePath);\n\treturn read === null\n\t\t? null\n\t\t: createHash(\"sha256\").update(read.bytes).digest(\"hex\");\n}\n\nfunction lockPaths(lock: InstructionsLock | null): string[] {\n\treturn lock === null ? [] : Object.keys(lock.files);\n}\n\n/**\n * Every path the lock names has to survive the same checks a manifest path\n * does, plus the reserved-root rule — a hand-edited or accidentally\n * committed lock is exactly how `.git/config` would otherwise become an\n * unlink target with a hash anyone can read off disk.\n */\nfunction assertSafeLockPaths(paths: readonly string[]): void {\n\tfor (const lockedPath of paths) {\n\t\tconst check = checkRelativePath(lockedPath);\n\t\tif (!check.ok) {\n\t\t\tthrow new Error(\n\t\t\t\t`Refusing to sync: ${describeRejection(check)}. The lock names a path this tool will not touch.`,\n\t\t\t);\n\t\t}\n\t\tif (isReservedPath(lockedPath)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Refusing to sync: ${describeRejection({\n\t\t\t\t\tok: false,\n\t\t\t\t\treason: \"reserved_path\",\n\t\t\t\t\tdetail: lockedPath,\n\t\t\t\t})}. The lock names a path this tool will not touch.`,\n\t\t\t);\n\t\t}\n\t}\n\tconst collision = findCollision(paths);\n\tif (collision !== null) {\n\t\tthrow new Error(\n\t\t\t`Refusing to sync: ${describeRejection({\n\t\t\t\tok: false,\n\t\t\t\treason: \"collision\",\n\t\t\t\tdetail: `${collision.first} and ${collision.second}`,\n\t\t\t})}. The lock names two paths this tool cannot tell apart.`,\n\t\t);\n\t}\n}\n\n/**\n * Does the working tree still hold what the lock says it holds?\n *\n * The server answers \"unchanged\" by comparing digests, and a digest describes\n * the PUBLISHED snapshot — it says nothing about the checkout. Accepting that\n * answer as \"nothing to do\" meant an edited, deleted or chmod-ed instruction\n * file stayed that way until some later publication happened to move the\n * digest. For a feature whose point is that an agent reads the same\n * instructions everyone else does, that is the failure that matters most:\n * tampering persists and the tool reports success.\n *\n * Returns the paths that no longer match, as reasons a person can act on.\n * Never throws: a symlink or a directory standing where a file should be is\n * drift to REPORT, and the re-plan that follows is what refuses it.\n */\nexport async function verifyLedger(input: {\n\t/** An already-canonical root — `resolveDestinationRoot` or `resolveExistingRoot`. */\n\troot: string;\n\tlock: InstructionsLock;\n}): Promise<string[]> {\n\t// FIRST, before a single path is joined or opened. This function reads\n\t// paths that come out of an unauthenticated file in the checkout, and it\n\t// used to read them raw: `../outside` reached outside the destination, and\n\t// `rules/` replaced by a symlink was followed wherever it pointed. The\n\t// same validation `computeSyncPlan` runs, run before anything is touched.\n\tassertSafeLockPaths(lockPaths(input.lock));\n\n\tconst drifted: string[] = [];\n\tfor (const [lockedPath, locked] of Object.entries(input.lock.files)) {\n\t\t// A refusal from the guarded reader — a symlinked ancestor, a\n\t\t// directory where a file belongs — is drift, not a crash: the caller\n\t\t// re-plans, and planning refuses it there with the same message.\n\t\tlet read: Awaited<ReturnType<typeof readFileSafely>>;\n\t\ttry {\n\t\t\tread = await readFileSafely(input.root, lockedPath);\n\t\t} catch (error) {\n\t\t\tdrifted.push(\n\t\t\t\t`${lockedPath} (${error instanceof Error ? error.message.replace(/^Refusing to sync: /, \"\").replace(/\\.$/, \"\") : String(error)})`,\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\t\tif (read === null) {\n\t\t\tdrifted.push(`${lockedPath} (missing)`);\n\t\t\tcontinue;\n\t\t}\n\t\tconst actual = createHash(\"sha256\").update(read.bytes).digest(\"hex\");\n\t\tif (actual !== locked.sha256) {\n\t\t\tdrifted.push(`${lockedPath} (edited)`);\n\t\t\tcontinue;\n\t\t}\n\t\t// Modes are meaningless on Windows and a published `0755` that arrived\n\t\t// as `0644` leaves a script that will not run, so this is checked\n\t\t// wherever it can be.\n\t\tif (\n\t\t\tprocess.platform !== \"win32\" &&\n\t\t\tlocked.mode !== null &&\n\t\t\t(read.mode & 0o7777) !== (locked.mode & 0o7777)\n\t\t) {\n\t\t\tdrifted.push(\n\t\t\t\t`${lockedPath} (mode ${(read.mode & 0o7777).toString(8)}, published as ${(locked.mode & 0o7777).toString(8)})`,\n\t\t\t);\n\t\t}\n\t}\n\treturn drifted;\n}\n\nexport async function computeSyncPlan(input: {\n\t/** An already-canonical root, as every guarded read resolves against it. */\n\tdestination: string;\n\tmanifest: InstructionManifestEntry[];\n\tlock: InstructionsLock | null;\n}): Promise<SyncPlan> {\n\tconst { destination, manifest, lock } = input;\n\n\t// `assertValidManifest` has already checked every manifest entry's path,\n\t// shape, mode, uniqueness, count and digest before this is called. What\n\t// is re-checked here is the LOCK, which no server validated: it is a\n\t// plain file in the checkout, and it is the only thing that can authorise\n\t// a delete.\n\tassertSafeLockPaths(lockPaths(lock));\n\n\t// A Map, not the parsed object: a manifest path of `constructor` or\n\t// `toString` reads a value off `Object.prototype` when the lookup is a\n\t// plain property access, and `__proto__` does not read back at all.\n\tconst lockedFiles = new Map(Object.entries(lock?.files ?? {}));\n\tconst manifestPaths = new Set(manifest.map((entry) => entry.path));\n\t// The union, not the two sets separately. Each list is internally free of\n\t// collisions by now, which says nothing about a path appearing in one under\n\t// a spelling the other uses differently — and that case is a RENAME, not a\n\t// conflict. See `isRenameOf` below for what it costs to get wrong.\n\tconst manifestKeys = new Map(\n\t\tmanifest.map(\n\t\t\t(entry) => [collisionKey(entry.path), entry.path] as const,\n\t\t),\n\t);\n\tconst entries: PlanEntry[] = [];\n\n\tfor (const entry of manifest) {\n\t\tconst localHash = await hashLocalFile(destination, entry.path);\n\t\tif (localHash === entry.sha256) {\n\t\t\tentries.push({\n\t\t\t\tpath: entry.path,\n\t\t\t\taction: \"verified\",\n\t\t\t\tsha256: entry.sha256,\n\t\t\t\tmode: entry.mode,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tconst lockedHash = lockedFiles.get(entry.path)?.sha256;\n\t\tconst action: PlanAction =\n\t\t\tlocalHash === null\n\t\t\t\t? \"added\"\n\t\t\t\t: localHash === lockedHash\n\t\t\t\t\t? \"updated\"\n\t\t\t\t\t: \"replaced\";\n\t\tentries.push({\n\t\t\tpath: entry.path,\n\t\t\taction,\n\t\t\tsha256: entry.sha256,\n\t\t\tmode: entry.mode,\n\t\t});\n\t}\n\n\tfor (const [lockedPath, locked] of lockedFiles) {\n\t\tif (manifestPaths.has(lockedPath)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// `README.md` in the lock and `readme.md` in the manifest are two\n\t\t// spellings of one file wherever the filesystem folds case or\n\t\t// normalises names — and writes run before deletes, so planning a\n\t\t// delete here unlinked the file the same run had just written and then\n\t\t// wrote a lock claiming it was there. The manifest spelling's own write\n\t\t// IS the update; this one must not be touched. On Linux the two really\n\t\t// are separate files, and skipping the delete is still the right answer:\n\t\t// a tool that deletes a file because another file's name resembles it\n\t\t// would be worse than one that leaves a stale copy and says so.\n\t\tconst renamedTo = manifestKeys.get(collisionKey(lockedPath));\n\t\tif (renamedTo !== undefined) {\n\t\t\tentries.push({\n\t\t\t\tpath: lockedPath,\n\t\t\t\taction: \"kept-renamed\",\n\t\t\t\tsha256: locked.sha256,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst localHash = await hashLocalFile(destination, lockedPath);\n\t\tif (localHash === null) {\n\t\t\tcontinue;\n\t\t}\n\t\tentries.push({\n\t\t\tpath: lockedPath,\n\t\t\taction: localHash === locked.sha256 ? \"deleted\" : \"kept-modified\",\n\t\t\t// Carried so the unlink can prove it is still removing the file\n\t\t\t// this hash described, rather than whatever is at the path by the\n\t\t\t// time the writes are done.\n\t\t\tsha256: locked.sha256,\n\t\t});\n\t}\n\n\tentries.sort((a, b) => a.path.localeCompare(b.path));\n\n\treturn {\n\t\tentries,\n\t\twrites: entries.filter(\n\t\t\t(entry) =>\n\t\t\t\tentry.action === \"added\" ||\n\t\t\t\tentry.action === \"updated\" ||\n\t\t\t\tentry.action === \"replaced\",\n\t\t),\n\t\tdeletes: entries.filter((entry) => entry.action === \"deleted\"),\n\t\tverified: entries.filter((entry) => entry.action === \"verified\"),\n\t\tkeptModified: entries.filter(\n\t\t\t(entry) => entry.action === \"kept-modified\",\n\t\t),\n\t\tkeptRenamed: entries.filter((entry) => entry.action === \"kept-renamed\"),\n\t};\n}\n\n/** The lock the sync should leave behind once `plan` has been applied. */\nexport function nextLock(input: {\n\tprojectId: string;\n\tsnapshot: { id: string; version: number; digest: string };\n\tmanifest: InstructionManifestEntry[];\n\tnow?: Date;\n}): InstructionsLock {\n\t// `Object.fromEntries` rather than assignment into `{}`: assigning\n\t// `files[\"__proto__\"]` sets the prototype instead of creating an own\n\t// property, so a published file called `__proto__` was written to disk and\n\t// then left out of the ledger — and a later snapshot that dropped it could\n\t// not prove the sync had created it.\n\tconst files: InstructionsLock[\"files\"] = Object.fromEntries(\n\t\tinput.manifest.map((entry) => [\n\t\t\tentry.path,\n\t\t\t{ sha256: entry.sha256, mode: entry.mode },\n\t\t]),\n\t);\n\treturn {\n\t\tversion: LOCK_VERSION,\n\t\tprojectId: input.projectId,\n\t\tsnapshotId: input.snapshot.id,\n\t\tsnapshotVersion: input.snapshot.version,\n\t\tdigest: input.snapshot.digest,\n\t\tsyncedAt: (input.now ?? new Date()).toISOString(),\n\t\tfiles,\n\t};\n}\n","/**\n * fabric mcp\n *\n * fabric mcp servers List accessible MCP servers\n * fabric mcp configs List your MCP configurations\n * fabric mcp configs show <id> Show a specific MCP configuration\n */\n\nimport type {\n\tFabricMcpConfig,\n\tFabricMcpConfigDetail,\n\tFabricMcpServer,\n} from \"@fabricorg/sdk\";\nimport { Command } from \"commander\";\nimport { getClient } from \"../../lib/client.js\";\nimport { resolveContext } from \"../../lib/context.js\";\nimport { printError, printOutput, printRecord } from \"../../lib/output.js\";\n\nexport function buildMcpCommand(): Command {\n\tconst mcp = new Command(\"mcp\").description(\n\t\t\"Manage MCP servers and configurations\",\n\t);\n\n\t// -- servers -------------------------------------------------------------\n\tmcp.command(\"servers\")\n\t\t.description(\"List accessible MCP servers (system + custom)\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\n\t\t\t\"--format <format>\",\n\t\t\t\"Output format: table|json|yaml|csv\",\n\t\t\t\"table\",\n\t\t)\n\t\t.option(\"-q, --quiet\", \"Print server keys only\")\n\t\t.action(\n\t\t\tasync (opts: {\n\t\t\t\torg?: string;\n\t\t\t\tpersonal?: boolean;\n\t\t\t\tformat: string;\n\t\t\t\tquiet?: boolean;\n\t\t\t}) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet list: FabricMcpServer[];\n\t\t\t\ttry {\n\t\t\t\t\tlist = await client.mcp.listServers({\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tif (opts.quiet) {\n\t\t\t\t\tfor (const s of list) {\n\t\t\t\t\t\tprocess.stdout.write(`${s.key}\\n`);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintOutput(list, {\n\t\t\t\t\tformat: opts.format as \"table\" | \"json\" | \"yaml\" | \"csv\",\n\t\t\t\t\tcolumns: [\n\t\t\t\t\t\t\"key\",\n\t\t\t\t\t\t\"name\",\n\t\t\t\t\t\t\"transport\",\n\t\t\t\t\t\t\"category\",\n\t\t\t\t\t\t\"isSystemProvided\",\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\t// -- configs -------------------------------------------------------------\n\tconst configs = new Command(\"configs\").description(\n\t\t\"Manage MCP configurations\",\n\t);\n\n\tconfigs\n\t\t.command(\"list\", { isDefault: true })\n\t\t.description(\"List your MCP configurations\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\n\t\t\t\"--format <format>\",\n\t\t\t\"Output format: table|json|yaml|csv\",\n\t\t\t\"table\",\n\t\t)\n\t\t.option(\"-q, --quiet\", \"Print IDs only\")\n\t\t.action(\n\t\t\tasync (opts: {\n\t\t\t\torg?: string;\n\t\t\t\tpersonal?: boolean;\n\t\t\t\tformat: string;\n\t\t\t\tquiet?: boolean;\n\t\t\t}) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet list: FabricMcpConfig[];\n\t\t\t\ttry {\n\t\t\t\t\tlist = await client.mcp.listConfigs({\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tif (opts.quiet) {\n\t\t\t\t\tfor (const c of list) {\n\t\t\t\t\t\tprocess.stdout.write(`${c.id}\\n`);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintOutput(list, {\n\t\t\t\t\tformat: opts.format as \"table\" | \"json\" | \"yaml\" | \"csv\",\n\t\t\t\t\tcolumns: [\n\t\t\t\t\t\t\"id\",\n\t\t\t\t\t\t\"serverName\",\n\t\t\t\t\t\t\"displayName\",\n\t\t\t\t\t\t\"authType\",\n\t\t\t\t\t\t\"enabled\",\n\t\t\t\t\t\t\"status\",\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\tconfigs\n\t\t.command(\"show <id>\")\n\t\t.description(\"Show a specific MCP configuration\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tid: string,\n\t\t\t\topts: { org?: string; personal?: boolean; format: string },\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet config: FabricMcpConfigDetail;\n\t\t\t\ttry {\n\t\t\t\t\tconfig = await client.mcp.getConfig(id, {\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(config, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintRecord({\n\t\t\t\t\tID: config.id,\n\t\t\t\t\tServer: config.serverName ?? config.mcpServerId,\n\t\t\t\t\t\"Server Key\": config.serverKey ?? \"(none)\",\n\t\t\t\t\t\"Display Name\": config.displayName ?? \"(none)\",\n\t\t\t\t\t\"Base URL\": config.baseUrl ?? \"(none)\",\n\t\t\t\t\tTransport: config.transport ?? \"(default)\",\n\t\t\t\t\t\"Auth Type\": config.authType,\n\t\t\t\t\tEnabled: config.enabled ? \"yes\" : \"no\",\n\t\t\t\t\tStatus: config.status,\n\t\t\t\t\t\"Last Health Check\":\n\t\t\t\t\t\tconfig.lastHealthCheckAt?.slice(0, 19) ?? \"(never)\",\n\t\t\t\t\tCreated: config.createdAt.slice(0, 10),\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\tconfigs\n\t\t.command(\"delete <id>\")\n\t\t.description(\"Delete an MCP configuration\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"-y, --yes\", \"Skip confirmation prompt\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tid: string,\n\t\t\t\topts: { org?: string; personal?: boolean; yes?: boolean },\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\n\t\t\t\tif (!opts.yes) {\n\t\t\t\t\tprocess.stderr.write(\n\t\t\t\t\t\t`Delete MCP config ${id}? This cannot be undone. Pass --yes to confirm.\\n`,\n\t\t\t\t\t);\n\t\t\t\t\tprocess.exit(2);\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tawait client.mcp.deleteConfig(id, {\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tprocess.stdout.write(`MCP config ${id} deleted.\\n`);\n\t\t\t},\n\t\t);\n\n\tmcp.addCommand(configs);\n\n\t// -- serve ---------------------------------------------------------------\n\tmcp.command(\"serve\")\n\t\t.description(\n\t\t\t\"Run a stdio MCP server exposing this workspace's whole integration catalog. \" +\n\t\t\t\t\"Point Claude Desktop, Cursor, or any MCP client at it.\",\n\t\t)\n\t\t.action(async () => {\n\t\t\t// Lazy import — avoids loading the MCP SDK when running other commands\n\t\t\t// and keeps the CLI binary cold-start fast.\n\t\t\tconst { runStdio } = await import(\"@fabricorg/sdk-mcp/stdio\");\n\t\t\tawait runStdio();\n\t\t});\n\n\treturn mcp;\n}\n","/**\n * fabric orgs\n *\n * fabric orgs list List orgs you belong to\n * fabric orgs show <slug> Show org details\n */\n\nimport { Command } from \"commander\";\nimport { getClient } from \"../../lib/client.js\";\nimport { printError, printOutput, printRecord } from \"../../lib/output.js\";\n\nexport function buildOrgsCommand(): Command {\n\tconst orgs = new Command(\"orgs\").description(\"Manage organizations\");\n\n\t// -- list ----------------------------------------------------------------\n\torgs.command(\"list\")\n\t\t.description(\"List organizations you belong to\")\n\t\t.option(\n\t\t\t\"--format <format>\",\n\t\t\t\"Output format: table|json|yaml|csv\",\n\t\t\t\"table\",\n\t\t)\n\t\t.option(\"-q, --quiet\", \"Print slugs only\")\n\t\t.action(async (opts: { format: string; quiet?: boolean }) => {\n\t\t\tconst client = getClient();\n\t\t\tlet list: Awaited<ReturnType<typeof client.orgs.list>>;\n\t\t\ttry {\n\t\t\t\tlist = await client.orgs.list();\n\t\t\t} catch (err: unknown) {\n\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t}\n\n\t\t\tif (opts.quiet) {\n\t\t\t\tfor (const org of list) {\n\t\t\t\t\tprocess.stdout.write(`${org.slug}\\n`);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tprintOutput(list, {\n\t\t\t\tformat: opts.format as \"table\" | \"json\" | \"yaml\" | \"csv\",\n\t\t\t\tcolumns: [\"name\", \"slug\", \"role\", \"joinedAt\"],\n\t\t\t});\n\t\t});\n\n\t// -- show ----------------------------------------------------------------\n\torgs.command(\"show <slug>\")\n\t\t.description(\"Show details for an organization\")\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(async (slug: string, opts: { format: string }) => {\n\t\t\tconst client = getClient();\n\t\t\tlet list: Awaited<ReturnType<typeof client.orgs.list>>;\n\t\t\ttry {\n\t\t\t\tlist = await client.orgs.list();\n\t\t\t} catch (err: unknown) {\n\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t}\n\n\t\t\tconst org = list.find(\n\t\t\t\t(o: { slug: string; id: string }) =>\n\t\t\t\t\to.slug === slug || o.id === slug,\n\t\t\t);\n\t\t\tif (!org) {\n\t\t\t\tprintError(`Organization not found: ${slug}`, 4);\n\t\t\t}\n\n\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\tprintOutput(org, { format: fmt });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tprintRecord({\n\t\t\t\tName: org.name,\n\t\t\t\tSlug: org.slug,\n\t\t\t\tRole: org.role,\n\t\t\t\t\"Joined at\": String(org.joinedAt).slice(0, 10),\n\t\t\t\tLogo: org.logo ?? \"(none)\",\n\t\t\t});\n\t\t});\n\n\treturn orgs;\n}\n","/**\n * fabric projects\n *\n * fabric projects list List projects\n * fabric projects show <id> Show project details\n * fabric projects create <name> Create a project\n */\n\nimport type { FabricProject } from \"@fabricorg/sdk\";\nimport { Command } from \"commander\";\nimport { getClient } from \"../../lib/client.js\";\nimport { resolveContext } from \"../../lib/context.js\";\nimport {\n\tprintError,\n\tprintOutput,\n\tprintRecord,\n\tprintSuccess,\n} from \"../../lib/output.js\";\n\nexport function buildProjectsCommand(): Command {\n\tconst projects = new Command(\"projects\").description(\"Manage projects\");\n\n\t// -- list ----------------------------------------------------------------\n\tprojects\n\t\t.command(\"list\")\n\t\t.description(\"List projects\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\n\t\t\t\"--status <status>\",\n\t\t\t\"Filter by status: ACTIVE|DRAFT|COMPLETED|ARCHIVED\",\n\t\t)\n\t\t.option(\"--search <query>\", \"Search by name\")\n\t\t.option(\"--limit <n>\", \"Max results (default 20)\", \"20\")\n\t\t.option(\n\t\t\t\"--format <format>\",\n\t\t\t\"Output format: table|json|yaml|csv\",\n\t\t\t\"table\",\n\t\t)\n\t\t.option(\"-q, --quiet\", \"Print IDs only\")\n\t\t.action(\n\t\t\tasync (opts: {\n\t\t\t\torg?: string;\n\t\t\t\tpersonal?: boolean;\n\t\t\t\tstatus?: string;\n\t\t\t\tsearch?: string;\n\t\t\t\tlimit: string;\n\t\t\t\tformat: string;\n\t\t\t\tquiet?: boolean;\n\t\t\t}) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet list: FabricProject[];\n\t\t\t\ttry {\n\t\t\t\t\tlist = await client.projects.list({\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t\tstatus: opts.status as\n\t\t\t\t\t\t\t| FabricProject[\"status\"]\n\t\t\t\t\t\t\t| undefined,\n\t\t\t\t\t\tsearch: opts.search,\n\t\t\t\t\t\tlimit: Number(opts.limit),\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tif (opts.quiet) {\n\t\t\t\t\tfor (const p of list) {\n\t\t\t\t\t\tprocess.stdout.write(`${p.id}\\n`);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintOutput(list, {\n\t\t\t\t\tformat: opts.format as \"table\" | \"json\" | \"yaml\" | \"csv\",\n\t\t\t\t\tcolumns: [\"id\", \"name\", \"status\", \"createdAt\"],\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\t// -- show ----------------------------------------------------------------\n\tprojects\n\t\t.command(\"show <id>\")\n\t\t.description(\"Show project details\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tid: string,\n\t\t\t\topts: { org?: string; personal?: boolean; format: string },\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet project: FabricProject;\n\t\t\t\ttry {\n\t\t\t\t\tproject = await client.projects.get(id, {\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(project, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintRecord({\n\t\t\t\t\tID: project.id,\n\t\t\t\t\tName: project.name,\n\t\t\t\t\tStatus: project.status,\n\t\t\t\t\tDescription: project.description ?? \"(none)\",\n\t\t\t\t\tRepository: project.repositoryUrl ?? \"(none)\",\n\t\t\t\t\tCreated: project.createdAt.slice(0, 10),\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\t// -- create --------------------------------------------------------------\n\tprojects\n\t\t.command(\"create <name>\")\n\t\t.description(\"Create a new project\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"-d, --description <text>\", \"Project description\")\n\t\t.option(\"--repo <url>\", \"Repository URL\")\n\t\t.option(\n\t\t\t\"--status <status>\",\n\t\t\t\"Initial status: DRAFT|ACTIVE (default: DRAFT)\",\n\t\t\t\"DRAFT\",\n\t\t)\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tname: string,\n\t\t\t\topts: {\n\t\t\t\t\torg?: string;\n\t\t\t\t\tpersonal?: boolean;\n\t\t\t\t\tdescription?: string;\n\t\t\t\t\trepo?: string;\n\t\t\t\t\tstatus: string;\n\t\t\t\t\tformat: string;\n\t\t\t\t},\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet project: FabricProject;\n\t\t\t\ttry {\n\t\t\t\t\tproject = await client.projects.create({\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tdescription: opts.description,\n\t\t\t\t\t\trepositoryUrl: opts.repo,\n\t\t\t\t\t\tstatus: opts.status as \"DRAFT\" | \"ACTIVE\",\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(project, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintSuccess(`Project \"${project.name}\" created`);\n\t\t\t\tprintRecord({\n\t\t\t\t\tID: project.id,\n\t\t\t\t\tName: project.name,\n\t\t\t\t\tStatus: project.status,\n\t\t\t\t\tDescription: project.description ?? \"(none)\",\n\t\t\t\t\tCreated: project.createdAt.slice(0, 10),\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\t// -- update --------------------------------------------------------------\n\tprojects\n\t\t.command(\"update <id>\")\n\t\t.description(\"Update a project\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--name <name>\", \"New name\")\n\t\t.option(\"-d, --description <text>\", \"New description\")\n\t\t.option(\"--repo <url>\", \"Repository URL\")\n\t\t.option(\"--status <status>\", \"Status: DRAFT|ACTIVE|COMPLETED|ARCHIVED\")\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tid: string,\n\t\t\t\topts: {\n\t\t\t\t\torg?: string;\n\t\t\t\t\tpersonal?: boolean;\n\t\t\t\t\tname?: string;\n\t\t\t\t\tdescription?: string;\n\t\t\t\t\trepo?: string;\n\t\t\t\t\tstatus?: string;\n\t\t\t\t\tformat: string;\n\t\t\t\t},\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet project: FabricProject;\n\t\t\t\ttry {\n\t\t\t\t\tproject = await client.projects.update(id, {\n\t\t\t\t\t\tname: opts.name,\n\t\t\t\t\t\tdescription: opts.description,\n\t\t\t\t\t\trepositoryUrl: opts.repo,\n\t\t\t\t\t\tstatus: opts.status as\n\t\t\t\t\t\t\t| \"DRAFT\"\n\t\t\t\t\t\t\t| \"ACTIVE\"\n\t\t\t\t\t\t\t| \"COMPLETED\"\n\t\t\t\t\t\t\t| \"ARCHIVED\"\n\t\t\t\t\t\t\t| undefined,\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(project, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintRecord({\n\t\t\t\t\tID: project.id,\n\t\t\t\t\tName: project.name,\n\t\t\t\t\tStatus: project.status,\n\t\t\t\t\tDescription: project.description ?? \"(none)\",\n\t\t\t\t\tUpdated: project.updatedAt.slice(0, 10),\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\treturn projects;\n}\n","/**\n * fabric prompts\n *\n * fabric prompts list List prompt templates\n * fabric prompts get <id> Get a prompt (prints latest version content)\n */\n\nimport type { FabricPrompt } from \"@fabricorg/sdk\";\nimport { Command } from \"commander\";\nimport { getClient } from \"../../lib/client.js\";\nimport { resolveContext } from \"../../lib/context.js\";\nimport {\n\tprintError,\n\tprintOutput,\n\tprintRecord,\n\tprintSuccess,\n} from \"../../lib/output.js\";\n\nexport function buildPromptsCommand(): Command {\n\tconst prompts = new Command(\"prompts\").description(\n\t\t\"Manage prompt templates\",\n\t);\n\n\t// -- list ----------------------------------------------------------------\n\tprompts\n\t\t.command(\"list\")\n\t\t.description(\"List prompt templates\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--search <query>\", \"Search by name\")\n\t\t.option(\"--category <cat>\", \"Filter by category\")\n\t\t.option(\"--limit <n>\", \"Max results\", \"50\")\n\t\t.option(\n\t\t\t\"--format <format>\",\n\t\t\t\"Output format: table|json|yaml|csv\",\n\t\t\t\"table\",\n\t\t)\n\t\t.option(\"-q, --quiet\", \"Print IDs only\")\n\t\t.action(\n\t\t\tasync (opts: {\n\t\t\t\torg?: string;\n\t\t\t\tpersonal?: boolean;\n\t\t\t\tsearch?: string;\n\t\t\t\tcategory?: string;\n\t\t\t\tlimit: string;\n\t\t\t\tformat: string;\n\t\t\t\tquiet?: boolean;\n\t\t\t}) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet list: FabricPrompt[];\n\t\t\t\ttry {\n\t\t\t\t\tlist = await client.prompts.list({\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t\tsearch: opts.search,\n\t\t\t\t\t\tcategory: opts.category,\n\t\t\t\t\t\tlimit: Number(opts.limit),\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tif (opts.quiet) {\n\t\t\t\t\tfor (const p of list) {\n\t\t\t\t\t\tprocess.stdout.write(`${p.id}\\n`);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintOutput(list, {\n\t\t\t\t\tformat: opts.format as \"table\" | \"json\" | \"yaml\" | \"csv\",\n\t\t\t\t\tcolumns: [\n\t\t\t\t\t\t\"id\",\n\t\t\t\t\t\t\"key\",\n\t\t\t\t\t\t\"name\",\n\t\t\t\t\t\t\"scope\",\n\t\t\t\t\t\t\"category\",\n\t\t\t\t\t\t\"updatedAt\",\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\t// -- get -----------------------------------------------------------------\n\tprompts\n\t\t.command(\"get <id>\")\n\t\t.description(\"Get a prompt (prints latest version content by default)\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\n\t\t\t\"--format <format>\",\n\t\t\t\"Output format: raw|table|json|yaml (default: raw)\",\n\t\t\t\"raw\",\n\t\t)\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tid: string,\n\t\t\t\topts: { org?: string; personal?: boolean; format: string },\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet prompt: FabricPrompt;\n\t\t\t\ttry {\n\t\t\t\t\tprompt = await client.prompts.get(id, {\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"raw\" | \"table\" | \"json\" | \"yaml\";\n\n\t\t\t\tif (fmt === \"json\") {\n\t\t\t\t\tprintOutput(prompt, { format: \"json\" });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(prompt, { format: \"yaml\" });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst content = prompt.versions?.[0]?.content ?? \"(no content)\";\n\n\t\t\t\tif (fmt === \"raw\") {\n\t\t\t\t\tprocess.stdout.write(`${content}\\n`);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// table: metadata + content block\n\t\t\t\tprintRecord({\n\t\t\t\t\tID: prompt.id,\n\t\t\t\t\tKey: prompt.key,\n\t\t\t\t\tName: prompt.name,\n\t\t\t\t\tScope: prompt.scope,\n\t\t\t\t\tCategory: prompt.category ?? \"(none)\",\n\t\t\t\t\tTags: (prompt.tags ?? []).join(\", \") || \"(none)\",\n\t\t\t\t});\n\t\t\t\tprocess.stdout.write(`\\n--- Content ---\\n${content}\\n`);\n\t\t\t},\n\t\t);\n\n\t// -- create --------------------------------------------------------------\n\tprompts\n\t\t.command(\"create\")\n\t\t.description(\"Create a new prompt\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.requiredOption(\"--key <key>\", \"Prompt key (unique identifier)\")\n\t\t.requiredOption(\"--name <name>\", \"Prompt name\")\n\t\t.option(\"-d, --description <text>\", \"Prompt description\")\n\t\t.option(\"--content <text>\", \"Initial prompt content\")\n\t\t.option(\"--category <cat>\", \"Category\")\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (opts: {\n\t\t\t\torg?: string;\n\t\t\t\tpersonal?: boolean;\n\t\t\t\tkey: string;\n\t\t\t\tname: string;\n\t\t\t\tdescription?: string;\n\t\t\t\tcontent?: string;\n\t\t\t\tcategory?: string;\n\t\t\t\tformat: string;\n\t\t\t}) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet prompt: FabricPrompt;\n\t\t\t\ttry {\n\t\t\t\t\tprompt = await client.prompts.create({\n\t\t\t\t\t\tkey: opts.key,\n\t\t\t\t\t\tname: opts.name,\n\t\t\t\t\t\tdescription: opts.description,\n\t\t\t\t\t\tcontent: opts.content,\n\t\t\t\t\t\tcategory: opts.category,\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(prompt, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintSuccess(`Prompt \"${prompt.name}\" created`);\n\t\t\t\tprintRecord({\n\t\t\t\t\tID: prompt.id,\n\t\t\t\t\tKey: prompt.key,\n\t\t\t\t\tName: prompt.name,\n\t\t\t\t\tScope: prompt.scope,\n\t\t\t\t\tCreated: prompt.createdAt.slice(0, 10),\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\t// -- update --------------------------------------------------------------\n\tprompts\n\t\t.command(\"update <id>\")\n\t\t.description(\"Update a prompt\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--name <name>\", \"New name\")\n\t\t.option(\"-d, --description <text>\", \"New description\")\n\t\t.option(\"--category <cat>\", \"Category\")\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tid: string,\n\t\t\t\topts: {\n\t\t\t\t\torg?: string;\n\t\t\t\t\tpersonal?: boolean;\n\t\t\t\t\tname?: string;\n\t\t\t\t\tdescription?: string;\n\t\t\t\t\tcategory?: string;\n\t\t\t\t\tformat: string;\n\t\t\t\t},\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet prompt: FabricPrompt;\n\t\t\t\ttry {\n\t\t\t\t\tprompt = await client.prompts.update(id, {\n\t\t\t\t\t\tname: opts.name,\n\t\t\t\t\t\tdescription: opts.description,\n\t\t\t\t\t\tcategory: opts.category,\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(prompt, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintRecord({\n\t\t\t\t\tID: prompt.id,\n\t\t\t\t\tKey: prompt.key,\n\t\t\t\t\tName: prompt.name,\n\t\t\t\t\tScope: prompt.scope,\n\t\t\t\t\tUpdated: prompt.updatedAt.slice(0, 10),\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\treturn prompts;\n}\n","/**\n * fabric reports\n *\n * fabric reports templates list List report templates\n * fabric reports templates show <id> Show template details\n * fabric reports executions list List report executions\n */\n\nimport type {\n\tFabricReportExecution,\n\tFabricReportTemplate,\n} from \"@fabricorg/sdk\";\nimport { Command } from \"commander\";\nimport { getClient } from \"../../lib/client.js\";\nimport { resolveContext } from \"../../lib/context.js\";\nimport { printError, printOutput, printRecord } from \"../../lib/output.js\";\n\nexport function buildReportsCommand(): Command {\n\tconst reports = new Command(\"reports\").description(\n\t\t\"Manage report templates and executions\",\n\t);\n\n\t// -- templates -----------------------------------------------------------\n\tconst templates = new Command(\"templates\").description(\n\t\t\"Manage report templates\",\n\t);\n\n\ttemplates\n\t\t.command(\"list\", { isDefault: true })\n\t\t.description(\"List report templates\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--search <query>\", \"Search by name\")\n\t\t.option(\"--category <cat>\", \"Filter by category\")\n\t\t.option(\"--limit <n>\", \"Max results (default 20)\", \"20\")\n\t\t.option(\n\t\t\t\"--format <format>\",\n\t\t\t\"Output format: table|json|yaml|csv\",\n\t\t\t\"table\",\n\t\t)\n\t\t.option(\"-q, --quiet\", \"Print IDs only\")\n\t\t.action(\n\t\t\tasync (opts: {\n\t\t\t\torg?: string;\n\t\t\t\tpersonal?: boolean;\n\t\t\t\tsearch?: string;\n\t\t\t\tcategory?: string;\n\t\t\t\tlimit: string;\n\t\t\t\tformat: string;\n\t\t\t\tquiet?: boolean;\n\t\t\t}) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet list: FabricReportTemplate[];\n\t\t\t\ttry {\n\t\t\t\t\tlist = await client.reports.listTemplates({\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t\tsearch: opts.search,\n\t\t\t\t\t\tcategory: opts.category,\n\t\t\t\t\t\tlimit: Number(opts.limit),\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tif (opts.quiet) {\n\t\t\t\t\tfor (const t of list) {\n\t\t\t\t\t\tprocess.stdout.write(`${t.id}\\n`);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintOutput(list, {\n\t\t\t\t\tformat: opts.format as \"table\" | \"json\" | \"yaml\" | \"csv\",\n\t\t\t\t\tcolumns: [\n\t\t\t\t\t\t\"id\",\n\t\t\t\t\t\t\"name\",\n\t\t\t\t\t\t\"templateType\",\n\t\t\t\t\t\t\"scope\",\n\t\t\t\t\t\t\"usageCount\",\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\ttemplates\n\t\t.command(\"show <id>\")\n\t\t.description(\"Show report template details\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tid: string,\n\t\t\t\topts: { org?: string; personal?: boolean; format: string },\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet tmpl: FabricReportTemplate;\n\t\t\t\ttry {\n\t\t\t\t\ttmpl = await client.reports.getTemplate(id, {\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(tmpl, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintRecord({\n\t\t\t\t\tID: tmpl.id,\n\t\t\t\t\tName: tmpl.name,\n\t\t\t\t\tType: tmpl.templateType,\n\t\t\t\t\tScope: tmpl.scope,\n\t\t\t\t\tCategory: tmpl.category ?? \"(none)\",\n\t\t\t\t\tTags: tmpl.tags.join(\", \") || \"(none)\",\n\t\t\t\t\tPublic: tmpl.isPublic ? \"yes\" : \"no\",\n\t\t\t\t\t\"Use Count\": String(tmpl.usageCount),\n\t\t\t\t\tDescription: tmpl.description ?? \"(none)\",\n\t\t\t\t\tUpdated: tmpl.updatedAt.slice(0, 10),\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\treports.addCommand(templates);\n\n\t// -- executions ----------------------------------------------------------\n\tconst executions = new Command(\"executions\").description(\n\t\t\"View report executions\",\n\t);\n\n\texecutions\n\t\t.command(\"list\", { isDefault: true })\n\t\t.description(\"List report executions\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--limit <n>\", \"Max results (default 20)\", \"20\")\n\t\t.option(\n\t\t\t\"--format <format>\",\n\t\t\t\"Output format: table|json|yaml|csv\",\n\t\t\t\"table\",\n\t\t)\n\t\t.option(\"-q, --quiet\", \"Print IDs only\")\n\t\t.action(\n\t\t\tasync (opts: {\n\t\t\t\torg?: string;\n\t\t\t\tpersonal?: boolean;\n\t\t\t\tlimit: string;\n\t\t\t\tformat: string;\n\t\t\t\tquiet?: boolean;\n\t\t\t}) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet list: FabricReportExecution[];\n\t\t\t\ttry {\n\t\t\t\t\tlist = await client.reports.listExecutions({\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t\tlimit: Number(opts.limit),\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tif (opts.quiet) {\n\t\t\t\t\tfor (const e of list) {\n\t\t\t\t\t\tprocess.stdout.write(`${e.id}\\n`);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintOutput(list, {\n\t\t\t\t\tformat: opts.format as \"table\" | \"json\" | \"yaml\" | \"csv\",\n\t\t\t\t\tcolumns: [\n\t\t\t\t\t\t\"id\",\n\t\t\t\t\t\t\"templateId\",\n\t\t\t\t\t\t\"status\",\n\t\t\t\t\t\t\"startedAt\",\n\t\t\t\t\t\t\"completedAt\",\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\treports.addCommand(executions);\n\n\treturn reports;\n}\n","/**\n * fabric skills\n *\n * fabric skills list Browse skill definitions\n * fabric skills show <id> Show skill details\n */\n\nimport type { FabricSkill } from \"@fabricorg/sdk\";\nimport { Command } from \"commander\";\nimport { getClient } from \"../../lib/client.js\";\nimport { resolveContext } from \"../../lib/context.js\";\nimport { printError, printOutput, printRecord } from \"../../lib/output.js\";\n\nexport function buildSkillsCommand(): Command {\n\tconst skills = new Command(\"skills\").description(\n\t\t\"Browse skill definitions\",\n\t);\n\n\t// -- list ----------------------------------------------------------------\n\tskills\n\t\t.command(\"list\")\n\t\t.description(\"List skills\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--search <query>\", \"Search by name\")\n\t\t.option(\"--category <cat>\", \"Filter by category\")\n\t\t.option(\"--limit <n>\", \"Max results\", \"50\")\n\t\t.option(\n\t\t\t\"--format <format>\",\n\t\t\t\"Output format: table|json|yaml|csv\",\n\t\t\t\"table\",\n\t\t)\n\t\t.option(\"-q, --quiet\", \"Print slugs only\")\n\t\t.action(\n\t\t\tasync (opts: {\n\t\t\t\torg?: string;\n\t\t\t\tpersonal?: boolean;\n\t\t\t\tsearch?: string;\n\t\t\t\tcategory?: string;\n\t\t\t\tlimit: string;\n\t\t\t\tformat: string;\n\t\t\t\tquiet?: boolean;\n\t\t\t}) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet list: FabricSkill[];\n\t\t\t\ttry {\n\t\t\t\t\tlist = await client.skills.list({\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t\tsearch: opts.search,\n\t\t\t\t\t\tcategory: opts.category,\n\t\t\t\t\t\tlimit: Number(opts.limit),\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tif (opts.quiet) {\n\t\t\t\t\tfor (const s of list) {\n\t\t\t\t\t\tprocess.stdout.write(`${s.slug}\\n`);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintOutput(list, {\n\t\t\t\t\tformat: opts.format as \"table\" | \"json\" | \"yaml\" | \"csv\",\n\t\t\t\t\tcolumns: [\"slug\", \"name\", \"category\", \"scope\", \"useCount\"],\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\t// -- show ----------------------------------------------------------------\n\tskills\n\t\t.command(\"show <id>\")\n\t\t.description(\"Show skill details (accepts ID or slug)\")\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(async (id: string, opts: { format: string }) => {\n\t\t\tconst client = getClient();\n\t\t\tlet skill: FabricSkill;\n\t\t\ttry {\n\t\t\t\tskill = await client.skills.get(id);\n\t\t\t} catch (err: unknown) {\n\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t}\n\n\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\tprintOutput(skill, { format: fmt });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tprintRecord({\n\t\t\t\tID: skill.id,\n\t\t\t\tSlug: skill.slug,\n\t\t\t\tName: skill.name,\n\t\t\t\tCategory: skill.category ?? \"(none)\",\n\t\t\t\tScope: skill.scope,\n\t\t\t\tTags: skill.tags.join(\", \") || \"(none)\",\n\t\t\t\tPublished: skill.isPublished ? \"yes\" : \"no\",\n\t\t\t\t\"Use Count\": String(skill.useCount),\n\t\t\t\tVersion: String(skill.version),\n\t\t\t\tDescription: skill.description,\n\t\t\t\tUpdated: skill.updatedAt.slice(0, 10),\n\t\t\t});\n\t\t});\n\n\treturn skills;\n}\n","/**\n * fabric workflows\n *\n * fabric workflows list List workflows\n * fabric workflows show <id> Show workflow details\n * fabric workflows trigger <id> Trigger a workflow execution\n * fabric workflows status <id> <execId> Get execution status\n */\n\nimport type { FabricExecution, FabricWorkflow } from \"@fabricorg/sdk\";\nimport { Command } from \"commander\";\nimport { getClient } from \"../../lib/client.js\";\nimport { resolveContext } from \"../../lib/context.js\";\nimport {\n\tprintError,\n\tprintOutput,\n\tprintRecord,\n\tprintSuccess,\n} from \"../../lib/output.js\";\n\nexport function buildWorkflowsCommand(): Command {\n\tconst workflows = new Command(\"workflows\").description(\"Manage workflows\");\n\n\t// -- list ----------------------------------------------------------------\n\tworkflows\n\t\t.command(\"list\")\n\t\t.description(\"List workflows\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--status <status>\", \"Filter: DRAFT|ACTIVE|PAUSED|ARCHIVED\")\n\t\t.option(\"--search <query>\", \"Search by name\")\n\t\t.option(\"--limit <n>\", \"Max results\", \"20\")\n\t\t.option(\n\t\t\t\"--format <format>\",\n\t\t\t\"Output format: table|json|yaml|csv\",\n\t\t\t\"table\",\n\t\t)\n\t\t.option(\"-q, --quiet\", \"Print IDs only\")\n\t\t.action(\n\t\t\tasync (opts: {\n\t\t\t\torg?: string;\n\t\t\t\tpersonal?: boolean;\n\t\t\t\tstatus?: string;\n\t\t\t\tsearch?: string;\n\t\t\t\tlimit: string;\n\t\t\t\tformat: string;\n\t\t\t\tquiet?: boolean;\n\t\t\t}) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet list: FabricWorkflow[];\n\t\t\t\ttry {\n\t\t\t\t\tlist = await client.workflows.list({\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t\tstatus: opts.status as\n\t\t\t\t\t\t\t| FabricWorkflow[\"status\"]\n\t\t\t\t\t\t\t| undefined,\n\t\t\t\t\t\tsearch: opts.search,\n\t\t\t\t\t\tlimit: Number(opts.limit),\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tif (opts.quiet) {\n\t\t\t\t\tfor (const w of list) {\n\t\t\t\t\t\tprocess.stdout.write(`${w.id}\\n`);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintOutput(list, {\n\t\t\t\t\tformat: opts.format as \"table\" | \"json\" | \"yaml\" | \"csv\",\n\t\t\t\t\tcolumns: [\n\t\t\t\t\t\t\"id\",\n\t\t\t\t\t\t\"name\",\n\t\t\t\t\t\t\"status\",\n\t\t\t\t\t\t\"triggerType\",\n\t\t\t\t\t\t\"createdAt\",\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\t// -- show ----------------------------------------------------------------\n\tworkflows\n\t\t.command(\"show <id>\")\n\t\t.description(\"Show workflow details\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tid: string,\n\t\t\t\topts: { org?: string; personal?: boolean; format: string },\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet wf: FabricWorkflow;\n\t\t\t\ttry {\n\t\t\t\t\twf = await client.workflows.get(id, {\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(wf, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintRecord({\n\t\t\t\t\tID: wf.id,\n\t\t\t\t\tName: wf.name,\n\t\t\t\t\tStatus: wf.status,\n\t\t\t\t\tTrigger: wf.triggerType,\n\t\t\t\t\tVersion: String(wf.version),\n\t\t\t\t\tCreated: wf.createdAt.slice(0, 10),\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\t// -- trigger -------------------------------------------------------------\n\tworkflows\n\t\t.command(\"trigger <id>\")\n\t\t.description(\"Trigger a workflow execution\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--input <json>\", \"JSON input for triggerData\", \"{}\")\n\t\t.option(\"--vars <json>\", \"JSON variables\", \"{}\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tid: string,\n\t\t\t\topts: {\n\t\t\t\t\torg?: string;\n\t\t\t\t\tpersonal?: boolean;\n\t\t\t\t\tinput: string;\n\t\t\t\t\tvars: string;\n\t\t\t\t},\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\n\t\t\t\tlet triggerData: Record<string, unknown> = {};\n\t\t\t\tlet variables: Record<string, unknown> = {};\n\t\t\t\ttry {\n\t\t\t\t\ttriggerData = JSON.parse(opts.input);\n\t\t\t\t\tvariables = JSON.parse(opts.vars);\n\t\t\t\t} catch {\n\t\t\t\t\tprintError(\"--input and --vars must be valid JSON\", 2);\n\t\t\t\t}\n\n\t\t\t\tlet result: {\n\t\t\t\t\texecutionId: string;\n\t\t\t\t\tworkflowId: string;\n\t\t\t\t\tstatus: string;\n\t\t\t\t};\n\t\t\t\ttry {\n\t\t\t\t\tresult = await client.workflows.trigger(id, {\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t\ttriggerData,\n\t\t\t\t\t\tvariables,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tprintSuccess(\"Workflow triggered\");\n\t\t\t\tprocess.stdout.write(` Execution ID: ${result.executionId}\\n`);\n\t\t\t\tprocess.stdout.write(` Status: ${result.status}\\n`);\n\t\t\t},\n\t\t);\n\n\t// -- status --------------------------------------------------------------\n\tworkflows\n\t\t.command(\"status <id> <execId>\")\n\t\t.description(\"Get workflow execution status\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tid: string,\n\t\t\t\texecId: string,\n\t\t\t\topts: { org?: string; personal?: boolean; format: string },\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet exec: FabricExecution;\n\t\t\t\ttry {\n\t\t\t\t\texec = await client.workflows.getExecution(id, execId, {\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(exec, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintRecord({\n\t\t\t\t\tID: exec.id,\n\t\t\t\t\t\"Workflow ID\": exec.workflowId,\n\t\t\t\t\tStatus: exec.status,\n\t\t\t\t\t\"Trigger type\": exec.triggerType,\n\t\t\t\t\tStarted: exec.startedAt?.slice(0, 19) ?? \"(not started)\",\n\t\t\t\t\tCompleted: exec.completedAt?.slice(0, 19) ?? \"(running)\",\n\t\t\t\t\tError: exec.error ?? \"(none)\",\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\treturn workflows;\n}\n","/**\n * fabric workspaces\n *\n * fabric workspaces list List workspaces\n * fabric workspaces show <id> Show workspace details\n */\n\nimport type { FabricWorkspace, FabricWorkspaceDetail } from \"@fabricorg/sdk\";\nimport { Command } from \"commander\";\nimport { getClient } from \"../../lib/client.js\";\nimport { resolveContext } from \"../../lib/context.js\";\nimport { printError, printOutput, printRecord } from \"../../lib/output.js\";\n\nexport function buildWorkspacesCommand(): Command {\n\tconst workspaces = new Command(\"workspaces\").description(\n\t\t\"Manage workspaces\",\n\t);\n\n\t// -- list ----------------------------------------------------------------\n\tworkspaces\n\t\t.command(\"list\")\n\t\t.description(\"List workspaces\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--search <query>\", \"Search by name\")\n\t\t.option(\"--status <status>\", \"Filter: ACTIVE|ARCHIVED\")\n\t\t.option(\"--limit <n>\", \"Max results (default 20)\", \"20\")\n\t\t.option(\n\t\t\t\"--format <format>\",\n\t\t\t\"Output format: table|json|yaml|csv\",\n\t\t\t\"table\",\n\t\t)\n\t\t.option(\"-q, --quiet\", \"Print IDs only\")\n\t\t.action(\n\t\t\tasync (opts: {\n\t\t\t\torg?: string;\n\t\t\t\tpersonal?: boolean;\n\t\t\t\tsearch?: string;\n\t\t\t\tstatus?: string;\n\t\t\t\tlimit: string;\n\t\t\t\tformat: string;\n\t\t\t\tquiet?: boolean;\n\t\t\t}) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet list: FabricWorkspace[];\n\t\t\t\ttry {\n\t\t\t\t\tlist = await client.workspaces.list({\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t\tsearch: opts.search,\n\t\t\t\t\t\tstatus: opts.status as\n\t\t\t\t\t\t\t| \"ACTIVE\"\n\t\t\t\t\t\t\t| \"ARCHIVED\"\n\t\t\t\t\t\t\t| undefined,\n\t\t\t\t\t\tlimit: Number(opts.limit),\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tif (opts.quiet) {\n\t\t\t\t\tfor (const w of list) {\n\t\t\t\t\t\tprocess.stdout.write(`${w.id}\\n`);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintOutput(list, {\n\t\t\t\t\tformat: opts.format as \"table\" | \"json\" | \"yaml\" | \"csv\",\n\t\t\t\t\tcolumns: [\n\t\t\t\t\t\t\"id\",\n\t\t\t\t\t\t\"name\",\n\t\t\t\t\t\t\"type\",\n\t\t\t\t\t\t\"status\",\n\t\t\t\t\t\t\"documentCount\",\n\t\t\t\t\t\t\"updatedAt\",\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\t// -- show ----------------------------------------------------------------\n\tworkspaces\n\t\t.command(\"show <id>\")\n\t\t.description(\"Show workspace details\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tid: string,\n\t\t\t\topts: { org?: string; personal?: boolean; format: string },\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet ws: FabricWorkspaceDetail;\n\t\t\t\ttry {\n\t\t\t\t\tws = await client.workspaces.get(id, {\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(ws, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintRecord({\n\t\t\t\t\tID: ws.id,\n\t\t\t\t\tName: ws.name,\n\t\t\t\t\tType: ws.type,\n\t\t\t\t\tStatus: ws.status,\n\t\t\t\t\tDescription: ws.description ?? \"(none)\",\n\t\t\t\t\tDocuments: String(ws.documentCount),\n\t\t\t\t\tConversations: String(ws.conversationCount),\n\t\t\t\t\tUpdated: ws.updatedAt.slice(0, 10),\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\treturn workspaces;\n}\n"],"mappings":"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","names":["Command","_a","_a","rows","cols","_a","Command","Command","FabricClient","Command","Command","_a","FabricClient","Command","Command","Command","Command","_a","Command","Command","_a","Command","Command","Command","Command","Command","_a","Command","Command","_a","path","Command","createHash","_a","_a","_a","createHash","_a","readFile","path","path","readFile","_a","readFile","path","path","readFile","createHash","SHA256_HEX","createHash","_a","createHash","createHash","_a","Command","_a","path","Command","Command","_a","config","Command","Command","_a","Command","Command","_a","Command","Command","_a","Command","Command","_a","Command","Command","_a","Command","Command","_a","Command","Command","_a","Command"]}
1
+ {"version":3,"sources":["../src/bin/fabric.ts","../package.json","../src/commands/agents/index.ts","../src/lib/client.ts","../src/lib/config.ts","../src/lib/output.ts","../src/lib/context.ts","../src/commands/auth/keys.ts","../src/commands/auth/login.ts","../src/commands/auth/logout.ts","../src/commands/auth/whoami.ts","../src/commands/chats/index.ts","../src/commands/completion/index.ts","../src/commands/ctx/index.ts","../src/commands/features/index.ts","../src/commands/frames/index.ts","../src/commands/instructions/index.ts","../src/lib/instructions/apply.ts","../src/lib/instructions/paths.ts","../src/lib/instructions/safe-write.ts","../src/lib/instructions/bundle.ts","../src/lib/instructions/hook.ts","../src/lib/instructions/lock.ts","../src/lib/instructions/manifest.ts","../src/lib/instructions/plan.ts","../src/commands/mcp/index.ts","../src/commands/orgs/index.ts","../src/commands/projects/index.ts","../src/commands/prompts/index.ts","../src/commands/reports/index.ts","../src/commands/skills/index.ts","../src/commands/workflows/index.ts","../src/commands/workspaces/index.ts"],"sourcesContent":["/**\n * @fabricorg/cli — fabric command\n *\n * Usage: fabric <command> [subcommand] [options]\n *\n * Exit codes:\n * 0 success\n * 1 general failure\n * 2 invalid usage / bad arguments\n * 3 auth failure\n * 4 not found\n * 5 forbidden\n * 6 rate limited\n * 7 validation error\n */\n\nimport { Command } from \"commander\";\nimport packageJson from \"../../package.json\";\nimport { buildAgentsCommand } from \"../commands/agents/index.js\";\nimport { buildKeysCommand } from \"../commands/auth/keys.js\";\nimport { buildLoginCommand } from \"../commands/auth/login.js\";\nimport { buildLogoutCommand } from \"../commands/auth/logout.js\";\nimport { buildWhoamiCommand } from \"../commands/auth/whoami.js\";\nimport { buildChatsCommand } from \"../commands/chats/index.js\";\nimport { buildCompletionCommand } from \"../commands/completion/index.js\";\nimport { buildCtxCommand } from \"../commands/ctx/index.js\";\nimport { buildFeaturesCommand } from \"../commands/features/index.js\";\nimport { buildFramesCommand } from \"../commands/frames/index.js\";\nimport { buildInstructionsCommand } from \"../commands/instructions/index.js\";\nimport { buildMcpCommand } from \"../commands/mcp/index.js\";\nimport { buildOrgsCommand } from \"../commands/orgs/index.js\";\nimport { buildProjectsCommand } from \"../commands/projects/index.js\";\nimport { buildPromptsCommand } from \"../commands/prompts/index.js\";\nimport { buildReportsCommand } from \"../commands/reports/index.js\";\nimport { buildSkillsCommand } from \"../commands/skills/index.js\";\nimport { buildWorkflowsCommand } from \"../commands/workflows/index.js\";\nimport { buildWorkspacesCommand } from \"../commands/workspaces/index.js\";\nimport { getConfigPath } from \"../lib/config.js\";\n\nconst program = new Command();\n\nprogram\n\t.name(\"fabric\")\n\t.description(\"Fabric AI platform CLI\")\n\t.version(packageJson.version)\n\t.option(\n\t\t\"--format <format>\",\n\t\t\"Output format: table|json|yaml|csv\",\n\t\tprocess.env.FABRIC_FORMAT ?? \"table\",\n\t);\n\n// ---------------------------------------------------------------------------\n// fabric auth\n// ---------------------------------------------------------------------------\nconst auth = new Command(\"auth\").description(\n\t\"Authenticate and manage API keys\",\n);\nauth.addCommand(buildLoginCommand());\nauth.addCommand(buildLogoutCommand());\nauth.addCommand(buildWhoamiCommand());\nauth.addCommand(buildKeysCommand());\nprogram.addCommand(auth);\n\n// ---------------------------------------------------------------------------\n// fabric ctx\n// ---------------------------------------------------------------------------\nprogram.addCommand(buildCtxCommand());\n\n// ---------------------------------------------------------------------------\n// fabric orgs\n// ---------------------------------------------------------------------------\nprogram.addCommand(buildOrgsCommand());\n\n// ---------------------------------------------------------------------------\n// fabric projects\n// ---------------------------------------------------------------------------\nprogram.addCommand(buildProjectsCommand());\n\n// ---------------------------------------------------------------------------\n// fabric features\n// ---------------------------------------------------------------------------\nprogram.addCommand(buildFeaturesCommand());\n\n// ---------------------------------------------------------------------------\n// fabric workflows\n// ---------------------------------------------------------------------------\nprogram.addCommand(buildWorkflowsCommand());\n\n// ---------------------------------------------------------------------------\n// fabric prompts\n// ---------------------------------------------------------------------------\nprogram.addCommand(buildPromptsCommand());\n\n// ---------------------------------------------------------------------------\n// fabric agents\n// ---------------------------------------------------------------------------\nprogram.addCommand(buildAgentsCommand());\n\n// ---------------------------------------------------------------------------\n// fabric skills\n// ---------------------------------------------------------------------------\nprogram.addCommand(buildSkillsCommand());\n\n// ---------------------------------------------------------------------------\n// fabric instructions\n// ---------------------------------------------------------------------------\nprogram.addCommand(buildInstructionsCommand());\n\n// ---------------------------------------------------------------------------\n// fabric mcp\n// ---------------------------------------------------------------------------\nprogram.addCommand(buildMcpCommand());\n\n// ---------------------------------------------------------------------------\n// fabric frames\n// ---------------------------------------------------------------------------\nprogram.addCommand(buildFramesCommand());\n\n// ---------------------------------------------------------------------------\n// fabric workspaces\n// ---------------------------------------------------------------------------\nprogram.addCommand(buildWorkspacesCommand());\n\n// ---------------------------------------------------------------------------\n// fabric chats\n// ---------------------------------------------------------------------------\nprogram.addCommand(buildChatsCommand());\n\n// ---------------------------------------------------------------------------\n// fabric reports\n// ---------------------------------------------------------------------------\nprogram.addCommand(buildReportsCommand());\n\n// ---------------------------------------------------------------------------\n// fabric completion\n// ---------------------------------------------------------------------------\nprogram.addCommand(buildCompletionCommand());\n\n// ---------------------------------------------------------------------------\n// fabric config\n// ---------------------------------------------------------------------------\nconst config = new Command(\"config\").description(\"Show CLI configuration\");\nconfig\n\t.command(\"path\")\n\t.description(\"Print the path to the config file\")\n\t.action(() => {\n\t\tprocess.stdout.write(`${getConfigPath()}\\n`);\n\t});\nprogram.addCommand(config);\n\n// ---------------------------------------------------------------------------\n// Global error handler — structured JSON for --format json\n// ---------------------------------------------------------------------------\nprocess.on(\"unhandledRejection\", (reason) => {\n\tconst message = reason instanceof Error ? reason.message : String(reason);\n\tif (process.env.FABRIC_FORMAT === \"json\") {\n\t\tprocess.stderr.write(\n\t\t\tJSON.stringify({ error: { message, code: \"UNHANDLED_ERROR\" } }) +\n\t\t\t\t\"\\n\",\n\t\t);\n\t} else {\n\t\tprocess.stderr.write(`✗ ${message}\\n`);\n\t}\n\tprocess.exit(1);\n});\n\nprogram.parse(process.argv);\n","{\n\t\"name\": \"@fabricorg/cli\",\n\t\"version\": \"0.3.1\",\n\t\"description\": \"CLI for the Fabric AI platform\",\n\t\"keywords\": [\n\t\t\"fabric\",\n\t\t\"ai\",\n\t\t\"cli\",\n\t\t\"developer-tools\"\n\t],\n\t\"homepage\": \"https://fabric.pro\",\n\t\"license\": \"MIT\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"git+https://github.com/Fabric-Pro/fabric-oss.git\",\n\t\t\"directory\": \"packages/cli\"\n\t},\n\t\"type\": \"module\",\n\t\"bin\": {\n\t\t\"fabric\": \"./dist/fabric.js\"\n\t},\n\t\"files\": [\n\t\t\"dist\"\n\t],\n\t\"publishConfig\": {\n\t\t\"access\": \"public\"\n\t},\n\t\"scripts\": {\n\t\t\"build\": \"tsup\",\n\t\t\"dev\": \"tsup --watch\",\n\t\t\"type-check\": \"tsc --noEmit\",\n\t\t\"test\": \"vitest run\",\n\t\t\"test:watch\": \"vitest\",\n\t\t\"fabric\": \"node --import tsx/esm src/bin/fabric.ts\"\n\t},\n\t\"dependencies\": {\n\t\t\"@fabricorg/sdk\": \"workspace:*\",\n\t\t\"@fabricorg/sdk-mcp\": \"workspace:*\",\n\t\t\"cli-table3\": \"^0.6.5\",\n\t\t\"commander\": \"^13.1.0\",\n\t\t\"conf\": \"^13.1.0\",\n\t\t\"fflate\": \"^0.8.3\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@repo/tsconfig\": \"workspace:*\",\n\t\t\"tsup\": \"^8.0.0\",\n\t\t\"tsx\": \"^4.21.0\",\n\t\t\"typescript\": \"5.9.3\",\n\t\t\"vitest\": \"^4.1.11\"\n\t}\n}\n","/**\n * fabric agents\n *\n * fabric agents list List agents\n * fabric agents show <id> Show agent details\n */\n\nimport type { FabricAgent } from \"@fabricorg/sdk\";\nimport { Command } from \"commander\";\nimport { getClient } from \"../../lib/client.js\";\nimport { resolveContext } from \"../../lib/context.js\";\nimport { printError, printOutput, printRecord } from \"../../lib/output.js\";\n\nexport function buildAgentsCommand(): Command {\n\tconst agents = new Command(\"agents\").description(\"Manage agents\");\n\n\t// -- list ----------------------------------------------------------------\n\tagents\n\t\t.command(\"list\")\n\t\t.description(\"List agents\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--status <status>\", \"Filter: ACTIVE|INACTIVE|DEPRECATED\")\n\t\t.option(\"--limit <n>\", \"Max results\", \"50\")\n\t\t.option(\n\t\t\t\"--format <format>\",\n\t\t\t\"Output format: table|json|yaml|csv\",\n\t\t\t\"table\",\n\t\t)\n\t\t.option(\"-q, --quiet\", \"Print IDs only\")\n\t\t.action(\n\t\t\tasync (opts: {\n\t\t\t\torg?: string;\n\t\t\t\tpersonal?: boolean;\n\t\t\t\tstatus?: string;\n\t\t\t\tlimit: string;\n\t\t\t\tformat: string;\n\t\t\t\tquiet?: boolean;\n\t\t\t}) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet list: FabricAgent[];\n\t\t\t\ttry {\n\t\t\t\t\tlist = await client.agents.list({\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t\tstatus: opts.status as\n\t\t\t\t\t\t\t| FabricAgent[\"status\"]\n\t\t\t\t\t\t\t| undefined,\n\t\t\t\t\t\tlimit: Number(opts.limit),\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tif (opts.quiet) {\n\t\t\t\t\tfor (const a of list) {\n\t\t\t\t\t\tprocess.stdout.write(`${a.id}\\n`);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintOutput(list, {\n\t\t\t\t\tformat: opts.format as \"table\" | \"json\" | \"yaml\" | \"csv\",\n\t\t\t\t\tcolumns: [\n\t\t\t\t\t\t\"id\",\n\t\t\t\t\t\t\"name\",\n\t\t\t\t\t\t\"displayName\",\n\t\t\t\t\t\t\"framework\",\n\t\t\t\t\t\t\"status\",\n\t\t\t\t\t\t\"createdAt\",\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\t// -- show ----------------------------------------------------------------\n\tagents\n\t\t.command(\"show <id>\")\n\t\t.description(\"Show agent details\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tid: string,\n\t\t\t\topts: { org?: string; personal?: boolean; format: string },\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet agent: FabricAgent;\n\t\t\t\ttry {\n\t\t\t\t\tagent = await client.agents.get(id, {\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(agent, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintRecord({\n\t\t\t\t\tID: agent.id,\n\t\t\t\t\t\"Agent ID\": agent.agentId,\n\t\t\t\t\tName: agent.name,\n\t\t\t\t\t\"Display name\": agent.displayName,\n\t\t\t\t\tFramework: agent.framework,\n\t\t\t\t\tStatus: agent.status,\n\t\t\t\t\t\"Deployment URL\": agent.deploymentUrl ?? \"(none)\",\n\t\t\t\t\tCreated: agent.createdAt.slice(0, 10),\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\t// -- execute -------------------------------------------------------------\n\tagents\n\t\t.command(\"execute <id>\")\n\t\t.description(\"Execute an agent\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--input <json>\", 'Input JSON (e.g. \\'{\"key\":\"value\"}\\')')\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tid: string,\n\t\t\t\topts: {\n\t\t\t\t\torg?: string;\n\t\t\t\t\tpersonal?: boolean;\n\t\t\t\t\tinput?: string;\n\t\t\t\t\tformat: string;\n\t\t\t\t},\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\n\t\t\t\tlet inputObj: Record<string, unknown> = {};\n\t\t\t\tif (opts.input) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tinputObj = JSON.parse(opts.input);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tprintError(\"--input must be valid JSON\", 2);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tlet result: import(\"@fabricorg/sdk\").FabricAgentExecution;\n\t\t\t\ttry {\n\t\t\t\t\tresult = await client.agents.execute(id, {\n\t\t\t\t\t\tinput: inputObj,\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(result, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintRecord({\n\t\t\t\t\t\"Task ID\": result.taskId,\n\t\t\t\t\t\"Workflow ID\": result.workflowId,\n\t\t\t\t\t\"Run ID\": result.runId ?? \"(pending)\",\n\t\t\t\t\tStatus: result.status,\n\t\t\t\t\t...(result.warning ? { Warning: result.warning } : {}),\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\treturn agents;\n}\n","/**\n * Returns a configured FabricClient for CLI commands.\n * Exits with a clear error if no API key is available.\n */\n\nimport { FabricAuthError, FabricClient } from \"@fabricorg/sdk\";\nimport { getApiKey, getBaseUrl } from \"./config.js\";\nimport { printError } from \"./output.js\";\n\nexport interface ClientOverrides {\n\t/**\n\t * Retry policy. The SDK's default retries twice, and its timeout is PER\n\t * ATTEMPT, so a \"5 second\" call can really take about 15.75 seconds with\n\t * backoff. Session-hook mode turns retries off so its own deadline is the\n\t * only bound that matters.\n\t */\n\tretry?: { maxRetries: number };\n\t/**\n\t * Per-request timeout. The SDK sets this on the CLIENT, not per call, so\n\t * a command that must answer fast — the session-start instructions check\n\t * — builds its own client rather than reaching for a per-call option that\n\t * does not exist.\n\t */\n\ttimeoutMs?: number;\n}\n\nexport function getClient(overrides: ClientOverrides = {}): FabricClient {\n\tconst apiKey = getApiKey();\n\n\tif (!apiKey) {\n\t\tprintError(\n\t\t\t\"Not authenticated. Run:\\n fabric auth login --key <api-key>\",\n\t\t\t3,\n\t\t);\n\t}\n\n\ttry {\n\t\treturn new FabricClient({\n\t\t\tapiKey,\n\t\t\tbaseUrl: getBaseUrl(),\n\t\t\t...(overrides.timeoutMs !== undefined\n\t\t\t\t? { timeoutMs: overrides.timeoutMs }\n\t\t\t\t: {}),\n\t\t\t...(overrides.retry !== undefined\n\t\t\t\t? { retry: overrides.retry }\n\t\t\t\t: {}),\n\t\t});\n\t} catch (err: unknown) {\n\t\tif (err instanceof FabricAuthError) {\n\t\t\tprintError(err.message, 3);\n\t\t}\n\t\tthrow err;\n\t}\n}\n","/**\n * Config storage for @fabricorg/cli\n *\n * Persists to XDG_CONFIG_HOME/fabricai/config.json (Linux/macOS)\n * or %APPDATA%\\fabricai\\config.json (Windows).\n *\n * The API key is stored as-is in the config file with 0600 permissions.\n * Future: migrate to system keychain.\n */\n\nimport Conf from \"conf\";\n\ninterface CliConfig {\n\t/** Active profile name */\n\tactiveProfile: string;\n\tprofiles: Record<string, ProfileConfig>;\n\t/** Default output format */\n\tdefaultFormat: \"table\" | \"json\" | \"yaml\" | \"csv\";\n}\n\ninterface ProfileConfig {\n\t/** API key for this profile */\n\tapiKey?: string;\n\t/** Override base URL (e.g. for self-hosted) */\n\tbaseUrl?: string;\n\t/** Default context for commands */\n\tdefaultContext?: ContextConfig;\n}\n\nexport type ContextConfig =\n\t| { type: \"personal\" }\n\t| { type: \"org\"; slug: string };\n\nconst DEFAULTS: CliConfig = {\n\tactiveProfile: \"default\",\n\tprofiles: {},\n\tdefaultFormat: \"table\",\n};\n\nlet _store: Conf<CliConfig> | undefined;\n\nfunction getStore(): Conf<CliConfig> {\n\tif (!_store) {\n\t\t_store = new Conf<CliConfig>({\n\t\t\tprojectName: \"fabricai\",\n\t\t\tdefaults: DEFAULTS,\n\t\t});\n\t}\n\treturn _store;\n}\n\nfunction getConfig(): CliConfig {\n\treturn getStore().store;\n}\n\nfunction getActiveProfile(): ProfileConfig {\n\tconst cfg = getConfig();\n\treturn cfg.profiles[cfg.activeProfile] ?? {};\n}\n\nexport function getApiKey(): string | undefined {\n\t// Env var takes precedence over stored config\n\tif (process.env.FABRIC_API_KEY) {\n\t\treturn process.env.FABRIC_API_KEY;\n\t}\n\treturn getActiveProfile().apiKey;\n}\n\nexport function getBaseUrl(): string | undefined {\n\tif (process.env.FABRIC_BASE_URL) {\n\t\treturn process.env.FABRIC_BASE_URL;\n\t}\n\treturn getActiveProfile().baseUrl;\n}\n\nexport function getDefaultContext(): ContextConfig | undefined {\n\t// Env var takes precedence\n\tif (process.env.FABRIC_ORG) {\n\t\treturn { type: \"org\", slug: process.env.FABRIC_ORG };\n\t}\n\tif (process.env.FABRIC_PERSONAL === \"1\") {\n\t\treturn { type: \"personal\" };\n\t}\n\treturn getActiveProfile().defaultContext;\n}\n\nexport function getOutputFormat(): \"table\" | \"json\" | \"yaml\" | \"csv\" {\n\tif (\n\t\tprocess.env.FABRIC_FORMAT === \"json\" ||\n\t\tprocess.env.FABRIC_FORMAT === \"yaml\" ||\n\t\tprocess.env.FABRIC_FORMAT === \"csv\"\n\t) {\n\t\treturn process.env.FABRIC_FORMAT as \"json\" | \"yaml\" | \"csv\";\n\t}\n\treturn getConfig().defaultFormat;\n}\n\nexport interface SaveApiKeyOptions {\n\t/** Persisted only when a login explicitly selected a deployment URL. */\n\tbaseUrl?: string;\n}\n\n/**\n * Save credentials into the active profile in one profile update.\n *\n * `FABRIC_BASE_URL` remains an execution-time override: callers only pass a\n * base URL here when the person explicitly chose it with `--base-url`.\n */\nexport function saveApiKey(\n\tapiKey: string,\n\t{ baseUrl }: SaveApiKeyOptions = {},\n): void {\n\tconst store = getStore();\n\tconst profile = store.get(\"activeProfile\") as string;\n\tconst profiles = store.get(\"profiles\") as CliConfig[\"profiles\"];\n\tconst current = profiles[profile] ?? {};\n\tstore.set(\"profiles\", {\n\t\t...profiles,\n\t\t[profile]: {\n\t\t\t...current,\n\t\t\tapiKey,\n\t\t\t...(baseUrl === undefined ? {} : { baseUrl }),\n\t\t},\n\t});\n}\n\nexport function clearApiKey(profile?: string): void {\n\tconst store = getStore();\n\tconst active = profile ?? (store.get(\"activeProfile\") as string);\n\tconst profiles = store.get(\"profiles\") as CliConfig[\"profiles\"];\n\tconst { apiKey: _, ...rest } = profiles[active] ?? {};\n\tstore.set(\"profiles\", { ...profiles, [active]: rest });\n}\n\nexport function saveDefaultContext(ctx: ContextConfig, profile?: string): void {\n\tconst store = getStore();\n\tconst active = profile ?? (store.get(\"activeProfile\") as string);\n\tconst profiles = store.get(\"profiles\") as CliConfig[\"profiles\"];\n\tstore.set(\"profiles\", {\n\t\t...profiles,\n\t\t[active]: { ...(profiles[active] ?? {}), defaultContext: ctx },\n\t});\n}\n\nexport function getConfigPath(): string {\n\treturn getStore().path;\n}\n","/**\n * Output formatting for @fabricorg/cli\n *\n * Supports: table (default), json, yaml, csv, quiet (IDs only)\n */\n\nimport Table from \"cli-table3\";\nimport { getOutputFormat } from \"./config.js\";\n\ntype OutputFormat = \"table\" | \"json\" | \"yaml\" | \"csv\" | \"quiet\";\n\nexport interface OutputOptions {\n\tformat?: OutputFormat;\n\t/** Column names to include in table/csv output (in order) */\n\tcolumns?: string[];\n\t/** Key to use for --quiet / IDs-only output */\n\tidKey?: string;\n}\n\n/** Print data to stdout in the selected format. */\nexport function printOutput(data: unknown, opts: OutputOptions = {}): void {\n\tconst format = opts.format ?? (getOutputFormat() as OutputFormat);\n\n\tif (format === \"json\") {\n\t\tprocess.stdout.write(`${JSON.stringify(data, null, 2)}\\n`);\n\t\treturn;\n\t}\n\n\tif (format === \"yaml\") {\n\t\tprocess.stdout.write(`${toYaml(data)}\\n`);\n\t\treturn;\n\t}\n\n\tif (format === \"quiet\") {\n\t\tconst rows = Array.isArray(data) ? data : [data];\n\t\tconst key = opts.idKey ?? \"id\";\n\t\tfor (const row of rows) {\n\t\t\tconst val = (row as Record<string, unknown>)[key];\n\t\t\tif (val !== undefined) {\n\t\t\t\tprocess.stdout.write(`${String(val)}\\n`);\n\t\t\t}\n\t\t}\n\t\treturn;\n\t}\n\n\tif (format === \"csv\") {\n\t\tconst rows = Array.isArray(data) ? data : [data];\n\t\tif (rows.length === 0) {\n\t\t\treturn;\n\t\t}\n\t\tconst cols = opts.columns ?? Object.keys(rows[0] as object);\n\t\tprocess.stdout.write(`${cols.map(csvEscape).join(\",\")}\\n`);\n\t\tfor (const row of rows) {\n\t\t\tprocess.stdout.write(\n\t\t\t\t`${cols\n\t\t\t\t\t.map((c) =>\n\t\t\t\t\t\tcsvEscape(\n\t\t\t\t\t\t\tString((row as Record<string, unknown>)[c] ?? \"\"),\n\t\t\t\t\t\t),\n\t\t\t\t\t)\n\t\t\t\t\t.join(\",\")}\\n`,\n\t\t\t);\n\t\t}\n\t\treturn;\n\t}\n\n\t// Default: table\n\tconst rows = Array.isArray(data) ? data : [data];\n\tif (rows.length === 0) {\n\t\tprocess.stdout.write(\"(no results)\\n\");\n\t\treturn;\n\t}\n\tconst cols = opts.columns ?? Object.keys(rows[0] as object);\n\tconst table = new Table({ head: cols, style: { head: [\"cyan\"] } });\n\tfor (const row of rows) {\n\t\ttable.push(\n\t\t\tcols.map((c) => formatCell((row as Record<string, unknown>)[c])),\n\t\t);\n\t}\n\tprocess.stdout.write(`${table.toString()}\\n`);\n}\n\n/** Print a single key-value object as aligned pairs */\nexport function printRecord(\n\tdata: Record<string, unknown>,\n\topts: OutputOptions = {},\n): void {\n\tconst format = opts.format ?? (getOutputFormat() as OutputFormat);\n\tif (format === \"json\") {\n\t\tprintOutput(data, opts);\n\t\treturn;\n\t}\n\tif (format === \"yaml\") {\n\t\tprintOutput(data, opts);\n\t\treturn;\n\t}\n\tconst table = new Table({ style: { head: [\"cyan\"] } });\n\tfor (const [key, val] of Object.entries(data)) {\n\t\ttable.push({ [key]: formatCell(val) });\n\t}\n\tprocess.stdout.write(`${table.toString()}\\n`);\n}\n\n/** Print a success message to stdout */\nexport function printSuccess(message: string): void {\n\tprocess.stdout.write(`✓ ${message}\\n`);\n}\n\n/** Print an error message to stderr and exit with given code */\nexport function printError(message: string, exitCode = 1): never {\n\tprocess.stderr.write(`✗ ${message}\\n`);\n\tprocess.exit(exitCode);\n}\n\n/** Print a warning to stderr (no exit) */\nexport function printWarning(message: string): void {\n\tprocess.stderr.write(`⚠ ${message}\\n`);\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction formatCell(val: unknown): string {\n\tif (val === null || val === undefined) {\n\t\treturn \"\";\n\t}\n\tif (typeof val === \"boolean\") {\n\t\treturn val ? \"yes\" : \"no\";\n\t}\n\tif (typeof val === \"object\") {\n\t\treturn JSON.stringify(val);\n\t}\n\tconst s = String(val);\n\t// Truncate ISO dates to just the date portion for readability in tables\n\tif (/^\\d{4}-\\d{2}-\\d{2}T/.test(s)) {\n\t\treturn s.slice(0, 10);\n\t}\n\treturn s;\n}\n\nfunction csvEscape(s: string): string {\n\tif (s.includes(\",\") || s.includes('\"') || s.includes(\"\\n\")) {\n\t\treturn `\"${s.replace(/\"/g, '\"\"')}\"`;\n\t}\n\treturn s;\n}\n\n/** Minimal YAML serializer (no dependencies) */\nfunction toYaml(val: unknown, indent = 0): string {\n\tconst pad = \" \".repeat(indent);\n\tif (val === null || val === undefined) {\n\t\treturn \"~\";\n\t}\n\tif (typeof val === \"boolean\" || typeof val === \"number\") {\n\t\treturn String(val);\n\t}\n\tif (typeof val === \"string\") {\n\t\tif (val.includes(\"\\n\") || val.includes(\":\") || val.includes('\"')) {\n\t\t\treturn `\"${val.replace(/\"/g, '\\\\\"')}\"`;\n\t\t}\n\t\treturn val;\n\t}\n\tif (Array.isArray(val)) {\n\t\tif (val.length === 0) {\n\t\t\treturn \"[]\";\n\t\t}\n\t\treturn val\n\t\t\t.map((item) => `${pad}- ${toYaml(item, indent + 1)}`)\n\t\t\t.join(\"\\n\");\n\t}\n\tif (typeof val === \"object\") {\n\t\tconst entries = Object.entries(val as Record<string, unknown>);\n\t\tif (entries.length === 0) {\n\t\t\treturn \"{}\";\n\t\t}\n\t\treturn entries\n\t\t\t.map(([k, v]) => {\n\t\t\t\tconst valStr = toYaml(v, indent + 1);\n\t\t\t\tconst isMultiline = valStr.includes(\"\\n\");\n\t\t\t\treturn isMultiline\n\t\t\t\t\t? `${pad}${k}:\\n${valStr}`\n\t\t\t\t\t: `${pad}${k}: ${valStr}`;\n\t\t\t})\n\t\t\t.join(\"\\n\");\n\t}\n\treturn String(val);\n}\n","/**\n * Context resolution for @fabricorg/cli\n *\n * Every resource command runs inside exactly one organization. Personal context\n * is gone (Fizzy #1875, PO-9): the flag, the environment variable and the\n * stored default that selected it are retired here.\n *\n * The stored shape still PARSES a personal default, and that is deliberate.\n * Configs written by earlier versions have one on disk, and a client that\n * crashed on its own config file would be a worse failure than the one being\n * fixed. It is read, recognised, and refused with a message that says how to\n * replace it — never silently treated as \"no default\", which would send the\n * user hunting for a setting they can see is set.\n */\n\nimport type { ContextConfig } from \"./config.js\";\nimport { getDefaultContext } from \"./config.js\";\nimport { printError } from \"./output.js\";\n\nexport interface ResolvedContext {\n\ttype: \"org\";\n\tslug: string;\n}\n\n/**\n * The same resolution as `resolveContext`, as a VALUE instead of an exit.\n *\n * `resolveContext` calls `printError`, which calls `process.exit` — correct\n * for a command a person is watching, and fatal to the session-start hook\n * contract in `commands/instructions`, which must never exit non-zero for\n * any reason. `process.exit` cannot be caught by the `try/catch` that owns\n * that contract, so a stored personal default (or a stale\n * `FABRIC_PERSONAL=1`) took the whole process down with code 2 before the\n * boundary ever saw it.\n *\n * `resolveContext` below is a thin exiting wrapper over it, so the two cannot\n * drift.\n */\ntype ContextResolution =\n\t| { ok: true; context: ResolvedContext | undefined }\n\t| { ok: false; message: string; exitCode: number };\n\nconst PERSONAL_RETIRED_HINT =\n\t\"selects personal context, which no longer exists — every command runs inside an organization.\\n\" +\n\t\"Name one with --org <slug>, or set a default with:\\n fabric ctx use org <slug>\";\n\nfunction tryResolveContext(\n\tpersonal: boolean | undefined,\n\torg: string | undefined,\n\trequired = true,\n): ContextResolution {\n\tif (personal) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\tmessage: `--personal ${PERSONAL_RETIRED_HINT}`,\n\t\t\texitCode: 2,\n\t\t};\n\t}\n\tif (org) {\n\t\treturn { ok: true, context: { type: \"org\", slug: org } };\n\t}\n\n\tconst stored: ContextConfig | undefined = getDefaultContext();\n\tif (stored?.type === \"personal\") {\n\t\tconst source =\n\t\t\tprocess.env.FABRIC_PERSONAL === \"1\"\n\t\t\t\t? \"FABRIC_PERSONAL=1\"\n\t\t\t\t: \"Your stored default context\";\n\t\treturn {\n\t\t\tok: false,\n\t\t\tmessage: `${source} ${PERSONAL_RETIRED_HINT}`,\n\t\t\texitCode: 2,\n\t\t};\n\t}\n\tif (stored?.type === \"org\") {\n\t\treturn { ok: true, context: { type: \"org\", slug: stored.slug } };\n\t}\n\n\tif (required) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\tmessage:\n\t\t\t\t\"Context is required. Use --org <slug>, or set a default with:\\n fabric ctx use org <slug>\",\n\t\t\texitCode: 2,\n\t\t};\n\t}\n\n\treturn { ok: true, context: undefined };\n}\n\n/**\n * Resolves tenant context from CLI flags, env vars, or stored default.\n * Exits with code 2 when context is ambiguous or names a retired one.\n *\n * A thin wrapper over `tryResolveContext`, which holds the actual rules —\n * see there for why the non-exiting form exists.\n *\n * @param personal - value of the retired --personal flag\n * @param org - value of --org flag\n * @param required - if false, returns undefined when context is unset (for auth commands)\n */\nexport function resolveContext(\n\tpersonal: boolean | undefined,\n\torg: string | undefined,\n\trequired = true,\n): ResolvedContext | undefined {\n\tconst resolution = tryResolveContext(personal, org, required);\n\tif (!resolution.ok) {\n\t\tprintError(resolution.message, resolution.exitCode);\n\t}\n\treturn resolution.context;\n}\n","/**\n * fabric auth keys\n *\n * fabric auth keys list\n * fabric auth keys create --name \"CI deploy\" --scopes workflows:run,agents:read\n * fabric auth keys revoke <id>\n */\n\nimport { Command } from \"commander\";\nimport { getClient } from \"../../lib/client.js\";\nimport { printError, printOutput, printSuccess } from \"../../lib/output.js\";\n\nexport function buildKeysCommand(): Command {\n\tconst keys = new Command(\"keys\").description(\"Manage API keys\");\n\n\t// -- list ----------------------------------------------------------------\n\tkeys.command(\"list\")\n\t\t.description(\"List your API keys\")\n\t\t.option(\n\t\t\t\"--format <format>\",\n\t\t\t\"Output format: table|json|yaml|csv\",\n\t\t\t\"table\",\n\t\t)\n\t\t.action(async (opts: { format: string }) => {\n\t\t\tconst client = getClient();\n\t\t\tlet list: Awaited<ReturnType<typeof client.auth.listKeys>>;\n\t\t\ttry {\n\t\t\t\tlist = await client.auth.listKeys();\n\t\t\t} catch (err: unknown) {\n\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t}\n\t\t\tprintOutput(list, {\n\t\t\t\tformat: opts.format as \"table\" | \"json\" | \"yaml\" | \"csv\",\n\t\t\t\tcolumns: [\n\t\t\t\t\t\"id\",\n\t\t\t\t\t\"name\",\n\t\t\t\t\t\"keyPrefix\",\n\t\t\t\t\t\"scopes\",\n\t\t\t\t\t\"lastUsedAt\",\n\t\t\t\t\t\"expiresAt\",\n\t\t\t\t\t\"createdAt\",\n\t\t\t\t],\n\t\t\t});\n\t\t});\n\n\t// -- create --------------------------------------------------------------\n\tkeys.command(\"create\")\n\t\t.description(\"Create a new API key (raw key shown only once)\")\n\t\t.requiredOption(\"-n, --name <name>\", \"Key name\")\n\t\t.option(\n\t\t\t\"-s, --scopes <scopes>\",\n\t\t\t\"Comma-separated scopes (e.g. projects:read,workflows:run)\",\n\t\t\t\"orgs:read\",\n\t\t)\n\t\t.option(\n\t\t\t\"-e, --expires <days>\",\n\t\t\t\"Days until expiry (1–365, omit for no expiry)\",\n\t\t)\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (opts: {\n\t\t\t\tname: string;\n\t\t\t\tscopes: string;\n\t\t\t\texpires?: string;\n\t\t\t\tformat: string;\n\t\t\t}) => {\n\t\t\t\tconst client = getClient();\n\t\t\t\tconst scopes = opts.scopes.split(\",\").map((s) => s.trim());\n\t\t\t\tconst expiresInDays = opts.expires\n\t\t\t\t\t? Number.parseInt(opts.expires, 10)\n\t\t\t\t\t: undefined;\n\n\t\t\t\tif (\n\t\t\t\t\texpiresInDays !== undefined &&\n\t\t\t\t\tNumber.isNaN(expiresInDays)\n\t\t\t\t) {\n\t\t\t\t\tprintError(\"--expires must be a number\", 2);\n\t\t\t\t}\n\n\t\t\t\tlet created: Awaited<ReturnType<typeof client.auth.createKey>>;\n\t\t\t\ttry {\n\t\t\t\t\tcreated = await client.auth.createKey({\n\t\t\t\t\t\tname: opts.name,\n\t\t\t\t\t\tscopes,\n\t\t\t\t\t\texpiresInDays,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(created, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprocess.stdout.write(\"\\n\");\n\t\t\t\tprintSuccess(`API key created: ${created.name}`);\n\t\t\t\tprocess.stdout.write(`\\n Key: ${created.rawKey}\\n`);\n\t\t\t\tprocess.stdout.write(` Prefix: ${created.keyPrefix}\\n`);\n\t\t\t\tprocess.stdout.write(\n\t\t\t\t\t` Scopes: ${created.scopes.join(\", \")}\\n`,\n\t\t\t\t);\n\t\t\t\tif (created.expiresAt) {\n\t\t\t\t\tprocess.stdout.write(\n\t\t\t\t\t\t` Expires: ${String(created.expiresAt).slice(0, 10)}\\n`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tprocess.stdout.write(\n\t\t\t\t\t\"\\n ⚠ Store this key now — it will never be shown again.\\n\\n\",\n\t\t\t\t);\n\t\t\t},\n\t\t);\n\n\t// -- revoke --------------------------------------------------------------\n\tkeys.command(\"revoke <id>\")\n\t\t.description(\"Permanently revoke an API key\")\n\t\t.action(async (id: string) => {\n\t\t\tconst client = getClient();\n\t\t\ttry {\n\t\t\t\tawait client.auth.revokeKey(id);\n\t\t\t} catch (err: unknown) {\n\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t}\n\t\t\tprintSuccess(`API key ${id} revoked.`);\n\t\t});\n\n\treturn keys;\n}\n","/**\n * fabric auth login\n *\n * Stores an API key for subsequent commands.\n *\n * fabric auth login --key fab_...\n * fabric auth login (prompts interactively)\n */\n\nimport * as readline from \"node:readline\";\nimport { FabricAuthError, FabricClient, FabricError } from \"@fabricorg/sdk\";\nimport { Command } from \"commander\";\nimport { getBaseUrl, saveApiKey } from \"../../lib/config.js\";\nimport { printError, printSuccess } from \"../../lib/output.js\";\n\nconst DEFAULT_BASE_URL = \"https://fabric.pro\";\n\nfunction displayBaseUrl(baseUrl: string): string {\n\ttry {\n\t\treturn new URL(baseUrl).origin;\n\t} catch {\n\t\treturn \"the configured Fabric deployment\";\n\t}\n}\n\nasync function promptApiKey(): Promise<string> {\n\tconst rl = readline.createInterface({\n\t\tinput: process.stdin,\n\t\toutput: process.stdout,\n\t});\n\n\treturn new Promise((resolve) => {\n\t\t// Don't echo the key\n\t\tprocess.stdout.write(\"Fabric API Key: \");\n\t\tprocess.stdin.resume();\n\t\tprocess.stdin.setEncoding(\"utf8\");\n\n\t\tlet key = \"\";\n\t\tprocess.stdin.once(\"data\", (chunk) => {\n\t\t\tkey = String(chunk).trim();\n\t\t\tprocess.stdout.write(\"\\n\");\n\t\t\trl.close();\n\t\t\tresolve(key);\n\t\t});\n\t});\n}\n\nexport function buildLoginCommand(): Command {\n\treturn new Command(\"login\")\n\t\t.description(\"Authenticate with a Fabric API key\")\n\t\t.option(\"-k, --key <api-key>\", \"API key (fab_... or org_...)\")\n\t\t.option(\"--base-url <url>\", \"Override the Fabric base URL\")\n\t\t.action(async (opts: { key?: string; baseUrl?: string }) => {\n\t\t\tlet apiKey = opts.key?.trim();\n\n\t\t\tif (!apiKey) {\n\t\t\t\tapiKey = await promptApiKey();\n\t\t\t}\n\n\t\t\tif (!apiKey) {\n\t\t\t\tprintError(\"API key is required\", 2);\n\t\t\t}\n\n\t\t\tif (!apiKey.startsWith(\"fab_\") && !apiKey.startsWith(\"org_\")) {\n\t\t\t\tprintError(\n\t\t\t\t\t\"Invalid API key format. Keys must start with fab_ or org_\",\n\t\t\t\t\t2,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Verify the key works before saving\n\t\t\tconst baseUrl = opts.baseUrl ?? getBaseUrl();\n\t\t\tconst effectiveBaseUrl = displayBaseUrl(\n\t\t\t\tbaseUrl ?? DEFAULT_BASE_URL,\n\t\t\t);\n\t\t\tconst client = new FabricClient({ apiKey, baseUrl });\n\n\t\t\tlet name: string;\n\t\t\tlet email: string;\n\t\t\ttry {\n\t\t\t\tconst me = await client.auth.whoami();\n\t\t\t\tname = me.user.name ?? me.user.email;\n\t\t\t\temail = me.user.email;\n\t\t\t} catch (error) {\n\t\t\t\tif (\n\t\t\t\t\terror instanceof FabricAuthError ||\n\t\t\t\t\t(error instanceof FabricError && error.status === 401)\n\t\t\t\t) {\n\t\t\t\t\tprintError(\n\t\t\t\t\t\t\"Authentication failed. Check that the key is valid and not expired.\",\n\t\t\t\t\t\t3,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tif (error instanceof FabricError && error.status > 0) {\n\t\t\t\t\tprintError(\n\t\t\t\t\t\t`Authentication request to ${effectiveBaseUrl} failed with HTTP ${error.status}.`,\n\t\t\t\t\t\t3,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tprintError(\n\t\t\t\t\t`Could not connect to ${effectiveBaseUrl}. Check that the deployment URL is correct and reachable.`,\n\t\t\t\t\t3,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// An environment override selects the verification target for this\n\t\t\t// invocation only. Persist a deployment only when the person supplied\n\t\t\t// `--base-url`, so FABRIC_BASE_URL remains an explicit override.\n\t\t\tsaveApiKey(apiKey, {\n\t\t\t\t...(opts.baseUrl === undefined\n\t\t\t\t\t? {}\n\t\t\t\t\t: { baseUrl: opts.baseUrl }),\n\t\t\t});\n\t\t\tprintSuccess(`Authenticated as ${name} (${email})`);\n\t\t});\n}\n","/**\n * fabric auth logout\n * Removes the stored API key from config.\n */\n\nimport { Command } from \"commander\";\nimport { clearApiKey, getApiKey } from \"../../lib/config.js\";\nimport { printSuccess, printWarning } from \"../../lib/output.js\";\n\nexport function buildLogoutCommand(): Command {\n\treturn new Command(\"logout\")\n\t\t.description(\"Remove stored API key\")\n\t\t.action(() => {\n\t\t\tif (!getApiKey()) {\n\t\t\t\tprintWarning(\"No API key stored — already logged out.\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tclearApiKey();\n\t\t\tprintSuccess(\"Logged out. API key removed.\");\n\t\t});\n}\n","/**\n * fabric auth whoami\n * Prints the authenticated identity and org memberships.\n */\n\nimport { Command } from \"commander\";\nimport { getClient } from \"../../lib/client.js\";\nimport { printError, printOutput, printRecord } from \"../../lib/output.js\";\n\nexport function buildWhoamiCommand(): Command {\n\treturn new Command(\"whoami\")\n\t\t.description(\"Show current authentication and identity\")\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(async (opts: { format: string }) => {\n\t\t\tconst client = getClient();\n\n\t\t\tlet me: Awaited<ReturnType<typeof client.auth.whoami>>;\n\t\t\ttry {\n\t\t\t\tme = await client.auth.whoami();\n\t\t\t} catch (err: unknown) {\n\t\t\t\tprintError((err as Error).message ?? \"Request failed\", 3);\n\t\t\t}\n\n\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\n\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\tprintOutput(me, { format: fmt });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Human-readable\n\t\t\tprintRecord({\n\t\t\t\tUser: me.user.name ?? \"(no name)\",\n\t\t\t\tEmail: me.user.email,\n\t\t\t\tRole: me.user.role,\n\t\t\t\t\"Key type\": me.keyType,\n\t\t\t\t\"Key prefix\": me.keyPrefix,\n\t\t\t\tScopes: me.scopes.join(\", \"),\n\t\t\t\t\"Orgs count\": String(me.orgs.length),\n\t\t\t\t\"Member since\": me.user.createdAt.slice(0, 10),\n\t\t\t});\n\n\t\t\tif (me.orgs.length > 0) {\n\t\t\t\tprocess.stdout.write(\"\\nOrganizations:\\n\");\n\t\t\t\tprintOutput(me.orgs, {\n\t\t\t\t\tformat: \"table\",\n\t\t\t\t\tcolumns: [\"name\", \"slug\", \"role\", \"joinedAt\"],\n\t\t\t\t});\n\t\t\t}\n\t\t});\n}\n","/**\n * fabric chats\n *\n * fabric chats list List AI chat sessions\n * fabric chats show <id> Show chat details\n */\n\nimport type { FabricChat } from \"@fabricorg/sdk\";\nimport { Command } from \"commander\";\nimport { getClient } from \"../../lib/client.js\";\nimport { resolveContext } from \"../../lib/context.js\";\nimport { printError, printOutput, printRecord } from \"../../lib/output.js\";\n\nexport function buildChatsCommand(): Command {\n\tconst chats = new Command(\"chats\").description(\"Manage AI chat sessions\");\n\n\tchats\n\t\t.command(\"list\")\n\t\t.description(\"List AI chat sessions\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--limit <n>\", \"Max results (default 20)\", \"20\")\n\t\t.option(\n\t\t\t\"--format <format>\",\n\t\t\t\"Output format: table|json|yaml|csv\",\n\t\t\t\"table\",\n\t\t)\n\t\t.option(\"-q, --quiet\", \"Print IDs only\")\n\t\t.action(\n\t\t\tasync (opts: {\n\t\t\t\torg?: string;\n\t\t\t\tpersonal?: boolean;\n\t\t\t\tlimit: string;\n\t\t\t\tformat: string;\n\t\t\t\tquiet?: boolean;\n\t\t\t}) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet list: FabricChat[];\n\t\t\t\ttry {\n\t\t\t\t\tlist = await client.chats.list({\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t\tlimit: Number(opts.limit),\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tif (opts.quiet) {\n\t\t\t\t\tfor (const c of list) {\n\t\t\t\t\t\tprocess.stdout.write(`${c.id}\\n`);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintOutput(list, {\n\t\t\t\t\tformat: opts.format as \"table\" | \"json\" | \"yaml\" | \"csv\",\n\t\t\t\t\tcolumns: [\"id\", \"title\", \"updatedAt\"],\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\tchats\n\t\t.command(\"show <id>\")\n\t\t.description(\"Show chat details\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tid: string,\n\t\t\t\topts: { org?: string; personal?: boolean; format: string },\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet chat: FabricChat;\n\t\t\t\ttry {\n\t\t\t\t\tchat = await client.chats.get(id, {\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(chat, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintRecord({\n\t\t\t\t\tID: chat.id,\n\t\t\t\t\tTitle: chat.title ?? \"(untitled)\",\n\t\t\t\t\tUpdated: chat.updatedAt.slice(0, 16).replace(\"T\", \" \"),\n\t\t\t\t\tCreated: chat.createdAt.slice(0, 10),\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\treturn chats;\n}\n","/**\n * fabric completion\n *\n * fabric completion bash Output bash completion script\n * fabric completion zsh Output zsh completion script\n * fabric completion fish Output fish completion script\n */\n\nimport { Command } from \"commander\";\n\nconst BASH_COMPLETION = `\n# fabric bash completion\n_fabric_completion() {\n local cur prev words cword\n _init_completion || return\n\n local commands=\"auth ctx orgs projects features workflows prompts agents skills mcp frames workspaces chats reports config completion\"\n\n case \"$prev\" in\n fabric)\n COMPREPLY=($(compgen -W \"$commands\" -- \"$cur\"))\n return ;;\n auth)\n COMPREPLY=($(compgen -W \"login logout whoami keys\" -- \"$cur\"))\n return ;;\n keys)\n COMPREPLY=($(compgen -W \"list create revoke\" -- \"$cur\"))\n return ;;\n ctx)\n COMPREPLY=($(compgen -W \"current use\" -- \"$cur\"))\n return ;;\n orgs)\n COMPREPLY=($(compgen -W \"list show\" -- \"$cur\"))\n return ;;\n projects)\n COMPREPLY=($(compgen -W \"list show create update\" -- \"$cur\"))\n return ;;\n features)\n COMPREPLY=($(compgen -W \"list show create update tasks\" -- \"$cur\"))\n return ;;\n workflows)\n COMPREPLY=($(compgen -W \"list show trigger status\" -- \"$cur\"))\n return ;;\n prompts)\n COMPREPLY=($(compgen -W \"list get create update\" -- \"$cur\"))\n return ;;\n agents)\n COMPREPLY=($(compgen -W \"list show execute\" -- \"$cur\"))\n return ;;\n skills)\n COMPREPLY=($(compgen -W \"list show\" -- \"$cur\"))\n return ;;\n mcp)\n COMPREPLY=($(compgen -W \"servers configs\" -- \"$cur\"))\n return ;;\n configs)\n COMPREPLY=($(compgen -W \"list show delete\" -- \"$cur\"))\n return ;;\n frames)\n COMPREPLY=($(compgen -W \"list show\" -- \"$cur\"))\n return ;;\n workspaces)\n COMPREPLY=($(compgen -W \"list show\" -- \"$cur\"))\n return ;;\n chats)\n COMPREPLY=($(compgen -W \"list show\" -- \"$cur\"))\n return ;;\n reports)\n COMPREPLY=($(compgen -W \"templates executions\" -- \"$cur\"))\n return ;;\n templates)\n COMPREPLY=($(compgen -W \"list show\" -- \"$cur\"))\n return ;;\n executions)\n COMPREPLY=($(compgen -W \"list\" -- \"$cur\"))\n return ;;\n completion)\n COMPREPLY=($(compgen -W \"bash zsh fish\" -- \"$cur\"))\n return ;;\n esac\n\n COMPREPLY=($(compgen -W \"--format --org --personal --quiet --help\" -- \"$cur\"))\n}\n\ncomplete -F _fabric_completion fabric\n`.trim();\n\nconst ZSH_COMPLETION = `\n#compdef fabric\n\n_fabric() {\n local state\n\n _arguments \\\\\n '--format[Output format]:format:(table json yaml csv)' \\\\\n '--version[Show version]' \\\\\n '--help[Show help]' \\\\\n '1: :->command' \\\\\n '*: :->args'\n\n case $state in\n command)\n local commands=(\n 'auth:Authenticate and manage API keys'\n 'ctx:Manage active context'\n 'orgs:List organizations'\n 'projects:Manage projects'\n 'features:Manage project features'\n 'workflows:Manage workflows'\n 'prompts:Manage prompts'\n 'agents:Manage agents'\n 'skills:Browse skills'\n 'mcp:Manage MCP servers and configs'\n 'frames:Manage AI-generated frames'\n 'workspaces:Manage workspaces'\n 'chats:View AI chat history'\n 'reports:Manage reports'\n 'config:Show CLI configuration'\n 'completion:Output shell completion script'\n )\n _describe 'command' commands\n ;;\n args)\n case $words[2] in\n auth)\n local subcmds=('login:Log in' 'logout:Log out' 'whoami:Show current user' 'keys:Manage API keys')\n _describe 'subcommand' subcmds ;;\n projects)\n local subcmds=('list:List projects' 'show:Show project' 'create:Create project' 'update:Update project')\n _describe 'subcommand' subcmds ;;\n features)\n local subcmds=('list:List features' 'show:Show feature' 'create:Create feature' 'update:Update feature' 'tasks:List tasks')\n _describe 'subcommand' subcmds ;;\n workflows)\n local subcmds=('list:List workflows' 'show:Show workflow' 'trigger:Trigger workflow' 'status:Check status')\n _describe 'subcommand' subcmds ;;\n prompts)\n local subcmds=('list:List prompts' 'get:Get prompt' 'create:Create prompt' 'update:Update prompt')\n _describe 'subcommand' subcmds ;;\n agents)\n local subcmds=('list:List agents' 'show:Show agent' 'execute:Execute agent')\n _describe 'subcommand' subcmds ;;\n mcp)\n local subcmds=('servers:List MCP servers' 'configs:Manage MCP configs')\n _describe 'subcommand' subcmds ;;\n frames)\n local subcmds=('list:List frames' 'show:Show frame')\n _describe 'subcommand' subcmds ;;\n workspaces)\n local subcmds=('list:List workspaces' 'show:Show workspace')\n _describe 'subcommand' subcmds ;;\n skills)\n local subcmds=('list:List skills' 'show:Show skill')\n _describe 'subcommand' subcmds ;;\n chats)\n local subcmds=('list:List chats' 'show:Show chat')\n _describe 'subcommand' subcmds ;;\n reports)\n local subcmds=('templates:Manage report templates' 'executions:List report executions')\n _describe 'subcommand' subcmds ;;\n completion)\n local subcmds=('bash:Bash completion' 'zsh:Zsh completion' 'fish:Fish completion')\n _describe 'subcommand' subcmds ;;\n esac ;;\n esac\n}\n\n_fabric \"$@\"\n`.trim();\n\nconst FISH_COMPLETION = `\n# fabric fish completion\nset -l fabric_commands auth ctx orgs projects features workflows prompts agents skills mcp frames workspaces chats reports config completion\n\ncomplete -c fabric -f\n\n# Top-level commands\ncomplete -c fabric -n '__fish_use_subcommand' -a auth -d 'Authenticate and manage API keys'\ncomplete -c fabric -n '__fish_use_subcommand' -a ctx -d 'Manage active context'\ncomplete -c fabric -n '__fish_use_subcommand' -a orgs -d 'List organizations'\ncomplete -c fabric -n '__fish_use_subcommand' -a projects -d 'Manage projects'\ncomplete -c fabric -n '__fish_use_subcommand' -a features -d 'Manage project features'\ncomplete -c fabric -n '__fish_use_subcommand' -a workflows -d 'Manage workflows'\ncomplete -c fabric -n '__fish_use_subcommand' -a prompts -d 'Manage prompts'\ncomplete -c fabric -n '__fish_use_subcommand' -a agents -d 'Manage agents'\ncomplete -c fabric -n '__fish_use_subcommand' -a skills -d 'Browse skills'\ncomplete -c fabric -n '__fish_use_subcommand' -a mcp -d 'Manage MCP servers and configs'\ncomplete -c fabric -n '__fish_use_subcommand' -a frames -d 'Manage AI-generated frames'\ncomplete -c fabric -n '__fish_use_subcommand' -a workspaces -d 'Manage workspaces'\ncomplete -c fabric -n '__fish_use_subcommand' -a chats -d 'View AI chat history'\ncomplete -c fabric -n '__fish_use_subcommand' -a reports -d 'Manage reports'\ncomplete -c fabric -n '__fish_use_subcommand' -a config -d 'Show CLI configuration'\ncomplete -c fabric -n '__fish_use_subcommand' -a completion -d 'Output shell completion script'\n\n# Subcommands\ncomplete -c fabric -n '__fish_seen_subcommand_from auth' -a 'login logout whoami keys'\ncomplete -c fabric -n '__fish_seen_subcommand_from ctx' -a 'current use'\ncomplete -c fabric -n '__fish_seen_subcommand_from orgs' -a 'list show'\ncomplete -c fabric -n '__fish_seen_subcommand_from projects' -a 'list show create update'\ncomplete -c fabric -n '__fish_seen_subcommand_from features' -a 'list show create update tasks'\ncomplete -c fabric -n '__fish_seen_subcommand_from workflows' -a 'list show trigger status'\ncomplete -c fabric -n '__fish_seen_subcommand_from prompts' -a 'list get create update'\ncomplete -c fabric -n '__fish_seen_subcommand_from agents' -a 'list show execute'\ncomplete -c fabric -n '__fish_seen_subcommand_from skills' -a 'list show'\ncomplete -c fabric -n '__fish_seen_subcommand_from mcp' -a 'servers configs'\ncomplete -c fabric -n '__fish_seen_subcommand_from configs' -a 'list show delete'\ncomplete -c fabric -n '__fish_seen_subcommand_from frames' -a 'list show'\ncomplete -c fabric -n '__fish_seen_subcommand_from workspaces' -a 'list show'\ncomplete -c fabric -n '__fish_seen_subcommand_from chats' -a 'list show'\ncomplete -c fabric -n '__fish_seen_subcommand_from reports' -a 'templates executions'\ncomplete -c fabric -n '__fish_seen_subcommand_from templates' -a 'list show'\ncomplete -c fabric -n '__fish_seen_subcommand_from executions' -a 'list'\ncomplete -c fabric -n '__fish_seen_subcommand_from completion' -a 'bash zsh fish'\n\n# Common flags\ncomplete -c fabric -l format -d 'Output format' -a 'table json yaml csv'\ncomplete -c fabric -l org -d 'Organization context' -r\ncomplete -c fabric -l personal -d 'Personal context'\ncomplete -c fabric -s q -l quiet -d 'Quiet output'\ncomplete -c fabric -l help -d 'Show help'\n`.trim();\n\nexport function buildCompletionCommand(): Command {\n\tconst completion = new Command(\"completion\").description(\n\t\t\"Output shell completion script\",\n\t);\n\n\tcompletion\n\t\t.command(\"bash\")\n\t\t.description(\"Output bash completion script\")\n\t\t.action(() => {\n\t\t\tprocess.stdout.write(`${BASH_COMPLETION}\\n`);\n\t\t\tprocess.stderr.write(\n\t\t\t\t'# Add to ~/.bashrc:\\n# eval \"$(fabric completion bash)\"\\n',\n\t\t\t);\n\t\t});\n\n\tcompletion\n\t\t.command(\"zsh\")\n\t\t.description(\"Output zsh completion script\")\n\t\t.action(() => {\n\t\t\tprocess.stdout.write(`${ZSH_COMPLETION}\\n`);\n\t\t\tprocess.stderr.write(\n\t\t\t\t'# Add to ~/.zshrc:\\n# eval \"$(fabric completion zsh)\"\\n',\n\t\t\t);\n\t\t});\n\n\tcompletion\n\t\t.command(\"fish\")\n\t\t.description(\"Output fish completion script\")\n\t\t.action(() => {\n\t\t\tprocess.stdout.write(`${FISH_COMPLETION}\\n`);\n\t\t\tprocess.stderr.write(\n\t\t\t\t\"# Save to ~/.config/fish/completions/fabric.fish\\n\",\n\t\t\t);\n\t\t});\n\n\treturn completion;\n}\n","/**\n * fabric ctx\n *\n * fabric ctx current Show active context\n * fabric ctx use org <slug> Set an org as default\n *\n * `use personal` is retired (Fizzy #1875, PO-9). It is still REGISTERED rather\n * than deleted, so someone who types it — or has it in a script — is told what\n * replaced it instead of meeting \"unknown command\". A config written by an\n * earlier version can still hold a personal default; `current` reports it as\n * needing replacing rather than printing it as if it still worked.\n */\n\nimport { Command } from \"commander\";\nimport { getDefaultContext, saveDefaultContext } from \"../../lib/config.js\";\nimport { printError, printSuccess, printWarning } from \"../../lib/output.js\";\n\nexport function buildCtxCommand(): Command {\n\tconst ctx = new Command(\"ctx\").description(\n\t\t\"Manage the organization commands run in\",\n\t);\n\n\t// -- current ------------------------------------------------------------\n\tctx.command(\"current\")\n\t\t.description(\"Show the active default context\")\n\t\t.action(() => {\n\t\t\tconst stored = getDefaultContext();\n\t\t\tif (!stored) {\n\t\t\t\tprintWarning(\n\t\t\t\t\t\"No default context set. Use --org <slug> on each command, or run:\\n fabric ctx use org <slug>\",\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (stored.type === \"personal\") {\n\t\t\t\t// Reported, not hidden: it is set, the user can see it is set,\n\t\t\t\t// and saying \"none\" would send them looking for a setting that\n\t\t\t\t// is right there.\n\t\t\t\tprintWarning(\n\t\t\t\t\t\"Context: personal — retired, and no command will accept it.\\nReplace it with:\\n fabric ctx use org <slug>\",\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tprocess.stdout.write(`Context: org:${stored.slug}\\n`);\n\t\t});\n\n\t// -- use ----------------------------------------------------------------\n\tconst use = new Command(\"use\").description(\n\t\t\"Set the default organization for commands\",\n\t);\n\n\tuse.command(\"personal\")\n\t\t.description(\"Retired — context is organization-only\")\n\t\t.action(() => {\n\t\t\tprintError(\n\t\t\t\t\"Personal context no longer exists — every command runs inside an organization.\\nSet one with:\\n fabric ctx use org <slug>\",\n\t\t\t\t2,\n\t\t\t);\n\t\t});\n\n\tuse.command(\"org <slug>\")\n\t\t.description(\"Use an org context by default\")\n\t\t.action((slug: string) => {\n\t\t\tsaveDefaultContext({ type: \"org\", slug });\n\t\t\tprintSuccess(`Default context set to: org:${slug}`);\n\t\t});\n\n\tctx.addCommand(use);\n\n\treturn ctx;\n}\n","/**\n * fabric features\n *\n * fabric features list --project <id> List features in a project\n * fabric features show --project <id> <id> Show feature details\n * fabric features create --project <id> <title> Create a feature\n */\n\nimport type { FabricFeature } from \"@fabricorg/sdk\";\nimport { Command } from \"commander\";\nimport { getClient } from \"../../lib/client.js\";\nimport { resolveContext } from \"../../lib/context.js\";\nimport {\n\tprintError,\n\tprintOutput,\n\tprintRecord,\n\tprintSuccess,\n} from \"../../lib/output.js\";\n\nexport function buildFeaturesCommand(): Command {\n\tconst features = new Command(\"features\").description(\n\t\t\"Manage project features\",\n\t);\n\n\t// -- list ----------------------------------------------------------------\n\tfeatures\n\t\t.command(\"list\")\n\t\t.description(\"List features in a project\")\n\t\t.requiredOption(\"-p, --project <id>\", \"Project ID\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\n\t\t\t\"--priority <priority>\",\n\t\t\t\"Filter: P0_CRITICAL|P1_HIGH|P2_MEDIUM|P3_LOW\",\n\t\t)\n\t\t.option(\"--search <query>\", \"Search by title\")\n\t\t.option(\"--limit <n>\", \"Max results (default 50)\", \"50\")\n\t\t.option(\n\t\t\t\"--format <format>\",\n\t\t\t\"Output format: table|json|yaml|csv\",\n\t\t\t\"table\",\n\t\t)\n\t\t.option(\"-q, --quiet\", \"Print IDs only\")\n\t\t.action(\n\t\t\tasync (opts: {\n\t\t\t\tproject: string;\n\t\t\t\torg?: string;\n\t\t\t\tpersonal?: boolean;\n\t\t\t\tpriority?: string;\n\t\t\t\tsearch?: string;\n\t\t\t\tlimit: string;\n\t\t\t\tformat: string;\n\t\t\t\tquiet?: boolean;\n\t\t\t}) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet list: FabricFeature[];\n\t\t\t\ttry {\n\t\t\t\t\tlist = await client.projects.listFeatures(opts.project, {\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t\tpriority: opts.priority as\n\t\t\t\t\t\t\t| FabricFeature[\"priority\"]\n\t\t\t\t\t\t\t| undefined,\n\t\t\t\t\t\tsearch: opts.search,\n\t\t\t\t\t\tlimit: Number(opts.limit),\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tif (opts.quiet) {\n\t\t\t\t\tfor (const f of list) {\n\t\t\t\t\t\tprocess.stdout.write(`${f.id}\\n`);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintOutput(list, {\n\t\t\t\t\tformat: opts.format as \"table\" | \"json\" | \"yaml\" | \"csv\",\n\t\t\t\t\tcolumns: [\"identifier\", \"title\", \"priority\", \"createdAt\"],\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\t// -- show ----------------------------------------------------------------\n\tfeatures\n\t\t.command(\"show <id>\")\n\t\t.description(\"Show feature details\")\n\t\t.requiredOption(\"-p, --project <projectId>\", \"Project ID\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tid: string,\n\t\t\t\topts: {\n\t\t\t\t\tproject: string;\n\t\t\t\t\torg?: string;\n\t\t\t\t\tpersonal?: boolean;\n\t\t\t\t\tformat: string;\n\t\t\t\t},\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet feature: FabricFeature;\n\t\t\t\ttry {\n\t\t\t\t\tfeature = await client.projects.getFeature(\n\t\t\t\t\t\topts.project,\n\t\t\t\t\t\tid,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(feature, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintRecord({\n\t\t\t\t\tID: feature.id,\n\t\t\t\t\tIdentifier: feature.identifier,\n\t\t\t\t\tTitle: feature.title,\n\t\t\t\t\tPriority: feature.priority,\n\t\t\t\t\tDescription: feature.description ?? \"(none)\",\n\t\t\t\t\t\"Acceptance Criteria\":\n\t\t\t\t\t\tfeature.acceptanceCriteria ?? \"(none)\",\n\t\t\t\t\tProject: feature.projectId,\n\t\t\t\t\tAssignee: feature.assigneeId ?? \"(none)\",\n\t\t\t\t\tCreated: feature.createdAt.slice(0, 10),\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\t// -- create --------------------------------------------------------------\n\tfeatures\n\t\t.command(\"create <title>\")\n\t\t.description(\"Create a feature in a project\")\n\t\t.requiredOption(\"-p, --project <projectId>\", \"Project ID\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"-d, --description <text>\", \"Feature description\")\n\t\t.option(\n\t\t\t\"--priority <priority>\",\n\t\t\t\"Priority: P0_CRITICAL|P1_HIGH|P2_MEDIUM|P3_LOW (default: P2_MEDIUM)\",\n\t\t)\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\ttitle: string,\n\t\t\t\topts: {\n\t\t\t\t\tproject: string;\n\t\t\t\t\torg?: string;\n\t\t\t\t\tpersonal?: boolean;\n\t\t\t\t\tdescription?: string;\n\t\t\t\t\tpriority?: string;\n\t\t\t\t\tformat: string;\n\t\t\t\t},\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet feature: FabricFeature;\n\t\t\t\ttry {\n\t\t\t\t\tfeature = await client.projects.createFeature(\n\t\t\t\t\t\topts.project,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttitle,\n\t\t\t\t\t\t\tdescription: opts.description,\n\t\t\t\t\t\t\tpriority: opts.priority as\n\t\t\t\t\t\t\t\t| FabricFeature[\"priority\"]\n\t\t\t\t\t\t\t\t| undefined,\n\t\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(feature, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintSuccess(`Feature ${feature.identifier} created`);\n\t\t\t\tprintRecord({\n\t\t\t\t\tID: feature.id,\n\t\t\t\t\tIdentifier: feature.identifier,\n\t\t\t\t\tTitle: feature.title,\n\t\t\t\t\tPriority: feature.priority,\n\t\t\t\t\tProject: feature.projectId,\n\t\t\t\t\tCreated: feature.createdAt.slice(0, 10),\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\t// -- tasks ---------------------------------------------------------------\n\tfeatures\n\t\t.command(\"tasks\")\n\t\t.description(\"List tasks (sub-items) for a feature\")\n\t\t.requiredOption(\"-p, --project <projectId>\", \"Project ID\")\n\t\t.requiredOption(\"-f, --feature <featureId>\", \"Feature ID\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\n\t\t\t\"--format <format>\",\n\t\t\t\"Output format: table|json|yaml|csv\",\n\t\t\t\"table\",\n\t\t)\n\t\t.option(\"-q, --quiet\", \"Print IDs only\")\n\t\t.action(\n\t\t\tasync (opts: {\n\t\t\t\tproject: string;\n\t\t\t\tfeature: string;\n\t\t\t\torg?: string;\n\t\t\t\tpersonal?: boolean;\n\t\t\t\tformat: string;\n\t\t\t\tquiet?: boolean;\n\t\t\t}) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet tasks: import(\"@fabricorg/sdk\").FabricTask[];\n\t\t\t\ttry {\n\t\t\t\t\ttasks = await client.projects.listTasks(\n\t\t\t\t\t\topts.project,\n\t\t\t\t\t\topts.feature,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tif (opts.quiet) {\n\t\t\t\t\tfor (const t of tasks) {\n\t\t\t\t\t\tprocess.stdout.write(`${t.id}\\n`);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintOutput(tasks, {\n\t\t\t\t\tformat: opts.format as \"table\" | \"json\" | \"yaml\" | \"csv\",\n\t\t\t\t\tcolumns: [\n\t\t\t\t\t\t\"identifier\",\n\t\t\t\t\t\t\"title\",\n\t\t\t\t\t\t\"status\",\n\t\t\t\t\t\t\"estimatedHours\",\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\t// -- update --------------------------------------------------------------\n\tfeatures\n\t\t.command(\"update <id>\")\n\t\t.description(\"Update a feature\")\n\t\t.requiredOption(\"-p, --project <projectId>\", \"Project ID\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--title <title>\", \"New title\")\n\t\t.option(\"-d, --description <text>\", \"New description\")\n\t\t.option(\n\t\t\t\"--priority <priority>\",\n\t\t\t\"Priority: P0_CRITICAL|P1_HIGH|P2_MEDIUM|P3_LOW\",\n\t\t)\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tid: string,\n\t\t\t\topts: {\n\t\t\t\t\tproject: string;\n\t\t\t\t\torg?: string;\n\t\t\t\t\tpersonal?: boolean;\n\t\t\t\t\ttitle?: string;\n\t\t\t\t\tdescription?: string;\n\t\t\t\t\tpriority?: string;\n\t\t\t\t\tformat: string;\n\t\t\t\t},\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet feature: FabricFeature;\n\t\t\t\ttry {\n\t\t\t\t\tfeature = await client.projects.updateFeature(\n\t\t\t\t\t\topts.project,\n\t\t\t\t\t\tid,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttitle: opts.title,\n\t\t\t\t\t\t\tdescription: opts.description,\n\t\t\t\t\t\t\tpriority: opts.priority as\n\t\t\t\t\t\t\t\t| FabricFeature[\"priority\"]\n\t\t\t\t\t\t\t\t| undefined,\n\t\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(feature, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintRecord({\n\t\t\t\t\tID: feature.id,\n\t\t\t\t\tIdentifier: feature.identifier,\n\t\t\t\t\tTitle: feature.title,\n\t\t\t\t\tPriority: feature.priority,\n\t\t\t\t\tUpdated: feature.updatedAt.slice(0, 10),\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\treturn features;\n}\n","/**\n * fabric frames\n *\n * fabric frames list List frames and slideshows\n * fabric frames show <id> Show frame details\n */\n\nimport type { FabricFrame } from \"@fabricorg/sdk\";\nimport { Command } from \"commander\";\nimport { getClient } from \"../../lib/client.js\";\nimport { resolveContext } from \"../../lib/context.js\";\nimport { printError, printOutput, printRecord } from \"../../lib/output.js\";\n\nexport function buildFramesCommand(): Command {\n\tconst frames = new Command(\"frames\").description(\n\t\t\"Manage AI-generated frames and slideshows\",\n\t);\n\n\t// -- list ----------------------------------------------------------------\n\tframes\n\t\t.command(\"list\")\n\t\t.description(\"List frames and slideshows\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--limit <n>\", \"Max results (default 50)\", \"50\")\n\t\t.option(\n\t\t\t\"--format <format>\",\n\t\t\t\"Output format: table|json|yaml|csv\",\n\t\t\t\"table\",\n\t\t)\n\t\t.option(\"-q, --quiet\", \"Print IDs only\")\n\t\t.action(\n\t\t\tasync (opts: {\n\t\t\t\torg?: string;\n\t\t\t\tpersonal?: boolean;\n\t\t\t\tlimit: string;\n\t\t\t\tformat: string;\n\t\t\t\tquiet?: boolean;\n\t\t\t}) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet list: FabricFrame[];\n\t\t\t\ttry {\n\t\t\t\t\tlist = await client.frames.list({\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t\tlimit: Number(opts.limit),\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tif (opts.quiet) {\n\t\t\t\t\tfor (const f of list) {\n\t\t\t\t\t\tprocess.stdout.write(`${f.id}\\n`);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintOutput(list, {\n\t\t\t\t\tformat: opts.format as \"table\" | \"json\" | \"yaml\" | \"csv\",\n\t\t\t\t\tcolumns: [\n\t\t\t\t\t\t\"id\",\n\t\t\t\t\t\t\"title\",\n\t\t\t\t\t\t\"fileType\",\n\t\t\t\t\t\t\"status\",\n\t\t\t\t\t\t\"isPublic\",\n\t\t\t\t\t\t\"updatedAt\",\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\t// -- show ----------------------------------------------------------------\n\tframes\n\t\t.command(\"show <id>\")\n\t\t.description(\"Show frame details\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tid: string,\n\t\t\t\topts: { org?: string; personal?: boolean; format: string },\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet frame: FabricFrame;\n\t\t\t\ttry {\n\t\t\t\t\tframe = await client.frames.get(id, {\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(frame, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintRecord({\n\t\t\t\t\tID: frame.id,\n\t\t\t\t\tTitle: frame.title,\n\t\t\t\t\tKind: frame.kind ?? \"(none)\",\n\t\t\t\t\t\"File Type\": frame.fileType,\n\t\t\t\t\tStatus: frame.status,\n\t\t\t\t\tPublic: frame.isPublic ? \"yes\" : \"no\",\n\t\t\t\t\t\"Share Token\": frame.shareToken ?? \"(none)\",\n\t\t\t\t\tDescription: frame.description ?? \"(none)\",\n\t\t\t\t\tUpdated: frame.updatedAt.slice(0, 10),\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\treturn frames;\n}\n","/**\n * fabric instructions\n *\n * fabric instructions check --project <id> Is the local copy current?\n * fabric instructions sync --project <id> Make it current.\n * fabric instructions init --project <id> --tool claude-code\n * Take the first copy, then write the session hook.\n *\n * The first file-writing commands in this CLI. Everything that touches the\n * filesystem lives in `lib/instructions/` as small testable modules; this\n * file is argument parsing, the sequence, and the words a developer reads.\n *\n * `--hook` is the contract that makes this safe to run at session start: it\n * NEVER exits non-zero, it has ONE absolute deadline covering every request\n * it makes, and it never prints more than it has to. A coding session that\n * cannot start because Fabric is unreachable would be a far worse failure\n * than instructions that are one version stale.\n */\nimport path from \"node:path\";\nimport type { FabricClient, PublishedInstructions } from \"@fabricorg/sdk\";\nimport { Command } from \"commander\";\nimport { getClient } from \"../../lib/client.js\";\nimport { getApiKey, getConfigPath } from \"../../lib/config.js\";\nimport { applyPlan } from \"../../lib/instructions/apply.js\";\nimport { extractBundle, fetchBundle } from \"../../lib/instructions/bundle.js\";\nimport {\n\tassertKeyStaysOutside,\n\tbuildHookCommand,\n\tCLAUDE_SETTINGS_RELATIVE_PATH,\n\tmergeSessionStartHook,\n} from \"../../lib/instructions/hook.js\";\nimport {\n\ttype InstructionsLock,\n\tLOCK_DIRECTORY,\n\tlockPath,\n\treadLock,\n\twriteLock,\n} from \"../../lib/instructions/lock.js\";\nimport {\n\tassertValidManifest,\n\tmaxArchiveBytes,\n} from \"../../lib/instructions/manifest.js\";\nimport {\n\tcomputeSyncPlan,\n\tnextLock,\n\ttype SyncPlan,\n\tverifyLedger,\n} from \"../../lib/instructions/plan.js\";\nimport {\n\tresolveDestinationRoot,\n\tresolveExistingRoot,\n} from \"../../lib/instructions/safe-write.js\";\nimport { printOutput } from \"../../lib/output.js\";\n\n/**\n * The whole of hook mode, end to end, including the bundle download.\n *\n * One ABSOLUTE deadline rather than one per request. The SDK's timeout is\n * per attempt and it retries twice by default, so three \"5 second\" calls\n * plus backoff is about 15.75 seconds — past the point where Claude Code\n * kills the hook itself, possibly mid-write. Retries are off in hook mode\n * and this bound covers everything.\n */\nconst HOOK_DEADLINE_MS = 10_000;\n\n/** A manual check: no writes, so one short request and no more. */\nconst CHECK_TIMEOUT_MS = 5_000;\n\n/** A manual sync may wait longer for the manifest, but not indefinitely. */\nconst SYNC_TIMEOUT_MS = 15_000;\n\n/** The archive, when a person is waiting rather than a session start. */\nconst BUNDLE_TIMEOUT_MS = 60_000;\n\n/**\n * A failure that already knows which documented exit code it is\n * (`src/bin/fabric.ts`). Errors from the SDK are translated into one of\n * these at the boundary so the command bodies can just throw.\n */\nclass CliFailure extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\treadonly exitCode: number,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"CliFailure\";\n\t}\n}\n\ninterface CommonOptions {\n\tproject: string;\n\tdest?: string;\n\torg?: string;\n\thook?: boolean;\n\t/**\n\t * Declared for `--help` and read through `optsWithGlobals()`, never off\n\t * this object: Commander stores a flag both a parent and a subcommand\n\t * declare on the parent.\n\t */\n\tformat?: string;\n}\n\ntype OutputFormat = \"text\" | \"json\";\n\nexport function buildInstructionsCommand(): Command {\n\tconst instructions = new Command(\"instructions\").description(\n\t\t\"Keep a checkout current with a project's published coding instructions\",\n\t);\n\n\tinstructions\n\t\t.command(\"check\")\n\t\t.description(\n\t\t\t\"Report whether the local copy is behind the published one\",\n\t\t)\n\t\t.requiredOption(\"--project <id>\", \"Project ID\")\n\t\t.option(\"--dest <dir>\", \"Destination directory (default: cwd)\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\n\t\t\t\"--verify\",\n\t\t\t\"Also hash the local files against the lock and report any that drifted\",\n\t\t)\n\t\t.option(\n\t\t\t\"--hook\",\n\t\t\t\"Session-hook mode: plain text, never fails, never blocks a session\",\n\t\t)\n\t\t// No default: a default here would shadow the program-level --format,\n\t\t// which is where `FABRIC_FORMAT` enters.\n\t\t.option(\"--format <format>\", \"Output format: text|json\")\n\t\t.action(async function (\n\t\t\tthis: Command,\n\t\t\topts: CommonOptions & { verify?: boolean },\n\t\t) {\n\t\t\tawait run(opts, \"check\", () => runCheck(opts, formatFor(this)));\n\t\t});\n\n\tinstructions\n\t\t.command(\"sync\")\n\t\t.description(\n\t\t\t\"Write the published coding instructions into the checkout\",\n\t\t)\n\t\t.requiredOption(\"--project <id>\", \"Project ID\")\n\t\t.option(\"--dest <dir>\", \"Destination directory (default: cwd)\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--dry-run\", \"Print the plan and write nothing\")\n\t\t.option(\n\t\t\t\"--hook\",\n\t\t\t\"Session-hook mode: plain text, never fails, never blocks a session\",\n\t\t)\n\t\t.option(\"--format <format>\", \"Output format: text|json\")\n\t\t.action(async function (\n\t\t\tthis: Command,\n\t\t\topts: CommonOptions & { dryRun?: boolean },\n\t\t) {\n\t\t\tawait run(opts, \"sync\", () => runSync(opts, formatFor(this)));\n\t\t});\n\n\tinstructions\n\t\t.command(\"init\")\n\t\t.description(\n\t\t\t\"Write a SessionStart hook for a coding tool and take the first copy\",\n\t\t)\n\t\t.requiredOption(\"--project <id>\", \"Project ID\")\n\t\t.requiredOption(\n\t\t\t\"--tool <tool>\",\n\t\t\t\"Coding tool to configure: claude-code\",\n\t\t)\n\t\t.option(\"--dest <dir>\", \"Destination directory (default: cwd)\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\n\t\t\t\"--apply\",\n\t\t\t\"Let the hook apply changes instead of only reporting them\",\n\t\t)\n\t\t.option(\"--format <format>\", \"Output format: text|json\")\n\t\t.action(async function (\n\t\t\tthis: Command,\n\t\t\topts: CommonOptions & { tool: string; apply?: boolean },\n\t\t) {\n\t\t\t// Never hook mode: `init` is run by a person, so its failures\n\t\t\t// are real failures with real exit codes.\n\t\t\tawait run({ ...opts, hook: false }, \"init\", () =>\n\t\t\t\trunInit(opts, formatFor(this)),\n\t\t\t);\n\t\t});\n\n\treturn instructions;\n}\n\n// ---------------------------------------------------------------------------\n// Output format\n// ---------------------------------------------------------------------------\n\n/**\n * The format this invocation should print in: `json`, or text.\n *\n * One reader, `optsWithGlobals()`, because Commander has already done the\n * resolving. The root command declares `--format` with a default of\n * `FABRIC_FORMAT ?? \"table\"`, these commands declare their own, and\n * `optsWithGlobals` merges them with the command's own value winning. Reading\n * `FABRIC_FORMAT` again here undid that: `FABRIC_FORMAT=json fabric --format\n * table instructions check` printed JSON at the very moment the flag said not\n * to (review round 2, finding 10).\n *\n * Anything that is not `json` prints text. `table`, `yaml` and `csv` are real\n * values elsewhere in this CLI and these commands have no such shape — one\n * paragraph or one JSON object — so they degrade rather than fail. Refusing\n * them here would also be a promise this cannot keep: when a parent and a\n * subcommand declare the same flag, Commander stores the value on the ROOT,\n * so `fabric instructions check --format yaml` never arrives as a local\n * option at all.\n */\nfunction formatFor(command: Command): OutputFormat {\n\tconst resolved = command.optsWithGlobals() as { format?: string };\n\treturn resolved.format === \"json\" ? \"json\" : \"text\";\n}\n\n// ---------------------------------------------------------------------------\n// The never-fail boundary\n// ---------------------------------------------------------------------------\n\n/**\n * One place where every failure is turned into either an exit code or, under\n * `--hook`, a single line on stderr and a zero exit.\n *\n * \"Every\" is literal: network, auth, HTTP, timeout, a bad lock file, a\n * refused path, a retired context default. Nothing inside may call\n * `process.exit` itself — `printError` does, and `process.exit` cannot be\n * caught here, which is why these commands build their own client rather than\n * reaching for the exiting helpers the other commands use, and why they read\n * no stored context at all.\n */\nasync function run(\n\topts: { hook?: boolean },\n\tverb: string,\n\tbody: () => Promise<void>,\n): Promise<void> {\n\ttry {\n\t\tif (opts.hook) {\n\t\t\tawait withDeadline(HOOK_DEADLINE_MS, body);\n\t\t} else {\n\t\t\tawait body();\n\t\t}\n\t} catch (error) {\n\t\tconst message = describeError(error);\n\t\tif (opts.hook) {\n\t\t\tprocess.stderr.write(\n\t\t\t\t`fabric: coding instructions ${verb} skipped: ${message}\\n`,\n\t\t\t);\n\t\t\tprocess.exit(0);\n\t\t}\n\t\tprocess.stderr.write(`✗ ${message}\\n`);\n\t\tprocess.exit(error instanceof CliFailure ? error.exitCode : 1);\n\t}\n}\n\n/**\n * The absolute bound on hook mode.\n *\n * A race rather than a chain of per-request timeouts: the guarantee has to\n * hold whatever the SDK, the runtime or a wedged socket does, and only the\n * caller can promise that. The losing work is abandoned rather than awaited,\n * which is safe because the boundary above exits the process immediately\n * afterwards.\n */\nasync function withDeadline(\n\ttotalMs: number,\n\tbody: () => Promise<void>,\n): Promise<void> {\n\tconst controller = new AbortController();\n\tlet timer: NodeJS.Timeout | undefined;\n\tconst deadline = new Promise<never>((_resolve, reject) => {\n\t\ttimer = setTimeout(() => {\n\t\t\tcontroller.abort();\n\t\t\treject(\n\t\t\t\tnew Error(\n\t\t\t\t\t`gave up after ${totalMs}ms so the session is not held up`,\n\t\t\t\t),\n\t\t\t);\n\t\t}, totalMs);\n\t});\n\tactiveDeadline = controller.signal;\n\ttry {\n\t\tawait Promise.race([body(), deadline]);\n\t} finally {\n\t\tactiveDeadline = undefined;\n\t\tif (timer) {\n\t\t\tclearTimeout(timer);\n\t\t}\n\t}\n}\n\n/**\n * The deadline signal in force, if any, so the bundle download can be\n * cancelled by the same clock that bounds the command. Module state rather\n * than a threaded parameter because every command body is single-shot within\n * one process.\n */\nlet activeDeadline: AbortSignal | undefined;\n\nfunction describeError(error: unknown): string {\n\tif (error instanceof Error) {\n\t\t// Collapsed to one line: under `--hook` this lands in a terminal\n\t\t// banner and, on Claude Code, in the agent's context.\n\t\treturn error.message.replace(/\\s*\\n\\s*/g, \" \");\n\t}\n\treturn String(error);\n}\n\n/**\n * SDK errors carry an HTTP status; the CLI's documented exit codes do not\n * come from it automatically. Mapped once, here.\n */\nfunction asCliFailure(error: unknown): CliFailure {\n\tif (error instanceof CliFailure) {\n\t\treturn error;\n\t}\n\tconst status = (error as { status?: number }).status;\n\tconst message = error instanceof Error ? error.message : String(error);\n\tswitch (status) {\n\t\tcase 401:\n\t\t\treturn new CliFailure(message, 3);\n\t\tcase 403:\n\t\t\treturn new CliFailure(message, 5);\n\t\tcase 404:\n\t\t\treturn new CliFailure(message, 4);\n\t\tcase 429:\n\t\t\treturn new CliFailure(message, 6);\n\t\tcase 400:\n\t\tcase 422:\n\t\t\treturn new CliFailure(message, 7);\n\t\tdefault:\n\t\t\treturn new CliFailure(message, 1);\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Shared steps\n// ---------------------------------------------------------------------------\n\nfunction destinationOf(opts: { dest?: string }): string {\n\treturn path.resolve(opts.dest ?? process.cwd());\n}\n\n/**\n * A client that throws instead of exiting, and that never retries in hook\n * mode.\n *\n * `getClient` calls `printError`, which exits with code 3 — correct for every\n * other command and fatal to the `--hook` contract, which must never exit\n * non-zero for any reason.\n */\nfunction instructionsClient(\n\topts: { hook?: boolean },\n\ttimeoutMs: number,\n): FabricClient {\n\tif (!getApiKey()) {\n\t\tthrow new CliFailure(\n\t\t\t\"Not authenticated. Run: fabric auth login --key <api-key>\",\n\t\t\t3,\n\t\t);\n\t}\n\t// `withoutContext()`: the SDK constructor adopts `FABRIC_ORG` /\n\t// `FABRIC_PERSONAL` and injects them into every URL that does not name a\n\t// context. On a project-authoritative surface that ambient default is not\n\t// a default, it is a contradiction waiting to be refused — see\n\t// `orgSlugFor`.\n\treturn getClient(\n\t\topts.hook\n\t\t\t? {\n\t\t\t\t\ttimeoutMs: Math.min(timeoutMs, HOOK_DEADLINE_MS),\n\t\t\t\t\tretry: { maxRetries: 0 },\n\t\t\t\t}\n\t\t\t: { timeoutMs },\n\t).withoutContext();\n}\n\n/**\n * The org slug to send: the one on the command line, or none at all.\n *\n * These commands are PROJECT-AUTHORITATIVE — the project decides which\n * organization it is in, and the route resolves that from the project itself.\n * Sending a stored default context (or `FABRIC_ORG`) turned that resolution\n * into a contradiction for anyone whose default is not the project's host\n * organization, and the clearest case is the one the route exists to support:\n * an invited guest, whose own default organization is never the one hosting a\n * project they were invited to. Their request carried `?org=<their own org>`,\n * the route compared it with the project's, and refused.\n *\n * So the ambient default is not consulted here and the client is built\n * without one. `--org` remains available for the caller who wants the request\n * bound explicitly; an explicit slug that disagrees with the project is still\n * a 404, which is the point of passing it.\n */\nfunction orgSlugFor(opts: CommonOptions): string | undefined {\n\treturn opts.org;\n}\n\nasync function fetchPublished(\n\tclient: FabricClient,\n\topts: CommonOptions,\n\tsinceDigest?: string,\n): Promise<PublishedInstructions> {\n\tconst org = orgSlugFor(opts);\n\tlet published: PublishedInstructions;\n\ttry {\n\t\tpublished = await client.instructions.getPublished(opts.project, {\n\t\t\torg,\n\t\t\tsinceDigest,\n\t\t});\n\t} catch (error) {\n\t\tthrow asCliFailure(error);\n\t}\n\tassertHookMayAct(opts, published);\n\treturn published;\n}\n\n/**\n * A hook may not act on a project whose instructions come from git.\n *\n * Asserted on EVERY response rather than on the first one, because a command\n * can make two calls: a delta answer, and then — when the local tree has\n * drifted — a full refetch. Checking only the first meant a project switched\n * to `REPOSITORY` between the two was planned, downloaded and applied by a\n * hook, which is the second writer `init` refuses to create.\n *\n * `init` refuses such a project outright; a person running `sync` or `check`\n * by hand is unaffected, because for someone without access to that\n * repository a download is the only way to read the instructions at all.\n */\nfunction assertHookMayAct(\n\topts: { hook?: boolean },\n\tpublished: PublishedInstructions,\n): void {\n\tif (opts.hook && published.sourceOfTruth === \"REPOSITORY\") {\n\t\tthrow new CliFailure(\n\t\t\t\"this project's instructions now come from a git repository; run `fabric instructions init` again or remove the hook\",\n\t\t\t4,\n\t\t);\n\t}\n}\n\n/**\n * The lock, refused when it belongs to a different project.\n *\n * A lock is a per-destination file and a destination holds one project's\n * tree. `sync --project B` in a directory synced from project A would\n * otherwise send A's digest, receive B's manifest, and then use A's ledger to\n * decide what to delete — classifying every A-only file as \"the sync wrote\n * this, remove it\". Equal digests across the two could even report \"up to\n * date\" for a tree that holds the wrong project's instructions entirely.\n */\nasync function readLockForProject(\n\tdestination: string,\n\tprojectId: string,\n): Promise<InstructionsLock | null> {\n\tconst lock = await readLock(destination);\n\tif (lock !== null && lock.projectId !== projectId) {\n\t\tthrow new CliFailure(\n\t\t\t`${lockPath(destination)} belongs to project ${lock.projectId}, not ${projectId}. Use a different --dest, or remove that lock if this directory should now follow ${projectId}.`,\n\t\t\t7,\n\t\t);\n\t}\n\treturn lock;\n}\n\nfunction line(text: string): void {\n\tprocess.stdout.write(`${text}\\n`);\n}\n\nfunction listPaths(label: string, paths: string[]): void {\n\tif (paths.length === 0) {\n\t\treturn;\n\t}\n\tline(` ${label}:`);\n\tfor (const p of paths) {\n\t\tline(` ${p}`);\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// check\n// ---------------------------------------------------------------------------\n\nasync function runCheck(\n\topts: CommonOptions & { verify?: boolean },\n\tformat: OutputFormat,\n): Promise<void> {\n\tconst destination = destinationOf(opts);\n\t// Canonical, but NOT created: `check` is informational and must not make a\n\t// directory as a side effect. Every guarded read resolves against this,\n\t// and a literal path would refuse legitimately — `/tmp` is a symlink on\n\t// macOS, so the string a user passes and the directory they mean differ.\n\tconst root = await resolveExistingRoot(destination);\n\tconst lock = await readLockForProject(destination, opts.project);\n\tconst client = instructionsClient(opts, CHECK_TIMEOUT_MS);\n\tconst published = await fetchPublished(client, opts, lock?.digest);\n\n\t// Deliberately NOT validated against `assertValidManifest`: `check`\n\t// writes nothing, so a skewed manifest here can only produce a less\n\t// useful report, and refusing would make the informational command the\n\t// fragile one. `sync` validates before it can act on it.\n\n\t// Off by default, and that is the trade rather than an oversight: this is\n\t// the command a session start runs, one request and no local reads. With\n\t// `--verify` it also hashes every file the lock names, which is what\n\t// answers \"is my checkout still what was published\" as opposed to \"has\n\t// the published version moved\". `sync` always does this.\n\tconst drifted =\n\t\topts.verify && lock !== null ? await verifyLedger({ root, lock }) : [];\n\n\tif (format === \"json\") {\n\t\tprintOutput(\n\t\t\t{\n\t\t\t\tprojectId: opts.project,\n\t\t\t\tdestination,\n\t\t\t\tsynced: lock !== null,\n\t\t\t\tlocalDigest: lock?.digest ?? null,\n\t\t\t\tverified: Boolean(opts.verify),\n\t\t\t\tdrifted,\n\t\t\t\t...published,\n\t\t\t},\n\t\t\t{ format: \"json\" },\n\t\t);\n\t\treturn;\n\t}\n\n\treportPublishedState(opts, destination, lock, published);\n\n\t// The common tail. Every text-mode branch returns through here, because\n\t// `--verify` promises to report local drift and three of those branches\n\t// used to return before saying a word about it.\n\tif (opts.verify) {\n\t\treportDrift(opts, destination, drifted);\n\t}\n}\n\n/** What the server said about the published snapshot, in text. */\nfunction reportPublishedState(\n\topts: CommonOptions,\n\tdestination: string,\n\tlock: InstructionsLock | null,\n\tpublished: PublishedInstructions,\n): void {\n\tif (!published.published) {\n\t\tline(\"This project has no published coding instructions yet.\");\n\t\treturn;\n\t}\n\n\tconst version = published.snapshot?.version;\n\n\tif (!lock) {\n\t\tline(\n\t\t\t`Coding instructions have not been synced into ${destination} yet (published version ${version}, ${published.snapshot?.fileCount} files).`,\n\t\t);\n\t\tline(\n\t\t\t`Run \\`fabric instructions sync --project ${opts.project}\\` to take a copy.`,\n\t\t);\n\t\treturn;\n\t}\n\n\tif (published.unchanged) {\n\t\t// \"the published version has not moved\" — NOT \"your files are\n\t\t// correct\". Without `--verify` nothing local has been read at all, and\n\t\t// saying \"up to date\" invited exactly the wrong conclusion.\n\t\tline(`Published coding instructions unchanged (version ${version}).`);\n\t\treturn;\n\t}\n\n\tif (published.changes === null || published.changes === undefined) {\n\t\tline(\n\t\t\t`Coding instructions changed, and the version in ${destination} is not one the server still recognises, so what changed cannot be listed. A full sync is needed (published version ${version}).`,\n\t\t);\n\t\tline(\n\t\t\t`Run \\`fabric instructions sync --project ${opts.project}\\` to apply.`,\n\t\t);\n\t\treturn;\n\t}\n\n\tconst { added, changed, removed } = published.changes;\n\tline(\n\t\t`Coding instructions updated: ${added.length} added, ${changed.length} changed, ${removed.length} removed (version ${version}).`,\n\t);\n\tlistPaths(\"added\", added);\n\tlistPaths(\"changed\", changed);\n\tlistPaths(\"removed\", removed);\n\tline(\n\t\t`Run \\`fabric instructions sync --project ${opts.project}\\` to apply.`,\n\t);\n}\n\n/** What `--verify` found, in the two places the report can end. */\nfunction reportDrift(\n\topts: CommonOptions,\n\tdestination: string,\n\tdrifted: string[],\n): void {\n\tif (drifted.length === 0) {\n\t\tline(`Every file in ${destination} matches the lock.`);\n\t\treturn;\n\t}\n\tline(`${drifted.length} local file(s) no longer match the lock:`);\n\tlistPaths(\"drifted\", drifted);\n\tline(\n\t\t`Run \\`fabric instructions sync --project ${opts.project}\\` to put them back.`,\n\t);\n}\n\n// ---------------------------------------------------------------------------\n// sync\n// ---------------------------------------------------------------------------\n\nasync function runSync(\n\topts: CommonOptions & { dryRun?: boolean },\n\tformat: OutputFormat,\n): Promise<void> {\n\tconst result = await syncOnce(opts);\n\tif (format === \"json\") {\n\t\tprintOutput(result, { format: \"json\" });\n\t\treturn;\n\t}\n\treportSync(result, opts);\n}\n\ninterface SyncOutcome {\n\tprojectId: string;\n\tdestination: string;\n\tpublished: boolean;\n\tunchanged: boolean;\n\tdryRun: boolean;\n\tversion: number | null;\n\tdigest: string | null;\n\tadded: string[];\n\tupdated: string[];\n\treplaced: string[];\n\tremoved: string[];\n\tkeptModified: string[];\n\t/**\n\t * Paths the lock still names under an old spelling that the manifest now\n\t * spells differently. Reported rather than removed: on a case-insensitive\n\t * filesystem they ARE the file the sync just wrote.\n\t */\n\tkeptRenamed: string[];\n\t/**\n\t * Paths the lock claimed that the working tree no longer matched, when the\n\t * published snapshot itself had not moved. Non-empty means this run\n\t * repaired local drift rather than applying a new version.\n\t */\n\tdrifted: string[];\n\tverified: number;\n\tlockPath: string;\n}\n\nfunction emptyOutcome(\n\topts: CommonOptions & { dryRun?: boolean },\n\tdestination: string,\n): SyncOutcome {\n\treturn {\n\t\tprojectId: opts.project,\n\t\tdestination,\n\t\tpublished: true,\n\t\tunchanged: false,\n\t\tdryRun: Boolean(opts.dryRun),\n\t\tversion: null,\n\t\tdigest: null,\n\t\tadded: [],\n\t\tupdated: [],\n\t\treplaced: [],\n\t\tremoved: [],\n\t\tkeptModified: [],\n\t\tkeptRenamed: [],\n\t\tdrifted: [],\n\t\tverified: 0,\n\t\tlockPath: lockPath(destination),\n\t};\n}\n\nasync function syncOnce(\n\topts: CommonOptions & { dryRun?: boolean; rejectRepository?: boolean },\n): Promise<SyncOutcome> {\n\t// Canonical from here on: every write resolves against this, so a\n\t// symlinked `--dest` (or `/tmp` on macOS) is decided once rather than at\n\t// each write.\n\tconst root = await resolveDestinationRoot(destinationOf(opts));\n\tconst outcome = emptyOutcome(opts, root);\n\n\tconst lock = await readLockForProject(root, opts.project);\n\tconst client = instructionsClient(opts, SYNC_TIMEOUT_MS);\n\tlet published = await fetchPublished(client, opts, lock?.digest);\n\tassertInitSyncMayAct(opts, published);\n\n\t// Hook mode rejects repository-backed instructions in `fetchPublished`;\n\t// init's first sync performs the same check above so its drift refetch does\n\t// not trust only the first response.\n\n\tif (!published.published || !published.snapshot) {\n\t\t// A real failure for a person who asked for a copy; the `--hook`\n\t\t// boundary turns it into one quiet line for a session start.\n\t\tthrow new CliFailure(\n\t\t\t\"This project has no published coding instructions yet.\",\n\t\t\t4,\n\t\t);\n\t}\n\n\toutcome.version = published.snapshot.version;\n\toutcome.digest = published.snapshot.digest;\n\n\tif (published.unchanged) {\n\t\t// \"Unchanged\" is the SERVER's answer about the SNAPSHOT, and it says\n\t\t// nothing about the checkout. Accepting it as \"nothing to do\" let an\n\t\t// edited, deleted or chmod-ed instruction file stay that way until\n\t\t// some later publication happened to move the digest — so a tampered\n\t\t// tree reported success indefinitely. The ledger is the local half of\n\t\t// the question, and hashing it is the price of a command that applies\n\t\t// things.\n\t\tconst drifted = lock === null ? [] : await verifyLedger({ root, lock });\n\t\tif (drifted.length === 0) {\n\t\t\toutcome.unchanged = true;\n\t\t\treturn outcome;\n\t\t}\n\n\t\toutcome.drifted = drifted;\n\t\t// The first call answered with a delta and therefore carries no\n\t\t// manifest. Ask again without a base digest: the plan needs the whole\n\t\t// published list to put the tree back.\n\t\tpublished = await fetchPublished(client, opts);\n\t\tassertInitSyncMayAct(opts, published);\n\t\tif (!published.published || !published.snapshot) {\n\t\t\tthrow new CliFailure(\n\t\t\t\t\"This project has no published coding instructions yet.\",\n\t\t\t\t4,\n\t\t\t);\n\t\t}\n\t\toutcome.version = published.snapshot.version;\n\t\toutcome.digest = published.snapshot.digest;\n\t}\n\n\t// An absent manifest is a refusal, never an empty one. `[]` means\n\t// \"delete everything the lock names\", so a version-skewed or truncated\n\t// response was one step from emptying the tree and writing a ledger that\n\t// agreed with it.\n\tconst manifest = assertValidManifest({\n\t\tmanifest: published.manifest,\n\t\tsnapshot: published.snapshot,\n\t});\n\n\tconst plan = await computeSyncPlan({ destination: root, manifest, lock });\n\tfillPlanPaths(outcome, plan);\n\n\tif (opts.dryRun) {\n\t\t// The plan is computable from the manifest alone, so a dry run\n\t\t// downloads nothing at all.\n\t\treturn outcome;\n\t}\n\n\tlet contents = new Map<string, Uint8Array>();\n\tif (plan.writes.length > 0) {\n\t\tconst org = orgSlugFor(opts);\n\t\tlet download: { url: string };\n\t\ttry {\n\t\t\tdownload = await client.instructions.createDownloadUrl(\n\t\t\t\topts.project,\n\t\t\t\t{ org },\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tthrow asCliFailure(error);\n\t\t}\n\t\tconst sizes = new Map(\n\t\t\tmanifest.map((entry) => [entry.path, entry.size] as const),\n\t\t);\n\t\tconst archive = await fetchBundle(download.url, {\n\t\t\ttimeoutMs: opts.hook ? HOOK_DEADLINE_MS : BUNDLE_TIMEOUT_MS,\n\t\t\t// Bounded by what this manifest says it holds, not by what the\n\t\t\t// response claims. The manifest has already been checked against\n\t\t\t// the published snapshot limits, so this is a number the client\n\t\t\t// decided.\n\t\t\tmaxBytes: maxArchiveBytes(manifest),\n\t\t\t// In hook mode the same clock that bounds the command bounds the\n\t\t\t// download, rather than a second independent budget after it.\n\t\t\tsignal: activeDeadline,\n\t\t});\n\t\tcontents = extractBundle(\n\t\t\tarchive,\n\t\t\tplan.writes.map((entry) => ({\n\t\t\t\tpath: entry.path,\n\t\t\t\tsize: sizes.get(entry.path) ?? -1,\n\t\t\t})),\n\t\t);\n\t}\n\n\tconst applied = await applyPlan({ root, plan, contents });\n\t// What actually happened, not what was planned: a delete whose file was\n\t// edited between planning and the unlink is reported as kept, because that\n\t// is what it is.\n\toutcome.removed = applied.deleted;\n\toutcome.keptModified = [\n\t\t...outcome.keptModified,\n\t\t...applied.keptModified,\n\t].sort();\n\n\t// Last, and only now: a lock written before the files would claim\n\t// ownership of paths that are not there, and the next run would delete\n\t// whatever the developer had in their place.\n\tconst lockToWrite: InstructionsLock = nextLock({\n\t\tprojectId: opts.project,\n\t\tsnapshot: {\n\t\t\tid: published.snapshot.id,\n\t\t\tversion: published.snapshot.version,\n\t\t\tdigest: published.snapshot.digest,\n\t\t},\n\t\tmanifest,\n\t});\n\tawait writeLock(root, lockToWrite);\n\n\treturn outcome;\n}\n\n/**\n * `init` uses a manual sync for its first copy, but it must still reject a\n * project that switches to repository-backed instructions during that sync.\n * Keeping this distinct from hook mode preserves manual `sync` behavior.\n */\nfunction assertInitSyncMayAct(\n\topts: { rejectRepository?: boolean },\n\tpublished: PublishedInstructions,\n): void {\n\tif (opts.rejectRepository && published.sourceOfTruth === \"REPOSITORY\") {\n\t\tthrow new CliFailure(\n\t\t\t\"This project's coding instructions come from its repository, so they arrive with `git pull`. A session hook would fight it; nothing was written.\",\n\t\t\t7,\n\t\t);\n\t}\n}\n\nfunction fillPlanPaths(outcome: SyncOutcome, plan: SyncPlan): void {\n\toutcome.added = plan.entries\n\t\t.filter((entry) => entry.action === \"added\")\n\t\t.map((entry) => entry.path);\n\toutcome.updated = plan.entries\n\t\t.filter((entry) => entry.action === \"updated\")\n\t\t.map((entry) => entry.path);\n\toutcome.replaced = plan.entries\n\t\t.filter((entry) => entry.action === \"replaced\")\n\t\t.map((entry) => entry.path);\n\toutcome.removed = plan.deletes.map((entry) => entry.path);\n\toutcome.keptModified = plan.keptModified.map((entry) => entry.path);\n\toutcome.keptRenamed = plan.keptRenamed.map((entry) => entry.path);\n\toutcome.verified = plan.verified.length;\n}\n\nfunction reportSync(\n\toutcome: SyncOutcome,\n\topts: CommonOptions & { dryRun?: boolean },\n): void {\n\tif (outcome.unchanged) {\n\t\tline(\n\t\t\t`Coding instructions are up to date (version ${outcome.version}).`,\n\t\t);\n\t\treturn;\n\t}\n\n\tconst total =\n\t\toutcome.added.length +\n\t\toutcome.updated.length +\n\t\toutcome.replaced.length +\n\t\toutcome.removed.length;\n\tif (outcome.drifted.length > 0) {\n\t\tline(\n\t\t\t`Coding instructions version ${outcome.version} is still the published one, but ${outcome.drifted.length} local file(s) no longer match it:`,\n\t\t);\n\t\tlistPaths(\"drifted\", outcome.drifted);\n\t}\n\n\tconst prefix = opts.dryRun ? \"Would apply\" : \"Applied\";\n\tline(\n\t\t`${prefix} coding instructions version ${outcome.version}: ${outcome.added.length} added, ${outcome.updated.length} updated, ${outcome.replaced.length} replaced, ${outcome.removed.length} removed (${outcome.verified} already current).`,\n\t);\n\tlistPaths(\"added\", outcome.added);\n\tlistPaths(\"updated\", outcome.updated);\n\tlistPaths(\"replaced local edits\", outcome.replaced);\n\tlistPaths(\"removed\", outcome.removed);\n\tlistPaths(\"kept, modified locally\", outcome.keptModified);\n\tlistPaths(\"kept, renamed in the published snapshot\", outcome.keptRenamed);\n\tif (!opts.dryRun) {\n\t\tline(`Lock: ${outcome.lockPath}`);\n\t}\n\tif (\n\t\ttotal === 0 &&\n\t\toutcome.keptModified.length === 0 &&\n\t\toutcome.keptRenamed.length === 0\n\t) {\n\t\tline(`Everything in ${outcome.destination} already matched.`);\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// init\n// ---------------------------------------------------------------------------\n\nasync function runInit(\n\topts: CommonOptions & { tool: string; apply?: boolean },\n\tformat: OutputFormat,\n): Promise<void> {\n\tif (opts.tool !== \"claude-code\") {\n\t\tthrow new CliFailure(\n\t\t\t`Unsupported tool \"${opts.tool}\". Only --tool claude-code is supported today; other tools follow.`,\n\t\t\t2,\n\t\t);\n\t}\n\n\tconst root = await resolveDestinationRoot(destinationOf(opts));\n\n\t// Two local preconditions, both answered before any network call: a lock\n\t// that belongs to another project, and a credential file that would end\n\t// up inside the checkout. Neither needs the server to decide, and making\n\t// a reader wait on a request to learn about them is backwards.\n\tawait readLockForProject(root, opts.project);\n\ttry {\n\t\tawait assertKeyStaysOutside(root, getConfigPath());\n\t} catch (error) {\n\t\tthrow new CliFailure(describeError(error), 7);\n\t}\n\n\tconst client = instructionsClient(opts, SYNC_TIMEOUT_MS);\n\tconst published = await fetchPublished(client, opts);\n\n\tif (published.sourceOfTruth === \"REPOSITORY\") {\n\t\t// A sync hook on a repository-backed project would fight `git pull`:\n\t\t// the files arrive through the repository, and two writers with no\n\t\t// merge between them is worse than one.\n\t\tthrow new CliFailure(\n\t\t\t\"This project's coding instructions come from its repository, so they arrive with `git pull`. A session hook would fight it; nothing was written.\",\n\t\t\t7,\n\t\t);\n\t}\n\n\tconst outcome = published.published\n\t\t? // A second manifest call, deliberately: the one above answered \"may\n\t\t\t// a hook be installed for this project at all\", and this one is the\n\t\t\t// sync's own. Do it before the hook write: a failed first copy must\n\t\t\t// not leave a new or updated hook behind.\n\t\t\tawait syncOnce({ ...opts, hook: false, rejectRepository: true })\n\t\t: null;\n\n\tconst command = buildHookCommand(\n\t\topts.project,\n\t\tBoolean(opts.apply),\n\t\topts.org,\n\t);\n\tconst merged = await mergeSessionStartHook({\n\t\troot,\n\t\tprojectId: opts.project,\n\t\tcommand,\n\t});\n\n\tif (format === \"json\") {\n\t\tprintOutput(\n\t\t\t{\n\t\t\t\tprojectId: opts.project,\n\t\t\t\tdestination: root,\n\t\t\t\tsettingsPath: merged.settingsPath,\n\t\t\t\thookCommand: merged.command,\n\t\t\t\tcreatedSettingsFile: merged.createdFile,\n\t\t\t\treplacedHooks: merged.replacedCount,\n\t\t\t\tsync: outcome,\n\t\t\t},\n\t\t\t{ format: \"json\" },\n\t\t);\n\t\treturn;\n\t}\n\n\tline(\n\t\tmerged.replacedCount > 0\n\t\t\t? `Updated the SessionStart hook in ${merged.settingsPath}.`\n\t\t\t: `Added a SessionStart hook to ${merged.settingsPath}.`,\n\t);\n\tline(` ${command}`);\n\tline(\n\t\topts.apply\n\t\t\t? \" It applies changes at session start.\"\n\t\t\t: \" It only reports changes; add --apply to init to have it apply them.\",\n\t);\n\n\tif (outcome === null) {\n\t\tline(\n\t\t\t\"This project has nothing published yet, so there is nothing to copy — the hook will pick it up once there is.\",\n\t\t);\n\t} else {\n\t\tline(\"\");\n\t\treportSync(outcome, opts);\n\t}\n\n\tline(\"\");\n\tline(\n\t\t`${CLAUDE_SETTINGS_RELATIVE_PATH} and ${LOCK_DIRECTORY}/ are local to this machine. If this repository does not ignore them already, add them to your own ignore rules — this command does not edit .gitignore.`,\n\t);\n}\n","/**\n * Turning a plan into files, with two rules that decide the shape of\n * everything below.\n *\n * First: verify every byte before writing any byte. Each entry's sha256 is\n * checked against the manifest up front, so a corrupt or tampered archive\n * aborts with nothing written at all, rather than half a tree of good files\n * and one bad one. The caller then does not rewrite the lock, so the next run\n * plans from the last known-good state.\n *\n * Second: every write goes through `safe-write.ts` — the same writer the\n * lock and the Claude Code settings file use. Symlink refusal, canonical\n * containment, exclusive temp creation and the pre-rename recheck all live\n * there, so there is exactly one implementation of \"may this land here\".\n */\nimport { createHash } from \"node:crypto\";\nimport { chmod } from \"node:fs/promises\";\nimport { describeRejection } from \"./paths.js\";\nimport type { PlanEntry, SyncPlan } from \"./plan.js\";\nimport {\n\tassertWritableTarget,\n\tdeleteFileSafely,\n\tisAllowedMode,\n\tpermissionBits,\n\twriteFileSafely,\n} from \"./safe-write.js\";\n\nexport interface ApplyResult {\n\twritten: string[];\n\tdeleted: string[];\n\t/** Paths whose mode was corrected without rewriting their bytes. */\n\tremoded: string[];\n\t/**\n\t * Paths the plan meant to delete that no longer matched the hash it\n\t * decided on — someone edited them between planning and now, so they were\n\t * left where they are.\n\t */\n\tkeptModified: string[];\n}\n\nexport interface ApplyInput {\n\t/** An already-canonical destination from `resolveDestinationRoot`. */\n\troot: string;\n\tplan: SyncPlan;\n\t/** Extracted archive entries, keyed by the manifest path. */\n\tcontents: Map<string, Uint8Array>;\n}\n\nexport async function applyPlan(input: ApplyInput): Promise<ApplyResult> {\n\tconst { root, plan, contents } = input;\n\n\t// ---- Phase 1: prove the whole plan before touching the tree ----------\n\t//\n\t// EVERY path the plan names, including the ones it does not intend to\n\t// write. A `verified` entry is one whose local bytes already match, and a\n\t// symlink pointing at those bytes used to reach exactly that verdict: no\n\t// write, no check, and a lock written over a path that is not a file.\n\t// This runs before the platform and mode short-circuits further down for\n\t// the same reason — a check that only some plans reach is not a check.\n\tfor (const entry of [\n\t\t...plan.writes,\n\t\t...plan.verified,\n\t\t...plan.deletes,\n\t\t...plan.keptRenamed,\n\t]) {\n\t\tconst check = await assertWritableTarget(root, entry.path);\n\t\tif (!check.ok) {\n\t\t\tthrow new Error(\n\t\t\t\t`Refusing to sync: ${describeRejection(check)}. Nothing was written.`,\n\t\t\t);\n\t\t}\n\t}\n\n\tfor (const entry of plan.writes) {\n\t\tif (!isAllowedMode(entry.mode)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Refusing to sync: ${entry.path} asks for file mode ${(entry.mode ?? 0).toString(8)}, and only 644 and 755 are accepted. Nothing was written.`,\n\t\t\t);\n\t\t}\n\t\tconst bytes = contents.get(entry.path);\n\t\tif (!bytes) {\n\t\t\tthrow new Error(\n\t\t\t\t`The downloaded bundle is missing ${entry.path}. Nothing was written.`,\n\t\t\t);\n\t\t}\n\t\tconst actual = createHash(\"sha256\").update(bytes).digest(\"hex\");\n\t\tif (actual !== entry.sha256) {\n\t\t\tthrow new Error(\n\t\t\t\t`Checksum mismatch for ${entry.path}: the published snapshot expects ${entry.sha256} and the downloaded bundle contains ${actual}. Nothing was written.`,\n\t\t\t);\n\t\t}\n\t}\n\n\t// ---- Phase 2: apply --------------------------------------------------\n\tconst written: string[] = [];\n\tconst deleted: string[] = [];\n\tconst remoded: string[] = [];\n\tconst keptModified: string[] = [];\n\n\tfor (const entry of plan.writes) {\n\t\t// Non-null: phase 1 refused the whole plan if any byte was missing.\n\t\tconst bytes = contents.get(entry.path) as Uint8Array;\n\t\tawait writeFileSafely({\n\t\t\troot,\n\t\t\trelativePath: entry.path,\n\t\t\tbytes,\n\t\t\tmode: entry.mode ?? null,\n\t\t});\n\t\twritten.push(entry.path);\n\t}\n\n\t// A file whose bytes already match still has to carry the published\n\t// mode: a script that arrives non-executable is as broken as one that\n\t// arrives with the wrong contents, and `verified` would otherwise never\n\t// fix it.\n\tfor (const entry of plan.verified) {\n\t\tif (await applyMode(root, entry)) {\n\t\t\tremoded.push(entry.path);\n\t\t}\n\t}\n\n\tfor (const entry of plan.deletes) {\n\t\t// The hash the plan decided on travels with the unlink. Planning ran\n\t\t// before the download, the extraction and every write above, and an\n\t\t// editor saving in that window would otherwise have its work deleted\n\t\t// on the strength of a hash that no longer describes the file.\n\t\tif (entry.sha256 === undefined) {\n\t\t\tthrow new Error(\n\t\t\t\t`Refusing to delete ${entry.path}: the plan carries no hash for it.`,\n\t\t\t);\n\t\t}\n\t\tconst outcome = await deleteFileSafely(root, entry.path, entry.sha256);\n\t\tif (outcome === \"deleted\") {\n\t\t\tdeleted.push(entry.path);\n\t\t} else if (outcome === \"modified\") {\n\t\t\tkeptModified.push(entry.path);\n\t\t}\n\t}\n\t// Directories are deliberately left behind. An empty directory is\n\t// harmless; removing one races with anything the developer put in it.\n\n\treturn { written, deleted, remoded, keptModified };\n}\n\n/** Returns true when a mode was actually applied. */\nasync function applyMode(root: string, entry: PlanEntry): Promise<boolean> {\n\tconst bits = permissionBits(entry.mode);\n\tif (bits === null || process.platform === \"win32\") {\n\t\treturn false;\n\t}\n\tif (!isAllowedMode(entry.mode)) {\n\t\tthrow new Error(\n\t\t\t`Refusing to sync: ${entry.path} asks for file mode ${(entry.mode ?? 0).toString(8)}, and only 644 and 755 are accepted.`,\n\t\t);\n\t}\n\t// The same guard the writes use: a `chmod` is a mutation too, and phase 1\n\t// proving this path was a regular file does not make it one now.\n\tconst check = await assertWritableTarget(root, entry.path);\n\tif (!check.ok) {\n\t\tthrow new Error(`Refusing to sync: ${describeRejection(check)}.`);\n\t}\n\ttry {\n\t\tawait chmod(check.path, bits);\n\t\treturn true;\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n\t\t\treturn false;\n\t\t}\n\t\tthrow error;\n\t}\n}\n","/**\n * Path safety for the file-writing half of this CLI.\n *\n * The paths this module guards arrive from a server response and from a zip\n * archive, and they are about to become filesystem writes on a developer's\n * machine. That makes the check local: the server validates paths on upload,\n * but a client that trusts a remote path list has moved the decision to the\n * wrong side of the wire. Nothing here asks the network anything.\n *\n * Three layers, and they answer different questions:\n *\n * `checkRelativePath` is this STRING safe to turn into a write?\n * `isReservedPath` is this path one this feature refuses to own?\n * `collisionKey` do two safe strings name the same file anyway?\n *\n * The filesystem half — symlinks, canonical containment, atomic writes —\n * lives in `safe-write.ts`, because it needs a resolved destination root and\n * these functions deliberately do not.\n */\n\ntype PathRejectReason =\n\t| \"empty\"\n\t| \"absolute\"\n\t| \"traversal\"\n\t| \"backslash\"\n\t| \"control_char\"\n\t| \"trailing_separator\"\n\t| \"trailing_dot_or_space\"\n\t| \"reserved_device_name\"\n\t| \"alternate_data_stream\"\n\t| \"reserved_path\"\n\t| \"not_a_regular_file\"\n\t| \"escapes_destination\"\n\t| \"symlink\"\n\t| \"not_a_directory\"\n\t| \"collision\";\n\nexport interface PathRejection {\n\tok: false;\n\treason: PathRejectReason;\n\t/** The offending path, as given, or the link that was in the way. */\n\tdetail: string;\n}\n\nexport type PathCheck = { ok: true; path: string } | PathRejection;\n\nconst DRIVE_LETTER = /^[A-Za-z]:/;\n\n/**\n * Names Windows resolves to a device rather than a file, with or without an\n * extension: `NUL`, `nul.txt` and `CON.md` all reach the device. Writing the\n * tree on Windows would silently discard those files; worse, a manifest could\n * use one to make a write look like it happened.\n */\nconst RESERVED_DEVICE_NAME = /^(?:CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])(?:\\.|$)/i;\n\n/**\n * Paths this feature refuses to write or delete, whatever a manifest or a\n * lock says.\n *\n * `.git` is the obvious one: a lock is a plain JSON file inside the checkout,\n * so anything that can edit it could otherwise name `.git/config` — a file\n * whose current hash is easy to know — and have the next sync unlink it.\n * `.fabric` is here because the lock lives there and must never be able to\n * authorise its own deletion or replacement through the manifest path.\n */\nconst RESERVED_ROOTS = [\".git\", \".fabric\"] as const;\n\n/**\n * Single files this feature refuses to own, as opposed to whole roots.\n *\n * `.claude/settings.local.json` is the file `init` itself writes. Instruction\n * files legitimately live elsewhere under `.claude/` — skills, commands — so\n * reserving the whole root would refuse the feature's own content; reserving\n * this one path stops a published manifest from overwriting the session hook\n * that was just installed, and stops the resulting lock from later\n * authorising its deletion.\n */\nconst RESERVED_EXACT_PATHS = [\".claude/settings.local.json\"] as const;\n\n/**\n * NUL and friends, found by character code rather than by a regular\n * expression.\n *\n * A character class cannot say this here. Written as unicode escapes, the\n * formatter rewrites each escape into the character it names, which puts\n * a literal NUL byte in this source file and makes git treat it as binary.\n * A loop says the same thing and stays readable in a diff.\n */\nfunction hasControlCharacter(input: string): boolean {\n\tfor (let index = 0; index < input.length; index++) {\n\t\tconst code = input.charCodeAt(index);\n\t\tif (code <= 0x1f || code === 0x7f) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Is this manifest/archive path safe to turn into a write inside a\n * destination? String-level only — see `safe-write.ts` for the filesystem\n * half.\n */\nexport function checkRelativePath(input: string): PathCheck {\n\tif (input.length === 0) {\n\t\treturn { ok: false, reason: \"empty\", detail: input };\n\t}\n\tif (hasControlCharacter(input)) {\n\t\treturn { ok: false, reason: \"control_char\", detail: input };\n\t}\n\tif (input.includes(\"\\\\\")) {\n\t\treturn { ok: false, reason: \"backslash\", detail: input };\n\t}\n\tif (input.startsWith(\"/\") || DRIVE_LETTER.test(input)) {\n\t\treturn { ok: false, reason: \"absolute\", detail: input };\n\t}\n\tif (input.endsWith(\"/\")) {\n\t\treturn { ok: false, reason: \"trailing_separator\", detail: input };\n\t}\n\tconst segments = input.split(\"/\");\n\tif (segments.some((s) => s.length === 0)) {\n\t\t// An empty segment means `a//b` or a leading slash already refused\n\t\t// above; either way the string is not the path it appears to be.\n\t\treturn { ok: false, reason: \"empty\", detail: input };\n\t}\n\tif (segments.some((s) => s === \".\" || s === \"..\")) {\n\t\treturn { ok: false, reason: \"traversal\", detail: input };\n\t}\n\tfor (const segment of segments) {\n\t\t// Windows strips a trailing dot or space from a name, so `a.md.` and\n\t\t// `a.md ` both open `a.md`. Two manifest entries that differ only\n\t\t// there would be two writes to one file, with the lock claiming both.\n\t\tif (/[. ]$/.test(segment)) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\treason: \"trailing_dot_or_space\",\n\t\t\t\tdetail: input,\n\t\t\t};\n\t\t}\n\t\tif (RESERVED_DEVICE_NAME.test(segment)) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\treason: \"reserved_device_name\",\n\t\t\t\tdetail: input,\n\t\t\t};\n\t\t}\n\t\t// `a.md:stream` addresses an NTFS alternate data stream on `a.md`,\n\t\t// which is a write to a file the manifest never named.\n\t\tif (segment.includes(\":\")) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\treason: \"alternate_data_stream\",\n\t\t\t\tdetail: input,\n\t\t\t};\n\t\t}\n\t}\n\treturn { ok: true, path: input };\n}\n\n/**\n * Is this a path this feature refuses to own, whoever asked?\n *\n * Applied to manifest entries AND to lock entries, on writes AND on deletes:\n * the lock is the thing being defended against here, so checking only what\n * the server sent would miss the case entirely.\n */\nexport function isReservedPath(input: string): boolean {\n\tconst first = input.split(\"/\")[0]?.toLowerCase();\n\tif (RESERVED_ROOTS.some((root) => first === root)) {\n\t\treturn true;\n\t}\n\t// Compared by collision key, not by string: on a case-insensitive\n\t// filesystem `.claude/Settings.Local.json` is the same file, and a\n\t// manifest that spells it differently must not slip past.\n\tconst key = collisionKey(input);\n\treturn RESERVED_EXACT_PATHS.some(\n\t\t(reserved) => collisionKey(reserved) === key,\n\t);\n}\n\n/**\n * A key two paths share when the filesystem would treat them as one file.\n *\n * macOS stores names in a normalised form and compares case-insensitively,\n * so `café.md` written as NFC and as NFD are one file with two spellings,\n * and `README.md`/`readme.md` are one file. The server's own collision check\n * catches ordinary case variants; it does not catch Unicode normalisation.\n *\n * Deliberately conservative and platform-independent: a manifest that would\n * collide on macOS is refused on Linux too, because the alternative is a\n * tree that syncs cleanly for one developer and silently loses a file for\n * the next.\n */\nexport function collisionKey(input: string): string {\n\treturn input.normalize(\"NFC\").toLowerCase();\n}\n\n/**\n * The first pair of manifest/lock paths that name the same file, or null.\n */\nexport function findCollision(\n\tpaths: readonly string[],\n): { first: string; second: string } | null {\n\tconst seen = new Map<string, string>();\n\tfor (const candidate of paths) {\n\t\tconst key = collisionKey(candidate);\n\t\tconst previous = seen.get(key);\n\t\tif (previous !== undefined) {\n\t\t\treturn { first: previous, second: candidate };\n\t\t}\n\t\tseen.set(key, candidate);\n\t}\n\treturn null;\n}\n\n/** A one-line reason a reader can act on. */\nexport function describeRejection(rejection: PathRejection): string {\n\tswitch (rejection.reason) {\n\t\tcase \"empty\":\n\t\t\treturn `empty or malformed path (${JSON.stringify(rejection.detail)})`;\n\t\tcase \"absolute\":\n\t\t\treturn `absolute path refused: ${rejection.detail}`;\n\t\tcase \"traversal\":\n\t\t\treturn `path traversal refused: ${rejection.detail}`;\n\t\tcase \"backslash\":\n\t\t\treturn `backslash in path refused: ${rejection.detail}`;\n\t\tcase \"control_char\":\n\t\t\treturn `control character in path refused: ${JSON.stringify(rejection.detail)}`;\n\t\tcase \"trailing_separator\":\n\t\t\treturn `path names a directory, not a file: ${rejection.detail}`;\n\t\tcase \"trailing_dot_or_space\":\n\t\t\treturn `path segment ending in a dot or space refused: ${rejection.detail}`;\n\t\tcase \"reserved_device_name\":\n\t\t\treturn `reserved device name refused: ${rejection.detail}`;\n\t\tcase \"alternate_data_stream\":\n\t\t\treturn `colon in path refused: ${rejection.detail}`;\n\t\tcase \"reserved_path\":\n\t\t\treturn `this tool never writes or deletes ${RESERVED_ROOTS.join(\", \")} or ${RESERVED_EXACT_PATHS.join(\", \")}: ${rejection.detail}`;\n\t\tcase \"not_a_regular_file\":\n\t\t\treturn `path is not a regular file: ${rejection.detail}`;\n\t\tcase \"escapes_destination\":\n\t\t\treturn `path resolves outside the destination: ${rejection.detail}`;\n\t\tcase \"symlink\":\n\t\t\t// \"follow\", not \"write through\": the same guard now runs for reads\n\t\t\t// — the ledger check and the planner both go through it — and a\n\t\t\t// read-only `check --verify` should not talk about writing.\n\t\t\treturn `refusing to follow a symlink: ${rejection.detail}`;\n\t\tcase \"not_a_directory\":\n\t\t\treturn `a path component is not a directory: ${rejection.detail}`;\n\t\tcase \"collision\":\n\t\t\treturn `two paths name the same file on a case- or Unicode-insensitive filesystem: ${rejection.detail}`;\n\t}\n}\n","/**\n * The one writer every file this feature creates goes through — instruction\n * files, the lock, and the Claude Code settings file alike.\n *\n * It exists because there were three writers before and only one of them was\n * guarded. `.claude -> ..` or `.fabric -> ..` in a checkout turned `init` and\n * `sync` into writes outside the destination, because the hook and the lock\n * never asked the question the instruction files did. A guard that only some\n * writes call is not a guard.\n *\n * What every write proves first:\n *\n * 1. The destination is canonicalised once with `realpath`. Lexical\n * resolution is not enough — `/tmp` is a symlink on macOS, so the\n * literal string a user passes and the directory they mean are\n * routinely different, and containment has to be decided on the real\n * one. The destination itself is resolved rather than refused for that\n * reason; everything BELOW it is held to the stricter rule.\n * 2. No segment between the root and the file is a symlink. Checked with\n * `lstat`, from the first child down to and including the target.\n * 3. The deepest existing ancestor's `realpath` is still inside the root.\n * Layer 2 answers \"is this a link\"; this answers \"did anything else —\n * a bind mount, a replaced directory — move it\".\n * 4. The temp file is created with `wx` and an unpredictable name, so a\n * pre-planted file is an error rather than a file we write through.\n * 5. The parent is re-checked immediately before `rename`, closing the\n * window between the walk and the write.\n *\n * Bytes are preserved exactly: no newline conversion, no re-encoding. The\n * server hashes these files and so does the next sync.\n */\nimport { createHash, randomBytes } from \"node:crypto\";\nimport type { Stats } from \"node:fs\";\nimport type { FileHandle } from \"node:fs/promises\";\nimport {\n\tlstat,\n\tmkdir,\n\topen,\n\treadFile,\n\trealpath,\n\trename,\n\tunlink,\n} from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { describeRejection, type PathCheck } from \"./paths.js\";\n\n/**\n * The modes a published file may carry.\n *\n * The server derives exactly these two from an upload, so anything else is a\n * malformed or hostile manifest rather than a file that needs it. An\n * allow-list rather than a mask, because masking with `0o7777` preserves\n * setuid, setgid, sticky and every write bit — a manifest asking for `04777`\n * would have been honoured.\n */\nconst ALLOWED_MODES = new Set([0o644, 0o755]);\n\nexport function isAllowedMode(mode: number | null | undefined): boolean {\n\tif (mode === null || mode === undefined) {\n\t\treturn true;\n\t}\n\tif (!Number.isInteger(mode) || mode < 0) {\n\t\treturn false;\n\t}\n\t// A manifest records the full `st_mode` (`0o100644`), so compare on the\n\t// permission bits and require the file-type bits to be a regular file or\n\t// absent.\n\tconst type = mode & 0o170000;\n\tif (type !== 0 && type !== 0o100000) {\n\t\treturn false;\n\t}\n\treturn ALLOWED_MODES.has(mode & 0o7777);\n}\n\n/** The permission bits to apply, or null when none were published. */\nexport function permissionBits(mode: number | null | undefined): number | null {\n\tif (mode === null || mode === undefined) {\n\t\treturn null;\n\t}\n\treturn mode & 0o7777;\n}\n\n/**\n * Canonicalise the destination once, for every subsequent check to resolve\n * against. Created if missing: `--dest` naming a directory that does not\n * exist yet is an ordinary first sync.\n */\nexport async function resolveDestinationRoot(\n\tdestination: string,\n): Promise<string> {\n\tawait mkdir(destination, { recursive: true });\n\treturn realpath(destination);\n}\n\n/**\n * Where a relative path lands under an already-canonical root, or why it may\n * not land at all. `relativePath` must already have passed\n * `checkRelativePath`.\n */\nexport async function assertSafeTarget(\n\troot: string,\n\trelativePath: string,\n): Promise<PathCheck> {\n\tconst target = path.resolve(root, relativePath);\n\tif (target === root || !target.startsWith(root + path.sep)) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\treason: \"escapes_destination\",\n\t\t\tdetail: relativePath,\n\t\t};\n\t}\n\n\tconst segments = relativePath.split(\"/\");\n\tlet current = root;\n\tlet deepestExisting = root;\n\tfor (const [index, segment] of segments.entries()) {\n\t\tcurrent = path.join(current, segment);\n\t\tconst stats = await lstatOrNull(current);\n\t\tif (stats === null) {\n\t\t\t// Everything below here is about to be created, and a path that\n\t\t\t// does not exist cannot be a link to somewhere else.\n\t\t\tbreak;\n\t\t}\n\t\tif (stats.isSymbolicLink()) {\n\t\t\treturn { ok: false, reason: \"symlink\", detail: current };\n\t\t}\n\t\t// An ANCESTOR that is not a directory. `lstat` on anything below it\n\t\t// answers ENOTDIR, which used to read as \"absent\" — so a regular file\n\t\t// at `z` let `z/child.md` pass the whole-plan preflight and fail in\n\t\t// `makeParents` after earlier entries had already been written.\n\t\tif (index < segments.length - 1 && !stats.isDirectory()) {\n\t\t\treturn { ok: false, reason: \"not_a_directory\", detail: current };\n\t\t}\n\t\tdeepestExisting = current;\n\t}\n\n\t// Layer 3. `lstat` said no component IS a link; this says the components\n\t// still resolve where they appeared to.\n\tif (deepestExisting !== root) {\n\t\tconst canonical = await realpath(deepestExisting).catch(() => null);\n\t\tif (\n\t\t\tcanonical !== null &&\n\t\t\tcanonical !== root &&\n\t\t\t!canonical.startsWith(root + path.sep)\n\t\t) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\treason: \"escapes_destination\",\n\t\t\t\tdetail: relativePath,\n\t\t\t};\n\t\t}\n\t}\n\n\treturn { ok: true, path: target };\n}\n\n/**\n * `assertSafeTarget`, plus: whatever is already at the final path must be an\n * ordinary file.\n *\n * `assertSafeTarget` answers \"may this land here\" — no symlinked component,\n * nothing resolving outside the root. It does not answer \"is the thing\n * already there a file\". A directory at a manifest path passed it, and the\n * eventual `rename` refused, but only after earlier entries in the same plan\n * had already been written. A fifo, socket or device node would be opened and\n * written through. Both are now refusals, and the caller runs this over EVERY\n * manifest and delete path before it mutates anything.\n */\nexport async function assertWritableTarget(\n\troot: string,\n\trelativePath: string,\n): Promise<PathCheck> {\n\tconst check = await assertSafeTarget(root, relativePath);\n\tif (!check.ok) {\n\t\treturn check;\n\t}\n\tconst stats = await lstatOrNull(check.path);\n\tif (stats === null) {\n\t\treturn check;\n\t}\n\tif (stats.isSymbolicLink()) {\n\t\treturn { ok: false, reason: \"symlink\", detail: check.path };\n\t}\n\tif (!stats.isFile()) {\n\t\treturn { ok: false, reason: \"not_a_regular_file\", detail: check.path };\n\t}\n\treturn check;\n}\n\n/**\n * Read a file under an already-canonical root, through the same guard every\n * write goes through, or `null` when it is not there.\n *\n * READS need the walk as much as writes do. The ledger check and the planner\n * used to `path.join` and `lstat` directly, which meant a lock path of\n * `../outside` read outside the destination, and an ancestor replaced by a\n * symlink was followed to wherever it pointed — hashing, and possibly loading\n * into memory, a file this tool has no business opening. A refusal is the\n * answer in both cases, not a hash.\n */\nexport async function readFileSafely(\n\troot: string,\n\trelativePath: string,\n): Promise<{ bytes: Uint8Array; mode: number } | null> {\n\tconst check = await assertWritableTarget(root, relativePath);\n\tif (!check.ok) {\n\t\tthrow new Error(`Refusing to sync: ${describeRejection(check)}.`);\n\t}\n\tconst stats = await lstatOrNull(check.path);\n\tif (stats === null) {\n\t\treturn null;\n\t}\n\ttry {\n\t\treturn { bytes: await readFile(check.path), mode: stats.mode };\n\t} catch (error) {\n\t\t// Removed between the `lstat` and the `open`: absent is the honest\n\t\t// answer, and the caller plans to write it.\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n\t\t\treturn null;\n\t\t}\n\t\tthrow error;\n\t}\n}\n\n/**\n * The canonical form of a destination that must NOT be created.\n *\n * `resolveDestinationRoot` makes the directory, which is right for a sync and\n * wrong for `check`, an informational command. A destination that does not\n * exist has no lock either, so the literal resolved path is a fine answer.\n */\nexport async function resolveExistingRoot(\n\tdestination: string,\n): Promise<string> {\n\treturn realpath(destination).catch(() => path.resolve(destination));\n}\n\n/**\n * Create every missing parent directory of `relativePath`, one segment at a\n * time, refusing a symlink at each step.\n *\n * `mkdir(..., { recursive: true })` cannot be used for this: it follows an\n * existing symlinked component silently, which is the whole thing being\n * defended against.\n */\nasync function makeParents(root: string, relativePath: string): Promise<void> {\n\tconst segments = relativePath.split(\"/\").slice(0, -1);\n\tlet current = root;\n\tfor (const segment of segments) {\n\t\tcurrent = path.join(current, segment);\n\t\tconst stats = await lstatOrNull(current);\n\t\tif (stats === null) {\n\t\t\tawait mkdir(current).catch(async (error: NodeJS.ErrnoException) => {\n\t\t\t\t// A concurrent writer got there first. Re-check what landed\n\t\t\t\t// rather than assuming it is a directory.\n\t\t\t\tif (error.code !== \"EEXIST\") {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\tconst raced = await lstatOrNull(current);\n\t\t\t\tif (raced?.isSymbolicLink()) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Refusing to sync: ${describeRejection({ ok: false, reason: \"symlink\", detail: current })}.`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tif (stats.isSymbolicLink()) {\n\t\t\tthrow new Error(\n\t\t\t\t`Refusing to sync: ${describeRejection({ ok: false, reason: \"symlink\", detail: current })}.`,\n\t\t\t);\n\t\t}\n\t\tif (!stats.isDirectory()) {\n\t\t\tthrow new Error(\n\t\t\t\t`Refusing to sync: ${describeRejection({ ok: false, reason: \"not_a_directory\", detail: current })}.`,\n\t\t\t);\n\t\t}\n\t}\n}\n\n/**\n * Write one file atomically under an already-canonical root.\n *\n * `relativePath` must have passed `checkRelativePath` and any policy check\n * the caller owns (reserved paths, collisions) BEFORE this is called — this\n * function enforces the filesystem invariants, not the feature's rules.\n */\nexport async function writeFileSafely(input: {\n\troot: string;\n\trelativePath: string;\n\tbytes: Uint8Array;\n\tmode?: number | null;\n}): Promise<void> {\n\tconst check = await assertSafeTarget(input.root, input.relativePath);\n\tif (!check.ok) {\n\t\tthrow new Error(`Refusing to sync: ${describeRejection(check)}.`);\n\t}\n\tif (!isAllowedMode(input.mode)) {\n\t\tthrow new Error(\n\t\t\t`Refusing to sync: ${input.relativePath} asks for file mode ${(input.mode ?? 0).toString(8)}, and only 644 and 755 are accepted.`,\n\t\t);\n\t}\n\n\tawait makeParents(input.root, input.relativePath);\n\n\tconst target = check.path;\n\tconst directory = path.dirname(target);\n\t// The identity of the directory we are about to create the temp file in.\n\t// Cleanup below unlinks BY PATH, and a path no longer names the same\n\t// directory once something has swapped it; unlinking then would delete a\n\t// stranger's file and leave the real temp behind. Node has no\n\t// handle-relative unlink, so the next best thing is to refuse to clean up\n\t// through a path that has moved.\n\tconst directoryBefore = await lstatOrNull(directory);\n\t// Unpredictable, so a pre-planted temp file cannot be waiting for us, and\n\t// `wx` so creating one that already exists is an error rather than a\n\t// write through whatever is there.\n\tconst temporary = path.join(\n\t\tdirectory,\n\t\t`.${path.basename(target)}.${randomBytes(8).toString(\"hex\")}.tmp`,\n\t);\n\n\tlet handle: FileHandle | null = null;\n\ttry {\n\t\thandle = await open(temporary, \"wx\", 0o600);\n\t\tawait handle.writeFile(input.bytes);\n\t\tconst bits = permissionBits(input.mode);\n\t\tif (bits !== null && process.platform !== \"win32\") {\n\t\t\tawait handle.chmod(bits);\n\t\t}\n\t\tawait handle.close();\n\t\thandle = null;\n\n\t\t// The walk above happened before the file was written. Re-check the\n\t\t// parent now, so a directory swapped for a link in between cannot\n\t\t// receive the rename.\n\t\tconst parentStats = await lstatOrNull(directory);\n\t\tif (parentStats === null || parentStats.isSymbolicLink()) {\n\t\t\tthrow new Error(\n\t\t\t\t`Refusing to sync: ${describeRejection({ ok: false, reason: \"symlink\", detail: directory })}.`,\n\t\t\t);\n\t\t}\n\t\tconst targetStats = await lstatOrNull(target);\n\t\tif (targetStats?.isSymbolicLink()) {\n\t\t\tthrow new Error(\n\t\t\t\t`Refusing to sync: ${describeRejection({ ok: false, reason: \"symlink\", detail: target })}.`,\n\t\t\t);\n\t\t}\n\n\t\tawait rename(temporary, target);\n\t} catch (error) {\n\t\tawait handle?.close().catch(() => {});\n\t\tif (await isSameDirectory(directory, directoryBefore)) {\n\t\t\tawait unlink(temporary).catch(() => {});\n\t\t}\n\t\tthrow error;\n\t}\n}\n\n/** Does this path still name the directory we checked earlier? */\nasync function isSameDirectory(\n\tdirectory: string,\n\tbefore: Stats | null,\n): Promise<boolean> {\n\tif (before === null) {\n\t\treturn false;\n\t}\n\tconst now = await lstatOrNull(directory);\n\treturn now !== null && now.dev === before.dev && now.ino === before.ino;\n}\n\nexport type DeleteOutcome = \"deleted\" | \"missing\" | \"modified\";\n\n/**\n * Remove one file under an already-canonical root — but only if it is still\n * the file the caller decided to remove.\n *\n * The plan hashes a departed file during planning, and a download, an\n * extraction and every write happen between then and here. An unconditional\n * `unlink` therefore deleted whatever was at that path by the time it ran,\n * including an edit the developer had saved in the meantime. The expected\n * hash travels with the request and is checked against the bytes on disk\n * immediately before the unlink; a file that no longer matches is left alone\n * and reported as kept.\n *\n * Residual, stated rather than hidden: a write landing between that hash and\n * the `unlink` is still lost. Node offers no way to unlink a specific inode,\n * so closing it entirely would need handle-relative syscalls the runtime does\n * not expose. Concurrent mutation of the destination by the same user during\n * a sync is out of scope for this tool.\n */\nexport async function deleteFileSafely(\n\troot: string,\n\trelativePath: string,\n\texpectedSha256: string,\n): Promise<DeleteOutcome> {\n\tconst check = await assertSafeTarget(root, relativePath);\n\tif (!check.ok) {\n\t\tthrow new Error(`Refusing to sync: ${describeRejection(check)}.`);\n\t}\n\n\tconst stats = await lstatOrNull(check.path);\n\tif (stats === null) {\n\t\treturn \"missing\";\n\t}\n\tif (stats.isSymbolicLink()) {\n\t\tthrow new Error(\n\t\t\t`Refusing to sync: ${describeRejection({ ok: false, reason: \"symlink\", detail: check.path })}.`,\n\t\t);\n\t}\n\tif (!stats.isFile()) {\n\t\tthrow new Error(\n\t\t\t`Refusing to sync: ${describeRejection({ ok: false, reason: \"not_a_regular_file\", detail: check.path })}.`,\n\t\t);\n\t}\n\n\tlet actual: string;\n\ttry {\n\t\tactual = createHash(\"sha256\")\n\t\t\t.update(await readFile(check.path))\n\t\t\t.digest(\"hex\");\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n\t\t\treturn \"missing\";\n\t\t}\n\t\tthrow error;\n\t}\n\tif (actual !== expectedSha256) {\n\t\treturn \"modified\";\n\t}\n\n\ttry {\n\t\tawait unlink(check.path);\n\t\treturn \"deleted\";\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n\t\t\treturn \"missing\";\n\t\t}\n\t\tthrow error;\n\t}\n}\n\n/**\n * `lstat`, with ONLY `ENOENT` meaning \"nothing there\".\n *\n * `ENOTDIR` used to be folded in here, and it does not mean the same thing at\n * all: it means an ancestor exists and is not a directory. Reading it as\n * \"absent\" is what let a regular file at `z` pass the preflight for\n * `z/child.md`. Callers that walk a path check the ancestors themselves; this\n * one lets the error through so nothing can mistake the two again.\n */\nasync function lstatOrNull(target: string) {\n\ttry {\n\t\treturn await lstat(target);\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n\t\t\treturn null;\n\t\t}\n\t\tthrow error;\n\t}\n}\n\n/**\n * Does `candidate` sit inside `root` once both are resolved as far as the\n * filesystem allows?\n *\n * Used for the credential check in `hook.ts`, where the question is about a\n * path that may not exist yet and whose ancestors may be links. Lexical\n * comparison answered it wrongly in both directions: a config file reached\n * through a symlink into the checkout looked outside it, and a destination\n * under a symlinked parent looked like a mismatch.\n */\nexport async function resolvesInside(\n\troot: string,\n\tcandidate: string,\n): Promise<boolean> {\n\tconst canonicalRoot = await realpath(root).catch(() => path.resolve(root));\n\tconst canonicalCandidate = await realpathDeepest(candidate);\n\treturn (\n\t\tcanonicalCandidate === canonicalRoot ||\n\t\tcanonicalCandidate.startsWith(canonicalRoot + path.sep)\n\t);\n}\n\n/**\n * `realpath` of the deepest existing ancestor, with the not-yet-existing tail\n * appended. `realpath` throws on a missing path, and a config file that has\n * not been written yet still has an answer worth having.\n */\nasync function realpathDeepest(candidate: string): Promise<string> {\n\tconst absolute = path.resolve(candidate);\n\tconst tail: string[] = [];\n\tlet current = absolute;\n\tfor (;;) {\n\t\tconst resolved = await realpath(current).catch(() => null);\n\t\tif (resolved !== null) {\n\t\t\treturn tail.length === 0 ? resolved : path.join(resolved, ...tail);\n\t\t}\n\t\tconst parent = path.dirname(current);\n\t\tif (parent === current) {\n\t\t\treturn absolute;\n\t\t}\n\t\ttail.unshift(path.basename(current));\n\t\tcurrent = parent;\n\t}\n}\n","/**\n * Fetching and unpacking the published bundle.\n *\n * The archive is held in memory and never written to disk as an archive. A\n * temp zip on disk would be one more thing to clean up after an interrupted\n * run — but \"in memory\" only works while the size is bounded by something the\n * CLIENT decided, which is what `maxBytes` is. The response body is read in\n * chunks and abandoned the moment it exceeds that; `arrayBuffer()` buffered\n * whatever the server sent before anything could look at it, so a malformed\n * or hostile response sized the allocation itself.\n *\n * Only the paths the plan asked for are extracted, and the manifest's own\n * sizes bound the decompression. The filter is the only place that runs\n * before `fflate` allocates, so per-entry and aggregate limits belong there\n * rather than after the fact: the sha256 check in `apply.ts` catches\n * substituted CONTENT, but it runs on bytes that have already been\n * decompressed into memory.\n */\nimport { unzipSync } from \"fflate\";\n\nexport interface FetchBundleOptions {\n\t/** Per-attempt budget when no shared signal is supplied. */\n\ttimeoutMs: number;\n\t/**\n\t * The most compressed bytes worth reading, from `maxArchiveBytes`. A\n\t * declared `Content-Length` above it is refused before the body is read;\n\t * a body that grows past it is abandoned mid-stream.\n\t */\n\tmaxBytes: number;\n\t/**\n\t * A deadline owned by the caller. In hook mode one signal covers the\n\t * manifest call and this download together, so the whole command has a\n\t * single absolute bound rather than one per request.\n\t */\n\tsignal?: AbortSignal;\n\t/** Injectable for tests; defaults to the global fetch. */\n\tfetchImpl?: typeof fetch;\n}\n\nexport async function fetchBundle(\n\turl: string,\n\toptions: FetchBundleOptions,\n): Promise<Uint8Array> {\n\tconst fetchImpl = options.fetchImpl ?? fetch;\n\tconst controller = new AbortController();\n\tconst timer = setTimeout(() => controller.abort(), options.timeoutMs);\n\tconst onExternalAbort = () => controller.abort();\n\toptions.signal?.addEventListener(\"abort\", onExternalAbort, { once: true });\n\tif (options.signal?.aborted) {\n\t\tcontroller.abort();\n\t}\n\ttry {\n\t\tconst response = await fetchImpl(url, { signal: controller.signal });\n\t\tif (!response.ok) {\n\t\t\tthrow new Error(\n\t\t\t\t`Downloading the coding-instructions bundle failed with HTTP ${response.status}.`,\n\t\t\t);\n\t\t}\n\n\t\tconst declared = Number(response.headers.get(\"content-length\"));\n\t\tif (Number.isFinite(declared) && declared > options.maxBytes) {\n\t\t\tthrow new Error(\n\t\t\t\t`The coding-instructions bundle declares ${declared} bytes and this snapshot's manifest allows at most ${options.maxBytes}. Nothing was written.`,\n\t\t\t);\n\t\t}\n\n\t\treturn await readBounded(response, options.maxBytes);\n\t} catch (error) {\n\t\tif (error instanceof Error && error.name === \"AbortError\") {\n\t\t\tthrow new Error(\n\t\t\t\t`Downloading the coding-instructions bundle timed out after ${options.timeoutMs}ms.`,\n\t\t\t);\n\t\t}\n\t\tthrow error;\n\t} finally {\n\t\tclearTimeout(timer);\n\t\toptions.signal?.removeEventListener(\"abort\", onExternalAbort);\n\t}\n}\n\n/**\n * Read a response body, refusing it the moment it passes `maxBytes`.\n *\n * The cap is compared against bytes ALREADY RECEIVED, so the refusal costs at\n * most one chunk beyond it rather than the whole body. A response with no\n * readable stream — an older polyfill, a test double built from a string —\n * falls back to `arrayBuffer()` and is length-checked after the fact, which\n * is the best available answer when the body cannot be consumed in pieces.\n */\nasync function readBounded(\n\tresponse: Response,\n\tmaxBytes: number,\n): Promise<Uint8Array> {\n\tconst body = response.body;\n\tif (!body) {\n\t\tconst bytes = new Uint8Array(await response.arrayBuffer());\n\t\tif (bytes.length > maxBytes) {\n\t\t\tthrow new Error(\n\t\t\t\t`The coding-instructions bundle is larger than the ${maxBytes} bytes this snapshot's manifest allows. Nothing was written.`,\n\t\t\t);\n\t\t}\n\t\treturn bytes;\n\t}\n\n\tconst reader = body.getReader();\n\tconst chunks: Uint8Array[] = [];\n\tlet total = 0;\n\ttry {\n\t\tfor (;;) {\n\t\t\tconst { done, value } = await reader.read();\n\t\t\tif (done) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (!value) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\ttotal += value.length;\n\t\t\tif (total > maxBytes) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`The coding-instructions bundle is larger than the ${maxBytes} bytes this snapshot's manifest allows. Nothing was written.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tchunks.push(value);\n\t\t}\n\t} finally {\n\t\tawait reader.cancel().catch(() => {});\n\t}\n\n\tconst archive = new Uint8Array(total);\n\tlet offset = 0;\n\tfor (const chunk of chunks) {\n\t\tarchive.set(chunk, offset);\n\t\toffset += chunk.length;\n\t}\n\treturn archive;\n}\n\nexport interface WantedEntry {\n\tpath: string;\n\t/** The manifest's size for this path, in bytes. */\n\tsize: number;\n}\n\n/**\n * Extract exactly the wanted paths, within exactly the wanted sizes.\n *\n * A zip entry name is matched literally against the manifest path. Nothing\n * here normalises, joins or resolves anything — a name that does not appear\n * in `wanted` is simply not returned, so an archive carrying `../../etc/x`\n * cannot reach the filesystem even before the path guard sees it.\n *\n * Three bounds, all enforced inside the filter so a hostile archive is\n * refused before it is decompressed:\n *\n * - a name the manifest does not list is skipped;\n * - an entry whose declared original size is not the manifest's size for\n * that path is refused (a zip bomb declaring 4 GB for a 200-byte file\n * never gets allocated);\n * - a second entry with a wanted name is refused rather than allowed to\n * win, which is what \"last one wins\" would otherwise let it do.\n */\nexport function extractBundle(\n\tarchive: Uint8Array,\n\twanted: Iterable<WantedEntry>,\n): Map<string, Uint8Array> {\n\tconst sizes = new Map<string, number>();\n\tfor (const entry of wanted) {\n\t\tsizes.set(entry.path, entry.size);\n\t}\n\tif (sizes.size === 0) {\n\t\treturn new Map();\n\t}\n\n\tconst seen = new Set<string>();\n\tconst unzipped = unzipSync(archive, {\n\t\tfilter: (file) => {\n\t\t\tconst expected = sizes.get(file.name);\n\t\t\tif (expected === undefined) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (seen.has(file.name)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`The downloaded bundle contains ${file.name} more than once. Nothing was written.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tseen.add(file.name);\n\t\t\tif (\n\t\t\t\tfile.originalSize !== undefined &&\n\t\t\t\tfile.originalSize !== expected\n\t\t\t) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`The downloaded bundle declares ${file.originalSize} bytes for ${file.name} and the manifest says ${expected}. Nothing was written.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\t});\n\n\tconst contents = new Map<string, Uint8Array>();\n\tfor (const [name, bytes] of Object.entries(unzipped)) {\n\t\tconst expected = sizes.get(name);\n\t\tif (expected === undefined) {\n\t\t\tcontinue;\n\t\t}\n\t\t// The declared size is a claim; this is the measurement.\n\t\tif (bytes.length !== expected) {\n\t\t\tthrow new Error(\n\t\t\t\t`The downloaded bundle holds ${bytes.length} bytes for ${name} and the manifest says ${expected}. Nothing was written.`,\n\t\t\t);\n\t\t}\n\t\tcontents.set(name, bytes);\n\t}\n\treturn contents;\n}\n","/**\n * The Claude Code SessionStart hook that keeps a checkout current.\n *\n * Written into `.claude/settings.local.json` and NEVER `settings.json`. The\n * local file is per-developer and normally untracked; the shared one is\n * committed, and a hook committed into a repository runs on everybody's\n * machine with whatever credentials they happen to have.\n *\n * The command never carries the key. It names a project and nothing else —\n * the CLI reads its credential from `FABRIC_API_KEY` or from the per-user\n * config file, both outside the repository. `assertKeyStaysOutside` is what\n * makes that a guarantee rather than a habit, and it compares REAL paths:\n * a config directory reached through a symlink into the checkout is inside\n * it however the string is spelled.\n *\n * `matcher` is deliberately omitted so the hook runs on startup, resume,\n * clear and compact alike: a session resumed after a pull is exactly when the\n * published version is most likely to have moved.\n */\nimport { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { resolvesInside, writeFileSafely } from \"./safe-write.js\";\n\nexport const CLAUDE_SETTINGS_RELATIVE_PATH = path.join(\n\t\".claude\",\n\t\"settings.local.json\",\n);\n\n/** The same path in the POSIX spelling the guarded writer expects. */\nconst CLAUDE_SETTINGS_POSIX_PATH = \".claude/settings.local.json\";\n\n/** Seconds. Long enough for a cold start plus one manifest call, short enough to be invisible. */\nconst HOOK_TIMEOUT_SECONDS = 15;\n\n/** The subcommands a hook this tool wrote may name. */\nconst HOOK_SUBCOMMANDS = new Set([\"check\", \"sync\"]);\n\ninterface CommandHook {\n\ttype: \"command\";\n\tcommand: string;\n\ttimeout?: number;\n\t[key: string]: unknown;\n}\n\ninterface HookGroup {\n\tmatcher?: string;\n\thooks: CommandHook[];\n\t[key: string]: unknown;\n}\n\nexport interface MergeHookResult {\n\tsettingsPath: string;\n\tcommand: string;\n\t/** True when the settings file did not exist before. */\n\tcreatedFile: boolean;\n\t/** How many existing Fabric hooks for this project were replaced or dropped. */\n\treplacedCount: number;\n}\n\n/**\n * The command the session hook runs.\n *\n * An explicit `--org` is carried through when `init` was given one. These\n * commands do not consult a stored default context, so a slug that was\n * supplied once on the command line has nowhere else to live — leaving it out\n * would install a hook that binds differently from the `init` that created\n * it. It still never carries the key.\n */\nexport function buildHookCommand(\n\tprojectId: string,\n\tapply: boolean,\n\torg?: string,\n): string {\n\tconst verb = apply ? \"sync\" : \"check\";\n\tconst context = org ? ` --org ${org}` : \"\";\n\treturn `fabric instructions ${verb} --project ${projectId}${context} --hook`;\n}\n\n/**\n * Would writing this hook put the API key inside the repository?\n *\n * The hook itself carries no key, so the only way one lands in the tree is\n * the CLI's own config file being stored there — which happens when\n * `XDG_CONFIG_HOME` or `APPDATA` points inside the checkout, including\n * through a symlink. Refuse rather than write a hook whose credential source\n * a `git add -A` would commit.\n */\nexport async function assertKeyStaysOutside(\n\tdestination: string,\n\tconfigPath: string,\n): Promise<void> {\n\tif (await resolvesInside(destination, configPath)) {\n\t\tthrow new Error(\n\t\t\t`The CLI stores its API key at ${configPath}, which resolves inside ${destination}. Writing a session hook here would leave a live credential in the repository. Move the CLI config outside the project (set XDG_CONFIG_HOME) or export FABRIC_API_KEY instead, then run this again.`,\n\t\t);\n\t}\n}\n\n/**\n * Add — or replace — the Fabric SessionStart hook for one project.\n *\n * Idempotent by project id, and idempotent across a file that already has\n * duplicates: EVERY matching entry is removed and exactly one is written\n * back. Matching is on parsed argv tokens, not on a substring — `--project\n * abc` must not match `--project abc-extra`, and `--project=abc` is the same\n * request written differently. Every other key in the file, and every other\n * hook, is preserved exactly.\n */\nexport async function mergeSessionStartHook(input: {\n\t/** An already-canonical destination from `resolveDestinationRoot`. */\n\troot: string;\n\tprojectId: string;\n\tcommand: string;\n}): Promise<MergeHookResult> {\n\tconst settingsPath = path.join(input.root, CLAUDE_SETTINGS_RELATIVE_PATH);\n\n\tlet existingRaw: string | null = null;\n\ttry {\n\t\texistingRaw = await readFile(settingsPath, \"utf8\");\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tlet settings: Record<string, unknown> = {};\n\tif (existingRaw !== null && existingRaw.trim().length > 0) {\n\t\tlet parsed: unknown;\n\t\ttry {\n\t\t\tparsed = JSON.parse(existingRaw);\n\t\t} catch {\n\t\t\t// Refused, never rewritten: this file is the developer's own, and\n\t\t\t// a JSON error in it is nearly always a half-finished edit rather\n\t\t\t// than something to discard.\n\t\t\tthrow new Error(\n\t\t\t\t`${settingsPath} is not valid JSON. Fix or remove it, then run this again — it was left untouched.`,\n\t\t\t);\n\t\t}\n\t\tif (\n\t\t\ttypeof parsed !== \"object\" ||\n\t\t\tparsed === null ||\n\t\t\tArray.isArray(parsed)\n\t\t) {\n\t\t\tthrow new Error(\n\t\t\t\t`${settingsPath} does not contain a JSON object. It was left untouched.`,\n\t\t\t);\n\t\t}\n\t\tsettings = parsed as Record<string, unknown>;\n\t}\n\n\t// Every nested shape is checked before anything is rebuilt. Top-level JSON\n\t// was refused carefully and these were not: `{\"hooks\": [\"custom\"]}` or a\n\t// `SessionStart` that is not an array used to be replaced with a\n\t// freshly-built hooks object, discarding whatever the developer had. A\n\t// shape this tool does not understand is no more ours to normalise than a\n\t// half-finished edit is.\n\tif (settings.hooks !== undefined && !isRecord(settings.hooks)) {\n\t\tthrow refuseShape(settingsPath, '\"hooks\" is not an object');\n\t}\n\tconst hooks = isRecord(settings.hooks) ? { ...settings.hooks } : {};\n\tif (\n\t\thooks.SessionStart !== undefined &&\n\t\t!Array.isArray(hooks.SessionStart)\n\t) {\n\t\tthrow refuseShape(settingsPath, '\"hooks.SessionStart\" is not an array');\n\t}\n\tconst rawGroups = Array.isArray(hooks.SessionStart)\n\t\t? hooks.SessionStart\n\t\t: [];\n\tfor (const [index, group] of rawGroups.entries()) {\n\t\tif (!isRecord(group)) {\n\t\t\tthrow refuseShape(\n\t\t\t\tsettingsPath,\n\t\t\t\t`\"hooks.SessionStart[${index}]\" is not an object`,\n\t\t\t);\n\t\t}\n\t\tif (group.hooks !== undefined && !Array.isArray(group.hooks)) {\n\t\t\tthrow refuseShape(\n\t\t\t\tsettingsPath,\n\t\t\t\t`\"hooks.SessionStart[${index}].hooks\" is not an array`,\n\t\t\t);\n\t\t}\n\t}\n\tconst sessionStart: HookGroup[] = (rawGroups as HookGroup[]).map(\n\t\t(group) => ({\n\t\t\t...group,\n\t\t\thooks: Array.isArray(group?.hooks) ? [...group.hooks] : [],\n\t\t}),\n\t);\n\n\tconst replacement: CommandHook = {\n\t\ttype: \"command\",\n\t\tcommand: input.command,\n\t\ttimeout: HOOK_TIMEOUT_SECONDS,\n\t};\n\n\t// Remove EVERY entry for this project first, then add one back. Replacing\n\t// in place and stopping at the first match left duplicates behind, and a\n\t// file that has accumulated two of our hooks should come out with one.\n\tlet replacedCount = 0;\n\tconst pruned: HookGroup[] = [];\n\tfor (const group of sessionStart) {\n\t\tconst kept = group.hooks.filter(\n\t\t\t(hook) => !isFabricHookFor(hook, input.projectId),\n\t\t);\n\t\tconst removed = group.hooks.length - kept.length;\n\t\treplacedCount += removed;\n\t\t// A group we emptied held nothing but our own hook; leaving\n\t\t// `{hooks: []}` behind would accumulate one husk per run. A group\n\t\t// that was ALREADY empty is somebody else's and is kept untouched,\n\t\t// which is why this turns on `removed` rather than on length alone.\n\t\tif (kept.length === 0 && removed > 0) {\n\t\t\tcontinue;\n\t\t}\n\t\tpruned.push({ ...group, hooks: kept });\n\t}\n\n\tpruned.push({ hooks: [replacement] });\n\n\tconst next = {\n\t\t...settings,\n\t\thooks: { ...hooks, SessionStart: pruned },\n\t};\n\n\tawait writeFileSafely({\n\t\troot: input.root,\n\t\trelativePath: CLAUDE_SETTINGS_POSIX_PATH,\n\t\tbytes: new TextEncoder().encode(\n\t\t\t`${JSON.stringify(next, null, 2).replace(/\\r\\n/g, \"\\n\")}\\n`,\n\t\t),\n\t});\n\n\treturn {\n\t\tsettingsPath,\n\t\tcommand: input.command,\n\t\tcreatedFile: existingRaw === null,\n\t\treplacedCount,\n\t};\n}\n\n/**\n * Is this hook one this tool wrote for this project?\n *\n * Token-exact. The command is split on whitespace — every command this tool\n * generates is a plain, unquoted argv line, so a command that needs shell\n * quoting to parse is by definition not ours.\n */\nfunction isFabricHookFor(hook: unknown, projectId: string): boolean {\n\tif (!isRecord(hook) || typeof hook.command !== \"string\") {\n\t\treturn false;\n\t}\n\tconst tokens = hook.command.trim().split(/\\s+/);\n\tif (tokens[0] !== \"fabric\" || tokens[1] !== \"instructions\") {\n\t\treturn false;\n\t}\n\tif (tokens[2] === undefined || !HOOK_SUBCOMMANDS.has(tokens[2])) {\n\t\treturn false;\n\t}\n\treturn readProjectToken(tokens) === projectId;\n}\n\n/**\n * The `--project` value, from either `--project X` or `--project=X`, and only\n * when the command names exactly one.\n *\n * `fabric instructions check --project other --project target --hook` is a\n * command Commander resolves to `target`, while reading the first occurrence\n * answers `other`. Either reading makes this matcher wrong about somebody's\n * hook: merging for `other` would delete a hook that syncs `target`, and\n * merging for `target` would leave that entry behind and add a second. A\n * command this tool did not write is not this tool's to rewrite, so an\n * ambiguous one is left exactly as it is.\n */\nfunction readProjectToken(tokens: string[]): string | null {\n\tlet found: string | null = null;\n\tlet occurrences = 0;\n\tfor (let index = 3; index < tokens.length; index++) {\n\t\tconst token = tokens[index] as string;\n\t\tif (token === \"--project\") {\n\t\t\toccurrences++;\n\t\t\tfound = tokens[index + 1] ?? null;\n\t\t\tcontinue;\n\t\t}\n\t\tif (token.startsWith(\"--project=\")) {\n\t\t\toccurrences++;\n\t\t\tfound = token.slice(\"--project=\".length);\n\t\t}\n\t}\n\treturn occurrences === 1 ? found : null;\n}\n\n/** The same refusal shape as an unparseable file: say what, and touch nothing. */\nfunction refuseShape(settingsPath: string, what: string): Error {\n\treturn new Error(\n\t\t`${settingsPath} has a shape this tool does not recognise: ${what}. Fix or remove it, then run this again — it was left untouched.`,\n\t);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","/**\n * `<dest>/.fabric/instructions.lock` — what the last sync wrote.\n *\n * ## What the lock is, and what it is not\n *\n * It is a CONTENT LEDGER: a list of paths with the hash each one had when\n * this tool last wrote it. It is the only reason the sync may delete\n * anything — a path must be in the ledger AND still hash to what the ledger\n * recorded before it can be removed.\n *\n * It is NOT authenticated. It is a plain JSON file inside the checkout, so\n * anything that can write there can write it. That bounds what a tampered\n * lock can do rather than preventing it: an attacker who can already edit\n * files in the tree can make the next sync delete a file whose CURRENT\n * content hash they name correctly. They cannot make it write anywhere new,\n * because writes come from the server manifest, and they cannot name\n * `.git/**` or `.fabric/**` at all (`isReservedPath`). Closing the rest\n * needs a ledger stored outside the checkout, which is a larger change than\n * this feature.\n *\n * The lock is rewritten LAST, after every write has succeeded. A ledger\n * naming files that are not there would authorise deleting whatever is in\n * their place on the next run.\n */\nimport { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { writeFileSafely } from \"./safe-write.js\";\n\nexport const LOCK_DIRECTORY = \".fabric\";\nexport const LOCK_FILENAME = \"instructions.lock\";\n\n/** Bumped only if the shape below changes incompatibly. */\nexport const LOCK_VERSION = 1;\n\n/** The lock's own path, relative to the destination — never from a manifest. */\nconst LOCK_RELATIVE_PATH = `${LOCK_DIRECTORY}/${LOCK_FILENAME}`;\n\nconst SHA256_HEX = /^[0-9a-f]{64}$/;\n\ninterface LockFileEntry {\n\tsha256: string;\n\t/** POSIX mode as published, or null when the snapshot recorded none. */\n\tmode: number | null;\n}\n\nexport interface InstructionsLock {\n\tversion: number;\n\tprojectId: string;\n\tsnapshotId: string;\n\tsnapshotVersion: number;\n\tdigest: string;\n\t/** ISO 8601 timestamp of the sync that wrote this lock. */\n\tsyncedAt: string;\n\t/** Every path that sync wrote or verified — the manifest at that time. */\n\tfiles: Record<string, LockFileEntry>;\n}\n\nexport function lockPath(destination: string): string {\n\treturn path.join(destination, LOCK_DIRECTORY, LOCK_FILENAME);\n}\n\n/**\n * The lock, or `null` when this tree has never been synced.\n *\n * A lock that exists but does not validate is an ERROR and never a `null`.\n * Treating a damaged ledger as \"never synced\" would orphan every file the\n * previous sync wrote and hide the damage; the caller stops and says so.\n */\nexport async function readLock(\n\tdestination: string,\n): Promise<InstructionsLock | null> {\n\tconst file = lockPath(destination);\n\tlet raw: string;\n\ttry {\n\t\traw = await readFile(file, \"utf8\");\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n\t\t\treturn null;\n\t\t}\n\t\tthrow error;\n\t}\n\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch {\n\t\tthrow new Error(\n\t\t\t`${file} is unreadable: it is not valid JSON. Delete it to start from a clean sync.`,\n\t\t);\n\t}\n\tconst problem = lockProblem(parsed);\n\tif (problem !== null) {\n\t\tthrow new Error(\n\t\t\t`${file} is unreadable: ${problem}. Delete it to start from a clean sync.`,\n\t\t);\n\t}\n\treturn parsed as InstructionsLock;\n}\n\n/** Pretty JSON with LF endings and a trailing newline, so a diff of it reads. */\nfunction serializeLock(lock: InstructionsLock): string {\n\treturn `${JSON.stringify(lock, null, 2).replace(/\\r\\n/g, \"\\n\")}\\n`;\n}\n\n/**\n * Write the lock through the same guarded writer as every instruction file.\n * `root` is an already-canonical destination from `resolveDestinationRoot`:\n * a `.fabric -> ..` symlink is how the lock write used to escape the tree.\n */\nexport async function writeLock(\n\troot: string,\n\tlock: InstructionsLock,\n): Promise<void> {\n\tawait writeFileSafely({\n\t\troot,\n\t\trelativePath: LOCK_RELATIVE_PATH,\n\t\tbytes: new TextEncoder().encode(serializeLock(lock)),\n\t});\n}\n\n/**\n * Why this value is not a lock, or `null` when it is one.\n *\n * Every field is checked, including `version`: a future lock this build does\n * not understand must stop the run rather than be half-read.\n */\nfunction lockProblem(value: unknown): string | null {\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n\t\treturn \"it is not a JSON object\";\n\t}\n\tconst candidate = value as Record<string, unknown>;\n\n\tif (candidate.version !== LOCK_VERSION) {\n\t\treturn `its version is ${JSON.stringify(candidate.version)} and this build writes version ${LOCK_VERSION}`;\n\t}\n\tfor (const field of [\n\t\t\"projectId\",\n\t\t\"snapshotId\",\n\t\t\"digest\",\n\t\t\"syncedAt\",\n\t] as const) {\n\t\tconst actual = candidate[field];\n\t\tif (typeof actual !== \"string\" || actual.length === 0) {\n\t\t\treturn `its \"${field}\" is not a non-empty string`;\n\t\t}\n\t}\n\tif (\n\t\ttypeof candidate.snapshotVersion !== \"number\" ||\n\t\t!Number.isInteger(candidate.snapshotVersion) ||\n\t\tcandidate.snapshotVersion < 0\n\t) {\n\t\treturn 'its \"snapshotVersion\" is not a non-negative integer';\n\t}\n\tif (\n\t\ttypeof candidate.files !== \"object\" ||\n\t\tcandidate.files === null ||\n\t\tArray.isArray(candidate.files)\n\t) {\n\t\treturn 'its \"files\" is not an object';\n\t}\n\n\tfor (const [filePath, entry] of Object.entries(\n\t\tcandidate.files as Record<string, unknown>,\n\t)) {\n\t\tif (\n\t\t\ttypeof entry !== \"object\" ||\n\t\t\tentry === null ||\n\t\t\tArray.isArray(entry)\n\t\t) {\n\t\t\treturn `its entry for ${JSON.stringify(filePath)} is not an object`;\n\t\t}\n\t\tconst record = entry as Record<string, unknown>;\n\t\tif (\n\t\t\ttypeof record.sha256 !== \"string\" ||\n\t\t\t!SHA256_HEX.test(record.sha256)\n\t\t) {\n\t\t\treturn `its entry for ${JSON.stringify(filePath)} has no 64-character hex sha256`;\n\t\t}\n\t\tif (\n\t\t\trecord.mode !== null &&\n\t\t\t(typeof record.mode !== \"number\" ||\n\t\t\t\t!Number.isInteger(record.mode) ||\n\t\t\t\trecord.mode < 0)\n\t\t) {\n\t\t\treturn `its entry for ${JSON.stringify(filePath)} has a mode that is neither null nor a non-negative integer`;\n\t\t}\n\t}\n\treturn null;\n}\n","/**\n * Deciding whether a server response is a manifest at all.\n *\n * An absent manifest used to become `[]`, and an empty manifest means\n * \"delete everything the lock names\". A version-skewed server, a truncated\n * proxy response or a field rename was therefore one step away from wiping\n * the tree and writing an empty ledger. A manifest is now either complete\n * and self-consistent or it is a refusal.\n *\n * Three independent things are checked, because each catches a different\n * failure:\n *\n * - every ENTRY is well-formed, and no two name the same file;\n * - the COUNT matches the snapshot's own `fileCount`, which catches a\n * truncated list that is otherwise perfectly well-formed;\n * - the DIGEST recomputed from the entries matches the snapshot's, which\n * catches a list that is the right length and the wrong content.\n *\n * The digest recipe is the server's (`packages/instructions/src/manifest.ts`):\n * sha256 over `path\\0sha256\\n` lines sorted by path. It is reimplemented\n * here rather than imported because `@repo/instructions` is a private\n * workspace package and this one is published to npm.\n */\nimport { createHash } from \"node:crypto\";\nimport type { InstructionManifestEntry } from \"@fabricorg/sdk\";\nimport {\n\tcheckRelativePath,\n\tdescribeRejection,\n\tfindCollision,\n\tisReservedPath,\n} from \"./paths.js\";\nimport { isAllowedMode } from \"./safe-write.js\";\n\nconst SHA256_HEX = /^[0-9a-f]{64}$/;\n\n/**\n * What a published snapshot can legitimately be.\n *\n * Mirrors `SNAPSHOT_LIMITS` in `packages/instructions/src/limits.ts`, which\n * bounds what publishing will ACCEPT; these bound what a client will act on.\n * Reimplemented rather than imported for the same reason the digest recipe is:\n * that package is private and this one is published to npm.\n *\n * The point is memory, not policy. Before this, `fileCount` and the per-entry\n * sizes were checked against each other but never against an absolute, so a\n * manifest claiming a million files of 4 GB each was internally consistent and\n * sized the download bound off its own claim.\n *\n * `maxPathBytes` and `maxDepth` are deliberately LOOSER than the server's 512\n * and 32: a client that refuses what the server would happily publish breaks\n * the moment those limits are raised, and 1024 bytes across 5000 files is\n * still bounded. Everything else matches exactly.\n */\nconst MANIFEST_LIMITS = {\n\tmaxFiles: 5000,\n\tmaxTotalBytes: 52_428_800,\n\tmaxFileBytes: 5_242_880,\n\tmaxPathBytes: 1024,\n\tmaxDepth: 64,\n} as const;\n\n/**\n * Per-entry zip framing, in bytes, before the path itself.\n *\n * A zip carries each file twice in structure: a 30-byte local header and a\n * 46-byte central-directory header, each followed by the name, plus optional\n * extra fields and a data descriptor. 512 is generous for all of it, and\n * generous is the right direction — this is a ceiling on what will be\n * DOWNLOADED, and a bound that is too tight refuses a snapshot the server\n * considers perfectly valid.\n */\nconst ZIP_ENTRY_OVERHEAD_BYTES = 512;\n\n/**\n * The largest archive worth downloading for this manifest.\n *\n * A flat slack was wrong: zip framing grows with the number of entries and\n * the length of their names, so a legitimate snapshot of 5000 empty files\n * with 200-byte paths needs about 2.4 MB of pure structure and could not be\n * synced at all. The bound now scales the way the format does.\n */\nexport function maxArchiveBytes(\n\tentries: ReadonlyArray<{ path: string; size: number }>,\n): number {\n\tlet total = 1_048_576;\n\tfor (const entry of entries) {\n\t\ttotal +=\n\t\t\tentry.size +\n\t\t\tZIP_ENTRY_OVERHEAD_BYTES +\n\t\t\t2 * Buffer.byteLength(entry.path, \"utf8\");\n\t}\n\treturn total;\n}\n\n/**\n * The snapshot digest, computed the way the server computes it.\n *\n * Keep in step with `computeSnapshotDigest` in `@repo/instructions`. A\n * divergence here turns every sync into a refusal, which is the safe\n * direction but still a break.\n */\nexport function computeSnapshotDigest(\n\tentries: ReadonlyArray<{ path: string; sha256: string }>,\n): string {\n\tconst lines = [...entries]\n\t\t.sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0))\n\t\t.map((entry) => `${entry.path}\\0${entry.sha256}\\n`)\n\t\t.join(\"\");\n\treturn createHash(\"sha256\")\n\t\t.update(Buffer.from(lines, \"utf8\"))\n\t\t.digest(\"hex\");\n}\n\n/**\n * Validate a published manifest, or explain why it is not one.\n *\n * Throws rather than returning a result: every caller's only response to a\n * bad manifest is to stop, and under `--hook` the message becomes the one\n * line a developer sees.\n */\nexport function assertValidManifest(input: {\n\tmanifest: unknown;\n\tsnapshot: { digest: string; fileCount: number; version: number };\n}): InstructionManifestEntry[] {\n\tconst { manifest, snapshot } = input;\n\n\tif (!Array.isArray(manifest)) {\n\t\tthrow new Error(\n\t\t\t`The server described version ${snapshot.version} as published but sent no file manifest. Nothing was changed.`,\n\t\t);\n\t}\n\n\tif (manifest.length > MANIFEST_LIMITS.maxFiles) {\n\t\tthrow new Error(\n\t\t\t`The manifest for version ${snapshot.version} lists ${manifest.length} files and a published snapshot holds at most ${MANIFEST_LIMITS.maxFiles}. Nothing was changed.`,\n\t\t);\n\t}\n\n\tconst entries: InstructionManifestEntry[] = [];\n\tfor (const raw of manifest) {\n\t\tentries.push(validateEntry(raw));\n\t}\n\n\tconst totalBytes = entries.reduce((total, entry) => total + entry.size, 0);\n\tif (totalBytes > MANIFEST_LIMITS.maxTotalBytes) {\n\t\tthrow new Error(\n\t\t\t`The manifest for version ${snapshot.version} describes ${totalBytes} bytes and a published snapshot holds at most ${MANIFEST_LIMITS.maxTotalBytes}. Nothing was changed.`,\n\t\t);\n\t}\n\n\tconst collision = findCollision(entries.map((entry) => entry.path));\n\tif (collision !== null) {\n\t\tthrow new Error(\n\t\t\t`Refusing to sync: ${describeRejection({\n\t\t\t\tok: false,\n\t\t\t\treason: \"collision\",\n\t\t\t\tdetail: `${collision.first} and ${collision.second}`,\n\t\t\t})}.`,\n\t\t);\n\t}\n\n\tif (entries.length !== snapshot.fileCount) {\n\t\tthrow new Error(\n\t\t\t`The manifest for version ${snapshot.version} lists ${entries.length} files and the snapshot says ${snapshot.fileCount}. Nothing was changed.`,\n\t\t);\n\t}\n\n\tconst recomputed = computeSnapshotDigest(entries);\n\tif (recomputed !== snapshot.digest) {\n\t\tthrow new Error(\n\t\t\t`The manifest for version ${snapshot.version} does not match its own digest (${snapshot.digest}); it hashes to ${recomputed}. Nothing was changed.`,\n\t\t);\n\t}\n\n\treturn entries;\n}\n\nfunction validateEntry(raw: unknown): InstructionManifestEntry {\n\tif (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) {\n\t\tthrow new Error(\n\t\t\t\"The server sent a manifest entry that is not an object. Nothing was changed.\",\n\t\t);\n\t}\n\tconst entry = raw as Record<string, unknown>;\n\n\tif (typeof entry.path !== \"string\") {\n\t\tthrow new Error(\n\t\t\t\"The server sent a manifest entry with no path. Nothing was changed.\",\n\t\t);\n\t}\n\tconst check = checkRelativePath(entry.path);\n\tif (!check.ok) {\n\t\tthrow new Error(\n\t\t\t`Refusing to sync: ${describeRejection(check)}. The published snapshot names a path this tool will not write.`,\n\t\t);\n\t}\n\tconst pathBytes = Buffer.byteLength(entry.path, \"utf8\");\n\tif (pathBytes > MANIFEST_LIMITS.maxPathBytes) {\n\t\tthrow new Error(\n\t\t\t`The manifest entry for ${entry.path.slice(0, 80)}… has a ${pathBytes}-byte path and at most ${MANIFEST_LIMITS.maxPathBytes} is accepted. Nothing was changed.`,\n\t\t);\n\t}\n\tif (entry.path.split(\"/\").length > MANIFEST_LIMITS.maxDepth) {\n\t\tthrow new Error(\n\t\t\t`The manifest entry for ${entry.path} is nested deeper than ${MANIFEST_LIMITS.maxDepth} directories. Nothing was changed.`,\n\t\t);\n\t}\n\tif (isReservedPath(entry.path)) {\n\t\tthrow new Error(\n\t\t\t`Refusing to sync: ${describeRejection({\n\t\t\t\tok: false,\n\t\t\t\treason: \"reserved_path\",\n\t\t\t\tdetail: entry.path,\n\t\t\t})}.`,\n\t\t);\n\t}\n\tif (typeof entry.sha256 !== \"string\" || !SHA256_HEX.test(entry.sha256)) {\n\t\tthrow new Error(\n\t\t\t`The manifest entry for ${entry.path} has no 64-character hex sha256. Nothing was changed.`,\n\t\t);\n\t}\n\tif (\n\t\ttypeof entry.size !== \"number\" ||\n\t\t!Number.isInteger(entry.size) ||\n\t\tentry.size < 0\n\t) {\n\t\tthrow new Error(\n\t\t\t`The manifest entry for ${entry.path} has no non-negative integer size. Nothing was changed.`,\n\t\t);\n\t}\n\tif (entry.size > MANIFEST_LIMITS.maxFileBytes) {\n\t\tthrow new Error(\n\t\t\t`The manifest entry for ${entry.path} declares ${entry.size} bytes and a published file holds at most ${MANIFEST_LIMITS.maxFileBytes}. Nothing was changed.`,\n\t\t);\n\t}\n\tif (\n\t\tentry.mode !== null &&\n\t\t(typeof entry.mode !== \"number\" || !Number.isInteger(entry.mode))\n\t) {\n\t\tthrow new Error(\n\t\t\t`The manifest entry for ${entry.path} has a mode that is neither null nor an integer. Nothing was changed.`,\n\t\t);\n\t}\n\tif (!isAllowedMode(entry.mode as number | null)) {\n\t\tthrow new Error(\n\t\t\t`Refusing to sync: ${entry.path} asks for file mode ${((entry.mode as number) ?? 0).toString(8)}, and only 644 and 755 are accepted.`,\n\t\t);\n\t}\n\n\treturn {\n\t\tpath: entry.path,\n\t\tsha256: entry.sha256,\n\t\tsize: entry.size,\n\t\tmode: entry.mode as number | null,\n\t\tkind: (entry.kind ?? \"OTHER\") as InstructionManifestEntry[\"kind\"],\n\t};\n}\n","/**\n * What a sync would do, decided against the LOCAL TREE and not only the lock.\n *\n * The lock says what the last sync wrote; the working tree says what is\n * actually there now. Planning from the lock alone gets both interesting\n * cases wrong — a file the developer edited since the sync would be silently\n * overwritten with no notice, and a file they deleted would never come back\n * because the lock still claims it is present. So every path is hashed.\n *\n * Seven outcomes, and the distinctions between them are the whole point:\n *\n * verified local bytes already equal the published bytes — no write\n * added nothing local — a new file\n * updated local matches the lock, so this is the sync's own file\n * moving forward\n * replaced local matches neither the lock nor the manifest — local\n * edits are about to be overwritten, and the report says so\n * deleted gone from the manifest, and local still matches the lock,\n * so the sync wrote it and may remove it\n * kept-modified gone from the manifest, but local differs from the lock —\n * the developer changed it, so it stays\n * kept-renamed gone from the manifest under this spelling, but the\n * manifest names the same physical file another way — the\n * write for the new spelling is the update, so the old one\n * must not be unlinked afterwards\n *\n * A path absent from the lock is never deleted, whatever it is — and a\n * reserved path (`.git/`, `.fabric/`, the tool's own Claude settings file) is\n * refused outright wherever it appears, because the lock is an unauthenticated\n * file in the checkout (see `lock.ts`) and those are the paths a tampered one\n * would most want to name.\n */\nimport { createHash } from \"node:crypto\";\nimport type { InstructionManifestEntry } from \"@fabricorg/sdk\";\nimport { type InstructionsLock, LOCK_VERSION } from \"./lock.js\";\nimport {\n\tcheckRelativePath,\n\tcollisionKey,\n\tdescribeRejection,\n\tfindCollision,\n\tisReservedPath,\n} from \"./paths.js\";\nimport { readFileSafely } from \"./safe-write.js\";\n\ntype PlanAction =\n\t| \"verified\"\n\t| \"added\"\n\t| \"updated\"\n\t| \"replaced\"\n\t| \"deleted\"\n\t| \"kept-modified\"\n\t| \"kept-renamed\";\n\nexport interface PlanEntry {\n\tpath: string;\n\taction: PlanAction;\n\t/** The published hash, for everything the manifest still carries. */\n\tsha256?: string;\n\tmode?: number | null;\n}\n\nexport interface SyncPlan {\n\tentries: PlanEntry[];\n\t/** Entries whose bytes must be fetched and written. */\n\twrites: PlanEntry[];\n\t/** Entries to unlink. Always a subset of the previous lock. */\n\tdeletes: PlanEntry[];\n\tverified: PlanEntry[];\n\tkeptModified: PlanEntry[];\n\t/**\n\t * Lock paths that are the same physical file as a manifest path under a\n\t * different spelling. Never deleted; reported so the old spelling is not\n\t * a surprise on the filesystems where it survives.\n\t */\n\tkeptRenamed: PlanEntry[];\n}\n\n/**\n * Hex sha256 of a local file, or `null` when nothing is there.\n *\n * Every read goes through `readFileSafely`, the same guarded walk the writes\n * use: no symlinked component anywhere on the way down, nothing resolving\n * outside the destination, a regular file or nothing at all. A link pointing\n * at a file that happens to hold the published bytes used to hash EQUAL and\n * become `verified` — no write, no check, and a lock written over a path that\n * is not a file.\n */\nasync function hashLocalFile(\n\troot: string,\n\trelativePath: string,\n): Promise<string | null> {\n\tconst read = await readFileSafely(root, relativePath);\n\treturn read === null\n\t\t? null\n\t\t: createHash(\"sha256\").update(read.bytes).digest(\"hex\");\n}\n\nfunction lockPaths(lock: InstructionsLock | null): string[] {\n\treturn lock === null ? [] : Object.keys(lock.files);\n}\n\n/**\n * Every path the lock names has to survive the same checks a manifest path\n * does, plus the reserved-root rule — a hand-edited or accidentally\n * committed lock is exactly how `.git/config` would otherwise become an\n * unlink target with a hash anyone can read off disk.\n */\nfunction assertSafeLockPaths(paths: readonly string[]): void {\n\tfor (const lockedPath of paths) {\n\t\tconst check = checkRelativePath(lockedPath);\n\t\tif (!check.ok) {\n\t\t\tthrow new Error(\n\t\t\t\t`Refusing to sync: ${describeRejection(check)}. The lock names a path this tool will not touch.`,\n\t\t\t);\n\t\t}\n\t\tif (isReservedPath(lockedPath)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Refusing to sync: ${describeRejection({\n\t\t\t\t\tok: false,\n\t\t\t\t\treason: \"reserved_path\",\n\t\t\t\t\tdetail: lockedPath,\n\t\t\t\t})}. The lock names a path this tool will not touch.`,\n\t\t\t);\n\t\t}\n\t}\n\tconst collision = findCollision(paths);\n\tif (collision !== null) {\n\t\tthrow new Error(\n\t\t\t`Refusing to sync: ${describeRejection({\n\t\t\t\tok: false,\n\t\t\t\treason: \"collision\",\n\t\t\t\tdetail: `${collision.first} and ${collision.second}`,\n\t\t\t})}. The lock names two paths this tool cannot tell apart.`,\n\t\t);\n\t}\n}\n\n/**\n * Does the working tree still hold what the lock says it holds?\n *\n * The server answers \"unchanged\" by comparing digests, and a digest describes\n * the PUBLISHED snapshot — it says nothing about the checkout. Accepting that\n * answer as \"nothing to do\" meant an edited, deleted or chmod-ed instruction\n * file stayed that way until some later publication happened to move the\n * digest. For a feature whose point is that an agent reads the same\n * instructions everyone else does, that is the failure that matters most:\n * tampering persists and the tool reports success.\n *\n * Returns the paths that no longer match, as reasons a person can act on.\n * Never throws: a symlink or a directory standing where a file should be is\n * drift to REPORT, and the re-plan that follows is what refuses it.\n */\nexport async function verifyLedger(input: {\n\t/** An already-canonical root — `resolveDestinationRoot` or `resolveExistingRoot`. */\n\troot: string;\n\tlock: InstructionsLock;\n}): Promise<string[]> {\n\t// FIRST, before a single path is joined or opened. This function reads\n\t// paths that come out of an unauthenticated file in the checkout, and it\n\t// used to read them raw: `../outside` reached outside the destination, and\n\t// `rules/` replaced by a symlink was followed wherever it pointed. The\n\t// same validation `computeSyncPlan` runs, run before anything is touched.\n\tassertSafeLockPaths(lockPaths(input.lock));\n\n\tconst drifted: string[] = [];\n\tfor (const [lockedPath, locked] of Object.entries(input.lock.files)) {\n\t\t// A refusal from the guarded reader — a symlinked ancestor, a\n\t\t// directory where a file belongs — is drift, not a crash: the caller\n\t\t// re-plans, and planning refuses it there with the same message.\n\t\tlet read: Awaited<ReturnType<typeof readFileSafely>>;\n\t\ttry {\n\t\t\tread = await readFileSafely(input.root, lockedPath);\n\t\t} catch (error) {\n\t\t\tdrifted.push(\n\t\t\t\t`${lockedPath} (${error instanceof Error ? error.message.replace(/^Refusing to sync: /, \"\").replace(/\\.$/, \"\") : String(error)})`,\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\t\tif (read === null) {\n\t\t\tdrifted.push(`${lockedPath} (missing)`);\n\t\t\tcontinue;\n\t\t}\n\t\tconst actual = createHash(\"sha256\").update(read.bytes).digest(\"hex\");\n\t\tif (actual !== locked.sha256) {\n\t\t\tdrifted.push(`${lockedPath} (edited)`);\n\t\t\tcontinue;\n\t\t}\n\t\t// Modes are meaningless on Windows and a published `0755` that arrived\n\t\t// as `0644` leaves a script that will not run, so this is checked\n\t\t// wherever it can be.\n\t\tif (\n\t\t\tprocess.platform !== \"win32\" &&\n\t\t\tlocked.mode !== null &&\n\t\t\t(read.mode & 0o7777) !== (locked.mode & 0o7777)\n\t\t) {\n\t\t\tdrifted.push(\n\t\t\t\t`${lockedPath} (mode ${(read.mode & 0o7777).toString(8)}, published as ${(locked.mode & 0o7777).toString(8)})`,\n\t\t\t);\n\t\t}\n\t}\n\treturn drifted;\n}\n\nexport async function computeSyncPlan(input: {\n\t/** An already-canonical root, as every guarded read resolves against it. */\n\tdestination: string;\n\tmanifest: InstructionManifestEntry[];\n\tlock: InstructionsLock | null;\n}): Promise<SyncPlan> {\n\tconst { destination, manifest, lock } = input;\n\n\t// `assertValidManifest` has already checked every manifest entry's path,\n\t// shape, mode, uniqueness, count and digest before this is called. What\n\t// is re-checked here is the LOCK, which no server validated: it is a\n\t// plain file in the checkout, and it is the only thing that can authorise\n\t// a delete.\n\tassertSafeLockPaths(lockPaths(lock));\n\n\t// A Map, not the parsed object: a manifest path of `constructor` or\n\t// `toString` reads a value off `Object.prototype` when the lookup is a\n\t// plain property access, and `__proto__` does not read back at all.\n\tconst lockedFiles = new Map(Object.entries(lock?.files ?? {}));\n\tconst manifestPaths = new Set(manifest.map((entry) => entry.path));\n\t// The union, not the two sets separately. Each list is internally free of\n\t// collisions by now, which says nothing about a path appearing in one under\n\t// a spelling the other uses differently — and that case is a RENAME, not a\n\t// conflict. See `isRenameOf` below for what it costs to get wrong.\n\tconst manifestKeys = new Map(\n\t\tmanifest.map(\n\t\t\t(entry) => [collisionKey(entry.path), entry.path] as const,\n\t\t),\n\t);\n\tconst entries: PlanEntry[] = [];\n\n\tfor (const entry of manifest) {\n\t\tconst localHash = await hashLocalFile(destination, entry.path);\n\t\tif (localHash === entry.sha256) {\n\t\t\tentries.push({\n\t\t\t\tpath: entry.path,\n\t\t\t\taction: \"verified\",\n\t\t\t\tsha256: entry.sha256,\n\t\t\t\tmode: entry.mode,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tconst lockedHash = lockedFiles.get(entry.path)?.sha256;\n\t\tconst action: PlanAction =\n\t\t\tlocalHash === null\n\t\t\t\t? \"added\"\n\t\t\t\t: localHash === lockedHash\n\t\t\t\t\t? \"updated\"\n\t\t\t\t\t: \"replaced\";\n\t\tentries.push({\n\t\t\tpath: entry.path,\n\t\t\taction,\n\t\t\tsha256: entry.sha256,\n\t\t\tmode: entry.mode,\n\t\t});\n\t}\n\n\tfor (const [lockedPath, locked] of lockedFiles) {\n\t\tif (manifestPaths.has(lockedPath)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// `README.md` in the lock and `readme.md` in the manifest are two\n\t\t// spellings of one file wherever the filesystem folds case or\n\t\t// normalises names — and writes run before deletes, so planning a\n\t\t// delete here unlinked the file the same run had just written and then\n\t\t// wrote a lock claiming it was there. The manifest spelling's own write\n\t\t// IS the update; this one must not be touched. On Linux the two really\n\t\t// are separate files, and skipping the delete is still the right answer:\n\t\t// a tool that deletes a file because another file's name resembles it\n\t\t// would be worse than one that leaves a stale copy and says so.\n\t\tconst renamedTo = manifestKeys.get(collisionKey(lockedPath));\n\t\tif (renamedTo !== undefined) {\n\t\t\tentries.push({\n\t\t\t\tpath: lockedPath,\n\t\t\t\taction: \"kept-renamed\",\n\t\t\t\tsha256: locked.sha256,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst localHash = await hashLocalFile(destination, lockedPath);\n\t\tif (localHash === null) {\n\t\t\tcontinue;\n\t\t}\n\t\tentries.push({\n\t\t\tpath: lockedPath,\n\t\t\taction: localHash === locked.sha256 ? \"deleted\" : \"kept-modified\",\n\t\t\t// Carried so the unlink can prove it is still removing the file\n\t\t\t// this hash described, rather than whatever is at the path by the\n\t\t\t// time the writes are done.\n\t\t\tsha256: locked.sha256,\n\t\t});\n\t}\n\n\tentries.sort((a, b) => a.path.localeCompare(b.path));\n\n\treturn {\n\t\tentries,\n\t\twrites: entries.filter(\n\t\t\t(entry) =>\n\t\t\t\tentry.action === \"added\" ||\n\t\t\t\tentry.action === \"updated\" ||\n\t\t\t\tentry.action === \"replaced\",\n\t\t),\n\t\tdeletes: entries.filter((entry) => entry.action === \"deleted\"),\n\t\tverified: entries.filter((entry) => entry.action === \"verified\"),\n\t\tkeptModified: entries.filter(\n\t\t\t(entry) => entry.action === \"kept-modified\",\n\t\t),\n\t\tkeptRenamed: entries.filter((entry) => entry.action === \"kept-renamed\"),\n\t};\n}\n\n/** The lock the sync should leave behind once `plan` has been applied. */\nexport function nextLock(input: {\n\tprojectId: string;\n\tsnapshot: { id: string; version: number; digest: string };\n\tmanifest: InstructionManifestEntry[];\n\tnow?: Date;\n}): InstructionsLock {\n\t// `Object.fromEntries` rather than assignment into `{}`: assigning\n\t// `files[\"__proto__\"]` sets the prototype instead of creating an own\n\t// property, so a published file called `__proto__` was written to disk and\n\t// then left out of the ledger — and a later snapshot that dropped it could\n\t// not prove the sync had created it.\n\tconst files: InstructionsLock[\"files\"] = Object.fromEntries(\n\t\tinput.manifest.map((entry) => [\n\t\t\tentry.path,\n\t\t\t{ sha256: entry.sha256, mode: entry.mode },\n\t\t]),\n\t);\n\treturn {\n\t\tversion: LOCK_VERSION,\n\t\tprojectId: input.projectId,\n\t\tsnapshotId: input.snapshot.id,\n\t\tsnapshotVersion: input.snapshot.version,\n\t\tdigest: input.snapshot.digest,\n\t\tsyncedAt: (input.now ?? new Date()).toISOString(),\n\t\tfiles,\n\t};\n}\n","/**\n * fabric mcp\n *\n * fabric mcp servers List accessible MCP servers\n * fabric mcp configs List your MCP configurations\n * fabric mcp configs show <id> Show a specific MCP configuration\n */\n\nimport type {\n\tFabricMcpConfig,\n\tFabricMcpConfigDetail,\n\tFabricMcpServer,\n} from \"@fabricorg/sdk\";\nimport { Command } from \"commander\";\nimport { getClient } from \"../../lib/client.js\";\nimport { resolveContext } from \"../../lib/context.js\";\nimport { printError, printOutput, printRecord } from \"../../lib/output.js\";\n\nexport function buildMcpCommand(): Command {\n\tconst mcp = new Command(\"mcp\").description(\n\t\t\"Manage MCP servers and configurations\",\n\t);\n\n\t// -- servers -------------------------------------------------------------\n\tmcp.command(\"servers\")\n\t\t.description(\"List accessible MCP servers (system + custom)\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\n\t\t\t\"--format <format>\",\n\t\t\t\"Output format: table|json|yaml|csv\",\n\t\t\t\"table\",\n\t\t)\n\t\t.option(\"-q, --quiet\", \"Print server keys only\")\n\t\t.action(\n\t\t\tasync (opts: {\n\t\t\t\torg?: string;\n\t\t\t\tpersonal?: boolean;\n\t\t\t\tformat: string;\n\t\t\t\tquiet?: boolean;\n\t\t\t}) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet list: FabricMcpServer[];\n\t\t\t\ttry {\n\t\t\t\t\tlist = await client.mcp.listServers({\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tif (opts.quiet) {\n\t\t\t\t\tfor (const s of list) {\n\t\t\t\t\t\tprocess.stdout.write(`${s.key}\\n`);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintOutput(list, {\n\t\t\t\t\tformat: opts.format as \"table\" | \"json\" | \"yaml\" | \"csv\",\n\t\t\t\t\tcolumns: [\n\t\t\t\t\t\t\"key\",\n\t\t\t\t\t\t\"name\",\n\t\t\t\t\t\t\"transport\",\n\t\t\t\t\t\t\"category\",\n\t\t\t\t\t\t\"isSystemProvided\",\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\t// -- configs -------------------------------------------------------------\n\tconst configs = new Command(\"configs\").description(\n\t\t\"Manage MCP configurations\",\n\t);\n\n\tconfigs\n\t\t.command(\"list\", { isDefault: true })\n\t\t.description(\"List your MCP configurations\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\n\t\t\t\"--format <format>\",\n\t\t\t\"Output format: table|json|yaml|csv\",\n\t\t\t\"table\",\n\t\t)\n\t\t.option(\"-q, --quiet\", \"Print IDs only\")\n\t\t.action(\n\t\t\tasync (opts: {\n\t\t\t\torg?: string;\n\t\t\t\tpersonal?: boolean;\n\t\t\t\tformat: string;\n\t\t\t\tquiet?: boolean;\n\t\t\t}) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet list: FabricMcpConfig[];\n\t\t\t\ttry {\n\t\t\t\t\tlist = await client.mcp.listConfigs({\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tif (opts.quiet) {\n\t\t\t\t\tfor (const c of list) {\n\t\t\t\t\t\tprocess.stdout.write(`${c.id}\\n`);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintOutput(list, {\n\t\t\t\t\tformat: opts.format as \"table\" | \"json\" | \"yaml\" | \"csv\",\n\t\t\t\t\tcolumns: [\n\t\t\t\t\t\t\"id\",\n\t\t\t\t\t\t\"serverName\",\n\t\t\t\t\t\t\"displayName\",\n\t\t\t\t\t\t\"authType\",\n\t\t\t\t\t\t\"enabled\",\n\t\t\t\t\t\t\"status\",\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\tconfigs\n\t\t.command(\"show <id>\")\n\t\t.description(\"Show a specific MCP configuration\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tid: string,\n\t\t\t\topts: { org?: string; personal?: boolean; format: string },\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet config: FabricMcpConfigDetail;\n\t\t\t\ttry {\n\t\t\t\t\tconfig = await client.mcp.getConfig(id, {\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(config, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintRecord({\n\t\t\t\t\tID: config.id,\n\t\t\t\t\tServer: config.serverName ?? config.mcpServerId,\n\t\t\t\t\t\"Server Key\": config.serverKey ?? \"(none)\",\n\t\t\t\t\t\"Display Name\": config.displayName ?? \"(none)\",\n\t\t\t\t\t\"Base URL\": config.baseUrl ?? \"(none)\",\n\t\t\t\t\tTransport: config.transport ?? \"(default)\",\n\t\t\t\t\t\"Auth Type\": config.authType,\n\t\t\t\t\tEnabled: config.enabled ? \"yes\" : \"no\",\n\t\t\t\t\tStatus: config.status,\n\t\t\t\t\t\"Last Health Check\":\n\t\t\t\t\t\tconfig.lastHealthCheckAt?.slice(0, 19) ?? \"(never)\",\n\t\t\t\t\tCreated: config.createdAt.slice(0, 10),\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\tconfigs\n\t\t.command(\"delete <id>\")\n\t\t.description(\"Delete an MCP configuration\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"-y, --yes\", \"Skip confirmation prompt\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tid: string,\n\t\t\t\topts: { org?: string; personal?: boolean; yes?: boolean },\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\n\t\t\t\tif (!opts.yes) {\n\t\t\t\t\tprocess.stderr.write(\n\t\t\t\t\t\t`Delete MCP config ${id}? This cannot be undone. Pass --yes to confirm.\\n`,\n\t\t\t\t\t);\n\t\t\t\t\tprocess.exit(2);\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tawait client.mcp.deleteConfig(id, {\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tprocess.stdout.write(`MCP config ${id} deleted.\\n`);\n\t\t\t},\n\t\t);\n\n\tmcp.addCommand(configs);\n\n\t// -- serve ---------------------------------------------------------------\n\tmcp.command(\"serve\")\n\t\t.description(\n\t\t\t\"Run a stdio MCP server exposing this workspace's whole integration catalog. \" +\n\t\t\t\t\"Point Claude Desktop, Cursor, or any MCP client at it.\",\n\t\t)\n\t\t.action(async () => {\n\t\t\t// Lazy import — avoids loading the MCP SDK when running other commands\n\t\t\t// and keeps the CLI binary cold-start fast.\n\t\t\tconst { runStdio } = await import(\"@fabricorg/sdk-mcp/stdio\");\n\t\t\tawait runStdio();\n\t\t});\n\n\treturn mcp;\n}\n","/**\n * fabric orgs\n *\n * fabric orgs list List orgs you belong to\n * fabric orgs show <slug> Show org details\n */\n\nimport { Command } from \"commander\";\nimport { getClient } from \"../../lib/client.js\";\nimport { printError, printOutput, printRecord } from \"../../lib/output.js\";\n\nexport function buildOrgsCommand(): Command {\n\tconst orgs = new Command(\"orgs\").description(\"Manage organizations\");\n\n\t// -- list ----------------------------------------------------------------\n\torgs.command(\"list\")\n\t\t.description(\"List organizations you belong to\")\n\t\t.option(\n\t\t\t\"--format <format>\",\n\t\t\t\"Output format: table|json|yaml|csv\",\n\t\t\t\"table\",\n\t\t)\n\t\t.option(\"-q, --quiet\", \"Print slugs only\")\n\t\t.action(async (opts: { format: string; quiet?: boolean }) => {\n\t\t\tconst client = getClient();\n\t\t\tlet list: Awaited<ReturnType<typeof client.orgs.list>>;\n\t\t\ttry {\n\t\t\t\tlist = await client.orgs.list();\n\t\t\t} catch (err: unknown) {\n\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t}\n\n\t\t\tif (opts.quiet) {\n\t\t\t\tfor (const org of list) {\n\t\t\t\t\tprocess.stdout.write(`${org.slug}\\n`);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tprintOutput(list, {\n\t\t\t\tformat: opts.format as \"table\" | \"json\" | \"yaml\" | \"csv\",\n\t\t\t\tcolumns: [\"name\", \"slug\", \"role\", \"joinedAt\"],\n\t\t\t});\n\t\t});\n\n\t// -- show ----------------------------------------------------------------\n\torgs.command(\"show <slug>\")\n\t\t.description(\"Show details for an organization\")\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(async (slug: string, opts: { format: string }) => {\n\t\t\tconst client = getClient();\n\t\t\tlet list: Awaited<ReturnType<typeof client.orgs.list>>;\n\t\t\ttry {\n\t\t\t\tlist = await client.orgs.list();\n\t\t\t} catch (err: unknown) {\n\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t}\n\n\t\t\tconst org = list.find(\n\t\t\t\t(o: { slug: string; id: string }) =>\n\t\t\t\t\to.slug === slug || o.id === slug,\n\t\t\t);\n\t\t\tif (!org) {\n\t\t\t\tprintError(`Organization not found: ${slug}`, 4);\n\t\t\t}\n\n\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\tprintOutput(org, { format: fmt });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tprintRecord({\n\t\t\t\tName: org.name,\n\t\t\t\tSlug: org.slug,\n\t\t\t\tRole: org.role,\n\t\t\t\t\"Joined at\": String(org.joinedAt).slice(0, 10),\n\t\t\t\tLogo: org.logo ?? \"(none)\",\n\t\t\t});\n\t\t});\n\n\treturn orgs;\n}\n","/**\n * fabric projects\n *\n * fabric projects list List projects\n * fabric projects show <id> Show project details\n * fabric projects create <name> Create a project\n */\n\nimport type { FabricProject } from \"@fabricorg/sdk\";\nimport { Command } from \"commander\";\nimport { getClient } from \"../../lib/client.js\";\nimport { resolveContext } from \"../../lib/context.js\";\nimport {\n\tprintError,\n\tprintOutput,\n\tprintRecord,\n\tprintSuccess,\n} from \"../../lib/output.js\";\n\nexport function buildProjectsCommand(): Command {\n\tconst projects = new Command(\"projects\").description(\"Manage projects\");\n\n\t// -- list ----------------------------------------------------------------\n\tprojects\n\t\t.command(\"list\")\n\t\t.description(\"List projects\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\n\t\t\t\"--status <status>\",\n\t\t\t\"Filter by status: ACTIVE|DRAFT|COMPLETED|ARCHIVED\",\n\t\t)\n\t\t.option(\"--search <query>\", \"Search by name\")\n\t\t.option(\"--limit <n>\", \"Max results (default 20)\", \"20\")\n\t\t.option(\n\t\t\t\"--format <format>\",\n\t\t\t\"Output format: table|json|yaml|csv\",\n\t\t\t\"table\",\n\t\t)\n\t\t.option(\"-q, --quiet\", \"Print IDs only\")\n\t\t.action(\n\t\t\tasync (opts: {\n\t\t\t\torg?: string;\n\t\t\t\tpersonal?: boolean;\n\t\t\t\tstatus?: string;\n\t\t\t\tsearch?: string;\n\t\t\t\tlimit: string;\n\t\t\t\tformat: string;\n\t\t\t\tquiet?: boolean;\n\t\t\t}) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet list: FabricProject[];\n\t\t\t\ttry {\n\t\t\t\t\tlist = await client.projects.list({\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t\tstatus: opts.status as\n\t\t\t\t\t\t\t| FabricProject[\"status\"]\n\t\t\t\t\t\t\t| undefined,\n\t\t\t\t\t\tsearch: opts.search,\n\t\t\t\t\t\tlimit: Number(opts.limit),\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tif (opts.quiet) {\n\t\t\t\t\tfor (const p of list) {\n\t\t\t\t\t\tprocess.stdout.write(`${p.id}\\n`);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintOutput(list, {\n\t\t\t\t\tformat: opts.format as \"table\" | \"json\" | \"yaml\" | \"csv\",\n\t\t\t\t\tcolumns: [\"id\", \"name\", \"status\", \"createdAt\"],\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\t// -- show ----------------------------------------------------------------\n\tprojects\n\t\t.command(\"show <id>\")\n\t\t.description(\"Show project details\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tid: string,\n\t\t\t\topts: { org?: string; personal?: boolean; format: string },\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet project: FabricProject;\n\t\t\t\ttry {\n\t\t\t\t\tproject = await client.projects.get(id, {\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(project, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintRecord({\n\t\t\t\t\tID: project.id,\n\t\t\t\t\tName: project.name,\n\t\t\t\t\tStatus: project.status,\n\t\t\t\t\tDescription: project.description ?? \"(none)\",\n\t\t\t\t\tRepository: project.repositoryUrl ?? \"(none)\",\n\t\t\t\t\tCreated: project.createdAt.slice(0, 10),\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\t// -- create --------------------------------------------------------------\n\tprojects\n\t\t.command(\"create <name>\")\n\t\t.description(\"Create a new project\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"-d, --description <text>\", \"Project description\")\n\t\t.option(\"--repo <url>\", \"Repository URL\")\n\t\t.option(\n\t\t\t\"--status <status>\",\n\t\t\t\"Initial status: DRAFT|ACTIVE (default: DRAFT)\",\n\t\t\t\"DRAFT\",\n\t\t)\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tname: string,\n\t\t\t\topts: {\n\t\t\t\t\torg?: string;\n\t\t\t\t\tpersonal?: boolean;\n\t\t\t\t\tdescription?: string;\n\t\t\t\t\trepo?: string;\n\t\t\t\t\tstatus: string;\n\t\t\t\t\tformat: string;\n\t\t\t\t},\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet project: FabricProject;\n\t\t\t\ttry {\n\t\t\t\t\tproject = await client.projects.create({\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tdescription: opts.description,\n\t\t\t\t\t\trepositoryUrl: opts.repo,\n\t\t\t\t\t\tstatus: opts.status as \"DRAFT\" | \"ACTIVE\",\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(project, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintSuccess(`Project \"${project.name}\" created`);\n\t\t\t\tprintRecord({\n\t\t\t\t\tID: project.id,\n\t\t\t\t\tName: project.name,\n\t\t\t\t\tStatus: project.status,\n\t\t\t\t\tDescription: project.description ?? \"(none)\",\n\t\t\t\t\tCreated: project.createdAt.slice(0, 10),\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\t// -- update --------------------------------------------------------------\n\tprojects\n\t\t.command(\"update <id>\")\n\t\t.description(\"Update a project\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--name <name>\", \"New name\")\n\t\t.option(\"-d, --description <text>\", \"New description\")\n\t\t.option(\"--repo <url>\", \"Repository URL\")\n\t\t.option(\"--status <status>\", \"Status: DRAFT|ACTIVE|COMPLETED|ARCHIVED\")\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tid: string,\n\t\t\t\topts: {\n\t\t\t\t\torg?: string;\n\t\t\t\t\tpersonal?: boolean;\n\t\t\t\t\tname?: string;\n\t\t\t\t\tdescription?: string;\n\t\t\t\t\trepo?: string;\n\t\t\t\t\tstatus?: string;\n\t\t\t\t\tformat: string;\n\t\t\t\t},\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet project: FabricProject;\n\t\t\t\ttry {\n\t\t\t\t\tproject = await client.projects.update(id, {\n\t\t\t\t\t\tname: opts.name,\n\t\t\t\t\t\tdescription: opts.description,\n\t\t\t\t\t\trepositoryUrl: opts.repo,\n\t\t\t\t\t\tstatus: opts.status as\n\t\t\t\t\t\t\t| \"DRAFT\"\n\t\t\t\t\t\t\t| \"ACTIVE\"\n\t\t\t\t\t\t\t| \"COMPLETED\"\n\t\t\t\t\t\t\t| \"ARCHIVED\"\n\t\t\t\t\t\t\t| undefined,\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(project, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintRecord({\n\t\t\t\t\tID: project.id,\n\t\t\t\t\tName: project.name,\n\t\t\t\t\tStatus: project.status,\n\t\t\t\t\tDescription: project.description ?? \"(none)\",\n\t\t\t\t\tUpdated: project.updatedAt.slice(0, 10),\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\treturn projects;\n}\n","/**\n * fabric prompts\n *\n * fabric prompts list List prompt templates\n * fabric prompts get <id> Get a prompt (prints latest version content)\n */\n\nimport type { FabricPrompt } from \"@fabricorg/sdk\";\nimport { Command } from \"commander\";\nimport { getClient } from \"../../lib/client.js\";\nimport { resolveContext } from \"../../lib/context.js\";\nimport {\n\tprintError,\n\tprintOutput,\n\tprintRecord,\n\tprintSuccess,\n} from \"../../lib/output.js\";\n\nexport function buildPromptsCommand(): Command {\n\tconst prompts = new Command(\"prompts\").description(\n\t\t\"Manage prompt templates\",\n\t);\n\n\t// -- list ----------------------------------------------------------------\n\tprompts\n\t\t.command(\"list\")\n\t\t.description(\"List prompt templates\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--search <query>\", \"Search by name\")\n\t\t.option(\"--category <cat>\", \"Filter by category\")\n\t\t.option(\"--limit <n>\", \"Max results\", \"50\")\n\t\t.option(\n\t\t\t\"--format <format>\",\n\t\t\t\"Output format: table|json|yaml|csv\",\n\t\t\t\"table\",\n\t\t)\n\t\t.option(\"-q, --quiet\", \"Print IDs only\")\n\t\t.action(\n\t\t\tasync (opts: {\n\t\t\t\torg?: string;\n\t\t\t\tpersonal?: boolean;\n\t\t\t\tsearch?: string;\n\t\t\t\tcategory?: string;\n\t\t\t\tlimit: string;\n\t\t\t\tformat: string;\n\t\t\t\tquiet?: boolean;\n\t\t\t}) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet list: FabricPrompt[];\n\t\t\t\ttry {\n\t\t\t\t\tlist = await client.prompts.list({\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t\tsearch: opts.search,\n\t\t\t\t\t\tcategory: opts.category,\n\t\t\t\t\t\tlimit: Number(opts.limit),\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tif (opts.quiet) {\n\t\t\t\t\tfor (const p of list) {\n\t\t\t\t\t\tprocess.stdout.write(`${p.id}\\n`);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintOutput(list, {\n\t\t\t\t\tformat: opts.format as \"table\" | \"json\" | \"yaml\" | \"csv\",\n\t\t\t\t\tcolumns: [\n\t\t\t\t\t\t\"id\",\n\t\t\t\t\t\t\"key\",\n\t\t\t\t\t\t\"name\",\n\t\t\t\t\t\t\"scope\",\n\t\t\t\t\t\t\"category\",\n\t\t\t\t\t\t\"updatedAt\",\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\t// -- get -----------------------------------------------------------------\n\tprompts\n\t\t.command(\"get <id>\")\n\t\t.description(\"Get a prompt (prints latest version content by default)\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\n\t\t\t\"--format <format>\",\n\t\t\t\"Output format: raw|table|json|yaml (default: raw)\",\n\t\t\t\"raw\",\n\t\t)\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tid: string,\n\t\t\t\topts: { org?: string; personal?: boolean; format: string },\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet prompt: FabricPrompt;\n\t\t\t\ttry {\n\t\t\t\t\tprompt = await client.prompts.get(id, {\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"raw\" | \"table\" | \"json\" | \"yaml\";\n\n\t\t\t\tif (fmt === \"json\") {\n\t\t\t\t\tprintOutput(prompt, { format: \"json\" });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(prompt, { format: \"yaml\" });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst content = prompt.versions?.[0]?.content ?? \"(no content)\";\n\n\t\t\t\tif (fmt === \"raw\") {\n\t\t\t\t\tprocess.stdout.write(`${content}\\n`);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// table: metadata + content block\n\t\t\t\tprintRecord({\n\t\t\t\t\tID: prompt.id,\n\t\t\t\t\tKey: prompt.key,\n\t\t\t\t\tName: prompt.name,\n\t\t\t\t\tScope: prompt.scope,\n\t\t\t\t\tCategory: prompt.category ?? \"(none)\",\n\t\t\t\t\tTags: (prompt.tags ?? []).join(\", \") || \"(none)\",\n\t\t\t\t});\n\t\t\t\tprocess.stdout.write(`\\n--- Content ---\\n${content}\\n`);\n\t\t\t},\n\t\t);\n\n\t// -- create --------------------------------------------------------------\n\tprompts\n\t\t.command(\"create\")\n\t\t.description(\"Create a new prompt\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.requiredOption(\"--key <key>\", \"Prompt key (unique identifier)\")\n\t\t.requiredOption(\"--name <name>\", \"Prompt name\")\n\t\t.option(\"-d, --description <text>\", \"Prompt description\")\n\t\t.option(\"--content <text>\", \"Initial prompt content\")\n\t\t.option(\"--category <cat>\", \"Category\")\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (opts: {\n\t\t\t\torg?: string;\n\t\t\t\tpersonal?: boolean;\n\t\t\t\tkey: string;\n\t\t\t\tname: string;\n\t\t\t\tdescription?: string;\n\t\t\t\tcontent?: string;\n\t\t\t\tcategory?: string;\n\t\t\t\tformat: string;\n\t\t\t}) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet prompt: FabricPrompt;\n\t\t\t\ttry {\n\t\t\t\t\tprompt = await client.prompts.create({\n\t\t\t\t\t\tkey: opts.key,\n\t\t\t\t\t\tname: opts.name,\n\t\t\t\t\t\tdescription: opts.description,\n\t\t\t\t\t\tcontent: opts.content,\n\t\t\t\t\t\tcategory: opts.category,\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(prompt, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintSuccess(`Prompt \"${prompt.name}\" created`);\n\t\t\t\tprintRecord({\n\t\t\t\t\tID: prompt.id,\n\t\t\t\t\tKey: prompt.key,\n\t\t\t\t\tName: prompt.name,\n\t\t\t\t\tScope: prompt.scope,\n\t\t\t\t\tCreated: prompt.createdAt.slice(0, 10),\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\t// -- update --------------------------------------------------------------\n\tprompts\n\t\t.command(\"update <id>\")\n\t\t.description(\"Update a prompt\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--name <name>\", \"New name\")\n\t\t.option(\"-d, --description <text>\", \"New description\")\n\t\t.option(\"--category <cat>\", \"Category\")\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tid: string,\n\t\t\t\topts: {\n\t\t\t\t\torg?: string;\n\t\t\t\t\tpersonal?: boolean;\n\t\t\t\t\tname?: string;\n\t\t\t\t\tdescription?: string;\n\t\t\t\t\tcategory?: string;\n\t\t\t\t\tformat: string;\n\t\t\t\t},\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet prompt: FabricPrompt;\n\t\t\t\ttry {\n\t\t\t\t\tprompt = await client.prompts.update(id, {\n\t\t\t\t\t\tname: opts.name,\n\t\t\t\t\t\tdescription: opts.description,\n\t\t\t\t\t\tcategory: opts.category,\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(prompt, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintRecord({\n\t\t\t\t\tID: prompt.id,\n\t\t\t\t\tKey: prompt.key,\n\t\t\t\t\tName: prompt.name,\n\t\t\t\t\tScope: prompt.scope,\n\t\t\t\t\tUpdated: prompt.updatedAt.slice(0, 10),\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\treturn prompts;\n}\n","/**\n * fabric reports\n *\n * fabric reports templates list List report templates\n * fabric reports templates show <id> Show template details\n * fabric reports executions list List report executions\n */\n\nimport type {\n\tFabricReportExecution,\n\tFabricReportTemplate,\n} from \"@fabricorg/sdk\";\nimport { Command } from \"commander\";\nimport { getClient } from \"../../lib/client.js\";\nimport { resolveContext } from \"../../lib/context.js\";\nimport { printError, printOutput, printRecord } from \"../../lib/output.js\";\n\nexport function buildReportsCommand(): Command {\n\tconst reports = new Command(\"reports\").description(\n\t\t\"Manage report templates and executions\",\n\t);\n\n\t// -- templates -----------------------------------------------------------\n\tconst templates = new Command(\"templates\").description(\n\t\t\"Manage report templates\",\n\t);\n\n\ttemplates\n\t\t.command(\"list\", { isDefault: true })\n\t\t.description(\"List report templates\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--search <query>\", \"Search by name\")\n\t\t.option(\"--category <cat>\", \"Filter by category\")\n\t\t.option(\"--limit <n>\", \"Max results (default 20)\", \"20\")\n\t\t.option(\n\t\t\t\"--format <format>\",\n\t\t\t\"Output format: table|json|yaml|csv\",\n\t\t\t\"table\",\n\t\t)\n\t\t.option(\"-q, --quiet\", \"Print IDs only\")\n\t\t.action(\n\t\t\tasync (opts: {\n\t\t\t\torg?: string;\n\t\t\t\tpersonal?: boolean;\n\t\t\t\tsearch?: string;\n\t\t\t\tcategory?: string;\n\t\t\t\tlimit: string;\n\t\t\t\tformat: string;\n\t\t\t\tquiet?: boolean;\n\t\t\t}) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet list: FabricReportTemplate[];\n\t\t\t\ttry {\n\t\t\t\t\tlist = await client.reports.listTemplates({\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t\tsearch: opts.search,\n\t\t\t\t\t\tcategory: opts.category,\n\t\t\t\t\t\tlimit: Number(opts.limit),\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tif (opts.quiet) {\n\t\t\t\t\tfor (const t of list) {\n\t\t\t\t\t\tprocess.stdout.write(`${t.id}\\n`);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintOutput(list, {\n\t\t\t\t\tformat: opts.format as \"table\" | \"json\" | \"yaml\" | \"csv\",\n\t\t\t\t\tcolumns: [\n\t\t\t\t\t\t\"id\",\n\t\t\t\t\t\t\"name\",\n\t\t\t\t\t\t\"templateType\",\n\t\t\t\t\t\t\"scope\",\n\t\t\t\t\t\t\"usageCount\",\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\ttemplates\n\t\t.command(\"show <id>\")\n\t\t.description(\"Show report template details\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tid: string,\n\t\t\t\topts: { org?: string; personal?: boolean; format: string },\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet tmpl: FabricReportTemplate;\n\t\t\t\ttry {\n\t\t\t\t\ttmpl = await client.reports.getTemplate(id, {\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(tmpl, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintRecord({\n\t\t\t\t\tID: tmpl.id,\n\t\t\t\t\tName: tmpl.name,\n\t\t\t\t\tType: tmpl.templateType,\n\t\t\t\t\tScope: tmpl.scope,\n\t\t\t\t\tCategory: tmpl.category ?? \"(none)\",\n\t\t\t\t\tTags: tmpl.tags.join(\", \") || \"(none)\",\n\t\t\t\t\tPublic: tmpl.isPublic ? \"yes\" : \"no\",\n\t\t\t\t\t\"Use Count\": String(tmpl.usageCount),\n\t\t\t\t\tDescription: tmpl.description ?? \"(none)\",\n\t\t\t\t\tUpdated: tmpl.updatedAt.slice(0, 10),\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\treports.addCommand(templates);\n\n\t// -- executions ----------------------------------------------------------\n\tconst executions = new Command(\"executions\").description(\n\t\t\"View report executions\",\n\t);\n\n\texecutions\n\t\t.command(\"list\", { isDefault: true })\n\t\t.description(\"List report executions\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--limit <n>\", \"Max results (default 20)\", \"20\")\n\t\t.option(\n\t\t\t\"--format <format>\",\n\t\t\t\"Output format: table|json|yaml|csv\",\n\t\t\t\"table\",\n\t\t)\n\t\t.option(\"-q, --quiet\", \"Print IDs only\")\n\t\t.action(\n\t\t\tasync (opts: {\n\t\t\t\torg?: string;\n\t\t\t\tpersonal?: boolean;\n\t\t\t\tlimit: string;\n\t\t\t\tformat: string;\n\t\t\t\tquiet?: boolean;\n\t\t\t}) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet list: FabricReportExecution[];\n\t\t\t\ttry {\n\t\t\t\t\tlist = await client.reports.listExecutions({\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t\tlimit: Number(opts.limit),\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tif (opts.quiet) {\n\t\t\t\t\tfor (const e of list) {\n\t\t\t\t\t\tprocess.stdout.write(`${e.id}\\n`);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintOutput(list, {\n\t\t\t\t\tformat: opts.format as \"table\" | \"json\" | \"yaml\" | \"csv\",\n\t\t\t\t\tcolumns: [\n\t\t\t\t\t\t\"id\",\n\t\t\t\t\t\t\"templateId\",\n\t\t\t\t\t\t\"status\",\n\t\t\t\t\t\t\"startedAt\",\n\t\t\t\t\t\t\"completedAt\",\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\treports.addCommand(executions);\n\n\treturn reports;\n}\n","/**\n * fabric skills\n *\n * fabric skills list Browse skill definitions\n * fabric skills show <id> Show skill details\n */\n\nimport type { FabricSkill } from \"@fabricorg/sdk\";\nimport { Command } from \"commander\";\nimport { getClient } from \"../../lib/client.js\";\nimport { resolveContext } from \"../../lib/context.js\";\nimport { printError, printOutput, printRecord } from \"../../lib/output.js\";\n\nexport function buildSkillsCommand(): Command {\n\tconst skills = new Command(\"skills\").description(\n\t\t\"Browse skill definitions\",\n\t);\n\n\t// -- list ----------------------------------------------------------------\n\tskills\n\t\t.command(\"list\")\n\t\t.description(\"List skills\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--search <query>\", \"Search by name\")\n\t\t.option(\"--category <cat>\", \"Filter by category\")\n\t\t.option(\"--limit <n>\", \"Max results\", \"50\")\n\t\t.option(\n\t\t\t\"--format <format>\",\n\t\t\t\"Output format: table|json|yaml|csv\",\n\t\t\t\"table\",\n\t\t)\n\t\t.option(\"-q, --quiet\", \"Print slugs only\")\n\t\t.action(\n\t\t\tasync (opts: {\n\t\t\t\torg?: string;\n\t\t\t\tpersonal?: boolean;\n\t\t\t\tsearch?: string;\n\t\t\t\tcategory?: string;\n\t\t\t\tlimit: string;\n\t\t\t\tformat: string;\n\t\t\t\tquiet?: boolean;\n\t\t\t}) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet list: FabricSkill[];\n\t\t\t\ttry {\n\t\t\t\t\tlist = await client.skills.list({\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t\tsearch: opts.search,\n\t\t\t\t\t\tcategory: opts.category,\n\t\t\t\t\t\tlimit: Number(opts.limit),\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tif (opts.quiet) {\n\t\t\t\t\tfor (const s of list) {\n\t\t\t\t\t\tprocess.stdout.write(`${s.slug}\\n`);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintOutput(list, {\n\t\t\t\t\tformat: opts.format as \"table\" | \"json\" | \"yaml\" | \"csv\",\n\t\t\t\t\tcolumns: [\"slug\", \"name\", \"category\", \"scope\", \"useCount\"],\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\t// -- show ----------------------------------------------------------------\n\tskills\n\t\t.command(\"show <id>\")\n\t\t.description(\"Show skill details (accepts ID or slug)\")\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(async (id: string, opts: { format: string }) => {\n\t\t\tconst client = getClient();\n\t\t\tlet skill: FabricSkill;\n\t\t\ttry {\n\t\t\t\tskill = await client.skills.get(id);\n\t\t\t} catch (err: unknown) {\n\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t}\n\n\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\tprintOutput(skill, { format: fmt });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tprintRecord({\n\t\t\t\tID: skill.id,\n\t\t\t\tSlug: skill.slug,\n\t\t\t\tName: skill.name,\n\t\t\t\tCategory: skill.category ?? \"(none)\",\n\t\t\t\tScope: skill.scope,\n\t\t\t\tTags: skill.tags.join(\", \") || \"(none)\",\n\t\t\t\tPublished: skill.isPublished ? \"yes\" : \"no\",\n\t\t\t\t\"Use Count\": String(skill.useCount),\n\t\t\t\tVersion: String(skill.version),\n\t\t\t\tDescription: skill.description,\n\t\t\t\tUpdated: skill.updatedAt.slice(0, 10),\n\t\t\t});\n\t\t});\n\n\treturn skills;\n}\n","/**\n * fabric workflows\n *\n * fabric workflows list List workflows\n * fabric workflows show <id> Show workflow details\n * fabric workflows trigger <id> Trigger a workflow execution\n * fabric workflows status <id> <execId> Get execution status\n */\n\nimport type { FabricExecution, FabricWorkflow } from \"@fabricorg/sdk\";\nimport { Command } from \"commander\";\nimport { getClient } from \"../../lib/client.js\";\nimport { resolveContext } from \"../../lib/context.js\";\nimport {\n\tprintError,\n\tprintOutput,\n\tprintRecord,\n\tprintSuccess,\n} from \"../../lib/output.js\";\n\nexport function buildWorkflowsCommand(): Command {\n\tconst workflows = new Command(\"workflows\").description(\"Manage workflows\");\n\n\t// -- list ----------------------------------------------------------------\n\tworkflows\n\t\t.command(\"list\")\n\t\t.description(\"List workflows\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--status <status>\", \"Filter: DRAFT|ACTIVE|PAUSED|ARCHIVED\")\n\t\t.option(\"--search <query>\", \"Search by name\")\n\t\t.option(\"--limit <n>\", \"Max results\", \"20\")\n\t\t.option(\n\t\t\t\"--format <format>\",\n\t\t\t\"Output format: table|json|yaml|csv\",\n\t\t\t\"table\",\n\t\t)\n\t\t.option(\"-q, --quiet\", \"Print IDs only\")\n\t\t.action(\n\t\t\tasync (opts: {\n\t\t\t\torg?: string;\n\t\t\t\tpersonal?: boolean;\n\t\t\t\tstatus?: string;\n\t\t\t\tsearch?: string;\n\t\t\t\tlimit: string;\n\t\t\t\tformat: string;\n\t\t\t\tquiet?: boolean;\n\t\t\t}) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet list: FabricWorkflow[];\n\t\t\t\ttry {\n\t\t\t\t\tlist = await client.workflows.list({\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t\tstatus: opts.status as\n\t\t\t\t\t\t\t| FabricWorkflow[\"status\"]\n\t\t\t\t\t\t\t| undefined,\n\t\t\t\t\t\tsearch: opts.search,\n\t\t\t\t\t\tlimit: Number(opts.limit),\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tif (opts.quiet) {\n\t\t\t\t\tfor (const w of list) {\n\t\t\t\t\t\tprocess.stdout.write(`${w.id}\\n`);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintOutput(list, {\n\t\t\t\t\tformat: opts.format as \"table\" | \"json\" | \"yaml\" | \"csv\",\n\t\t\t\t\tcolumns: [\n\t\t\t\t\t\t\"id\",\n\t\t\t\t\t\t\"name\",\n\t\t\t\t\t\t\"status\",\n\t\t\t\t\t\t\"triggerType\",\n\t\t\t\t\t\t\"createdAt\",\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\t// -- show ----------------------------------------------------------------\n\tworkflows\n\t\t.command(\"show <id>\")\n\t\t.description(\"Show workflow details\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tid: string,\n\t\t\t\topts: { org?: string; personal?: boolean; format: string },\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet wf: FabricWorkflow;\n\t\t\t\ttry {\n\t\t\t\t\twf = await client.workflows.get(id, {\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(wf, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintRecord({\n\t\t\t\t\tID: wf.id,\n\t\t\t\t\tName: wf.name,\n\t\t\t\t\tStatus: wf.status,\n\t\t\t\t\tTrigger: wf.triggerType,\n\t\t\t\t\tVersion: String(wf.version),\n\t\t\t\t\tCreated: wf.createdAt.slice(0, 10),\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\t// -- trigger -------------------------------------------------------------\n\tworkflows\n\t\t.command(\"trigger <id>\")\n\t\t.description(\"Trigger a workflow execution\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--input <json>\", \"JSON input for triggerData\", \"{}\")\n\t\t.option(\"--vars <json>\", \"JSON variables\", \"{}\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tid: string,\n\t\t\t\topts: {\n\t\t\t\t\torg?: string;\n\t\t\t\t\tpersonal?: boolean;\n\t\t\t\t\tinput: string;\n\t\t\t\t\tvars: string;\n\t\t\t\t},\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\n\t\t\t\tlet triggerData: Record<string, unknown> = {};\n\t\t\t\tlet variables: Record<string, unknown> = {};\n\t\t\t\ttry {\n\t\t\t\t\ttriggerData = JSON.parse(opts.input);\n\t\t\t\t\tvariables = JSON.parse(opts.vars);\n\t\t\t\t} catch {\n\t\t\t\t\tprintError(\"--input and --vars must be valid JSON\", 2);\n\t\t\t\t}\n\n\t\t\t\tlet result: {\n\t\t\t\t\texecutionId: string;\n\t\t\t\t\tworkflowId: string;\n\t\t\t\t\tstatus: string;\n\t\t\t\t};\n\t\t\t\ttry {\n\t\t\t\t\tresult = await client.workflows.trigger(id, {\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t\ttriggerData,\n\t\t\t\t\t\tvariables,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tprintSuccess(\"Workflow triggered\");\n\t\t\t\tprocess.stdout.write(` Execution ID: ${result.executionId}\\n`);\n\t\t\t\tprocess.stdout.write(` Status: ${result.status}\\n`);\n\t\t\t},\n\t\t);\n\n\t// -- status --------------------------------------------------------------\n\tworkflows\n\t\t.command(\"status <id> <execId>\")\n\t\t.description(\"Get workflow execution status\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tid: string,\n\t\t\t\texecId: string,\n\t\t\t\topts: { org?: string; personal?: boolean; format: string },\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet exec: FabricExecution;\n\t\t\t\ttry {\n\t\t\t\t\texec = await client.workflows.getExecution(id, execId, {\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(exec, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintRecord({\n\t\t\t\t\tID: exec.id,\n\t\t\t\t\t\"Workflow ID\": exec.workflowId,\n\t\t\t\t\tStatus: exec.status,\n\t\t\t\t\t\"Trigger type\": exec.triggerType,\n\t\t\t\t\tStarted: exec.startedAt?.slice(0, 19) ?? \"(not started)\",\n\t\t\t\t\tCompleted: exec.completedAt?.slice(0, 19) ?? \"(running)\",\n\t\t\t\t\tError: exec.error ?? \"(none)\",\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\treturn workflows;\n}\n","/**\n * fabric workspaces\n *\n * fabric workspaces list List workspaces\n * fabric workspaces show <id> Show workspace details\n */\n\nimport type { FabricWorkspace, FabricWorkspaceDetail } from \"@fabricorg/sdk\";\nimport { Command } from \"commander\";\nimport { getClient } from \"../../lib/client.js\";\nimport { resolveContext } from \"../../lib/context.js\";\nimport { printError, printOutput, printRecord } from \"../../lib/output.js\";\n\nexport function buildWorkspacesCommand(): Command {\n\tconst workspaces = new Command(\"workspaces\").description(\n\t\t\"Manage workspaces\",\n\t);\n\n\t// -- list ----------------------------------------------------------------\n\tworkspaces\n\t\t.command(\"list\")\n\t\t.description(\"List workspaces\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--search <query>\", \"Search by name\")\n\t\t.option(\"--status <status>\", \"Filter: ACTIVE|ARCHIVED\")\n\t\t.option(\"--limit <n>\", \"Max results (default 20)\", \"20\")\n\t\t.option(\n\t\t\t\"--format <format>\",\n\t\t\t\"Output format: table|json|yaml|csv\",\n\t\t\t\"table\",\n\t\t)\n\t\t.option(\"-q, --quiet\", \"Print IDs only\")\n\t\t.action(\n\t\t\tasync (opts: {\n\t\t\t\torg?: string;\n\t\t\t\tpersonal?: boolean;\n\t\t\t\tsearch?: string;\n\t\t\t\tstatus?: string;\n\t\t\t\tlimit: string;\n\t\t\t\tformat: string;\n\t\t\t\tquiet?: boolean;\n\t\t\t}) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet list: FabricWorkspace[];\n\t\t\t\ttry {\n\t\t\t\t\tlist = await client.workspaces.list({\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t\tsearch: opts.search,\n\t\t\t\t\t\tstatus: opts.status as\n\t\t\t\t\t\t\t| \"ACTIVE\"\n\t\t\t\t\t\t\t| \"ARCHIVED\"\n\t\t\t\t\t\t\t| undefined,\n\t\t\t\t\t\tlimit: Number(opts.limit),\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tif (opts.quiet) {\n\t\t\t\t\tfor (const w of list) {\n\t\t\t\t\t\tprocess.stdout.write(`${w.id}\\n`);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintOutput(list, {\n\t\t\t\t\tformat: opts.format as \"table\" | \"json\" | \"yaml\" | \"csv\",\n\t\t\t\t\tcolumns: [\n\t\t\t\t\t\t\"id\",\n\t\t\t\t\t\t\"name\",\n\t\t\t\t\t\t\"type\",\n\t\t\t\t\t\t\"status\",\n\t\t\t\t\t\t\"documentCount\",\n\t\t\t\t\t\t\"updatedAt\",\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\t// -- show ----------------------------------------------------------------\n\tworkspaces\n\t\t.command(\"show <id>\")\n\t\t.description(\"Show workspace details\")\n\t\t.option(\"--org <slug>\", \"Organization context\")\n\t\t.option(\"--personal\", \"Retired — context is organization-only\")\n\t\t.option(\"--format <format>\", \"Output format: table|json|yaml\", \"table\")\n\t\t.action(\n\t\t\tasync (\n\t\t\t\tid: string,\n\t\t\t\topts: { org?: string; personal?: boolean; format: string },\n\t\t\t) => {\n\t\t\t\tconst ctx = resolveContext(opts.personal, opts.org, false);\n\t\t\t\tconst client = getClient();\n\t\t\t\tlet ws: FabricWorkspaceDetail;\n\t\t\t\ttry {\n\t\t\t\t\tws = await client.workspaces.get(id, {\n\t\t\t\t\t\torg: ctx?.type === \"org\" ? ctx.slug : undefined,\n\t\t\t\t\t});\n\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\tprintError((err as Error).message, 1);\n\t\t\t\t}\n\n\t\t\t\tconst fmt = opts.format as \"table\" | \"json\" | \"yaml\";\n\t\t\t\tif (fmt === \"json\" || fmt === \"yaml\") {\n\t\t\t\t\tprintOutput(ws, { format: fmt });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tprintRecord({\n\t\t\t\t\tID: ws.id,\n\t\t\t\t\tName: ws.name,\n\t\t\t\t\tType: ws.type,\n\t\t\t\t\tStatus: ws.status,\n\t\t\t\t\tDescription: ws.description ?? \"(none)\",\n\t\t\t\t\tDocuments: String(ws.documentCount),\n\t\t\t\t\tConversations: String(ws.conversationCount),\n\t\t\t\t\tUpdated: ws.updatedAt.slice(0, 10),\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\n\treturn workspaces;\n}\n"],"mappings":"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","names":["Command","_a","_a","rows","cols","_a","Command","Command","FabricAuthError","FabricClient","Command","Command","_a","FabricClient","FabricAuthError","Command","Command","Command","Command","_a","Command","Command","_a","Command","Command","Command","Command","Command","_a","Command","Command","_a","path","Command","createHash","_a","_a","_a","createHash","_a","readFile","path","path","readFile","_a","readFile","path","path","readFile","createHash","SHA256_HEX","createHash","_a","createHash","createHash","_a","Command","_a","path","Command","Command","_a","config","Command","Command","_a","Command","Command","_a","Command","Command","_a","Command","Command","_a","Command","Command","_a","Command","Command","_a","Command","Command","_a","Command"]}