@oxy-hq/cli 0.1.0
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.
- package/README.md +163 -0
- package/dist/main.mjs +6688 -0
- package/dist/main.mjs.map +1 -0
- package/dist/mcp-VdontkUr.mjs +316 -0
- package/dist/mcp-VdontkUr.mjs.map +1 -0
- package/json-schemas/agent-test.json +104 -0
- package/json-schemas/agentic.json +406 -0
- package/json-schemas/app.json +1884 -0
- package/json-schemas/config.json +2215 -0
- package/json-schemas/flow-test.json +124 -0
- package/json-schemas/global-semantics.json +782 -0
- package/json-schemas/workflow.json +1907 -0
- package/package.json +65 -0
- package/skills/oxy-airway-pipelines/SKILL.md +338 -0
- package/skills/oxy-automations/SKILL.md +67 -0
- package/skills/oxy-cli/SKILL.md +134 -0
- package/skills/oxy-custom-apps/SKILL.md +330 -0
- package/skills/oxy-data-architecture/SKILL.md +225 -0
- package/skills/oxy-semantic-modeling/SKILL.md +216 -0
- package/template/.gitattributes +2 -0
- package/template/.github/scripts/ci-publish.sh +77 -0
- package/template/.github/scripts/discover-apps.sh +175 -0
- package/template/.github/scripts/publish-env.sh +55 -0
- package/template/.github/workflows/publish.yaml +653 -0
- package/template/.github/workflows/validate.yaml +264 -0
- package/template/.nvmrc +1 -0
- package/template/.oxyc-managed +297 -0
- package/template/README.md +414 -0
- package/template/_gitignore +32 -0
- package/template/apps/.gitkeep +0 -0
- package/template/config.yml +53 -0
- package/template/memory/.gitkeep +0 -0
- package/template/package.json +17 -0
- package/template/pipelines/.gitkeep +0 -0
- package/template/pnpm-workspace.yaml +32 -0
- package/template/scripts/dev.sh +443 -0
- package/template/semantics/topics/.gitkeep +0 -0
- package/template/semantics/views/.gitkeep +0 -0
- package/template/workflows/.gitkeep +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.mjs","names":["readCache","writeCache","cacheFile","readCache","loadManifest","describe","unreachable","parseYaml","loadManifest"],"sources":["../src/util/errors.ts","../src/util/paths.ts","../src/api/cache.ts","../src/github/gh.ts","../src/util/git.ts","../src/customer/repos.ts","../src/customer/activity.ts","../src/ui/tty.ts","../src/ui/log.ts","../src/customer/dossier.ts","../src/github/customers.ts","../src/ui/render.ts","../src/commands/activity.ts","../src/api/fields.ts","../src/api/paths.ts","../src/api/request.ts","../src/api/output.ts","../src/api/paginate.ts","../src/commands/api.ts","../src/context/target.ts","../src/commands/assume.ts","../src/auth/credentials.ts","../src/auth/login.ts","../src/commands/auth.ts","../src/commands/customers.ts","../src/api/catalog.ts","../src/commands/discover.ts","../src/commands/guide.ts","../src/customer/workspace.ts","../src/commands/launch.ts","../src/commands/proxy.ts","../src/github/topics.ts","../src/template/manifest.ts","../src/template/render.ts","../src/template/adopt.ts","../src/generated/embedded-assets.ts","../src/template/embedded.ts","../src/template/locate.ts","../src/commands/registry.ts","../src/commands/repos.ts","../src/commands/skills.ts","../src/commands/validate.ts","../src/template/install.ts","../src/template/sync.ts","../src/commands/workspace.ts","../src/context/resolve.ts","../src/util/suggest.ts","../src/main.ts"],"sourcesContent":["/**\n * Failure, as something the caller can branch on.\n *\n * The audience is half machine, and an agent decides what to do next *solely*\n * from the exit code — so \"printed an error and exited 0\" is the one failure\n * mode this file exists to make unrepresentable. Every error path here carries\n * a code, and `main.ts` is the only place that calls `process.exit`.\n */\n\n/**\n * The exit-code contract. Stable, documented in `oxyc help exit-codes`, and\n * pinned by a test: a caller that branches on these is entitled to.\n *\n * 0/1/2 are the POSIX-conventional trio. The rest are ours, and each exists\n * because the *response* to it differs: an agent that gets AUTH re-runs\n * `oxyc login`, one that gets NOT_FOUND stops, one that gets UNAVAILABLE\n * retries. Collapsing them into 1 would make all three indistinguishable.\n */\nexport const ExitCode = {\n OK: 0,\n /** Something went wrong and there is nothing more specific to say. */\n FAILURE: 1,\n /** The invocation itself was wrong: unknown flag, missing argument, bad value. */\n USAGE: 2,\n /** No usable credential for this target. `oxyc login` is the fix. */\n AUTH: 4,\n /** The server answered 404, or a named customer/route/app does not exist. */\n NOT_FOUND: 5,\n /** The server answered 4xx other than 401/403/404 — the request was malformed. */\n REQUEST: 6,\n /** The server answered 5xx, or the network failed. Retryable. */\n UNAVAILABLE: 7,\n /** A refusal: the operation would have destroyed or overwritten something. */\n REFUSED: 8\n} as const;\n\nexport type ExitCodeValue = (typeof ExitCode)[keyof typeof ExitCode];\n\n/**\n * An error that already knows how it should end the process.\n *\n * THREE CHANNELS, and which one a string takes is a decision. `message` says\n * what went wrong. `hint` elaborates it — where to look, what the failure is\n * not, a command that helps. `remedy` is the one line about what to DO, and is\n * rendered set apart from the rest rather than in the run of elaborations.\n * Keeping them separate is what lets the renderer style them differently and\n * what stops any of them being buried mid-sentence where a reader skimming\n * stderr will miss it.\n *\n * NOT YET APPLIED EVERYWHERE. About seventy `hint:` values predate `remedy`,\n * and a fair number of them — `gh auth login`, `brew install jq` — are remedies\n * by this definition. Moved so far: the three sites that shipped ONE SENTENCE\n * through two channels, plus the one remedy left behind in a file being edited\n * for that reason — a leftover is least defensible in a file already open. The\n * rest is a sweep, deliberately not folded into the commit that introduced the\n * field.\n *\n * It is NOT UNIFORMLY a call-site edit. Three groups:\n *\n * - Sites building `new CliError` directly can move by renaming the field.\n * `authError` is the obvious first one — it is the canonical remedy\n * (`oxyc login --env …`) and the most-hit error in the tool, and nothing\n * stands between it and the field.\n * - Sites going through `refusal` can now pass one: it takes an OPTIONS OBJECT\n * rather than a fourth positional string, because four same-typed optionals\n * in a row let a `detail` and a `remedy` be swapped with no compile error,\n * and these two fields exist precisely to render differently.\n * - Sites going through `usageError` cannot yet. It is deliberately NOT widened\n * on spec: of its ten callers four pass a hint in position two, and adding an\n * optional third invites `usageError(msg, \"run X\")` to mean a remedy and\n * render as one more `→`. The risk is the future caller, not the count. It\n * gets an options object when one needs the field.\n */\nexport class CliError extends Error {\n readonly code: ExitCodeValue;\n readonly hint?: string;\n /** Extra lines printed verbatim under the message — a response body, a diff. */\n readonly detail?: string;\n\n /**\n * What to do about it, rendered set apart from the message.\n *\n * SEPARATE FROM `hint`, which shares one marker with path lists and other\n * elaborations. Without this the error path was the one consumer a remedy\n * could not reach in its own voice: `hint` renders through `log.hint`, so a\n * remedy handed to it printed as `→ chmod …` — an instruction in the run of\n * elaborations, which is what `log.remedy` exists to prevent.\n */\n readonly remedy?: string;\n\n constructor(\n message: string,\n opts: { code?: ExitCodeValue; hint?: string; detail?: string; remedy?: string } = {}\n ) {\n super(message);\n this.name = \"CliError\";\n this.code = opts.code ?? ExitCode.FAILURE;\n this.hint = opts.hint;\n this.detail = opts.detail;\n this.remedy = opts.remedy;\n }\n}\n\n/** The invocation was wrong. Distinct from a request that failed. */\nexport function usageError(message: string, hint?: string): CliError {\n return new CliError(message, { code: ExitCode.USAGE, hint });\n}\n\n/**\n * No credential for `target`.\n *\n * The hint names the exact command including the env, because the common case\n * is being logged into production and calling dev — where \"run oxyc login\"\n * without the `--env` sends you to log in again to the host you already have.\n */\nexport function authError(target: string, env: string, tokenEnv: string): CliError {\n return new CliError(`not authenticated for ${target}`, {\n code: ExitCode.AUTH,\n hint: `oxyc login --env ${env} (or set ${tokenEnv})`\n });\n}\n\n/**\n * A refusal — the operation was understood and declined because doing it would\n * have cost something unrecoverable. Never used for \"it failed\"; only for\n * \"it would have worked, and that is the problem\".\n */\nexport function refusal(\n message: string,\n // `code?: never` REJECTS one, rather than the spread order silently winning.\n // Excess-property checking is a literal-only rule, so a variable carrying a\n // `code` is assignable to a parameter that merely omits the field — ordering\n // then decides who wins, and the caller gets no signal that what they asked\n // for did not happen. As a property-type mismatch it is a compile error even\n // for a variable.\n //\n // THE ORDER STILL MATTERS — that is the runtime half. The type stops a typed\n // caller; `{ ...opts, code }` below stops an `as any`, an `@ts-expect-error`,\n // and the day a sweep widens this signature and drops the `never`. A\n // `refusal()` that exits 0 is \"printed an error and exited 0\", which this\n // file's header names as the one thing it exists to make unrepresentable.\n opts: { hint?: string; detail?: string; remedy?: string; code?: never } = {}\n): CliError {\n return new CliError(message, { ...opts, code: ExitCode.REFUSED });\n}\n\n/** Map an HTTP status onto the exit-code contract above. */\nexport function exitCodeForStatus(status: number): ExitCodeValue {\n if (status === 401 || status === 403) return ExitCode.AUTH;\n if (status === 404) return ExitCode.NOT_FOUND;\n if (status >= 500) return ExitCode.UNAVAILABLE;\n if (status >= 400) return ExitCode.REQUEST;\n return ExitCode.FAILURE;\n}\n","/**\n * Where this tool keeps things on disk.\n *\n * Cache and state are separated on purpose: everything under `cacheDir()` is\n * reconstructible from the network and may be deleted at any moment by the OS\n * or by `oxyc cache clear`, while `stateDir()` holds things whose loss costs\n * something. Putting a token in a cache directory is how a Mac's periodic\n * cleanup logs you out.\n */\n\nimport { chmodSync, mkdirSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\n/** `dirs::cache_dir()`, matching the Rust crate's platform rules. */\nexport function cacheDir(): string {\n if (process.platform === \"darwin\") return join(homedir(), \"Library\", \"Caches\");\n if (process.platform === \"win32\") {\n return process.env.LOCALAPPDATA ?? join(homedir(), \"AppData\", \"Local\");\n }\n const xdg = process.env.XDG_CACHE_HOME;\n if (xdg?.startsWith(\"/\")) return xdg;\n return join(homedir(), \".cache\");\n}\n\n/** This tool's cache root. `OXYC_CACHE_DIR` overrides, for tests. */\nexport function oxycCacheDir(): string {\n return process.env.OXYC_CACHE_DIR ?? join(cacheDir(), \"oxyc\");\n}\n\n/**\n * `mkdir -p`, returning the path so it composes into a `join`.\n *\n * `mode` is worth passing for anything holding response bodies or tokens:\n * the default is 0755, so a directory of cached authenticated responses would\n * be readable by every other user on the machine.\n */\nexport function ensureDir(path: string, mode?: number): string {\n mkdirSync(path, mode === undefined ? { recursive: true } : { recursive: true, mode });\n // `mkdir`'s mode applies only to a directory it CREATES. A cache directory\n // written by an earlier version — before these were tightened — already\n // exists at 0755, so without this every existing install would keep serving\n // world-readable response bodies and nothing would say so. Best-effort: a\n // filesystem with no POSIX modes must not fail the command over it.\n if (mode !== undefined) {\n try {\n chmodSync(path, mode);\n } catch {\n // A Windows share, or a directory owned by someone else. The caller's\n // work is not worth failing for a permission bit it cannot set.\n }\n }\n return path;\n}\n\n/**\n * A filesystem-safe fragment of an arbitrary string.\n *\n * Two different inputs can collapse onto one name, which is why every cache\n * file that uses this ALSO stores its true key inside the file and checks it\n * on read: the filename is the convenience, the stored field is the identity.\n */\nexport function slugifyForPath(value: string): string {\n return value.replace(/[^A-Za-z0-9._-]/g, \"_\");\n}\n","/**\n * `--cache <duration>` — reuse a recent successful response instead of asking\n * again.\n *\n * `gh api` has this and it matters more here than there: the caller is often\n * an agent walking the same few endpoints repeatedly inside one debugging\n * session, and the second `oxyc api {org}/workspaces` in ninety seconds is\n * asking a question whose answer cannot have changed.\n *\n * ONLY SUCCESSFUL, SAFE REQUESTS ARE CACHED. A cached 500 would turn a\n * transient outage into a sticky one, and a cached POST would silently drop\n * the second half of \"create it twice\" — so the write path refuses anything\n * that is not a 2xx GET/HEAD, rather than trusting callers to pass `--cache`\n * only where it is safe.\n */\n\nimport { createHash } from \"node:crypto\";\nimport { existsSync, readdirSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nimport { usageError } from \"../util/errors.js\";\nimport { ensureDir, oxycCacheDir } from \"../util/paths.js\";\n\ninterface CacheEntry {\n /** The full request key, stored so a filename collision can be detected. */\n key: string;\n status: number;\n headers: Record<string, string>;\n body: string;\n storedAt: number;\n}\n\n/**\n * Parse a Go-style duration (`30s`, `5m`, `2h`) into milliseconds.\n *\n * gh's spelling, so the flag transfers. A bare number is refused rather than\n * assumed to be seconds: `--cache 60` meaning a minute in one tool and an\n * hour in another is exactly the ambiguity a unit suffix removes.\n */\nexport function parseDuration(value: string): number {\n const match = /^(\\d+)(ms|s|m|h)$/.exec(value.trim());\n if (!match) {\n throw usageError(`invalid --cache '${value}', expected a duration like 30s, 5m or 2h`);\n }\n const amount = Number(match[1]);\n switch (match[2]) {\n case \"ms\":\n return amount;\n case \"s\":\n return amount * 1000;\n case \"m\":\n return amount * 60_000;\n default:\n return amount * 3_600_000;\n }\n}\n\n/**\n * The cache key: everything that can change the answer.\n *\n * The token is included via its hash — two people sharing a laptop must not\n * read each other's responses, and the same endpoint genuinely answers\n * differently per caller (`/api/user`, anything org-scoped). Hashed rather\n * than stored so the key itself is not a second place a bearer token lives.\n */\nexport function cacheKey(\n method: string,\n url: string,\n body: string | undefined,\n token: string | undefined\n): string {\n const identity = token ? createHash(\"sha256\").update(token).digest(\"hex\").slice(0, 16) : \"anon\";\n return `${method} ${url} ${identity} ${body ? createHash(\"sha256\").update(body).digest(\"hex\") : \"\"}`;\n}\n\nfunction entryPath(key: string): string {\n const digest = createHash(\"sha256\").update(key).digest(\"hex\");\n // 0700, and the entries below are written 0600. These files hold the BODIES\n // of authenticated multi-tenant responses — a customer's rows, an org's\n // member list — and the cache key already hashes the token precisely so two\n // users on one machine cannot read each other's. Leaving the bytes\n // world-readable would hand back exactly what that key is protecting.\n // Credentials take 0600 for the same reason; so should these.\n return join(ensureDir(join(oxycCacheDir(), \"responses\"), 0o700), `${digest}.json`);\n}\n\n/** A cached response, if there is a fresh one under this exact key. */\nexport function readCache(key: string, maxAgeMs: number): CacheEntry | undefined {\n try {\n const entry = JSON.parse(readFileSync(entryPath(key), \"utf8\")) as CacheEntry;\n // The filename is a hash and hashes can in principle collide; the stored\n // key is the identity. Cheap to check, and a wrong-body response served\n // as right would be indistinguishable from a server bug.\n if (entry.key !== key) return undefined;\n if (Date.now() - entry.storedAt > maxAgeMs) return undefined;\n return entry;\n } catch {\n return undefined;\n }\n}\n\n/** Store a response, if it is one that may be stored. */\nexport function writeCache(\n key: string,\n method: string,\n status: number,\n headers: Record<string, string>,\n body: string\n): void {\n const safe = method === \"GET\" || method === \"HEAD\";\n if (!safe || status < 200 || status >= 300) return;\n const entry: CacheEntry = { key, status, headers, body, storedAt: Date.now() };\n try {\n writeFileSync(entryPath(key), JSON.stringify(entry), { mode: 0o600 });\n } catch {\n // A cache that cannot be written is a slow tool, not a broken one.\n }\n}\n\n/** Everything this CLI writes under the cache root. */\nconst KNOWN_CACHES = [\"responses\", \"catalog\", \"customers\", \"repos.json\"] as const;\n\n/**\n * Drop EVERY cache this CLI writes, and report what went.\n *\n * `oxyc cache clear` used to call `clearResponseCache` alone while advertising\n * \"responses, route catalogs and customer listings\" — so the catalog, the\n * customer list and the repo scan all survived a command whose whole purpose\n * is to make the next call ask again. Someone clearing the cache to escape a\n * stale answer got the stale answer back.\n *\n * Clears what `KNOWN_CACHES` lists, BY NAME. A cache added later is therefore\n * not covered automatically — it survives, and shows up in\n * `unknownCacheEntries`, which is the deliberate trade: sweeping the whole\n * root would cover it, and would also `rm -rf` whatever else an\n * `OXYC_CACHE_DIR` pointed at a shared directory happened to contain.\n */\nexport function clearAllCaches(): string[] {\n const root = oxycCacheDir();\n // Nothing cached yet is the ordinary state on a fresh machine, and `cache\n // clear` is precisely the command somebody runs when they are not sure. It\n // must not be the one that throws ENOENT at them.\n if (!existsSync(root)) return [];\n const cleared: string[] = [];\n for (const entry of KNOWN_CACHES) {\n const path = join(root, entry);\n if (existsSync(path)) {\n rmSync(path, { recursive: true, force: true });\n cleared.push(entry);\n }\n }\n return cleared;\n}\n\n/**\n * Entries under the cache root this function does not know how to clear.\n *\n * NAMED, NOT DELETED. `clearAllCaches` used to sweep the whole root so that a\n * cache added later was covered without anyone remembering — but\n * `OXYC_CACHE_DIR` is a plain env override, so pointed at a shared directory,\n * `$XDG_CACHE_HOME`, or a mistyped path, that sweep is an unannounced `rm -rf`\n * of somebody else's files. Reporting the strays keeps the property that\n * mattered (an omission shows up in the output) with none of the risk.\n */\nexport function unknownCacheEntries(): string[] {\n const root = oxycCacheDir();\n if (!existsSync(root)) return [];\n try {\n return readdirSync(root, { withFileTypes: true })\n .map((e) => e.name)\n .filter((name) => !(KNOWN_CACHES as readonly string[]).includes(name));\n } catch {\n return [];\n }\n}\n","/**\n * Every call to the `gh` CLI goes through here.\n *\n * THE SAFETY RULE, which this whole file exists to enforce, is inherited from\n * `customer-tooling/lib/customers.sh` and is worth restating because every\n * function below is shaped by it:\n *\n * An empty or partial answer is an ERROR, never \"there is nothing\".\n *\n * GitHub is the only thing that knows who the customers are. A `gh` that is\n * missing, unauthenticated, rate-limited, offline or 5xx-ing must fail LOUDLY,\n * because an empty list returned from any of those makes every customer\n * silently vanish — from `oxyc list`, from name resolution, from every command\n * that asks. Nobody audits a list for absence.\n *\n * The inverse rule lives in `topics.ts`, for the write path: a 404 IS an\n * answer; everything else is inconclusive.\n */\n\nimport { spawnSync } from \"node:child_process\";\n\nimport { CliError, ExitCode } from \"../util/errors.js\";\n\nexport interface GhResult {\n stdout: string;\n stderr: string;\n status: number;\n}\n\n/** Run `gh` and hand back the raw result. Never throws on a non-zero exit. */\nexport function ghRaw(args: string[], input?: string): GhResult {\n const result = spawnSync(\"gh\", args, {\n input,\n encoding: \"utf8\",\n maxBuffer: 128 * 1024 * 1024\n });\n if (result.error) {\n const missing = (result.error as NodeJS.ErrnoException).code === \"ENOENT\";\n throw new CliError(\n missing ? \"the `gh` CLI is not installed\" : `gh failed to start: ${result.error.message}`,\n {\n code: missing ? ExitCode.USAGE : ExitCode.FAILURE,\n hint: missing ? \"brew install gh && gh auth login\" : undefined\n }\n );\n }\n return {\n stdout: result.stdout ?? \"\",\n stderr: result.stderr ?? \"\",\n status: result.status ?? 1\n };\n}\n\n/**\n * Classify a `gh` failure into a message that says which of the four things\n * went wrong.\n *\n * Four causes, four messages, because only one of them is about the data and\n * the other three are about the caller's machine. \"no customers found\" for an\n * expired token is the specific wrong answer this replaces.\n */\nfunction classify(result: GhResult, what: string): CliError {\n const stderr = result.stderr.toLowerCase();\n if (\n stderr.includes(\"not logged\") ||\n stderr.includes(\"authentication\") ||\n stderr.includes(\"gh auth login\")\n ) {\n return new CliError(`not authenticated to GitHub, so ${what} cannot be read`, {\n code: ExitCode.AUTH,\n hint: \"gh auth login\"\n });\n }\n if (stderr.includes(\"rate limit\")) {\n return new CliError(`GitHub rate-limited the request for ${what}`, {\n code: ExitCode.UNAVAILABLE,\n hint: \"wait for the limit to reset, or use a token with a higher quota\"\n });\n }\n if (\n stderr.includes(\"dial tcp\") ||\n stderr.includes(\"no such host\") ||\n stderr.includes(\"connection refused\") ||\n stderr.includes(\"timeout\") ||\n stderr.includes(\"network is unreachable\")\n ) {\n return new CliError(`could not reach GitHub to read ${what}`, {\n code: ExitCode.UNAVAILABLE,\n hint: \"check your connection and retry\"\n });\n }\n return new CliError(`gh failed while reading ${what}`, {\n code: ExitCode.UNAVAILABLE,\n detail: result.stderr.trim() || undefined\n });\n}\n\n/**\n * Run `gh` and parse JSON, refusing every shape of \"nothing came back\".\n *\n * `what` names the thing being read so the four messages above can be\n * specific — \"the customer list\", \"pokehouse-oxy's topics\".\n *\n * An exit-0-with-no-stdout is refused BEFORE parsing, because `JSON.parse(\"\")`\n * throws while `gh` exiting 0 with empty output is a real failure mode\n * (a broken pipe, an aborted paginated call) that would otherwise reach the\n * caller as a parse error about the wrong thing.\n */\nexport function ghJson<T>(args: string[], what: string): T {\n const result = ghRaw(args);\n if (result.status !== 0) throw classify(result, what);\n if (!result.stdout.trim()) {\n throw new CliError(`gh returned nothing while reading ${what}`, {\n code: ExitCode.UNAVAILABLE,\n hint: \"this is not an empty result — retry, and check `gh auth status`\"\n });\n }\n try {\n return JSON.parse(result.stdout) as T;\n } catch (cause) {\n throw new CliError(`could not parse gh's answer for ${what}`, {\n code: ExitCode.UNAVAILABLE,\n detail: (cause as Error).message\n });\n }\n}\n\n/**\n * A listing that came back exactly AT its limit is refused, not served.\n *\n * `gh repo list` and `gh search prs` truncate silently at their limit, and a\n * truncated list is a partial one — its dropped rows look like customers who\n * were deleted, or work nobody did. The guard cannot tell \"exactly N,\n * complete\" from \"truncated at N\", so it refuses both and says how to widen.\n *\n * This is not hypothetical: the first real `oxyc activity pokehouse` refused\n * because that repo has exactly 200 merged PRs and the limit was 200.\n */\nexport function refuseIfAtLimit(count: number, limit: number, what: string): void {\n if (count < limit) return;\n throw new CliError(`${what} came back at the limit of ${limit}, so it may be truncated`, {\n code: ExitCode.REFUSED,\n hint: `narrow the query, or raise the limit — a truncated list is served as complete otherwise`\n });\n}\n\n/** Whether `gh` is on PATH at all. For `oxyc doctor`, which reports rather than fails. */\nexport function ghAvailable(): boolean {\n const result = spawnSync(\"gh\", [\"--version\"], { encoding: \"utf8\" });\n return !result.error && result.status === 0;\n}\n","/**\n * The git questions this tool asks, in one place.\n *\n * All read-only except `clone`. Nothing here commits, branches or pushes —\n * that is a deliberate boundary inherited from the bash tooling: every command\n * writes files into a working tree and stops, and taking that through a branch\n * and a pull request stays a human's job.\n */\n\nimport { spawnSync } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nimport { CliError, ExitCode } from \"../util/errors.js\";\n\nfunction git(args: string[], cwd?: string): { stdout: string; stderr: string; status: number } {\n const result = spawnSync(\"git\", args, { cwd, encoding: \"utf8\", maxBuffer: 64 * 1024 * 1024 });\n if (result.error) {\n throw new CliError(`git failed to start: ${result.error.message}`, {\n code: ExitCode.FAILURE,\n hint: \"install git (xcode-select --install, or brew install git)\"\n });\n }\n return {\n stdout: result.stdout ?? \"\",\n stderr: result.stderr ?? \"\",\n status: result.status ?? 1\n };\n}\n\n/** Is `dir` inside a git working tree? */\nexport function isRepo(dir: string): boolean {\n return git([\"rev-parse\", \"--is-inside-work-tree\"], dir).status === 0;\n}\n\n/**\n * The repo ROOT for `dir`.\n *\n * Walks up to the real `.git`, which matters for the subdirectory-workspace\n * shape: a command run from `pokehouse-oxy/oxy/` must resolve the repo, not\n * the workspace.\n */\nexport function repoRoot(dir: string): string | undefined {\n const result = git([\"rev-parse\", \"--show-toplevel\"], dir);\n if (result.status !== 0) return undefined;\n return result.stdout.trim() || undefined;\n}\n\n/**\n * `<owner>/<name>` from a remote URL.\n *\n * DISCOVERY IS BY REMOTE, NOT BY PATH, and that is load-bearing rather than\n * tidy: on a real machine the checkouts sit under directory names that match\n * neither the GitHub org nor, in one case, the repo name. A\n * `<root>/<org>/<name>` convention finds none of them and reports four repos\n * as missing while all four are on disk.\n */\nexport function slugFromRemote(dir: string, remote = \"origin\"): string | undefined {\n const result = git([\"remote\", \"get-url\", remote], dir);\n if (result.status !== 0) return undefined;\n return parseRemoteSlug(result.stdout.trim());\n}\n\n/** `<owner>/<name>` from an SSH or HTTPS GitHub remote. */\nexport function parseRemoteSlug(url: string): string | undefined {\n const cleaned = url.trim().replace(/\\.git$/, \"\");\n // git@github.com:owner/name | ssh://git@github.com/owner/name\n const ssh = /^(?:ssh:\\/\\/)?[^@]+@[^:/]+[:/](.+)$/.exec(cleaned);\n if (ssh?.[1]) {\n const parts = ssh[1].split(\"/\").filter(Boolean);\n if (parts.length >= 2) return parts.slice(-2).join(\"/\");\n }\n // https://github.com/owner/name\n try {\n const parts = new URL(cleaned).pathname.split(\"/\").filter(Boolean);\n if (parts.length >= 2) return parts.slice(-2).join(\"/\");\n } catch {\n // Not a URL — fall through.\n }\n return undefined;\n}\n\n/** The checked-out branch, or `undefined` on a detached HEAD. */\nexport function currentBranch(dir: string): string | undefined {\n const result = git([\"symbolic-ref\", \"--quiet\", \"--short\", \"HEAD\"], dir);\n if (result.status !== 0) return undefined;\n return result.stdout.trim() || undefined;\n}\n\n/** The commit `HEAD` points at. */\nexport function headSha(dir: string): string | undefined {\n const result = git([\"rev-parse\", \"HEAD\"], dir);\n return result.status === 0 ? result.stdout.trim() : undefined;\n}\n\nexport interface WorkingTreeState {\n dirty: boolean;\n untracked: string[];\n modified: string[];\n}\n\n/**\n * What is uncommitted in `dir`.\n *\n * Untracked files are reported SEPARATELY from modified ones because the\n * commands that refuse on them refuse for different reasons: a modified file\n * is work in progress, an untracked one may be the only copy of something.\n */\nexport function workingTreeState(dir: string): WorkingTreeState {\n const result = git([\"status\", \"--porcelain=v1\", \"--untracked-files=all\"], dir);\n const untracked: string[] = [];\n const modified: string[] = [];\n for (const line of result.stdout.split(\"\\n\")) {\n if (!line.trim()) continue;\n const status = line.slice(0, 2);\n const path = line.slice(3);\n if (status === \"??\") untracked.push(path);\n else modified.push(path);\n }\n return { dirty: modified.length > 0, untracked, modified };\n}\n\n/** Clone `slug` into `dest`, preferring `gh` so private repos work unattended. */\nexport function clone(slug: string, dest: string, useGh: boolean): void {\n const [bin, args] = useGh\n ? ([\"gh\", [\"repo\", \"clone\", slug, dest]] as const)\n : ([\"git\", [\"clone\", `https://github.com/${slug}.git`, dest]] as const);\n const result = spawnSync(bin, [...args], { stdio: \"inherit\" });\n if (result.status !== 0) {\n throw new CliError(`could not clone ${slug} into ${dest}`, {\n code: ExitCode.FAILURE,\n hint: useGh ? undefined : \"install gh for private repos: brew install gh && gh auth login\"\n });\n }\n}\n\n/** Does `dir` look like a checkout at all? */\nexport function looksLikeCheckout(dir: string): boolean {\n return existsSync(join(dir, \".git\"));\n}\n","/**\n * Where OUR repos are on THIS machine — discovered, never assumed.\n *\n * A session working for a customer regularly has to touch one of the shared\n * repos: read how a connector behaves, fix the bug upstream, check what a\n * version actually shipped. Without this, it either guesses a path or clones a\n * second copy of a repo already sitting on disk.\n *\n * DISCOVERY IS BY GIT REMOTE, NOT BY PATH, and that is the whole design. On a\n * real machine every one of these is checked out under a directory named after\n * neither its GitHub org nor, in one case, its repo:\n *\n * ~/Workspace/github.com/dataframehq/oxy-internal → oxy-hq/oxygen-internal\n * ~/Workspace/github.com/dataframehq/airlayer → oxy-hq/airlayer\n *\n * A `<root>/<org>/<name>` convention finds NONE of them and reports four repos\n * as missing while all four are on disk. Reading `origin` finds them whatever\n * the directory is called.\n *\n * IT NEVER CLONES. A repo already on disk is named by its real path; one that\n * is not is named with the command that would fetch it, and the session\n * decides. A tool that pulled gigabytes because a briefing mentioned a repo is\n * one people switch off.\n */\n\nimport { existsSync, readdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { slugFromRemote } from \"../util/git.js\";\nimport { ensureDir, oxycCacheDir } from \"../util/paths.js\";\n\n/**\n * The shared repos, as a CONSTANT of the tool rather than a per-customer\n * field. They are the same for every customer, so a per-customer copy would be\n * the unread-field failure a `repos: []` already was once.\n */\nexport const SHARED_REPOS = [\n \"oxy-hq/oxygen-internal\",\n \"oxy-hq/airway-internal\",\n \"oxy-hq/airlayer\",\n \"oxy-hq/airhouse-internal\"\n] as const;\n\n/** Directories searched for checkouts. `OXYC_REPO_ROOTS` overrides (colon-separated). */\nfunction repoRoots(): string[] {\n const override = process.env.OXYC_REPO_ROOTS;\n if (override) return override.split(\":\").filter(Boolean);\n return [\n join(homedir(), \"Workspace\", \"github.com\"),\n join(homedir(), \"oxy-hq\"),\n join(homedir(), \"src\"),\n join(homedir(), \"code\"),\n join(homedir(), \"Projects\")\n ].filter((dir) => existsSync(dir));\n}\n\ninterface RepoCache {\n fetchedAt: number;\n map: Record<string, string>;\n}\n\nfunction cacheFile(): string {\n // The cache ROOT is closed here as well as the file, because `repos.json`\n // sits directly in it — the per-subdirectory 0700s elsewhere do not cover a\n // file written at the top level. It maps every checkout on this machine,\n // which is a map of what the owner works on.\n return join(ensureDir(oxycCacheDir(), 0o700), \"repos.json\");\n}\n\n/** A day: checkouts move rarely, and a stale entry is validated on read. */\nconst REPO_CACHE_TTL_MS = 86_400_000;\n\n/**\n * Scan for checkouts, two levels deep under each root.\n *\n * Two levels because the common layouts are `<root>/<org>/<repo>` and\n * `<root>/<repo>`. Deeper would walk into `node_modules` and `target` on a\n * machine that keeps code under its home directory, which costs seconds for\n * repos nobody was looking for.\n */\nfunction scan(): Record<string, string> {\n const map: Record<string, string> = {};\n for (const root of repoRoots()) {\n for (const first of safeDirs(root)) {\n const firstPath = join(root, first);\n record(map, firstPath);\n for (const second of safeDirs(firstPath)) {\n record(map, join(firstPath, second));\n }\n }\n }\n return map;\n}\n\nfunction safeDirs(dir: string): string[] {\n try {\n return readdirSync(dir, { withFileTypes: true })\n .filter((e) => e.isDirectory() && !e.name.startsWith(\".\") && e.name !== \"node_modules\")\n .map((e) => e.name);\n } catch {\n return [];\n }\n}\n\nfunction record(map: Record<string, string>, path: string): void {\n if (!existsSync(join(path, \".git\"))) return;\n const slug = slugFromRemote(path);\n // First one wins, so a scan that finds two checkouts of the same repo is\n // deterministic rather than depending on directory order.\n if (slug && !map[slug]) map[slug] = path;\n}\n\n/** `<org>/<repo>` → local path, for every checkout found. */\nexport function repoMap(opts: { refresh?: boolean } = {}): Record<string, string> {\n if (!opts.refresh) {\n try {\n const cached = JSON.parse(readFileSync(cacheFile(), \"utf8\")) as RepoCache;\n if (Date.now() - cached.fetchedAt < REPO_CACHE_TTL_MS) {\n // Validated on read: a checkout that has been moved or deleted since\n // the scan must not be reported as present, because the session would\n // then `cd` into nothing.\n return Object.fromEntries(\n Object.entries(cached.map).filter(([, path]) => existsSync(path))\n );\n }\n } catch {\n // No cache, or an unreadable one. Scan.\n }\n }\n const map = scan();\n try {\n writeFileSync(cacheFile(), JSON.stringify({ fetchedAt: Date.now(), map }), { mode: 0o600 });\n } catch {\n // A cache that cannot be written costs a scan per launch, not an answer.\n }\n return map;\n}\n\n/** The local path for one of our repos, if it is on this machine. */\nexport function localPath(slug: string, opts: { refresh?: boolean } = {}): string | undefined {\n return repoMap(opts)[slug];\n}\n\n/**\n * The block a launch briefing embeds: each shared repo, and either where it is\n * or the command that would fetch it.\n */\nexport function sharedRepoContext(opts: { refresh?: boolean } = {}): string {\n const map = repoMap(opts);\n return SHARED_REPOS.map((slug) => {\n const path = map[slug];\n return path ? ` ${slug} — ${path}` : ` ${slug} — not on this machine (gh repo clone ${slug})`;\n }).join(\"\\n\");\n}\n\n/**\n * The line a session writes into a cross-repo pull request body.\n *\n * ONE DEFINITION, TWO READERS. The briefing tells a session to write this, and\n * `oxyc activity` matches on exactly it. A briefing that told the session a\n * different spelling would produce pull requests the reader can never find, so\n * neither side is allowed its own copy.\n */\nexport function attributionLine(customerName: string): string {\n return `Customer: ${customerName}`;\n}\n","/**\n * Delivery activity — merged pull requests per customer, read from GitHub at\n * query time.\n *\n * TWO QUERIES, AND THEY DIFFER IN KIND:\n *\n * the customer's OWN repo the repo IS the customer, so every merged PR\n * counts and nothing has to be marked. Exact,\n * retroactive, forgery-proof.\n * our SHARED repos returns their whole PR stream, so repo scope\n * means nothing here. Attribution is per-PR: a\n * `Customer: <name>` line the session writes into\n * the body. GitHub search TOKENIZES, so a hit is a\n * CANDIDATE; the local re-filter below decides.\n *\n * THE SAFETY RULE is `gh.ts`'s, for the same reason: an empty answer here is\n * indistinguishable from a broken call, a merged PR that never appears looks\n * like work that never happened, and nobody audits a record for absence.\n */\n\nimport { ghJson, refuseIfAtLimit } from \"../github/gh.js\";\nimport { CliError, ExitCode } from \"../util/errors.js\";\nimport { attributionLine, SHARED_REPOS } from \"./repos.js\";\n\nexport interface ActivityRecord {\n repo: string;\n number: number;\n title: string;\n url: string;\n author: string;\n mergedAt: string;\n /** `own` for the customer's repo, `shared` for one of ours. */\n via: \"own\" | \"shared\";\n /** `YYYY-MM`, derived here so a reader of the file can group without this code. */\n month: string;\n}\n\n/**\n * The ceiling `gh search prs` is asked for, and THE DEFAULT IS THE CEILING.\n *\n * The refusal below fires whenever the count EQUALS the limit, and it cannot\n * tell \"exactly N, complete\" from \"truncated at N\". Any default below gh's own\n * maximum therefore turns some perfectly ordinary repo into a permanent\n * refusal — which is not hypothetical: the first real run of this command\n * refused because that customer's repo had exactly 200 merged pull requests\n * and the default was 200. At the ceiling, a refusal means a result set\n * genuinely larger than anything gh will return, where `--since` really is the\n * answer.\n */\nfunction searchLimit(): number {\n const raw = Number(process.env.OXYC_SEARCH_LIMIT ?? \"1000\");\n return Number.isFinite(raw) && raw > 0 ? Math.min(raw, 1000) : 1000;\n}\n\n/**\n * The attribution matcher — and THE ONE THAT LOOKS RIGHT AND MATCHES NOTHING.\n *\n * The obvious spelling is an exact `^Customer: <name>$` body line. Transcribed\n * into jq that filter can NEVER fire, because jq's `^` and `$` are STRING\n * anchors, not line anchors, and its \"m\" flag only makes `.` match a newline.\n * Every cross-repo PR would have been dropped and the command would have\n * reported an honest-looking zero forever.\n *\n * JavaScript has a real multiline flag, so the trap does not exist here — but\n * the rest of the pattern is each its own small refusal and all of them are\n * kept:\n *\n * (^|\\r?\\n) a real line start. GitHub bodies are \\n today, but the API\n * has always been free to hand back \\r\\n, and a stray CR\n * would sit between the name and the anchor and silently miss.\n * [Cc]ustomer: the label a human repairing a body by hand might lowercase.\n * [ \\t]* spacing nobody should have to get exactly right.\n * <name> REGEX-ESCAPED: a repo name may contain `.`, which is a\n * metacharacter, and an unescaped one matches any character.\n * [ \\t\\r]*(\\n|$) trailing whitespace, and the CR again.\n *\n * What it deliberately does NOT match: the name inside a prose sentence, an\n * indented `- Customer: x` list item, or `x-staging` when the customer is `x`.\n */\nexport function attributionPattern(customerName: string): RegExp {\n const escaped = customerName.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n return new RegExp(`(^|\\\\r?\\\\n)[Cc]ustomer:[ \\\\t]*${escaped}[ \\\\t\\\\r]*(\\\\n|$)`);\n}\n\ninterface SearchHit {\n repository?: { nameWithOwner?: string };\n number?: number;\n title?: string;\n url?: string;\n author?: { login?: string };\n body?: string;\n closedAt?: string;\n}\n\n/** One guarded `gh search prs`. Every failure mode is loud; none returns empty. */\nfunction search(term: string | undefined, since: string | undefined, repos: string[]): SearchHit[] {\n const limit = searchLimit();\n const args = [\n \"search\",\n \"prs\",\n \"--merged\",\n \"--limit\",\n String(limit),\n \"--json\",\n \"repository,number,title,url,author,body,closedAt\"\n ];\n for (const repo of repos) args.push(\"--repo\", repo);\n if (since) args.push(\"--merged-at\", `>=${since}`);\n // The term may be empty — that is the customer's own repo, where the repo\n // filter IS the query and there is nothing to search for.\n if (term) args.push(term);\n\n const hits = ghJson<SearchHit[]>(args, `merged pull requests in ${repos.join(\", \")}`);\n refuseIfAtLimit(hits.length, limit, `the pull-request search for ${repos.join(\", \")}`);\n return hits;\n}\n\nfunction normalise(hit: SearchHit, via: \"own\" | \"shared\"): ActivityRecord | undefined {\n const mergedAt = hit.closedAt;\n if (!mergedAt) return undefined;\n return {\n repo: hit.repository?.nameWithOwner ?? \"\",\n number: hit.number ?? 0,\n title: hit.title ?? \"\",\n url: hit.url ?? \"\",\n author: hit.author?.login ?? \"\",\n mergedAt,\n via,\n // Derived HERE rather than at render time: it is the bucketing key, and a\n // reader who never runs this code can still group the file.\n month: mergedAt.slice(0, 7)\n };\n}\n\nexport interface ActivityOptions {\n /** The customer's repo name, which is also the attribution token. */\n name: string;\n /** `<org>/<name>` for the customer's own repo. */\n ownRepo: string;\n /** Only pull requests merged on or after this date (YYYY-MM-DD). */\n since?: string;\n /** Extra repos to search, beyond the shared four. */\n extraRepos?: string[];\n}\n\n/**\n * Both queries, merged.\n *\n * The customer's own repo needs no attribution; the shared repos are\n * RE-FILTERED LOCALLY because a GitHub search hit is only a candidate — the\n * index tokenises, so searching for `Customer: acme` also returns PRs that\n * merely mention either word.\n */\nexport function collectActivity(opts: ActivityOptions): ActivityRecord[] {\n const own = search(undefined, opts.since, [opts.ownRepo])\n .map((hit) => normalise(hit, \"own\"))\n .filter((r): r is ActivityRecord => r !== undefined);\n\n const sharedRepos = [...SHARED_REPOS, ...(opts.extraRepos ?? [])];\n const pattern = attributionPattern(opts.name);\n const shared = search(attributionLine(opts.name), opts.since, sharedRepos)\n .filter((hit) => pattern.test(hit.body ?? \"\"))\n .map((hit) => normalise(hit, \"shared\"))\n .filter((r): r is ActivityRecord => r !== undefined);\n\n return [...own, ...shared].sort((a, b) => a.mergedAt.localeCompare(b.mergedAt));\n}\n\n/**\n * Attributions naming somebody who is NOT this customer, among the candidates\n * already fetched.\n *\n * OPPORTUNISTIC, and said out loud rather than sold as a sweep: these are\n * bodies the search returned while looking for THIS customer, so the only ones\n * visible are those that happened to share tokens. A typo nobody's search\n * collides with stays invisible. Finding a real one usually means a typo, or a\n * repo that lost its topic — both worth a human's eye, and neither worth a\n * second firehose query against the bare word \"Customer\", which comes back at\n * the cap.\n */\nexport function foreignAttributions(records: SearchHit[], name: string): string[] {\n const found = new Set<string>();\n for (const hit of records) {\n for (const match of (hit.body ?? \"\").matchAll(/(?:^|\\r?\\n)[Cc]ustomer:[ \\t]*([^\\s\\r\\n]+)/g)) {\n const named = match[1];\n if (named && named !== name) found.add(named);\n }\n }\n return [...found].sort();\n}\n\n/** The distinct months a result set touches, oldest first. */\nexport function monthsIn(records: ActivityRecord[]): string[] {\n return [...new Set(records.map((r) => r.month))].sort();\n}\n\n/**\n * Markdown for one month.\n *\n * NO GENERATED-ON TIMESTAMP, deliberately. The record is keyed by (repo,\n * number) so a re-run is idempotent; a date stamped into the markdown would\n * make every re-run a diff, and a file that churns without changing meaning is\n * one people stop reading. Git already records when it was written.\n */\nexport function renderMonth(month: string, display: string, records: ActivityRecord[]): string {\n const forMonth = records.filter((r) => r.month === month);\n const lines = [`# ${display} — ${month}`, \"\"];\n for (const via of [\"own\", \"shared\"] as const) {\n const group = forMonth.filter((r) => r.via === via);\n if (group.length === 0) continue;\n lines.push(via === \"own\" ? \"## In their repo\" : \"## In our repos\", \"\");\n for (const record of group) {\n lines.push(\n `- [${record.repo}#${record.number}](${record.url}) — ${record.title} (@${record.author})`\n );\n }\n lines.push(\"\");\n }\n return lines.join(\"\\n\");\n}\n\n/** One JSON object per line — the authoritative half, byte-stable across re-runs. */\nexport function renderJsonl(month: string, records: ActivityRecord[]): string {\n return records\n .filter((r) => r.month === month)\n .map((r) =>\n JSON.stringify({\n repo: r.repo,\n number: r.number,\n title: r.title,\n url: r.url,\n author: r.author,\n merged_at: r.mergedAt,\n via: r.via,\n month: r.month\n })\n )\n .join(\"\\n\");\n}\n\n/** A month with no merged PRs produces NO FILE rather than an empty one. */\nexport function requireNonEmpty(records: ActivityRecord[], name: string): void {\n if (records.length > 0) return;\n throw new CliError(`no merged pull requests found for ${name}`, {\n code: ExitCode.NOT_FOUND,\n hint: 'an empty file is a claim, and \"we did nothing\" is not one this record is entitled to make'\n });\n}\n","/**\n * Which of the two audiences is reading, and the styling that follows from it.\n *\n * One tool, two readers. A human at a terminal wants colour, alignment and a\n * spinner; an agent — or a pipe — wants markdown and plain bytes. The test is\n * whether the stream is a TTY, per clig.dev, and it is asked *per stream*:\n * stdout is routinely piped while stderr stays attached to the terminal, and\n * a run that dropped colour from its progress messages because its data was\n * being piped would be answering the wrong question.\n */\n\nimport pc from \"picocolors\";\n\n/** True when stdout is a terminal — i.e. a human is reading the *data*. */\nexport function stdoutIsTty(): boolean {\n return Boolean(process.stdout.isTTY);\n}\n\n/** True when stderr is a terminal — i.e. a human is reading the *progress*. */\nexport function stderrIsTty(): boolean {\n return Boolean(process.stderr.isTTY);\n}\n\n/**\n * Whether to emit ANSI colour.\n *\n * `NO_COLOR` (any non-empty value) wins over everything — it is the whole\n * point of the convention that a user can turn colour off without the tool\n * getting a vote. `FORCE_COLOR` is the other direction, for CI logs that\n * render ANSI. Absent both, the stream decides.\n */\nexport function colorEnabled(stream: \"stdout\" | \"stderr\" = \"stdout\"): boolean {\n if (process.env.NO_COLOR) return false;\n if (process.env.FORCE_COLOR && process.env.FORCE_COLOR !== \"0\") return true;\n return stream === \"stdout\" ? stdoutIsTty() : stderrIsTty();\n}\n\n/**\n * Colour helpers that no-op when colour is off.\n *\n * picocolors already checks `NO_COLOR` and TTY-ness itself, but only against\n * stdout — so a message written to stderr while stdout is piped would come\n * out uncoloured for a human who is looking straight at it. Routing every\n * style through here keeps the per-stream answer above authoritative.\n */\nfunction styler(stream: \"stdout\" | \"stderr\") {\n const on = colorEnabled(stream);\n const wrap =\n (fn: (s: string) => string) =>\n (s: string): string =>\n on ? fn(s) : s;\n return {\n bold: wrap(pc.bold),\n dim: wrap(pc.dim),\n red: wrap(pc.red),\n green: wrap(pc.green),\n yellow: wrap(pc.yellow),\n blue: wrap(pc.blue),\n cyan: wrap(pc.cyan),\n magenta: wrap(pc.magenta),\n gray: wrap(pc.gray),\n underline: wrap(pc.underline)\n };\n}\n\n/** Styles for data written to stdout. */\nexport const out = styler(\"stdout\");\n/** Styles for messages written to stderr. */\nexport const err = styler(\"stderr\");\n\n/**\n * How wide to lay a table or wrap a paragraph.\n *\n * Falls back to 100 rather than 80 when there is no terminal: the non-TTY\n * reader is a pipe or an agent, neither of which has an 80-column limit, and\n * a route path plus its description does not fit in 80.\n */\nexport function terminalWidth(): number {\n const cols = process.stdout.columns;\n if (typeof cols === \"number\" && cols > 20) return cols;\n return 100;\n}\n","/**\n * Everything that is *not* the answer goes to stderr.\n *\n * The rule that makes this tool pipeable: stdout carries the response body and\n * nothing else, so `oxyc api user | jq .email` works and `oxyc routes --json`\n * is valid JSON on the first byte. Progress, warnings, staleness notices and\n * the \"what to run next\" hints all go here.\n */\n\nimport { err, stderrIsTty } from \"./tty.js\";\n\nfunction write(line: string): void {\n process.stderr.write(`${line}\\n`);\n}\n\n/** Ordinary progress. Suppressed when `--quiet` set OXYC_QUIET. */\nexport function info(message: string): void {\n if (process.env.OXYC_QUIET) return;\n write(err.dim(message));\n}\n\n/**\n * Something is off but the run continues — a stale cache, a skipped file.\n *\n * Never suppressed by `--quiet`. A warning that a quiet flag can hide is a\n * warning nobody sees on the run where it mattered, and the loudest of these\n * (\"serving a STALE customer list\") exists precisely to stop a degraded answer\n * from passing as a good one.\n */\nexport function warn(message: string): void {\n write(`${err.yellow(\"warning:\")} ${message}`);\n}\n\n/** A failure, on its way to a non-zero exit. */\nexport function error(message: string): void {\n write(`${err.red(\"error:\")} ${message}`);\n}\n\n/**\n * A line elaborating the message above it — under a warning, an error or a\n * refusal, never on its own.\n *\n * Originally documented as \"what to type next\", which its callers outgrew: the\n * highest-volume one lists PATHS, another states a CONSEQUENCE, others do name\n * a command. What they share is that `→` points back at the line above, and\n * that is the accurate reading of the marker — not \"listed item\", which an\n * earlier version of `remedy`'s doc leaned on and which the path lists happen\n * to satisfy by coincidence.\n */\nexport function hint(message: string): void {\n write(` ${err.dim(\"→\")} ${message}`);\n}\n\n/**\n * What to do about what was just reported — set apart from it.\n *\n * A SIBLING OF `hint`, not `hint` itself, and the distinction is SEPARATION,\n * not \"listed item versus instruction\": `→` elaborates the line above, so a\n * remedy printed with it is one more elaboration among ten paths, read in\n * sequence with them. This is the one line that is not about what happened but\n * about what to do, and the blank lines are what say so. Not `info` either —\n * that is suppressed by `--quiet`, and this hangs off a warning that\n * deliberately is not.\n *\n * Takes the whole group, so N remedies are one bracketed block rather than N\n * blocks with doubled blanks between them — and SPLITS EACH ONE, so a remedy\n * that grows a newline keeps the marker on every line instead of printing a\n * bare continuation. One meaning for the parameter: each argument is a remedy.\n * A caller splitting its own string would have made it two.\n */\nexport function remedy(...messages: string[]): void {\n // Checked on the ARGUMENTS, not on the split: `split(\"\\n\")` always yields at\n // least one element, so `lines.length === 0` is the same test one derivation\n // away — and the caller this guard is for spreads a possibly-empty array.\n if (messages.length === 0) return;\n const lines = messages.flatMap((message) => message.split(\"\\n\"));\n // BLANK ON BOTH SIDES. With one only above, the block attached DOWNWARD to\n // whatever came next — and the common case is a `log.error` that follows\n // immediately, so `fix:` ended up closer to an unrelated error than to the\n // warning it belongs to, inverting the grouping the separator was added for.\n write(\"\");\n for (const line of lines) write(` ${err.dim(\"fix:\")} ${line}`);\n write(\"\");\n}\n\n/**\n * A step whose duration a human would otherwise wonder about.\n *\n * Deliberately not a spinner library: a spinner writes escape codes on a timer\n * and a non-TTY stderr — CI, an agent capturing output — collects every frame\n * as a separate line. Under a TTY this rewrites one line; otherwise it prints\n * the label once and the outcome once, which is exactly what a log wants.\n */\nexport function step(label: string): { done: (outcome?: string) => void } {\n if (process.env.OXYC_QUIET) return { done: () => {} };\n if (!stderrIsTty()) {\n write(err.dim(`${label}…`));\n return {\n done: (outcome) => {\n if (outcome) write(err.dim(` ${outcome}`));\n }\n };\n }\n process.stderr.write(err.dim(`${label}… `));\n return {\n done: (outcome) => {\n process.stderr.write(`\\r\u001b[2K${err.dim(`${label}… ${outcome ?? \"done\"}`)}\\n`);\n }\n };\n}\n","/**\n * Where a customer's repo lives on THIS machine.\n *\n * A customer IS an `<org>/<name>` repo on GitHub — shared with the team, so\n * nothing about their identity may be a path that exists on one laptop. The\n * local path is DERIVED, per machine, from the slug:\n *\n * <root>/<org>/<name>, root = $OXYC_DOSSIER_ROOT or ~/.oxyc/dossiers\n *\n * The default root is tool-owned, like `~/.claude` or `~/.cargo`. A default\n * under the user's own code tree would fix portability across usernames while\n * still assuming every teammate lays their code out the same way — the same\n * class of assumption this scheme exists to remove. `$OXYC_DOSSIER_ROOT` is\n * the escape hatch for anyone who wants dossiers in their own layout; the\n * clones stay ordinary git repos wherever they land.\n *\n * The root deliberately stops BEFORE the org: the org comes from the slug, so\n * two orgs cannot collide on a repo name, and a root that already carried one\n * would resolve `oxy-hq/acme-oxy` to `…/oxy-hq/oxy-hq/acme-oxy`.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { ghAvailable } from \"../github/gh.js\";\nimport * as log from \"../ui/log.js\";\nimport { CliError, ExitCode } from \"../util/errors.js\";\nimport { clone, looksLikeCheckout, repoRoot, slugFromRemote } from \"../util/git.js\";\n\n/**\n * The directory every dossier clone sits under.\n *\n * `~/.oxyc/dossiers` rather than this tool's own state directory, and that is\n * a MIGRATION decision, not a preference: the bash `oxyc` this replaces used\n * exactly that path, and teammates have customer repos cloned there with\n * branches and uncommitted work in them. Moving the default would leave every\n * one of those orphaned — the tool would report each customer as \"not cloned\n * here\" and cheerfully clone a second copy beside the first.\n */\nexport function dossierRoot(): string {\n return process.env.OXYC_DOSSIER_ROOT ?? join(homedir(), \".oxyc\", \"dossiers\");\n}\n\n/**\n * The local path a repo slug resolves to.\n *\n * The slug is VALIDATED rather than pasted in: `<root>/<whatever>` would\n * happily accept an absolute path (`/Users/someone/…` → `<root>//Users/…`) or\n * a `..`, which is exactly the machine-specific shape this scheme exists to\n * keep out of a customer's identity.\n */\nexport function dossierPath(slug: string): string {\n if (!/^[A-Za-z0-9][A-Za-z0-9._-]*\\/[A-Za-z0-9][A-Za-z0-9._-]*$/.test(slug)) {\n throw new CliError(`not a repo slug: \"${slug}\"`, {\n code: ExitCode.USAGE,\n hint: \"expected <org>/<name>, e.g. oxy-hq/acme-oxy — not a path\"\n });\n }\n return join(dossierRoot(), slug);\n}\n\n/** Is the clone here? */\nexport function isCloned(slug: string): boolean {\n const path = dossierPath(slug);\n return existsSync(path) && looksLikeCheckout(path);\n}\n\n/**\n * The clone, cloning it if it is not here yet.\n *\n * ONE DECISION, TWO CONSUMERS: the command PRINTED when this declines to clone\n * must be the command it would have RUN. Splitting the choice out is what\n * stops the printed instruction from drifting away from the real one.\n */\nexport function ensureCloned(slug: string, opts: { autoClone?: boolean } = {}): string {\n const path = dossierPath(slug);\n if (isCloned(slug)) return path;\n\n const useGh = ghAvailable();\n const command = useGh\n ? `gh repo clone ${slug} ${path}`\n : `git clone https://github.com/${slug}.git ${path}`;\n\n if (!opts.autoClone) {\n throw new CliError(`${slug} is not cloned here`, {\n code: ExitCode.NOT_FOUND,\n hint: command\n });\n }\n\n log.info(`cloning ${slug} → ${path}`);\n clone(slug, path, useGh);\n return path;\n}\n\n/**\n * The customer a directory belongs to, if any.\n *\n * Resolves by walking to the git root and reading `origin`, so it works from\n * anywhere inside the checkout — including from inside a subdirectory\n * workspace, which is where a session that has `cd`-ed into `oxy/` will be.\n */\nexport function slugForDirectory(dir: string): string | undefined {\n const root = repoRoot(dir);\n if (!root) return undefined;\n return slugFromRemote(root);\n}\n","/**\n * Who the customers are — derived from GitHub, never read from a file.\n *\n * Membership is the repo topic `oxy-customer` in `$OXYC_ORG` and nothing else,\n * so creating or tagging the repo IS the registration. There is no suffix\n * rule: `-oxy` and the legacy `-context` are just names, and `pokehouse-oxy`\n * and `pokehouse-context` may both exist.\n *\n * Every refusal below is `customer-tooling/lib/customers.sh`'s, ported with\n * its reasoning intact. See `gh.ts` for the safety rule they all serve.\n */\n\nimport { readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport * as log from \"../ui/log.js\";\nimport { CliError, ExitCode } from \"../util/errors.js\";\nimport { ensureDir, oxycCacheDir, slugifyForPath } from \"../util/paths.js\";\nimport { ghJson, ghRaw, refuseIfAtLimit } from \"./gh.js\";\n\nexport interface Customer {\n /** The repo name, which is the customer's identity. */\n name: string;\n /** The repo description, used as a display name. May be empty. */\n description: string;\n}\n\ninterface CustomerCache {\n org: string;\n fetchedAt: number;\n customers: Customer[];\n}\n\n/** The org customer repos live in. */\nexport function customersOrg(): string {\n return process.env.OXYC_ORG ?? \"oxy-hq\";\n}\n\n/** The topic that decides membership. One place, so read and write agree. */\nexport function customersTopic(): string {\n return process.env.OXYC_CUSTOMER_TOPIC ?? \"oxy-customer\";\n}\n\n/**\n * The ceiling `gh` is asked for. A listing that comes back exactly AT it is\n * refused rather than served — see `refuseIfAtLimit`.\n */\nfunction listLimit(): number {\n const raw = Number(process.env.OXYC_LIST_LIMIT ?? \"1000\");\n return Number.isFinite(raw) && raw > 0 ? raw : 1000;\n}\n\n/**\n * An hour. Long enough that a session's worth of commands costs one `gh` call,\n * short enough that a customer created this morning shows up before lunch.\n */\nfunction cacheTtlMs(): number {\n const raw = Number(process.env.OXYC_CACHE_TTL ?? \"3600\");\n return (Number.isFinite(raw) && raw >= 0 ? raw : 3600) * 1000;\n}\n\n/**\n * The cache file, keyed by ORG in its NAME and again in its CONTENTS.\n *\n * Switching `$OXYC_ORG` must not serve another org's customers, and a single\n * shared file would do exactly that until the TTL expired. A filename cannot\n * carry every character an org name might, so the sanitised name is the\n * convenience and the stored field is the identity.\n */\nfunction cacheFile(org: string): string {\n // 0700/0600 like the response and catalog caches. This file is the customer\n // list of the business, read out of a PRIVATE GitHub org — leaving it\n // world-readable would publish to every local user exactly what `gh` had to\n // authenticate to see.\n return join(ensureDir(join(oxycCacheDir(), \"customers\"), 0o700), `${slugifyForPath(org)}.json`);\n}\n\nfunction readCache(org: string): CustomerCache | undefined {\n try {\n const cached = JSON.parse(readFileSync(cacheFile(org), \"utf8\")) as CustomerCache;\n if (cached.org !== org || !Array.isArray(cached.customers)) return undefined;\n return cached;\n } catch {\n return undefined;\n }\n}\n\nfunction writeCache(org: string, customers: Customer[]): void {\n try {\n writeFileSync(cacheFile(org), JSON.stringify({ org, fetchedAt: Date.now(), customers }), {\n mode: 0o600\n });\n } catch {\n log.warn(\"could not write the customer cache; every command will ask GitHub\");\n }\n}\n\n/** Drop the cached listing, so the next read asks GitHub. */\nexport function invalidateCache(org = customersOrg()): void {\n try {\n writeFileSync(cacheFile(org), JSON.stringify({ org, fetchedAt: 0, customers: [] }), {\n mode: 0o600\n });\n } catch {\n // Nothing to do: a cache that cannot be invalidated expires on its own.\n }\n}\n\n/**\n * Confirm `gh` can actually see private repos before asking it to list them.\n *\n * THE SINGLE MOST DANGEROUS SHAPE this module can be handed: customer repos\n * are private, so an unauthenticated `gh repo list` succeeds and returns a\n * plausible EMPTY ARRAY. Every refusal downstream is looking for a failure,\n * and this one does not look like a failure — so it is checked up front, as a\n * precondition, rather than inferred from a result that will never say it.\n */\nfunction requireGhAuth(org: string): void {\n const status = ghRaw([\"auth\", \"status\"]);\n if (status.status !== 0) {\n throw new CliError(\"gh is installed but not authenticated\", {\n code: ExitCode.AUTH,\n hint: \"gh auth login\",\n detail:\n `Customer repos in ${org} are private, so an unauthenticated listing comes back\\n` +\n `EMPTY — which is not \"${org} has no customers\".`\n });\n }\n}\n\n/** Ask GitHub. Every failure mode is loud; none of them returns an empty list. */\nfunction fetchCustomers(org: string): Customer[] {\n requireGhAuth(org);\n const limit = listLimit();\n\n const repos = ghJson<Array<{ name?: unknown; description?: unknown }>>(\n [\n \"repo\",\n \"list\",\n org,\n \"--topic\",\n customersTopic(),\n \"--limit\",\n String(limit),\n \"--json\",\n \"name,description\"\n ],\n `the customer list for ${org}`\n );\n\n // The shape is validated, not assumed. A `gh` that exits 0 having printed\n // something which is not an array of named repos has told us nothing, and\n // nothing must not be allowed to read as an empty list.\n if (!Array.isArray(repos)) {\n throw new CliError(`gh returned something that is not a list of repos for ${org}`, {\n code: ExitCode.UNAVAILABLE,\n hint: `this is not \"${org} has no customers\"`\n });\n }\n for (const repo of repos) {\n if (typeof repo.name !== \"string\" || !repo.name) {\n throw new CliError(\"a repo came back with no name, so the listing is unusable\", {\n code: ExitCode.UNAVAILABLE\n });\n }\n }\n\n refuseIfAtLimit(repos.length, limit, `the customer listing for ${org}`);\n\n return repos\n .map((repo) => ({\n name: repo.name as string,\n // Tabs, CRs and newlines squeezed out so a description holds the line\n // format for any value GitHub will accept.\n description: String(repo.description ?? \"\").replace(/[\\t\\r\\n]+/g, \" \")\n }))\n .sort((a, b) => a.name.localeCompare(b.name));\n}\n\n/**\n * The customers, from cache when it is fresh.\n *\n * On a live failure with a cache in hand the cache is served STALE AND SAID\n * SO, because degrading to stale-but-correct is the point of having one.\n * Degrading to EMPTY is the failure it exists to prevent.\n */\nexport function listCustomers(opts: { refresh?: boolean; org?: string } = {}): Customer[] {\n const org = opts.org ?? customersOrg();\n const cached = readCache(org);\n\n if (!opts.refresh && cached && Date.now() - cached.fetchedAt < cacheTtlMs()) {\n return cached.customers;\n }\n\n try {\n const customers = fetchCustomers(org);\n writeCache(org, customers);\n return customers;\n } catch (cause) {\n if (cached?.customers.length) {\n const ageMinutes = Math.round((Date.now() - cached.fetchedAt) / 60_000);\n log.warn(`serving a STALE customer list (${ageMinutes}m old): ${(cause as Error).message}`);\n return cached.customers;\n }\n throw cause;\n }\n}\n\n/**\n * Resolve a name to a customer.\n *\n * The \"unknown customer\" message points at `--refresh` deliberately: a\n * customer a teammate registered minutes ago is invisible to every command\n * until the hour-long cache expires, and that is by far the likeliest reason a\n * real name does not resolve.\n */\nexport function resolveCustomer(name: string, opts: { refresh?: boolean } = {}): Customer {\n const customers = listCustomers(opts);\n const exact = customers.find((c) => c.name === name);\n if (exact) return exact;\n\n // A bare `pokehouse` should find `pokehouse-oxy`: the suffix is a naming\n // habit, not part of the identity, and making people type it would be\n // making them remember which of two habits a given repo used.\n const prefixed = customers.filter((c) => c.name.startsWith(`${name}-`));\n if (prefixed.length === 1) return prefixed[0] as Customer;\n if (prefixed.length > 1) {\n throw new CliError(`\"${name}\" matches ${prefixed.length} customers`, {\n code: ExitCode.USAGE,\n detail: prefixed.map((c) => ` ${c.name}`).join(\"\\n\"),\n hint: \"name one of them exactly\"\n });\n }\n\n throw new CliError(`unknown customer \"${name}\"`, {\n code: ExitCode.NOT_FOUND,\n hint: \"oxyc list --refresh — a customer registered in the last hour may not be cached yet\"\n });\n}\n\n/** `<org>/<name>` — the slug that identifies a customer everywhere. */\nexport function customerSlug(customer: Customer, org = customersOrg()): string {\n return `${org}/${customer.name}`;\n}\n\n/** The display name: the repo description, falling back to the repo name. */\nexport function displayName(customer: Customer): string {\n return customer.description.trim() || customer.name;\n}\n","/**\n * The one place a table, a paragraph or a status line becomes bytes.\n *\n * The two audiences want genuinely different things and neither is a\n * degraded version of the other: a human wants aligned columns and colour, an\n * agent wants a markdown table — which LLMs read far more reliably than either\n * ASCII art or JSON, and at a fraction of JSON's token cost, because a JSON\n * array repeats every field name on every row.\n *\n * So the *caller* never picks a format. It hands over rows and columns; this\n * decides, from `stdoutIsTty()`, and there is exactly one such decision in the\n * codebase.\n */\n\nimport { out, stdoutIsTty, terminalWidth } from \"./tty.js\";\n\nexport interface Column<T> {\n header: string;\n /** The cell, already stringified. Empty string for \"nothing to show\". */\n value: (row: T) => string;\n /** Right-align (counts, sizes). Ignored in markdown output. */\n align?: \"left\" | \"right\";\n}\n\n/**\n * Render `rows` as a table on stdout: aligned + coloured for a terminal,\n * GitHub-flavoured markdown for anything else.\n *\n * An empty `rows` prints nothing at all rather than a header with no body. A\n * bare header reads as a claim that the set was inspected and found empty,\n * which is only sometimes what happened — the caller says that in words, where\n * it can also say *why*.\n */\nexport function table<T>(rows: T[], columns: Column<T>[]): string {\n if (rows.length === 0) return \"\";\n // Each path escapes for itself: markdown needs the pipe escaped, a terminal\n // does not and is one column wider per pipe if it gets it.\n return stdoutIsTty()\n ? alignedTable(\n rows.map((r) => columns.map((c) => oneLine(c.value(r)))),\n columns\n )\n : markdownTable(\n rows.map((r) => columns.map((c) => forMarkdown(c.value(r)))),\n columns\n );\n}\n\n/**\n * Collapse anything that would break a ROW into a single line.\n *\n * A newline turns one table into a table and some loose prose; a tab is\n * squeezed for the same reason the bash tooling squeezes it out of a\n * description — the format has to hold for any value the upstream will accept,\n * not just the well-behaved ones. Both paths need this.\n */\nfunction oneLine(value: string): string {\n return value.replace(/[\\r\\n\\t]+/g, \" \");\n}\n\n/**\n * …and, for markdown only, escape the delimiter.\n *\n * SPLIT FROM `oneLine` because a pipe is a MARKDOWN concern. Running the\n * aligned path through the escape too meant a terminal header from\n * `SELECT 1 AS \"a|b\"` printed as `a\\|b` — two characters wider than the value\n * it measured, so every column after it sat one place out.\n */\nfunction forMarkdown(value: string): string {\n return oneLine(value).replace(/\\|/g, \"\\\\|\");\n}\n\nfunction alignedTable<T>(cells: string[][], columns: Column<T>[]): string {\n // Same reason as the markdown path: a header carrying a newline would break\n // the alignment for every row below it.\n const headers = columns.map((c) => oneLine(c.header));\n const widths = columns.map((_c, i) =>\n Math.max(visibleWidth(headers[i] ?? \"\"), ...cells.map((row) => visibleWidth(row[i] ?? \"\")))\n );\n const line = (values: string[], style: (s: string) => string) =>\n values\n .map((v, i) => {\n const w = widths[i] ?? 0;\n const padded = columns[i]?.align === \"right\" ? v.padStart(w) : v.padEnd(w);\n // The last column is never padded: trailing spaces are invisible and\n // they make a copied line carry junk.\n return style(i === values.length - 1 ? v : padded);\n })\n .join(\" \")\n .trimEnd();\n\n const header = line(headers, out.bold);\n const body = cells.map((row) => line(row, (s) => s));\n return [header, ...body].join(\"\\n\");\n}\n\nfunction markdownTable<T>(cells: string[][], columns: Column<T>[]): string {\n // HEADERS ARE SANITIZED TOO, and that is not symmetry for its own sake.\n // `--md` derives its column names from RESPONSE DATA — the keys of a JSON\n // object, or the header row of a SQL result — so a query as ordinary as\n // SELECT 1 AS \"a | b\"\n // puts a pipe in a header and splits every row of the rendered table onto\n // the wrong columns. A newline does worse. Cells have always been cleaned;\n // headers were not, because when this was written they were only ever\n // literals in our own source.\n const header = `| ${columns.map((c) => forMarkdown(c.header)).join(\" | \")} |`;\n const rule = `| ${columns.map(() => \"---\").join(\" | \")} |`;\n const body = cells.map((row) => `| ${row.join(\" | \")} |`);\n return [header, rule, ...body].join(\"\\n\");\n}\n\n/**\n * Display width, ignoring ANSI escapes.\n *\n * Values reaching a table are usually plain, but a caller is allowed to colour\n * one (a red `unhealthy`), and counting the escape bytes as width would push\n * every following column out by exactly the length of the escape sequence —\n * a misalignment that only appears once something is coloured.\n */\nfunction visibleWidth(s: string): number {\n // biome-ignore lint/suspicious/noControlCharactersInRegex: matching ANSI escapes is the point\n return s.replace(/\u001b\\[[0-9;]*m/g, \"\").length;\n}\n\n/** Greedy word wrap. Long prose in a fixed-width column reads better wrapped. */\nexport function wrap(text: string, width = terminalWidth() - 10): string[] {\n if (!text) return [];\n const lines: string[] = [];\n let current = \"\";\n for (const word of text.split(/\\s+/).filter(Boolean)) {\n if (current && current.length + 1 + word.length > width) {\n lines.push(current);\n current = \"\";\n }\n current = current ? `${current} ${word}` : word;\n }\n if (current) lines.push(current);\n return lines;\n}\n\n/**\n * A heading, as a section separator.\n *\n * Markdown when piped, so an agent reading a multi-section report can tell\n * where one section ends; bold-and-blank-line for a human, because `##` in a\n * terminal is noise.\n */\nexport function heading(text: string): string {\n return stdoutIsTty() ? `\\n${out.bold(text)}` : `\\n## ${text}\\n`;\n}\n","/**\n * `oxyc activity <customer>` — merged pull requests for a customer, from their\n * own repo and from ours.\n *\n * Reporting is the default; `--write` files the record into the customer's\n * dossier. Nothing is committed: the record rides your pull request like any\n * other change.\n */\n\nimport { mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nimport type { Context } from \"../context/resolve.js\";\nimport {\n collectActivity,\n monthsIn,\n renderJsonl,\n renderMonth,\n requireNonEmpty\n} from \"../customer/activity.js\";\nimport { dossierPath, isCloned } from \"../customer/dossier.js\";\nimport { customersOrg, displayName, resolveCustomer } from \"../github/customers.js\";\nimport * as log from \"../ui/log.js\";\nimport { table } from \"../ui/render.js\";\nimport { out } from \"../ui/tty.js\";\nimport { CliError, ExitCode } from \"../util/errors.js\";\n\nexport interface ActivityFlags {\n since?: string;\n repo: string[];\n write?: boolean;\n json?: boolean;\n}\n\nexport function runActivity(ctx: Context, name: string, flags: ActivityFlags): void {\n const customer = resolveCustomer(name, { refresh: ctx.flags.refresh });\n const org = customersOrg();\n const slug = `${org}/${customer.name}`;\n const display = displayName(customer);\n\n if (flags.since && !/^\\d{4}-\\d{2}-\\d{2}$/.test(flags.since)) {\n throw new CliError(`--since expects YYYY-MM-DD, got \"${flags.since}\"`, {\n code: ExitCode.USAGE\n });\n }\n\n const records = collectActivity({\n name: customer.name,\n ownRepo: slug,\n since: flags.since,\n extraRepos: flags.repo\n });\n\n if (flags.json) {\n process.stdout.write(`${JSON.stringify(records, null, 2)}\\n`);\n return;\n }\n\n requireNonEmpty(records, customer.name);\n\n if (!flags.write) {\n process.stdout.write(\n `${table(records, [\n { header: \"MONTH\", value: (r) => r.month },\n { header: \"REPO\", value: (r) => r.repo },\n { header: \"PR\", value: (r) => `#${r.number}`, align: \"right\" },\n { header: \"TITLE\", value: (r) => r.title },\n { header: \"VIA\", value: (r) => r.via }\n ])}\\n`\n );\n return;\n }\n\n if (!isCloned(slug)) {\n throw new CliError(`${slug} is not cloned here, so there is nowhere to write the record`, {\n code: ExitCode.NOT_FOUND,\n hint: `gh repo clone ${slug} ${dossierPath(slug)}`\n });\n }\n\n const dir = join(dossierPath(slug), \"activity\");\n mkdirSync(dir, { recursive: true });\n const written: string[] = [];\n // A month with no merged PRs never appears in `monthsIn`, so it produces no\n // file rather than an empty one — an empty file is a claim.\n for (const month of monthsIn(records)) {\n const md = join(dir, `${month}.md`);\n const jsonl = join(dir, `${month}.jsonl`);\n writeFileSync(md, `${renderMonth(month, display, records)}\\n`);\n writeFileSync(jsonl, `${renderJsonl(month, records)}\\n`);\n written.push(md, jsonl);\n }\n\n process.stdout.write(`${out.green(`wrote ${written.length} file(s) under ${dir}`)}\\n`);\n log.info(\"nothing was committed — the record rides your pull request like any other change\");\n}\n","/**\n * `-f` and `-F`, with `gh api`'s semantics.\n *\n * The letters and their meanings are gh's, not ours, because the whole point\n * of this command is that muscle memory transfers:\n *\n * -f, --raw-field key=value ALWAYS a string\n * -F, --field key=value typed — true/false/null/123 keep their JSON\n * type, `@file` reads a file, `@-` reads stdin,\n * and anything else stays a string\n *\n * The fallback-to-string in `-F` is what makes a bare UUID work: it is not\n * valid JSON, and erroring on it would make the typed flag unusable for the\n * single most common value in this API.\n */\n\nimport { readFileSync } from \"node:fs\";\n\nimport { usageError } from \"../util/errors.js\";\n\nexport type FieldValue = string | number | boolean | null | FieldValue[];\n\n/** Split `key=value`, naming the flag in the error so it says which one. */\nfunction splitField(flag: string, raw: string): [string, string] {\n const idx = raw.indexOf(\"=\");\n if (idx < 0) {\n throw usageError(`invalid ${flag} '${raw}', expected key=value`);\n }\n return [raw.slice(0, idx), raw.slice(idx + 1)];\n}\n\n/** Everything on stdin, as a string. Read at most once per process. */\nlet stdinCache: string | undefined;\nfunction readStdin(): string {\n if (stdinCache === undefined) {\n try {\n stdinCache = readFileSync(0, \"utf8\");\n } catch {\n stdinCache = \"\";\n }\n }\n return stdinCache;\n}\n\n/**\n * A `-F` value, typed.\n *\n * `@` prefixes are checked before JSON so a value that is *both* — `@1` — is\n * read as a filename, which is gh's behaviour and the less surprising of the\n * two: nobody writes `@1` meaning the number 1.\n */\nexport function parseTypedValue(raw: string): FieldValue {\n if (raw === \"@-\") return readStdin().trim();\n if (raw.startsWith(\"@\")) {\n const path = raw.slice(1);\n try {\n return readFileSync(path, \"utf8\").trim();\n } catch (cause) {\n throw usageError(`could not read ${path}: ${(cause as Error).message}`);\n }\n }\n if (raw === \"true\") return true;\n if (raw === \"false\") return false;\n if (raw === \"null\") return null;\n try {\n // JSON.parse handles numbers, arrays and objects. A bare word throws,\n // which is the fallback-to-string case below.\n const parsed: unknown = JSON.parse(raw);\n if (parsed === null || typeof parsed !== \"object\") return parsed as FieldValue;\n return parsed as FieldValue;\n } catch {\n return raw;\n }\n}\n\nexport interface ParsedFields {\n /** The assembled parameter object, ready to be a body or a query string. */\n params: Record<string, FieldValue>;\n /** Whether any field was given at all — distinct from \"an empty object\". */\n present: boolean;\n}\n\n/**\n * Assemble `-f` and `-F` into one object.\n *\n * Typed fields are applied second so a key given to both wins as the typed\n * value — the more specific instruction wins, and the alternative (first one\n * wins) would make `-f x=1 -F x=1` depend on argv order.\n *\n * A key ending in `[]` accumulates into an array across repeats, so\n * `-F 'ids[]=a' -F 'ids[]=b'` sends `{\"ids\":[\"a\",\"b\"]}`. Without it, sending a\n * two-element array means hand-writing JSON into a single flag, which is\n * exactly the escaping misery `-F` exists to remove.\n */\nexport function parseFields(rawFields: string[], typedFields: string[]): ParsedFields {\n const params: Record<string, FieldValue> = {};\n\n const assign = (key: string, value: FieldValue) => {\n if (key.endsWith(\"[]\")) {\n const name = key.slice(0, -2);\n const existing = params[name];\n params[name] = Array.isArray(existing) ? [...existing, value] : [value];\n return;\n }\n params[key] = value;\n };\n\n for (const raw of rawFields) {\n const [key, value] = splitField(\"--raw-field\", raw);\n assign(key, value);\n }\n for (const raw of typedFields) {\n const [key, value] = splitField(\"--field\", raw);\n assign(key, parseTypedValue(value));\n }\n\n return { params, present: rawFields.length > 0 || typedFields.length > 0 };\n}\n\n/**\n * Params as a query string, for a method that carries no body.\n *\n * `gh api` moves fields to the query on GET/HEAD/DELETE rather than refusing\n * them, and this API has plenty of GET endpoints with parameters\n * (`?page=`, `?limit=`, `?branch=`), so the alternative would be forcing\n * callers back to hand-built URLs for the commonest case.\n *\n * An array becomes repeated keys (`ids=a&ids=b`) — what axum's\n * `Query<Vec<_>>` extractors read — and `null` is dropped rather than sent as\n * the four letters \"null\", which no query parser reads as absence.\n */\nexport function paramsToQuery(params: Record<string, FieldValue>): string {\n const search = new URLSearchParams();\n for (const [key, value] of Object.entries(params)) {\n if (value === null || value === undefined) continue;\n if (Array.isArray(value)) {\n for (const item of value) {\n if (item !== null) search.append(key, String(item));\n }\n continue;\n }\n search.append(key, String(value));\n }\n return search.toString();\n}\n","/**\n * Turning what somebody typed into the path the server mounts, and filling in\n * the `{...}` placeholders from the resolved context.\n */\n\nimport { usageError } from \"../util/errors.js\";\n\n/**\n * Top-level mounts that are NOT under `/api`.\n *\n * Needed because the normaliser's job is \"prefix `/api/` unless it is already\n * a real path\", and without this list every one of these gets a second prefix.\n *\n * THIS FIXES A LIVE BUG in the Rust `oxy api`, which is worth stating because\n * the fix looks like gratuitous divergence otherwise. `normalize_path` there\n * tests only for an `api` first segment, so the API-key surface — documented\n * in its own `--help` as `oxy api /external/api/<workspace_id>/sql/query` —\n * normalises to `/api/external/api/<workspace_id>/sql/query` and 404s. The\n * documented example could never have worked.\n */\nconst TOP_LEVEL_MOUNTS = new Set([\n \"api\",\n \"external\",\n \"apidoc\",\n \"customer-apps\",\n \"healthz\",\n \"readyz\",\n \"livez\",\n \"metrics\"\n]);\n\n/**\n * Normalise a user-supplied path to something the server mounts.\n *\n * `user` → `/api/user`; `/user` → `/api/user`; `api/user` → `/api/user`;\n * `/external/api/x/sql/query` → itself. A leading slash is accepted rather\n * than required because both spellings are natural and neither is wrong.\n */\nexport function normalizePath(path: string): string {\n const trimmed = path.trim().replace(/^\\/+/, \"\");\n if (!trimmed) return \"/api\";\n const first = trimmed.split(\"/\")[0] ?? \"\";\n if (TOP_LEVEL_MOUNTS.has(first)) return `/${trimmed}`;\n return `/api/${trimmed}`;\n}\n\n/**\n * Whether a path sits on the API-key-only surface.\n *\n * Used to pick the credential: `/external/api/*` expects `X-API-Key`, every\n * other surface a bearer. Deciding from the path means a caller never has to\n * know which header a route wants — which is the entire reason this command\n * exists rather than a `curl` alias.\n */\nexport function isExternalSurface(path: string): boolean {\n return path.startsWith(\"/external/api/\");\n}\n\n/** The values a `{placeholder}` can be filled from. */\nexport interface PlaceholderValues {\n org?: string;\n workspace?: string;\n project?: string;\n customer?: string;\n me?: string;\n}\n\n/**\n * Substitute `{org}`, `{workspace}`, `{project}`, `{customer}` and `{me}`.\n *\n * `gh api` does this with `{owner}` and `{repo}` from the git remote, and it\n * is the single feature that makes the command usable from memory rather than\n * from a scratchpad of ids. Ours resolve from the customer context, which is\n * what the two merged tools share:\n *\n * oxyc api {workspace}/threads # inside a customer repo, no ids typed\n *\n * An UNRESOLVED placeholder is an error, never a literal. Sending\n * `/api/{workspace}/threads` to the server produces a 404 about a workspace\n * literally named `{workspace}`, and the caller has to work backwards from\n * that to \"the context did not resolve\" — so the failure is raised here,\n * where it can say which value was missing and how to supply it.\n */\nexport function substitutePlaceholders(path: string, values: PlaceholderValues): string {\n return path.replace(/\\{([a-z_]+)\\}/g, (match, name: string) => {\n if (!SUPPORTED.includes(name as keyof PlaceholderValues)) {\n // A DIFFERENT failure from \"did not resolve\", and worth its own message:\n // `could not resolve {nonsence}` reads as a supported placeholder that\n // happens to be unset, sending the caller off to look for the flag that\n // would set it. There is no such flag.\n throw usageError(\n `unknown placeholder ${match}`,\n `supported: ${SUPPORTED.map((n) => `{${n}}`).join(\" \")}`\n );\n }\n const value = values[name as keyof PlaceholderValues];\n if (value) return encodeURIComponent(value);\n throw usageError(`could not resolve ${match} in the path`, placeholderHint(name));\n });\n}\n\n/** The placeholder names this CLI fills in. */\nconst SUPPORTED: (keyof PlaceholderValues)[] = [\"org\", \"workspace\", \"project\", \"customer\", \"me\"];\n\n/** What to do about a supported placeholder that did not resolve. */\nfunction placeholderHint(name: string): string {\n switch (name) {\n case \"org\":\n return \"pass --org <slug>, or run from a customer repo (`oxyc <customer> --here`)\";\n case \"workspace\":\n return \"pass --workspace <id>, or run `oxyc api {org}/workspaces` to find one\";\n case \"project\":\n return \"pass --project <id>\";\n case \"customer\":\n return \"run inside a customer repo, or name one with --customer\";\n default:\n return \"run `oxyc login` first — {me} is your own account\";\n }\n}\n\n/** The placeholder names a path uses, for reporting before a request is made. */\nexport function placeholdersIn(path: string): string[] {\n return [...path.matchAll(/\\{([a-z_]+)\\}/g)].map((m) => m[1] as string);\n}\n","/**\n * One authenticated HTTP request to an Oxy deployment.\n *\n * This is the layer every other command goes through, so it is also the only\n * place that knows how a credential is attached and how a failure becomes an\n * exit code. A command that built its own `fetch` would be a second answer to\n * both questions, and the second answer is always the one that forgets the\n * `X-API-Key` surface.\n */\n\nimport { CliError, ExitCode, exitCodeForStatus } from \"../util/errors.js\";\nimport { cacheKey, readCache, writeCache } from \"./cache.js\";\nimport { isExternalSurface } from \"./paths.js\";\n\nexport interface RequestOptions {\n target: string;\n /** Already normalised and placeholder-substituted. */\n path: string;\n method: string;\n body?: string;\n headers?: Record<string, string>;\n bearer?: string;\n apiKey?: string;\n /** Milliseconds a cached response stays usable. 0 disables the cache. */\n cacheMs?: number;\n timeoutMs?: number;\n}\n\nexport interface ApiResponse {\n status: number;\n statusText: string;\n headers: Record<string, string>;\n body: string;\n url: string;\n /** True when this came from `--cache` rather than the network. */\n fromCache: boolean;\n}\n\n/** Requests wait two minutes, matching the Rust CLI's client timeout. */\nconst DEFAULT_TIMEOUT_MS = 120_000;\n\n/**\n * Build the absolute URL. The target keeps its path, if it has one, because\n * `--target https://host/oxy` is a supported shape for a deployment served\n * under a prefix — concatenating rather than using `new URL(path, target)`,\n * which would discard that prefix.\n */\nexport function buildUrl(target: string, path: string): string {\n return `${target.replace(/\\/+$/, \"\")}${path}`;\n}\n\n/**\n * Pick and attach the credential.\n *\n * The path decides, not the caller: `/external/api/*` is the API-key surface\n * and everything else is the bearer surface. An `Authorization` header the\n * caller passed by hand wins over both — that is the escape hatch for a\n * credential this tool does not model.\n */\nfunction authHeaders(opts: RequestOptions): Record<string, string> {\n const explicit = Object.keys(opts.headers ?? {}).map((h) => h.toLowerCase());\n const headers: Record<string, string> = {};\n if (isExternalSurface(opts.path)) {\n if (opts.apiKey && !explicit.includes(\"x-api-key\")) headers[\"X-API-Key\"] = opts.apiKey;\n // The bearer goes along too when there is one: some external routes accept\n // either, and sending both never makes a request that would have worked\n // fail — the server picks the one it recognises.\n if (opts.bearer && !explicit.includes(\"authorization\")) {\n headers.Authorization = `Bearer ${opts.bearer}`;\n }\n return headers;\n }\n if (opts.bearer && !explicit.includes(\"authorization\")) {\n headers.Authorization = `Bearer ${opts.bearer}`;\n }\n return headers;\n}\n\n/**\n * Make the request. Returns the response whatever its status — turning a 4xx\n * into an error is the *caller's* decision, because `--include` and\n * `--paginate` both need to see the failed response before deciding.\n */\nexport async function request(opts: RequestOptions): Promise<ApiResponse> {\n const url = buildUrl(opts.target, opts.path);\n const method = opts.method.toUpperCase();\n\n const key = cacheKey(method, url, opts.body, opts.bearer);\n if (opts.cacheMs && opts.cacheMs > 0) {\n const hit = readCache(key, opts.cacheMs);\n if (hit) {\n return {\n status: hit.status,\n statusText: \"OK (cached)\",\n headers: hit.headers,\n body: hit.body,\n url,\n fromCache: true\n };\n }\n }\n\n const headers: Record<string, string> = {\n Accept: \"application/json\",\n \"User-Agent\": \"oxyc\",\n ...authHeaders(opts),\n ...(opts.headers ?? {})\n };\n // Default to JSON when sending a body; an explicit `-H content-type:` above\n // has already overwritten this, since the caller's headers are spread last.\n if (\n opts.body !== undefined &&\n !Object.keys(headers).some((h) => h.toLowerCase() === \"content-type\")\n ) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n\n let response: Response;\n try {\n response = await fetch(url, {\n method,\n headers,\n body: opts.body,\n signal: AbortSignal.timeout(opts.timeoutMs ?? DEFAULT_TIMEOUT_MS)\n });\n } catch (cause) {\n const message = (cause as Error).message;\n // A timeout and a refused connection are both \"the deployment did not\n // answer\", which is retryable — distinct from a request the server\n // rejected, and the distinction is what an agent branches on.\n throw new CliError(`request to ${url} failed: ${message}`, {\n code: ExitCode.UNAVAILABLE,\n hint: message.includes(\"timed out\")\n ? \"the deployment may be starting up — retry, or raise --timeout\"\n : `check the target is reachable: ${opts.target}`\n });\n }\n\n const body = await response.text();\n const responseHeaders: Record<string, string> = {};\n response.headers.forEach((value, name) => {\n responseHeaders[name] = value;\n });\n\n if (opts.cacheMs && opts.cacheMs > 0) {\n writeCache(key, method, response.status, responseHeaders, body);\n }\n\n return {\n status: response.status,\n statusText: response.statusText,\n headers: responseHeaders,\n body,\n url,\n fromCache: false\n };\n}\n\n/**\n * Turn a non-2xx response into the error it deserves.\n *\n * The body goes into `detail` rather than the message because it is the part\n * that actually says what was wrong, and it is often several lines of JSON —\n * folded into a one-line message it would be unreadable, and truncated it\n * would lose the field name that identifies the problem.\n */\nexport function errorForResponse(response: ApiResponse): CliError {\n const code = exitCodeForStatus(response.status);\n const hint =\n code === ExitCode.AUTH\n ? \"your token may be expired or lack the role — try `oxyc login` again, or `oxyc assume <org> --reason …` for a tenant surface\"\n : code === ExitCode.NOT_FOUND\n ? \"check the path with `oxyc routes <filter>` — and note an admin 404 can be a scope boundary, not a missing row\"\n : undefined;\n return new CliError(`${response.status} ${response.statusText} — ${response.url}`, {\n code,\n hint,\n detail: response.body.trim() || undefined\n });\n}\n\n/** JSON-parse a response body, or `undefined` when it is not JSON. */\nexport function parseJson(body: string): unknown {\n try {\n return JSON.parse(body);\n } catch {\n return undefined;\n }\n}\n","/**\n * Turning a response body into what the reader actually wanted.\n *\n * The default is the body VERBATIM, exactly as `gh api` does it, and that is a\n * deliberate refusal to be clever: the moment stdout depends on whether a\n * terminal is attached, `oxyc api … | jq` and `oxyc api …` stop being the same\n * command, and every script written against one breaks under the other. What\n * TTY-ness may change is pretty-printing whitespace — never structure.\n *\n * `--md` is the opt-in that matters for the agent audience: an array of\n * objects as a markdown table is dramatically cheaper than the same data as\n * JSON, because JSON repeats every field name on every row, and LLMs read\n * markdown tables more reliably than either JSON or aligned ASCII.\n */\n\nimport { spawnSync } from \"node:child_process\";\nimport { type Column, table } from \"../ui/render.js\";\nimport { stdoutIsTty } from \"../ui/tty.js\";\nimport { CliError, ExitCode } from \"../util/errors.js\";\nimport { parseJson } from \"./request.js\";\n\nexport interface OutputOptions {\n /** A jq program to run over the body. */\n jq?: string;\n /** Render arrays of objects as a markdown table. */\n md?: boolean;\n /** Print nothing at all. */\n silent?: boolean;\n /** Pretty-print JSON even when piped. */\n pretty?: boolean;\n}\n\n/**\n * Run `--jq` by shelling out to jq.\n *\n * The alternatives were each worse. A WASM jq adds megabytes to a package\n * whose selling point is `npx` start-up; a hand-written JSONPath subset would\n * be a *different language* wearing jq's flag name, and the first `--jq` that\n * silently means something else is worse than not having the flag. jq is\n * already a stated prerequisite of the tooling this command absorbs, so the\n * dependency is not new — and when it is missing the error says so and names\n * the install line, rather than producing wrong output.\n */\nexport function runJq(input: string, program: string): string {\n const result = spawnSync(\"jq\", [\"-r\", program], {\n input,\n encoding: \"utf8\",\n maxBuffer: 256 * 1024 * 1024\n });\n\n if (result.error) {\n const isMissing = (result.error as NodeJS.ErrnoException).code === \"ENOENT\";\n throw new CliError(\n isMissing\n ? \"--jq needs the `jq` binary, which is not on PATH\"\n : `jq failed: ${result.error.message}`,\n {\n code: isMissing ? ExitCode.USAGE : ExitCode.FAILURE,\n hint: isMissing ? \"brew install jq (or apt-get install jq)\" : undefined\n }\n );\n }\n if (result.status !== 0) {\n throw new CliError(`jq exited ${result.status}`, {\n code: ExitCode.USAGE,\n detail: result.stderr?.trim() || undefined,\n hint: \"check the jq program — `oxyc api <path>` without --jq shows the shape\"\n });\n }\n return result.stdout;\n}\n\n/**\n * Render an array of objects as a markdown table.\n *\n * Columns are the union of every row's keys IN FIRST-SEEN ORDER, not sorted:\n * handlers put the identifying field first, and alphabetising would bury `id`\n * and `name` in the middle of a row nobody can then scan.\n *\n * A nested value becomes compact JSON in its cell rather than `[object Object]`\n * — ugly, but it is still the data, and a cell that silently says nothing is\n * how a caller concludes a field is empty when it is populated.\n */\nexport function toMarkdown(payload: unknown): string | undefined {\n const columnar = fromColumnarShapes(payload);\n if (columnar) return columnar;\n\n const rows = Array.isArray(payload) ? payload : findFirstArray(payload);\n if (!rows || rows.length === 0) return undefined;\n if (!rows.every((r) => typeof r === \"object\" && r !== null && !Array.isArray(r))) {\n return undefined;\n }\n\n const keys: string[] = [];\n for (const row of rows as Record<string, unknown>[]) {\n for (const key of Object.keys(row)) {\n if (!keys.includes(key)) keys.push(key);\n }\n }\n const columns: Column<Record<string, unknown>>[] = keys.map((key) => ({\n header: key,\n value: (row) => cell(row[key])\n }));\n return table(rows as Record<string, unknown>[], columns);\n}\n\n/**\n * The two columnar shapes this API answers queries with.\n *\n * Handled explicitly because they are the MOST COMMON data response here and\n * neither is an array of objects, so the generic path below rejects both and a\n * caller asking for a table of query results — the single likeliest use of\n * `--md` — got raw JSON instead.\n *\n * `[[\"id\",\"name\"],[\"1\",\"ada\"]]` header row first; what\n * `/sql/query` returns by default\n * `{columns:[...], rows:[[...]]}` what `/projects/*_/query` returns\n *\n * A single-row array-of-arrays is a header with no data, which renders as an\n * empty table rather than being mistaken for one data row.\n */\nfunction fromColumnarShapes(payload: unknown): string | undefined {\n if (Array.isArray(payload) && payload.length > 0 && payload.every(Array.isArray)) {\n const [header, ...body] = payload as unknown[][];\n return renderColumnar((header ?? []).map(String), body);\n }\n if (typeof payload === \"object\" && payload !== null) {\n const record = payload as Record<string, unknown>;\n // `rows` must be rows — ARRAYS. A payload carrying `columns` and `rows`\n // where the rows are objects is a different shape entirely, and indexing\n // objects positionally renders a table of empty cells. Falling through to\n // the generic array-of-objects path below gets it right instead of\n // confidently getting it wrong.\n if (\n Array.isArray(record.columns) &&\n Array.isArray(record.rows) &&\n record.rows.every((r) => Array.isArray(r))\n ) {\n return renderColumnar(record.columns.map(String), record.rows as unknown[][]);\n }\n }\n return undefined;\n}\n\nfunction renderColumnar(headers: string[], body: unknown[][]): string {\n // KEYED BY INDEX, not by header name. `SELECT a.id, b.id` gives two columns\n // called `id`, and building a row object off the names collapses them — both\n // columns then print the second one's value, silently and identically.\n const rows = body.map((row) => headers.map((_h, i) => row?.[i] ?? null));\n const rendered = table(\n rows,\n headers.map((h, i) => ({ header: h, value: (r: unknown[]) => cell(r[i]) }))\n );\n if (rendered) return rendered;\n\n // Zero rows. `table()` prints nothing for an empty set, because a bare\n // header there is a claim it cannot support — it does not know whether the\n // set was inspected. HERE it was: the query ran and came back with these\n // columns and no rows, so the header IS the answer, and it tells the caller\n // what they queried as well as that it was empty.\n //\n // Rendered through `table()` with a single placeholder row rather than by\n // hand-writing pipes: the by-hand version was markdown unconditionally, so\n // on a terminal the same query came back aligned when it had rows and\n // pipe-delimited when it did not.\n return (\n table(\n [headers.map(() => \"\")],\n headers.map((h, i) => ({\n header: h,\n value: (r: string[]) => r[i] ?? \"\"\n }))\n )\n .split(\"\\n\")\n // Drop the placeholder row, keeping whichever header form the stream got.\n .slice(0, stdoutIsTty() ? 1 : 2)\n .join(\"\\n\")\n );\n}\n\nfunction cell(value: unknown): string {\n if (value === null || value === undefined) return \"\";\n if (typeof value === \"object\") return JSON.stringify(value);\n return String(value);\n}\n\n/**\n * The rows of a list response: the first array-of-OBJECTS field.\n *\n * Not merely the first array. A response like `{columns: [\"a\"], rows: [{…}]}`\n * has two array fields and only the second is rows — taking the first found\n * `columns`, saw an array of strings, and gave up, so a payload the generic\n * path could have rendered came back as raw JSON instead.\n *\n * Falls back to the first array of any kind so a response whose rows are\n * genuinely scalars is still found and then rejected by the caller's own\n * shape check, rather than being invisible here.\n */\nfunction findFirstArray(payload: unknown): unknown[] | undefined {\n if (typeof payload !== \"object\" || payload === null) return undefined;\n const arrays = Object.values(payload as Record<string, unknown>).filter(Array.isArray);\n return (\n arrays.find(\n (value) =>\n value.length > 0 &&\n value.every((v) => typeof v === \"object\" && v !== null && !Array.isArray(v))\n ) ?? arrays[0]\n );\n}\n\n/**\n * The final bytes for a response body.\n *\n * Order matters: `--jq` runs on the raw body, so a program can see fields\n * `--md` would have flattened, and `--md` then runs on jq's output so\n * `--jq '.threads' --md` is a table of exactly the rows you selected.\n */\nexport function formatBody(body: string, opts: OutputOptions): string {\n if (opts.silent) return \"\";\n\n let current = body;\n if (opts.jq) current = runJq(current, opts.jq);\n\n if (opts.md) {\n const rendered = toMarkdown(parseJson(current));\n // Not table-shaped — a scalar, a nested object, a jq program that emitted\n // lines. Falling back to the value is right: `--md` asks for the most\n // readable form available, and refusing to print would lose the answer.\n if (rendered !== undefined) return rendered;\n }\n\n if (opts.pretty || (stdoutIsTty() && !opts.jq)) {\n const parsed = parseJson(current);\n if (parsed !== undefined) return JSON.stringify(parsed, null, 2);\n }\n return current;\n}\n","/**\n * `--paginate` — walk every page and hand back one document.\n *\n * `gh api --paginate` has an easy job: GitHub sends `Link: rel=\"next\"` on\n * every paginated endpoint, so the client follows a URL it was given. Oxy has\n * no such header and no single pagination shape — `thread.rs` answers with\n * `{pagination:{total_pages,has_next}}`, `workspaces/ops.rs` with a bare\n * `has_more`, and plenty of list endpoints with neither.\n *\n * So this is a HEURISTIC, and it says so in `--help` rather than pretending to\n * be a contract. It reads, in order: a `Link: rel=\"next\"` header (free\n * correctness if one ever appears), then `pagination.has_next`, then\n * `has_more`, then `page < pagination.total_pages`. Nothing recognised means\n * one page, which is the safe direction — a missed page is visible in the\n * result, an invented one is not.\n */\n\nimport * as log from \"../ui/log.js\";\nimport { CliError, ExitCode } from \"../util/errors.js\";\nimport {\n type ApiResponse,\n errorForResponse,\n parseJson,\n type RequestOptions,\n request\n} from \"./request.js\";\n\n/**\n * The ceiling on pages walked in one run.\n *\n * Not a tuning knob so much as a guard against a server whose \"has more\" never\n * goes false — a bug that without this turns one command into an infinite\n * request loop against production. Hitting it is REPORTED, never silent: a\n * truncated result that reads as complete is the failure this whole file is\n * shaped to avoid.\n */\nconst MAX_PAGES = 100;\n\nexport interface PaginateOptions extends RequestOptions {\n /** Force the field holding the rows, when the guess would be wrong. */\n paginateKey?: string;\n /** Emit an array of whole pages instead of merging them (`--slurp`). */\n slurp?: boolean;\n maxPages?: number;\n}\n\nexport interface PageShape {\n /** The field the rows live under, if this looks like a list response. */\n rowsKey?: string;\n rows: unknown[];\n hasMore: boolean;\n}\n\n/** A JSON object, narrowed enough to index. */\ntype JsonObject = Record<string, unknown>;\n\nfunction isObject(value: unknown): value is JsonObject {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/**\n * Read one page: where the rows are, and whether to ask for another.\n *\n * `paginateKey` wins outright. Otherwise the rows are the first array-valued\n * field — first rather than largest, because a response with two arrays\n * (`{threads:[…], tags:[…]}`) has one that is the page and one that is\n * metadata, and declaration order puts the page first in every handler here.\n */\nexport function readPage(payload: unknown, page: number, explicitKey?: string): PageShape {\n if (Array.isArray(payload)) {\n // A bare array carries NO \"is there more\" signal, so it is one page.\n //\n // The tempting reading — \"a full page means ask for another\" — is a bug,\n // not a heuristic: an endpoint that ignores `?page` returns the SAME array\n // every time, so that rule loops to the page cap and merges a hundred\n // copies of the same rows. A hundred duplicates presented as a result is\n // far worse than a missed page, which at least shows up as a short list.\n // This is the module's stated policy applied consistently: nothing\n // recognised means one page.\n return { rows: payload, hasMore: false };\n }\n if (!isObject(payload)) return { rows: [], hasMore: false };\n\n const rowsKey = explicitKey ?? Object.keys(payload).find((k) => Array.isArray(payload[k]));\n const rows = rowsKey && Array.isArray(payload[rowsKey]) ? (payload[rowsKey] as unknown[]) : [];\n\n const pagination = isObject(payload.pagination) ? payload.pagination : undefined;\n let hasMore = false;\n if (pagination && typeof pagination.has_next === \"boolean\") {\n hasMore = pagination.has_next;\n } else if (typeof payload.has_more === \"boolean\") {\n hasMore = payload.has_more;\n } else if (pagination && typeof pagination.total_pages === \"number\") {\n hasMore = page < pagination.total_pages;\n }\n\n return { rowsKey, rows, hasMore };\n}\n\n/** Follow `Link: rel=\"next\"` when the server bothers to send one. */\nexport function linkNext(headers: Record<string, string>): string | undefined {\n const link = headers.link ?? headers.Link;\n if (!link) return undefined;\n for (const part of link.split(\",\")) {\n const match = /<([^>]+)>\\s*;\\s*rel=\"?next\"?/.exec(part.trim());\n if (match) return match[1];\n }\n return undefined;\n}\n\n/** Replace or add `?page=` on a path. */\nexport function withPage(path: string, page: number): string {\n const [base, query = \"\"] = path.split(\"?\", 2);\n const params = new URLSearchParams(query);\n params.set(\"page\", String(page));\n return `${base}?${params.toString()}`;\n}\n\n/**\n * Walk every page and return one body.\n *\n * Merged (the default), the result is the LAST page's object with the rows\n * replaced by every row from every page — so `pagination.total` still reads\n * correctly and a `--jq '.threads[]'` written against a single page keeps\n * working unchanged. Slurped (`--slurp`), it is an array of whole pages,\n * which is what you want when the per-page metadata is the point.\n */\nexport async function paginate(opts: PaginateOptions): Promise<string> {\n const method = opts.method.toUpperCase();\n if (method !== \"GET\") {\n // gh refuses this too. A paginated POST would re-submit the body once per\n // page, which for anything non-idempotent is a very expensive surprise.\n throw new CliError(`--paginate cannot be used with ${method}`, {\n code: ExitCode.USAGE,\n hint: \"it would repeat the request body once per page\"\n });\n }\n\n const limit = opts.maxPages ?? MAX_PAGES;\n const pages: unknown[] = [];\n const merged: unknown[] = [];\n let rowsKey: string | undefined;\n let lastPayload: unknown;\n let path = opts.path;\n let page = 1;\n\n for (; page <= limit; page++) {\n const response: ApiResponse = await request({ ...opts, path });\n if (response.status < 200 || response.status >= 300) throw errorForResponse(response);\n\n const payload = parseJson(response.body);\n if (payload === undefined) {\n // Not JSON — there is nothing to merge, so one page is the answer and\n // the raw body is it.\n return response.body;\n }\n lastPayload = payload;\n pages.push(payload);\n\n const shape = readPage(payload, page, opts.paginateKey);\n rowsKey ??= shape.rowsKey;\n merged.push(...shape.rows);\n\n const next = linkNext(response.headers);\n if (next) {\n path = next.startsWith(\"http\") ? new URL(next).pathname + new URL(next).search : next;\n continue;\n }\n if (!shape.hasMore) break;\n path = withPage(opts.path, page + 1);\n }\n\n if (page > limit) {\n log.warn(\n `stopped after ${limit} pages — the result is TRUNCATED. Narrow the query, or raise --max-pages.`\n );\n }\n\n if (opts.slurp) return JSON.stringify(pages, null, 2);\n if (rowsKey && isObject(lastPayload)) {\n return JSON.stringify({ ...lastPayload, [rowsKey]: merged }, null, 2);\n }\n return JSON.stringify(merged, null, 2);\n}\n","/**\n * `oxyc api` — the `gh api` of this tool.\n *\n * Everything the flags do is `gh api`'s, down to the letters, because the\n * whole value proposition is that muscle memory and half-remembered snippets\n * transfer. Where we differ it is for a reason written down at the site:\n * the `{org}` placeholder family, `--md`, and the pagination heuristic.\n */\n\nimport { readFileSync } from \"node:fs\";\nimport { parseDuration } from \"../api/cache.js\";\nimport { paramsToQuery, parseFields } from \"../api/fields.js\";\nimport { formatBody } from \"../api/output.js\";\nimport { paginate } from \"../api/paginate.js\";\nimport { isExternalSurface, normalizePath, substitutePlaceholders } from \"../api/paths.js\";\nimport { errorForResponse, request } from \"../api/request.js\";\nimport type { Context } from \"../context/resolve.js\";\nimport * as log from \"../ui/log.js\";\nimport { CliError, ExitCode, usageError } from \"../util/errors.js\";\n\nexport interface ApiFlags {\n method?: string;\n rawField: string[];\n field: string[];\n header: string[];\n input?: string;\n jq?: string;\n md?: boolean;\n paginate?: boolean;\n paginateKey?: string;\n maxPages?: string;\n slurp?: boolean;\n cache?: string;\n include?: boolean;\n silent?: boolean;\n verbose?: boolean;\n timeout?: string;\n}\n\n/**\n * Read `--input`: `-` is stdin, `@file` or a bare path is a file.\n *\n * A bare path is accepted as well as `@path` because `--input` already means\n * \"from a file\" — requiring the `@` too is ceremony, and `gh` accepts the bare\n * form here as well.\n */\nfunction readInput(value: string): string {\n if (value === \"-\") return readFileSync(0, \"utf8\");\n const path = value.startsWith(\"@\") ? value.slice(1) : value;\n try {\n return readFileSync(path, \"utf8\");\n } catch (cause) {\n throw usageError(`could not read ${path}: ${(cause as Error).message}`);\n }\n}\n\n/** Parse `-H 'Name: value'` into a header map. */\nfunction parseHeaders(raw: string[]): Record<string, string> {\n const headers: Record<string, string> = {};\n for (const entry of raw) {\n const idx = entry.indexOf(\":\");\n if (idx < 0) throw usageError(`invalid --header '${entry}', expected 'Name: value'`);\n headers[entry.slice(0, idx).trim()] = entry.slice(idx + 1).trim();\n }\n return headers;\n}\n\n/**\n * `gh` makes `--template`, `--jq`, `--silent` and `--verbose` mutually\n * exclusive, and the reason is worth keeping: each one *replaces* the output,\n * so combining two means one silently wins. We have no `--template`, and\n * `--md` composes with `--jq` by design (jq selects, md renders), so the\n * exclusion is over the three that genuinely conflict.\n */\nfunction rejectConflictingOutput(flags: ApiFlags): void {\n const chosen = [\n flags.jq !== undefined && \"--jq\",\n flags.silent && \"--silent\",\n flags.verbose && \"--verbose\"\n ].filter(Boolean) as string[];\n if (chosen.length > 1) {\n throw usageError(`only one of ${chosen.join(\", \")} may be used`);\n }\n if (flags.slurp && !flags.paginate) {\n throw usageError(\"--slurp requires --paginate\", \"it wraps each page as an array element\");\n }\n}\n\nexport async function runApi(ctx: Context, rawPath: string, flags: ApiFlags): Promise<void> {\n rejectConflictingOutput(flags);\n\n const fields = parseFields(flags.rawField, flags.field);\n const body = flags.input !== undefined ? readInput(flags.input) : undefined;\n\n if (body !== undefined && fields.present) {\n throw usageError(\n \"--input cannot be combined with -f/-F\",\n \"either send a raw body or build one from fields, not both\"\n );\n }\n\n // Method defaults to GET, or POST when something is being sent. Same rule as\n // `gh api`, and the same rule the Rust `oxy api` used.\n const method = (\n flags.method ?? (body !== undefined || fields.present ? \"POST\" : \"GET\")\n ).toUpperCase();\n const carriesBody = ![\"GET\", \"HEAD\", \"DELETE\"].includes(method);\n\n let path = substitutePlaceholders(normalizePath(rawPath), ctx.placeholders());\n\n // Fields on a body-less method become query parameters rather than being\n // refused — this API has plenty of parameterised GETs, and the alternative\n // is forcing callers back to hand-built URLs for the commonest case.\n let requestBody: string | undefined = body;\n if (fields.present) {\n if (carriesBody) {\n requestBody = JSON.stringify(fields.params);\n } else {\n const query = paramsToQuery(fields.params);\n if (query) path += (path.includes(\"?\") ? \"&\" : \"?\") + query;\n }\n }\n\n const target = ctx.target();\n const external = isExternalSurface(path);\n // The API-key surface accepts a key OR a bearer, so a missing key is only\n // fatal when there is no bearer either. Demanding both would refuse a\n // request that would have worked.\n const apiKey = ctx.apiKey();\n const bearer = external && apiKey ? ctx.maybeBearer() : ctx.bearer();\n\n if (external && !apiKey && !bearer) {\n throw new CliError(`${path} is the API-key surface and no key is set`, {\n code: ExitCode.AUTH,\n hint: `set ${ctx.flags.apiKeyEnv ?? \"OXY_API_KEY\"}, or run \\`oxyc login\\` for a bearer`\n });\n }\n\n const common = {\n target,\n path,\n method,\n body: requestBody,\n headers: parseHeaders(flags.header),\n bearer,\n apiKey,\n cacheMs: flags.cache ? parseDuration(flags.cache) : 0,\n timeoutMs: flags.timeout ? parseDuration(flags.timeout) : undefined\n };\n\n if (flags.verbose) {\n log.info(`${method} ${target}${path}`);\n if (requestBody) log.info(requestBody);\n }\n\n if (flags.paginate) {\n const merged = await paginate({\n ...common,\n paginateKey: flags.paginateKey,\n slurp: flags.slurp,\n maxPages: flags.maxPages ? Number(flags.maxPages) : undefined\n });\n emit(formatBody(merged, { jq: flags.jq, md: flags.md, silent: flags.silent }));\n return;\n }\n\n const response = await request(common);\n\n if (flags.include || flags.verbose) {\n // Headers go to STDOUT, not stderr, because `-i` asks for them as part of\n // the response — `gh api -i | head` has to show them.\n process.stdout.write(`HTTP ${response.status} ${response.statusText}\\n`);\n for (const [name, value] of Object.entries(response.headers)) {\n process.stdout.write(`${name}: ${value}\\n`);\n }\n process.stdout.write(\"\\n\");\n }\n if (response.fromCache) log.info(\"(served from --cache)\");\n\n if (response.status < 200 || response.status >= 300) throw errorForResponse(response);\n\n noteNullBody(response.body, bearer);\n emit(formatBody(response.body, { jq: flags.jq, md: flags.md, silent: flags.silent }));\n}\n\n/**\n * A bare `null` with a 200 is ambiguous, and the ambiguity is expensive.\n *\n * An expired session on this API does not always answer 401 — `/api/user`\n * answers `200 null`, which an agent reads as \"there is no such user\" and goes\n * off to debug the wrong thing. Some endpoints do legitimately answer `null`\n * for a missing row, so this cannot be an error; it is a note on STDERR, which\n * leaves the piped body untouched and costs nothing when the null was real.\n */\nfunction noteNullBody(body: string, bearer: string | undefined): void {\n if (!bearer || body.trim() !== \"null\") return;\n log.warn(\n \"the response is `null` with a 200 — on this API that is also what an expired session looks like\"\n );\n log.hint(\"oxyc whoami — to tell the two apart\");\n}\n\n/** Write a body, with exactly one trailing newline and none for empty output. */\nfunction emit(text: string): void {\n if (!text) return;\n process.stdout.write(text.endsWith(\"\\n\") ? text : `${text}\\n`);\n}\n","/**\n * Turning `--env` / `--target` into a base URL, and mining the org slug a\n * pasted URL carries.\n *\n * A port of `crates/app/src/cli/commands/env_url.rs` and the target half of\n * `app_manifest.rs`. Kept faithful rather than improved: `oxy` and `oxyc` share\n * a credentials file keyed by HOST, so the two must agree about which host an\n * `--env` names or they will cache tokens under different keys and each report\n * the other's login as missing.\n *\n * The one thing worth restating, because it is not obvious from the signature:\n * both org host schemes canonicalise back to the *deployment's* product host.\n * `poke-house.oxygen-hq.com` and `acme.oxygen-hq.com` are the same target with\n * different org slugs, so you log in once per deployment and not once per\n * customer.\n */\n\nimport { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\n/** A resolved `--env`: where to send the request, and whose org it named. */\nexport interface ResolvedEnv {\n /** Base URL. No trailing slash, no path. */\n target: string;\n /** Org slug the host carried, when it carried one. Never invented. */\n orgSlug?: string;\n}\n\n/**\n * Org-subdomain zones and the product host that serves each.\n *\n * Mirrors the server's one-zone-per-deployment model (`OXY_ORG_SUBDOMAIN_ZONE`\n * in `oxy_app_core::org_host_dispatch`). The CLI cannot read that env var, so\n * the well-known deployments are listed; an unknown zone falls through to\n * \"the URL is its own target\", which is the honest answer for a self-hosted or\n * preview deployment rather than a guess.\n */\nconst ORG_ZONES: ReadonlyArray<readonly [zone: string, product: string]> = [\n [\"oxygen-hq.com\", \"https://app.oxygen-hq.com\"],\n [\"dev.oxy.tech\", \"https://aip.dev.oxy.tech\"],\n [\"staging.oxy.tech\", \"https://aip.staging.oxy.tech\"]\n];\n\n/** Host labels that are infrastructure — present, they imply no org. */\nconst RESERVED_LABELS = new Set([\n \"app\",\n \"aip\",\n \"www\",\n \"api\",\n \"admin\",\n \"static\",\n \"assets\",\n \"cdn\",\n \"docs\",\n \"customer-apps\",\n \"customerapps\"\n]);\n\n/**\n * Built-in target for a well-known env name.\n *\n * `local` is the Vite dev server on 5173, NOT oxy's own 3000 — and that is\n * load-bearing rather than a preference. `oxyc login` opens `<target>/cli-auth`,\n * a route that exists only in the live web app, while `oxy serve` serves a\n * pre-built embedded bundle that may predate it. Vite proxies `/api/*` through\n * to :3000, so requests work either way; login only works through 5173.\n */\nexport function defaultTarget(env: string): string | undefined {\n switch (env) {\n case \"local\":\n return \"http://localhost:5173\";\n case \"dev\":\n case \"development\":\n return \"https://aip.dev.oxy.tech\";\n case \"staging\":\n return \"https://aip.staging.oxy.tech\";\n case \"production\":\n case \"prod\":\n return \"https://app.oxygen-hq.com\";\n default:\n return undefined;\n }\n}\n\n/**\n * Should this `--env` value be read as a URL rather than an env name?\n *\n * Env names are bare identifiers; a `:`, `/` or `.` means somebody pasted an\n * address bar. Permissive about the scheme so a copied `app.oxygen-hq.com`\n * works without the `https://`.\n */\nexport function looksLikeUrl(value: string): boolean {\n const v = value.trim();\n if (!v) return false;\n return v.includes(\"://\") || v.includes(\".\") || v.includes(\"/\") || v.includes(\":\");\n}\n\n/**\n * Add a scheme so the value parses. Loopback gets `http` — nobody runs TLS on\n * a local `oxy serve` — everything else `https`.\n */\nfunction withScheme(value: string): string {\n if (value.includes(\"://\")) return value;\n // A bracketed IPv6 literal is taken through its closing `]`; splitting on\n // ':' first would chop `[::1]:3000` into `[`.\n const host = value.startsWith(\"[\")\n ? `${value.split(\"]\")[0]}]`\n : (value.split(/[/:]/)[0] ?? value);\n const loopback = [\"localhost\", \"127.0.0.1\", \"0.0.0.0\", \"[::1]\"].includes(host);\n return `${loopback ? \"http\" : \"https\"}://${value}`;\n}\n\n/**\n * `scheme://host[:port]`. Path, query and fragment are dropped because the URL\n * a user pastes is a *page* (`/orgs/…/threads/…`), not an API base. `--target`\n * is the escape hatch that stays verbatim, for a deployment under a path.\n */\nfunction baseUrl(url: URL): string {\n const host = url.hostname.replace(/\\.+$/, \"\").toLowerCase();\n return url.port ? `${url.protocol}//${host}:${url.port}` : `${url.protocol}//${host}`;\n}\n\n/** The single label of `host` inside `zone`. A multi-label prefix is refused. */\nfunction labelInZone(host: string, zone: string): string | undefined {\n const suffix = `.${zone}`;\n if (!host.endsWith(suffix)) return undefined;\n const label = host.slice(0, -suffix.length);\n if (!label || label.includes(\".\")) return undefined;\n return label;\n}\n\n/** Org slug carried by `<org>--<app>.customer-apps.<zone>`. */\nfunction customAppOrg(host: string, zone: string): string | undefined {\n const label = labelInZone(host, `customer-apps.${zone}`);\n if (!label) return undefined;\n const idx = label.indexOf(\"--\");\n if (idx <= 0) return undefined;\n const org = label.slice(0, idx);\n const app = label.slice(idx + 2);\n if (!org || !app) return undefined;\n return org;\n}\n\n/** Resolve a pasted URL to a target, plus the org slug its host named. */\nexport function parseEnvUrl(value: string): ResolvedEnv | undefined {\n let url: URL;\n try {\n url = new URL(withScheme(value.trim()));\n } catch {\n return undefined;\n }\n const host = url.hostname.replace(/\\.+$/, \"\").toLowerCase();\n\n for (const [zone, product] of ORG_ZONES) {\n // Custom-app subdomain first: its host also ends in the org zone, but its\n // label carries a `--` pair the org rule would mis-read as a slug.\n const appOrg = customAppOrg(host, zone);\n if (appOrg) return { target: product, orgSlug: appOrg };\n\n const label = labelInZone(host, zone);\n if (!label) continue;\n if (RESERVED_LABELS.has(label)) return { target: product };\n return { target: product, orgSlug: label };\n }\n\n return { target: baseUrl(url) };\n}\n\n/** The subset of `oxy-app.json` this CLI reads. Unknown fields are ignored. */\nexport interface OxyAppManifest {\n slug?: string;\n orgSlug?: string;\n name?: string;\n environments?: Record<string, { target?: string }>;\n}\n\n/** Load `<dir>/oxy-app.json`, or `undefined` if absent or unparsable. */\nexport function loadManifest(dir: string): OxyAppManifest | undefined {\n try {\n return JSON.parse(readFileSync(join(dir, \"oxy-app.json\"), \"utf8\")) as OxyAppManifest;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Resolve the deployment to talk to.\n *\n * Precedence, matching the Rust exactly:\n * `--target` → manifest `environments.<env>.target` → built-in default\n * → the `--env` value read as a URL\n *\n * The URL reading is last and purely additive: every named env keeps working\n * exactly as before, and a name always beats the URL interpretation. That\n * ordering is why `--env local` never tries to resolve `local` as a hostname.\n */\nexport function resolveEnv(\n env: string | undefined,\n targetFlag: string | undefined,\n manifest?: OxyAppManifest\n): ResolvedEnv | undefined {\n // `--target` is the explicit escape hatch and stays verbatim, including for\n // a deployment served under a path. Its org slug is still mined, so\n // `--target https://<org>.oxygen-hq.com` knows which org it points at.\n if (targetFlag?.trim()) {\n const verbatim = targetFlag.trim().replace(/\\/+$/, \"\");\n return { target: verbatim, orgSlug: parseEnvUrl(verbatim)?.orgSlug };\n }\n\n const name = env?.trim();\n if (!name) return undefined;\n\n const fromManifest = manifest?.environments?.[name]?.target?.trim();\n if (fromManifest) {\n return {\n target: fromManifest.replace(/\\/+$/, \"\"),\n orgSlug: parseEnvUrl(fromManifest)?.orgSlug\n };\n }\n\n const builtin = defaultTarget(name);\n if (builtin) return { target: builtin };\n\n if (looksLikeUrl(name)) return parseEnvUrl(name);\n return undefined;\n}\n","/**\n * `oxyc assume start | status | end` — acting as an organization.\n *\n * A thin client over `/api/assume`, ported from the Rust `oxy assume` so a\n * developer with only `oxyc` can do the staff loop without the other binary.\n * The sessions are Postgres rows and the Rust CLI is not privileged, so both\n * tools see the same live sessions — logging in with either and acting with\n * either is one state, not two.\n *\n * WHY THE EXIT IS NOT BEHIND `/admin`: `/api/assume` is mounted outside it\n * deliberately, because acting as an org CLOSES the admin surface. An `end`\n * that lived behind the door it locks would leave an operator stuck for the\n * full 60 minutes. `router/global.rs` states that where the mount is.\n */\n\nimport { parseJson, request } from \"../api/request.js\";\nimport type { Context } from \"../context/resolve.js\";\nimport { looksLikeUrl, parseEnvUrl } from \"../context/target.js\";\nimport * as log from \"../ui/log.js\";\nimport { table } from \"../ui/render.js\";\nimport { out } from \"../ui/tty.js\";\nimport { CliError, ExitCode, exitCodeForStatus } from \"../util/errors.js\";\n\n/** What `/api/assume` returns for one live session. */\ninterface SessionDto {\n id: string;\n org_id: string;\n org_name?: string | null;\n org_slug?: string | null;\n /**\n * Carried because the server sends it and a reader of this type should know\n * why it exists: a partner's surface is the partner console, not the org\n * home. Neither this CLI nor the Rust branches on it today — the line below\n * prints the org home either way — so the distinction is documented here\n * rather than asserted next to code that does not make it.\n */\n is_partner: boolean;\n actor_email: string;\n reason: string;\n started_at: string;\n expires_at: string;\n /**\n * THE SERVER'S COUNTDOWN, and the reason `minutesLeft` prefers it: it is\n * `expires_at - now` computed where `now` is the server's clock. Recomputing\n * locally misreports the one field an operator uses to decide whether to\n * start again, on any laptop whose clock has drifted.\n */\n expires_in_seconds?: number;\n}\n\nconst UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n/**\n * `--org` as an org id.\n *\n * THREE SPELLINGS, because all three are things an operator has to hand: the\n * UUID from a support ticket, the slug from a conversation, and the URL they\n * are already looking at. A URL is the one worth supporting explicitly —\n * `--env https://poke-house.oxygen-hq.com` already names the org, so requiring\n * `--org poke-house` beside it would be asking for what was just said.\n */\n/**\n * The org a verb is about: what was passed, else what the `--env` URL named.\n *\n * EXPORTED AND NAMED because both `start` and `end` need it and neither could\n * be tested on it: a loopback harness always passes `--target`, which\n * overrides `--env` and takes the org slug with it, so the hint is\n * unreachable end-to-end. Written once, it is one small thing to pin — and the\n * bug it exists to prevent was `end` not having it, which quietly ended every\n * live session when an operator named one org by URL.\n */\nexport function orgOrHint(ctx: Pick<Context, \"env\">, org: string | undefined): string {\n return (org ?? ctx.env().orgSlug ?? \"\").trim();\n}\n\nasync function resolveOrgId(ctx: Context, org: string | undefined): Promise<string> {\n const raw = orgOrHint(ctx, org);\n if (!raw) {\n throw new CliError(\"no organization given\", {\n code: ExitCode.USAGE,\n remedy:\n \"pass --org <slug|uuid|url>, or point --env at an org URL \" +\n \"(e.g. --env https://poke-house.oxygen-hq.com)\"\n });\n }\n if (UUID.test(raw)) return raw;\n\n const slug = looksLikeUrl(raw) ? parseEnvUrl(raw)?.orgSlug : raw;\n if (!slug) {\n throw new CliError(`could not read an org from '${raw}'`, {\n code: ExitCode.USAGE,\n detail: \"org URLs look like https://<org-slug>.oxygen-hq.com\",\n remedy: \"pass the slug or the UUID instead\"\n });\n }\n return orgIdForSlug(ctx, slug);\n}\n\n/** Rows from an endpoint, or undefined when it is not reachable for this token. */\nasync function rows(ctx: Context, path: string): Promise<unknown[] | undefined> {\n const response = await request({\n target: ctx.target(),\n path,\n method: \"GET\",\n bearer: ctx.bearer()\n });\n if (response.status < 200 || response.status >= 300) return undefined;\n const body = parseJson(response.body);\n if (Array.isArray(body)) return body;\n // `/api/admin/orgs-meta` paginates; the rows are under a key.\n for (const key of [\"items\", \"orgs\", \"data\", \"results\"]) {\n const nested = (body as Record<string, unknown> | undefined)?.[key];\n if (Array.isArray(nested)) return nested;\n }\n return undefined;\n}\n\n/** `id` on `/orgs` and `/admin/orgs-meta`; `org_id` on a partner's client list. */\nfunction idForSlug(list: unknown[], slug: string): string | undefined {\n for (const row of list) {\n const r = row as Record<string, unknown>;\n if (r.slug !== slug) continue;\n const id = r.id ?? r.org_id;\n if (typeof id === \"string\") return id;\n }\n return undefined;\n}\n\n/**\n * THREE ENDPOINTS, IN ORDER OF REACH, matching the Rust.\n *\n * `/api/orgs` is what a member sees, `/admin/orgs-meta` what staff see, and\n * the partner client list what a partner sees. Trying them in that order means\n * the common case costs one call and the rarest costs three — and a partner,\n * who can reach only the third, still gets an answer rather than a 403 from\n * the first.\n */\nasync function orgIdForSlug(ctx: Context, slug: string): Promise<string> {\n const direct = await rows(ctx, \"/api/orgs\");\n if (direct) {\n const id = idForSlug(direct, slug);\n if (id) return id;\n }\n const admin = await rows(\n ctx,\n `/api/admin/orgs-meta?search=${encodeURIComponent(slug)}&page_size=200`\n );\n if (admin) {\n const id = idForSlug(admin, slug);\n if (id) return id;\n }\n const partner = await partnerClientId(ctx, slug);\n if (partner) return partner;\n throw new CliError(`no organization with slug '${slug}' is visible to you on ${ctx.target()}`, {\n code: ExitCode.NOT_FOUND,\n remedy: \"check the slug, or pass the org UUID directly with --org\"\n });\n}\n\n/**\n * A partner's assigned clients, across every partner they operate.\n *\n * TWO HOPS, because there is no one-shot route: `/api/partners` lists the\n * partners you hold a role at, and each one's clients are under\n * `/api/partners/{id}/orgs`. The first version of this called\n * `/api/partner/clients`, which is not a route in this repo at all — so the\n * one population this tier exists for got \"no organization with slug 'x' is\n * visible to you\" about an org that is.\n *\n * One unreadable partner does not abort the search: the next may hold the org.\n */\nasync function partnerClientId(ctx: Context, slug: string): Promise<string | undefined> {\n const partners = await rows(ctx, \"/api/partners\");\n if (!partners) return undefined;\n for (const p of partners) {\n const partnerId = (p as Record<string, unknown>).partner_id;\n if (typeof partnerId !== \"string\") continue;\n const clients = await rows(ctx, `/api/partners/${encodeURIComponent(partnerId)}/orgs`);\n if (!clients) continue;\n const id = idForSlug(clients, slug);\n if (id) return id;\n }\n return undefined;\n}\n\n/** `Acme (acme)` — or just whichever half the server gave us. */\nfunction describe(s: SessionDto): string {\n const name = s.org_name?.trim();\n const slug = s.org_slug?.trim();\n if (name && slug) return `${name} (${slug})`;\n return name || slug || s.org_id;\n}\n\nfunction minutesLeft(s: SessionDto): string {\n const seconds =\n typeof s.expires_in_seconds === \"number\"\n ? s.expires_in_seconds\n : (Date.parse(s.expires_at) - Date.now()) / 1000;\n if (Number.isNaN(seconds)) return \"?\";\n if (seconds <= 0) return \"expired\";\n return `${Math.floor(seconds / 60)}m`;\n}\n\n/**\n * The rules, printed after starting — because they are the part people are\n * surprised by, and a session you did not know was time-boxed is a session you\n * discover has ended mid-investigation.\n */\nfunction printSessionRules(target: string): void {\n log.info(\"60 minutes, not renewable — re-running returns the same session.\");\n // The one people are most surprised by, and the reason `assume.rs` lists\n // three properties rather than two: the session hangs off your ACCOUNT.\n log.info(\"it is your account that acts, not this terminal — your browser is in there too.\");\n log.info(`acting closes /admin; end it with \\`oxyc assume end\\` against ${target}.`);\n}\n\nexport async function runAssumeStart(\n ctx: Context,\n org: string | undefined,\n reason: string\n): Promise<void> {\n const trimmed = reason.trim();\n if (!trimmed) {\n throw new CliError(\"--reason must not be empty\", {\n code: ExitCode.USAGE,\n detail: \"it is recorded in the impersonation log, and an unexplained one is a red flag\"\n });\n }\n const orgId = await resolveOrgId(ctx, org);\n const target = ctx.target();\n\n const response = await request({\n target,\n path: \"/api/assume\",\n method: \"POST\",\n bearer: ctx.bearer(),\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ org_id: orgId, reason: trimmed })\n });\n\n if (response.status < 200 || response.status >= 300) {\n throw assumeError(response.status, orgId);\n }\n const session = parseJson(response.body) as SessionDto;\n process.stdout.write(`${out.green(`Now acting as ${describe(session)} on ${target}.`)}\\n`);\n if (session.org_slug) {\n process.stdout.write(`${out.dim(`Surface: ${target}/${session.org_slug}`)}\\n`);\n }\n printSessionRules(target);\n}\n\n/**\n * Map the server's status onto the reason it refused, so an operator is not\n * left guessing at a bare 403 — the same mapping the Rust makes.\n */\nfunction assumeError(status: number, orgId: string): CliError {\n const detail =\n status === 403\n ? \"you are not allowed to act as this org (Oxy staff may act as any org; a partner only as an assigned client, and only with `develop_apps`)\"\n : status === 404\n ? \"no organization with that id exists on this deployment\"\n : status === 400\n ? \"the request was rejected — a non-empty --reason is required\"\n : status === 401\n ? \"not authenticated for this target\"\n : \"the server refused the request\";\n return new CliError(`could not start an assume-role session for ${orgId} (${status})`, {\n code: exitCodeForStatus(status),\n detail,\n remedy: status === 401 ? \"oxyc login --env <env>\" : undefined\n });\n}\n\nexport async function runAssumeStatus(ctx: Context, json: boolean): Promise<void> {\n const target = ctx.target();\n const response = await request({\n target,\n path: \"/api/assume/current\",\n method: \"GET\",\n bearer: ctx.bearer()\n });\n if (response.status < 200 || response.status >= 300) {\n throw new CliError(`could not read assume sessions from ${target} (${response.status})`, {\n code: exitCodeForStatus(response.status),\n remedy: response.status === 401 ? \"oxyc login --env <env>\" : undefined\n });\n }\n const sessions = (parseJson(response.body) ?? []) as SessionDto[];\n\n if (json) {\n process.stdout.write(`${JSON.stringify(sessions, null, 2)}\\n`);\n return;\n }\n if (sessions.length === 0) {\n // NOT an error: \"you are not acting as anyone\" is a legitimate answer, and\n // the commonest reason a staff request 403s is that this is the state.\n log.info(`no live assume-role session on ${target}`);\n return;\n }\n process.stdout.write(\n `${table(sessions, [\n { header: \"ORG\", value: (s) => describe(s) },\n { header: \"LEFT\", value: (s) => minutesLeft(s) },\n { header: \"REASON\", value: (s) => s.reason }\n ])}\\n`\n );\n printSessionRules(target);\n}\n\nexport async function runAssumeEnd(\n ctx: Context,\n org: string | undefined,\n all: boolean\n): Promise<void> {\n const target = ctx.target();\n // AN EMPTY `--org` IS NOT AN ABSENT ONE. `oxyc assume end --org \"$ORG\"` with\n // `$ORG` unset is the ordinary way this happens, and reading it as \"no org\n // named\" sent an unscoped DELETE — every live session, across every org, on\n // a verb that cannot be undone. It also swallowed the `--env` hint, so a URL\n // naming one org ended all of them. The Rust refuses: `end` matches\n // `Some(_)` whatever it contains, and `resolve_org`'s\n // `.filter(|s| !s.is_empty())` answers \"no organization given\".\n //\n // Checked HERE rather than in `orgOrHint`, because \"\" is harmless for\n // `start` — `resolveOrgId` already refuses it — and the consequence only\n // lands on the destructive verb.\n if (org !== undefined && org.trim() === \"\") {\n throw new CliError(\"--org was given but is empty\", {\n code: ExitCode.USAGE,\n detail:\n \"an unset shell variable reads this way, and ending every session is not the safe guess\",\n remedy: \"name an org, or pass --all to end every session deliberately\"\n });\n }\n\n // THE `--env` URL NAMES AN ORG, and `end` has to hear it — `start` does\n // (`resolveOrgId` falls back to the same hint), so ignoring it here made one\n // URL mean an org for one verb and nothing for the other. `--all` is what\n // suppresses the hint — the flag exists to let you say \"everything\"\n // explicitly, not to unlock it.\n const hinted = orgOrHint(ctx, org);\n const orgId = all || !hinted ? undefined : await resolveOrgId(ctx, hinted);\n const path = orgId ? `/api/assume?org_id=${encodeURIComponent(orgId)}` : \"/api/assume\";\n\n const response = await request({ target, path, method: \"DELETE\", bearer: ctx.bearer() });\n if (response.status < 200 || response.status >= 300) {\n throw new CliError(`could not end the assume-role session (${response.status})`, {\n code: exitCodeForStatus(response.status),\n remedy: response.status === 401 ? \"oxyc login --env <env>\" : undefined\n });\n }\n process.stdout.write(\n `${out.green(orgId ? `Stopped acting as ${orgId} on ${target}.` : `Stopped acting on ${target}.`)}\\n`\n );\n}\n","/**\n * The token cache — the SAME file the Rust `oxy` binary reads and writes.\n *\n * Interop is the whole point: `oxy login` and `oxyc login` must be\n * interchangeable, so one tool logging in authenticates the other. That makes\n * the on-disk shape a contract with a program written in another language, and\n * every constant below is transcribed from `crates/app/src/cli/commands/login.rs`\n * rather than chosen here.\n *\n * THE PATH IS NOT `~/.config` ON macOS, whatever the Rust doc comment says.\n * `login.rs` builds it from `dirs::config_dir()`, and that crate returns\n * `$HOME/Library/Application Support` on macOS — verified against a live\n * credentials file. A `~/.config/oxy` implementation would read an empty store\n * on every Mac in the company and report every developer as logged out while\n * the Rust binary saw them logged in. `configDir()` reproduces the crate's\n * platform rules, and `credentials.test.ts` pins them.\n */\n\nimport { chmodSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { CliError, ExitCode } from \"../util/errors.js\";\n\n/** One host's cached credential. Field names are the Rust struct's, verbatim. */\nexport interface HostCredential {\n token: string;\n email: string;\n is_app_admin: boolean;\n}\n\n/** The file: a flat map of host key to credential. No envelope, no version. */\nexport type CredentialStore = Record<string, HostCredential>;\n\n/**\n * `dirs::config_dir()`, reimplemented.\n *\n * Deliberately not `env-paths` or any other convenience package: those pick\n * their own conventions (`~/Library/Preferences`, an app suffix), and being\n * *conventional* is worth nothing here — being byte-identical to what the Rust\n * crate returns is worth everything.\n */\nexport function configDir(): string {\n if (process.platform === \"darwin\") {\n return join(homedir(), \"Library\", \"Application Support\");\n }\n if (process.platform === \"win32\") {\n const appData = process.env.APPDATA;\n if (appData) return appData;\n return join(homedir(), \"AppData\", \"Roaming\");\n }\n const xdg = process.env.XDG_CONFIG_HOME;\n if (xdg?.startsWith(\"/\")) return xdg;\n return join(homedir(), \".config\");\n}\n\n/** The credentials file. `OXY_CREDENTIALS_PATH` overrides it, for tests. */\nexport function credentialsPath(): string {\n return process.env.OXY_CREDENTIALS_PATH ?? join(configDir(), \"oxy\", \"credentials.json\");\n}\n\n/**\n * The cache key for a target: `host` or `host:port`.\n *\n * Transcribed from `login.rs::host_key`. The port is part of the key because\n * a laptop routinely holds a `localhost:5173` token (the Vite dev server) and\n * a `localhost:3000` one (oxy itself) that are not interchangeable. An\n * unparseable target falls back to itself with a trailing slash trimmed —\n * same as the Rust, so a malformed value at least collides consistently.\n */\nexport function hostKey(target: string): string {\n try {\n const url = new URL(target);\n return url.port ? `${url.hostname}:${url.port}` : url.hostname;\n } catch {\n return target.replace(/\\/+$/, \"\");\n }\n}\n\n/**\n * The whole store, or an empty one.\n *\n * Unreadable and unparseable both degrade to empty rather than throwing: a\n * missing file is the ordinary state on a fresh machine, and the caller's next\n * move — say \"not authenticated, run oxyc login\" — is the right answer to a\n * corrupt file too. What is NOT acceptable is silently *writing over* it; see\n * `writeStore`.\n */\nexport function readStore(): CredentialStore {\n try {\n const raw = readFileSync(credentialsPath(), \"utf8\");\n const parsed: unknown = JSON.parse(raw);\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) return {};\n return parsed as CredentialStore;\n } catch {\n return {};\n }\n}\n\n/**\n * Write the store back, atomically, owner-only.\n *\n * tmp-then-rename because the file holds live bearer tokens for every host you\n * have ever logged into: a partial write during `oxyc login --env dev` would\n * take production's token with it. `0600` matches what `login.rs` sets, and\n * for the same reason — a world-readable token file on a shared machine is a\n * credential leak with no symptom.\n */\nexport function writeStore(store: CredentialStore): void {\n const path = credentialsPath();\n const dir = dirname(path);\n mkdirSync(dir, { recursive: true, mode: 0o700 });\n // THE TEMP FILE IS A SIBLING OF THE TARGET, not something in `os.tmpdir()`.\n // `rename(2)` cannot cross a filesystem boundary, and `/tmp` is a separate\n // mount on plenty of machines (a tmpfs on most Linux distributions, a\n // separate volume in many container images) — from there this throws a raw\n // `EXDEV` and `oxyc login` dies on a Node stack trace with the token already\n // captured. A sibling is on the same filesystem by construction.\n //\n // The unit test cannot see this: it points OXY_CREDENTIALS_PATH inside\n // tmpdir(), so both paths were on the same mount there either way.\n const tmp = join(dir, `.credentials.${process.pid}.${Date.now()}.tmp`);\n try {\n writeFileSync(tmp, `${JSON.stringify(store, null, 2)}\\n`, { mode: 0o600 });\n renameSync(tmp, path);\n } catch (cause) {\n try {\n rmSync(tmp, { force: true });\n } catch {\n // Nothing more to do; the throw below is the report.\n }\n throw new CliError(`could not write ${path}`, {\n code: ExitCode.FAILURE,\n detail: (cause as Error).message,\n hint: \"check the directory is writable, or set OXY_CREDENTIALS_PATH\"\n });\n }\n try {\n chmodSync(path, 0o600);\n } catch {\n // Best-effort: a filesystem without POSIX modes (a Windows share) still\n // gets the file. Failing the login over the mode would be worse.\n }\n}\n\n/** The cached token for `target`, if there is a non-empty one. */\nexport function loadToken(target: string): string | undefined {\n const entry = readStore()[hostKey(target)];\n const token = entry?.token?.trim();\n return token ? token : undefined;\n}\n\n/** The whole cached credential for `target` — token plus who it belongs to. */\nexport function loadCredential(target: string): HostCredential | undefined {\n return readStore()[hostKey(target)];\n}\n\n/** Cache `credential` under `target`, leaving every other host untouched. */\nexport function saveCredential(target: string, credential: HostCredential): void {\n const store = readStore();\n store[hostKey(target)] = credential;\n writeStore(store);\n}\n\n/** Drop `target`'s credential. Returns whether there was one to drop. */\nexport function clearCredential(target: string): boolean {\n const store = readStore();\n const key = hostKey(target);\n if (!(key in store)) return false;\n delete store[key];\n writeStore(store);\n return true;\n}\n\n/**\n * The bearer for `target`, by the same precedence the Rust CLI uses:\n * the env var first (the CI path), then the login cache.\n *\n * Returns `undefined` rather than throwing so the caller can decide whether\n * missing auth is fatal — `oxyc routes` against a cached catalog is not.\n */\nexport function resolveBearer(target: string, tokenEnv = \"OXY_TOKEN\"): string | undefined {\n const fromEnv = process.env[tokenEnv]?.trim();\n if (fromEnv) return fromEnv;\n return loadToken(target);\n}\n","/**\n * The browser loopback login — the same dance `oxy login` does, wire for wire.\n *\n * Bind an ephemeral `127.0.0.1` port, send the browser to\n * `<target>/cli-auth?port&state`, and catch the token the web app hands back to\n * `/callback`. The `/cli-auth` page reads the token from the already-logged-in\n * session, so there is no new minting endpoint and no password anywhere.\n *\n * Every constant here — the callback path, the two query parameter names, the\n * `state` check, the five-minute deadline — is transcribed from\n * `crates/app/src/cli/commands/login.rs`. It is a protocol shared with a page\n * we do not change in this repo, so drifting from it is a silent\n * \"login hangs forever\", not a compile error.\n */\n\nimport { spawn } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport { createServer } from \"node:http\";\nimport type { AddressInfo } from \"node:net\";\nimport * as log from \"../ui/log.js\";\nimport { err } from \"../ui/tty.js\";\nimport { CliError, ExitCode } from \"../util/errors.js\";\nimport { type HostCredential, saveCredential } from \"./credentials.js\";\n\n/** What `/api/user` gives back. Only the two fields the login flow reports. */\ninterface UserResponse {\n email?: string;\n is_app_admin?: boolean;\n}\n\n/** Matches the Rust's `SUCCESS_HTML` — the tab the user is left looking at. */\nconst SUCCESS_HTML =\n \"<!doctype html><meta charset=utf-8><title>oxy login</title>\" +\n '<body style=\"font-family:system-ui;padding:3rem;text-align:center\">' +\n \"<h2>Logged in to oxy ✓</h2><p>You can close this tab and return to your terminal.</p>\";\n\n/** The Rust waits 5 minutes. Long enough for an SSO detour with an MFA prompt. */\nconst LOGIN_TIMEOUT_MS = 300_000;\n\n/**\n * Run the loopback flow against one target and cache the result.\n *\n * Returns the token as well as storing it, so a caller chaining straight into\n * an assume-role session does not have to read the file it just wrote.\n */\nexport async function login(target: string): Promise<{ token: string; user: HostCredential }> {\n const state = randomUUID();\n const { port, waitForToken, close } = await startLoopback(state);\n\n try {\n const authUrl = `${target.replace(/\\/+$/, \"\")}/cli-auth?port=${port}&state=${encodeURIComponent(state)}`;\n log.info(`Opening ${authUrl} in your browser to log in…`);\n log.info(\"If it doesn't open automatically, paste that URL into your browser.\");\n openBrowser(authUrl);\n\n const token = await waitForToken;\n const user = await fetchUser(target, token);\n\n const credential: HostCredential = {\n token,\n email: user.email ?? \"\",\n is_app_admin: Boolean(user.is_app_admin)\n };\n saveCredential(target, credential);\n return { token, user: credential };\n } finally {\n close();\n }\n}\n\n/**\n * The loopback listener.\n *\n * It keeps accepting until it sees a callback whose `state` matches, rather\n * than resolving on the first request: a browser will cheerfully send a\n * `/favicon.ico` alongside the redirect, and treating that as the callback\n * would fail a login that was actually about to succeed.\n */\nasync function startLoopback(expectedState: string): Promise<{\n port: number;\n waitForToken: Promise<string>;\n close: () => void;\n}> {\n let resolveToken!: (token: string) => void;\n let rejectToken!: (reason: Error) => void;\n const waitForToken = new Promise<string>((resolve, reject) => {\n resolveToken = resolve;\n rejectToken = reject;\n });\n\n const server = createServer((req, res) => {\n // `req.url` is a path+query, so it needs a base to parse. The base is\n // discarded — only the path and the query matter.\n const parsed = new URL(req.url ?? \"/\", \"http://localhost\");\n if (parsed.pathname !== \"/callback\") {\n plain(res, 404, \"Not found\");\n return;\n }\n if (parsed.searchParams.get(\"state\") !== expectedState) {\n // A mismatch means this callback belongs to some other login attempt —\n // or to something that guessed the port. Refuse and keep listening.\n plain(res, 400, \"State mismatch — please retry `oxyc login`.\");\n return;\n }\n const token = parsed.searchParams.get(\"token\");\n if (!token) {\n plain(res, 400, \"No token in callback.\");\n return;\n }\n res.writeHead(200, {\n \"Content-Type\": \"text/html; charset=utf-8\",\n Connection: \"close\"\n });\n res.end(SUCCESS_HTML);\n resolveToken(token);\n });\n\n const timer = setTimeout(() => {\n rejectToken(\n new CliError(\"timed out waiting for the browser to complete login (5 min)\", {\n code: ExitCode.UNAVAILABLE,\n hint: \"oxyc login --env <env> — and complete the browser flow\"\n })\n );\n }, LOGIN_TIMEOUT_MS);\n // Do not hold the process open on the timer alone; the promise decides.\n timer.unref?.();\n\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject);\n server.listen(0, \"127.0.0.1\", resolve);\n });\n\n const address = server.address() as AddressInfo | null;\n if (!address) {\n server.close();\n throw new CliError(\"could not bind loopback port\", { code: ExitCode.UNAVAILABLE });\n }\n\n return {\n port: address.port,\n waitForToken,\n close: () => {\n clearTimeout(timer);\n server.close();\n }\n };\n}\n\nfunction plain(res: import(\"node:http\").ServerResponse, status: number, body: string): void {\n res.writeHead(status, {\n \"Content-Type\": \"text/plain; charset=utf-8\",\n Connection: \"close\"\n });\n res.end(body);\n}\n\n/**\n * Confirm the token and find out who it belongs to.\n *\n * Not merely informational: it is the difference between \"we captured a\n * string\" and \"the server accepts it\". A token cached without this check\n * fails later, at some unrelated command, with a 401 nobody connects back to\n * the login.\n */\nasync function fetchUser(target: string, token: string): Promise<UserResponse> {\n const url = `${target.replace(/\\/+$/, \"\")}/api/user`;\n let response: Response;\n try {\n response = await fetch(url, {\n headers: { Authorization: `Bearer ${token}` },\n signal: AbortSignal.timeout(30_000)\n });\n } catch (cause) {\n throw new CliError(`GET ${url} failed: ${(cause as Error).message}`, {\n code: ExitCode.UNAVAILABLE\n });\n }\n if (!response.ok) {\n throw new CliError(`login token rejected by ${url} (${response.status})`, {\n code: ExitCode.AUTH\n });\n }\n const body = (await response.json()) as UserResponse | null;\n if (!body) {\n throw new CliError(\"login token did not resolve to a user (got null)\", {\n code: ExitCode.AUTH\n });\n }\n return body;\n}\n\n/** Best-effort browser open. A failure is fine — the URL was already printed. */\nfunction openBrowser(url: string): void {\n const [bin, args] =\n process.platform === \"darwin\"\n ? ([\"open\", [url]] as const)\n : process.platform === \"win32\"\n ? ([\"cmd\", [\"/C\", \"start\", \"\", url]] as const)\n : ([\"xdg-open\", [url]] as const);\n try {\n spawn(bin, [...args], { stdio: \"ignore\", detached: true }).unref();\n } catch {\n // The URL is on stderr already; a machine with no browser is a valid\n // place to run this, and failing the login over it would be wrong.\n }\n}\n\n/** The line `login` prints about publish rights, shared with `whoami`. */\nexport function adminStatusLine(credential: HostCredential): string {\n return credential.is_app_admin\n ? err.green(\"Global admin: yes — you can publish.\")\n : err.yellow(\n \"Global admin: no — you can't publish yet. Ask #platform to add you to OXY_GLOBAL_ADMINS.\"\n );\n}\n","/**\n * `oxyc login`, `logout`, `whoami`, `token`.\n *\n * These write the SAME file the Rust `oxy` binary uses, so logging in with\n * either tool authenticates both. That is the whole reason `oxyc` can be\n * installed on its own: a developer with only `npx @oxy-hq/cli` is not a\n * second-class citizen, and one with both never logs in twice.\n */\n\nimport { parseJson, request } from \"../api/request.js\";\nimport { clearCredential, loadCredential, resolveBearer } from \"../auth/credentials.js\";\nimport { adminStatusLine, login } from \"../auth/login.js\";\nimport type { Context } from \"../context/resolve.js\";\nimport * as log from \"../ui/log.js\";\nimport { out } from \"../ui/tty.js\";\nimport { CliError, ExitCode } from \"../util/errors.js\";\nimport { runAssumeStart } from \"./assume.js\";\n\n/**\n * Log into one deployment, or several.\n *\n * MULTI-ENV IS SEQUENTIAL, not concurrent: each one opens a browser and waits\n * for its callback, and two tabs racing for the same loopback port is a login\n * that fails for a reason nobody can read. `oxy login --env dev,staging` does\n * the same, and the two tools write the same credential file — so logging into\n * three with one tool leaves the other authenticated for three.\n *\n * A FAILURE DOES NOT ABANDON THE REST. Logging into dev and staging is a\n * sequence of independent acts, and stopping at the first would leave you\n * having typed a browser flow for nothing. Each is reported as it lands, and\n * the exit code is non-zero if any failed.\n */\nexport async function runLogin(\n ctx: Context,\n envs: string[],\n assume?: { org?: string; reason: string }\n): Promise<void> {\n const targets = envs.length > 0 ? envs.map((e) => ctx.withEnv(e)) : [ctx];\n const failures: string[] = [];\n\n for (const one of targets) {\n const target = one.target();\n try {\n const { user } = await login(target);\n process.stderr.write(`${out.green(`Logged in as ${user.email} (${target}).`)}\\n`);\n process.stderr.write(`${adminStatusLine(user)}\\n`);\n } catch (cause) {\n failures.push(target);\n log.warn(`could not log into ${target}: ${(cause as Error).message}`);\n continue;\n }\n\n // Single-target by construction — `main.ts` refuses the multi-env case\n // before any browser opens, which is where a usage error belongs.\n if (assume) {\n await runAssumeStart(one, assume.org, assume.reason);\n }\n }\n\n if (failures.length > 0) {\n throw new CliError(`could not log into ${failures.length} of ${targets.length} deployment(s)`, {\n code: ExitCode.FAILURE,\n detail: failures.join(\"\\n\")\n });\n }\n}\n\nexport function runLogout(ctx: Context): void {\n const target = ctx.target();\n if (clearCredential(target)) {\n process.stderr.write(`${out.green(`Logged out of ${target}.`)}\\n`);\n return;\n }\n log.info(`no cached credential for ${target}`);\n}\n\n/**\n * Who this token is, and what it can reach.\n *\n * Deliberately makes a live call rather than printing the cached email: the\n * cached value is what was true at login, and the failure this command exists\n * to diagnose — an expired token, a revoked grant, a missing assume session —\n * is invisible in the cache. A `whoami` that reads a file cannot tell you the\n * token stopped working.\n */\nexport async function runWhoami(ctx: Context, json: boolean): Promise<void> {\n const target = ctx.target();\n const bearer = ctx.bearer();\n\n const response = await request({\n target,\n path: \"/api/user\",\n method: \"GET\",\n bearer,\n timeoutMs: 30_000\n });\n if (response.status === 401 || response.status === 403) {\n throw new CliError(`the cached token for ${target} is no longer accepted`, {\n code: ExitCode.AUTH,\n hint: `oxyc login --env ${ctx.flags.env ?? \"production\"}`\n });\n }\n if (response.status < 200 || response.status >= 300) {\n throw new CliError(`could not read /api/user (${response.status})`, {\n code: ExitCode.UNAVAILABLE\n });\n }\n\n const payload = parseJson(response.body);\n\n // A 200 whose body is `null` is the shape an EXPIRED token produces here:\n // the request is accepted, no user resolves, and the server says so with a\n // null rather than a 401. Reporting that as success — falling back to the\n // cached email, which is still sitting in the credentials file — is the\n // precise failure this command exists to catch, and it is what the first\n // run of this code did. `login.rs` refuses the same shape at login time.\n if (payload === null || payload === undefined) {\n throw new CliError(`the token for ${target} no longer resolves to a user`, {\n code: ExitCode.AUTH,\n detail:\n \"GET /api/user answered 200 with a null body, which is what an expired session looks like.\",\n hint: `oxyc login --env ${ctx.flags.env ?? \"production\"}`\n });\n }\n\n if (json) {\n process.stdout.write(`${response.body.trim()}\\n`);\n return;\n }\n\n const user = payload as Record<string, unknown>;\n const cached = loadCredential(target);\n const lines = [\n `${out.bold(\"target\")} ${target}`,\n `${out.bold(\"email\")} ${String(user.email ?? cached?.email ?? \"unknown\")}`,\n `${out.bold(\"app admin\")} ${user.is_app_admin ? \"yes\" : \"no\"}`\n ];\n if (typeof user.id === \"string\") lines.push(`${out.bold(\"user id\")} ${user.id}`);\n const customer = ctx.customer();\n if (customer)\n lines.push(`${out.bold(\"customer\")} ${customer.name} (from the repo you are in)`);\n process.stdout.write(`${lines.join(\"\\n\")}\\n`);\n}\n\n/**\n * Print the bearer, for a raw `curl`.\n *\n * It exists because the alternative is people copying tokens out of the\n * credentials file by hand, which is worse in every way — including that they\n * then paste the wrong host's.\n */\nexport function runToken(ctx: Context): void {\n const target = ctx.target();\n const token = resolveBearer(target, ctx.flags.tokenEnv ?? \"OXY_TOKEN\");\n if (!token) {\n throw new CliError(`not authenticated for ${target}`, {\n code: ExitCode.AUTH,\n hint: `oxyc login --env ${ctx.flags.env ?? \"production\"}`\n });\n }\n process.stdout.write(`${token}\\n`);\n}\n","/**\n * `oxyc list` and `oxyc path` — the two commands that answer \"who is there\"\n * and \"where is their repo\".\n */\n\nimport type { Context } from \"../context/resolve.js\";\nimport { dossierPath, isCloned } from \"../customer/dossier.js\";\nimport { customersOrg, displayName, listCustomers, resolveCustomer } from \"../github/customers.js\";\nimport { table } from \"../ui/render.js\";\nimport { out } from \"../ui/tty.js\";\n\n/**\n * The customers, with their display names and whether their repo is here.\n *\n * `--refresh` is on THIS command specifically, and it is the only way past the\n * hour-long cache. That placement is deliberate: a customer a teammate\n * registered minutes ago is invisible to every other command until the cache\n * expires, so every \"unknown customer\" message points here.\n */\nexport function runList(_ctx: Context, flags: { refresh?: boolean; json?: boolean }): void {\n const org = customersOrg();\n const customers = listCustomers({ refresh: flags.refresh });\n\n if (flags.json) {\n process.stdout.write(\n `${JSON.stringify(\n customers.map((c) => ({\n name: c.name,\n display_name: displayName(c),\n slug: `${org}/${c.name}`,\n cloned: isCloned(`${org}/${c.name}`),\n path: dossierPath(`${org}/${c.name}`)\n })),\n null,\n 2\n )}\\n`\n );\n return;\n }\n\n if (customers.length === 0) {\n // Reaching here means the listing SUCCEEDED and was empty — every failure\n // mode threw upstream. So this really is \"nobody is tagged\", and saying\n // which topic decides it is the actionable half.\n process.stderr.write(\n `${out.yellow(`no repos in ${org} carry the customer topic.`)}\\n` +\n ` ${out.dim(`register one with \\`oxyc import ${org}/<repo>\\``)}\\n`\n );\n return;\n }\n\n process.stdout.write(\n `${table(customers, [\n { header: \"CUSTOMER\", value: (c) => c.name },\n { header: \"NAME\", value: (c) => displayName(c) },\n { header: \"LOCAL\", value: (c) => (isCloned(`${org}/${c.name}`) ? \"cloned\" : \"—\") }\n ])}\\n`\n );\n}\n\n/**\n * Where a customer's repo is, and nothing else.\n *\n * One line on stdout so it composes: `cd \"$(oxyc path pokehouse)\"`. Everything\n * explanatory goes to stderr for exactly that reason.\n */\nexport function runPath(_ctx: Context, name: string, flags: { refresh?: boolean }): void {\n const customer = resolveCustomer(name, { refresh: flags.refresh });\n const slug = `${customersOrg()}/${customer.name}`;\n const path = dossierPath(slug);\n process.stdout.write(`${path}\\n`);\n if (!isCloned(slug)) {\n process.stderr.write(\n `${out.yellow(\"not cloned here yet\")} — ${out.dim(`gh repo clone ${slug} ${path}`)}\\n`\n );\n }\n}\n","/**\n * What endpoints exist, and what each one expects.\n *\n * Discovery is the reason this tool is worth building for an agent: without it\n * the caller needs a checkout to know the surface, and the whole premise is a\n * caller who has neither a checkout nor a doc site open.\n *\n * The Rust `oxy api` answered this from data baked into the binary at build\n * time — `crates/app/build_route_catalog.rs` walks the axum router source and\n * emits a table. That has one flaw this design fixes: the table describes the\n * routes the BINARY could mount, and several mounts are mode-conditional, so a\n * listed path can still 404 on the deployment in front of you. Asking the\n * deployment is strictly more truthful.\n *\n * It costs an authenticated network call, so the answer is cached per host and\n * a failure degrades to STALE AND SAID SO rather than to nothing — the\n * discipline `customer-tooling`'s `lib/customers.sh` writes down at length,\n * and for the same reason: an empty answer here reads as \"this deployment has\n * no such route\", which is a lie that sends the caller off to debug the wrong\n * thing.\n */\n\nimport { readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { hostKey } from \"../auth/credentials.js\";\nimport * as log from \"../ui/log.js\";\nimport { CliError, ExitCode } from \"../util/errors.js\";\nimport { ensureDir, oxycCacheDir, slugifyForPath } from \"../util/paths.js\";\nimport { parseJson, request } from \"./request.js\";\n\n/** One endpoint, as `/api/_catalog` reports it. Mirrors Rust `RouteDescription`. */\nexport interface CatalogRoute {\n method: string;\n path: string;\n surface: string;\n /** The credential this surface expects, spelled out rather than implied. */\n credential: string;\n path_parameters: string[];\n description: string;\n note: string;\n handler: string;\n /** `ide-only`, `worker-only` or `fleet-ok` — the role_manifest's own answer. */\n role: string;\n}\n\nexport interface Catalog {\n routes: CatalogRoute[];\n surfaces: Array<{ id: string; label: string; credential: string }>;\n /** Which deployment answered, and when — both shown when serving stale. */\n host: string;\n fetchedAt: number;\n /** True when this came off disk after the network failed. */\n stale?: boolean;\n}\n\n/** An hour: long enough that a session costs one call, short enough to notice a deploy. */\nconst CATALOG_TTL_MS = 3_600_000;\n\nfunction catalogPath(target: string): string {\n // 0700/0600 like the response cache: a full route table for a deployment\n // is reconnaissance, which is why the endpoint serving it is authenticated.\n const dir = ensureDir(join(oxycCacheDir(), \"catalog\"), 0o700);\n return join(dir, `${slugifyForPath(hostKey(target))}.json`);\n}\n\nfunction readDisk(target: string): Catalog | undefined {\n try {\n const cached = JSON.parse(readFileSync(catalogPath(target), \"utf8\")) as Catalog;\n // The filename is a sanitised host and can in principle collide; the\n // stored host is the identity. Serving one deployment's route table as\n // another's would be indistinguishable from a routing bug.\n if (cached.host !== hostKey(target)) return undefined;\n return cached;\n } catch {\n return undefined;\n }\n}\n\nfunction writeDisk(target: string, catalog: Catalog): void {\n try {\n writeFileSync(catalogPath(target), JSON.stringify(catalog), { mode: 0o600 });\n } catch {\n // A cache that cannot be written costs a call per command, not an answer.\n }\n}\n\nexport interface CatalogOptions {\n target: string;\n bearer?: string;\n /** Ignore a fresh cache and ask the deployment again. */\n refresh?: boolean;\n}\n\n/**\n * The route table for `target`.\n *\n * Fresh cache → live `/api/_catalog` → stale cache with a warning → an error\n * that says which of the two things went wrong. Never an empty catalog: an\n * empty list would be reported as \"no such route\" by every caller.\n *\n * ASKS FOR THE WHOLE TABLE even though the endpoint takes a `?filter=`,\n * because the cache is the point: one full fetch per host per hour serves\n * every later `oxyc routes <anything>` offline, where a filtered fetch would\n * be a round trip per query and could not be cached under one key without\n * poisoning it — a cached \"routes matching threads\" is not a route table, and\n * serving it as one would report every other endpoint as missing. `?filter=`\n * still earns its place on the endpoint, for the cache-less caller: a script,\n * a `curl`, a one-off.\n */\nexport async function loadCatalog(opts: CatalogOptions): Promise<Catalog> {\n const cached = readDisk(opts.target);\n if (!opts.refresh && cached && Date.now() - cached.fetchedAt < CATALOG_TTL_MS) {\n return cached;\n }\n\n // NO CREDENTIAL AND NOTHING CACHED: say so before asking, because the answer\n // an unauthenticated request gets back is not diagnostic. `/api/_catalog` is\n // on the protected router, and an anonymous request to it comes back 404 —\n // which this code would otherwise report as \"that deployment predates route\n // discovery\", sending the reader off to check a deployment version when what\n // they actually need is to log in. With a cache in hand the stale path below\n // is still better than an error, so the check is only for the empty case.\n if (!opts.bearer && !cached) {\n throw new CliError(`not authenticated for ${opts.target}`, {\n code: ExitCode.AUTH,\n hint: `oxyc login --target ${opts.target} — route discovery needs a token`\n });\n }\n\n try {\n const response = await request({\n target: opts.target,\n path: \"/api/_catalog\",\n method: \"GET\",\n bearer: opts.bearer,\n timeoutMs: 30_000\n });\n\n if (response.status === 401 || response.status === 403) {\n if (cached) return serveStale(cached, \"not authenticated for the route catalog\");\n throw new CliError(`the route catalog at ${opts.target} rejected this token`, {\n code: ExitCode.AUTH,\n hint: `oxyc login --target ${opts.target}`\n });\n }\n if (response.status === 404) {\n // An older deployment that predates `/api/_catalog`. Not an error the\n // caller can act on beyond \"this one cannot tell you\", so say exactly\n // that rather than \"not found\", which reads as a bad path.\n if (cached) return serveStale(cached, `${opts.target} has no /api/_catalog (older build)`);\n throw new CliError(`${opts.target} does not serve /api/_catalog`, {\n code: ExitCode.NOT_FOUND,\n hint: \"that deployment predates route discovery — try `oxyc openapi` for the documented subset\"\n });\n }\n if (response.status < 200 || response.status >= 300) {\n if (cached) return serveStale(cached, `catalog request failed (${response.status})`);\n throw new CliError(`could not read the route catalog (${response.status})`, {\n code: ExitCode.UNAVAILABLE\n });\n }\n\n const payload = parseJson(response.body) as Partial<Catalog> | undefined;\n if (!payload?.routes?.length) {\n // An EMPTY catalog is refused, never served. It is indistinguishable\n // from a deployment with no routes, and every caller downstream would\n // report a real endpoint as nonexistent.\n if (cached) return serveStale(cached, \"the deployment returned an empty route catalog\");\n throw new CliError(\"the deployment returned an empty route catalog\", {\n code: ExitCode.UNAVAILABLE,\n hint: \"this is a server bug, not a bad path — report it rather than working around it\"\n });\n }\n\n const catalog: Catalog = {\n routes: payload.routes,\n surfaces: payload.surfaces ?? [],\n host: hostKey(opts.target),\n fetchedAt: Date.now()\n };\n writeDisk(opts.target, catalog);\n return catalog;\n } catch (cause) {\n if (cause instanceof CliError && !cached) throw cause;\n if (cached) return serveStale(cached, (cause as Error).message);\n throw cause;\n }\n}\n\n/**\n * Serve the cache and say so.\n *\n * The warning is not decoration. A stale route table is usually right and\n * occasionally wrong in the one way that matters — a route added since the\n * cache was written reads as nonexistent — so the reader has to know which\n * kind of answer they are holding.\n */\nfunction serveStale(cached: Catalog, why: string): Catalog {\n const ageMinutes = Math.round((Date.now() - cached.fetchedAt) / 60_000);\n log.warn(`serving a STALE route catalog (${ageMinutes}m old): ${why}`);\n log.hint(\"oxyc routes --refresh once the deployment is reachable\");\n return { ...cached, stale: true };\n}\n\n/** Routes whose method, path or surface contains `needle`, case-insensitively. */\nexport function searchRoutes(catalog: Catalog, needle: string | undefined): CatalogRoute[] {\n if (!needle) return catalog.routes;\n const n = needle.toLowerCase();\n return catalog.routes.filter(\n (r) =>\n r.path.toLowerCase().includes(n) ||\n r.method.toLowerCase().includes(n) ||\n r.surface.toLowerCase().includes(n) ||\n r.description.toLowerCase().includes(n)\n );\n}\n\n/** The OpenAPI document the deployment publishes. */\nexport async function loadOpenApi(opts: CatalogOptions): Promise<unknown> {\n const response = await request({\n target: opts.target,\n path: \"/apidoc/openapi.json\",\n method: \"GET\",\n bearer: opts.bearer,\n timeoutMs: 30_000\n });\n if (response.status < 200 || response.status >= 300) {\n throw new CliError(`could not read the OpenAPI document (${response.status})`, {\n code: ExitCode.UNAVAILABLE,\n hint: `check ${opts.target}/apidoc is served by this deployment`\n });\n }\n const doc = parseJson(response.body);\n if (doc === undefined) {\n throw new CliError(\"the OpenAPI endpoint did not return JSON\", {\n code: ExitCode.UNAVAILABLE\n });\n }\n return doc;\n}\n","/**\n * `oxyc routes`, `oxyc schema`, `oxyc openapi` — how a caller with no checkout\n * finds out what it may ask for.\n *\n * These are the commands the tool exists for. An agent debugging a customer's\n * data has the binary and a token and nothing else: no repo, no doc site, no\n * running server it can browse. Everything it needs to construct a correct\n * request has to be reachable from here.\n */\n\nimport {\n type Catalog,\n type CatalogRoute,\n loadCatalog,\n loadOpenApi,\n searchRoutes\n} from \"../api/catalog.js\";\nimport type { Context } from \"../context/resolve.js\";\nimport { heading, table, wrap } from \"../ui/render.js\";\nimport { out, stdoutIsTty } from \"../ui/tty.js\";\nimport { CliError, ExitCode } from \"../util/errors.js\";\n\nexport interface RoutesFlags {\n json?: boolean;\n refresh?: boolean;\n /** Include `ide-only` and `worker-only` routes, which most callers cannot use. */\n all?: boolean;\n}\n\n/**\n * List the endpoints this deployment mounts.\n *\n * UNFILTERED OUTPUT IS A TABLE; a filter buys the prose. That is not a\n * cosmetic choice — the full surface is ~600 routes, and printing each one's\n * description unfiltered produces something no human scrolls through and no\n * agent should be made to read. Narrowing is what makes the prose affordable,\n * which is also why the error for \"no matches\" points back at the filter.\n */\nexport async function runRoutes(\n ctx: Context,\n filter: string | undefined,\n flags: RoutesFlags\n): Promise<void> {\n const catalog = await loadCatalog({\n target: ctx.target(),\n bearer: ctx.maybeBearer(),\n refresh: flags.refresh\n });\n\n let matches = searchRoutes(catalog, filter);\n if (!flags.all) {\n // `ide-only` and `worker-only` routes are mounted on one instance of the\n // fleet. They are real, but a caller hitting the load balancer will get a\n // 421 or a forward, so listing them alongside the rest as if they were\n // equally reachable is misleading. `--all` is the escape hatch.\n matches = matches.filter((r) => r.role === \"fleet-ok\");\n }\n\n if (flags.json) {\n process.stdout.write(`${JSON.stringify(matches, null, 2)}\\n`);\n return;\n }\n\n if (matches.length === 0) {\n throw new CliError(`no route matches ${JSON.stringify(filter ?? \"\")}`, {\n code: ExitCode.NOT_FOUND,\n hint: \"oxyc routes — the full list\\noxyc routes --all — including ide-only and worker-only mounts\"\n });\n }\n\n // A filter narrow enough to read in full gets the prose; a broad one gets\n // the compact table. 40 is where a screenful stops being a screenful.\n //\n // NEITHER ARM REFUSES, and `oxy_routes` mirrors that (`mcp.ts`): a broad\n // match degrades to method, path and credential rather than dead-ending a\n // caller who filtered in good faith. `credential` survives there for the same\n // reason `renderCompact` keeps it in each surface heading below — it is what\n // separates the bearer mount from the API-key one. The MCP threshold is\n // higher because a context window is not a screen.\n const verbose = Boolean(filter) && matches.length <= 40;\n process.stdout.write(\n verbose ? renderDetailed(catalog, matches) : renderCompact(catalog, matches)\n );\n process.stdout.write(\"\\n\");\n\n if (!filter) {\n process.stderr.write(\n `\\n${out.dim(`${matches.length} routes. Narrow with \\`oxyc routes <filter>\\` to see what each one does.`)}\\n`\n );\n }\n}\n\n/** The compact grouped table: method and path, grouped by surface. */\nfunction renderCompact(catalog: Catalog, matches: CatalogRoute[]): string {\n const sections: string[] = [];\n for (const surface of surfacesOf(catalog, matches)) {\n const group = matches.filter((r) => r.surface === surface.id);\n if (group.length === 0) continue;\n sections.push(heading(`${surface.label} — ${surface.credential}`));\n sections.push(\n table(group, [\n { header: \"METHOD\", value: (r) => r.method },\n { header: \"PATH\", value: (r) => r.path }\n ])\n );\n }\n return sections.join(\"\\n\");\n}\n\n/** Method, path, what it does, and the mount comment that explains why. */\nfunction renderDetailed(catalog: Catalog, matches: CatalogRoute[]): string {\n const lines: string[] = [];\n for (const surface of surfacesOf(catalog, matches)) {\n const group = matches.filter((r) => r.surface === surface.id);\n if (group.length === 0) continue;\n lines.push(heading(`${surface.label} — ${surface.credential}`));\n for (const route of group) {\n lines.push(` ${out.bold(route.method.padEnd(7))} ${route.path}`);\n for (const line of wrap(route.description, 84)) lines.push(` ${line}`);\n // Marked as a note, because a mount comment is not always *about* its\n // mount — it may be explaining the route above it, or one since removed.\n wrap(route.note, 78).forEach((line, i) => {\n lines.push(` ${i === 0 ? \"note: \" : \" \"}${line}`);\n });\n if (route.path_parameters.length > 0) {\n lines.push(` ${out.dim(`params: ${route.path_parameters.join(\", \")}`)}`);\n }\n }\n }\n return lines.join(\"\\n\");\n}\n\n/** Surfaces in the catalog's own display order, falling back to first-seen. */\nfunction surfacesOf(catalog: Catalog, matches: CatalogRoute[]) {\n if (catalog.surfaces.length > 0) return catalog.surfaces;\n const seen: string[] = [];\n for (const route of matches) if (!seen.includes(route.surface)) seen.push(route.surface);\n return seen.map((id) => ({ id, label: id, credential: \"\" }));\n}\n\n/**\n * `oxyc schema <path>` — the request and response shapes for one endpoint.\n *\n * This is the piece the Rust CLI never had: `--openapi` printed the whole\n * document and left the caller to find their operation in it. An agent\n * building a request body needs one operation's schema, and dumping 47 of them\n * to find it costs more context than the request it is trying to make.\n */\nexport async function runSchema(\n ctx: Context,\n rawPath: string,\n method: string | undefined\n): Promise<void> {\n const doc = (await loadOpenApi({ target: ctx.target(), bearer: ctx.maybeBearer() })) as {\n paths?: Record<string, Record<string, unknown>>;\n components?: unknown;\n };\n\n const paths = doc.paths ?? {};\n\n // Exact match on the comparable form first, then a substring on the literal\n // segments — an agent that types `threads` should get the thread endpoints\n // rather than an error about a path that is almost right.\n const wanted = comparablePath(rawPath);\n const exact = Object.entries(paths).filter(([p]) => comparablePath(p) === wanted);\n const candidates =\n exact.length > 0\n ? exact\n : Object.entries(paths).filter(([p]) =>\n literalSegments(p).includes(literalSegments(rawPath))\n );\n\n if (candidates.length === 0) {\n throw new CliError(`no documented schema for ${rawPath}`, {\n code: ExitCode.NOT_FOUND,\n hint:\n \"the OpenAPI document covers a curated subset of the surface.\\n\" +\n ` \\`oxyc routes ${rawPath}\\` shows whether the endpoint exists at all.`\n });\n }\n\n const selected: Record<string, unknown> = {};\n for (const [path, operations] of candidates) {\n const filtered = method\n ? Object.fromEntries(\n Object.entries(operations).filter(([verb]) => verb.toLowerCase() === method.toLowerCase())\n )\n : operations;\n if (Object.keys(filtered).length > 0) selected[path] = filtered;\n }\n\n if (Object.keys(selected).length === 0) {\n throw new CliError(`no ${method?.toUpperCase()} operation documented for ${rawPath}`, {\n code: ExitCode.NOT_FOUND,\n hint: `oxyc schema ${rawPath} — without --method, to see which verbs are documented`\n });\n }\n\n // `components` rides along because schemas are `$ref`-heavy and a body\n // description full of unresolvable references is not a description.\n process.stdout.write(\n `${JSON.stringify({ paths: selected, components: doc.components }, null, 2)}\\n`\n );\n}\n\n/**\n * A path reduced to what two spellings of the same endpoint have in common.\n *\n * TWO MISMATCHES, both of which made the obvious implementation useless\n * against the real document:\n *\n * 1. **No `/api` prefix.** OpenAPI carries it in `servers`, so the document\n * says `/{workspace_id}/agents` while every other surface of this CLI —\n * and every caller — says `/api/{workspace_id}/agents`. Normalising the\n * request path *up* to `/api/...` guaranteed a miss on every lookup.\n * 2. **Different placeholder names.** The document says `{workspace_id}`;\n * this CLI's own placeholder is `{workspace}`, and `oxyc schema\n * {workspace}/threads` is exactly what someone copies from `oxyc api`.\n *\n * So both sides are reduced: the `/api` prefix dropped, and every `{...}`\n * collapsed to `{}`. The names inside braces carry no information a lookup\n * needs — position does.\n */\nexport function comparablePath(path: string): string {\n return path\n .trim()\n .replace(/^\\/+/, \"/\")\n .replace(/^(?!\\/)/, \"/\")\n .replace(/^\\/api(?=\\/|$)/, \"\")\n .replace(/\\{[^}]*\\}/g, \"{}\")\n .replace(/\\/+$/, \"\")\n .toLowerCase();\n}\n\n/** The literal (non-placeholder) part of a path, for a fuzzy substring match. */\nexport function literalSegments(path: string): string {\n return comparablePath(path).replace(/\\{\\}/g, \"\");\n}\n\n/** `oxyc openapi` — the whole document, for piping into jq. */\nexport async function runOpenApi(ctx: Context): Promise<void> {\n const doc = await loadOpenApi({ target: ctx.target(), bearer: ctx.maybeBearer() });\n process.stdout.write(`${JSON.stringify(doc, null, stdoutIsTty() ? 2 : 0)}\\n`);\n}\n","/**\n * `oxyc guide` — teach an agent this tool, in one command, in any harness.\n *\n * THE GAP THIS FILLS. There are already three ways an LLM can learn `oxyc`,\n * and each reaches a different audience:\n *\n * 1. the tool describes itself — `--help`, `routes`, `schema`, `exit-codes`.\n * Works for ANY agent with no setup, and is the foundation. But it is\n * pull-based: the agent has to already suspect `oxyc` is the right tool.\n * 2. the bundled Claude skill (`oxyc skills install`). Rich, but Claude-only\n * and behind an install step.\n * 3. error messages that name the next command. The highest-bandwidth\n * channel, because it arrives exactly when the agent is stuck — but only\n * once it is already stuck.\n *\n * None of them puts \"here is what this tool is for\" into an agent's context\n * BEFORE it needs it, in a harness-agnostic way. That is what this is: a\n * compact page a human pastes into `AGENTS.md`, `CLAUDE.md`, `.cursorrules`,\n * a system prompt, or whatever their agent reads.\n *\n * COMPLEMENTS `oxyc mcp` rather than competing with it. MCP reaches an agent\n * whose runtime can launch a server; this reaches every other one — a plain\n * shell, a CI job, a harness with no MCP support — and it costs nothing per\n * turn beyond the lines it occupies.\n *\n * KEPT SHORT ON PURPOSE. Something that lands in a context window on every\n * turn has to earn each line; the detail lives behind `routes` and `schema`.\n */\n\nimport { basename, dirname, extname, resolve, sep } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { stdoutIsTty } from \"../ui/tty.js\";\n\n/**\n * How to invoke THIS binary, resolved at runtime.\n *\n * The guide is a page a human pastes verbatim into `AGENTS.md`, so a `<repo>`\n * placeholder is a line an agent runs as-is and gets\n * `Cannot find module '<repo>/…'`. Until the package is published there is no\n * short spelling, so the honest one is the absolute path this process was\n * started from — which the binary knows.\n *\n * `process.argv[1]` is that path, and after a global install it is the\n * `bin/oxyc` symlink rather than `dist/main.mjs`. `node <symlink>` works on\n * POSIX because npm links the JS file itself, so the line stays runnable —\n * it just will not be the path the prose above it describes.\n */\nfunction selfInvocation(): string {\n // A compiled single-file binary IS the executable: there is no `node` and no\n // `dist/main.mjs`. Printing one would hand an agent a path that does not\n // exist, which is the one thing this page cannot afford to do.\n const runner = basename(process.execPath, extname(process.execPath));\n if (runner !== \"node\" && runner !== \"bun\") return \"oxyc\";\n\n const self = fileURLToPath(import.meta.url);\n // From `dist/main.mjs` at runtime; from `src/commands/guide.ts` under vitest.\n const dist = self.includes(`${sep}dist${sep}`)\n ? process.argv[1] || self\n : resolve(dirname(self), \"..\", \"..\", \"dist\", \"main.mjs\");\n return `node ${dist}`;\n}\n\nconst GUIDE = () => `## oxyc — the Oxy CLI\n\nAuthenticated HTTP client for the Oxy platform (\\`gh api\\`-shaped), plus the\ntooling that scopes work to one customer. Use it to get real data out of a\ndeployment: query a customer's warehouse or semantic layer, read threads, runs\nand apps, or reproduce a reported bug against live data.\n\n ${selfInvocation()} <command>\n\nIf your runtime speaks MCP, \\`oxyc mcp\\` serves the same surface as four tools\n(\\`oxy_routes\\`, \\`oxy_schema\\`, \\`oxy_request\\`, \\`oxy_whoami\\`).\n\n### Never guess a path\n\n oxyc routes <filter> # what exists, and what each endpoint does\n oxyc schema <path> [-X POST] # the body it expects\n oxyc api <path> [flags] # call it\n\n### Getting data out\n\n oxyc api orgs --md # org ids\n oxyc api {org}/workspaces --md # workspace ids\n oxyc api {workspace}/databases --jq '.[].name' # connection names\n oxyc api {workspace}/sql/query -f 'sql=select 1' -f database=<name> --md\n\n\\`{org}\\` \\`{workspace}\\` \\`{project}\\` \\`{customer}\\` \\`{me}\\` fill themselves from the\ncustomer repo you are in, or from \\`--org\\` / \\`--workspace\\` / \\`--project\\`. An\nunresolved one errors and names the flag that would fill it.\n\n### Flags worth knowing\n\n -f k=v / -F k=v string / JSON-typed field --input @file raw body\n --jq '<expr>' filter server-side shape --md markdown table\n --paginate walk every page --cache 5m reuse a recent GET\n --env local|dev|staging|production, or paste a URL\n\nPrefer \\`--jq\\` and \\`--md\\` before reading a large response: \\`--md\\` is far fewer\ntokens than the same rows as JSON, which repeats every field name per row.\n\n### Branch on the exit code\n\n 0 ok · 1 it ran and found problems · 2 you called it wrong, stop\n 4 log in (\\`oxyc login --env <env>\\`) · 5 not found · 6 malformed request\n 7 retryable (5xx/timeout) · 8 refused\n\n### Beyond the API\n\n oxyc validate # check the workspace YAML — no network, no token\n oxyc proxy --env dev # local app dev against cloud data\n oxyc <customer> # a session scoped to one customer\n oxyc doctor <customer> # what the tool knows, changing nothing\n oxyc assume status # a staff 403 usually means no session, not a role\n oxyc assume start --org <o> -r \"why\" # 60 min, not renewable\n\n\\`oxyc validate\\` is the only one that works entirely offline. It is STRUCTURAL —\n\\`oxy validate\\` also resolves \\`databases:\\` and \\`llm.ref\\` and wins where they differ.\n\n### Traps\n\n- \\`200\\` with a body of \\`null\\` can mean an EXPIRED SESSION, not \"no such\n thing\" — \\`/api/user\\` does exactly that. \\`oxyc whoami\\` tells them apart.\n- \\`/sql/query\\` returns arrays of strings, HEADER ROW FIRST —\n \\`[[\"id\",\"name\"],[\"1\",\"ada\"]]\\` — not an object. \\`--md\\` renders it.\n- \\`oxyc schema\\` covers the data plane only. Blank means undocumented, not\n nonexistent; \\`oxyc routes <path>\\` confirms the endpoint is real.\n- A listed route can still 404 if it is \\`ide-only\\`; \\`oxyc routes --all\\` shows those.\n- Read freely. Ask before running a mutating request against production.\n`;\n\n/**\n * Print the guide.\n *\n * Markdown either way — it is meant to be pasted into a file, and a terminal\n * reader is going to copy it rather than read it in place.\n */\nexport function runGuide(): void {\n process.stdout.write(GUIDE());\n if (stdoutIsTty()) {\n process.stderr.write(\"\\nPaste that into AGENTS.md / CLAUDE.md, or: oxyc guide >> AGENTS.md\\n\");\n }\n}\n","/**\n * Where a customer repo's Oxy WORKSPACE is — which is not always the repo.\n *\n * Every repo `oxyc new` scaffolds is a workspace at its root: `config.yml` sits\n * beside `semantics/`, `pipelines/` and `workflows/`. `oxyc import` brings in\n * repos that predate the template, and they are not all that shape —\n * `oxy-hq/pokehouse-oxy` is a PROJECT that CONTAINS a workspace at `oxy/`,\n * with `etl/`, `kestra/`, three apps and four workflows of its own at the root.\n * None of that is the workspace and all of it is the customer's.\n *\n * DETECTION, NEVER ASSUMPTION, and only ambiguity refuses:\n *\n * config.yml at the repo root → the repo IS the workspace (\".\")\n * exactly one, one level down → that subdirectory\n * none → there is none; not an error\n * two or more → an ERROR that names both\n *\n * The asymmetry is deliberate. Guessing between two candidates scopes a\n * session to the wrong tree and says nothing about it, which is unrecoverable\n * from the inside. Finding none is not a guess: a customer repo may hold\n * memory and notes and no workspace at all.\n *\n * THE WORKSPACE NEVER MOVES. The platform registered its subdirectory at\n * onboarding and nothing re-opens that field, so flattening a repo to match\n * the template would silently break the registration.\n */\n\nimport { existsSync, mkdirSync, readdirSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport * as log from \"../ui/log.js\";\nimport { CliError, ExitCode } from \"../util/errors.js\";\n\n/** What makes a directory an Oxy workspace, named once. */\nconst WORKSPACE_MARKER = \"config.yml\";\n\n/**\n * The repo's own statement about its shape.\n *\n * Its OWN file, deliberately not a field in `.oxyc-template.json`: the stamp\n * is machine-written and classified `managed`, so a sync may rewrite it — a\n * hand-written fact placed there would be destroyed by the very sync it exists\n * to inform. The stamp also answers \"what was this rendered from\", which is\n * about the past; this answers \"what shape is this repo\", which is true\n * whether oxyc rendered it or not. And an imported repo has no stamp at all,\n * while being exactly the case most likely to need an override.\n */\nconst REPO_CONFIG_FILE = \".oxyc.json\";\n\n/** Directories never walked when looking for a workspace. */\nconst SKIP_DIRS = new Set([\n \".git\",\n \".github\",\n \"node_modules\",\n \"target\",\n \"dist\",\n \"out\",\n \".worktrees\",\n \".oxy_state\",\n \".venv\"\n]);\n\n/** The three outcomes of reading `.oxyc.json`. */\ntype Override =\n | { kind: \"none\" }\n | { kind: \"workspace\"; path: string }\n | { kind: \"invalid\"; why: string };\n\n/**\n * The workspace this repo declares for itself.\n *\n * Three outcomes rather than two, because \"no override\" and \"a broken\n * override\" must not read the same: a repo that states its own shape and\n * states it WRONGLY is not a repo to guess about — the guess would silently\n * disagree with what somebody wrote down.\n */\nfunction readOverride(repoDir: string): Override {\n const file = join(repoDir, REPO_CONFIG_FILE);\n if (!existsSync(file)) return { kind: \"none\" };\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(readFileSync(file, \"utf8\"));\n } catch {\n return {\n kind: \"invalid\",\n why: `${REPO_CONFIG_FILE} is not valid JSON. Expected: {\"workspace\": \"<subdirectory>\"}`\n };\n }\n\n const raw =\n typeof parsed === \"object\" && parsed !== null\n ? (parsed as { workspace?: unknown }).workspace\n : undefined;\n // A missing key, an explicit null and an empty string all mean \"nothing to\n // apply\" rather than the string \"null\".\n if (typeof raw !== \"string\" || !raw.trim()) return { kind: \"none\" };\n\n const value = raw.trim();\n if (value.startsWith(\"/\")) {\n return {\n kind: \"invalid\",\n why: `${REPO_CONFIG_FILE} names an absolute workspace path (${value}); it must be relative to the repo root, because the repo is cloned to a different path on every machine`\n };\n }\n if (\n value === \"..\" ||\n value.startsWith(\"../\") ||\n value.endsWith(\"/..\") ||\n value.includes(\"/../\")\n ) {\n return {\n kind: \"invalid\",\n why: `${REPO_CONFIG_FILE} names a workspace outside the repo (${value}); it is a directory INSIDE the repo, or the repo itself`\n };\n }\n\n // `oxy/` and `oxy` are the same directory; `./` and `.` are the repo root.\n const normalized = value.replace(/\\/+$/, \"\").replace(/^\\.\\//, \"\");\n return { kind: \"workspace\", path: normalized === \"\" ? \".\" : normalized };\n}\n\n/** Directories one level down that hold a `config.yml`. */\nfunction candidates(repoDir: string): string[] {\n let entries: string[];\n try {\n entries = readdirSync(repoDir, { withFileTypes: true })\n .filter((e) => e.isDirectory() && !SKIP_DIRS.has(e.name) && !e.name.startsWith(\".\"))\n .map((e) => e.name);\n } catch {\n return [];\n }\n return entries.filter((name) => existsSync(join(repoDir, name, WORKSPACE_MARKER))).sort();\n}\n\n/**\n * The workspace path relative to the repo root, or `undefined` when the repo\n * holds no workspace at all.\n *\n * Throws only on genuine ambiguity, and on an override that is present and\n * wrong.\n */\nexport function resolveWorkspace(repoDir: string): string | undefined {\n const override = readOverride(repoDir);\n if (override.kind === \"invalid\") {\n throw new CliError(`${repoDir} declares a workspace oxyc cannot use`, {\n code: ExitCode.REFUSED,\n detail: override.why,\n hint: \"fix .oxyc.json — oxyc will not guess past a repo's own statement about its shape\"\n });\n }\n if (override.kind === \"workspace\") {\n const abs = override.path === \".\" ? repoDir : join(repoDir, override.path);\n if (!existsSync(join(abs, WORKSPACE_MARKER))) {\n throw new CliError(\n `${REPO_CONFIG_FILE} names ${override.path}, which has no ${WORKSPACE_MARKER}`,\n {\n code: ExitCode.REFUSED,\n hint: \"fix .oxyc.json, or add the workspace it names\"\n }\n );\n }\n return override.path;\n }\n\n if (existsSync(join(repoDir, WORKSPACE_MARKER))) return \".\";\n\n const found = candidates(repoDir);\n if (found.length === 1) return found[0];\n if (found.length > 1) {\n throw new CliError(`${repoDir} has more than one Oxy workspace`, {\n code: ExitCode.REFUSED,\n detail: found.map((d) => ` ${d}/${WORKSPACE_MARKER}`).join(\"\\n\"),\n hint: `say which one in ${REPO_CONFIG_FILE}: {\"workspace\": \"<subdirectory>\"}`\n });\n }\n return undefined;\n}\n\n/** The absolute workspace directory, or `undefined` when there is none. */\nexport function workspaceDir(repoDir: string): string | undefined {\n const rel = resolveWorkspace(repoDir);\n if (rel === undefined) return undefined;\n return rel === \".\" ? repoDir : join(repoDir, rel);\n}\n\n/**\n * Where a session's memory facts go — the REPO root in both layouts.\n *\n * Memory is about the CUSTOMER, not about the Oxy workspace inside their repo,\n * so it does not follow the workspace into a subdirectory. This is also the\n * one directory oxyc creates in a repo it did not scaffold.\n */\nexport function memoryDir(repoDir: string): string {\n return join(repoDir, \"memory\");\n}\n\n/**\n * The memory directory, created if absent.\n *\n * A failure warns rather than aborting: a session with nowhere to write memory\n * is still worth more than no session.\n */\nexport function ensureMemoryDir(repoDir: string): string {\n const dir = memoryDir(repoDir);\n try {\n mkdirSync(dir, { recursive: true });\n } catch {\n log.warn(`could not create the memory directory at ${dir}`);\n }\n return dir;\n}\n","/**\n * `oxyc <customer>` — start a Claude Code session scoped to one customer.\n *\n * The briefing is the product here. Everything below exists so that the prompt\n * handed to the model DESCRIBES THE SESSION IT IS ACTUALLY ATTACHED TO — three\n * repo shapes times `--here`, each saying exactly what is true of it. \"Your\n * working directory IS their workspace\" is false twice over: for a repo whose\n * root holds the customer's own ETL, apps and workflows with the workspace in\n * `oxy/`, and for a repo that holds no workspace at all.\n *\n * A prompt that overclaims is worse than a vague one, because the model has no\n * way to check it.\n */\n\nimport { spawn } from \"node:child_process\";\n\nimport type { Context } from \"../context/resolve.js\";\nimport { dossierPath, ensureCloned, isCloned } from \"../customer/dossier.js\";\nimport { attributionLine, sharedRepoContext } from \"../customer/repos.js\";\nimport { ensureMemoryDir, resolveWorkspace, workspaceDir } from \"../customer/workspace.js\";\nimport { customersOrg, displayName, resolveCustomer } from \"../github/customers.js\";\nimport * as log from \"../ui/log.js\";\nimport { ExitCode } from \"../util/errors.js\";\n\nexport interface LaunchFlags {\n /** Run in the current directory, granting the customer's repo via --add-dir. */\n here?: boolean;\n /** Print the command instead of running it. */\n dryRun?: boolean;\n /** Everything after `--`, handed to claude. */\n passthrough: string[];\n}\n\nexport function runLaunch(ctx: Context, name: string, flags: LaunchFlags): void {\n // No fallback on a failed resolve: it is either unknown, ambiguous (it says\n // which, and lists the candidates), or `gh` could not answer at all.\n // Continuing past any of those launches a session scoped to a customer\n // nobody named.\n const customer = resolveCustomer(name, { refresh: ctx.flags.refresh });\n const slug = `${customersOrg()}/${customer.name}`;\n const repoDir = isCloned(slug) ? dossierPath(slug) : ensureCloned(slug, { autoClone: true });\n\n // Detected AFTER any clone, because the clone is what can bring a\n // `config.yml` into a checkout that had none.\n const workspaceRel = resolveWorkspace(repoDir);\n const workspace = workspaceDir(repoDir);\n\n // Created rather than merely named: this path is handed to Claude Code as\n // `autoMemoryDirectory`, and a repo oxyc did not scaffold has no `memory/`.\n const memory = ensureMemoryDir(repoDir);\n const display = displayName(customer);\n\n const briefing = buildBriefing({\n display,\n // The repo NAME, never the display name and never the abbreviation that\n // was typed: the display name is a description wherever one is set, so it\n // is not a resolvable identifier, and `pokehouse-oxy` and\n // `pokehouse-context` both strip to `pokehouse` — stripping manufactures\n // the one collision a full repo name cannot have.\n name: customer.name,\n repoDir,\n workspace,\n workspaceRel,\n memory,\n here: Boolean(flags.here)\n });\n\n const settings = JSON.stringify({ autoMemoryDirectory: memory });\n const args = flags.here\n ? [\n \"--settings\",\n settings,\n \"--add-dir\",\n repoDir,\n \"--append-system-prompt\",\n briefing,\n ...flags.passthrough\n ]\n : [\"--settings\", settings, \"--append-system-prompt\", briefing, ...flags.passthrough];\n\n if (flags.dryRun || process.env.OXYC_DRY_RUN === \"1\") {\n // The `cd` is printed too, because it is half of what makes the session\n // what it is — a line that omitted it would describe a launch nobody\n // performs.\n const prefix = flags.here ? \"\" : `cd ${repoDir} && `;\n process.stdout.write(`${prefix}claude ${args.map(shellQuote).join(\" \")}\\n`);\n return;\n }\n\n log.info(`${customer.name} → ${flags.here ? process.cwd() : repoDir}`);\n const child = spawn(\"claude\", args, {\n cwd: flags.here ? process.cwd() : repoDir,\n stdio: \"inherit\",\n env: { ...process.env, OXYC_DOSSIER: repoDir }\n });\n // REPORTED HERE, not thrown. This callback runs on the event loop long after\n // `runLaunch` returned, so a throw from it unwinds to nothing: node prints an\n // uncaught-exception stack and exits 1. A machine without Claude Code\n // installed — the whole reason this branch exists — would get that stack\n // instead of the one line telling it what to install.\n child.on(\"error\", (cause) => {\n const missing = (cause as NodeJS.ErrnoException).code === \"ENOENT\";\n log.error(missing ? \"`claude` is not on PATH\" : `could not start claude: ${cause.message}`);\n log.hint(\n missing\n ? \"install Claude Code, or use `--dry-run` to print the command instead\"\n : \"use `--dry-run` to print the command and run it yourself\"\n );\n // NOT `USAGE`. That code means \"you called it wrong, stop\", and an agent\n // reading it concludes its own arguments were the problem and will not act\n // on the hint it was just handed. `oxyc launch acme` on a box without\n // Claude Code installed is a CORRECT invocation in an incomplete\n // environment — `UNAVAILABLE` says exactly that, and is the code the\n // contract already documents as retryable-once-the-dependency-is-there.\n process.exit(missing ? ExitCode.UNAVAILABLE : ExitCode.FAILURE);\n });\n // The child owns the terminal from here; its exit code is ours.\n child.on(\"exit\", (code) => process.exit(code ?? 0));\n}\n\ninterface BriefingInput {\n display: string;\n name: string;\n repoDir: string;\n workspace: string | undefined;\n workspaceRel: string | undefined;\n memory: string;\n here: boolean;\n}\n\n/**\n * Where the work is, said truthfully for each of the six cases.\n *\n * Under `--here` the working directory is one of OUR repos and the customer's\n * is merely granted, so every sentence has to be re-pointed.\n */\nfunction whereClause(input: BriefingInput): string {\n const { display, repoDir, workspace, workspaceRel } = input;\n const subdir = workspaceRel && workspaceRel !== \".\" ? workspaceRel : undefined;\n\n if (input.here) {\n if (!workspaceRel) {\n return `${display}'s repo is at ${repoDir}, which is NOT your working directory this session. It holds no Oxy workspace — no config.yml — so it is their memory and notes rather than a semantic model.`;\n }\n if (!subdir) {\n return `${display}'s Oxy workspace — semantic model, pipelines, automations, custom apps — is at ${repoDir}, which is NOT your working directory this session.`;\n }\n return `${display}'s Oxy workspace — semantic model, pipelines, automations, custom apps — is the ${subdir}/ subdirectory of their repo, at ${workspace}, which is NOT your working directory this session. Nor is the repo it sits in, at ${repoDir}; the rest of that repo, outside ${subdir}/, is the customer's own work and no part of the workspace.`;\n }\n\n if (!workspaceRel) {\n return `Your working directory is ${display}'s repo. It holds no Oxy workspace — there is no config.yml at its root or one level below — so treat it as their memory, notes and whatever else the team keeps for them, not as a semantic model Oxy compiles.`;\n }\n if (!subdir) {\n return `Your working directory IS ${display}'s Oxy workspace: the semantic model, pipelines, automations and custom apps under it are theirs, and editing them is customer work rather than tooling work.`;\n }\n return `Your working directory is ${display}'s repo, and it is NOT the whole of their Oxy workspace. The workspace is the ${subdir}/ subdirectory, at ${workspace}: the semantic model, pipelines, automations and custom apps under THAT directory are what Oxy compiles and serves.\n\nEverything else in ${repoDir} — outside ${subdir}/ — is the customer's own work sitting alongside it: their own tooling, their own CI, their own apps. It is theirs to read and to change on their behalf, but it is not the workspace, and nothing about it follows the conventions oxy expects of one.\n\nEditing either is customer work rather than tooling work.`;\n}\n\nfunction buildBriefing(input: BriefingInput): string {\n const subdir = input.workspaceRel && input.workspaceRel !== \".\" ? input.workspaceRel : undefined;\n\n // Worth saying out loud exactly when the repo is not the workspace —\n // otherwise a session told the workspace is `oxy/` will reasonably put\n // memory under it.\n const memoryNote = subdir\n ? `\\n\\nThat directory is at the REPO ROOT, deliberately outside the ${subdir}/ workspace: what you learn is about the CUSTOMER, not about their workspace, and this repo holds more than the workspace does.`\n : \"\";\n\n return `You are working on behalf of the customer ${input.display}.\n\n${whereClause(input)}\n\nChanges to their repo go via a branch and a pull request — memory included.\nBranch per CHANGE, not per session: one session may produce several.\n\nSome work for this customer lands in OUR repos rather than in theirs. Those are:\n\n${sharedRepoContext()}\nPrefer the checkout that is already there over cloning a second copy.\n\nWhen you open a pull request in any of them — that is, in a repo that is NOT\n${input.name} — put this on its own line in the body:\n\n ${attributionLine(input.name)}\n\nIt is the only thing that ties that pull request back to this customer:\n\"oxyc activity\" finds the pull request by matching that exact line. Their own\nrepo needs no such line, because the repo is already the answer.\n\nDurable, customer-specific facts you learn this session — their infrastructure,\ntheir data quirks, decisions made for them, gotchas that cost time — belong in\nthe memory directory at ${input.memory}, which is shared with the team via git.${memoryNote}\nCommit a fact deliberately, in the pull request of the change that prompted it,\nrather than sweeping it up at the end of the session.\n\nProduct-level facts that are true regardless of which customer you are working\nfor do not belong there; they belong in the ordinary project memory.`;\n}\n\n/** Single-quote for a shell, so `--dry-run` prints something runnable. */\nfunction shellQuote(value: string): string {\n if (/^[A-Za-z0-9_./:@-]+$/.test(value)) return value;\n return `'${value.replaceAll(\"'\", `'\\\\''`)}'`;\n}\n","/**\n * `oxyc proxy` — local custom-app dev against a cloud Oxy.\n *\n * An OUTBOUND sidecar: it does not serve the app (your dev server does). It\n * listens on `--port` (default 3000, where a local `oxy serve` would be, so a\n * dev server's existing Oxy proxy target already matches) and forwards the Oxy\n * calls your dev server sends it — attaching the `oxy login` bearer and\n * applying guardrails — to the resolved cloud target.\n *\n * A PORT of `crates/app/src/cli/commands/proxy.rs`, and the guardrails are\n * carried across verbatim rather than reinvented, because each one is a\n * decision somebody argued and every one of them is about not writing to a\n * customer's production data from a laptop:\n *\n * - side-effecting calls are HELD by default (`--allow-writes` forwards)\n * - tracking events are DROPPED by default (`--allow-events` forwards)\n * - auth endpoints reach the backend UNAUTHENTICATED, so sign-in works\n * - the dev token is a FALLBACK, never an override of a real browser session\n * - `Set-Cookie` is rewritten so a cloud cookie is storable on localhost\n *\n * The token lives only in this process and is never returned to the browser.\n * Authorization is decided by the cloud; the proxy only forwards.\n */\n\nimport { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\n\nimport type { Context } from \"../context/resolve.js\";\nimport * as log from \"../ui/log.js\";\nimport { out } from \"../ui/tty.js\";\nimport { CliError, ExitCode } from \"../util/errors.js\";\n\nexport interface ProxyFlags {\n port?: string;\n allowWrites?: boolean;\n allowEvents?: boolean;\n yes?: boolean;\n}\n\n/**\n * Cap on a buffered request body. Requests through the proxy are small (query\n * and semantic-query JSON); the large payloads are RESPONSES, which stream.\n */\nconst MAX_REQUEST_BODY = 25 * 1024 * 1024;\n\n/**\n * Headers this proxy must not forward.\n *\n * The first eight are hop-by-hop by definition. `content-encoding` and\n * `content-range` are here for a different and less obvious reason: node's\n * `fetch` is not `reqwest`. undici sends its own\n * `accept-encoding: gzip, deflate, br` and DECODES the response transparently,\n * so by the time the body reaches this code it is plain bytes — forwarding the\n * upstream's `content-encoding: gzip` labels them as compressed and the\n * browser fails with `ERR_CONTENT_DECODING_FAILED` on exactly the\n * `POST /projects/{id}/query` round-trip this command exists for.\n *\n * The Rust original is safe by omission rather than by design: its `reqwest`\n * is built without the `gzip`/`brotli` features, so it never asks for a\n * compressed body and never had the case.\n */\nconst HOP_BY_HOP = new Set([\n \"connection\",\n \"keep-alive\",\n \"proxy-authenticate\",\n \"proxy-authorization\",\n \"te\",\n \"trailer\",\n \"transfer-encoding\",\n \"upgrade\",\n \"content-length\",\n \"content-encoding\",\n // Safe to strip only because `range` is not among the headers\n // `buildRequestHeaders` forwards, so upstream never answers 206. Unlike\n // `content-encoding`, undici does not rewrite this one — adding `range` to\n // that forward list without removing this entry would silently break every\n // partial response.\n \"content-range\"\n]);\n\n/**\n * `POST /api/customer-apps/{id}/events` — usage tracking. Dropped by default\n * so local dev never writes to the target's analytics.\n */\nexport function isEventsPath(path: string): boolean {\n const bare = path.split(\"?\")[0] ?? path;\n return bare.startsWith(\"/api/customer-apps/\") && bare.endsWith(\"/events\");\n}\n\n/**\n * Auth / session endpoints. These must reach the backend UNAUTHENTICATED to\n * establish a session, so the proxy never injects the dev bearer on them and\n * never holds them behind `--allow-writes`.\n */\nexport function isAuthPath(path: string): boolean {\n const bare = path.split(\"?\")[0] ?? path;\n return bare.startsWith(\"/api/auth/\") || bare === \"/api/user\";\n}\n\n/**\n * Whether a request should be HELD.\n *\n * ALLOWLIST, NOT DENYLIST: any mutating method is held EXCEPT the two\n * POST-but-read data-plane endpoints, which carry their filter in the body.\n * GET/HEAD are never mutating; events and auth have their own handling.\n */\nexport function isWritePath(method: string, path: string): boolean {\n const mutating = [\"POST\", \"PUT\", \"PATCH\", \"DELETE\"].includes(method.toUpperCase());\n if (!mutating || isEventsPath(path) || isAuthPath(path)) return false;\n const bare = path.split(\"?\")[0] ?? path;\n const readPost =\n method.toUpperCase() === \"POST\" &&\n (bare.endsWith(\"/query\") || bare.endsWith(\"/semantic-query\"));\n return !readPost;\n}\n\n/**\n * Make a cloud backend's `Set-Cookie` storable by a browser on `localhost`.\n *\n * The standard dev-proxy rewrite: strip `Domain=` (which would scope the\n * cookie to the cloud host) and `Secure` (which a plain-http localhost will\n * not store), and relax `SameSite=None`, which browsers only honour together\n * with `Secure`.\n */\nexport function rewriteSetCookie(value: string): string {\n return value\n .split(\";\")\n .map((part) => part.trim())\n .filter((part) => !/^domain=/i.test(part) && !/^secure$/i.test(part))\n .map((part) => (/^samesite=none$/i.test(part) ? \"SameSite=Lax\" : part))\n .join(\"; \");\n}\n\n/**\n * Headers to send upstream.\n *\n * The browser's own auth is forwarded transparently so a signed-in session\n * works; `Origin` and `Referer` go too, because the backend derives its base\n * URL from them and an OAuth `redirect_uri` that does not match what the\n * provider issued the code for is a 401 at sign-in.\n *\n * The dev bearer is injected ONLY as a fallback — when the request carries no\n * auth of its own and is not an auth endpoint — so it can never override a\n * real session or break login.\n */\nexport function buildRequestHeaders(\n incoming: NodeJS.Dict<string | string[]>,\n token: string | undefined,\n path: string\n): Record<string, string> {\n const headers: Record<string, string> = {};\n for (const name of [\"content-type\", \"accept\", \"cookie\", \"authorization\", \"origin\", \"referer\"]) {\n const value = incoming[name];\n if (typeof value === \"string\") headers[name] = value;\n else if (Array.isArray(value) && value[0]) headers[name] = value[0];\n }\n const hasAuth = \"cookie\" in headers || \"authorization\" in headers;\n if (!hasAuth && !isAuthPath(path) && token) headers.authorization = `Bearer ${token}`;\n return headers;\n}\n\n/** Read a request body, refusing anything past the cap. */\nfunction readBody(req: IncomingMessage): Promise<Buffer> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n let size = 0;\n req.on(\"data\", (chunk: Buffer) => {\n size += chunk.length;\n if (size > MAX_REQUEST_BODY) {\n reject(new Error(`request body over ${MAX_REQUEST_BODY} bytes`));\n req.destroy();\n return;\n }\n chunks.push(chunk);\n });\n req.on(\"end\", () => resolve(Buffer.concat(chunks)));\n req.on(\"error\", reject);\n });\n}\n\nfunction json(res: ServerResponse, status: number, body: unknown): void {\n const payload = JSON.stringify(body);\n res.writeHead(status, {\n \"content-type\": \"application/json\",\n \"content-length\": Buffer.byteLength(payload)\n });\n res.end(payload);\n}\n\n/**\n * Is this target a production deployment?\n *\n * A PURE PREDICATE, and exported, because it is the one guardrail this port\n * adds on top of the Rust — so it has no prior art to lean on, and a regex is\n * the kind of thing that goes wrong quietly. Testing it through `runProxy`\n * would mean starting a server that never exits for every negative case.\n *\n * Matched on the HOST, after `parseEnvUrl` has already canonicalised an org\n * subdomain (`acme.oxygen-hq.com`) to the product host — so naming a customer's\n * own subdomain is refused too.\n *\n * NARROWER THAN THE RUST IN ONE CASE, deliberately: `proxy.rs` also refuses on\n * the env NAME, so a manifest mapping `production` to a non-prod URL is refused\n * there and allowed here. Here the URL is the truth — an `oxy-app.json` that\n * deliberately points `production` somewhere else is a statement about where\n * production is, and refusing it would make the manifest unusable.\n */\nexport function isProductionTarget(target: string): boolean {\n let host: string;\n try {\n host = new URL(target).hostname.toLowerCase();\n } catch {\n // Unparseable: treat as production. The guard exists to prevent an\n // accident, and \"I could not tell\" is not a reason to allow one.\n return true;\n }\n // The apex is matched explicitly: `\"oxygen-hq.com\".endsWith(\".oxygen-hq.com\")`\n // is false, and the regex this replaced did catch the apex. `app.` needs no\n // arm of its own — the suffix already subsumes it.\n return host === \"oxygen-hq.com\" || host.endsWith(\".oxygen-hq.com\");\n}\n\nexport async function runProxy(ctx: Context, flags: ProxyFlags): Promise<void> {\n const target = ctx.target();\n const port = Number(flags.port ?? 3000);\n if (!Number.isInteger(port) || port < 1 || port > 65_535) {\n throw new CliError(`invalid --port ${flags.port}`, { code: ExitCode.USAGE });\n }\n\n // A production target is confirmed, not assumed. The guardrails hold writes\n // by default, but `--allow-writes` plus a forgotten `--env` is a laptop\n // writing to a customer's live data.\n if (isProductionTarget(target) && !flags.yes) {\n throw new CliError(`refusing to proxy to a production target (${target}) without --yes`, {\n code: ExitCode.REFUSED,\n hint: \"oxyc proxy --env dev — or pass --yes if production is really what you want\"\n });\n }\n\n const token = ctx.maybeBearer();\n if (!token) {\n log.warn(`no cached token for ${target} — only requests carrying their own auth will work`);\n log.hint(`oxyc login --env ${ctx.flags.env ?? \"production\"}`);\n }\n\n const server = createServer(async (req, res) => {\n const path = req.url ?? \"/\";\n const method = (req.method ?? \"GET\").toUpperCase();\n\n if (!flags.allowEvents && isEventsPath(path)) {\n // DROPPED, and answered 204 rather than refused: the SDK's tracking call\n // is fire-and-forget, and a 4xx would surface in the app's console as a\n // bug that is not one.\n log.info(`${out.dim(\"dropped\")} ${method} ${path} (tracking; --allow-events to forward)`);\n res.writeHead(204).end();\n return;\n }\n\n if (!flags.allowWrites && isWritePath(method, path)) {\n // HELD with a 403 and a body that says WHY. A silent 200 would let a\n // dev believe a write landed in the cloud when nothing happened.\n log.warn(`held ${method} ${path} (side-effecting; --allow-writes to forward)`);\n // 409, NOT 403, and the status is chosen to MISS the auth-shaped ones.\n // `@oxy-hq/sdk`'s error interpreter matches `^403:` as its catch-all and\n // renders \"Access denied — check the oxy server logs\", which discards\n // the body written here specifically to say why and sends the developer\n // to a server's logs for something their own laptop did. 409 has no\n // branch there, so the message survives. The Rust original returns 409\n // for the same reason.\n json(res, 409, {\n error: \"held_by_oxyc_proxy\",\n message: `oxyc proxy holds side-effecting calls by default. Re-run with --allow-writes to forward ${method} ${path}.`\n });\n return;\n }\n\n let body: Buffer;\n try {\n body = await readBody(req);\n } catch (cause) {\n json(res, 413, { error: \"request_too_large\", message: (cause as Error).message });\n return;\n }\n\n try {\n const upstream = await fetch(`${target.replace(/\\/+$/, \"\")}${path}`, {\n method,\n headers: buildRequestHeaders(req.headers, token, path),\n body: method === \"GET\" || method === \"HEAD\" ? undefined : body,\n redirect: \"manual\"\n });\n\n const outHeaders: Record<string, string | string[]> = {};\n upstream.headers.forEach((value, name) => {\n if (HOP_BY_HOP.has(name.toLowerCase())) return;\n outHeaders[name] = name.toLowerCase() === \"set-cookie\" ? rewriteSetCookie(value) : value;\n });\n // `getSetCookie` keeps multiple cookies separate; the iteration above\n // collapses them, and a login that sets two would lose one.\n const cookies = upstream.headers.getSetCookie?.() ?? [];\n if (cookies.length > 0) outHeaders[\"set-cookie\"] = cookies.map(rewriteSetCookie);\n\n res.writeHead(upstream.status, outHeaders);\n if (upstream.body) {\n // Streamed, not buffered: responses are the large payloads here, and\n // an SSE stream buffered to completion never arrives at all.\n for await (const chunk of upstream.body as unknown as AsyncIterable<Uint8Array>) {\n res.write(chunk);\n }\n }\n res.end();\n log.info(`${upstream.status} ${method} ${path}`);\n } catch (cause) {\n log.error(`${method} ${path} failed: ${(cause as Error).message}`);\n json(res, 502, { error: \"upstream_unreachable\", message: (cause as Error).message });\n }\n });\n\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", (cause: NodeJS.ErrnoException) => {\n reject(\n cause.code === \"EADDRINUSE\"\n ? new CliError(`port ${port} is already in use`, {\n code: ExitCode.UNAVAILABLE,\n hint: \"a local `oxy serve` is probably on it — stop it, or pass --port\"\n })\n : cause\n );\n });\n server.listen(port, \"127.0.0.1\", resolve);\n });\n\n process.stderr.write(\n `${out.green(`oxyc proxy → ${target}`)}\\n` +\n ` listening on http://127.0.0.1:${port}\\n` +\n ` writes ${flags.allowWrites ? out.yellow(\"FORWARDED\") : \"held\"}` +\n ` · events ${flags.allowEvents ? out.yellow(\"FORWARDED\") : \"dropped\"}\\n`\n );\n\n // Runs until interrupted; the process is the server.\n await new Promise<void>(() => {});\n}\n","/**\n * Registering a customer is TAGGING A REPO. This file is the only thing that\n * writes that tag.\n *\n * `customers.ts` answers \"who are the customers\" by reading the topic; this is\n * the other half. The topic name is NOT redefined here — it comes from\n * `customersTopic()`, so the reader and the writer cannot disagree about what\n * registration means.\n *\n * THE RULE THIS FILE IS SHAPED BY, inverted from `customers.ts`'s:\n *\n * A 404 is an answer. Offline, 5xx, rate-limited, an expired token, or a\n * private repo you cannot see are INCONCLUSIVE — never \"missing\".\n *\n * It matters more here than anywhere else because the caller ACTS on it:\n * `import` refuses a repo that does not exist, and `new` CREATES one it\n * believes does not exist. Reading \"GitHub is having a moment\" as \"no such\n * repo\" is how `new` clobbers a live customer's repository.\n */\n\nimport { CliError, ExitCode } from \"../util/errors.js\";\nimport { customersTopic, invalidateCache } from \"./customers.js\";\nimport { ghJson, ghRaw } from \"./gh.js\";\n\n/** What we could learn about a repo's existence. */\nexport type RepoExistence =\n | { kind: \"exists\"; topics: string[]; description: string; isPrivate: boolean }\n | { kind: \"absent\" }\n | { kind: \"inconclusive\"; why: string };\n\n/**\n * Does `<org>/<name>` exist, and what is on it?\n *\n * The three-way return is the whole design. A boolean would force every caller\n * to pick a side for \"we could not tell\", and both sides are wrong: treating\n * it as present blocks a legitimate `new`, treating it as absent lets `new`\n * create over a repo that is merely invisible right now.\n */\nexport function inspectRepo(slug: string): RepoExistence {\n const result = ghRaw([\n \"repo\",\n \"view\",\n slug,\n \"--json\",\n \"name,description,isPrivate,repositoryTopics\"\n ]);\n if (result.status === 0) {\n try {\n const parsed = JSON.parse(result.stdout) as {\n description?: string;\n isPrivate?: boolean;\n repositoryTopics?: Array<{ name?: string }> | null;\n };\n return {\n kind: \"exists\",\n topics: (parsed.repositoryTopics ?? []).map((t) => t.name ?? \"\").filter(Boolean),\n description: parsed.description ?? \"\",\n isPrivate: Boolean(parsed.isPrivate)\n };\n } catch {\n return { kind: \"inconclusive\", why: \"gh returned unparsable JSON for the repo\" };\n }\n }\n\n const stderr = result.stderr.toLowerCase();\n // Only these two spellings are a real 404. Everything else — including\n // \"HTTP 403\" on a private repo the token cannot see — is inconclusive.\n if (stderr.includes(\"could not resolve to a repository\") || stderr.includes(\"404\")) {\n return { kind: \"absent\" };\n }\n return { kind: \"inconclusive\", why: result.stderr.trim() || `gh exited ${result.status}` };\n}\n\n/** Turn an inconclusive answer into the refusal it has to be. */\nexport function refuseInconclusive(slug: string, why: string): CliError {\n return new CliError(`could not determine whether ${slug} exists`, {\n code: ExitCode.REFUSED,\n detail: why,\n hint: \"retry once GitHub is reachable — this is NOT 'the repo does not exist'\"\n });\n}\n\n/** Is this repo registered as a customer workspace? */\nexport function isRegistered(slug: string): boolean {\n const repo = inspectRepo(slug);\n if (repo.kind === \"inconclusive\") throw refuseInconclusive(slug, repo.why);\n if (repo.kind === \"absent\") return false;\n return repo.topics.includes(customersTopic());\n}\n\n/**\n * Add the topic. Idempotent, because `gh repo edit --add-topic` is.\n *\n * The cache is invalidated on the way out rather than left to expire: the\n * whole point of `import` is that the next command sees the customer, and an\n * hour of \"unknown customer\" after a successful registration reads as a\n * failed registration.\n */\nexport function addTopic(slug: string): void {\n const result = ghRaw([\"repo\", \"edit\", slug, \"--add-topic\", customersTopic()]);\n if (result.status !== 0) {\n throw new CliError(`could not tag ${slug} as a customer workspace`, {\n code: ExitCode.FAILURE,\n detail: result.stderr.trim() || undefined,\n hint: \"you need admin rights on the repo to edit its topics\"\n });\n }\n invalidateCache();\n}\n\n/** Drop the topic. The REPO is never deleted — see `oxyc remove`. */\nexport function removeTopic(slug: string): void {\n const result = ghRaw([\"repo\", \"edit\", slug, \"--remove-topic\", customersTopic()]);\n if (result.status !== 0) {\n throw new CliError(`could not untag ${slug}`, {\n code: ExitCode.FAILURE,\n detail: result.stderr.trim() || undefined\n });\n }\n invalidateCache();\n}\n\n/** Set the repo description, which is what `oxyc list` shows as a display name. */\nexport function setDescription(slug: string, description: string): void {\n const result = ghRaw([\"repo\", \"edit\", slug, \"--description\", description]);\n if (result.status !== 0) {\n throw new CliError(`could not set the description on ${slug}`, {\n code: ExitCode.FAILURE,\n detail: result.stderr.trim() || undefined\n });\n }\n invalidateCache();\n}\n\n/**\n * Create the repo, already tagged and private.\n *\n * Private is not a default worth making configurable: these repos hold a\n * customer's semantic model and their memory facts. A public one is a\n * disclosure, and the flag to make it public would exist only to be set by\n * accident.\n */\nexport function createRepo(slug: string, description: string): void {\n const args = [\"repo\", \"create\", slug, \"--private\", \"--description\", description];\n const result = ghRaw(args);\n if (result.status !== 0) {\n throw new CliError(`could not create ${slug}`, {\n code: ExitCode.FAILURE,\n detail: result.stderr.trim() || undefined\n });\n }\n addTopic(slug);\n}\n\n/** The default branch, for the commands that must not act on a detached HEAD. */\nexport function defaultBranch(slug: string): string | undefined {\n try {\n const parsed = ghJson<{ defaultBranchRef?: { name?: string } }>(\n [\"repo\", \"view\", slug, \"--json\", \"defaultBranchRef\"],\n `${slug}'s default branch`\n );\n return parsed.defaultBranchRef?.name;\n } catch {\n return undefined;\n }\n}\n","/**\n * `.oxyc-managed` — who owns each file in a customer repo, and which of the\n * repo's two trees each file describes.\n *\n * THE MANIFEST IS THE WHOLE AUTHORITY. Nothing in the sync or adopt engines\n * second-guesses it, and a file wrongly classified `managed` is DATA LOSS in a\n * live customer repo.\n *\n * TWO INDEPENDENT AXES, not five roles:\n *\n * managed / scaffold / mixed who owns the bytes\n * scope-repo / scope-workspace which tree the file describes\n *\n * They are independent because `package.json` is `mixed` AND repo-scoped while\n * `config.yml` is `scaffold` AND workspace-scoped — a file that could answer\n * only one question would lose the other. Each family has its OWN reader with\n * its own allowlist, so a line from one is invisible to the other and a typo\n * in either (`manged`, `scope-wrokspace`) falls to that family's default and\n * fails the completeness test rather than quietly classifying a file under a\n * word nothing recognises.\n *\n * THE TWO DEFAULTS POINT OPPOSITE WAYS, and that is the most important thing\n * in this file:\n *\n * role defaults to `unmatched` — the customer's, never touch. A wrong role\n * costs data loss, so forgetting one can only ever make a sync do\n * LESS. Most of a real repo is unmatched by construction: views,\n * topics, pipelines, an app bundle, a lockfile, memory facts.\n *\n * scope defaults to `repo` — always in scope, i.e. the LOUD direction. Scope\n * cannot cost data (it never widens what a role permits), so what it\n * trades is noise against silence. Forget a `scope-workspace` line and\n * a file gets reported on every run until somebody writes it; forget a\n * `scope-repo` line under the opposite default and the file can never\n * arrive and nothing anywhere says so.\n */\n\nimport { readFileSync } from \"node:fs\";\n\nimport { CliError, ExitCode } from \"../util/errors.js\";\n\n/** Who owns a file's bytes. */\nexport type Role = \"managed\" | \"scaffold\" | \"mixed\" | \"unmatched\";\n\n/** Which of the repo's two trees a file describes. */\nexport type Scope = \"repo\" | \"workspace\";\n\ninterface Rule {\n pattern: string;\n value: string;\n}\n\nexport interface Manifest {\n roles: Rule[];\n scopes: Rule[];\n}\n\nconst ROLE_DIRECTIVES = new Set([\"managed\", \"scaffold\", \"mixed\"]);\nconst SCOPE_DIRECTIVES = new Set([\"scope-repo\", \"scope-workspace\"]);\n\n/**\n * Parse `.oxyc-managed`.\n *\n * An unrecognised directive is IGNORED rather than rejected, which sounds\n * careless and is the safe reading: each family has its own allowlist, so a\n * typo lands in neither and the file falls to both defaults — `unmatched`\n * (never written) and `scope-repo` (always reported). The completeness test is\n * what catches it, loudly, rather than a parse error that would block every\n * command over one bad line.\n */\nexport function parseManifest(text: string): Manifest {\n const roles: Rule[] = [];\n const scopes: Rule[] = [];\n\n for (const raw of text.split(\"\\n\")) {\n const line = raw.trim();\n if (!line || line.startsWith(\"#\")) continue;\n const [directive, ...rest] = line.split(/\\s+/);\n const pattern = rest.join(\" \").trim();\n if (!directive || !pattern) continue;\n if (ROLE_DIRECTIVES.has(directive)) roles.push({ pattern, value: directive });\n else if (SCOPE_DIRECTIVES.has(directive)) {\n scopes.push({ pattern, value: directive === \"scope-workspace\" ? \"workspace\" : \"repo\" });\n }\n }\n\n return { roles, scopes };\n}\n\n/** Read the manifest that ships with the template. */\nexport function loadManifest(path: string): Manifest {\n try {\n return parseManifest(readFileSync(path, \"utf8\"));\n } catch (cause) {\n throw new CliError(`could not read the ownership manifest at ${path}`, {\n code: ExitCode.FAILURE,\n detail: (cause as Error).message,\n hint: \"without it, nothing can be classified — and an unclassified file is never written\"\n });\n }\n}\n\n/**\n * Glob match with shell `case` semantics, where `*` SPANS `/`.\n *\n * That is the bash tooling's behaviour and the manifest is written against it:\n * `.github/workflows/*` is meant to cover any depth beneath, and `*.gitkeep`\n * every placeholder wherever it sits. A `minimatch`-style `*` that stopped at\n * a slash would silently unmatch rules the manifest relies on — turning\n * `managed` files into `unmatched` ones, which fails safe but stops the sync\n * doing its job.\n */\nexport function globMatch(pattern: string, path: string): boolean {\n const escaped = pattern.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const regex = new RegExp(`^${escaped.replace(/\\*/g, \".*\").replace(/\\?/g, \".\")}$`);\n return regex.test(path);\n}\n\n/**\n * The role for a repo-relative path.\n *\n * LAST MATCHING RULE WINS, so a later, narrower line can override a broader\n * one — the same way the file reads top to bottom.\n */\nexport function roleFor(manifest: Manifest, path: string): Role {\n let role: Role = \"unmatched\";\n for (const rule of manifest.roles) {\n if (globMatch(rule.pattern, path)) role = rule.value as Role;\n }\n return role;\n}\n\n/** The scope for a repo-relative path. Defaults to `repo` — the loud direction. */\nexport function scopeFor(manifest: Manifest, path: string): Scope {\n let scope: Scope = \"repo\";\n for (const rule of manifest.scopes) {\n if (globMatch(rule.pattern, path)) scope = rule.value as Scope;\n }\n return scope;\n}\n\n/**\n * Is this template file in scope for a repo whose workspace is `workspaceRel`?\n *\n * A workspace-scoped file describes the Oxy workspace. In a repo that IS its\n * workspace (`.`) that is the root, so everything is in scope. In a repo that\n * keeps its workspace in `oxy/`, a workspace-scoped file describes nothing at\n * the root — installing it there would build a second, half-populated\n * workspace beside the real one.\n */\nexport function inScope(\n manifest: Manifest,\n path: string,\n workspaceRel: string | undefined\n): boolean {\n if (scopeFor(manifest, path) === \"repo\") return true;\n return workspaceRel === \".\" || workspaceRel === undefined;\n}\n\n/**\n * Every template path that neither family classifies.\n *\n * Backs the completeness check: the manifest must answer BOTH questions for\n * every file the template ships, so that the two defaults are unreachable from\n * a healthy manifest and govern only one that is already failing this test.\n */\nexport function unclassified(\n manifest: Manifest,\n templatePaths: string[]\n): {\n missingRole: string[];\n missingScope: string[];\n} {\n const missingRole: string[] = [];\n const missingScope: string[] = [];\n for (const path of templatePaths) {\n if (!manifest.roles.some((r) => globMatch(r.pattern, path))) missingRole.push(path);\n if (!manifest.scopes.some((r) => globMatch(r.pattern, path))) missingScope.push(path);\n }\n return { missingRole, missingScope };\n}\n","/**\n * Rendering the template, and the provenance stamp that records what a repo\n * was rendered FROM.\n *\n * A SYNC IS A RE-RENDER, NOT A COPY, and both halves of that had to be learned\n * by running against a real customer repo:\n *\n * 1. Template files carry `__NAME__`, `__SLUG__` and `__WORKSPACE__`, so a\n * plain copy writes the literal placeholder into a live repo.\n * 2. The COMPARISON must substitute too. Diffing raw template bytes reports\n * every placeholder-bearing file as drifted on every run — a report\n * people stop reading, which costs more than not having one.\n */\n\nimport { existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from \"node:fs\";\nimport { dirname, join, relative } from \"node:path\";\n\nimport { CliError, ExitCode } from \"../util/errors.js\";\nimport { currentBranch, headSha, isRepo, workingTreeState } from \"../util/git.js\";\n\n/** The file recording what a repo was rendered from. */\nexport const STAMP_FILE = \".oxyc-template.json\";\n\n/** The provenance value that means \"oxyc did NOT render this tree\". */\nexport const PROVENANCE_IMPORTED = \"imported\";\n\nexport interface Substitutions {\n slug: string;\n name: string;\n /** The workspace path relative to the repo root. `.` for a root workspace. */\n workspace: string;\n}\n\n/**\n * Substitute placeholders in file CONTENTS — never in paths.\n *\n * A file with no placeholder keeps its EXACT bytes, which is why the\n * comparison is `substituted === original` rather than an unconditional\n * rewrite: an empty `.gitkeep` must stay empty rather than becoming a stray\n * newline, and a byte-identical file must stay byte-identical so the drift\n * report does not invent a difference.\n */\nexport function substitute(content: string, subs: Substitutions): string {\n const out = content\n .replaceAll(\"__SLUG__\", subs.slug)\n .replaceAll(\"__NAME__\", subs.name)\n .replaceAll(\"__WORKSPACE__\", subs.workspace);\n return out;\n}\n\n/**\n * The two directions of one rename: the template ships `_gitignore`, a repo\n * gets `.gitignore`.\n *\n * The underscore is not a style choice. npm strips a file literally named\n * `.gitignore` out of a published tarball, so a template shipping one works\n * perfectly from a checkout and arrives on npm with no ignore rules at all —\n * which commits `node_modules/` and `out/` on the customer's first\n * `git add -A`. `sdk/create-oxy-app`'s templates use the same convention for\n * the same reason.\n *\n * Both directions live here, next to each other, because they must stay exact\n * inverses: a walk that renames one way and a lookup that renames the other\n * are how a file gets classified under a path it is never installed at.\n */\nexport function repoPathFor(templateRel: string): string {\n return templateRel.replace(/(^|\\/)_gitignore$/, \"$1.gitignore\");\n}\n\n/** The inverse of [`repoPathFor`]. */\nexport function templateSourceFor(repoRel: string): string {\n return repoRel.replace(/(^|\\/)\\.gitignore$/, \"$1_gitignore\");\n}\n\n/** Every file under `root`, as paths relative to it. Directories are skipped. */\nexport function walkFiles(root: string, prefix = \"\"): string[] {\n const out: string[] = [];\n let entries: import(\"node:fs\").Dirent[];\n try {\n entries = readdirSync(join(root, prefix), { withFileTypes: true });\n } catch {\n return out;\n }\n for (const entry of entries) {\n const rel = prefix ? `${prefix}/${entry.name}` : entry.name;\n // `.git` is the one directory a template tree must never carry into a\n // render — it would make the rendered repo a clone of the tooling.\n if (entry.name === \".git\") continue;\n if (entry.isDirectory()) out.push(...walkFiles(root, rel));\n else out.push(rel);\n }\n return out.sort();\n}\n\n/**\n * Render `src` into `dest`, substituting as it goes.\n *\n * REFUSES AN EXISTING DESTINATION OUTRIGHT, so a partial render over somebody's\n * work is not a state this can reach.\n */\nexport function renderTemplate(src: string, dest: string, subs: Substitutions): string[] {\n if (existsSync(dest) && readdirSync(dest).length > 0) {\n throw new CliError(`${dest} already exists and is not empty`, {\n code: ExitCode.REFUSED,\n hint: \"rendering into it could overwrite work — move it aside, or pick another destination\"\n });\n }\n\n const written: string[] = [];\n for (const rel of walkFiles(src)) {\n const from = join(src, rel);\n const target = repoPathFor(rel);\n const to = join(dest, target);\n mkdirSync(dirname(to), { recursive: true });\n writeFileSync(to, substitute(readFileSync(from, \"utf8\"), subs), {\n mode: statSync(from).mode & 0o777\n });\n written.push(target);\n }\n return written;\n}\n\n/** The provenance document. `syncable` is DERIVED, never passed in. */\nexport interface Stamp {\n _comment: string;\n stamp_version: 1;\n generated_by: string;\n rendered_at: string | null;\n provenance: string;\n /** A tree oxyc rendered may be synced; an imported one may not. */\n syncable: boolean;\n source_commit: string | null;\n source_branch: string | null;\n source_dirty: boolean | null;\n}\n\nconst STAMP_COMMENT =\n \"Provenance for this workspace: what oxyc rendered it from. Written by `oxyc new` \" +\n \"from the customer-tooling template; read later by `oxyc update` to report how far \" +\n \"this repo has drifted from that template. Machine-written — edit the repo, not this file.\";\n\n/**\n * Build the stamp document.\n *\n * `syncable` is derived here so there is exactly ONE rule and no caller can\n * write a document whose two halves disagree. Every unanswerable question is\n * written down as `null` rather than guessed at.\n */\nexport function buildStamp(input: {\n sha?: string;\n branch?: string;\n dirty?: boolean;\n provenance: string;\n renderedAt?: string;\n by: string;\n}): Stamp {\n return {\n _comment: STAMP_COMMENT,\n stamp_version: 1,\n generated_by: input.by,\n rendered_at: input.renderedAt ?? null,\n provenance: input.provenance,\n syncable: input.provenance !== PROVENANCE_IMPORTED,\n source_commit: input.sha ?? null,\n source_branch: input.branch ?? null,\n source_dirty: input.dirty ?? null\n };\n}\n\n/**\n * Write the stamp into `dest`, recording the state of the template tree `src`.\n *\n * THREE STATES, and only three, so a reader never has to interpret:\n *\n * clean `source_commit` describes the bytes that were copied\n * dirty the commit is known but the template tree had uncommitted\n * changes, so the rendered bytes are NOT that commit's\n * unknown no commit could be determined at all\n *\n * `dirty` exists because the alternative is a lie: a stamp naming a commit\n * whose contents were not what got rendered makes a later drift report\n * confidently wrong, which is worse than no report. A drift check must refuse\n * to compute against anything but `clean`.\n *\n * NEVER FAILS THE SCAFFOLD. A customer's repo matters more than its\n * provenance, so the file is written either way.\n */\nexport function writeStamp(dest: string, src: string, by: string, renderedAt: string): Stamp {\n let sha: string | undefined;\n let branch: string | undefined;\n let dirty: boolean | undefined;\n\n // `git` may be absent, and `src` may be an ordinary directory that was never\n // a repository — a fixture, an unpacked tarball, a clone whose `.git` was\n // stripped. Both are ordinary here, not errors.\n try {\n if (isRepo(src)) {\n sha = headSha(src);\n if (sha) {\n branch = currentBranch(src);\n const state = workingTreeState(src);\n dirty = state.dirty || state.untracked.length > 0;\n }\n }\n } catch {\n // Leaves everything `unknown`, which is the honest answer.\n }\n\n const stamp = buildStamp({\n sha,\n branch,\n dirty,\n provenance: sha ? (dirty ? \"dirty\" : \"clean\") : \"unknown\",\n renderedAt,\n by\n });\n try {\n writeFileSync(join(dest, STAMP_FILE), `${JSON.stringify(stamp, null, 2)}\\n`);\n } catch {\n // Provenance is a nicety; the repo is the product.\n }\n return stamp;\n}\n\n/** Read a repo's stamp, or `undefined` when it has none or it is unreadable. */\nexport function readStamp(repoDir: string): Stamp | undefined {\n try {\n return JSON.parse(readFileSync(join(repoDir, STAMP_FILE), \"utf8\")) as Stamp;\n } catch {\n return undefined;\n }\n}\n\n/**\n * May `oxyc update --apply` rewrite files in this repo?\n *\n * The proof is the stamp: no stamp, or one saying `provenance: \"imported\"`,\n * means NO. Dropping our workflows beside somebody else's four is the failure\n * the manifest exists to prevent, and `oxyc adopt` is the one explicit act\n * that converts \"refused forever\" into \"syncable\".\n */\nexport function isSyncable(repoDir: string): boolean {\n const stamp = readStamp(repoDir);\n if (!stamp) return false;\n if (stamp.provenance === PROVENANCE_IMPORTED) return false;\n return stamp.syncable !== false;\n}\n\n/** Which command wrote the stamp — the one fact that tells `new` and `adopt` apart. */\nexport function generatedBy(repoDir: string): string | undefined {\n return readStamp(repoDir)?.generated_by;\n}\n\n/** Relative path helper shared by the sync and adopt walks. */\nexport function relativeTo(root: string, path: string): string {\n return relative(root, path).split(\"\\\\\").join(\"/\");\n}\n","/**\n * `oxyc adopt <customer>` — install the managed files an IMPORTED repo lacks,\n * then stamp it, so `oxyc update` works on it from then on.\n *\n * THE ONE-WAY DOOR THIS OPENS. `oxyc update` may only rewrite a repo it can\n * prove it wrote, and the proof is the stamp. Every imported repo has none, so\n * every imported repo is refused forever — correct, and also terminal: the\n * live imported repos are each missing eight managed files and under that rule\n * could never receive the template's CI or dev tooling at all. `doctor` names\n * the gap; this closes it.\n *\n * A SEPARATE COMMAND AND NOT A FLAG ON `update`: `--adopt` would sit one\n * keystroke from the flag people type on a repo oxyc really did scaffold, and\n * its whole effect is to make a repo writable by a command that then writes to\n * it without asking.\n *\n * WHAT IT MAY TOUCH, and the argument is entirely the manifest's:\n *\n * managed YES. CI workflows, the scripts they call, `.gitattributes`, the\n * stamp. Every one is repo-relative and belongs at the ROOT in\n * both layouts, so installing them cannot move or mirror the\n * workspace.\n * scaffold NO. Those are the WORKSPACE's files, and an imported repo has\n * its own inside `oxy/`, written before oxyc ever saw the repo.\n * mixed ONLY WHEN THE REPO DOES NOT HAVE IT — see `mixedPlan` below.\n * unmatched NO, by construction: the walk is over the TEMPLATE.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nimport { CliError, ExitCode } from \"../util/errors.js\";\nimport { inScope, type Manifest, roleFor } from \"./manifest.js\";\nimport { generatedBy, readStamp, repoPathFor, type Substitutions, walkFiles } from \"./render.js\";\n\n/** The command name recorded in a stamp this writes. */\nexport const ADOPT_GENERATED_BY = \"oxyc adopt\";\n/** The command name `oxyc new` records — the value that tells the two apart. */\nexport const NEW_GENERATED_BY = \"oxyc new\";\n\nexport interface AdoptPlan {\n /** Managed files the repo lacks — installed by `--apply`. */\n install: string[];\n /** Mixed files the repo lacks — also installed; see the note below. */\n installMixed: string[];\n /** Managed paths that already exist and are NOT this command's own output. */\n collisions: string[];\n /** Managed files an earlier run of THIS command already landed. */\n alreadyHere: string[];\n /** Skipped because they describe a workspace that lives elsewhere. */\n outOfScope: string[];\n}\n\nexport interface AdoptOptions {\n templateDir: string;\n repoDir: string;\n manifest: Manifest;\n subs: Substitutions;\n workspaceRel: string | undefined;\n}\n\n/**\n * Decide whether this repo may be adopted at all.\n *\n * IT FINISHES ITS OWN WORK. A repo whose stamp says `oxyc adopt` wrote it is\n * not somebody else's repo to refuse — it is THIS command's output, and a file\n * still missing from it is a file only this command installs, since `update`\n * reports a missing mixed file and never restores it. An adopt that refused\n * its own output is how a live repo ended up holding `scripts/dev.sh` and no\n * `package.json`, reachable by neither command.\n */\nexport function assertAdoptable(repoDir: string): { completing: boolean } {\n const stamp = readStamp(repoDir);\n if (!stamp) return { completing: false };\n\n const by = generatedBy(repoDir);\n if (by === ADOPT_GENERATED_BY) return { completing: true };\n\n if (by === NEW_GENERATED_BY) {\n throw new CliError(`${repoDir} was scaffolded by \\`oxyc new\\``, {\n code: ExitCode.REFUSED,\n hint: \"`oxyc update` is its path — adopt is for a repo oxyc did not create\"\n });\n }\n // A hand-written `provenance: \"imported\"` outranks everything: somebody\n // wrote that down on purpose.\n throw new CliError(`${repoDir} already carries a stamp oxyc did not write`, {\n code: ExitCode.REFUSED,\n detail: `generated_by: ${by ?? \"(absent)\"}, provenance: ${stamp.provenance}`,\n hint: \"that was recorded deliberately — remove or correct the stamp if it is wrong\"\n });\n}\n\n/**\n * What adopting would install, and what stands in the way.\n *\n * Reports and decides nothing; the caller does both.\n */\nexport function planAdopt(opts: AdoptOptions, completing: boolean): AdoptPlan {\n const plan: AdoptPlan = {\n install: [],\n installMixed: [],\n collisions: [],\n alreadyHere: [],\n outOfScope: []\n };\n\n for (const templateRel of walkFiles(opts.templateDir)) {\n const repoRel = repoPathFor(templateRel);\n\n if (!inScope(opts.manifest, repoRel, opts.workspaceRel)) {\n plan.outOfScope.push(repoRel);\n continue;\n }\n\n const role = roleFor(opts.manifest, repoRel);\n const present = existsSync(join(opts.repoDir, repoRel));\n\n if (role === \"managed\") {\n if (!present) {\n plan.install.push(repoRel);\n } else if (completing) {\n // Not a collision: the claim is already written and the file at that\n // path is one adopt itself installed. Refusing here would refuse the\n // completing run for exactly the files the earlier run got right.\n plan.alreadyHere.push(repoRel);\n } else {\n plan.collisions.push(repoRel);\n }\n continue;\n }\n\n // A MIXED file that is PRESENT is never touched: part of it is the\n // customer's and overwriting it destroys their half. A mixed file that is\n // ABSENT has no half of theirs to protect, and withholding it strands the\n // managed files it pairs with — `scripts/dev.sh` installed with no\n // `package.json` to carry the `dev` script that runs it is a tool with no\n // handle. PER FILE, not per role.\n //\n // SCOPED TO ADOPT, deliberately. `oxyc update` keeps REPORTING a missing\n // mixed file rather than restoring it: a scaffolded repo always had both\n // halves, so an absence there is a deletion somebody meant, and update\n // runs over and over where adopt is a one-time act typed on purpose.\n if (role === \"mixed\" && !present) plan.installMixed.push(repoRel);\n }\n\n return plan;\n}\n\n/**\n * A collision refuses the WHOLE adopt rather than installing the rest.\n *\n * Adopting does not merely copy files — it writes a CLAIM: this repo is a\n * render of the template, and every managed path in it is oxyc's to rewrite.\n * `oxyc update --apply` acts on that claim silently. So a partial adopt does\n * not leave the customer's file untouched; it leaves it MARKED, sitting at a\n * managed path in a repo that now reports itself syncable, for the next\n * `update --apply` — run by someone who was not here — to destroy without\n * asking.\n *\n * That is data loss deferred by one command, and deferred loss is worse than\n * immediate refusal precisely because nobody is watching when it lands. The\n * refusal is completely recoverable: rename or delete their file, or write a\n * manifest rule saying it is theirs, and run adopt again.\n *\n * The alternatives are worse in the same direction. Installing the rest with a\n * warning relies on somebody reading a warning about a consequence that\n * arrives weeks later. Installing the rest and withholding the stamp leaves a\n * repo carrying our CI that no command can ever sync — the exact state adopt\n * exists to end. Skipping the colliding path and stamping anyway is the\n * marked-file case again, with the mark hidden.\n */\nexport function refuseOnCollision(plan: AdoptPlan, repoLabel: string): void {\n if (plan.collisions.length === 0) return;\n throw new CliError(\n `${repoLabel} already has files at ${plan.collisions.length} managed path(s)`,\n {\n code: ExitCode.REFUSED,\n detail: plan.collisions.map((p) => ` ${p}`).join(\"\\n\"),\n hint:\n \"adopt is all-or-nothing: it would mark these as oxyc's to rewrite, and a later\\n\" +\n \" `oxyc update --apply` would destroy them. Move them aside, or add a manifest\\n\" +\n \" rule saying they are the customer's, then run adopt again.\"\n }\n );\n}\n","// @generated by scripts/embed-assets.mjs — do not edit.\n//\n// 33 files from `json-schemas/`, `skills/`, `template/`,\n// gzipped and base64'd so a compiled single-file `oxyc` still ships them.\n// Regenerate with `pnpm --filter @oxy-hq/cli build`.\n\n/** sha256 of the compressed payload, truncated — the extraction cache key. */\nexport const ASSETS_DIGEST = \"a4b68ef9f2e724e1\";\n\n/** The directories this payload reconstructs, relative to a package root. */\nexport const ASSET_DIRS = [\"json-schemas\",\"skills\",\"template\"] as const;\n\n/** gzip(JSON({ \"<path>\": { d: base64, x?: 1 } })), base64'd. */\nexport const ASSETS_GZIP_BASE64 =\n \"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\";\n","/**\n * Unpacking the assets that a compiled `oxyc` carries inside itself.\n *\n * `bun build --compile` produces one executable and nothing else, so the\n * `template/`, `skills/` and `json-schemas/` directories cannot be read off\n * disk the way they are from an npm install. `scripts/embed-assets.mjs` inlines\n * them into `../generated/embedded-assets.ts`; this unpacks that on demand.\n *\n * **Why extract to disk rather than serve from memory.** `oxyc skills install`\n * symlinks into the skills directory and `oxyc new` copies a directory tree —\n * both need real paths that other processes (Claude Code, git) can open. A\n * virtual filesystem would have meant rewriting every consumer to go through an\n * asset reader and would still not have given `skills install` something to\n * point a symlink at.\n *\n * The extraction directory is keyed by the payload digest, so a new release\n * unpacks alongside the old one instead of reusing it. It lives under the cache\n * root, which is documented as disposable — that is correct here: losing it\n * costs one re-extraction, because the bytes are in the executable.\n */\n\nimport {\n chmodSync,\n existsSync,\n mkdirSync,\n mkdtempSync,\n renameSync,\n rmSync,\n writeFileSync\n} from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { gunzipSync } from \"node:zlib\";\nimport { ASSET_DIRS, ASSETS_DIGEST, ASSETS_GZIP_BASE64 } from \"../generated/embedded-assets.js\";\nimport { CliError, ExitCode } from \"../util/errors.js\";\nimport { ensureDir, oxycCacheDir } from \"../util/paths.js\";\n\nexport { ASSET_DIRS };\n\n/**\n * What to tell someone whose installation is missing its assets.\n *\n * Every branch that can report a broken install shares this, so the curl URL\n * exists once — four hand-copied URLs is how one of them ends up stale.\n */\nexport const REINSTALL_REMEDY =\n \"reinstall: `curl -fsSL https://raw.githubusercontent.com/oxy-hq/oxygen/main/install_oxyc.sh | bash`\";\n\n/** One embedded file: base64 contents, plus the executable bit when it had one. */\ninterface EmbeddedFile {\n d: string;\n x?: 1;\n}\n\n/** Where a given build's assets unpack to. Digest-keyed, so upgrades never collide. */\nexport function embeddedAssetsDir(): string {\n return join(oxycCacheDir(), \"assets\", ASSETS_DIGEST);\n}\n\n/** True once every embedded directory is present at `root`. */\nfunction looksComplete(root: string): boolean {\n return ASSET_DIRS.every((dir) => existsSync(join(root, dir)));\n}\n\n/**\n * Materialise the embedded assets and return the directory holding them.\n *\n * Writes into a sibling temporary directory and renames it into place, so a\n * second `oxyc` running concurrently — or one killed halfway — can never leave\n * a half-written tree that later runs would treat as complete.\n */\nexport function extractEmbeddedAssets(): string {\n const target = embeddedAssetsDir();\n if (looksComplete(target)) return target;\n\n const parent = ensureDir(dirname(target));\n const staging = mkdtempSync(join(parent, `.${ASSETS_DIGEST}.tmp-`));\n try {\n let files: Record<string, EmbeddedFile>;\n try {\n files = JSON.parse(gunzipSync(Buffer.from(ASSETS_GZIP_BASE64, \"base64\")).toString(\"utf8\"));\n } catch (cause) {\n throw new CliError(\"the assets embedded in this build are corrupt\", {\n code: ExitCode.FAILURE,\n detail: cause instanceof Error ? cause.message : String(cause),\n remedy: REINSTALL_REMEDY\n });\n }\n\n for (const [relative, file] of Object.entries(files)) {\n const dest = join(staging, ...relative.split(\"/\"));\n mkdirSync(dirname(dest), { recursive: true });\n writeFileSync(dest, Buffer.from(file.d, \"base64\"));\n // `template/scripts/dev.sh` and the CI scripts are executable in the\n // repo. A scaffolded workspace whose `dev.sh` is 0644 fails in a way that\n // reads as a bug in the customer's repo rather than in this extraction.\n if (file.x) chmodSync(dest, 0o755);\n }\n\n if (!looksComplete(staging)) {\n throw new CliError(\"the assets embedded in this build are incomplete\", {\n code: ExitCode.FAILURE,\n remedy: REINSTALL_REMEDY\n });\n }\n\n try {\n renameSync(staging, target);\n } catch {\n // `rename` onto a non-empty directory fails, and there are two ways one\n // can be sitting there.\n //\n // Another process won the race and put its own COMPLETE tree there\n // first. Theirs is byte-identical — same digest — so use it, drop ours.\n if (looksComplete(target)) {\n rmSync(staging, { recursive: true, force: true });\n return target;\n }\n // Or a previous run was killed part-way and left a PARTIAL tree. Without\n // clearing it, every future run fails the same rename and the install is\n // wedged until someone finds the cache directory by hand — the failure\n // this whole staging dance exists to prevent.\n rmSync(target, { recursive: true, force: true });\n try {\n renameSync(staging, target);\n } catch (retryErr) {\n // Lost a race to a process that completed between the remove and the\n // retry. Its tree is the same bytes; anything else is a real failure.\n if (!looksComplete(target)) throw retryErr;\n rmSync(staging, { recursive: true, force: true });\n }\n }\n return target;\n } catch (err) {\n rmSync(staging, { recursive: true, force: true });\n throw err;\n }\n}\n","/**\n * Finding the assets that ship inside this package — the customer workspace\n * template, the Claude skills, and the JSON Schemas.\n *\n * There are two shapes this tool is installed in, and they resolve differently:\n *\n * - **A package on disk** (npm install, or a source checkout). The assets sit\n * next to `package.json`, one level up from the running file. Resolved from\n * `import.meta.url` rather than `process.cwd()`, because the whole point of\n * `npx @oxy-hq/cli` is being run from a directory that has nothing to do\n * with the package.\n * - **A compiled single-file binary** (`bun build --compile`, what the curl\n * installer ships). There is no package and no `dist/` — just an executable.\n * The assets travel inside it, base64'd by `scripts/embed-assets.mjs`, and\n * are unpacked to a cache directory the first time one is asked for.\n *\n * Disk wins whenever it is available, so an npm install and a checkout behave\n * exactly as they did before embedding existed; extraction is the fallback, not\n * the default. `OXYC_TEMPLATE_DIR` / `OXYC_SCHEMAS_DIR` / `OXYC_SKILLS_DIR`\n * override either, which is what lets a developer point at a working copy while\n * iterating — and what the tests use instead of building a package.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { CliError, ExitCode } from \"../util/errors.js\";\nimport { ASSET_DIRS, extractEmbeddedAssets, REINSTALL_REMEDY } from \"./embedded.js\";\n\n/**\n * The package root, when this is a real package on disk.\n *\n * Requires the asset directories to actually be present, not merely a\n * `package.json` — a compiled binary resolves `import.meta.url` to a synthetic\n * path whose parent may well contain some unrelated `package.json`, and\n * answering with that would send every lookup somewhere arbitrary.\n */\nfunction diskPackageRoot(): string | undefined {\n const here = dirname(fileURLToPath(import.meta.url));\n // Built: <pkg>/dist/main.mjs → <pkg>. Source (vitest): <pkg>/src/template → <pkg>.\n for (const candidate of [resolve(here, \"..\"), resolve(here, \"..\", \"..\")]) {\n if (!existsSync(join(candidate, \"package.json\"))) continue;\n if (ASSET_DIRS.some((dir) => !existsSync(join(candidate, dir)))) continue;\n return candidate;\n }\n return undefined;\n}\n\n/**\n * The directory holding `template/`, `skills/` and `json-schemas/` — either the\n * installed package, or the cache the embedded copy was unpacked into.\n *\n * Memoised because extraction checks the filesystem, and a single `oxyc update`\n * asks for the template several times.\n */\nlet cachedRoot: string | undefined;\nfunction packageRoot(): string {\n if (cachedRoot === undefined) cachedRoot = diskPackageRoot() ?? extractEmbeddedAssets();\n return cachedRoot;\n}\n\n/** Test seam: forget the resolved root, so an env-var change is picked up. */\nexport function resetPackageRootForTests(): void {\n cachedRoot = undefined;\n}\n\n/**\n * The customer workspace template that `oxyc new` renders and `oxyc update`\n * compares against.\n */\nexport function templateDir(): string {\n const override = process.env.OXYC_TEMPLATE_DIR;\n if (override) {\n if (!existsSync(override)) {\n throw new CliError(`OXYC_TEMPLATE_DIR points at ${override}, which does not exist`, {\n code: ExitCode.USAGE\n });\n }\n return override;\n }\n const shipped = join(packageRoot(), \"template\");\n if (!existsSync(shipped)) {\n throw new CliError(\"the workspace template is missing from this installation\", {\n code: ExitCode.FAILURE,\n remedy: REINSTALL_REMEDY\n });\n }\n return shipped;\n}\n\n/** The ownership manifest that ships with the template. */\nexport function manifestPath(): string {\n return join(templateDir(), \".oxyc-managed\");\n}\n\n/**\n * The JSON Schemas `oxyc validate` checks against.\n *\n * Copied here from the repo root at build time by `scripts/sync-schemas.mjs`\n * and gitignored, so there is one committed source of truth — they are\n * generated from the Rust config types, and `crates/app`'s\n * `json_schemas_are_current` test is what keeps those in step.\n */\nexport function schemasDir(): string {\n return process.env.OXYC_SCHEMAS_DIR ?? join(packageRoot(), \"json-schemas\");\n}\n\n/** The Claude skills bundled in this package, linked by `oxyc skills install`. */\nexport function skillsDir(): string {\n return process.env.OXYC_SKILLS_DIR ?? join(packageRoot(), \"skills\");\n}\n\n/**\n * Where the tooling repo is, when the template came from a working copy.\n *\n * Only used for the provenance stamp — with an npm install or a compiled binary\n * there is no git tree to describe, which the stamp records honestly as\n * `unknown` rather than inventing a commit.\n */\nexport function templateRepoRoot(): string {\n return process.env.OXYC_TEMPLATE_DIR\n ? resolve(process.env.OXYC_TEMPLATE_DIR, \"..\")\n : packageRoot();\n}\n","/**\n * `oxyc new`, `oxyc import`, `oxyc remove` — the three doors into and out of\n * the customer registry.\n *\n * REGISTRATION IS TAGGING A REPO and nothing else. `import` adds the topic and\n * stops; `new` creates the repo already tagged; `remove` drops the topic. There\n * is no customer file anywhere, which is why there is nothing else to keep in\n * sync.\n */\n\nimport { existsSync, rmSync } from \"node:fs\";\n\nimport type { Context } from \"../context/resolve.js\";\nimport { dossierPath, isCloned } from \"../customer/dossier.js\";\nimport { customersOrg, invalidateCache, resolveCustomer } from \"../github/customers.js\";\nimport { ghAvailable } from \"../github/gh.js\";\nimport {\n addTopic,\n createRepo,\n inspectRepo,\n refuseInconclusive,\n removeTopic\n} from \"../github/topics.js\";\nimport { NEW_GENERATED_BY } from \"../template/adopt.js\";\nimport { templateDir, templateRepoRoot } from \"../template/locate.js\";\nimport { renderTemplate, writeStamp } from \"../template/render.js\";\nimport * as log from \"../ui/log.js\";\nimport { out } from \"../ui/tty.js\";\nimport { CliError, ExitCode } from \"../util/errors.js\";\nimport { clone, currentBranch, isRepo, workingTreeState } from \"../util/git.js\";\n\n/**\n * Create a new customer workspace repo, tagged, scaffolded and pushed-ready.\n *\n * The order is deliberate: PROVE THE REPO DOES NOT EXIST, create it, render,\n * stamp. An inconclusive existence check refuses outright — reading \"GitHub is\n * having a moment\" as \"no such repo\" is how this command would create over a\n * live customer's repository.\n */\nexport function runNew(_ctx: Context, name: string, flags: { display?: string }): void {\n const org = customersOrg();\n const slug = `${org}/${name}`;\n\n const existence = inspectRepo(slug);\n if (existence.kind === \"inconclusive\") throw refuseInconclusive(slug, existence.why);\n if (existence.kind === \"exists\") {\n throw new CliError(`${slug} already exists`, {\n code: ExitCode.REFUSED,\n hint: `oxyc import ${slug} — to register a repo that is already there`\n });\n }\n\n const display = flags.display ?? name;\n const dest = dossierPath(slug);\n if (existsSync(dest)) {\n throw new CliError(`${dest} already exists`, {\n code: ExitCode.REFUSED,\n hint: \"move it aside — scaffolding into it could overwrite work\"\n });\n }\n\n log.info(`creating ${slug}`);\n createRepo(slug, display);\n\n log.info(`rendering the workspace template into ${dest}`);\n const written = renderTemplate(templateDir(), dest, {\n slug: name,\n name: display,\n // A freshly rendered tree IS a workspace at its root — any other value\n // would describe a repo this command cannot create.\n workspace: \".\"\n });\n writeStamp(dest, templateRepoRoot(), NEW_GENERATED_BY, new Date().toISOString());\n invalidateCache(org);\n\n process.stdout.write(\n `${out.green(`created ${slug}`)}\\n` +\n ` ${written.length + 1} files scaffolded at ${dest}\\n` +\n ` ${out.dim(\"nothing was committed or pushed — `git add -A && git commit && git push` when it looks right\")}\\n`\n );\n}\n\n/**\n * Register an EXISTING repo as a customer workspace.\n *\n * It never scaffolds: the repo has content already, and dropping the template\n * over it is what `oxyc adopt` exists to do carefully and on purpose.\n */\nexport function runImport(_ctx: Context, slug: string, flags: { clone?: boolean }): void {\n if (!slug.includes(\"/\")) {\n throw new CliError(`import needs <org>/<repo>, got \"${slug}\"`, {\n code: ExitCode.USAGE,\n hint: `oxyc import ${customersOrg()}/${slug}`\n });\n }\n\n const existence = inspectRepo(slug);\n if (existence.kind === \"inconclusive\") throw refuseInconclusive(slug, existence.why);\n if (existence.kind === \"absent\") {\n throw new CliError(`${slug} does not exist`, {\n code: ExitCode.NOT_FOUND,\n hint: `oxyc new ${slug.split(\"/\")[1]} — to create it`\n });\n }\n\n addTopic(slug);\n process.stdout.write(`${out.green(`registered ${slug}`)}\\n`);\n\n const path = dossierPath(slug);\n if (isCloned(slug)) return;\n if (flags.clone) {\n log.info(`cloning ${slug} → ${path}`);\n clone(slug, path, ghAvailable());\n return;\n }\n process.stdout.write(\n ` ${out.dim(`not cloned here — ${ghAvailable() ? `gh repo clone ${slug} ${path}` : `git clone https://github.com/${slug}.git ${path}`}`)}\\n`\n );\n}\n\n/**\n * Drop the topic. The REPO IS NEVER DELETED — not by this, and not by\n * `--purge`, which deletes only the local clone. A customer removed by mistake\n * is re-registered with `oxyc import`.\n */\nexport function runRemove(\n ctx: Context,\n name: string,\n flags: { purge?: boolean; yes?: boolean }\n): void {\n const customer = resolveCustomer(name, { refresh: ctx.flags.refresh });\n const slug = `${customersOrg()}/${customer.name}`;\n\n removeTopic(slug);\n process.stdout.write(\n `${out.green(`unregistered ${slug}`)} ${out.dim(\"(the repo itself is untouched)\")}\\n`\n );\n\n if (!flags.purge) return;\n\n const path = dossierPath(slug);\n if (!existsSync(path)) {\n log.info(\"no local clone to purge\");\n return;\n }\n\n // REFUSES IF THE CLONE HOLDS ANYTHING THAT EXISTS NOWHERE ELSE. `--purge` is\n // a convenience for reclaiming disk, and a convenience must not be able to\n // destroy the only copy of something.\n const blockers = purgeBlockers(path);\n if (blockers.length > 0) {\n throw new CliError(`${path} holds work that exists nowhere else`, {\n code: ExitCode.REFUSED,\n detail: blockers.map((b) => ` ${b}`).join(\"\\n\"),\n hint: \"push or discard it, then run `oxyc remove --purge` again\"\n });\n }\n\n // Never assumes yes: with no terminal to ask, an unconfirmed destructive\n // operation refuses rather than proceeding or hanging on a prompt nobody\n // can answer.\n if (!flags.yes && !process.stdin.isTTY) {\n throw new CliError(\"--purge needs --yes when stdin is not a terminal\", {\n code: ExitCode.REFUSED,\n hint: `oxyc remove ${name} --purge --yes`\n });\n }\n\n rmSync(path, { recursive: true, force: true });\n process.stdout.write(`${out.green(`deleted the local clone at ${path}`)}\\n`);\n}\n\n/** Everything in a clone that would be lost by deleting it. */\nfunction purgeBlockers(path: string): string[] {\n const blockers: string[] = [];\n if (!isRepo(path)) return [\"not a git repository — oxyc cannot tell what would be lost\"];\n\n const state = workingTreeState(path);\n if (state.modified.length > 0) blockers.push(`${state.modified.length} uncommitted change(s)`);\n if (state.untracked.length > 0) blockers.push(`${state.untracked.length} untracked file(s)`);\n\n const branch = currentBranch(path);\n if (!branch) blockers.push(\"detached HEAD\");\n\n return blockers;\n}\n","/**\n * `oxyc repos` — where OUR repos are checked out on this machine.\n *\n * Read-only, and it never clones: a repo that is not here is named with the\n * command that would fetch it, and the human decides.\n */\n\nimport { repoMap, SHARED_REPOS } from \"../customer/repos.js\";\nimport { table } from \"../ui/render.js\";\nimport { out } from \"../ui/tty.js\";\n\nexport function runRepos(flags: { refresh?: boolean }): void {\n const map = repoMap({ refresh: flags.refresh });\n // The shared four first, in their canonical order, then anything else the\n // scan turned up — a machine that also holds `oxy-hq/docs` should say so,\n // but not ahead of the repos a customer session actually reaches for.\n const rows = [\n ...SHARED_REPOS.map((slug) => ({ slug, path: map[slug], shared: true })),\n ...Object.entries(map)\n .filter(([slug]) => !SHARED_REPOS.includes(slug as (typeof SHARED_REPOS)[number]))\n .map(([slug, path]) => ({ slug, path, shared: false }))\n ];\n\n process.stdout.write(\n `${table(rows, [\n { header: \"REPO\", value: (r) => r.slug },\n { header: \"SHARED\", value: (r) => (r.shared ? \"yes\" : \"\") },\n {\n header: \"PATH\",\n value: (r) => r.path ?? out.dim(`not on this machine — gh repo clone ${r.slug}`)\n }\n ])}\\n`\n );\n}\n","/**\n * `oxyc skills install` / `oxyc skills list` — put this package's Claude skills\n * where every session will load them.\n *\n * THIS IS THE ONE PLACE THE PORT CHANGES SHAPE rather than translating.\n *\n * The bash tooling symlinked `skills/` OUT of a git clone that had to persist\n * forever: moving or deleting the clone broke `oxyc` and left dangling links\n * in `~/.claude/skills/`, and a `git pull` that ADDED a skill created no link\n * for it and printed no warning, so it silently did not load until somebody\n * remembered to re-run `install.sh`. `oxyc self-update` existed almost\n * entirely to remember that step.\n *\n * As an npm package the skills ship INSIDE the install, so the whole class\n * goes away: `pnpm add -g @oxy-hq/cli` replaces the pull, and this command\n * re-points the links at whatever version is now installed. What is kept is\n * the part that was actually load-bearing — never clobbering a name that\n * something else owns, and exiting non-zero when a skill could not be linked.\n * A skill that did not link is never reported as fine.\n */\n\nimport {\n existsSync,\n lstatSync,\n mkdirSync,\n readdirSync,\n readlinkSync,\n rmSync,\n symlinkSync\n} from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { REINSTALL_REMEDY } from \"../template/embedded.js\";\nimport { skillsDir } from \"../template/locate.js\";\nimport * as log from \"../ui/log.js\";\nimport { table } from \"../ui/render.js\";\nimport { out } from \"../ui/tty.js\";\nimport { CliError, ExitCode, refusal } from \"../util/errors.js\";\n\n/** Where Claude Code loads global skills from. */\nfunction targetDir(): string {\n return process.env.OXYC_SKILLS_TARGET ?? join(homedir(), \".claude\", \"skills\");\n}\n\ntype LinkState = \"linked\" | \"relinked\" | \"already\" | \"blocked\";\n\ninterface SkillResult {\n name: string;\n state: LinkState;\n detail: string;\n}\n\n/** The skills this package ships. */\nfunction shipped(): string[] {\n const dir = skillsDir();\n if (!existsSync(dir)) return [];\n return readdirSync(dir, { withFileTypes: true })\n .filter((e) => e.isDirectory())\n .map((e) => e.name)\n .sort();\n}\n\n/**\n * Link one skill, refusing to clobber a name something else owns.\n *\n * A foreign symlink or a real directory at that name is left ALONE and\n * reported — the bash installer did the same, and the difference is that its\n * \"skipped\" line was one nobody read. Here it makes the command exit non-zero.\n */\nfunction linkOne(name: string, source: string, target: string): SkillResult {\n const dest = join(target, name);\n if (!existsSync(dest) && !isSymlink(dest)) {\n symlinkSync(source, dest, \"dir\");\n return { name, state: \"linked\", detail: source };\n }\n if (isSymlink(dest)) {\n const current = readlinkSync(dest);\n if (current === source) return { name, state: \"already\", detail: source };\n // A link pointing at an OLD install of this package is ours to move; one\n // pointing anywhere else is not.\n if (current.includes(`${\"@oxy-hq\"}/cli`) || current.includes(\"customer-tooling\")) {\n rmSync(dest);\n symlinkSync(source, dest, \"dir\");\n return { name, state: \"relinked\", detail: `was ${current}` };\n }\n return { name, state: \"blocked\", detail: `a symlink to ${current} is in the way` };\n }\n return { name, state: \"blocked\", detail: \"a real directory is in the way\" };\n}\n\nfunction isSymlink(path: string): boolean {\n try {\n return lstatSync(path).isSymbolicLink();\n } catch {\n return false;\n }\n}\n\n/** Link every shipped skill into the user's global skills directory. */\nexport function runSkillsInstall(): void {\n const source = skillsDir();\n const target = targetDir();\n const names = shipped();\n\n if (names.length === 0) {\n throw new CliError(\"this installation ships no skills\", {\n code: ExitCode.FAILURE,\n remedy: REINSTALL_REMEDY\n });\n }\n\n mkdirSync(target, { recursive: true });\n const results = names.map((name) => linkOne(name, join(source, name), target));\n\n process.stdout.write(\n `${table(results, [\n { header: \"SKILL\", value: (r) => r.name },\n { header: \"STATE\", value: (r) => (r.state === \"blocked\" ? out.red(r.state) : r.state) },\n { header: \"DETAIL\", value: (r) => r.detail }\n ])}\\n`\n );\n\n const blocked = results.filter((r) => r.state === \"blocked\");\n if (blocked.length === 0) return;\n\n // NON-ZERO, deliberately. A skill that was not linked will not load, and a\n // command that reported that as success is how the gap stayed invisible.\n throw refusal(`${blocked.length} skill(s) could not be linked`, {\n detail: blocked.map((r) => ` ${r.name}: ${r.detail}`).join(\"\\n\"),\n remedy: `move what is in the way under ${target}, then run \\`oxyc skills install\\` again`\n });\n}\n\n/** What this package ships, and whether each is currently linked. */\nexport function runSkillsList(): void {\n const source = skillsDir();\n const target = targetDir();\n const rows = shipped().map((name) => {\n const dest = join(target, name);\n const linked = isSymlink(dest) && readlinkSync(dest) === join(source, name);\n return { name, linked };\n });\n\n if (rows.length === 0) {\n // SAME SENTENCE AS THE THROW ABOVE, so it gets the same remedy — a listing\n // that finds nothing is not a failure (exit 0 stands), but a reader who\n // sees this and the thrown version has no reason to be told what to do in\n // only one of them.\n log.warn(\"this installation ships no skills\");\n log.remedy(REINSTALL_REMEDY);\n return;\n }\n\n process.stdout.write(\n `${table(rows, [\n { header: \"SKILL\", value: (r) => r.name },\n { header: \"LINKED\", value: (r) => (r.linked ? \"yes\" : out.yellow(\"no\")) }\n ])}\\n`\n );\n}\n","/**\n * `oxyc validate` — check a workspace's YAML against the schemas.\n *\n * ONE SOURCE OF TRUTH, WHICH IS THE ONLY REASON THIS IS HONEST TO PORT.\n * The schemas are not written here: `json-schemas/*.json` are generated from\n * the Rust config types by `oxy gen-config-schema`, and `crates/app`'s\n * `json_schemas_are_current` test fails if the committed copies drift from\n * those types. This reads them. A hand-written TypeScript mirror of\n * `AgentConfig` would be a second definition that diverges silently — the\n * exact shape of bug this CLI has spent its whole review finding.\n *\n * DOES NOT REPLACE `oxy validate`. That one builds a real `ConfigBuilder`, so\n * it can resolve `databases:` entries and `llm.ref` against `config.yml` —\n * checks that need the workspace loaded, not just parsed. This is the\n * structural half: schema conformance, fast, no Rust binary, and reachable\n * from `npx`. Where they disagree, the Rust one is right.\n */\n\nimport { existsSync, lstatSync, readdirSync, readFileSync, realpathSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { extname, join, parse, relative, resolve } from \"node:path\";\nimport { Ajv, type ErrorObject } from \"ajv\";\nimport addFormats from \"ajv-formats\";\nimport { parse as parseYaml } from \"yaml\";\nimport { REINSTALL_REMEDY } from \"../template/embedded.js\";\nimport { schemasDir } from \"../template/locate.js\";\nimport * as log from \"../ui/log.js\";\nimport { heading, table } from \"../ui/render.js\";\nimport { out } from \"../ui/tty.js\";\nimport { CliError, ExitCode } from \"../util/errors.js\";\nimport { repoRoot } from \"../util/git.js\";\n\n/**\n * Which schema governs which file.\n *\n * Keyed by the SUFFIX rather than the extension, because these are all `.yml`\n * and the kind is carried by the second-to-last segment. `.workflow.yml` is\n * the retired spelling of `.automation.yml` and is still accepted by the\n * platform, so it is accepted here.\n */\nconst SCHEMA_KINDS: ReadonlyArray<readonly [stem: string, schema: string]> = [\n [\".automation\", \"workflow.json\"],\n [\".procedure\", \"workflow.json\"],\n [\".workflow\", \"workflow.json\"],\n [\".agentic\", \"agentic.json\"],\n [\".app\", \"app.json\"],\n [\".agent.test\", \"agent-test.json\"],\n [\"config\", \"config.json\"]\n];\n\n/**\n * Both YAML spellings, because the walk accepts both and the product does too.\n *\n * The first version listed only `.yml`, so `config.yaml` and `x.app.yaml` were\n * walked, matched nothing, and skipped in silence — while the web app's Monaco\n * config validates both spellings. A workspace using `.yaml` would have been\n * reported clean without a single file being read.\n */\nconst SCHEMA_FOR: ReadonlyArray<readonly [suffix: string, schema: string]> = SCHEMA_KINDS.flatMap(\n ([stem, schema]) =>\n [\n [`${stem}.yml`, schema],\n [`${stem}.yaml`, schema]\n ] as const\n);\n\n/**\n * Directories never walked.\n *\n * A superset of the canonical list in `migrate_automations.rs` rather than a\n * copy of it — `build` is the one that matters and was missing, because a\n * stray rendered copy of a workspace file actually lands there. The extras\n * (`.github`, `out`, `__pycache__`) cost nothing: nothing validatable is\n * authored in them.\n */\nconst SKIP = new Set([\n \"build\",\n \".git\",\n \".github\",\n \"node_modules\",\n \"target\",\n \"dist\",\n \"out\",\n \".worktrees\",\n \".oxy_state\",\n \".venv\",\n \"__pycache__\"\n]);\n\nexport interface ValidateFlags {\n /** Validate one file instead of the whole workspace. */\n file?: string;\n /** Emit findings as JSON. */\n json?: boolean;\n}\n\ninterface Finding {\n file: string;\n path: string;\n message: string;\n}\n\n/** The schema a path is governed by, or `undefined` for a file we do not check. */\nexport function schemaFor(path: string): string | undefined {\n const normalised = path.split(\"\\\\\").join(\"/\");\n const basename = normalised.split(\"/\").pop() ?? normalised;\n for (const [suffix, schema] of SCHEMA_FOR) {\n // MATCHED AGAINST THE BASENAME, not the whole path, and the distinction\n // is not cosmetic: `endsWith(\"config.yml\")` is true for `myconfig.yml`,\n // which would then be validated against the workspace config schema and\n // reported as broken for having none of its fields. Same shape as\n // `/api/user` matching `/api/users` in the proxy.\n //\n // A dotted suffix still needs the leading `.`, so `notanapp.yml` does not\n // match `.app.yml`.\n if (suffix.startsWith(\".\") ? basename.endsWith(suffix) : basename === suffix) return schema;\n }\n return undefined;\n}\n\n/** What the walk found: files to check, and links it could not follow. */\ninterface Walked {\n files: string[];\n /**\n * Entries named like a workspace file that could not be read, and why.\n *\n * NOT ONLY LINKS. A FIFO, socket or device named `x.app.yml` lands here too,\n * and none of them is a symlink — the warning string and this doc both said\n * \"symlink\" while the bucket had already widened.\n */\n broken: SkippedFile<string>[];\n}\n\n/**\n * A file that was named and NOT checked, and the reason it was not.\n *\n * One shape, two buckets: `broken` for an entry the filesystem would not give\n * us, `unchecked` for one we had no schema to check it against. The code spaces\n * are different — `whyUnreadable` explains the first, `whyUnchecked` the second\n * — but a caller reading `--json` gets the same `{path, code}` either way,\n * which is what lets it act on the reason instead of on the bucket's name.\n *\n * The reason is CHECKED, not assumed. Reporting every `statSync` failure as\n * \"the target is gone\" was true for `ENOENT` and a claim about a condition\n * nobody established for the rest — `ELOOP` for `ln -s x.app.yml x.app.yml`\n * (worth naming, on a walk that deliberately avoids needing cycle detection),\n * `EACCES` for an unreadable directory above the target, `ENOTDIR` for a link\n * through a path component that is a file.\n *\n * `code` is the OS errno except for two that are OURS, said here so a caller\n * branching on it knows which names come from the kernel: `ENOTFILE`, because\n * there is no errno for \"this is a FIFO\", and `EUNKNOWN`, for the case where\n * the thrown error carried no code at all. Inventing either silently would be\n * the same defect as the assumed cause above.\n */\ninterface SkippedFile<C extends string> {\n path: string;\n code: C;\n}\n\n/**\n * The `--json` document's shape, declared once.\n *\n * An INTERFACE rather than a shared empty literal to spread. The spread bought\n * the same \"both documents carry every field\" property, but paid for it with a\n * silent default: add a field and the populated document emits its EMPTY value\n * beside real data. Annotating both literals makes the omission a compile error\n * instead, which is the version that cannot ship wrong.\n */\ninterface ValidateReport {\n checked: number;\n unchecked: SkippedFile<SkipCode>[];\n broken: SkippedFile<string>[];\n findings: Finding[];\n}\n\n/** Our own code for an entry that exists and is not a regular file. */\nconst ENOTFILE = \"ENOTFILE\";\n\n/** Our own code for a throw that carried none — never an OS errno. */\nconst EUNKNOWN = \"EUNKNOWN\";\n\n/** Named once: two throws print it, and one of them may replace it. */\nconst WHOLE_WORKSPACE_HINT = \"oxyc validate — to check the whole workspace\";\n\n/** The kind is known and its schema is not on disk in this installation. */\nconst SCHEMA_MISSING = \"SCHEMA_MISSING\";\n\n/**\n * `oxyc` has no schema mapped for this file kind at all.\n *\n * UNREACHABLE THROUGH BOTH DOORS TODAY, on the same footing as the `undefined`\n * this replaced: `walk` filters on `!schemaFor(rel)` before it emits, and the\n * `--file` branch throws USAGE on the same predicate. It exists so the value\n * and the message agree with the contract the day either filter moves — which\n * is why `whyUnchecked` is pinned directly rather than through a run that\n * cannot produce this code.\n */\nconst KIND_UNKNOWN = \"KIND_UNKNOWN\";\n\n/**\n * Every reason `unchecked` can hold — a CLOSED set, unlike an OS errno.\n *\n * Written as a union so `whyUnchecked` can be exhaustive rather than merely\n * typed: see the `never` at the end of it.\n */\ntype SkipCode = typeof SCHEMA_MISSING | typeof KIND_UNKNOWN;\n\n/**\n * Why a file was skipped, and — separately — what to do about it.\n *\n * TWO FIELDS, because they belong in two places. Folded into one string, the\n * only reachable headline read `3 file(s) NOT checked — the schema is not in\n * this installation — reinstall, or set OXYC_SCHEMAS_DIR at a checkout's\n * json-schemas/`: 140 characters and two em dashes, of which the second half\n * is a remedy. `listSkipped` puts the reason on the count and the remedy on its\n * own line below the paths, through `log.remedy` — NOT `log.hint`, whose `→`\n * elaborates the line above and so reads in sequence with the paths. The\n * remedy is the one line that is about what to DO, and the blank lines around\n * it are what say so.\n */\ninterface SkipReason {\n reason: string;\n remedy?: string;\n}\n\n/**\n * Why a file was not checked.\n *\n * TWO PRODUCERS, TWO REMEDIES, and the message used to assert the first one's\n * for both: \"reinstall, or set OXYC_SCHEMAS_DIR\" is right for a schema absent\n * from the installation and wrong for a kind `oxyc` does not map, where no\n * reinstall produces one.\n */\nexport function whyUnchecked(code: SkipCode): SkipReason {\n if (code === SCHEMA_MISSING) {\n return {\n // Worded to read after both \"3 file(s) NOT checked —\" and \"a0.app.yml —\",\n // since `listSkipped` puts it in either place.\n reason: \"the schema is not in this installation\",\n remedy: \"reinstall, or set OXYC_SCHEMAS_DIR at a checkout's json-schemas/\"\n };\n }\n if (code === KIND_UNKNOWN) {\n // No remedy: no reinstall produces a mapping `oxyc` does not have. That\n // asymmetry is the whole reason the two producers stopped sharing a line.\n return { reason: \"oxyc has no schema for this kind of file\" };\n }\n\n // EXHAUSTIVE, not merely typed. The union alone rejects a bad LITERAL at a\n // call site and nothing more, so ADDING A THIRD MEMBER compiled and fell out\n // of the last arm wearing `KIND_UNKNOWN`'s sentence — a claim about a cause\n // nobody established, which is the assumed-cause defect the surrounding\n // commits exist to close. `KIND_UNKNOWN`'s own doc names a third member as\n // the growth path, so this is the reachable shape, not a hypothetical.\n //\n // NOT a typo'd constant VALUE, which an earlier version of this comment also\n // claimed: producer and consumer both reference the constant, so a mistyped\n // `KIND_UNKNOWN` still reaches the arm written for it and the reader still\n // gets the right sentence. One shape, and `never` closes it.\n //\n // What an impossible code does NOW is throw — `whyUnchecked` returns\n // `undefined`, and `listSkipped`'s per-file line dereferences it. Loud and\n // wrong beats quiet and wrong, which is the trade, but it is a change and\n // worth saying rather than implying nothing happens.\n //\n // `whyUnreadable` cannot have any of this: the kernel's errno space is open,\n // which is why it keeps a fallback and this does not.\n const unreachable: never = code;\n return unreachable;\n}\n\n/**\n * What each code actually means, for the hint beside the path.\n *\n * Exported for the same reason `whyUnchecked` is: two of these arms —\n * `EACCES`/`EPERM` and `EUNKNOWN` — cannot be produced by a run on CI without\n * `chmod` or root, so swapping their strings passed the whole suite. A run\n * exercises the other four.\n */\nexport function whyUnreadable(code: string): SkipReason {\n if (code === \"ENOENT\") return { reason: \"the target is gone\" };\n if (code === \"ELOOP\") return { reason: \"the link points at itself, or round a cycle\" };\n if (code === \"EACCES\" || code === \"EPERM\") {\n return { reason: \"permission denied on the path to the target\" };\n }\n if (code === \"ENOTDIR\") return { reason: \"a component of the path is a file, not a directory\" };\n if (code === ENOTFILE) return { reason: \"not a regular file — a socket, device or FIFO\" };\n if (code === EUNKNOWN) return { reason: \"the filesystem refused it without saying why\" };\n // The fallback `whyUnchecked` deliberately does not have — an errno nobody\n // mapped is a real possibility, and the code itself beats inventing a cause.\n return { reason: code };\n}\n\n/**\n * Every YAML file under `root` that a schema governs.\n *\n * `withFileTypes` hands back a `Dirent`, which does NOT follow links, so every\n * link — to a file, to a directory, to nothing — answers `false` to\n * `isDirectory()` and falls through to the extension check together. The three\n * are separated here, by one `statSync` per link that reaches it:\n *\n * - A link to a FILE is emitted under its OWN name, and `schemaFor` decides its\n * kind from that name. `--file` was changed back to match — in an Oxy\n * workspace the kind of a file is its name, and a link called `x.app.yml` is\n * an app.\n * - A link to a DIRECTORY is skipped whatever it is called. Not descended into,\n * deliberately: following one needs cycle detection, and this is the cheap way\n * not to need it. Skipped EXPLICITLY rather than by omission, because a name\n * like `apps.app.yml` clears the extension check and reaches `readFileSync`,\n * which reports `EISDIR` as a YAML parse finding.\n * - Anything else — a broken link, a link to a FIFO, a FIFO — is collected\n * rather than emitted. Emitted, it reached `validateFile`, whose missing-file\n * guard throws `NOT_FOUND`: written for the `--file` branch, where \"no such\n * file\" answers a typo'd argument, and on the walk it aborted the whole run at\n * the first one. Exit 5, nothing printed about the other forty files, and a\n * hint naming the command already being run — one `models/x.view.yml` pointing\n * into a removed worktree was enough.\n *\n * So this emits REGULAR FILES AND LINKS TO THEM, full stop, which is what makes\n * `validateFile`'s two refusals unreachable from here rather than a condition\n * the two functions have to remember to agree on.\n *\n * The directory arm is the one place the two branches see different sets, under\n * two conditions rather than one: a link whose target is INSIDE the root is\n * still reached by its real path — nothing missed, only named differently —\n * UNLESS that real path is under a `SKIP` name, where it is genuinely invisible\n * and no `--file` note applies. A link pointing OUTSIDE the root is not walked,\n * while `--file apps/x.app.yml` reads straight through it. Pinned in\n * `validate.test.ts`.\n */\nfunction walk(root: string, prefix = \"\"): Walked {\n const out: Walked = { files: [], broken: [] };\n let entries: import(\"node:fs\").Dirent[];\n try {\n entries = readdirSync(join(root, prefix), { withFileTypes: true });\n } catch {\n return out;\n }\n for (const entry of entries) {\n const rel = prefix ? `${prefix}/${entry.name}` : entry.name;\n if (entry.isDirectory()) {\n if (SKIP.has(entry.name)) continue;\n const nested = walk(root, rel);\n out.files.push(...nested.files);\n out.broken.push(...nested.broken);\n continue;\n }\n if (extname(entry.name) !== \".yml\" && extname(entry.name) !== \".yaml\") continue;\n if (!schemaFor(rel)) continue;\n\n // The only `stat` in this walk, and it runs on links that would otherwise\n // be EMITTED — after `schemaFor`, so an ordinary entry and a link nothing\n // validates both pay nothing. `statSync` FOLLOWS; `lstat` would re-derive\n // what `Dirent` has already said. Its outcomes are the last two arms above:\n // a directory is skipped, and a throw is a link that cannot be followed —\n // for a reason the caller records rather than guesses.\n if (entry.isSymbolicLink()) {\n let target: import(\"node:fs\").Stats;\n try {\n target = statSync(join(root, rel));\n } catch (cause) {\n out.broken.push({ path: rel, code: (cause as NodeJS.ErrnoException).code ?? EUNKNOWN });\n continue;\n }\n if (target.isDirectory()) continue;\n if (!target.isFile()) {\n out.broken.push({ path: rel, code: ENOTFILE });\n continue;\n }\n } else if (!entry.isFile()) {\n // FREE — the `Dirent` already knows, so this costs no syscall. It closes\n // the last door to the whole-run abort: a FIFO, socket or device named\n // `x.app.yml` cleared every arm above, reached `validateFile`, and took\n // its `not a file` throw and the other forty files with it. `walk` now\n // emits regular files and links to them, FULL STOP, which makes that\n // throw unreachable from here — an invariant rather than a divergence\n // the two functions have to remember to agree on.\n out.broken.push({ path: rel, code: ENOTFILE });\n continue;\n }\n out.files.push(rel);\n }\n out.files.sort();\n out.broken.sort((a, b) => a.path.localeCompare(b.path));\n return out;\n}\n\n/** Compile every schema once — ajv is slow to compile and fast to run. */\nfunction compileAll(): Map<string, ReturnType<Ajv[\"compile\"]>> {\n const dir = schemasDir();\n const ajv = new Ajv({\n allErrors: true,\n strict: false,\n allowUnionTypes: true,\n // ajv logs every unrecognised `format` to the console, and these schemas\n // are generated by `schemars`, which emits Rust integer widths as formats\n // — so an unconfigured ajv printed twenty \"unknown format\" lines ahead of\n // the actual result.\n //\n // The known ones are TAUGHT below. What is silenced here is only ajv's\n // `warn`; `error` still comes through, and `warnUnregisteredFormats` then\n // re-raises the one warning that mattered — named, once, instead of once\n // per occurrence — which is the property a bare `logger: false` would have\n // thrown away while a comment claimed otherwise.\n logger: { log: () => {}, warn: () => {}, error: (...a: unknown[]) => console.error(...a) }\n });\n addFormats(ajv);\n registerRustFormats(ajv);\n\n const compiled = new Map<string, ReturnType<Ajv[\"compile\"]>>();\n // Collected HERE rather than by re-reading the files afterwards: each document\n // is already parsed on this line, and a second pass would need its own\n // try/catch to re-handle a parse error this loop has already reported.\n const formats = new Set<string>();\n for (const [, schema] of SCHEMA_FOR) {\n if (compiled.has(schema)) continue;\n const path = join(dir, schema);\n if (!existsSync(path)) continue;\n try {\n const document = JSON.parse(readFileSync(path, \"utf8\"));\n formatsInSchemaPosition(document, formats);\n compiled.set(schema, ajv.compile(document));\n } catch (cause) {\n throw new CliError(`could not compile ${schema}`, {\n code: ExitCode.FAILURE,\n detail: (cause as Error).message,\n hint: \"the schema is generated by `oxy gen-config-schema` — regenerate it\"\n });\n }\n }\n warnUnregisteredFormats(ajv, formats);\n if (compiled.size === 0) {\n // The fix depends on WHERE you are. In a source checkout the schemas are\n // copied in by `prebuild` and gitignored, so \"reinstall\" is the wrong\n // advice — `pnpm build` is the fix, and telling a developer to reinstall a\n // package they are editing is how a five-second problem becomes an hour.\n //\n // A REMEDY, not a hint: it is the one line here about what to DO, and\n // `CliError.remedy` is what renders that set apart rather than in the run\n // of `→` elaborations. This is also the field's first producer — without\n // one, the error path's half of the split would be wired and untested.\n const inCheckout = existsSync(join(schemasDir(), \"..\", \"..\", \"..\", \"json-schemas\"));\n throw new CliError(\"no JSON Schemas are available in this installation\", {\n code: ExitCode.FAILURE,\n remedy: inCheckout\n ? \"run `pnpm build` in sdk/cli — the schemas are copied from the repo root by prebuild\"\n : REINSTALL_REMEDY\n });\n }\n return compiled;\n}\n\n/**\n * Every `format` a schema uses in SCHEMA POSITION.\n *\n * Walked rather than regex-scanned over the raw text, because `\"format\"` is\n * also an ordinary word: a `default:` or an `examples:` holding a serialised\n * config with its own `{\"format\": \"csv\"}` is data, not a constraint, and a text\n * scan cannot tell the two apart. A key only counts when its sibling keys mark\n * the object as a schema — `type`, `$ref`, `enum`, `properties` and friends.\n */\nexport function formatsInSchemaPosition(node: unknown, into: Set<string>): void {\n if (Array.isArray(node)) {\n for (const item of node) formatsInSchemaPosition(item, into);\n return;\n }\n if (!node || typeof node !== \"object\") return;\n const obj = node as Record<string, unknown>;\n\n if (typeof obj.format === \"string\" && SCHEMA_SIBLINGS.some((k) => k in obj)) {\n into.add(obj.format);\n }\n for (const [key, value] of Object.entries(obj)) {\n if (INSTANCE_DATA.has(key)) continue;\n formatsInSchemaPosition(value, into);\n }\n}\n\n/**\n * Keywords whose values are INSTANCE DATA, never subschemas.\n *\n * Descending into them is exactly the mistake the text scan made: a `default`\n * holding a serialised config with its own `format` key is a value, not a\n * constraint. `enum` belongs here for the same reason `const` does — it is the\n * plural of `const` — even though it also appears in `SCHEMA_SIBLINGS` below,\n * where it marks the *enclosing* object as a schema.\n *\n * MATCHED ON THE KEY NAME ANYWHERE, so a schema property literally named\n * `default` under `properties:` is skipped too, where these keyword semantics\n * do not apply. Same accepted direction as `SCHEMA_SIBLINGS`: what that costs\n * is a MISSED warning about a format nobody registered, never a false one.\n */\nconst INSTANCE_DATA = new Set([\"default\", \"examples\", \"const\", \"enum\"]);\n\n/**\n * A `format` beside any of these is a constraint; alone it is just a word.\n *\n * NOT EXHAUSTIVE, and it does not need to be: `not`, `if`/`then`/`else`,\n * `additionalProperties`, `patternProperties`, `propertyNames` and `contains`\n * all appear in these files and are absent here. A keyword this list misses\n * costs a MISSED warning, never a false one — and every string `format` these\n * schemas emit also carries `type`, which is the first entry.\n */\nconst SCHEMA_SIBLINGS = [\n \"type\",\n \"$ref\",\n \"enum\",\n \"properties\",\n \"items\",\n \"allOf\",\n \"anyOf\",\n \"oneOf\",\n \"minimum\",\n \"maximum\",\n \"pattern\"\n];\n\n/**\n * Warn on a `format` that nobody taught ajv.\n *\n * This is the half the silenced logger would otherwise have lost. An\n * unrecognised format is IGNORED by ajv — the constraint silently does not\n * apply — so a `schemars` upgrade that starts emitting a new one would quietly\n * stop validating that field, and with the warning suppressed nothing would\n * say so.\n *\n * WARNS RATHER THAN THROWS, deliberately. What an unknown format costs is one\n * constraint on one field; what a throw here costs is `oxyc validate` for the\n * whole workspace, every file, until someone ships a new release. A Rust type\n * gaining a `u128` is enough to trigger it — `schemars` emits `uint128` — and\n * losing a range check on one integer is not worth losing the command.\n */\nfunction warnUnregisteredFormats(ajv: Ajv, formats: Iterable<string>): void {\n const known = new Set(Object.keys((ajv as unknown as { formats: object }).formats ?? {}));\n const unknown = [...formats].filter((f) => !known.has(f)).sort();\n if (unknown.length === 0) return;\n log.warn(`the schemas use formats ajv does not know: ${unknown.join(\", \")}`);\n // Reason and remedy, split for the same reason `SkipReason` splits them —\n // this was one line chaining both across an em dash, one function from the\n // code that stopped doing that.\n log.hint(\"each is silently ignored, so that one constraint does not apply\");\n log.remedy(\"register them in registerRustFormats()\");\n}\n\n/**\n * The integer formats `schemars` emits, taught to ajv.\n *\n * They are not JSON Schema formats — they are Rust types. Registering them\n * with their real bounds means `port: 70000` is reported as out of range for a\n * `uint16` instead of passing because ajv did not recognise the word.\n */\nfunction registerRustFormats(ajv: Ajv): void {\n const RANGES: Record<string, [min: number, max: number]> = {\n uint: [0, Number.MAX_SAFE_INTEGER],\n uint8: [0, 255],\n uint16: [0, 65_535],\n uint32: [0, 4_294_967_295],\n uint64: [0, Number.MAX_SAFE_INTEGER],\n int8: [-128, 127],\n int16: [-32_768, 32_767],\n int32: [-2_147_483_648, 2_147_483_647],\n int64: [Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER]\n };\n for (const [name, [min, max]] of Object.entries(RANGES)) {\n ajv.addFormat(name, {\n type: \"number\",\n validate: (value: number) => Number.isInteger(value) && value >= min && value <= max\n });\n }\n // `double` and `float` are emitted for f64/f32 and admit anything numeric.\n for (const name of [\"double\", \"float\"]) {\n ajv.addFormat(name, { type: \"number\", validate: () => true });\n }\n}\n\n/** ajv's error objects, flattened to something a person can act on. */\nfunction describe(file: string, errors: ErrorObject[] | null | undefined): Finding[] {\n return (errors ?? []).map((e) => ({\n file,\n // `instancePath` is a JSON pointer; a caller wants a YAML path.\n path: e.instancePath ? e.instancePath.replace(/^\\//, \"\").split(\"/\").join(\".\") : \"(root)\",\n message:\n e.keyword === \"additionalProperties\"\n ? `unknown field \\`${(e.params as { additionalProperty?: string }).additionalProperty}\\``\n : (e.message ?? \"invalid\")\n }));\n}\n\n/**\n * Validate one file.\n *\n * Returns a SKIP CODE when it could not be checked — distinct from `[]`, which\n * means \"checked, and clean\". Collapsing the two is how this\n * printed `23 file(s) valid` including every file kind whose schema was\n * missing from the installation: `compileAll` skips a schema that is not on\n * disk, this returned no findings, and the caller counted the file anyway.\n */\nfunction validateFile(\n root: string,\n rel: string,\n compiled: Map<string, ReturnType<Ajv[\"compile\"]>>\n): Finding[] | SkipCode {\n const schema = schemaFor(rel);\n // `undefined`, not `[]`, and for the same reason the doc gives: a file with\n // no schema was NOT checked. Unreachable through either door today — `walk`\n // filters on `!schemaFor(rel)` before emitting, and `--file` throws USAGE on\n // the same predicate — but `[]` here is the seed of the exact defect this\n // function's contract exists to prevent, and it grows back silently the day\n // either filter moves.\n if (!schema) return KIND_UNKNOWN;\n const validate = compiled.get(schema);\n if (!validate) return SCHEMA_MISSING;\n\n // NO FILESYSTEM CONDITION MAY ARRIVE LABELLED `(parse)`. Both are settled\n // here, outside the YAML try, because reported from inside it they read as\n // content problems and send the reader looking in a file for something that\n // is the file itself: \"ENOENT: no such file or directory\" for a path that is\n // not there, \"EISDIR: illegal operation on a directory\" for a directory named\n // `apps.app.yml` or a link to one. `existsSync` answered only the first —\n // it is true for a directory — so the walk arm got this rule and `--file`\n // kept the exception until now.\n const full = join(root, rel);\n let stats: import(\"node:fs\").Stats;\n try {\n stats = statSync(full);\n } catch (cause) {\n // THE REASON THE STAT GAVE, not the one that is usually true. `no such\n // file` for every failure meant `--file loop.app.yml` on a self-referential\n // link answered that a link `ls` can see does not exist, and `EACCES` sent\n // the reader hunting a path that is present and unreadable — while the walk\n // branch, three hundred lines up, named both correctly. Same helper, so the\n // two branches cannot drift apart again.\n const code = (cause as NodeJS.ErrnoException).code ?? EUNKNOWN;\n\n // AND `ENOENT` IS TWO CONDITIONS. `statSync` throws it for a path that is\n // not there and for a link whose target is not there, and only the first is\n // \"no such file\" — `--file stale.app.yml` pointing into a removed worktree\n // was told a link `ls` shows you does not exist, while the walk called the\n // same entry \"the target is gone\". `lstat` separates them for free.\n //\n // Two names rather than one negated conjunction: `absent` being false for\n // `ELOOP` is about the code, not about anything dangling, and collapsing\n // them made a reader tracing `EACCES` re-derive which conjunct fired.\n const dangling = code === \"ENOENT\" && isDanglingLink(full);\n const absent = code === \"ENOENT\" && !dangling;\n const why = whyUnreadable(code);\n\n throw new CliError(absent ? `no such file: ${rel}` : `cannot read ${rel}`, {\n // THE CODE MUST AGREE WITH THE MESSAGE. 5 means the path does not exist,\n // and an agent branches on the number alone — so returning it for a\n // cycle, a permission error or a dangling link tells a caller the\n // opposite of what it was just told in prose, and the actionable answer\n // (\"fix the mode\", \"repair the link\") is one it will never reach.\n code: absent ? ExitCode.NOT_FOUND : ExitCode.FAILURE,\n detail: absent ? undefined : why.reason,\n // ONE RULE FOR BOTH THROWS, now that `CliError` has a `remedy` of its\n // own: the workspace hint always prints, and a remedy — if that arm ever\n // grows one — prints beside it rather than replacing it. The earlier\n // `??` form both displaced the hint and, because `hint` renders through\n // `log.hint`, would have shown the remedy under `→`.\n //\n // No arm of `whyUnreadable` returns a remedy today, so this is dead in\n // exactly the way the deleted `ENOTFILE` fallback was — the difference is\n // that this one costs nothing to be right, where that one was a `??`\n // whose left side could never be taken.\n hint: WHOLE_WORKSPACE_HINT,\n remedy: why.remedy\n });\n }\n if (!stats.isFile()) {\n // Unreachable from the walk, which emits regular files only — this answers\n // a `--file` argument naming something that is not one. FAILURE, not\n // NOT_FOUND: a directory named `x.app.yml` is emphatically there.\n throw new CliError(`not a file: ${rel}`, {\n code: ExitCode.FAILURE,\n detail: stats.isDirectory()\n ? \"it is a directory — a name ending .app.yml does not make one a workspace file\"\n : whyUnreadable(ENOTFILE).reason,\n // Same rule as the sibling above. `ENOTFILE` is not a private code — a\n // FIFO named `x.app.yml` reaches `listSkipped` through `broken` too — so\n // the day that arm grows a remedy, both printers must show it or they\n // disagree about the same file.\n hint: WHOLE_WORKSPACE_HINT,\n remedy: whyUnreadable(ENOTFILE).remedy\n });\n }\n\n let parsed: unknown;\n try {\n parsed = parseYaml(readFileSync(full, \"utf8\"));\n } catch (cause) {\n // A YAML syntax error is the commonest finding of all, and reporting it as\n // a schema violation would send the reader looking at the wrong thing.\n return [\n {\n file: rel,\n path: \"(parse)\",\n message: (cause as Error).message.split(\"\\n\")[0] ?? \"unparsable YAML\"\n }\n ];\n }\n // An empty document parses to `null`, which every schema rejects with a\n // confusing type error. Say what it actually is.\n if (parsed === null || parsed === undefined) {\n return [{ file: rel, path: \"(root)\", message: \"the file is empty\" }];\n }\n\n return validate(parsed) ? [] : describe(rel, validate.errors);\n}\n\nexport function runValidate(flags: ValidateFlags, cwd = process.cwd()): void {\n const compiled = compileAll();\n\n // `cwd` is the base for BOTH paths. It used to be ignored on the `--file`\n // branch, which read `process.cwd()` instead — so the parameter meant two\n // different things depending on a flag.\n const single = flags.file;\n // ONE SPELLING FOR BOTH BRANCHES, so `root` means one thing regardless of the\n // flag. `findWorkspace` compares physical paths and returns one; rooting the\n // `--file` branch at the raw `cwd` left the two disagreeing about how to name\n // the same directory. No output differs from that today — `relative()` is\n // computed against whichever base was used, and each branch agrees with\n // itself — so it is an invariant, not a fix: it keeps the next thing to print\n // `root` from printing two forms.\n const base = physical(resolve(cwd));\n const root = single ? base : findWorkspace(cwd);\n\n // THE ARGUMENT IS NOT RESOLVED, and that is the whole point of the line.\n // `schemaFor` decides a file's KIND from its basename, so following a link\n // here changes what the file is: `ln -s tpl/base.yml my.app.yml` becomes\n // `base.yml`, matches nothing, and `--file my.app.yml` exits USAGE on a file\n // the whole-workspace walk validates happily — `walk` reads directories with\n // `withFileTypes`, and a `Dirent` does not follow links, so it sees the link's\n // own name. In an Oxy workspace the kind of a file IS its name, which makes\n // the walk the correct one and this the branch that had to change back.\n // `base` already carries every bit of canonicalisation this needed.\n const walked: Walked = single\n ? { files: [relative(root, resolve(base, single))], broken: [] }\n : walk(root);\n const { files, broken } = walked;\n\n if (single && !schemaFor(files[0] ?? \"\")) {\n throw new CliError(`oxyc validate does not know how to check ${single}`, {\n code: ExitCode.USAGE,\n hint: `it checks ${SCHEMA_FOR.map(([s]) => s).join(\", \")}`\n });\n }\n if (files.length === 0 && broken.length === 0) {\n // STILL A DOCUMENT ON STDOUT. `--json` promises one, and an empty stdout\n // makes `oxyc validate --json | jq` fail on the one workspace shape where\n // the answer is simply \"nothing to check\".\n if (flags.json) {\n const report: ValidateReport = { checked: 0, unchecked: [], broken: [], findings: [] };\n process.stdout.write(`${JSON.stringify(report, null, 2)}\\n`);\n return;\n }\n log.warn(`no validatable YAML found under ${root}`);\n log.hint(\"oxyc validate --file <path> to check one file\");\n return;\n }\n\n const findings: Finding[] = [];\n const checked: string[] = [];\n const unchecked: SkippedFile<SkipCode>[] = [];\n for (const rel of files) {\n const result = validateFile(root, rel, compiled);\n if (typeof result === \"string\") {\n unchecked.push({ path: rel, code: result });\n continue;\n }\n checked.push(rel);\n findings.push(...result);\n }\n\n // NOTHING READ, BUT SOMETHING NAMED. The commit that changed the word left the\n // number saying `valid`: with every file in `unchecked` or `broken`, stderr\n // said \"N file(s) NOT checked\" and the process exited 0. On `--file` there is\n // no partial answer to defend — the caller named one file, it was never\n // opened, and the command answered success. `util/errors.ts` exists so that\n // \"printed an error and exited 0\" is unrepresentable; this reached it through\n // the verdict rather than through an error.\n //\n // A genuinely EMPTY workspace still exits 0 — that is the case \"nothing to\n // check\" honestly describes, and THE EARLY RETURN ABOVE is what protects it,\n // not the second conjunct here. `checked === 0` on this line already implies\n // something was named: the only ways to get here with nothing checked are\n // every file landing in `unchecked`, or no files and a non-empty `broken`.\n // The conjunct is kept for the arithmetic in the message — \"all 0 candidate\n // file(s) were skipped\" would be nonsense — and is unreachable today, which\n // is said here so it is not mistaken for the discriminator. A mutation\n // removing it does not fail the suite, and no test claims otherwise.\n const nothingRead = checked.length === 0 && unchecked.length + broken.length > 0;\n\n if (flags.json) {\n const report: ValidateReport = { checked: checked.length, unchecked, broken, findings };\n process.stdout.write(`${JSON.stringify(report, null, 2)}\\n`);\n if (findings.length > 0) throw silentFailure(findings.length, checked.length);\n if (nothingRead) throw nothingReadFailure(unchecked.length + broken.length);\n return;\n }\n\n // NAMED, and named BEFORE the verdict. A file that was not read must never be\n // counted as valid — that is the answer a caller acts on. Two reasons a file\n // gets here, kept apart because the fix differs: no schema for its kind in\n // this installation, or a link that could not be followed — with the reason\n // that link actually gave, not one assumed for it.\n // A COUNT ON THE LINE, A REASON WHERE IT BELONGS. The count used to carry the\n // reason, which worked while `unchecked` had one producer and asserted the\n // wrong remedy the moment it had two: \"reinstall\" is right for a schema\n // absent from the installation and useless for a kind `oxyc` does not map at\n // all. Per-file was the first correction and repeated one long sentence ten\n // times; `listSkipped` settles where it goes.\n //\n // The DESCRIPTORS here are the mixed-bucket wording. `unchecked`'s is\n // unreachable today — `KIND_UNKNOWN` cannot be produced by a run, so that\n // bucket always agrees and always hoists — and is written for the day it can.\n listSkipped(\"no schema was applied\", unchecked, whyUnchecked);\n // \"symlink(s)\" was right when this bucket held only links; it now holds a\n // FIFO or device named like a workspace file too, which is not one.\n listSkipped(\"could not read them\", broken, whyUnreadable);\n\n if (findings.length === 0) {\n // `0 file(s) valid` in green was the line a skimmer read when nothing had\n // been opened at all. The earlier fix changed the word to `nothing\n // checked`; making the EXIT CODE agree removes the case entirely, because\n // every way to reach zero checked files now either returns above (a\n // workspace with nothing in it) or throws here. So the branch that printed\n // it is gone rather than left reading as live — `checked.length` is\n // guaranteed non-zero on this line.\n if (nothingRead) throw nothingReadFailure(unchecked.length + broken.length);\n process.stdout.write(`${out.green(`${checked.length} file(s) valid`)}\\n`);\n return;\n }\n\n process.stdout.write(\n `${heading(`${findings.length} problem(s) in ${checked.length} file(s)`)}\\n`\n );\n process.stdout.write(\n `${table(findings, [\n { header: \"FILE\", value: (f) => f.file },\n { header: \"AT\", value: (f) => f.path },\n { header: \"PROBLEM\", value: (f) => f.message }\n ])}\\n`\n );\n log.info(\"structural checks only — `oxy validate` also resolves databases: and llm.ref\");\n throw silentFailure(findings.length, checked.length);\n}\n\n/**\n * Name each skipped file with its reason, capped, and say when the cap bit.\n *\n * ONE SHARED REASON IS PRINTED ONCE. Moving the reason per file fixed a message\n * that asserted one producer's remedy for both — but a workspace where every\n * file was skipped for the same cause then repeated a sentence ten times, which\n * is worse to read than the wrong-remedy line was. So the reason goes on the\n * count when the bucket agrees and beside each path when it does not, which is\n * the only case that needed per-file wording in the first place.\n *\n * The trailing count matters for the same reason: `12 file(s) NOT checked` over\n * ten paths reads as a display bug rather than a cap.\n */\nfunction listSkipped<C extends string>(\n descriptor: string,\n files: SkippedFile<C>[],\n why: (code: C) => SkipReason\n): void {\n // The guard lives beside the print. It was at both call sites while the\n // `log.warn` was too; splitting them left `0 file(s) NOT checked` reachable\n // from any third caller, two functions away from the check preventing it.\n if (files.length === 0) return;\n\n const codes = [...new Set(files.map((f) => f.code))];\n const shared = codes.length === 1 ? why(codes[0] as C) : undefined;\n\n // ONE RULE FOR BOTH BUCKETS: a shared reason REPLACES the category\n // descriptor rather than chaining after it. `1 file(s) NOT checked — could\n // not read them — the target is gone` was two clauses saying one thing, and\n // the other call site had dropped its descriptor to avoid exactly that — so\n // the two headlines were being built to different rules.\n log.warn(`${files.length} file(s) NOT checked — ${shared?.reason ?? descriptor}`);\n\n const SHOWN = 10;\n for (const file of files.slice(0, SHOWN)) {\n log.hint(shared ? file.path : `${file.path} — ${why(file.code).reason}`);\n }\n if (files.length > SHOWN) log.hint(`… and ${files.length - SHOWN} more`);\n\n // REMEDIES LAST, DEDUPED, AND NEVER CHAINED ONTO THE REASON. The one\n // reachable shared headline used to carry both, at 140 characters — and a\n // remedy repeated per file is the noise that made the reason shared in the\n // first place. One line per distinct remedy, after the paths it applies to,\n // through `log.remedy` rather than `log.hint`: `→` elaborates the line above\n // and so reads in sequence with the paths, while a remedy is the one line\n // about what to DO and wants the blank lines that say so.\n //\n // ONE CALL, not a loop: `log.remedy` brackets its whole argument list, so N\n // remedies through N calls would be N blocks with doubled blanks between\n // them. Spreading a possibly-empty array is also what makes that function's\n // emptiness guard reachable rather than protection-shaped.\n const remedies = [...new Set(codes.map((c) => why(c).remedy))].filter((r) => r !== undefined);\n log.remedy(...remedies);\n}\n\n/**\n * Nothing was read, and it was not because there was nothing to read.\n *\n * FAILURE (1), for the same reason `silentFailure` is: the command ran and the\n * answer is bad. The files themselves are already named above — this only\n * supplies the number an agent branches on, which is the half that was saying\n * success.\n *\n * NOT `UNAVAILABLE` (7), though the nearest precedent on this branch — `launch`\n * reporting a missing `claude` — chose 7 on the \"correct invocation, incomplete\n * environment\" framing, and a schema missing from the installation fits that\n * exactly. This throw also covers a workspace whose only candidates were\n * unreadable links, which is a workspace problem and not an install one, so the\n * code covering both has to be the catch-all. Written here because the two\n * commands otherwise answer a same-looking shape with different numbers and\n * nothing in the tree says why.\n */\nfunction nothingReadFailure(named: number): CliError {\n return new CliError(`nothing was checked — all ${named} candidate file(s) were skipped`, {\n code: ExitCode.FAILURE\n });\n}\n\n/**\n * The findings are already printed, so this carries the exit code and nothing\n * else — a second copy of the list on stderr would just be noise.\n */\nfunction silentFailure(findings: number, files: number): CliError {\n // FAILURE (1), not REQUEST (6). The contract documents 6 as \"the server\n // answered 4xx\" and this command never makes a request — an agent branching\n // on 6 would conclude its own call was malformed rather than that the\n // workspace has findings. Same mismatch as `launch` reporting a missing\n // `claude` as USAGE, fixed in an earlier round.\n return new CliError(`${findings} problem(s) across ${files} file(s)`, {\n code: ExitCode.FAILURE\n });\n}\n\n/**\n * The workspace root: the nearest ancestor with a `config.yml`, else `cwd`.\n *\n * Walks UP rather than assuming the cwd, because `oxyc validate` is most\n * useful from wherever you happen to be inside a workspace — and a customer\n * repo keeps its workspace in a subdirectory as often as not.\n */\nfunction findWorkspace(from: string): string {\n // RESOLVED THROUGH SYMLINKS, both sides, or the home stop silently does not\n // fire. `os.homedir()` returns `$HOME` verbatim while `process.cwd()` is\n // `getcwd(3)` and therefore physical — so on a machine whose home or temp\n // directory crosses a link (macOS `$TMPDIR` is under `/var`, itself a link to\n // `/private/var`) the two spellings of one directory never compare equal and\n // the walk climbs straight past it. `git rev-parse --show-toplevel` is\n // physical already, which is why the repo stop was never affected.\n const start = physical(resolve(from));\n const home = physical(resolve(homedir()));\n const fsRoot = parse(start).root;\n // Through `physical` as well, though `git rev-parse --show-toplevel` resolves\n // via getcwd and is already physical for the ordinary case. It costs one call\n // and makes \"every path compared here is physical\" true by construction\n // rather than by an argument about another program's output — and the failure\n // mode if that argument is ever wrong is the silent-inert one above.\n const gitRoot = repoRoot(start);\n const repo = gitRoot === undefined ? undefined : physical(gitRoot);\n\n let dir = start;\n for (;;) {\n // `~` AND `/` ARE NEVER WORKSPACE ROOTS. A `config.yml` at either exists by\n // accident, and adopting one makes the walk below it a whole home directory\n // or a whole filesystem — the original symptom. A git root holding one IS a\n // workspace, so only these two are excluded.\n //\n // This is the half that does the work for a cwd outside home and outside a\n // repo: the climb from `/tmp/x/sub` is not shortened by any stop, so `/`\n // is reached and only this exclusion keeps a stray `/config.yml` from\n // becoming the root. It does NOT protect `/tmp/config.yml`, which is a real\n // ancestor and therefore a plausible workspace — see the note below.\n //\n // Running `oxyc validate` FROM `~` still walks the whole home directory:\n // the exclusion declines to adopt it, the home stop returns `start`, and\n // `start` is `~`. That is asking to validate here, which is a different\n // thing from climbing into it by accident.\n if (dir !== home && dir !== fsRoot && existsSync(join(dir, \"config.yml\"))) return dir;\n\n // Two stops, both observable. The git root is the only real evidence of\n // where a project ends; home bounds a cwd inside it so the walk cannot\n // cross into `/Users` or `/home` and adopt a stray file there. The\n // filesystem root is NOT among them on purpose — `parent === dir` below\n // already returns there, and listing it would be a term that changes\n // nothing while reading as protection.\n if (dir === repo || dir === home) return start;\n\n const parent = resolve(dir, \"..\");\n if (parent === dir) return start;\n dir = parent;\n }\n}\n\n/**\n * Is this a link whose target is missing?\n *\n * `statSync` gives `ENOENT` for both an absent path and a dangling link, and\n * only the first is \"no such file\". `lstat` does not follow, so it succeeds on\n * exactly the second.\n */\nfunction isDanglingLink(path: string): boolean {\n try {\n return lstatSync(path).isSymbolicLink();\n } catch {\n return false;\n }\n}\n\n/**\n * The physical path, or the input when it cannot be resolved.\n *\n * `realpathSync` throws on a path that does not exist, so the fallback is the\n * ordinary case for a `--file` argument naming a typo. Where it matters is\n * `$HOME`: pointed at something unmounted, the raw logical spelling comes back\n * and the HOME STOP goes quiet again — harmless, since there is nothing to walk\n * into under a home that is not there, but worth knowing which guard it is.\n */\nfunction physical(path: string): string {\n try {\n return realpathSync(path);\n } catch {\n return path;\n }\n}\n\n/*\n * NO LEVEL BOUND, deliberately. It would have to be small enough to stop a walk\n * out of `/tmp/x/sub` — two levels — and anything that small refuses a workspace\n * you are legitimately deep inside. Finding a `config.yml` in a real ancestor is\n * the feature; the exclusion above is what keeps \"ancestor\" from meaning `~`\n * or `/`.\n */\n\n/** Exposed for the tests: is this path a directory we would walk into? */\nexport function walkable(name: string): boolean {\n return !SKIP.has(name);\n}\n\n/** Exposed for the tests. */\nexport function listValidatable(root: string): string[] {\n return statSync(root).isDirectory() ? walk(root).files : [];\n}\n","/**\n * Landing one rendered template file into a repo.\n *\n * ONE IMPLEMENTATION, TWO CALLERS. `oxyc update --apply` and `oxyc adopt\n * --apply` both write template files, and if each had its own copy the two\n * would eventually disagree — an installed file that skipped the render, or\n * lost its exec bit, is a second definition of \"install\" that only one of the\n * two paths is ever tested through. That is not hypothetical: it is how a live\n * repo ended up with a `scripts/dev.sh` that had landed but could not run.\n */\n\nimport { chmodSync, mkdirSync, readFileSync, statSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport type { Manifest } from \"./manifest.js\";\nimport { type Substitutions, substitute, templateSourceFor } from \"./render.js\";\n\nexport interface InstallOptions {\n templateDir: string;\n repoDir: string;\n manifest: Manifest;\n subs: Substitutions;\n workspaceRel: string | undefined;\n}\n\n/**\n * Write the named files, rendered.\n *\n * RENDERED, NEVER COPIED: `__NAME__`, `__SLUG__` and `__WORKSPACE__` are\n * placeholders, and a plain copy writes the literal text into a live customer\n * repo. `__WORKSPACE__` is the one that matters most here — this is the path\n * that installs into a repo whose workspace is NOT the root, and a CI workflow\n * that compiles `__WORKSPACE__` is a workflow that can only fail.\n */\nexport function copyRendered(opts: InstallOptions, repoPaths: string[]): string[] {\n const written: string[] = [];\n for (const repoRel of repoPaths) {\n const source = join(opts.templateDir, templateSourceFor(repoRel));\n const target = join(opts.repoDir, repoRel);\n mkdirSync(dirname(target), { recursive: true });\n writeFileSync(target, substitute(readFileSync(source, \"utf8\"), opts.subs));\n try {\n chmodSync(target, statSync(source).mode & 0o777);\n } catch {\n // A filesystem without POSIX modes. The content landed, which is the\n // part that matters; a missing exec bit is reported by `doctor`.\n }\n written.push(repoRel);\n }\n return written;\n}\n","/**\n * The drift engine behind `oxyc update <customer>`: what a customer's repo\n * would look like if the template were rendered into it again, which of those\n * differences oxyc is allowed to do anything about, and — with `--apply` — the\n * writing of the ones it owns.\n *\n * READING IS THE DEFAULT AND WRITING IS THE FLAG, because the safe direction\n * has to be the one you get by accident.\n *\n * THE WALK IS OVER THE TEMPLATE, NEVER OVER THE CUSTOMER'S REPO. A file the\n * template does not ship is never visited, so it can never be named, counted\n * or written. That is what makes `unmatched` safe by construction rather than\n * by remembering.\n *\n * IT NEVER COMMITS, BRANCHES OR PUSHES. Files land in the working tree and\n * that is the end of it; taking that through a branch and a pull request stays\n * a human's job.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nimport { CliError, ExitCode } from \"../util/errors.js\";\nimport { isRepo, workingTreeState } from \"../util/git.js\";\nimport { copyRendered } from \"./install.js\";\nimport { inScope, type Manifest, type Role, roleFor } from \"./manifest.js\";\nimport {\n isSyncable,\n readStamp,\n repoPathFor,\n type Substitutions,\n substitute,\n walkFiles\n} from \"./render.js\";\n\n/** What happened to one template file. */\nexport interface DriftEntry {\n path: string;\n role: Role;\n state: \"same\" | \"differs\" | \"absent\";\n /** The rendered template bytes — what `--apply` would write, for a managed file. */\n rendered: string;\n /** The repo's bytes, when it has the file. */\n current?: string;\n}\n\nexport interface DriftReport {\n entries: DriftEntry[];\n /** Files whose role is `managed` and which differ or are absent. */\n writable: DriftEntry[];\n /** Counts by role, for the one-line summary. */\n counts: Record<Role, number>;\n /** Files skipped because they describe a workspace that lives elsewhere. */\n outOfScope: string[];\n}\n\nexport interface SyncOptions {\n templateDir: string;\n repoDir: string;\n manifest: Manifest;\n subs: Substitutions;\n /** The workspace path relative to the repo root, or `undefined` when none. */\n workspaceRel: string | undefined;\n}\n\n/**\n * Compare the repo against a re-render of the template.\n *\n * Computes and decides nothing about what to do; the caller reports and the\n * caller applies. Split out so the report and the apply walk the same tree in\n * the same order and cannot come to different conclusions about it — a report\n * that named eight files and an apply that wrote nine is the failure this\n * shape removes.\n */\nexport function computeDrift(opts: SyncOptions): DriftReport {\n const entries: DriftEntry[] = [];\n const outOfScope: string[] = [];\n const counts: Record<Role, number> = { managed: 0, scaffold: 0, mixed: 0, unmatched: 0 };\n\n for (const templateRel of walkFiles(opts.templateDir)) {\n const repoRel = repoPathFor(templateRel);\n\n // A template file describing the Oxy WORKSPACE describes nothing at the\n // root of a repo that keeps its workspace in `oxy/` — comparing it there\n // would report a file this repo will never have, on every run, forever.\n if (!inScope(opts.manifest, repoRel, opts.workspaceRel)) {\n outOfScope.push(repoRel);\n continue;\n }\n\n const role = roleFor(opts.manifest, repoRel);\n // `unmatched` is the customer's. The walk visits it because it is in the\n // template, but nothing is reported and nothing is written.\n if (role === \"unmatched\") continue;\n counts[role] += 1;\n\n const rendered = substitute(\n readFileSync(join(opts.templateDir, templateRel), \"utf8\"),\n opts.subs\n );\n const target = join(opts.repoDir, repoRel);\n\n if (!existsSync(target)) {\n entries.push({ path: repoRel, role, state: \"absent\", rendered });\n continue;\n }\n const current = readFileSync(target, \"utf8\");\n entries.push({\n path: repoRel,\n role,\n state: current === rendered ? \"same\" : \"differs\",\n rendered,\n current\n });\n }\n\n return {\n entries,\n // ONLY `managed`. A `scaffold` file is the customer's from the moment it\n // landed and a `mixed` one holds their bytes beside ours — update reports\n // both and rewrites neither. `oxyc adopt` is the only command that may\n // install a missing `mixed` file, and only because an imported repo never\n // had one to protect.\n writable: entries.filter((e) => e.role === \"managed\" && e.state !== \"same\"),\n counts,\n outOfScope\n };\n}\n\n/**\n * Refuse to write into a repo oxyc cannot prove it wrote.\n *\n * The proof is `.oxyc-template.json`. Every imported repo has none, so every\n * imported repo is refused — correct, and also terminal, which is exactly why\n * `oxyc adopt` exists as the one explicit act that ends it.\n */\nexport function requireSyncable(repoDir: string): void {\n const stamp = readStamp(repoDir);\n if (!stamp) {\n throw new CliError(\n `${repoDir} carries no ${\"`.oxyc-template.json`\"}, so oxyc cannot prove it rendered it`,\n {\n code: ExitCode.REFUSED,\n hint: \"oxyc adopt <customer> --apply — the one-time act that makes an imported repo syncable\"\n }\n );\n }\n if (!isSyncable(repoDir)) {\n throw new CliError(`${repoDir} is marked as imported, so oxyc will not rewrite its files`, {\n code: ExitCode.REFUSED,\n detail: `provenance: ${stamp.provenance}`,\n hint: \"somebody wrote that down on purpose — `oxyc adopt` is the path, if it should be syncable\"\n });\n }\n}\n\n/**\n * Refuse to apply while the TEMPLATE tree has uncommitted changes.\n *\n * The stamp an apply writes names the commit it synced from. With a dirty\n * template that commit does not describe the bytes that were copied, so the\n * stamp would be a lie — and a later drift report computed against it would be\n * confidently wrong.\n */\nexport function requireCleanTemplate(templateRoot: string): void {\n if (!isRepo(templateRoot)) return;\n const state = workingTreeState(templateRoot);\n if (!state.dirty && state.untracked.length === 0) return;\n throw new CliError(\"the template tree has uncommitted changes\", {\n code: ExitCode.REFUSED,\n detail: [...state.modified, ...state.untracked]\n .slice(0, 10)\n .map((p) => ` ${p}`)\n .join(\"\\n\"),\n hint: \"commit them first — otherwise the stamp would name a commit whose contents were not what got copied\"\n });\n}\n\n/**\n * Write the managed files.\n *\n * NEVER RE-WALKS: `report` has already decided, so the files written are\n * exactly the files it named. A report that named eight and an apply that\n * wrote nine is the failure the split exists to remove.\n *\n * Delegates the writing itself to `copyRendered`, which `oxyc adopt` also\n * uses — one definition of \"install\", so the two commands cannot come to\n * write files differently.\n */\nexport function applyDrift(opts: SyncOptions, report: DriftReport): string[] {\n return copyRendered(\n opts,\n report.writable.map((entry) => entry.path)\n );\n}\n\n/**\n * A capped unified-ish diff of one file.\n *\n * A MIXED file is shown as a DIFF, not just named: it is the role the tool\n * refuses to write and hands back to you, so \"differs, yours to merge\" without\n * \"merge what?\" has stopped one step short. Capped because an uncapped diff of\n * a lockfile is the noise that teaches people to skim.\n */\nexport function renderDiff(entry: DriftEntry, limit: number): string[] {\n if (entry.current === undefined) return [];\n const template = entry.rendered.split(\"\\n\");\n const yours = entry.current.split(\"\\n\");\n const out: string[] = [];\n const max = Math.max(template.length, yours.length);\n for (let i = 0; i < max; i++) {\n const t = template[i];\n const y = yours[i];\n if (t === y) continue;\n if (t !== undefined) out.push(` TEMPLATE ${t}`);\n if (y !== undefined) out.push(` YOURS ${y}`);\n if (limit > 0 && out.length >= limit) {\n out.push(` … capped at ${limit} lines (OXYC_DIFF_LINES=0 to remove the cap)`);\n break;\n }\n }\n return out;\n}\n\n/** The diff cap. `OXYC_DIFF_LINES=0` removes it. */\nexport function diffLimit(): number {\n const raw = process.env.OXYC_DIFF_LINES;\n if (raw === undefined) return 40;\n const parsed = Number(raw);\n return Number.isFinite(parsed) && parsed >= 0 ? parsed : 40;\n}\n","/**\n * `oxyc doctor`, `oxyc update`, `oxyc adopt` — the three commands that read a\n * customer repo and, for two of them, write into it.\n *\n * They share one walk (`computeDrift` / `planAdopt`) so that what `doctor`\n * reports, what `update` would write, and what `adopt` would install cannot\n * come to different conclusions about the same repo.\n */\n\nimport { existsSync } from \"node:fs\";\n\nimport type { Context } from \"../context/resolve.js\";\nimport { dossierPath, isCloned } from \"../customer/dossier.js\";\nimport { memoryDir, resolveWorkspace } from \"../customer/workspace.js\";\nimport { customersOrg, displayName, listCustomers, resolveCustomer } from \"../github/customers.js\";\nimport {\n ADOPT_GENERATED_BY,\n assertAdoptable,\n planAdopt,\n refuseOnCollision\n} from \"../template/adopt.js\";\nimport { copyRendered } from \"../template/install.js\";\nimport { manifestPath, templateDir, templateRepoRoot } from \"../template/locate.js\";\nimport { loadManifest } from \"../template/manifest.js\";\nimport { generatedBy, readStamp, writeStamp } from \"../template/render.js\";\nimport {\n applyDrift,\n computeDrift,\n diffLimit,\n renderDiff,\n requireCleanTemplate,\n requireSyncable\n} from \"../template/sync.js\";\nimport * as log from \"../ui/log.js\";\nimport { heading } from \"../ui/render.js\";\nimport { out } from \"../ui/tty.js\";\nimport { CliError, ExitCode } from \"../util/errors.js\";\n\n/** Everything the three commands need about one customer's repo. */\ninterface RepoView {\n name: string;\n display: string;\n slug: string;\n repoDir: string;\n cloned: boolean;\n workspaceRel: string | undefined;\n}\n\nfunction viewFor(name: string, refresh: boolean | undefined): RepoView {\n const customer = resolveCustomer(name, { refresh });\n const slug = `${customersOrg()}/${customer.name}`;\n const repoDir = dossierPath(slug);\n const cloned = isCloned(slug);\n return {\n name: customer.name,\n display: displayName(customer),\n slug,\n repoDir,\n cloned,\n // Resolution can throw on an ambiguous repo; that is a fact `doctor` wants\n // to report rather than crash on, so it is caught per caller.\n workspaceRel: cloned ? resolveWorkspace(repoDir) : undefined\n };\n}\n\nfunction requireClone(view: RepoView): void {\n if (view.cloned) return;\n throw new CliError(`${view.slug} is not cloned here`, {\n code: ExitCode.NOT_FOUND,\n hint: `gh repo clone ${view.slug} ${view.repoDir}`\n });\n}\n\nfunction substitutionsFor(view: RepoView) {\n return {\n slug: view.name,\n name: view.display,\n workspace: view.workspaceRel ?? \".\"\n };\n}\n\n// ── doctor ──────────────────────────────────────────────────────────────────\n\n/**\n * What the tool knows about a customer, said out loud, having written nothing.\n *\n * READ-ONLY IS THE WHOLE CONTRACT. There is no `--fix`, and deliberately no\n * path here that creates so much as a directory — `memoryDir` is called rather\n * than `ensureMemoryDir`, drift is computed without applying, and no stamp is\n * written. `update --apply` and `adopt --apply` do the writing; this exists so\n * somebody can see what they would do before they do it.\n */\nexport function runDoctor(ctx: Context, name: string | undefined, flags: { all?: boolean }): void {\n const names = flags.all\n ? listCustomers({ refresh: ctx.flags.refresh }).map((c) => c.name)\n : [requireName(name)];\n\n for (const each of names) {\n reportOne(ctx, each);\n }\n}\n\nfunction requireName(name: string | undefined): string {\n if (name) return name;\n throw new CliError(\"doctor needs a customer, or --all\", {\n code: ExitCode.USAGE,\n hint: \"oxyc doctor <customer> | oxyc doctor --all\"\n });\n}\n\nfunction reportOne(ctx: Context, name: string): void {\n let view: RepoView;\n try {\n view = viewFor(name, ctx.flags.refresh);\n } catch (cause) {\n process.stdout.write(`${heading(name)}\\n ${out.red((cause as Error).message)}\\n`);\n return;\n }\n\n const lines: string[] = [\n ` repo ${view.slug}`,\n ` display ${view.display}`,\n ` clone ${view.cloned ? view.repoDir : out.yellow(\"not here\")}`\n ];\n\n if (!view.cloned) {\n lines.push(` ${out.dim(`gh repo clone ${view.slug} ${view.repoDir}`)}`);\n process.stdout.write(`${heading(name)}\\n${lines.join(\"\\n\")}\\n`);\n return;\n }\n\n // A workspace in a SUBDIRECTORY is reported as a FACT, not a fault: the\n // platform's registered subdirectory was fixed at onboarding and nothing\n // re-opens that field, so there is nothing here to correct.\n lines.push(\n ` workspace ${\n view.workspaceRel === undefined\n ? out.yellow(\"none — this repo holds no Oxy workspace\")\n : view.workspaceRel === \".\"\n ? \"the repo root\"\n : `${view.workspaceRel}/ (subdirectory — registered at onboarding, do not flatten)`\n }`\n );\n lines.push(\n ` memory ${existsSync(memoryDir(view.repoDir)) ? \"present\" : \"absent (a launch would create it)\"}`\n );\n\n const stamp = readStamp(view.repoDir);\n const by = generatedBy(view.repoDir);\n lines.push(\n ` provenance ${stamp ? `${stamp.provenance}${by ? ` (by ${by})` : \"\"}` : out.yellow(\"imported — no stamp\")}`\n );\n\n const manifest = loadManifest(manifestPath());\n const subs = substitutionsFor(view);\n\n if (stamp && stamp.syncable !== false && stamp.provenance !== \"imported\") {\n const drift = computeDrift({\n templateDir: templateDir(),\n repoDir: view.repoDir,\n manifest,\n subs,\n workspaceRel: view.workspaceRel\n });\n const differs = drift.entries.filter((e) => e.state !== \"same\");\n lines.push(` update syncable — ${describeDrift(differs)}`);\n } else {\n // For a repo `update` refuses, the ADOPTION GAP is the useful answer:\n // which files `adopt --apply` would install and this repo lacks.\n const plan = planAdopt(\n {\n templateDir: templateDir(),\n repoDir: view.repoDir,\n manifest,\n subs,\n workspaceRel: view.workspaceRel\n },\n by === ADOPT_GENERATED_BY\n );\n const gap = plan.install.length + plan.installMixed.length;\n lines.push(\n ` update refused (no proof oxyc wrote it) — adoption gap: ${gap} file(s)` +\n (plan.collisions.length ? `, ${plan.collisions.length} collision(s)` : \"\")\n );\n for (const path of [...plan.install, ...plan.installMixed].slice(0, 12)) {\n lines.push(` ${out.dim(`missing ${path}`)}`);\n }\n }\n\n process.stdout.write(`${heading(name)}\\n${lines.join(\"\\n\")}\\n`);\n}\n\nfunction describeDrift(differs: { role: string }[]): string {\n if (differs.length === 0) return \"in line with the template\";\n const byRole = differs.reduce<Record<string, number>>((acc, e) => {\n acc[e.role] = (acc[e.role] ?? 0) + 1;\n return acc;\n }, {});\n return Object.entries(byRole)\n .map(([role, count]) => `${count} ${role}`)\n .join(\", \");\n}\n\n// ── update ──────────────────────────────────────────────────────────────────\n\nexport interface UpdateFlags {\n apply?: boolean;\n diffAll?: boolean;\n}\n\n/**\n * Report how far a customer's repo has drifted from the template, and with\n * `--apply` rewrite the files oxyc owns.\n *\n * A MIXED file is shown as a DIFF, not just named: it is the role the tool\n * refuses to write and hands back to you, so \"differs, yours to merge\" without\n * \"merge what?\" has stopped one step short.\n */\nexport function runUpdate(ctx: Context, name: string, flags: UpdateFlags): void {\n const view = viewFor(name, ctx.flags.refresh);\n requireClone(view);\n requireSyncable(view.repoDir);\n\n const opts = {\n templateDir: templateDir(),\n repoDir: view.repoDir,\n manifest: loadManifest(manifestPath()),\n subs: substitutionsFor(view),\n workspaceRel: view.workspaceRel\n };\n const drift = computeDrift(opts);\n const differs = drift.entries.filter((e) => e.state !== \"same\");\n\n process.stdout.write(`${heading(`${view.name} — ${view.repoDir}`)}\\n`);\n\n if (differs.length === 0) {\n process.stdout.write(\" in line with the template\\n\");\n return;\n }\n\n const limit = diffLimit();\n for (const entry of differs) {\n const label = entry.state === \"absent\" ? \"MISSING \" : \"DIFFERS \";\n const style = entry.role === \"managed\" ? out.yellow : out.dim;\n process.stdout.write(` ${style(label)}${entry.role.padEnd(9)}${entry.path}\\n`);\n // scaffold drift stays a one-liner: `config.yml` and `README.md` are\n // customised the day they are created, so that drift is expected and\n // permanent, and diffing it every run is the noise that teaches people to\n // skim. `--diff-all` is how you read what `--apply` is about to overwrite.\n const worthDiffing = flags.diffAll || entry.role === \"mixed\";\n if (worthDiffing && entry.state === \"differs\") {\n for (const line of renderDiff(entry, limit)) process.stdout.write(` ${line}\\n`);\n }\n }\n\n if (!flags.apply) {\n process.stdout.write(\n `\\n ${out.dim(`${drift.writable.length} managed file(s) would be rewritten by \\`oxyc update ${name} --apply\\``)}\\n`\n );\n return;\n }\n\n requireCleanTemplate(templateRepoRoot());\n const written = applyDrift(opts, drift);\n // Re-point the stamp at the commit that was just synced from, so the next\n // run measures from a known point.\n writeStamp(view.repoDir, templateRepoRoot(), \"oxyc update\", new Date().toISOString());\n process.stdout.write(`\\n ${out.green(`wrote ${written.length} file(s)`)}\\n`);\n log.info(\"nothing was committed — the change rides your pull request like any other\");\n}\n\n// ── adopt ───────────────────────────────────────────────────────────────────\n\n/**\n * Give an IMPORTED repo the managed files, then stamp it so `update` works.\n *\n * Report is the default and writing is the flag, as with `update`, and for the\n * same reason.\n */\nexport function runAdopt(ctx: Context, name: string, flags: { apply?: boolean }): void {\n const view = viewFor(name, ctx.flags.refresh);\n requireClone(view);\n\n if (view.workspaceRel === undefined) {\n // The managed files are machinery FOR a workspace. Installing CI that\n // compiles a workspace into a repo that has none would land a workflow\n // that can only fail.\n throw new CliError(`${view.slug} holds no Oxy workspace`, {\n code: ExitCode.REFUSED,\n hint: \"the managed files are machinery for a workspace — there is nothing here for them to act on\"\n });\n }\n\n const { completing } = assertAdoptable(view.repoDir);\n const opts = {\n templateDir: templateDir(),\n repoDir: view.repoDir,\n manifest: loadManifest(manifestPath()),\n subs: substitutionsFor(view),\n workspaceRel: view.workspaceRel\n };\n const plan = planAdopt(opts, completing);\n\n process.stdout.write(`${heading(`${view.name} — ${view.repoDir}`)}\\n`);\n refuseOnCollision(plan, view.slug);\n\n if (plan.install.length === 0 && plan.installMixed.length === 0) {\n process.stdout.write(` ${out.green(\"nothing left to install\")}\\n`);\n return;\n }\n\n for (const path of plan.install)\n process.stdout.write(` ${out.yellow(\"WOULD ADD\")} managed ${path}\\n`);\n for (const path of plan.installMixed)\n process.stdout.write(` ${out.yellow(\"WOULD ADD\")} mixed ${path}\\n`);\n if (plan.alreadyHere.length > 0) {\n process.stdout.write(\n ` ${out.dim(`${plan.alreadyHere.length} managed file(s) an earlier adopt already landed`)}\\n`\n );\n }\n if (plan.installMixed.length > 0) {\n // The rule that just operated, said out loud — without it, `WOULD ADD\n // package.json` sitting in a column of managed files contradicts the\n // manifest, which says a mixed file is never written.\n process.stdout.write(\n ` ${out.dim(\"a MIXED file is installed only because this repo does not have it; one that is present is never touched\")}\\n`\n );\n }\n\n if (!flags.apply) {\n process.stdout.write(`\\n ${out.dim(`oxyc adopt ${name} --apply to install them`)}\\n`);\n return;\n }\n\n const written = copyRendered(opts, [...plan.install, ...plan.installMixed]);\n // The stamp is left exactly where it is on a completing run: this repo's\n // claim is already written, and re-stamping would move the point a later\n // drift report measures from for no reason.\n if (!completing) {\n writeStamp(view.repoDir, templateRepoRoot(), ADOPT_GENERATED_BY, new Date().toISOString());\n }\n process.stdout.write(`\\n ${out.green(`installed ${written.length} file(s)`)}\\n`);\n process.stdout.write(\n ` ${out.dim(\"publish.yaml discovers apps under `apps/` only — an adopted repo that keeps them elsewhere gets a workflow that finds nothing (a safe no-op)\")}\\n`\n );\n log.info(\"nothing was committed — the change rides your pull request like any other\");\n}\n","/**\n * The merge point of the two tools.\n *\n * `oxyc`'s customer half knows WHO — which customer, where their repo is, what\n * org they are. `oxyc`'s API half knows HOW to ask a deployment a question.\n * This is what joins them: one resolution that produces both halves, so\n * `oxyc api {org}/workspaces` works from inside a customer repo without\n * anyone typing an id.\n *\n * `gh api` does the same trick with `{owner}` and `{repo}` read off the git\n * remote, and it is the single feature that makes that command usable from\n * memory. Everything here exists to make ours as cheap to use.\n *\n * RESOLUTION IS LAZY AND PARTIAL, deliberately. `oxyc routes` needs a target\n * and no customer; `oxyc list` needs neither. Resolving everything eagerly\n * would make a command fail on a fact it never uses — which is how a tool\n * ends up demanding a GitHub login to print its own help.\n */\n\nimport type { PlaceholderValues } from \"../api/paths.js\";\nimport { loadCredential, resolveBearer } from \"../auth/credentials.js\";\nimport { dossierPath, isCloned, slugForDirectory } from \"../customer/dossier.js\";\nimport { type Customer, customersOrg, resolveCustomer } from \"../github/customers.js\";\nimport { authError, CliError, ExitCode } from \"../util/errors.js\";\nimport { repoRoot } from \"../util/git.js\";\nimport { loadManifest, type OxyAppManifest, type ResolvedEnv, resolveEnv } from \"./target.js\";\n\n/** Flags every command shares. Kept in one shape so `main.ts` wires them once. */\nexport interface GlobalFlags {\n env?: string;\n target?: string;\n tokenEnv?: string;\n apiKeyEnv?: string;\n org?: string;\n workspace?: string;\n project?: string;\n customer?: string;\n refresh?: boolean;\n}\n\n/** Everything a command might need, resolved on demand. */\nexport interface Context {\n readonly cwd: string;\n readonly flags: GlobalFlags;\n readonly manifest?: OxyAppManifest;\n\n /** The deployment to talk to. Throws when nothing resolves. */\n target(): string;\n /** The resolved env, including the org slug a pasted URL carried. */\n env(): ResolvedEnv;\n /** The bearer, or a thrown `authError` naming the login command. */\n bearer(): string;\n /** The bearer if there is one, without throwing. */\n maybeBearer(): string | undefined;\n /** The API key for the `/external/api` surface, if one is configured. */\n apiKey(): string | undefined;\n /** The customer this invocation is about, if it is about one. */\n customer(): Customer | undefined;\n /** The customer's repo checkout on this machine, if it is here. */\n repoDir(): string | undefined;\n /** Values for `{org}` / `{workspace}` / … in a path. */\n placeholders(): PlaceholderValues;\n /**\n * The same invocation pointed at a different deployment.\n *\n * For `oxyc login --login-env dev,staging`, which is several independent acts\n * rather than one act with several targets — each needs its own resolved\n * env, and a `Context` memoizes the one it was built with. Rebuilding is\n * cheaper than making every consumer take a target parameter it has no use\n * for; `--target` is dropped, because it overrides `--env` and carrying it\n * would point all of them at one host.\n */\n withEnv(env: string): Context;\n}\n\n/**\n * Build the context for one invocation.\n *\n * Every accessor memoises, so a command that asks for the bearer three times\n * reads the credentials file once — and, more importantly, a command that\n * never asks never touches the network or the disk at all.\n */\nexport function createContext(flags: GlobalFlags, cwd = process.cwd()): Context {\n const manifest = loadManifest(cwd);\n const memo = new Map<string, unknown>();\n\n const once = <T>(key: string, compute: () => T): T => {\n if (!memo.has(key)) memo.set(key, compute());\n return memo.get(key) as T;\n };\n\n const env = (): ResolvedEnv =>\n once(\"env\", () => {\n const resolved = resolveEnv(flags.env ?? \"production\", flags.target, manifest);\n if (!resolved) {\n throw new CliError(`could not resolve a target for --env ${flags.env}`, {\n code: ExitCode.USAGE,\n hint: \"pass --target <url>, use a URL as the env (--env https://…), or add it to oxy-app.json environments\"\n });\n }\n return resolved;\n });\n\n const customer = (): Customer | undefined =>\n once(\"customer\", () => {\n // An explicit --customer (or a positional the launcher already resolved)\n // wins. Otherwise infer from the checkout we are standing in, which is\n // what makes the placeholders free inside a customer session.\n if (flags.customer) return resolveCustomer(flags.customer, { refresh: flags.refresh });\n const slug = slugForDirectory(cwd);\n if (!slug) return undefined;\n const [, name] = slug.split(\"/\");\n if (!name) return undefined;\n try {\n return resolveCustomer(name, { refresh: flags.refresh });\n } catch {\n // Standing in one of OUR repos, or any repo that is not a customer.\n // Not an error: most invocations are not about a customer at all.\n return undefined;\n }\n });\n\n const repoDir = (): string | undefined =>\n once(\"repoDir\", () => {\n const found = customer();\n if (found) {\n const slug = `${customersOrg()}/${found.name}`;\n if (isCloned(slug)) return dossierPath(slug);\n }\n // `--here`: working in one of our own repos on a customer's behalf.\n return repoRoot(cwd);\n });\n\n return {\n cwd,\n flags,\n manifest,\n env,\n // `target: undefined` on purpose: it overrides `--env`, so carrying it\n // would point every rebuilt context at one host — which is the opposite of\n // what asking for a different env means.\n withEnv: (next: string) => createContext({ ...flags, env: next, target: undefined }, cwd),\n target: () => env().target,\n maybeBearer: () =>\n once(\"bearer\", () => resolveBearer(env().target, flags.tokenEnv ?? \"OXY_TOKEN\")),\n bearer() {\n const token = this.maybeBearer();\n if (!token)\n throw authError(env().target, flags.env ?? \"production\", flags.tokenEnv ?? \"OXY_TOKEN\");\n return token;\n },\n apiKey: () => {\n const name = flags.apiKeyEnv ?? \"OXY_API_KEY\";\n return process.env[name]?.trim() || undefined;\n },\n customer,\n repoDir,\n placeholders: () =>\n once(\"placeholders\", () => {\n const found = customer();\n const values: PlaceholderValues = {\n // `--org` wins, then the org a pasted `--env` URL named, then the\n // customer's own slug. The URL is ahead of the customer because\n // pasting an address bar is a deliberate act of naming an org.\n org: flags.org ?? env().orgSlug ?? found?.name,\n workspace: flags.workspace,\n project: flags.project,\n customer: found?.name,\n me: loadCredential(env().target)?.email\n };\n // A workspace id was not passed and the repo is here: the workspace is\n // a directory, not an id, so it cannot fill {workspace}. Left unset so\n // the placeholder error says how to find one rather than substituting\n // a path into a URL.\n return values;\n })\n };\n}\n","/**\n * \"Did you mean…?\" for a token that is not a command.\n *\n * ITS OWN MODULE, and that is the whole point. It used to live in `main.ts`,\n * which meant the test had to import the ENTRY module to reach it — and that\n * in turn needed an `isEntryPoint()` guard so importing did not start the CLI\n * on the importer's argv. That guard compared `resolve(process.argv[1])`\n * against `import.meta.url`, which is wrong the moment an npm bin is involved:\n * `npm i -g` installs `…/bin/oxyc` as a SYMLINK to `dist/main.mjs`, `resolve()`\n * does not follow links, so the comparison fails, `main()` never runs, and the\n * binary prints nothing and exits 0 — the worst possible shape for a tool an\n * agent branches on the exit code of, and invisible to a test that spawns the\n * real path.\n *\n * Moving the function here deletes the guard and the bug with it. Nothing in\n * `main.ts` needs to be importable any more.\n */\n\n/**\n * The nearest command name within one or two edits, if there is one.\n *\n * Two is the usual cutoff for a suggestion: it catches a transposition\n * (`rotues`) and a doubled or dropped letter, without claiming that\n * `pokehouse` was a mistyped `doctor`. Short tokens get a tighter bound, since\n * two edits on a four-letter word is most of the word.\n *\n * TIES GO TO THE FIRST NAME IN THE LIST, deliberately and not by accident:\n * `<` rather than `<=` below. The caller passes commands in declaration order,\n * so a tie is resolved the same way on every run and by every machine — an\n * arbitrary but STABLE answer. Resolving it by \"whichever came last\" would\n * make the suggestion depend on how `buildProgram` happens to be ordered, and\n * that ordering changes whenever somebody adds a command.\n */\nexport function didYouMeanCommand(typed: string, known: string[]): string | undefined {\n const budget = typed.length <= 4 ? 1 : 2;\n let best: string | undefined;\n let bestDistance = budget + 1;\n for (const name of known) {\n const d = editDistance(typed, name);\n if (d < bestDistance) {\n bestDistance = d;\n best = name;\n }\n }\n return bestDistance <= budget ? best : undefined;\n}\n\n/** Levenshtein, iterative and allocation-light — the list is ~25 names. */\nexport function editDistance(a: string, b: string): number {\n let previous = Array.from({ length: b.length + 1 }, (_, i) => i);\n for (let i = 1; i <= a.length; i++) {\n const current = [i];\n for (let j = 1; j <= b.length; j++) {\n current[j] = Math.min(\n (previous[j] ?? 0) + 1,\n (current[j - 1] ?? 0) + 1,\n (previous[j - 1] ?? 0) + (a[i - 1] === b[j - 1] ? 0 : 1)\n );\n }\n previous = current;\n }\n return previous[b.length] ?? Number.MAX_SAFE_INTEGER;\n}\n","/**\n * `oxyc` — the command tree.\n *\n * Two halves under one root, joined by `createContext`:\n *\n * the PLATFORM half api / routes / schema / openapi / login / whoami\n * the CUSTOMER half list / path / new / import / doctor / …\n *\n * HELP IS SHORT ON PURPOSE. The Rust `oxy api --help` appended all ~600 routes\n * to its epilogue, which made `--help` a 400-line document — unreadable for a\n * human and, for the agent this tool is built for, several thousand tokens\n * spent before the first request. Discovery lives in `oxyc routes <filter>`,\n * which answers the same question and can be narrowed.\n *\n * This file is also the ONLY place that calls `process.exit`, so every path\n * out of the program goes through one renderer and one exit-code decision.\n */\n\nimport { Command } from \"commander\";\nimport { clearAllCaches, unknownCacheEntries } from \"./api/cache.js\";\nimport { runActivity } from \"./commands/activity.js\";\nimport { runApi } from \"./commands/api.js\";\nimport { runAssumeEnd, runAssumeStart, runAssumeStatus } from \"./commands/assume.js\";\nimport { runLogin, runLogout, runToken, runWhoami } from \"./commands/auth.js\";\nimport { runList, runPath } from \"./commands/customers.js\";\nimport { runOpenApi, runRoutes, runSchema } from \"./commands/discover.js\";\nimport { runGuide } from \"./commands/guide.js\";\nimport { runLaunch } from \"./commands/launch.js\";\nimport { runProxy } from \"./commands/proxy.js\";\nimport { runImport, runNew, runRemove } from \"./commands/registry.js\";\nimport { runRepos } from \"./commands/repos.js\";\nimport { runSkillsInstall, runSkillsList } from \"./commands/skills.js\";\nimport { runValidate } from \"./commands/validate.js\";\nimport { runAdopt, runDoctor, runUpdate } from \"./commands/workspace.js\";\nimport { createContext, type GlobalFlags } from \"./context/resolve.js\";\nimport * as log from \"./ui/log.js\";\nimport { err } from \"./ui/tty.js\";\nimport { CliError, ExitCode, usageError } from \"./util/errors.js\";\nimport { didYouMeanCommand } from \"./util/suggest.js\";\n\n/** Flags every command accepts, declared once and attached to each. */\nfunction withGlobals(command: Command): Command {\n return (\n command\n .option(\"--env <name|url>\", \"environment or URL to target\", \"production\")\n .option(\"--target <url>\", \"explicit base URL; overrides --env\")\n .option(\"--token-env <VAR>\", \"env var holding the bearer token\", \"OXY_TOKEN\")\n .option(\"--api-key-env <VAR>\", \"env var holding the API key for /external/api\", \"OXY_API_KEY\")\n .option(\"--org <slug>\", \"value for the {org} placeholder\")\n .option(\"--workspace <id>\", \"value for the {workspace} placeholder\")\n .option(\"--project <id>\", \"value for the {project} placeholder\")\n .option(\"--customer <name>\", \"act as though run inside this customer's repo\")\n // No `-q` short form: `gh api` spells the jq filter `-q, --jq`, and that\n // spelling is worth more than a short flag for quiet.\n .option(\"--quiet\", \"suppress progress messages on stderr\")\n );\n}\n\n/** Turn commander's parsed options into the shape the context wants. */\n/**\n * `--login-env a --login-env b` and `--login-env a,b` are the same set.\n *\n * Commander appends per occurrence; splitting on commas inside the reducer is\n * what makes the two spellings equivalent, which is what `oxy login` accepts\n * and therefore what a reader coming from it will type.\n */\nfunction collectEnvs(value: string, previous: string[]): string[] {\n const parts = value\n .split(\",\")\n .map((v) => v.trim())\n .filter(Boolean);\n return [...previous, ...parts];\n}\n\nfunction globals(opts: Record<string, unknown>): GlobalFlags {\n if (opts.quiet) process.env.OXYC_QUIET = \"1\";\n return {\n env: opts.env as string | undefined,\n target: opts.target as string | undefined,\n tokenEnv: opts.tokenEnv as string | undefined,\n apiKeyEnv: opts.apiKeyEnv as string | undefined,\n org: opts.org as string | undefined,\n workspace: opts.workspace as string | undefined,\n project: opts.project as string | undefined,\n customer: opts.customer as string | undefined,\n refresh: opts.refresh as boolean | undefined\n };\n}\n\nfunction buildProgram(): Command {\n const program = new Command(\"oxyc\")\n .description(\"The Oxy CLI — talk to the API, and work on a customer account.\")\n .version(\"0.1.0\")\n .showHelpAfterError(\"(run `oxyc --help`)\")\n .configureOutput({\n // ONLY `writeErr` is redirected, and the distinction matters. commander\n // uses `writeOut` for an explicit `--help` / `--version` — a SUCCESSFUL\n // invocation whose help text IS the answer, so `oxyc api --help | less`\n // and `oxyc routes --help | grep workspaces` have to work. It uses\n // `writeErr` for usage errors and help-after-error, which must not land\n // in the middle of piped JSON. `gh` splits them the same way.\n //\n // The stdout-purity rule this defends is about *data* output; no failure\n // path reaches `writeOut`.\n writeErr: (str) => process.stderr.write(str)\n });\n\n // ── the platform half ────────────────────────────────────────────────────\n\n withGlobals(\n program\n .command(\"api\")\n .argument(\"<path>\", \"path, relative to /api (a leading / or api/ is fine)\")\n .description(\"make an authenticated request to the Oxy API\")\n .option(\"-X, --method <verb>\", \"HTTP method (default GET, or POST with a body)\")\n .option(\"-f, --raw-field <key=value>\", \"string parameter\", collect, [])\n .option(\"-F, --field <key=value>\", 'typed parameter (true/3/[\"a\"]/@file/@-)', collect, [])\n .option(\"-H, --header <name:value>\", \"extra header\", collect, [])\n .option(\"--input <file|->\", \"raw request body from a file, or - for stdin\")\n .option(\"-q, --jq <expr>\", \"filter the response through jq\")\n .option(\"--md\", \"render an array of objects as a markdown table\")\n .option(\"--paginate\", \"follow every page and return one document\")\n .option(\"--paginate-key <field>\", \"the field holding the rows, when the guess is wrong\")\n .option(\"--max-pages <n>\", \"stop after n pages (default 100)\")\n .option(\"--slurp\", \"with --paginate, emit an array of pages instead of merging\")\n .option(\"--cache <duration>\", \"reuse a recent successful GET (30s, 5m, 2h)\")\n .option(\"-i, --include\", \"print the status line and response headers\")\n .option(\"--silent\", \"make the request, print nothing\")\n .option(\"--verbose\", \"log the request before making it\")\n .option(\"--timeout <duration>\", \"request timeout (default 2m)\")\n .addHelpText(\"after\", API_HELP)\n ).action(async (path: string, opts: Record<string, unknown>) => {\n const ctx = createContext(globals(opts));\n await runApi(ctx, path, {\n method: opts.method as string | undefined,\n rawField: opts.rawField as string[],\n field: opts.field as string[],\n header: opts.header as string[],\n input: opts.input as string | undefined,\n jq: opts.jq as string | undefined,\n md: opts.md as boolean | undefined,\n paginate: opts.paginate as boolean | undefined,\n paginateKey: opts.paginateKey as string | undefined,\n maxPages: opts.maxPages as string | undefined,\n slurp: opts.slurp as boolean | undefined,\n cache: opts.cache as string | undefined,\n include: opts.include as boolean | undefined,\n silent: opts.silent as boolean | undefined,\n verbose: opts.verbose as boolean | undefined,\n timeout: opts.timeout as string | undefined\n });\n });\n\n withGlobals(\n program\n .command(\"routes\")\n .argument(\"[filter]\", \"narrow by method, path, surface or description\")\n .description(\"list the endpoints this deployment mounts\")\n .option(\"--json\", \"emit one object per endpoint\")\n .option(\"--all\", \"include ide-only and worker-only mounts\")\n .option(\"--refresh\", \"ask the deployment again instead of using the cache\")\n ).action(async (filter: string | undefined, opts: Record<string, unknown>) => {\n const ctx = createContext(globals(opts));\n await runRoutes(ctx, filter, {\n json: opts.json as boolean | undefined,\n all: opts.all as boolean | undefined,\n refresh: opts.refresh as boolean | undefined\n });\n });\n\n withGlobals(\n program\n .command(\"schema\")\n .argument(\"<path>\", \"the endpoint whose request/response shape you want\")\n .description(\"request and response schemas for one endpoint\")\n .option(\"-X, --method <verb>\", \"narrow to one HTTP method\")\n ).action(async (path: string, opts: Record<string, unknown>) => {\n await runSchema(createContext(globals(opts)), path, opts.method as string | undefined);\n });\n\n withGlobals(program.command(\"openapi\").description(\"the whole OpenAPI document\")).action(\n async (opts: Record<string, unknown>) => {\n await runOpenApi(createContext(globals(opts)));\n }\n );\n\n // ── auth ─────────────────────────────────────────────────────────────────\n\n withGlobals(\n program\n .command(\"login\")\n .description(\"authenticate against a deployment, in the browser\")\n // REPEATABLE AND COMMA-SPLIT, matching `oxy login`'s `--env`. The\n // browser opens once per env, in sequence — `--login-env dev,staging` is\n // three acts, not one act with three targets. It is a separate flag\n // rather than making `--env` repeatable because `--env` is global here\n // and every other command takes exactly one.\n .option(\n \"--login-env <name|url...>\",\n \"extra deployments to log into (repeat, or comma-separate)\",\n collectEnvs,\n [] as string[]\n )\n .option(\"--assume [slug|uuid|url]\", \"act as this org immediately after logging in\")\n .option(\"-r, --reason <why>\", \"why you are acting as that org — recorded in the audit log\")\n ).action(async (opts: Record<string, unknown>) => {\n const extra = (opts.loginEnv as string[]) ?? [];\n // The positional `--env` is one of the set, not a separate default. No\n // `??` here: `withGlobals` already defaults the option and `createContext`\n // defaults it again — a third spelling would be dead.\n const envs = extra.length > 0 ? [String(opts.env), ...extra] : [];\n const assumeFlag = opts.assume;\n\n // EVERY USAGE ERROR BEFORE ANY BROWSER OPENS. These were checked inside\n // `runLogin`, after each env had already been through its flow — so\n // `--login-env staging --assume acme -r why` opened two browsers, waited\n // for two callbacks, and then exited USAGE. The Rust refuses at parse time\n // (`requires = \"assume\"`) and before target resolution; this is the same\n // moment, in the only place that sees the flags before the work.\n if (assumeFlag !== undefined && !opts.reason) {\n throw usageError(\"--assume requires --reason\", \"it is recorded in the impersonation log\");\n }\n if (opts.reason && assumeFlag === undefined) {\n throw usageError(\n \"--reason is only valid with --assume\",\n \"a reason with nothing to act as would have started a session for no org\"\n );\n }\n if (envs.length > 1 && assumeFlag !== undefined) {\n throw usageError(\n \"--assume is only valid when logging into a single env\",\n \"one session names one org on one deployment\"\n );\n }\n if (envs.length > 1 && opts.target) {\n throw usageError(\n \"--target is only valid when logging into a single env\",\n \"a single override would silently apply to all of them\"\n );\n }\n\n const assume =\n assumeFlag === undefined\n ? undefined\n : {\n // A bare `--assume` means \"the org `--env` already names\".\n org: typeof assumeFlag === \"string\" && assumeFlag ? assumeFlag : undefined,\n reason: String(opts.reason)\n };\n await runLogin(createContext(globals(opts)), envs, assume);\n });\n\n const assume = program\n .command(\"assume\")\n .description(\"act as an organization — staff and partner sessions, 60 minutes\");\n\n withGlobals(\n assume\n .command(\"start\")\n .description(\"begin acting as an org\")\n // `--org` comes from `withGlobals` — the placeholder flag and the org\n // being assumed are the same value, and two spellings for one idea is\n // how a user ends up passing the wrong one.\n .requiredOption(\"-r, --reason <why>\", \"why — recorded in the impersonation log\")\n ).action(async (opts: Record<string, unknown>) => {\n await runAssumeStart(\n createContext(globals(opts)),\n opts.org as string | undefined,\n String(opts.reason)\n );\n });\n\n withGlobals(\n assume\n .command(\"status\")\n .description(\"the assume-role sessions live for your account, and the time left\")\n .option(\"--json\", \"emit the raw session objects\")\n ).action(async (opts: Record<string, unknown>) => {\n await runAssumeStatus(createContext(globals(opts)), Boolean(opts.json));\n });\n\n withGlobals(\n assume\n .command(\"end\")\n .description(\"stop acting — one org, or every live session\")\n // The Rust declares `conflicts_with = \"all\"`. Silently preferring one is\n // the weaker half of that pair when the verb is destructive: a caller who\n // typed both meant something, and neither reading is safe to guess.\n .option(\"--all\", \"end every live session (refuses alongside --org)\")\n ).action(async (opts: Record<string, unknown>) => {\n if (opts.all && opts.org) {\n throw usageError(\n \"--all and --org name different sets\",\n \"drop one — ending every session and ending one are different acts\"\n );\n }\n await runAssumeEnd(\n createContext(globals(opts)),\n opts.org as string | undefined,\n Boolean(opts.all)\n );\n });\n\n withGlobals(\n program.command(\"logout\").description(\"drop the cached token for a deployment\")\n ).action((opts: Record<string, unknown>) => {\n runLogout(createContext(globals(opts)));\n });\n\n withGlobals(\n program\n .command(\"whoami\")\n .description(\"who the cached token is, checked against the deployment\")\n .option(\"--json\", \"emit the raw /api/user response\")\n ).action(async (opts: Record<string, unknown>) => {\n await runWhoami(createContext(globals(opts)), Boolean(opts.json));\n });\n\n withGlobals(\n program.command(\"token\").description(\"print the bearer token, for a raw curl\")\n ).action((opts: Record<string, unknown>) => {\n runToken(createContext(globals(opts)));\n });\n\n // ── the customer half ────────────────────────────────────────────────────\n\n withGlobals(\n program\n .command(\"list\")\n .description(\"the customers, from the GitHub topic that registers them\")\n .option(\"--refresh\", \"ask GitHub again rather than serving the hour-long cache\")\n .option(\"--json\", \"emit one object per customer\")\n ).action((opts: Record<string, unknown>) => {\n runList(createContext(globals(opts)), {\n refresh: opts.refresh as boolean | undefined,\n json: opts.json as boolean | undefined\n });\n });\n\n withGlobals(\n program\n .command(\"path\")\n .argument(\"<customer>\")\n .description(\"print where a customer's repo is, and stop\")\n .option(\"--refresh\", \"ask GitHub again rather than serving the cache\")\n ).action((name: string, opts: Record<string, unknown>) => {\n runPath(createContext(globals(opts)), name, { refresh: opts.refresh as boolean | undefined });\n });\n\n withGlobals(\n program\n .command(\"new\")\n .argument(\"<customer>\", \"the repo name to create, e.g. acme-oxy\")\n .description(\"create a new customer workspace repo, tagged and scaffolded\")\n .option(\"--display <name>\", \"the display name (repo description)\")\n ).action((name: string, opts: Record<string, unknown>) => {\n runNew(createContext(globals(opts)), name, { display: opts.display as string | undefined });\n });\n\n withGlobals(\n program\n .command(\"import\")\n .argument(\"<org/repo>\", \"an existing repo to register as a customer workspace\")\n .description(\"tag an EXISTING repo as a customer workspace\")\n .option(\"--clone\", \"also clone it locally\")\n ).action((slug: string, opts: Record<string, unknown>) => {\n runImport(createContext(globals(opts)), slug, { clone: opts.clone as boolean | undefined });\n });\n\n withGlobals(\n program\n .command(\"remove\")\n .alias(\"rm\")\n .argument(\"<customer>\")\n .description(\"untag a customer's repo (the repo itself is never deleted)\")\n .option(\"--purge\", \"also delete the local clone\")\n .option(\"--yes\", \"confirm --purge without a prompt\")\n ).action((name: string, opts: Record<string, unknown>) => {\n runRemove(createContext(globals(opts)), name, {\n purge: opts.purge as boolean | undefined,\n yes: opts.yes as boolean | undefined\n });\n });\n\n withGlobals(\n program\n .command(\"update\")\n .argument(\"<customer>\")\n .description(\"report how far a customer's repo has drifted from the template\")\n .option(\"--apply\", \"rewrite the MANAGED files, instead of only reporting them\")\n .option(\"--diff-all\", \"show the diff for every role, not just mixed files\")\n ).action((name: string, opts: Record<string, unknown>) => {\n runUpdate(createContext(globals(opts)), name, {\n apply: opts.apply as boolean | undefined,\n diffAll: opts.diffAll as boolean | undefined\n });\n });\n\n withGlobals(\n program\n .command(\"adopt\")\n .argument(\"<customer>\")\n .description(\"install the managed files an IMPORTED repo lacks, then stamp it\")\n .option(\"--apply\", \"install them, instead of only reporting them\")\n ).action((name: string, opts: Record<string, unknown>) => {\n runAdopt(createContext(globals(opts)), name, { apply: opts.apply as boolean | undefined });\n });\n\n withGlobals(\n program\n .command(\"doctor\")\n .argument(\"[customer]\")\n .description(\"report the state of a customer's repo, changing nothing\")\n .option(\"--all\", \"report every customer\")\n .option(\"--refresh\", \"ask GitHub again rather than serving the cache\")\n ).action((name: string | undefined, opts: Record<string, unknown>) => {\n runDoctor(createContext(globals(opts)), name, { all: opts.all as boolean | undefined });\n });\n\n withGlobals(\n program\n .command(\"activity\")\n .argument(\"<customer>\")\n .description(\"merged pull requests for a customer, from their repo and ours\")\n .option(\"--since <YYYY-MM-DD>\", \"only pull requests merged on or after this date\")\n .option(\"--repo <org/name>\", \"also search this repo\", collect, [])\n .option(\"--write\", \"file the record into the customer's dossier\")\n .option(\"--json\", \"emit the records as JSON\")\n ).action((name: string, opts: Record<string, unknown>) => {\n runActivity(createContext(globals(opts)), name, {\n since: opts.since as string | undefined,\n repo: opts.repo as string[],\n write: opts.write as boolean | undefined,\n json: opts.json as boolean | undefined\n });\n });\n\n withGlobals(\n program\n .command(\"repos\")\n .description(\"where OUR repos are checked out on this machine\")\n .option(\"--refresh\", \"rescan instead of using the cache\")\n ).action((opts: Record<string, unknown>) => {\n runRepos({ refresh: opts.refresh as boolean | undefined });\n });\n\n withGlobals(\n program\n .command(\"launch\", { isDefault: false })\n .argument(\"<customer>\")\n .argument(\"[claude-args...]\", \"arguments passed through to claude\")\n .description(\"start a Claude Code session scoped to one customer\")\n .option(\"--here\", \"run in the current directory, granting the customer's repo\")\n .option(\"--dry-run\", \"print the command instead of running it\")\n ).action((name: string, passthrough: string[], opts: Record<string, unknown>) => {\n runLaunch(createContext(globals(opts)), name, {\n here: opts.here as boolean | undefined,\n dryRun: opts.dryRun as boolean | undefined,\n passthrough\n });\n });\n\n const skills = program.command(\"skills\").description(\"the Claude skills this package ships\");\n skills.command(\"install\").description(\"link them into ~/.claude/skills\").action(runSkillsInstall);\n skills.command(\"list\").description(\"what ships, and what is linked\").action(runSkillsList);\n\n // ── housekeeping ─────────────────────────────────────────────────────────\n\n const cache = program.command(\"cache\").description(\"the on-disk caches\");\n cache\n .command(\"clear\")\n .description(\"drop every cache: responses, route catalogs, customer listings, repo scans\")\n .action(() => {\n const cleared = clearAllCaches();\n // Named rather than a count, because \"cleared\" alone is what let this\n // command claim three caches while clearing one.\n log.info(cleared.length === 0 ? \"nothing cached\" : `cleared: ${cleared.sort().join(\", \")}`);\n\n // Left alone deliberately — see `unknownCacheEntries`. Reported, because\n // a cache this command does not know about is exactly the omission the\n // old whole-root sweep existed to catch.\n const strays = unknownCacheEntries();\n if (strays.length > 0) {\n log.warn(`left alone (not written by oxyc): ${strays.sort().join(\", \")}`);\n log.hint(\n \"remove them by hand if they are stale — oxyc will not delete what it did not write\"\n );\n }\n });\n\n withGlobals(\n program\n .command(\"proxy\")\n .description(\"run a local outbound proxy so a custom app in `pnpm dev` hits cloud data\")\n .option(\"--port <n>\", \"local port to listen on\", \"3000\")\n .option(\"--allow-writes\", \"forward side-effecting calls instead of holding them\")\n .option(\"--allow-events\", \"forward tracking events instead of dropping them\")\n .option(\"--yes\", \"confirm proxying to a production target\")\n .addHelpText(\n \"after\",\n \"\\nGuardrails, on by default and carried over from `oxy proxy`: side-effecting\\n\" +\n \"calls are HELD, tracking events are DROPPED, auth endpoints reach the backend\\n\" +\n \"unauthenticated so sign-in works, and the cached token is a fallback that never\\n\" +\n \"overrides a real browser session.\\n\"\n )\n ).action(async (opts: Record<string, unknown>) => {\n await runProxy(createContext(globals(opts)), {\n port: opts.port as string | undefined,\n allowWrites: opts.allowWrites as boolean | undefined,\n allowEvents: opts.allowEvents as boolean | undefined,\n yes: opts.yes as boolean | undefined\n });\n });\n\n program\n .command(\"validate\")\n .description(\"check a workspace's YAML against the schemas, without a Rust binary\")\n .option(\"-f, --file <path>\", \"validate one file instead of the whole workspace\")\n .option(\"--json\", \"emit findings as JSON\")\n .addHelpText(\n \"after\",\n \"\\nStructural checks only. `oxy validate` additionally resolves `databases:` and\\n\" +\n \"`llm.ref` against config.yml, which needs the workspace loaded — where the two\\n\" +\n \"disagree, that one is right. The schemas here are generated from the same Rust\\n\" +\n \"types, so they cannot drift from it.\\n\"\n )\n .action((opts: Record<string, unknown>) => {\n runValidate({\n file: opts.file as string | undefined,\n json: opts.json as boolean | undefined\n });\n });\n\n withGlobals(\n program\n .command(\"mcp\")\n .description(\"serve the Oxy API as MCP tools over stdio, for an agent runtime\")\n .addHelpText(\n \"after\",\n \"\\nFour tools — oxy_routes, oxy_schema, oxy_request, oxy_whoami — not one per\\n\" +\n \"endpoint: an agent runtime ships every tool's schema on every turn, and ~670 of\\n\" +\n \"them would cost tens of KB per request. Discovery stays a question the agent\\n\" +\n \"asks, so this reaches endpoints added after the package was published.\\n\\n\" +\n \"Claude Code: claude mcp add oxyc -- npx -y @oxy-hq/cli mcp --env production\\n\"\n )\n ).action(async (opts: Record<string, unknown>) => {\n // IMPORTED HERE, not at the top. `@modelcontextprotocol/sdk` pulls in\n // express, ajv and zod, and a static import loads all of it on every\n // `oxyc` invocation — including `oxyc --help`. Worse, `zod` is a required\n // non-optional peer that only resolves through workspace hoisting, so on a\n // non-hoisting install a static import breaks EVERY command rather than\n // just this one.\n //\n // THIS FIXES LOAD TIME, NOT INSTALL WEIGHT. The SDK is still a plain\n // dependency, so `npx @oxy-hq/cli routes` downloads it and its tree for\n // someone who never runs `oxyc mcp`. An optional peer would move that cost\n // but make `oxyc mcp` fail at the import on a normal install, which is a\n // worse trade for the command an agent runtime is configured to start.\n const { runMcp } = await import(\"./commands/mcp.js\");\n await runMcp(createContext(globals(opts)));\n });\n\n program\n .command(\"guide\")\n .description(\"a compact page to paste into AGENTS.md / CLAUDE.md so an agent knows this tool\")\n .action(runGuide);\n\n program\n .command(\"exit-codes\")\n .description(\"what each exit code means\")\n .action(() => {\n process.stdout.write(EXIT_CODE_HELP);\n });\n\n return program;\n}\n\n/** commander's repeatable-option accumulator. */\nfunction collect(value: string, previous: string[]): string[] {\n return [...previous, value];\n}\n\nconst API_HELP = `\nPLACEHOLDERS\n {org} {workspace} {project} {customer} {me} are substituted from context —\n the customer repo you are standing in, a pasted --env URL, or the flags above.\n\n oxyc api {org}/workspaces\n oxyc api {workspace}/threads --jq '.threads[].title'\n\nBODIES\n -f key=value string -F key=value typed (true / 3 / [\"a\"] / @file / @-)\n -F 'ids[]=a' -F 'ids[]=b' repeats accumulate into an array\n --input @body.json raw body from a file, or - for stdin\n On GET/HEAD/DELETE, fields become query parameters instead of a body.\n\nSURFACES\n /api/** bearer, from \\`oxyc login\\`\n /external/api/** X-API-Key, from $OXY_API_KEY — selected automatically\n\nFINDING AN ENDPOINT\n oxyc routes threads what exists, and what each one does\n oxyc schema {workspace}/threads -X POST the body it expects\n`;\n\nconst EXIT_CODE_HELP = `0 success\n1 failure with nothing more specific to say\n2 usage error — a bad flag, a missing argument, a malformed value\n4 not authenticated, or the token was rejected (401/403)\n5 not found (404), or an unknown customer\n6 the request was malformed (4xx other than 401/403/404)\n7 unavailable — 5xx, a timeout, or the network failed. Retryable.\n8 refused — the operation would have destroyed or overwritten something\n`;\n\n/**\n * Render a failure and pick the exit code.\n *\n * The one rule that matters: errors go to STDERR and the exit code is never 0.\n * A tool that prints \"ERROR\" on stdout and exits 0 is invisible to an agent,\n * which branches on the code alone and will happily carry on with garbage.\n */\nfunction reportAndExit(cause: unknown): never {\n if (cause instanceof CliError) {\n log.error(cause.message);\n if (cause.detail) {\n for (const line of cause.detail.split(\"\\n\")) process.stderr.write(` ${err.dim(line)}\\n`);\n }\n if (cause.hint) {\n for (const line of cause.hint.split(\"\\n\")) log.hint(line);\n }\n // Through `log.remedy`, so an error's remedy reads the way a warning's\n // does. Handed to `hint` it wore `→` and joined the run of elaborations.\n // Whole, not split: `log.remedy`'s arguments are REMEDIES, and it splits\n // each one itself so every line keeps the marker. Splitting here made the\n // parameter mean two things depending on the caller.\n if (cause.remedy) log.remedy(cause.remedy);\n process.exit(cause.code);\n }\n log.error((cause as Error)?.message ?? String(cause));\n if (process.env.OXYC_DEBUG && cause instanceof Error && cause.stack) {\n process.stderr.write(`${err.dim(cause.stack)}\\n`);\n }\n process.exit(ExitCode.FAILURE);\n}\n\n/**\n * Make commander exit with OUR codes, on every command in the tree.\n *\n * `exitOverride` applies only to the command it is called on — it does NOT\n * propagate to subcommands. Setting it on the root alone left\n * `oxyc api user --nonsense` exiting 1 (commander's default) instead of 2,\n * which is exactly the distinction an agent branches on: 1 means \"the request\n * failed, maybe retry\", 2 means \"you called it wrong, stop\". So it is applied\n * recursively, and `main.test.ts` pins it.\n */\nfunction applyExitOverride(command: Command): void {\n command.exitOverride((error) => {\n // `--help` and `--version` are successes that commander signals by\n // throwing. Exiting non-zero on them would make `oxyc api --help` look\n // like a failed command in any script that checks.\n if (\n error.code === \"commander.helpDisplayed\" ||\n error.code === \"commander.help\" ||\n error.code === \"commander.version\"\n ) {\n process.exit(ExitCode.OK);\n }\n process.exit(ExitCode.USAGE);\n });\n for (const child of command.commands) applyExitOverride(child);\n}\n\n/**\n * `oxyc pokehouse` means `oxyc launch pokehouse`.\n *\n * The bare form is the flagship interaction of the tooling this absorbed —\n * what people type all day — so it has to survive the port. commander has no\n * first-class \"unknown verb is an argument\" hook, so the rewrite happens here,\n * before parsing, and only for a token that is neither a known command nor a\n * flag.\n *\n * THE COST, and the reason `didYouMeanCommand` exists: this makes every\n * mistyped command look like a customer. `oxyc rotues` would rewrite to\n * `launch rotues` and come back \"unknown customer rotues\" — an error about\n * the wrong thing entirely, which is the failure mode that makes a default\n * command a bad idea in the first place. So a token CLOSE to a real command is\n * treated as the typo it almost certainly is, and a token close to nothing is\n * treated as a customer name.\n */\nfunction expandBareCustomer(argv: string[], program: Command): string[] {\n const [node, script, first, ...rest] = argv;\n if (!first || first.startsWith(\"-\")) return argv;\n\n const known = program.commands.flatMap((c) => [c.name(), ...c.aliases()]);\n if (known.includes(first)) return argv;\n\n const meant = didYouMeanCommand(first, known);\n if (meant) {\n throw new CliError(`unknown command \"${first}\"`, {\n code: ExitCode.USAGE,\n hint: `did you mean \\`oxyc ${meant}\\`? (for a customer of that name: \\`oxyc launch ${first}\\`)`\n });\n }\n\n return [node as string, script as string, \"launch\", first, ...rest];\n}\n\nasync function main(): Promise<void> {\n const program = buildProgram();\n applyExitOverride(program);\n // `expandBareCustomer` can throw (a near-miss command name), so it is inside\n // `main` rather than at the call site — `main().catch(reportAndExit)` is what\n // turns that into the usage exit code and the suggestion.\n await program.parseAsync(expandBareCustomer(process.argv, program));\n}\n\n// A rejected promise anywhere in the tree has to end the process non-zero —\n// node's default for an unhandled rejection is a warning and exit 0, which is\n// the exact \"printed an error, reported success\" shape this tool refuses.\nprocess.on(\"unhandledRejection\", reportAndExit);\n\n// Unconditional. There was an `isEntryPoint()` guard here so that importing\n// this module (which the test did, to reach `didYouMeanCommand`) would not\n// start the CLI — but an npm bin is a SYMLINK, `resolve()` does not follow\n// links, and the comparison would have been false for every `npm i -g`\n// install: `oxyc` would print nothing and exit 0. The function moved to\n// `util/suggest.ts` instead, so there is nothing left to guard against.\nmain().catch(reportAndExit);\n"],"mappings":"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"}
|