@oxy-hq/cli 0.4.0 → 0.5.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/dist/main.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"main.mjs","names":["readCache","writeCache","cacheFile","readCache","isObject","loadManifest","UUID","describe","json","walk","unreachable","parseYaml"],"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/generated/version.ts","../src/publish/manifest.ts","../src/commands/init-ci.ts","../src/customer/workspace.ts","../src/commands/launch.ts","../src/commands/proxy.ts","../src/publish/dotenv.ts","../src/publish/functions.ts","../src/publish/provenance.ts","../src/publish/server.ts","../src/publish/tarball.ts","../src/commands/publish.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 FIXED A BUG the Rust `oxy api` shipped with, which is worth stating\n * because the list looks like gratuitous divergence otherwise. Its\n * `normalize_path` tested only for an `api` first segment, so the API-key\n * surface — documented in that command's own `--help` as\n * `oxy api /external/api/<workspace_id>/sql/query` — normalised to\n * `/api/external/api/<workspace_id>/sql/query` and 404d. The documented example\n * could never have worked. That command is gone; the list is still required,\n * because the surface it mishandled is not.\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 * Which rule decided `hasMore`, or `undefined` when nothing in the response\n * spoke to it.\n *\n * `hasMore: false` conflates two different answers — \"the server said this is\n * the last page\" and \"the server said nothing, so we stopped\" — and only the\n * second one is worth telling the caller about. Several Oxy list endpoints\n * take `page`/`page_size` (or `limit`/`offset`) and answer with a BARE ARRAY:\n * they really are paginated, the response just carries no way to know it, so\n * `--paginate` returns page one and looks complete. Naming the rule is what\n * lets `paginate()` say so instead.\n */\n signal?: \"pagination.has_next\" | \"has_more\" | \"pagination.total_pages\";\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 let signal: PageShape[\"signal\"];\n if (pagination && typeof pagination.has_next === \"boolean\") {\n hasMore = pagination.has_next;\n signal = \"pagination.has_next\";\n } else if (typeof payload.has_more === \"boolean\") {\n hasMore = payload.has_more;\n signal = \"has_more\";\n } else if (pagination && typeof pagination.total_pages === \"number\") {\n hasMore = page < pagination.total_pages;\n signal = \"pagination.total_pages\";\n }\n\n return { rowsKey, rows, hasMore, signal };\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/**\n * Whether the response spoke about pagination AT ALL.\n *\n * Deliberately not `linkNext(...) !== undefined`. The last page of a paginated\n * endpoint has no `rel=\"next\"` — that is what makes it the last page — so\n * testing for one conflates \"I am at the end of a collection that pages\" with\n * \"this endpoint has never heard of pagination\", and the warning at the bottom\n * of `paginate()` would fire on every single-page result from an endpoint that\n * is doing everything right. Oxy's handlers emit `rel=\"first\"` on every page\n * precisely so this question has an answer (`oxy_app_core::pagination`).\n */\nexport function hasLinkHeader(headers: Record<string, string>): boolean {\n return Boolean(headers.link ?? headers.Link);\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 /** Whether ANY page carried a signal this module knows how to read. */\n let sawSignal = false;\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 // ANY `Link` counts, not only one naming a next page — a last page is still\n // a page of something that paginates, and saying otherwise is what made this\n // warning fire on the endpoints that answer correctly.\n sawSignal ||= hasLinkHeader(response.headers) || shape.signal !== undefined;\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 // NOTHING RECOGNISED, SO ONE PAGE — said out loud rather than implied by a\n // short result. The heuristic stopping is the safe behaviour and stays; what\n // was missing is that the caller could not tell it apart from an endpoint\n // that genuinely had one page. Much of the admin surface takes `page` /\n // `page_size` and answers with a bare array, so `--paginate` there returns\n // the first 50 rows and reads as the whole table.\n //\n // Only on the opt-in flag, and only on stderr: someone who typed --paginate\n // asked to walk the pages, so \"I could not\" is an answer to their question,\n // not noise. It never fires for an endpoint that reported `has_next: false`.\n if (!sawSignal) {\n log.warn(\n `${opts.path} returned no pagination signal — this is ONE page, not necessarily every row.`\n );\n log.hint(\n \"if the endpoint takes page/page_size or limit/offset, walk it yourself: `oxyc api '<path>?page=1'`\"\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 the Rust `env_url.rs` and the target half of `app_manifest.rs`,\n * both since deleted. Kept faithful rather than improved: the credentials file\n * is keyed by HOST and still holds every login the Rust `oxy login` cached, so\n * a change to which host an `--env` names would look those tokens up under a\n * different key and report the 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\nimport { CliError, ExitCode } from \"../util/errors.js\";\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/**\n * Read `<dir>/oxy-app.json`. `undefined` only when there is no such file.\n *\n * A file that exists but cannot be read, is not JSON, or carries a field this\n * CLI reads in the wrong shape is an error naming the path — never `undefined`.\n * Treating it as absent made every caller carry on with the wrong target,\n * identity and function set: `publish` shipped with no functions bundled.\n * Unknown fields still pass, so an SDK field added tomorrow breaks nothing.\n */\nexport function readAppManifest(dir: string): Record<string, unknown> | undefined {\n const path = join(dir, \"oxy-app.json\");\n let raw: string;\n try {\n raw = readFileSync(path, \"utf8\");\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n throw invalidManifest(path, `cannot read it: ${(err as Error).message}`);\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (err) {\n throw invalidManifest(path, (err as Error).message);\n }\n const problem = shapeProblem(parsed);\n if (problem) throw invalidManifest(path, problem);\n return parsed as Record<string, unknown>;\n}\n\nfunction invalidManifest(path: string, detail: string): CliError {\n return new CliError(`${path} is not a valid oxy-app.json: ${detail}`, {\n code: ExitCode.USAGE,\n remedy: \"fix the file and re-run\"\n });\n}\n\nconst isObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\n/** Checks only the fields this CLI reads, as the types it reads them as. `null` is absent. */\nfunction shapeProblem(manifest: unknown): string | undefined {\n if (!isObject(manifest)) return \"the top level must be an object\";\n const notString = (obj: Record<string, unknown>, key: string) =>\n obj[key] != null && typeof obj[key] !== \"string\";\n const notObject = (obj: Record<string, unknown>, key: string) =>\n obj[key] != null && !isObject(obj[key]);\n\n for (const key of [\"slug\", \"orgSlug\", \"name\"]) {\n if (notString(manifest, key)) return `\\`${key}\\` must be a string`;\n }\n for (const key of [\"environments\", \"functions\", \"build\"]) {\n if (notObject(manifest, key)) return `\\`${key}\\` must be an object`;\n }\n const build = (manifest.build ?? {}) as Record<string, unknown>;\n for (const key of [\"install\", \"command\", \"outDir\"]) {\n if (notString(build, key)) return `\\`build.${key}\\` must be a string`;\n }\n for (const [section, field] of [\n [\"environments\", \"target\"],\n [\"functions\", \"entry\"]\n ] as const) {\n const entries = (manifest[section] ?? {}) as Record<string, unknown>;\n for (const [name, entry] of Object.entries(entries)) {\n if (!isObject(entry)) return `\\`${section}.${name}\\` must be an object`;\n if (notString(entry, field)) return `\\`${section}.${name}.${field}\\` must be a string`;\n }\n }\n return undefined;\n}\n\n/** `<dir>/oxy-app.json` for identity and target, strictly — see `readAppManifest`. */\nexport function loadManifest(dir: string): OxyAppManifest | undefined {\n return readAppManifest(dir) as OxyAppManifest | undefined;\n}\n\n/**\n * The manifest for a command that reads it only to resolve the target.\n *\n * A non-blank `--target` wins outright in `resolveEnv`, so the file cannot\n * change the outcome: it is not read, and a broken `oxy-app.json` does not fail\n * a command that was told where to go. Otherwise `loadManifest`, strict as\n * ever. `publish` and `init-ci` read it for identity and functions whatever\n * `--target` says, so they do not come through here.\n */\nexport function loadForTargetResolution(\n dir: string,\n targetFlag: string | undefined\n): OxyAppManifest | undefined {\n return targetFlag?.trim() ? undefined : loadManifest(dir);\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`. It replaced the Rust `oxy assume`, which\n * was deleted once this covered it. The sessions are Postgres rows hanging off\n * the account, so the browser and this terminal act as one — there is no\n * per-client state to keep in sync.\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. Nothing here 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.\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 this lists three\n // 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.\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. So it refuses: a present-but-blank\n // `--org` 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 deleted Rust `oxy login` wrote.\n *\n * It began as interop with a program written in another language, and the\n * shape is still that contract: every login cached before `oxyc` took over\n * lives in this file, so the path, the host key and the field names were\n * transcribed from the Rust `login.rs` rather than chosen here. Change any of\n * them and every existing login silently disappears.\n *\n * THE PATH IS NOT `~/.config` ON macOS, whatever the Rust doc comment said.\n * `login.rs` built 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.\n * `configDir()` reproduces the crate's platform rules, and\n * `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 the Rust `oxy login` did, 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 — was transcribed from\n * the Rust `login.rs` (since deleted). 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/** The tab the user is left looking at. */\nconst SUCCESS_HTML =\n \"<!doctype html><meta charset=utf-8><title>oxyc 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. The Rust `oxy login --env dev,staging`\n * did the same, and its logins are still in the same credential file.\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 // A JSON ARRAY — one document, not one object per line. Both readings are\n // defensible and `--help` used to claim the other one; an array is what\n // `oxyc list --json` and `oxyc openapi` already emit, and what a `| jq`\n // written against this expects.\n //\n // Indented for a human, compact for a pipe, exactly as `runOpenApi` below\n // decides it. Unfiltered this is ~670 objects of eight fields, where the\n // indentation alone is tens of KB of context an agent pays for and no\n // human is reading.\n process.stdout.write(`${JSON.stringify(matches, null, stdoutIsTty() ? 2 : 0)}\\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 publish --env dev # build + publish a custom app (draft; --promote for live)\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","// @generated by scripts/emit-version.mjs — do not edit.\n//\n// The single source of truth is `package.json`. `oxyc --version` reads this,\n// so a release is one bump in the manifest and nothing else.\nexport const VERSION = \"0.4.0\";\n","/**\n * The half of `oxy-app.json` that publishing reads, and the two name rules the\n * server enforces on it.\n *\n * `context/target.ts` owns identity and `environments`; this adds `build` and\n * `functions`. Both read the same file and ignore what they do not know, so an\n * SDK field added tomorrow cannot break a publish today.\n */\n\nimport { readAppManifest } from \"../context/target.js\";\n\nexport interface FunctionSpec {\n entry?: string;\n}\n\nexport interface PublishManifest {\n slug?: string;\n orgSlug?: string;\n build?: { install?: string; command?: string; outDir?: string };\n functions?: Record<string, FunctionSpec>;\n}\n\n/**\n * `<dir>/oxy-app.json`, or `undefined` when there is none. A broken one throws:\n * publishing past it used to ship a bundle with no functions and an identity\n * taken from flags or the directory.\n */\nexport function loadPublishManifest(dir: string): PublishManifest | undefined {\n return readAppManifest(dir) as PublishManifest | undefined;\n}\n\n/** A blank manifest value is no value: `\"install\": \"\"` falls back to the default. */\nfunction orDefault(value: string | undefined, fallback: string): string {\n return value?.trim() ? value : fallback;\n}\n\nexport interface BuildSteps {\n install: string;\n command: string;\n outDir: string;\n}\n\n/**\n * Install / build / output directory. `out` matches the directory the Vite\n * plugin forces, so an identity-only manifest publishes without a `build` block.\n */\nexport function buildSteps(manifest: PublishManifest | undefined): BuildSteps {\n return {\n install: orDefault(manifest?.build?.install, \"pnpm install\"),\n command: orDefault(manifest?.build?.command, \"pnpm build\"),\n outDir: orDefault(manifest?.build?.outDir, \"out\")\n };\n}\n\n/** Declared function names, or an empty list. */\nexport function declaredFunctions(manifest: PublishManifest | undefined): string[] {\n const functions = manifest?.functions;\n return functions && typeof functions === \"object\" ? Object.keys(functions) : [];\n}\n\n/** Source entry relative to the app directory. Default `functions/<name>.ts`. */\nexport function functionEntry(manifest: PublishManifest | undefined, name: string): string {\n return orDefault(manifest?.functions?.[name]?.entry, `functions/${name}.ts`);\n}\n\n/**\n * `^[a-z][a-z0-9-]{0,63}$` — the server's `is_valid_function_name`.\n *\n * A manifest key becomes `functions/<name>.js`, so `../../x` has to be refused\n * before esbuild is told to write there.\n */\nexport function isValidFunctionName(name: string): boolean {\n return /^[a-z][a-z0-9-]{0,63}$/.test(name);\n}\n\n/**\n * The server's `is_valid_slug`: 1–63 lowercase letters, digits and single\n * hyphens, no leading or trailing hyphen.\n *\n * Checked before anything is built, so an author whose bundle never went\n * through the Vite plugin learns about it before uploading rather than after.\n */\nexport function isValidSlug(slug: string): boolean {\n return (\n slug.length > 0 &&\n slug.length <= 63 &&\n /^[a-z0-9-]+$/.test(slug) &&\n !slug.startsWith(\"-\") &&\n !slug.endsWith(\"-\") &&\n !slug.includes(\"--\")\n );\n}\n","/**\n * `oxyc init-ci` — write a GitHub Actions workflow that publishes a custom app\n * with trusted publishing: no stored secret.\n *\n * `id-token: write` is a job-level permission every step in the job can use,\n * so the workflow is TWO jobs. `build` runs the package scripts and holds no\n * credential; `publish` holds the id-token, installs nothing, and does only\n * `oxyc publish --prebuilt` on the artifact `build` produced. Do not add steps\n * to the publish job — that isolation is the security model.\n *\n * It replaced the Rust `oxy init-ci`, whose workflow called a\n * `oxy-hq/publish-action` that was never published, so no workflow it wrote\n * could run.\n */\n\nimport { spawnSync } from \"node:child_process\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join, relative, sep } from \"node:path\";\nimport type { Context } from \"../context/resolve.js\";\nimport { VERSION } from \"../generated/version.js\";\nimport { buildSteps, isValidSlug, loadPublishManifest } from \"../publish/manifest.js\";\nimport * as log from \"../ui/log.js\";\nimport { out } from \"../ui/tty.js\";\nimport { refusal, usageError } from \"../util/errors.js\";\nimport { parseRemoteSlug, repoRoot } from \"../util/git.js\";\n\nexport const WORKFLOW_PATH = \".github/workflows/oxy-publish.yml\";\n\nexport interface InitCiFlags {\n app?: string;\n environment?: string;\n force?: boolean;\n}\n\nexport interface WorkflowOptions {\n org: string;\n app: string;\n environment: string;\n /** `--env` the publish step targets. */\n env: string;\n /** App directory relative to the repo root, `.` when they are the same. */\n appDir: string;\n outDir: string;\n /** Omit `version:` when package.json pins pnpm, or pnpm/action-setup refuses. */\n pnpmFromPackageJson: boolean;\n nodeVersionFile: boolean;\n cliVersion: string;\n}\n\n/** `org/app` from `--app`, else the manifest in the working directory. */\nfunction resolveApp(cwd: string, flag: string | undefined): { org: string; app: string } {\n const manifest = loadPublishManifest(cwd);\n const [org, app] = flag ? flag.split(\"/\") : [manifest?.orgSlug, manifest?.slug];\n if (!org || !app || (flag !== undefined && flag.split(\"/\").length !== 2)) {\n throw usageError(\n \"which app does this workflow publish?\",\n \"pass --app <org-slug>/<app-slug>, or run it from a directory whose oxy-app.json names both\"\n );\n }\n return { org, app };\n}\n\nfunction packageJsonPinsPnpm(dir: string): boolean {\n try {\n const pkg = JSON.parse(readFileSync(join(dir, \"package.json\"), \"utf8\")) as {\n packageManager?: string;\n };\n return typeof pkg.packageManager === \"string\" && pkg.packageManager.startsWith(\"pnpm@\");\n } catch {\n return false;\n }\n}\n\n/**\n * Refuse any value that is not inert in both YAML and a shell word.\n *\n * Every field below is written unquoted into a `run:` line or a `path:`, and\n * one of those lines runs in the job holding `id-token: write`. The org, the\n * out dir and the app directory come from a committed manifest and a checkout\n * path, so a `$(…)` in any of them would otherwise become code in the job this\n * workflow exists to keep clean. Allowlists, not escaping: a slug, a path and\n * a URL each have a shape, and anything outside it is a mistake worth hearing.\n */\nfunction assertWorkflowSafe(o: WorkflowOptions): void {\n const path = /^(?!\\/)(?!.*(?:^|\\/)\\.\\.(?:\\/|$))[A-Za-z0-9._/-]+$/;\n const checks: Array<[string, string, boolean]> = [\n [\"org\", o.org, isValidSlug(o.org)],\n [\"app\", o.app, isValidSlug(o.app)],\n [\"environment\", o.environment, /^[A-Za-z0-9._-]{1,255}$/.test(o.environment)],\n [\"--env\", o.env, /^[A-Za-z0-9._:/-]+$/.test(o.env)],\n [\"app directory\", o.appDir, path.test(o.appDir)],\n [\"outDir\", o.outDir, path.test(o.outDir)],\n [\"CLI version\", o.cliVersion, /^[0-9A-Za-z.+-]+$/.test(o.cliVersion)]\n ];\n for (const [label, value, ok] of checks) {\n if (!ok) {\n throw usageError(\n `refusing to write ${label} ${JSON.stringify(value)} into a workflow`,\n \"slugs, relative paths and plain URLs only — it is written unquoted into the job that holds id-token: write\"\n );\n }\n }\n}\n\n/** The workflow. Pure, so the job split can be pinned by a test. */\nexport function workflowYaml(o: WorkflowOptions): string {\n assertWorkflowSafe(o);\n const cli = `@oxy-hq/cli@${o.cliVersion}`;\n const workdir = o.appDir === \".\" ? \"\" : `\\n working-directory: ${o.appDir}`;\n const bundlePath = o.appDir === \".\" ? o.outDir : `${o.appDir}/${o.outDir}`;\n const pnpm = o.pnpmFromPackageJson ? \"\" : \"\\n with:\\n version: 10\";\n const node = o.nodeVersionFile ? \"node-version-file: .nvmrc\" : \"node-version: 20\";\n return `# Generated by \\`oxyc init-ci\\`. Trusted publishing — no stored secret.\n#\n# \\`id-token: write\\` is job-level and visible to every step, so the publish job\n# is isolated: it checks out the commit, downloads what \\`build\\` produced, and\n# publishes it. It runs no package script. Keep it that way — add nothing to it,\n# and pin these actions by SHA.\nname: Publish ${o.org}/${o.app} to Oxy\n\non:\n push:\n branches: [main]\n workflow_dispatch:\n\npermissions:\n contents: read\n\njobs:\n build:\n runs-on: ubuntu-latest\n # No id-token here: this job runs every dependency's install scripts.\n steps:\n - uses: actions/checkout@v4\n with:\n persist-credentials: false\n - uses: pnpm/action-setup@v4${pnpm}\n - uses: actions/setup-node@v4\n with:\n ${node}\n # Runs oxy-app.json's build and bundles its Oxy Functions into the output\n # directory — everything a publish does except the upload.\n - name: Build the bundle\n run: pnpm dlx ${cli} publish --build-only --org ${o.org} --app ${o.app}${workdir}\n - uses: actions/upload-artifact@v4\n with:\n name: oxy-bundle\n path: ${bundlePath}\n # Vite writes \\`.vite/manifest.json\\`; the default drops hidden files.\n include-hidden-files: true\n if-no-files-found: error\n\n publish:\n needs: build\n runs-on: ubuntu-latest\n # Attach required reviewers to this environment in Settings → Environments.\n environment: ${o.environment}\n permissions:\n id-token: write\n contents: read\n steps:\n # For oxy-app.json and the commit the build is recorded against.\n - uses: actions/checkout@v4\n with:\n persist-credentials: false\n - uses: actions/download-artifact@v4\n with:\n name: oxy-bundle\n path: ${bundlePath}\n - uses: actions/setup-node@v4\n with:\n ${node}\n - name: Publish\n env:\n # The CLI's own dependencies run no install scripts in this job.\n npm_config_ignore_scripts: \"true\"\n run: npx --yes ${cli} publish --prebuilt --dir ${o.outDir} --env ${o.env} --org ${o.org} --app ${o.app}${workdir}\n`;\n}\n\n/** `gh api users/<owner> --jq .id`, when gh is here and answers. */\nfunction ownerId(owner: string): string | undefined {\n try {\n const result = spawnSync(\"gh\", [\"api\", `users/${owner}`, \"--jq\", \".id\"], { encoding: \"utf8\" });\n return result.status === 0 ? result.stdout.trim() || undefined : undefined;\n } catch {\n return undefined;\n }\n}\n\nexport function runInitCi(ctx: Context, flags: InitCiFlags): void {\n const { org, app } = resolveApp(ctx.cwd, flags.app);\n const environment = flags.environment?.trim() || \"oxy-publish\";\n const root = repoRoot(ctx.cwd) ?? ctx.cwd;\n const path = join(root, WORKFLOW_PATH);\n if (existsSync(path) && !flags.force) {\n throw refusal(`${WORKFLOW_PATH} already exists`, { hint: \"pass --force to overwrite it\" });\n }\n\n const appDir = relative(root, ctx.cwd).split(sep).join(\"/\") || \".\";\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(\n path,\n workflowYaml({\n org,\n app,\n environment,\n env: ctx.flags.env ?? \"production\",\n appDir,\n outDir: buildSteps(loadPublishManifest(ctx.cwd)).outDir,\n pnpmFromPackageJson: packageJsonPinsPnpm(root),\n nodeVersionFile: existsSync(join(root, \".nvmrc\")),\n cliVersion: VERSION\n })\n );\n\n const remote = spawnSync(\"git\", [\"remote\", \"get-url\", \"origin\"], { cwd: root, encoding: \"utf8\" });\n const slug = remote.status === 0 ? parseRemoteSlug(remote.stdout) : undefined;\n const [owner = \"<owner>\", repo = \"<repo>\"] = slug?.split(\"/\") ?? [];\n const id = slug ? ownerId(owner) : undefined;\n\n process.stdout.write(`${out.green(\"wrote\")} ${path}\\n\\n`);\n log.info(\"next: register this workflow as a publisher for the app, then gate the environment\");\n process.stdout.write(\n ` oxyc api /api/customer-apps/<app-id>/publishers --env ${ctx.flags.env ?? \"production\"} -X POST \\\\\\n` +\n ` -f repo_owner=${owner} -F repo_owner_id=${id ?? `<numeric id: gh api users/${owner} --jq .id>`} \\\\\\n` +\n ` -f repo_name=${repo} -f workflow_ref=${WORKFLOW_PATH} -f environment=${environment}\\n\\n` +\n ` <app-id> is ${org}/${app}'s id on its admin page. Then add required reviewers to the\\n` +\n ` '${environment}' environment in Settings → Environments.\\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 `oxyc login` bearer and\n * applying guardrails — to the resolved cloud target.\n *\n * It replaced the Rust `oxy proxy`, and the guardrails came across verbatim\n * rather than reinvented, because each one is a decision somebody argued and\n * every one of them is about not writing to a customer's production data from\n * 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 * - a production target is refused without `--yes`\n *\n * An Oxy Function call also gets a W3C trace (the SDK's, or one minted here),\n * and its `request_id` / `trace_id` are printed per call.\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 { randomUUID } from \"node:crypto\";\nimport { once } from \"node:events\";\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 was safe by omission rather than by design: its `reqwest`\n * was built without the `gzip`/`brotli` features, so it never asked 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 // `traceparent` / `tracestate` are the SDK's W3C trace context. The trace a\n // page stamps on its error (`error.traceId`) must be the one the request\n // carried, or that id names a trace that exists nowhere.\n for (const name of [\n \"content-type\",\n \"accept\",\n \"cookie\",\n \"authorization\",\n \"origin\",\n \"referer\",\n \"traceparent\",\n \"tracestate\"\n ]) {\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/**\n * The function name when `path` is an Oxy Function call —\n * `/customer-apps/<org>/<slug>/fn/<name>[/…]`, the one call this proxy\n * annotates with its ids. A bundle asset that merely contains `/fn/` is not.\n */\nexport function functionRoute(path: string): string | undefined {\n const [customerApps, org, slug, fn, name] = (path.split(\"?\")[0] ?? path)\n .split(\"/\")\n .filter(Boolean);\n return customerApps === \"customer-apps\" && org && slug && fn === \"fn\" ? name : undefined;\n}\n\n/**\n * The trace id of a well-formed W3C `traceparent` — version, a non-zero 32-hex\n * trace id, a non-zero 16-hex span id, flags — or `undefined`. Anything else is\n * rejected whole, as the server's extractor would: a printed id must be real.\n */\nexport function traceIdOf(traceparent: string): string | undefined {\n const [version, trace, span, flags, ...rest] = traceparent.split(\"-\");\n const hex = (s: string | undefined, len: number) =>\n s !== undefined && s.length === len && /^[0-9a-f]+$/i.test(s);\n const nonZero = (s: string | undefined) => s !== undefined && /[^0]/.test(s);\n const ok =\n rest.length === 0 &&\n hex(version, 2) &&\n hex(trace, 32) &&\n nonZero(trace) &&\n hex(span, 16) &&\n nonZero(span) &&\n hex(flags, 2);\n return ok ? trace : undefined;\n}\n\n/**\n * Keep a well-formed inbound `traceparent` (the SDK minted it) or mint a sampled\n * one in its place, and return the trace id either way.\n *\n * A rejected header takes its `tracestate` with it (W3C): vendor state from a\n * trace that no longer applies must not ride on the new one. v4 UUIDs carry a\n * version nibble inside both slices, so neither id can come out all-zero.\n */\nexport function ensureTraceparent(headers: Record<string, string>): string {\n const existing = traceIdOf(headers.traceparent ?? \"\");\n if (existing) return existing;\n delete headers.tracestate;\n const traceId = randomUUID().replaceAll(\"-\", \"\");\n const spanId = randomUUID().replaceAll(\"-\", \"\").slice(0, 16);\n headers.traceparent = `00-${traceId}-${spanId}-01`;\n return traceId;\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 a host match is the kind of thing\n * that goes wrong quietly. Testing it through `runProxy` would mean starting a\n * 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 * NOT ON THE ENV NAME, deliberately, which is where the Rust `oxy proxy` this\n * replaced differed: it refused `--env production` whatever URL that resolved\n * to, and so also refused `--target http://localhost:3000` with no `--env`\n * (the name defaulted to production). Here the URL is the truth — an\n * `oxy-app.json` that deliberately points `production` somewhere else is a\n * statement about where production is, and refusing it would make the manifest\n * 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.\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 // The browser going away takes the upstream request with it. Without this\n // an SSE stream nobody reads stays open against the cloud until it ends on\n // its own, which for an agent run is minutes.\n const abort = new AbortController();\n res.on(\"close\", () => {\n if (!res.writableFinished) abort.abort();\n });\n\n try {\n const headers = buildRequestHeaders(req.headers, token, path);\n // A function call gets a trace of its own, minted here when the SDK did\n // not already send one, so the line printed below names the trace an\n // operator would open — the developer who just watched the call fail\n // should not have to find the id by hand.\n const fn = functionRoute(path);\n const traceId = fn ? ensureTraceparent(headers) : undefined;\n const upstream = await fetch(`${target.replace(/\\/+$/, \"\")}${path}`, {\n method,\n headers,\n body: method === \"GET\" || method === \"HEAD\" ? undefined : body,\n redirect: \"manual\",\n signal: abort.signal\n });\n if (fn) {\n // Unconditional, not `log.info`: `--quiet` must not hide the one line\n // this proxy prints that you would paste somewhere else.\n const requestId = upstream.headers.get(\"x-oxy-request-id\") ?? \"-\";\n process.stderr.write(\n ` ↳ ${upstream.status} fn ${fn} request_id=${requestId} trace_id=${traceId}\\n`\n );\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. Waits on\n // `drain` so a slow browser holds the upstream back rather than this\n // process buffering the whole result set on its behalf.\n for await (const chunk of upstream.body as unknown as AsyncIterable<Uint8Array>) {\n if (!res.write(chunk)) await once(res, \"drain\", { signal: abort.signal });\n }\n }\n res.end();\n log.info(`${upstream.status} ${method} ${path}`);\n } catch (cause) {\n if (abort.signal.aborted) {\n log.info(`${out.dim(\"closed\")} ${method} ${path} (the browser went away)`);\n return;\n }\n log.error(`${method} ${path} failed: ${(cause as Error).message}`);\n // Once the status is on the wire there is no error response left to\n // send: a second `writeHead` throws, and a throw in this async handler is\n // an unhandled rejection that exits the whole proxy. Cut the connection\n // instead, so the browser sees a failed response rather than a\n // truncated one that reads as complete.\n if (res.headersSent) {\n res.destroy();\n return;\n }\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 * `.env.local`, then `.env`, loaded into `process.env` without overriding\n * anything already set — so a laptop publish sees what the shell would, and\n * CI's real environment always wins.\n *\n * Each file is looked for in the working directory and then every parent,\n * nearest first, which is how the Rust `dotenv` crate found them: an app under\n * `apps/<org>/<app>/` picks up a repo-root `.env`.\n *\n * `${VAR}` expansion is NOT supported. Nothing a publish reads has needed it,\n * and a half-implemented expander is worse than an honest literal.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\n\n/** The nearest `name` at or above `dir`. */\nfunction findUp(dir: string, name: string): string | undefined {\n let current = dir;\n for (;;) {\n const candidate = join(current, name);\n if (existsSync(candidate)) return candidate;\n const parent = dirname(current);\n if (parent === current) return undefined;\n current = parent;\n }\n}\n\n/** `KEY=value` lines into pairs. Comments, blanks and malformed lines are skipped. */\nexport function parseDotenv(text: string): Array<[string, string]> {\n const pairs: Array<[string, string]> = [];\n for (const raw of text.split(/\\r?\\n/)) {\n const line = raw.trim().replace(/^export\\s+/, \"\");\n if (!line || line.startsWith(\"#\")) continue;\n const eq = line.indexOf(\"=\");\n if (eq <= 0) continue;\n const key = line.slice(0, eq).trim();\n if (!/^[A-Za-z_][A-Za-z0-9_.]*$/.test(key)) continue;\n pairs.push([key, parseValue(line.slice(eq + 1).trim())]);\n }\n return pairs;\n}\n\nfunction parseValue(value: string): string {\n const quote = value[0];\n if ((quote === '\"' || quote === \"'\") && value.length >= 2) {\n const end = value.indexOf(quote, 1);\n if (end > 0) {\n const inner = value.slice(1, end);\n return quote === '\"' ? inner.replace(/\\\\n/g, \"\\n\") : inner;\n }\n }\n // Unquoted: a ` #` starts a trailing comment.\n const hash = value.search(/\\s#/);\n return (hash >= 0 ? value.slice(0, hash) : value).trim();\n}\n\n/** Load both files for `cwd`. Returns the paths that were read. */\nexport function loadDotenv(cwd: string, env: NodeJS.ProcessEnv = process.env): string[] {\n const read: string[] = [];\n for (const name of [\".env.local\", \".env\"]) {\n const path = findUp(cwd, name);\n if (!path) continue;\n let text: string;\n try {\n text = readFileSync(path, \"utf8\");\n } catch {\n continue;\n }\n read.push(path);\n for (const [key, value] of parseDotenv(text)) {\n if (env[key] === undefined) env[key] = value;\n }\n }\n return read;\n}\n","/**\n * `functions/` in a published bundle: reserved for Oxy Functions, bundled here.\n *\n * The serve plane blocks `functions/<child>` for EVERY app, so a frontend file\n * built into that directory is uploaded and then never served. The check runs\n * whether or not the app declares functions; only its severity depends on\n * whether this publish is about to write there.\n */\n\nimport { spawnSync } from \"node:child_process\";\nimport { existsSync, mkdirSync, readdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nimport { CliError, ExitCode } from \"../util/errors.js\";\nimport { isValidFunctionName } from \"./manifest.js\";\n\n/** What sits in `functions/` that this publish did not put there, sorted. */\nexport interface FunctionsDirConflicts {\n /**\n * `<name>.js` for a valid function name no longer declared — plausibly Oxy's\n * own output from an earlier publish. A GUESS from the filename (`main.js`\n * satisfies the grammar too), so it chooses wording only, never severity.\n */\n staleArtifacts: string[];\n /** Anything else: a page, an asset, a bundler chunk, a directory. */\n frontend: string[];\n}\n\nfunction looksLikeOurArtifact(name: string): boolean {\n return name.endsWith(\".js\") && isValidFunctionName(name.slice(0, -\".js\".length));\n}\n\n/**\n * Inspect the reserved directory. An absent directory is the normal case; any\n * other read failure is fatal, because \"could not tell\" must not read as \"no\n * collision\".\n */\nexport function functionsDirConflicts(outFns: string, declared: string[]): FunctionsDirConflicts {\n const expected = new Set(declared.map((name) => `${name}.js`));\n let entries: string[];\n try {\n entries = readdirSync(outFns);\n } catch (cause) {\n if ((cause as NodeJS.ErrnoException).code === \"ENOENT\")\n return { staleArtifacts: [], frontend: [] };\n throw new CliError(\n `cannot inspect the reserved bundle path ${outFns}: ${(cause as Error).message}`\n );\n }\n const conflicts: FunctionsDirConflicts = { staleArtifacts: [], frontend: [] };\n for (const name of entries.filter((entry) => !expected.has(entry))) {\n (looksLikeOurArtifact(name) ? conflicts.staleArtifacts : conflicts.frontend).push(name);\n }\n conflicts.staleArtifacts.sort();\n conflicts.frontend.sort();\n return conflicts;\n}\n\n/** A bounded, stable rendering: five names, then a count. */\nexport function describeEntries(entries: string[]): string {\n const shown = 5;\n const head = entries\n .slice(0, shown)\n .map((entry) => `functions/${entry}`)\n .join(\", \");\n const extra = entries.length - shown;\n return extra > 0 ? `${head} (and ${extra} more)` : head;\n}\n\n/**\n * Enforce the reserved path. Returns a warning to print, or throws.\n *\n * Writing (functions declared): ANY conflict refuses, one message for both\n * buckets. Not writing: one warning — refusing would break a publish that\n * works, over files that are merely unreachable.\n */\nexport function enforceReservedFunctionsDir(\n bundleDir: string,\n declared: string[],\n weWillWrite: boolean\n): string | undefined {\n const conflicts = functionsDirConflicts(join(bundleDir, \"functions\"), declared);\n if (conflicts.frontend.length === 0 && conflicts.staleArtifacts.length === 0) return undefined;\n\n if (!weWillWrite) {\n // Capped per bucket, then joined: capping a merged list lets alphabetical\n // order decide which class of file gets named at all.\n const listed = [conflicts.frontend, conflicts.staleArtifacts]\n .filter((list) => list.length > 0)\n .map(describeEntries)\n .join(\", \");\n return (\n `this bundle declares no Oxy Functions, but its build output contains ${listed}. ` +\n \"`functions/` is reserved in a published bundle — those files will be uploaded and \" +\n \"will NOT be served. Emit them somewhere else.\"\n );\n }\n\n const detail: string[] = [];\n if (conflicts.frontend.length > 0) {\n detail.push(\n ` - ${describeEntries(conflicts.frontend)} — looks like frontend output; emit it somewhere else`\n );\n }\n if (conflicts.staleArtifacts.length > 0) {\n detail.push(\n ` - ${describeEntries(conflicts.staleArtifacts)} — looks like an artifact from a previous ` +\n \"publish, for a function oxy-app.json no longer declares\"\n );\n }\n throw new CliError(\n \"`functions/` is reserved for Oxy Functions in a published bundle, and this build output \" +\n \"already contains files Oxy did not put there\",\n {\n code: ExitCode.REFUSED,\n detail: detail.join(\"\\n\"),\n hint:\n \"publishing would upload them into a path the serve plane blocks — emit them somewhere \" +\n \"else, or clean the build directory and re-publish\"\n }\n );\n}\n\n/** Runs a command, streaming its output; throws when it fails. */\nexport type Runner = (label: string, command: string, args: string[], cwd: string) => void;\n\nexport const spawnRunner: Runner = (label, command, args, cwd) => {\n process.stderr.write(`[${label}] $ ${[command, ...args].join(\" \")}\\n`);\n // The child's stdout goes to OUR stderr: stdout is the result (`--json`).\n const result = spawnSync(command, args, { cwd, stdio: [\"inherit\", 2, 2] });\n if (result.error) throw new CliError(`failed to start \\`${command}\\`: ${result.error.message}`);\n if (result.status !== 0) {\n throw new CliError(\n `\\`${[command, ...args].join(\" \")}\\` failed (exit ${result.status ?? \"signal\"})`\n );\n }\n};\n\n/**\n * esbuild each declared function into `<bundleDir>/functions/<name>.js`.\n *\n * Through the app's own toolchain (`pnpm exec esbuild`) so dependencies resolve\n * exactly as in `pnpm build`, from the app directory. Argv, not a shell string,\n * so an entry path cannot inject into the command line.\n */\nexport function bundleFunctions(\n entries: Array<{ name: string; entry: string }>,\n appDir: string,\n bundleDir: string,\n run: Runner = spawnRunner\n): void {\n if (entries.length === 0) return;\n const outFns = join(bundleDir, \"functions\");\n mkdirSync(outFns, { recursive: true });\n for (const { name, entry } of entries) {\n run(\n `fn:${name}`,\n \"pnpm\",\n [\n \"exec\",\n \"esbuild\",\n entry,\n \"--bundle\",\n \"--format=esm\",\n // The runtime provides `ctx` / `fetch`, not Node built-ins.\n \"--platform=neutral\",\n // Stack traces remap to the author's `.ts` lines…\n \"--sourcemap=inline\",\n // …without shipping every original source file inside the map.\n \"--sources-content=false\",\n `--outfile=${join(outFns, `${name}.js`)}`\n ],\n appDir\n );\n }\n}\n\n/**\n * `--prebuilt`: the bundle was built and its functions bundled elsewhere (a CI\n * build job). Every declared function must already be there — the server does\n * not check, so a missing one would publish fine and 404 at runtime.\n */\nexport function requirePrebuiltFunctions(bundleDir: string, declared: string[]): void {\n const missing = declared.filter(\n (name) => !existsSync(join(bundleDir, \"functions\", `${name}.js`))\n );\n if (missing.length === 0) return;\n throw new CliError(`--prebuilt bundle is missing ${missing.length} declared function(s)`, {\n code: ExitCode.USAGE,\n detail: missing.map((name) => ` functions/${name}.js`).join(\"\\n\"),\n hint: \"build it with `oxyc publish --build-only` first, which bundles them into the output directory\"\n });\n}\n\n/** Validate every declared name before anything is written. */\nexport function validateFunctionNames(declared: string[]): void {\n const bad = declared.find((name) => !isValidFunctionName(name));\n if (bad !== undefined) {\n throw new CliError(`invalid function name ${JSON.stringify(bad)}`, {\n code: ExitCode.USAGE,\n hint: \"function names must match ^[a-z][a-z0-9-]{0,63}$\"\n });\n }\n}\n","/**\n * Where a build came from: git remote, commit and branch, recorded per build so\n * the admin UI can link it back to code.\n *\n * NEVER FAILS A PUBLISH. A `--dir` publish from a directory that is not a\n * checkout, or a runner with no git at all, is legitimate — every git answer\n * here degrades to \"unknown\", and the gaps become warnings.\n */\n\nimport { spawnSync } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\n\n/** One git answer, or `undefined` for any failure including a missing binary. */\nfunction gitAnswer(args: string[], cwd: string): string | undefined {\n try {\n const result = spawnSync(\"git\", args, { cwd, encoding: \"utf8\" });\n if (result.error || result.status !== 0) return undefined;\n return result.stdout.trim() || undefined;\n } catch {\n return undefined;\n }\n}\n\nexport interface GitSource {\n repo?: string;\n commit?: string;\n branch?: string;\n}\n\n/**\n * Remote, HEAD and branch of the checkout at `dir`.\n *\n * A detached HEAD reports no branch rather than the literal `HEAD` that\n * `rev-parse --abbrev-ref` prints — so a CI checkout of a pinned commit falls\n * through to `GITHUB_REF_NAME` instead of recording a branch named \"HEAD\".\n */\nexport function captureGitSource(dir: string): GitSource {\n const branch = gitAnswer([\"rev-parse\", \"--abbrev-ref\", \"HEAD\"], dir);\n return {\n repo: gitAnswer([\"remote\", \"get-url\", \"origin\"], dir),\n commit: gitAnswer([\"rev-parse\", \"HEAD\"], dir),\n branch: branch === \"HEAD\" ? undefined : branch\n };\n}\n\n/**\n * Uncommitted changes under `dir` — staged, unstaged or untracked — or\n * `undefined` when git cannot say.\n *\n * SCOPED TO `dir` by the `-- .` pathspec: many apps share one repo, and a\n * colleague's edit to a different app must not make this warning cry wolf.\n */\nexport function worktreeIsDirty(dir: string): boolean | undefined {\n try {\n const result = spawnSync(\"git\", [\"status\", \"--porcelain\", \"--\", \".\"], {\n cwd: dir,\n encoding: \"utf8\"\n });\n if (result.error || result.status !== 0) return undefined;\n return result.stdout.trim().length > 0;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Strip `userinfo@` from a scheme URL before it is persisted — an\n * `https://x-access-token:<TOKEN>@github.com/…` remote must never reach the\n * database. The scp-like `git@github.com:o/r` form carries no secret.\n */\nexport function sanitizeRemoteUrl(url: string): string {\n const schemeEnd = url.indexOf(\"://\");\n if (schemeEnd < 0) return url;\n const start = schemeEnd + 3;\n const rest = url.slice(start);\n const authorityEnd = rest.includes(\"/\") ? rest.indexOf(\"/\") : rest.length;\n const at = rest.slice(0, authorityEnd).lastIndexOf(\"@\");\n return at < 0 ? url : url.slice(0, start) + rest.slice(at + 1);\n}\n\n/** A field counts only with non-whitespace content: `--repo \"\"` is not provenance. */\nexport function isRecorded(value: string | undefined): boolean {\n return value !== undefined && value.trim().length > 0;\n}\n\nexport type ProvenanceGap = \"no-source\" | \"missing-repo\" | \"missing-commit\" | \"dirty-tree\";\n\n/**\n * Every way the recorded provenance fails to describe what is being shipped.\n *\n * Incompleteness (the same classification the admin list makes) and dirtiness\n * are orthogonal, so both are returned. A dirty tree only matters behind a\n * recorded commit — without one there is no claim for it to contradict.\n */\nexport function provenanceGaps(\n dirty: boolean | undefined,\n commit: string | undefined,\n repo: string | undefined\n): ProvenanceGap[] {\n const hasRepo = isRecorded(repo);\n const hasCommit = isRecorded(commit);\n const gaps: ProvenanceGap[] = [];\n if (!hasRepo && !hasCommit) gaps.push(\"no-source\");\n else if (!hasRepo) gaps.push(\"missing-repo\");\n else if (!hasCommit) gaps.push(\"missing-commit\");\n if (dirty === true && hasCommit) gaps.push(\"dirty-tree\");\n return gaps;\n}\n\nexport const GAP_MESSAGES: Record<ProvenanceGap, string> = {\n \"no-source\":\n \"no git source recorded for this build — nobody will be able to trace it back to code. \" +\n \"Publish from the app's git checkout, or pass --repo/--commit.\",\n \"missing-commit\":\n \"a git repo is recorded for this build but no commit — the link points at a branch, which \" +\n \"moves, so it won't identify the code that is running. Pass --commit, or publish from the checkout.\",\n \"missing-repo\":\n \"a commit is recorded for this build but no git repo — there is nowhere to resolve that sha. \" +\n \"Pass --repo, or publish from the checkout.\",\n \"dirty-tree\":\n \"publishing from a dirty working tree — the commit recorded for this build does NOT contain \" +\n \"the changes you are shipping. Commit and re-publish if this build needs to be reproducible.\"\n};\n\n/**\n * The default build id under GitHub Actions: the commit, qualified by the run.\n *\n * `GITHUB_SHA` alone repeats on \"Re-run all jobs\", and a build id is immutable\n * and cached by id — a reused one is a 409 at best and a merge into a cached\n * build at worst. Each qualifier falls back independently.\n */\nexport function ciBuildId(env: NodeJS.ProcessEnv = process.env): string | undefined {\n const sha = env.GITHUB_SHA?.trim();\n if (!sha) return undefined;\n const run = env.GITHUB_RUN_ID?.trim();\n const attempt = env.GITHUB_RUN_ATTEMPT?.trim();\n if (run && attempt) return `${sha}-${run}.${attempt}`;\n if (run) return `${sha}-${run}`;\n return sha;\n}\n\n/** `--build-id`, else the CI id, else a random one. */\nexport function resolveBuildId(\n flag: string | undefined,\n env: NodeJS.ProcessEnv = process.env\n): string {\n return flag?.trim() || ciBuildId(env) || randomUUID().replaceAll(\"-\", \"\");\n}\n","/**\n * The three HTTP calls a publish makes, plus the trusted-publishing exchange.\n *\n * Direct `fetch` rather than `api/request.ts`: the upload is multipart and the\n * two lookups are public, and neither fits a JSON-string request with a\n * credential chosen by path. What they share with it is the exit-code mapping.\n */\n\nimport { CliError, ExitCode, exitCodeForStatus } from \"../util/errors.js\";\n\nconst LOOKUP_TIMEOUT_MS = 30_000;\n/** The bundle upload, which can be tens of megabytes. */\nconst UPLOAD_TIMEOUT_MS = 120_000;\n\nasync function send(url: string, init: RequestInit, timeoutMs: number): Promise<Response> {\n try {\n return await fetch(url, { ...init, signal: AbortSignal.timeout(timeoutMs) });\n } catch (cause) {\n throw new CliError(`${init.method ?? \"GET\"} ${url} failed: ${(cause as Error).message}`, {\n code: ExitCode.UNAVAILABLE\n });\n }\n}\n\nasync function json<T>(response: Response, what: string): Promise<T> {\n const text = await response.text();\n try {\n return JSON.parse(text) as T;\n } catch {\n throw new CliError(`could not parse the ${what} response`, {\n code: ExitCode.UNAVAILABLE,\n detail: text.slice(0, 2000)\n });\n }\n}\n\nfunction base(target: string): string {\n return target.replace(/\\/+$/, \"\");\n}\n\n/** The project an app publishes into, from its `(org, app)` on the target. Public. */\nexport async function fetchProject(target: string, org: string, app: string): Promise<string> {\n const url = `${base(target)}/api/apps/${encodeURIComponent(org)}/${encodeURIComponent(app)}/build-config`;\n const response = await send(url, {}, LOOKUP_TIMEOUT_MS);\n if (response.status === 404) {\n throw new CliError(`app ${org}/${app} is not registered on ${target}`, {\n code: ExitCode.NOT_FOUND,\n hint: \"register it in the oxy admin UI, or pass --project <uuid> for its first publish\"\n });\n }\n if (!response.ok) {\n throw new CliError(`build-config lookup failed (${response.status}) at ${url}`, {\n code: exitCodeForStatus(response.status)\n });\n }\n return (await json<{ project_id: string }>(response, \"build-config\")).project_id;\n}\n\n/** The org a pinned workspace belongs to — a workspace has exactly one. Public. */\nexport async function fetchOrgForProject(target: string, projectId: string): Promise<string> {\n const url = `${base(target)}/api/org-for-project/${encodeURIComponent(projectId)}`;\n const response = await send(url, {}, LOOKUP_TIMEOUT_MS);\n if (response.status === 404) {\n throw new CliError(`workspace ${projectId} not found on ${target}`, {\n code: ExitCode.NOT_FOUND,\n hint: \"check --project / OXY_PROJECT\"\n });\n }\n if (!response.ok) {\n throw new CliError(`org-for-project lookup failed (${response.status}) at ${url}`, {\n code: exitCodeForStatus(response.status)\n });\n }\n return (await json<{ org_slug: string }>(response, \"org-for-project\")).org_slug;\n}\n\n/** The server's `PublishResult`. Extra fields are tolerated. */\nexport interface PublishResult {\n app_id: string;\n build_id: string;\n url: string;\n channel: string;\n org_slug?: string;\n is_new_app?: boolean;\n warnings?: string[];\n}\n\nexport interface UploadRequest {\n target: string;\n token: string;\n /** Multipart text fields, in order. Undefined values are left out. */\n fields: Array<[string, string | undefined]>;\n tarball: Buffer;\n}\n\n/**\n * POST the bundle. Resolves the parsed result, or throws with the status\n * mapped onto the exit-code contract and the server's body as detail.\n */\nexport async function uploadBundle(req: UploadRequest): Promise<PublishResult> {\n const form = new FormData();\n for (const [name, value] of req.fields) {\n if (value !== undefined) form.append(name, value);\n }\n // A copy into a plain ArrayBuffer: `Blob` does not accept a Buffer that may\n // sit on a SharedArrayBuffer, which is what the type of `gzipSync`'s result allows.\n const bytes = new Uint8Array(req.tarball);\n form.append(\"bundle\", new Blob([bytes], { type: \"application/gzip\" }), \"bundle.tar.gz\");\n\n const url = `${base(req.target)}/api/customer-apps/publish`;\n const response = await send(\n url,\n { method: \"POST\", headers: { authorization: `Bearer ${req.token}` }, body: form },\n UPLOAD_TIMEOUT_MS\n );\n if (!response.ok) {\n const body = await response.text();\n throw new CliError(`publish failed (${response.status})`, {\n code: exitCodeForStatus(response.status),\n detail: body.slice(0, 4000)\n });\n }\n return json<PublishResult>(response, \"publish\");\n}\n\n/** The two variables GitHub sets in a job granted `id-token: write`. */\nexport function githubOidcAvailable(env: NodeJS.ProcessEnv = process.env): boolean {\n return Boolean(env.ACTIONS_ID_TOKEN_REQUEST_URL && env.ACTIONS_ID_TOKEN_REQUEST_TOKEN);\n}\n\n/** The audience the server pins. A token minted for any other is refused. */\nexport const OIDC_AUDIENCE = \"oxy-publish\";\n\n/**\n * Trusted publishing: a GitHub OIDC token, exchanged for a publish credential\n * scoped to exactly `org/app` and valid for fifteen minutes.\n *\n * Called immediately before the upload, not at startup: the OIDC token is\n * single-use and the credential short-lived, and a build can take longer than\n * either should be held. The server matches the token's claims against a\n * publisher registered for the app — repository owner id, repo, workflow path,\n * environment — so a 403 here almost always means a registration mismatch.\n */\nexport async function exchangeGithubOidc(\n target: string,\n orgSlug: string,\n app: string,\n env: NodeJS.ProcessEnv = process.env\n): Promise<string> {\n const requestUrl = new URL(env.ACTIONS_ID_TOKEN_REQUEST_URL ?? \"\");\n requestUrl.searchParams.set(\"audience\", OIDC_AUDIENCE);\n const minted = await send(\n requestUrl.toString(),\n { headers: { authorization: `bearer ${env.ACTIONS_ID_TOKEN_REQUEST_TOKEN}` } },\n LOOKUP_TIMEOUT_MS\n );\n if (!minted.ok) {\n throw new CliError(`GitHub refused to mint an OIDC token (${minted.status})`, {\n code: ExitCode.AUTH,\n hint: \"the publishing job needs `permissions: id-token: write`\"\n });\n }\n const oidc = (await json<{ value?: string }>(minted, \"GitHub OIDC\")).value;\n if (!oidc) throw new CliError(\"GitHub returned no OIDC token\", { code: ExitCode.AUTH });\n\n const url = `${base(target)}/api/customer-apps/publish/oidc-exchange`;\n const exchanged = await send(\n url,\n {\n method: \"POST\",\n // `Bearer` exactly: the server matches the prefix case-sensitively.\n headers: { authorization: `Bearer ${oidc}`, \"content-type\": \"application/json\" },\n body: JSON.stringify({ app: `${orgSlug}/${app}` })\n },\n LOOKUP_TIMEOUT_MS\n );\n if (!exchanged.ok) {\n const body = await exchanged.text();\n throw new CliError(`trusted-publishing exchange failed (${exchanged.status})`, {\n code: exitCodeForStatus(exchanged.status),\n detail: body.slice(0, 2000),\n hint: `is this workflow registered as a publisher for ${orgSlug}/${app}, with the same repository, workflow file and environment?`\n });\n }\n const token = (await json<{ token?: string }>(exchanged, \"exchange\")).token;\n if (!token) throw new CliError(\"the exchange returned no token\", { code: ExitCode.AUTH });\n return token;\n}\n","/**\n * The bundle as a `.tar.gz`, entries at the archive root.\n *\n * WRITTEN HERE rather than taken from a tar package. The format needed is\n * small — POSIX ustar headers, plus a PAX `path` record for a name over 100\n * bytes — and `oxyc` also ships as a Bun-compiled binary, where a dependency\n * that reaches into Node's zlib internals can work under every test (which\n * run on Node) and fail only in the binary. `gzipSync` is public API on both.\n *\n * Symlinks are FOLLOWED and archived as their target's contents, as the Rust\n * client did: a link entry would unpack server-side as an empty file.\n */\n\nimport { readdirSync, readFileSync, realpathSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { gzipSync } from \"node:zlib\";\n\nimport { CliError, ExitCode } from \"../util/errors.js\";\n\nconst BLOCK = 512;\n\nfunction octal(value: number, width: number): string {\n return `${value.toString(8).padStart(width - 1, \"0\")}\\0`;\n}\n\n/** One 512-byte header block. `name` is written raw, truncated to 100 bytes. */\nfunction header(name: Buffer, size: number, mode: number, mtime: number, type: string): Buffer {\n const block = Buffer.alloc(BLOCK);\n name.copy(block, 0, 0, Math.min(name.length, 100));\n block.write(octal(mode, 8), 100, \"ascii\");\n block.write(octal(0, 8), 108, \"ascii\");\n block.write(octal(0, 8), 116, \"ascii\");\n block.write(octal(size, 12), 124, \"ascii\");\n block.write(octal(mtime, 12), 136, \"ascii\");\n block.write(\" \".repeat(8), 148, \"ascii\");\n block.write(type, 156, \"ascii\");\n block.write(\"ustar\\0\", 257, \"ascii\");\n block.write(\"00\", 263, \"ascii\");\n let sum = 0;\n for (const byte of block) sum += byte;\n block.write(`${sum.toString(8).padStart(6, \"0\")}\\0 `, 148, \"ascii\");\n return block;\n}\n\n/** `<len> path=<path>\\n`, where `<len>` counts the whole record including itself. */\nexport function paxPathRecord(path: string): Buffer {\n const body = ` path=${path}\\n`;\n const bodyLength = Buffer.byteLength(body);\n let length = bodyLength + String(bodyLength).length;\n if (String(length).length !== String(bodyLength).length)\n length = bodyLength + String(length).length;\n return Buffer.from(`${length}${body}`);\n}\n\nfunction padding(size: number): Buffer {\n const rest = size % BLOCK;\n return Buffer.alloc(rest === 0 ? 0 : BLOCK - rest);\n}\n\ninterface Entry {\n path: string;\n kind: \"file\" | \"dir\";\n source: string;\n}\n\n/**\n * Every entry under `root`, directories before their contents, sorted so the\n * same tree always produces the same archive. A symlinked directory that\n * points back up the tree is visited once.\n */\nfunction walk(root: string): Entry[] {\n const entries: Entry[] = [];\n const seen = new Set<string>([realpathSync(root)]);\n const visit = (dir: string, prefix: string): void => {\n for (const name of readdirSync(dir).sort()) {\n const source = join(dir, name);\n const path = prefix ? `${prefix}/${name}` : name;\n const stat = statSync(source);\n if (stat.isDirectory()) {\n const real = realpathSync(source);\n if (seen.has(real)) continue;\n seen.add(real);\n entries.push({ path: `${path}/`, kind: \"dir\", source });\n visit(source, path);\n } else if (stat.isFile()) {\n entries.push({ path, kind: \"file\", source });\n }\n }\n };\n visit(root, \"\");\n return entries;\n}\n\nfunction entryBlocks(entry: Entry): Buffer[] {\n const stat = statSync(entry.source);\n const mtime = Math.floor(stat.mtimeMs / 1000);\n const name = Buffer.from(entry.path);\n const blocks: Buffer[] = [];\n if (name.length > 100) {\n const record = paxPathRecord(entry.path);\n blocks.push(header(Buffer.from(\"PaxHeader\"), record.length, 0o644, mtime, \"x\"));\n blocks.push(record, padding(record.length));\n }\n if (entry.kind === \"dir\") {\n blocks.push(header(name, 0, 0o755, mtime, \"5\"));\n return blocks;\n }\n const content = readFileSync(entry.source);\n const mode = stat.mode & 0o111 ? 0o755 : 0o644;\n blocks.push(header(name, content.length, mode, mtime, \"0\"), content, padding(content.length));\n return blocks;\n}\n\n/** Tar and gzip the contents of `dir`. Throws when it is not a directory. */\nexport function tarGzDir(dir: string): Buffer {\n let isDir = false;\n try {\n isDir = statSync(dir).isDirectory();\n } catch {\n isDir = false;\n }\n if (!isDir) {\n throw new CliError(`bundle dir ${dir} does not exist (did the build run?)`, {\n code: ExitCode.USAGE\n });\n }\n const blocks = walk(dir).flatMap(entryBlocks);\n blocks.push(Buffer.alloc(BLOCK * 2));\n return gzipSync(Buffer.concat(blocks));\n}\n","/**\n * `oxyc publish` — build a custom app and ship the bundle to an Oxy deployment.\n *\n * From an app directory: read `oxy-app.json`, build per its `build` block (or\n * the defaults), bundle any Oxy Functions, resolve the project from the\n * target's public `build-config`, and POST the tarball. It replaced the Rust\n * `oxy publish` flag for flag; what it adds:\n *\n * --build-only build and bundle, stop before anything needs a credential\n * --prebuilt with --dir: the functions are already bundled — check, don't rebuild\n * --json the server's result, warnings included, on stdout\n *\n * and trusted publishing: in a GitHub Actions job granted `id-token: write`\n * with no token set, it exchanges the job's OIDC token for a credential scoped\n * to this one app.\n *\n * `--build-only` and `--prebuilt` exist for CI that keeps the credential out of\n * the job that runs package scripts: build there, publish the artifact in a job\n * that installs nothing.\n */\n\nimport { spawnSync } from \"node:child_process\";\nimport { join, resolve, sep } from \"node:path\";\n\nimport type { Context } from \"../context/resolve.js\";\nimport { loadDotenv } from \"../publish/dotenv.js\";\nimport {\n bundleFunctions,\n enforceReservedFunctionsDir,\n requirePrebuiltFunctions,\n validateFunctionNames\n} from \"../publish/functions.js\";\nimport {\n buildSteps,\n declaredFunctions,\n functionEntry,\n isValidSlug,\n loadPublishManifest,\n type PublishManifest\n} from \"../publish/manifest.js\";\nimport {\n captureGitSource,\n GAP_MESSAGES,\n isRecorded,\n provenanceGaps,\n resolveBuildId,\n sanitizeRemoteUrl,\n worktreeIsDirty\n} from \"../publish/provenance.js\";\nimport {\n exchangeGithubOidc,\n fetchOrgForProject,\n fetchProject,\n githubOidcAvailable,\n type PublishResult,\n uploadBundle\n} from \"../publish/server.js\";\nimport { tarGzDir } from \"../publish/tarball.js\";\nimport * as log from \"../ui/log.js\";\nimport { out } from \"../ui/tty.js\";\nimport { authError, CliError, ExitCode, usageError } from \"../util/errors.js\";\n\nexport interface PublishFlags {\n app?: string;\n buildId?: string;\n dir?: string;\n promote?: boolean;\n name?: string;\n repo?: string;\n commit?: string;\n branch?: string;\n buildOnly?: boolean;\n prebuilt?: boolean;\n json?: boolean;\n}\n\nfunction envValue(name: string): string | undefined {\n return process.env[name]?.trim() || undefined;\n}\n\n/** `(org, app)` from a working directory shaped `…/apps/<org>/<app>[/…]`. */\nexport function inferOrgApp(cwd: string): { org?: string; app?: string } {\n const parts = cwd.split(sep).filter(Boolean);\n const index = parts.lastIndexOf(\"apps\");\n if (index < 0) return {};\n return { org: parts[index + 1], app: parts[index + 2] };\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/** How this publish will authenticate, decided before anything is built. */\ntype Credential = { kind: \"token\"; token: string } | { kind: \"oidc\" };\n\nfunction resolveCredential(ctx: Context): Credential {\n const token = ctx.maybeBearer();\n if (token) return { kind: \"token\", token };\n if (githubOidcAvailable()) return { kind: \"oidc\" };\n throw authError(ctx.target(), ctx.flags.env ?? \"production\", ctx.flags.tokenEnv ?? \"OXY_TOKEN\");\n}\n\n/** One manifest build step, output to stderr so stdout stays the result. */\nfunction runBuildStep(label: string, command: string, cwd: string, basePath: string): void {\n process.stderr.write(`[${label}] $ ${command}\\n`);\n const result = spawnSync(\"sh\", [\"-c\", command], {\n cwd,\n stdio: [\"inherit\", 2, 2],\n env: { ...process.env, OXY_APP_BASE_PATH: basePath }\n });\n if (result.error) throw new CliError(`failed to start \\`${command}\\`: ${result.error.message}`);\n if (result.status !== 0) {\n throw new CliError(`build step \\`${command}\\` failed (exit ${result.status ?? \"signal\"})`);\n }\n}\n\ninterface Identity {\n org?: string;\n app: string;\n}\n\n/** flag → env → manifest → directory, for each half. */\nfunction resolveIdentity(ctx: Context, flags: PublishFlags, manifest?: PublishManifest): Identity {\n const inferred = inferOrgApp(ctx.cwd);\n const org = ctx.flags.org ?? envValue(\"OXY_ORG\") ?? manifest?.orgSlug ?? inferred.org;\n const app = flags.app ?? envValue(\"OXY_APP\") ?? manifest?.slug ?? inferred.app;\n if (!app) throw usageError(\"missing app\", \"set oxy-app.json `slug`, --app, or OXY_APP\");\n if (!isValidSlug(app)) {\n throw usageError(\n `invalid app slug ${JSON.stringify(app)}`,\n \"1-63 lowercase letters, digits and single hyphens — no leading, trailing or double hyphen, no underscore\"\n );\n }\n return { org, app };\n}\n\n/** Build from source (unless --dir), then check and bundle `functions/`. */\nfunction prepareBundle(\n ctx: Context,\n flags: PublishFlags,\n manifest: PublishManifest | undefined,\n identity: Identity\n): string {\n const declared = declaredFunctions(manifest);\n validateFunctionNames(declared);\n\n let bundleDir: string;\n if (flags.dir) {\n bundleDir = resolve(ctx.cwd, flags.dir);\n } else {\n if (!identity.org) {\n throw usageError(\n \"missing org: the app's base path needs it\",\n \"set oxy-app.json `orgSlug`, --org, OXY_ORG, or --project (a workspace determines its org), or publish a pre-built bundle with --dir\"\n );\n }\n const steps = buildSteps(manifest);\n const basePath = `/customer-apps/${identity.org}/${identity.app}/`;\n runBuildStep(\"install\", steps.install, ctx.cwd, basePath);\n runBuildStep(\"build\", steps.command, ctx.cwd, basePath);\n bundleDir = join(ctx.cwd, steps.outDir);\n }\n\n const warning = enforceReservedFunctionsDir(bundleDir, declared, declared.length > 0);\n if (warning) log.warn(warning);\n\n if (flags.prebuilt) {\n requirePrebuiltFunctions(bundleDir, declared);\n } else {\n const entries = declared.map((name) => ({ name, entry: functionEntry(manifest, name) }));\n bundleFunctions(entries, ctx.cwd, bundleDir);\n }\n return bundleDir;\n}\n\ninterface Provenance {\n repo?: string;\n commit?: string;\n branch?: string;\n}\n\n/** Flags win, then the checkout, then the CI variables; every gap is a warning. */\nfunction resolveProvenance(cwd: string, flags: PublishFlags): Provenance {\n const git = captureGitSource(cwd);\n const repoSource = flags.repo ?? git.repo;\n const provenance = {\n repo: repoSource === undefined ? undefined : sanitizeRemoteUrl(repoSource),\n commit: flags.commit ?? git.commit ?? envValue(\"GITHUB_SHA\"),\n branch: flags.branch ?? git.branch ?? envValue(\"GITHUB_REF_NAME\")\n };\n // Only ask git about dirt when there is a recorded commit for it to contradict.\n const dirty = isRecorded(provenance.commit) ? worktreeIsDirty(cwd) : undefined;\n for (const gap of provenanceGaps(dirty, provenance.commit, provenance.repo)) {\n log.warn(GAP_MESSAGES[gap]);\n }\n return provenance;\n}\n\n/** The credential for the upload itself — the OIDC exchange happens here, last. */\nasync function uploadToken(\n ctx: Context,\n credential: Credential,\n identity: Identity\n): Promise<string> {\n if (credential.kind === \"token\") return credential.token;\n if (!identity.org || UUID.test(identity.org)) {\n throw usageError(\n \"trusted publishing needs the org SLUG\",\n \"set oxy-app.json `orgSlug` or pass --org <slug> — the exchange is registered by slug\"\n );\n }\n log.info(\"exchanging the GitHub OIDC token for a publish credential\");\n return exchangeGithubOidc(ctx.target(), identity.org, identity.app);\n}\n\nfunction printResult(\n target: string,\n identity: Identity,\n result: PublishResult,\n asJson: boolean\n): void {\n for (const warning of result.warnings ?? []) log.warn(warning);\n if (asJson) {\n process.stdout.write(`${JSON.stringify(result, null, 2)}\\n`);\n return;\n }\n const org = result.org_slug ?? identity.org ?? \"\";\n const headline = result.is_new_app\n ? `Registered new app ${org}/${identity.app} (id ${result.app_id})`\n : `Published new version of ${org}/${identity.app} (id ${result.app_id})`;\n process.stdout.write(\n `${out.green(headline)}\\n` +\n ` build ${result.build_id} → ${result.channel} channel · ${target}${result.url}\\n`\n );\n}\n\nexport async function runPublish(ctx: Context, flags: PublishFlags): Promise<void> {\n if (flags.prebuilt && !flags.dir) {\n throw usageError(\"--prebuilt needs --dir\", \"it names a bundle that was built elsewhere\");\n }\n if (flags.prebuilt && flags.buildOnly) {\n throw usageError(\"--prebuilt and --build-only together do nothing\", \"drop one\");\n }\n\n for (const path of loadDotenv(ctx.cwd)) log.info(`loaded ${path}`);\n const manifest = loadPublishManifest(ctx.cwd);\n const identity = resolveIdentity(ctx, flags, manifest);\n const projectPin = ctx.flags.project ?? envValue(\"OXY_PROJECT\");\n\n // Decided before the build, so a missing login fails in a second rather\n // than after a two-minute install.\n const credential = flags.buildOnly ? undefined : resolveCredential(ctx);\n if (!identity.org && projectPin) {\n identity.org = await fetchOrgForProject(ctx.target(), projectPin);\n }\n\n const bundleDir = prepareBundle(ctx, flags, manifest, identity);\n if (flags.buildOnly || !credential) {\n if (flags.json) process.stdout.write(`${JSON.stringify({ bundle_dir: bundleDir }, null, 2)}\\n`);\n else process.stdout.write(`${out.green(\"built\")} ${bundleDir}\\n`);\n return;\n }\n\n const target = ctx.target();\n let project = projectPin;\n if (!project) {\n if (!identity.org) {\n throw usageError(\n \"missing org: needed to look up the project\",\n \"set oxy-app.json `orgSlug`, --org or OXY_ORG, or pass --project <uuid>\"\n );\n }\n project = await fetchProject(target, identity.org, identity.app);\n }\n\n const buildId = resolveBuildId(flags.buildId);\n const provenance = resolveProvenance(ctx.cwd, flags);\n const tarball = tarGzDir(bundleDir);\n const channel = flags.promote ? \"published\" : \"draft\";\n const who = identity.org\n ? `${identity.org}/${identity.app}`\n : `${identity.app} → workspace ${project}`;\n log.info(`publishing ${who} (${tarball.length} bytes) → ${target} [${channel}]`);\n\n const token = await uploadToken(ctx, credential, identity);\n let result: PublishResult;\n try {\n result = await uploadBundle({\n target,\n token,\n tarball,\n fields: [\n [\"app\", identity.app],\n [\"project\", project],\n [\"build_id\", buildId],\n [\"channel\", channel],\n // Optional: a pre-built bundle pinned to a project lets the server infer it.\n [\"org\", identity.org],\n [\"name\", flags.name],\n [\"source_repo\", provenance.repo],\n [\"commit_sha\", provenance.commit],\n [\"branch\", provenance.branch]\n ]\n });\n } catch (cause) {\n if (cause instanceof CliError && cause.code === ExitCode.AUTH && credential.kind === \"token\") {\n throw new CliError(cause.message, {\n code: cause.code,\n detail: cause.detail,\n hint: `publishing needs app-admin rights on the org — \\`oxyc whoami --env ${ctx.flags.env ?? \"production\"}\\` shows yours`\n });\n }\n throw cause;\n }\n printResult(target, identity, result, Boolean(flags.json));\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 = \"100ac2fc00976a2e\";\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 { tmpdir } from \"node:os\";\nimport { dirname, join, resolve, sep } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { CliError, ExitCode } from \"../util/errors.js\";\nimport {\n ASSET_DIRS,\n embeddedAssetsDir,\n extractEmbeddedAssets,\n REINSTALL_REMEDY\n} 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 * Why a path will not still be there tomorrow, phrased for an error message —\n * or `undefined` when it looks durable.\n *\n * ONLY `skills install` needs this, and only because it SYMLINKS. Every other\n * command reads its assets and is done; a link outlives the process and is read\n * months later by something that is not this tool. Run under `npx`, the package\n * lives in npm's `_npx` cache, so `oxyc skills install` reports six skills\n * linked, in green, and every one of them dangles the moment npm reclaims that\n * cache — Claude Code then silently stops loading them, and `~/.claude/skills/`\n * still looks populated. That is the exact failure `commands/skills.ts` opens by\n * describing: links out of a tree that had to persist forever, and did not.\n *\n * WHAT IS DELIBERATELY NOT MATCHED is as important as what is. A compiled\n * binary unpacks its assets into `<cache>/oxyc/assets/<digest>/`\n * (`template/embedded.ts`) — a cache directory, and a perfectly supported place\n * to link out of, because the curl install has nowhere else to put them and the\n * path is stable for as long as that build is installed. It is EXEMPTED BY\n * NAME, first and unconditionally, rather than left to the rules below to miss:\n * `cacheDir()` is `$XDG_CACHE_HOME` or `$HOME/.cache`, both of which a sandbox\n * or an ephemeral container can perfectly well place under the temp dir — and\n * then the last rule here would refuse the one install shape that has nowhere\n * else to keep its assets, quoting a remedy (`npm install -g`) that is not even\n * how that user installed. Everything else matches package-manager EXEC caches\n * specifically, never \"somewhere under a cache dir\", which is why `dlx` and\n * `_npx` are exact path segments.\n *\n * The escape hatch already exists and needs no flag: `OXYC_SKILLS_DIR` pointing\n * at a durable copy is checked here like any other source, so a setup this\n * heuristic misjudges has a one-line way past it.\n */\nexport function ephemeralSourceReason(path: string): string | undefined {\n const full = resolve(path);\n\n // The compiled binary's own unpacked assets — supported, and checked before\n // anything else so no later rule can take it away.\n const assets = resolve(embeddedAssetsDir());\n if (full === assets || full.startsWith(assets + sep)) return undefined;\n\n const segments = full.split(sep);\n // npm's `npx` cache: ~/.npm/_npx/<hash>/node_modules/...\n if (segments.includes(\"_npx\")) return \"an `npx` cache directory\";\n // `pnpm dlx` / `yarn dlx` unpack into a `dlx` directory under the store.\n if (segments.includes(\"dlx\")) return \"a `dlx` cache directory\";\n // `yarn dlx` and some `bunx` paths land straight in the system temp dir.\n if (full.startsWith(resolve(tmpdir()) + sep)) return \"a temporary directory\";\n return undefined;\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 { ephemeralSourceReason, 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 // REFUSED BEFORE ANY LINK IS MADE, because the alternative is worse than a\n // failure: `npx @oxy-hq/cli skills install` links out of npm's throwaway\n // cache, prints six green `linked` rows, and leaves six dangling entries the\n // moment npm reclaims it. Claude Code just stops loading them — no error, and\n // `~/.claude/skills/` still looks full.\n //\n // Refusing rather than COPYING, which is the friendlier-looking option and a\n // trap: real directories at those names are exactly what `linkOne` below\n // rightly declines to clobber, so a copy here would wedge every later\n // `skills install` from a proper global install. One upfront no beats a\n // permanent block.\n const ephemeral = ephemeralSourceReason(source);\n if (ephemeral) {\n throw refusal(`refusing to link skills out of ${ephemeral}`, {\n hint:\n \"the links would work now and break silently later — `oxyc skills install` \" +\n \"writes symlinks that something else reads months from now, so the source \" +\n \"has to outlive this process.\",\n detail: ` source: ${source}`,\n remedy: \"npm install -g @oxy-hq/cli && oxyc skills install\"\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 { loadForTargetResolution, 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\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 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 // Read here rather than up front: a broken oxy-app.json is an error, and\n // it must not fail a command that never resolves a target (`oxyc list`).\n const manifest = loadForTargetResolution(cwd, flags.target);\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 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 { runInitCi } from \"./commands/init-ci.js\";\nimport { runLaunch } from \"./commands/launch.js\";\nimport { runProxy } from \"./commands/proxy.js\";\nimport { runPublish } from \"./commands/publish.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 { VERSION } from \"./generated/version.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 the Rust `oxy login`\n * accepted 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 // From `package.json`, via `scripts/emit-version.mjs`. It was a literal, so\n // `oxyc --version` was a second copy of the version that a release bump did\n // not touch — worst for the standalone binary, where `--version` is the\n // only way to tell what you have.\n .version(VERSION)\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 the matching endpoints as a JSON array\")\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, as the Rust `oxy login`'s `--env` was. 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. Checked here because this is\n // 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 — --org takes a slug, a UUID, or an org URL\")\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 // Both together refuse. Silently preferring one is the wrong call when\n // the verb is destructive: a caller who typed both meant something, and\n // 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 the customers as a JSON array\")\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: side-effecting calls are HELD, tracking events are\\n\" +\n \"DROPPED, auth endpoints reach the backend unauthenticated so sign-in works, and\\n\" +\n \"the cached token is a fallback that never overrides a real browser session.\\n\" +\n \"\\nEach Oxy Function call prints `↳ <status> fn <name> request_id=… trace_id=…`.\\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 withGlobals(\n program\n .command(\"publish\")\n .description(\"build a custom app and publish its bundle (a draft, unless --promote)\")\n .option(\n \"--app <slug>\",\n \"app slug (default: OXY_APP, then oxy-app.json slug, then apps/<org>/<app>/)\"\n )\n .option(\"--build-id <id>\", \"unique per publish (default: the CI run, else random)\")\n .option(\"--dir <path>\", \"publish this pre-built directory instead of running the build\")\n .option(\"--promote\", \"publish straight to the live channel\")\n .option(\"--name <name>\", \"display name override for the app\")\n .option(\"--repo <url>\", \"git remote to record (default: the checkout's origin)\")\n .option(\"--commit <sha>\", \"commit to record (default: HEAD, or GITHUB_SHA)\")\n .option(\"--branch <name>\", \"branch to record (default: the checkout's, or GITHUB_REF_NAME)\")\n .option(\"--build-only\", \"build and bundle functions, then stop — no credential needed\")\n .option(\n \"--prebuilt\",\n \"with --dir: its functions are already bundled; check them, don't rebuild\"\n )\n .option(\"--json\", \"print the server's result as JSON\")\n .addHelpText(\n \"after\",\n \"\\n--org takes a slug or a UUID (default: OXY_ORG, then oxy-app.json orgSlug, then\\n\" +\n \"the apps/<org>/<app>/ directory). --project pins the workspace; otherwise it is\\n\" +\n \"resolved from the target. .env.local and .env are loaded without overriding.\\n\" +\n \"\\nAuth: the --token-env variable, then `oxyc login`'s cache — or, in a GitHub\\n\" +\n \"Actions job with `id-token: write` and neither, trusted publishing via OIDC.\\n\"\n )\n ).action(async (opts: Record<string, unknown>) => {\n await runPublish(createContext(globals(opts)), {\n app: opts.app as string | undefined,\n buildId: opts.buildId as string | undefined,\n dir: opts.dir as string | undefined,\n promote: opts.promote as boolean | undefined,\n name: opts.name as string | undefined,\n repo: opts.repo as string | undefined,\n commit: opts.commit as string | undefined,\n branch: opts.branch as string | undefined,\n buildOnly: opts.buildOnly as boolean | undefined,\n prebuilt: opts.prebuilt as boolean | undefined,\n json: opts.json as boolean | undefined\n });\n });\n\n withGlobals(\n program\n .command(\"init-ci\")\n .description(\n \"write a GitHub Actions workflow that publishes this app with trusted publishing\"\n )\n .option(\"--app <org/app>\", \"the app to publish (default: this directory's oxy-app.json)\")\n .option(\"--environment <name>\", \"GitHub environment the publish job runs in\", \"oxy-publish\")\n .option(\"--force\", \"overwrite an existing workflow\")\n ).action((opts: Record<string, unknown>) => {\n runInitCi(createContext(globals(opts)), {\n app: opts.app as string | undefined,\n environment: opts.environment as string | undefined,\n force: opts.force 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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"}
1
+ {"version":3,"file":"main.mjs","names":["readCache","writeCache","cacheFile","error","readCache","isObject","isObject","loadManifest","UUID","describe","LOOKUP_TIMEOUT_MS","json","resolveApp","isObject","MANIFEST","isObject","walk","unreachable","parseYaml"],"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/publish/server.ts","../src/commands/checks.ts","../src/commands/customers.ts","../src/api/catalog.ts","../src/commands/discover.ts","../src/commands/guide.ts","../src/generated/version.ts","../src/publish/manifest.ts","../src/commands/init-ci.ts","../src/customer/workspace.ts","../src/commands/launch.ts","../src/commands/oltp.ts","../src/commands/proxy.ts","../src/publish/dotenv.ts","../src/publish/capabilities.ts","../src/publish/placement-scan.ts","../src/publish/function-lint.ts","../src/publish/function-engines.ts","../src/publish/functions.ts","../src/publish/provenance.ts","../src/publish/tarball.ts","../src/commands/publish.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/publish/placement.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 /** `oxyc checks run`: a check ran and failed or timed out. */\n CHECK_FAILED: 9\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 FIXED A BUG the Rust `oxy api` shipped with, which is worth stating\n * because the list looks like gratuitous divergence otherwise. Its\n * `normalize_path` tested only for an `api` first segment, so the API-key\n * surface — documented in that command's own `--help` as\n * `oxy api /external/api/<workspace_id>/sql/query` — normalised to\n * `/api/external/api/<workspace_id>/sql/query` and 404d. The documented example\n * could never have worked. That command is gone; the list is still required,\n * because the surface it mishandled is not.\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 * Which rule decided `hasMore`, or `undefined` when nothing in the response\n * spoke to it.\n *\n * `hasMore: false` conflates two different answers — \"the server said this is\n * the last page\" and \"the server said nothing, so we stopped\" — and only the\n * second one is worth telling the caller about. Several Oxy list endpoints\n * take `page`/`page_size` (or `limit`/`offset`) and answer with a BARE ARRAY:\n * they really are paginated, the response just carries no way to know it, so\n * `--paginate` returns page one and looks complete. Naming the rule is what\n * lets `paginate()` say so instead.\n */\n signal?: \"pagination.has_next\" | \"has_more\" | \"pagination.total_pages\";\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 let signal: PageShape[\"signal\"];\n if (pagination && typeof pagination.has_next === \"boolean\") {\n hasMore = pagination.has_next;\n signal = \"pagination.has_next\";\n } else if (typeof payload.has_more === \"boolean\") {\n hasMore = payload.has_more;\n signal = \"has_more\";\n } else if (pagination && typeof pagination.total_pages === \"number\") {\n hasMore = page < pagination.total_pages;\n signal = \"pagination.total_pages\";\n }\n\n return { rowsKey, rows, hasMore, signal };\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/**\n * Whether the response spoke about pagination AT ALL.\n *\n * Deliberately not `linkNext(...) !== undefined`. The last page of a paginated\n * endpoint has no `rel=\"next\"` — that is what makes it the last page — so\n * testing for one conflates \"I am at the end of a collection that pages\" with\n * \"this endpoint has never heard of pagination\", and the warning at the bottom\n * of `paginate()` would fire on every single-page result from an endpoint that\n * is doing everything right. Oxy's handlers emit `rel=\"first\"` on every page\n * precisely so this question has an answer (`oxy_app_core::pagination`).\n */\nexport function hasLinkHeader(headers: Record<string, string>): boolean {\n return Boolean(headers.link ?? headers.Link);\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 /** Whether ANY page carried a signal this module knows how to read. */\n let sawSignal = false;\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 // ANY `Link` counts, not only one naming a next page — a last page is still\n // a page of something that paginates, and saying otherwise is what made this\n // warning fire on the endpoints that answer correctly.\n sawSignal ||= hasLinkHeader(response.headers) || shape.signal !== undefined;\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 // NOTHING RECOGNISED, SO ONE PAGE — said out loud rather than implied by a\n // short result. The heuristic stopping is the safe behaviour and stays; what\n // was missing is that the caller could not tell it apart from an endpoint\n // that genuinely had one page. Much of the admin surface takes `page` /\n // `page_size` and answers with a bare array, so `--paginate` there returns\n // the first 50 rows and reads as the whole table.\n //\n // Only on the opt-in flag, and only on stderr: someone who typed --paginate\n // asked to walk the pages, so \"I could not\" is an answer to their question,\n // not noise. It never fires for an endpoint that reported `has_next: false`.\n if (!sawSignal) {\n log.warn(\n `${opts.path} returned no pagination signal — this is ONE page, not necessarily every row.`\n );\n log.hint(\n \"if the endpoint takes page/page_size or limit/offset, walk it yourself: `oxyc api '<path>?page=1'`\"\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 the Rust `env_url.rs` and the target half of `app_manifest.rs`,\n * both since deleted. Kept faithful rather than improved: the credentials file\n * is keyed by HOST and still holds every login the Rust `oxy login` cached, so\n * a change to which host an `--env` names would look those tokens up under a\n * different key and report the 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\nimport { CliError, ExitCode } from \"../util/errors.js\";\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/**\n * Read `<dir>/oxy-app.json`. `undefined` only when there is no such file.\n *\n * A file that exists but cannot be read, is not JSON, or carries a field this\n * CLI reads in the wrong shape is an error naming the path — never `undefined`.\n * Treating it as absent made every caller carry on with the wrong target,\n * identity and function set: `publish` shipped with no functions bundled.\n * Unknown fields still pass, so an SDK field added tomorrow breaks nothing.\n */\nexport function readAppManifest(dir: string): Record<string, unknown> | undefined {\n const path = join(dir, \"oxy-app.json\");\n let raw: string;\n try {\n raw = readFileSync(path, \"utf8\");\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n throw invalidManifest(path, `cannot read it: ${(err as Error).message}`);\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (err) {\n throw invalidManifest(path, (err as Error).message);\n }\n const problem = shapeProblem(parsed);\n if (problem) throw invalidManifest(path, problem);\n return parsed as Record<string, unknown>;\n}\n\nfunction invalidManifest(path: string, detail: string): CliError {\n return new CliError(`${path} is not a valid oxy-app.json: ${detail}`, {\n code: ExitCode.USAGE,\n remedy: \"fix the file and re-run\"\n });\n}\n\nconst isObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\n/** Checks only the fields this CLI reads, as the types it reads them as. `null` is absent. */\nfunction shapeProblem(manifest: unknown): string | undefined {\n if (!isObject(manifest)) return \"the top level must be an object\";\n const notString = (obj: Record<string, unknown>, key: string) =>\n obj[key] != null && typeof obj[key] !== \"string\";\n const notObject = (obj: Record<string, unknown>, key: string) =>\n obj[key] != null && !isObject(obj[key]);\n\n for (const key of [\"slug\", \"orgSlug\", \"name\"]) {\n if (notString(manifest, key)) return `\\`${key}\\` must be a string`;\n }\n for (const key of [\"environments\", \"functions\", \"build\"]) {\n if (notObject(manifest, key)) return `\\`${key}\\` must be an object`;\n }\n const build = (manifest.build ?? {}) as Record<string, unknown>;\n for (const key of [\"install\", \"command\", \"outDir\"]) {\n if (notString(build, key)) return `\\`build.${key}\\` must be a string`;\n }\n for (const [section, field] of [\n [\"environments\", \"target\"],\n [\"functions\", \"entry\"]\n ] as const) {\n const entries = (manifest[section] ?? {}) as Record<string, unknown>;\n for (const [name, entry] of Object.entries(entries)) {\n if (!isObject(entry)) return `\\`${section}.${name}\\` must be an object`;\n if (notString(entry, field)) return `\\`${section}.${name}.${field}\\` must be a string`;\n }\n }\n return undefined;\n}\n\n/** `<dir>/oxy-app.json` for identity and target, strictly — see `readAppManifest`. */\nexport function loadManifest(dir: string): OxyAppManifest | undefined {\n return readAppManifest(dir) as OxyAppManifest | undefined;\n}\n\n/**\n * The manifest for a command that reads it only to resolve the target.\n *\n * A non-blank `--target` wins outright in `resolveEnv`, so the file cannot\n * change the outcome: it is not read, and a broken `oxy-app.json` does not fail\n * a command that was told where to go. Otherwise `loadManifest`, strict as\n * ever. `publish` and `init-ci` read it for identity and functions whatever\n * `--target` says, so they do not come through here.\n */\nexport function loadForTargetResolution(\n dir: string,\n targetFlag: string | undefined\n): OxyAppManifest | undefined {\n return targetFlag?.trim() ? undefined : loadManifest(dir);\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`. It replaced the Rust `oxy assume`, which\n * was deleted once this covered it. The sessions are Postgres rows hanging off\n * the account, so the browser and this terminal act as one — there is no\n * per-client state to keep in sync.\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. Nothing here 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\nexport async 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.\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 this lists three\n // 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.\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. So it refuses: a present-but-blank\n // `--org` 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 deleted Rust `oxy login` wrote.\n *\n * It began as interop with a program written in another language, and the\n * shape is still that contract: every login cached before `oxyc` took over\n * lives in this file, so the path, the host key and the field names were\n * transcribed from the Rust `login.rs` rather than chosen here. Change any of\n * them and every existing login silently disappears.\n *\n * THE PATH IS NOT `~/.config` ON macOS, whatever the Rust doc comment said.\n * `login.rs` built 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.\n * `configDir()` reproduces the crate's platform rules, and\n * `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 the Rust `oxy login` did, 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 — was transcribed from\n * the Rust `login.rs` (since deleted). 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/** The tab the user is left looking at. */\nconst SUCCESS_HTML =\n \"<!doctype html><meta charset=utf-8><title>oxyc 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. The Rust `oxy login --env dev,staging`\n * did the same, and its logins are still in the same credential file.\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 * The three HTTP calls a publish makes, plus the trusted-publishing exchange.\n *\n * Direct `fetch` rather than `api/request.ts`: the upload is multipart and the\n * two lookups are public, and neither fits a JSON-string request with a\n * credential chosen by path. What they share with it is the exit-code mapping.\n */\n\nimport { CliError, ExitCode, exitCodeForStatus } from \"../util/errors.js\";\n\nconst LOOKUP_TIMEOUT_MS = 30_000;\n/** The bundle upload, which can be tens of megabytes. */\nconst UPLOAD_TIMEOUT_MS = 120_000;\n\nasync function send(url: string, init: RequestInit, timeoutMs: number): Promise<Response> {\n try {\n return await fetch(url, { ...init, signal: AbortSignal.timeout(timeoutMs) });\n } catch (cause) {\n throw new CliError(`${init.method ?? \"GET\"} ${url} failed: ${(cause as Error).message}`, {\n code: ExitCode.UNAVAILABLE\n });\n }\n}\n\nasync function json<T>(response: Response, what: string): Promise<T> {\n const text = await response.text();\n try {\n return JSON.parse(text) as T;\n } catch {\n throw new CliError(`could not parse the ${what} response`, {\n code: ExitCode.UNAVAILABLE,\n detail: text.slice(0, 2000)\n });\n }\n}\n\nfunction base(target: string): string {\n return target.replace(/\\/+$/, \"\");\n}\n\n/** The project an app publishes into, from its `(org, app)` on the target. Public. */\nexport async function fetchProject(target: string, org: string, app: string): Promise<string> {\n const url = `${base(target)}/api/apps/${encodeURIComponent(org)}/${encodeURIComponent(app)}/build-config`;\n const response = await send(url, {}, LOOKUP_TIMEOUT_MS);\n if (response.status === 404) {\n throw new CliError(`app ${org}/${app} is not registered on ${target}`, {\n code: ExitCode.NOT_FOUND,\n hint: \"register it in the oxy admin UI, or pass --project <uuid> for its first publish\"\n });\n }\n if (!response.ok) {\n throw new CliError(`build-config lookup failed (${response.status}) at ${url}`, {\n code: exitCodeForStatus(response.status)\n });\n }\n return (await json<{ project_id: string }>(response, \"build-config\")).project_id;\n}\n\n/** The org a pinned workspace belongs to — a workspace has exactly one. Public. */\nexport async function fetchOrgForProject(target: string, projectId: string): Promise<string> {\n const url = `${base(target)}/api/org-for-project/${encodeURIComponent(projectId)}`;\n const response = await send(url, {}, LOOKUP_TIMEOUT_MS);\n if (response.status === 404) {\n throw new CliError(`workspace ${projectId} not found on ${target}`, {\n code: ExitCode.NOT_FOUND,\n hint: \"check --project / OXY_PROJECT\"\n });\n }\n if (!response.ok) {\n throw new CliError(`org-for-project lookup failed (${response.status}) at ${url}`, {\n code: exitCodeForStatus(response.status)\n });\n }\n return (await json<{ org_slug: string }>(response, \"org-for-project\")).org_slug;\n}\n\n/** The server's `PublishResult`. Extra fields are tolerated. */\nexport interface PublishResult {\n app_id: string;\n build_id: string;\n url: string;\n channel: string;\n org_slug?: string;\n is_new_app?: boolean;\n warnings?: string[];\n}\n\nexport interface UploadRequest {\n target: string;\n token: string;\n /** Multipart text fields, in order. Undefined values are left out. */\n fields: Array<[string, string | undefined]>;\n tarball: Buffer;\n}\n\n/**\n * POST the bundle. Resolves the parsed result, or throws with the status\n * mapped onto the exit-code contract and the server's body as detail.\n */\nexport async function uploadBundle(req: UploadRequest): Promise<PublishResult> {\n const form = new FormData();\n for (const [name, value] of req.fields) {\n if (value !== undefined) form.append(name, value);\n }\n // A copy into a plain ArrayBuffer: `Blob` does not accept a Buffer that may\n // sit on a SharedArrayBuffer, which is what the type of `gzipSync`'s result allows.\n const bytes = new Uint8Array(req.tarball);\n form.append(\"bundle\", new Blob([bytes], { type: \"application/gzip\" }), \"bundle.tar.gz\");\n\n const url = `${base(req.target)}/api/customer-apps/publish`;\n const response = await send(\n url,\n { method: \"POST\", headers: { authorization: `Bearer ${req.token}` }, body: form },\n UPLOAD_TIMEOUT_MS\n );\n if (!response.ok) {\n const body = await response.text();\n throw new CliError(`publish failed (${response.status})`, {\n code: exitCodeForStatus(response.status),\n detail: body.slice(0, 4000)\n });\n }\n return json<PublishResult>(response, \"publish\");\n}\n\n/** The two variables GitHub sets in a job granted `id-token: write`. */\nexport function githubOidcAvailable(env: NodeJS.ProcessEnv = process.env): boolean {\n return Boolean(env.ACTIONS_ID_TOKEN_REQUEST_URL && env.ACTIONS_ID_TOKEN_REQUEST_TOKEN);\n}\n\n/** The audience the server pins. A token minted for any other is refused. */\nexport const OIDC_AUDIENCE = \"oxy-publish\";\n\n/**\n * Trusted publishing: a GitHub OIDC token, exchanged for a publish credential\n * scoped to exactly `org/app` and valid for fifteen minutes.\n *\n * Called immediately before the upload, not at startup: the OIDC token is\n * single-use and the credential short-lived, and a build can take longer than\n * either should be held. The server matches the token's claims against a\n * publisher registered for the app — repository owner id, repo, workflow path,\n * environment — so a 403 here almost always means a registration mismatch.\n */\nexport interface ExchangedCredential {\n /** The short-lived, app-scoped publish token. */\n token: string;\n /**\n * The app it is scoped to, so a caller never looks one up — absent on a\n * deployment predating trusted checks. Optional on purpose: publishing does\n * not need it, and a `publish` that refused to run because a field it never\n * reads was missing would be a new failure on the load-bearing path. The\n * caller that needs it says so.\n */\n appId?: string;\n}\n\nexport async function exchangeGithubOidc(\n target: string,\n orgSlug: string,\n app: string,\n env: NodeJS.ProcessEnv = process.env\n): Promise<ExchangedCredential> {\n const requestUrl = new URL(env.ACTIONS_ID_TOKEN_REQUEST_URL ?? \"\");\n requestUrl.searchParams.set(\"audience\", OIDC_AUDIENCE);\n const minted = await send(\n requestUrl.toString(),\n { headers: { authorization: `bearer ${env.ACTIONS_ID_TOKEN_REQUEST_TOKEN}` } },\n LOOKUP_TIMEOUT_MS\n );\n if (!minted.ok) {\n throw new CliError(`GitHub refused to mint an OIDC token (${minted.status})`, {\n code: ExitCode.AUTH,\n hint: \"the publishing job needs `permissions: id-token: write`\"\n });\n }\n const oidc = (await json<{ value?: string }>(minted, \"GitHub OIDC\")).value;\n if (!oidc) throw new CliError(\"GitHub returned no OIDC token\", { code: ExitCode.AUTH });\n\n const url = `${base(target)}/api/customer-apps/publish/oidc-exchange`;\n const exchanged = await send(\n url,\n {\n method: \"POST\",\n // `Bearer` exactly: the server matches the prefix case-sensitively.\n headers: { authorization: `Bearer ${oidc}`, \"content-type\": \"application/json\" },\n body: JSON.stringify({ app: `${orgSlug}/${app}` })\n },\n LOOKUP_TIMEOUT_MS\n );\n if (!exchanged.ok) {\n const body = await exchanged.text();\n throw new CliError(`trusted-publishing exchange failed (${exchanged.status})`, {\n code: exitCodeForStatus(exchanged.status),\n detail: body.slice(0, 2000),\n hint: `is this workflow registered as a publisher for ${orgSlug}/${app}, with the same repository, workflow file and environment?`\n });\n }\n const body = await json<{ token?: string; app_id?: string }>(exchanged, \"exchange\");\n if (!body.token) throw new CliError(\"the exchange returned no token\", { code: ExitCode.AUTH });\n return { token: body.token, appId: body.app_id };\n}\n","/**\n * `oxyc checks run <app>` — run every function an app marked `\"check\": true`\n * and wait for a verdict.\n *\n * This is what a release workflow calls once an environment serves a build: it\n * POSTs one run per check, polls each to a terminal status, and exits\n * `CHECK_FAILED` (9) the moment any of them did not pass — so a release gate\n * can branch on the exit code alone, the same contract every other `oxyc`\n * command keeps.\n *\n * Talks only to four routes (`GET /api/admin/apps`, `GET .../functions`,\n * `POST .../functions/{name}/runs`, `GET .../function-runs/{run_id}`); nothing\n * here decides whether a function IS a check — that is `FunctionSummary.check`,\n * which the server projects from the manifest flag.\n *\n * Two surfaces, same handlers. A human runs this with their own credential and\n * hits `/api/admin/apps/…`. CI has no credential to store: in a job with\n * `id-token: write` it exchanges a GitHub OIDC token for the same short-lived,\n * app-scoped publish token `oxyc publish` uses, and then hits\n * `/api/customer-apps/…` — the same three handlers, mounted where a publish\n * token may reach them. The app-listing route is NOT one of them (a publish\n * token may not enumerate apps), which is why the exchange returns the app id\n * rather than leaving the CLI to look one up.\n */\n\nimport { errorForResponse, parseJson, request } from \"../api/request.js\";\nimport type { Context } from \"../context/resolve.js\";\nimport { exchangeGithubOidc, githubOidcAvailable } from \"../publish/server.js\";\nimport { err } from \"../ui/tty.js\";\nimport { CliError, ExitCode, usageError } from \"../util/errors.js\";\n\n/** The `--json` report: one object on stdout. */\nexport interface ChecksReport {\n app: string;\n appId: string;\n checks: CheckResult[];\n}\n\nexport interface CheckResult {\n name: string;\n runId: string;\n status: string;\n passed: boolean;\n error?: string;\n durationMs: number;\n}\n\ninterface AdminAppsPage {\n items?: { id: string; slug: string; org_slug: string }[];\n next_offset?: number | null;\n}\n\ninterface FunctionSummary {\n name: string;\n check?: boolean;\n}\n\ntype RunStatus = \"queued\" | \"running\" | \"done\" | \"failed\" | \"cancelled\" | \"timed_out\";\n\ninterface RunDetail {\n run_id: string;\n status: RunStatus;\n answer?: string | null;\n error?: string | null;\n}\n\nconst TERMINAL: ReadonlySet<RunStatus> = new Set([\"done\", \"failed\", \"cancelled\", \"timed_out\"]);\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n/** Hard stop on the admin-apps walk, mirroring `api/paginate.ts`'s `MAX_PAGES`. */\nconst MAX_APP_PAGES = 100;\n\nexport async function runChecks(\n ctx: Context,\n app: string,\n opts: { json: boolean; timeoutSeconds: number; pollMs?: number }\n): Promise<void> {\n // `main.ts` passes `Number(--timeout)`. A NaN deadline never passes, so the\n // poll would never end; zero or less times out every check before it runs.\n if (!Number.isFinite(opts.timeoutSeconds) || opts.timeoutSeconds <= 0) {\n throw usageError(\n \"--timeout must be a positive number of seconds\",\n \"e.g. --timeout 60 (the default is 300)\"\n );\n }\n const target = ctx.target();\n const machine = await resolveCredentials(ctx, target, app);\n const creds: Creds = {\n target,\n bearer: machine.bearer,\n headers: machine.apiKey ? { \"X-API-Key\": machine.apiKey } : undefined,\n surface: machine.surface\n };\n\n // `resolveApp` pages `/api/admin/apps`, which a publish token may not reach:\n // sending it there would 403 on a route the caller cannot be given. The OIDC\n // branch never gets here (the exchange hands back the id); a token supplied\n // through `OXY_TOKEN` does, and it needs the UUID.\n if (!machine.appId && creds.surface === MACHINE_SURFACE && !UUID_RE.test(app)) {\n throw usageError(\n \"a publish token cannot resolve <org>/<app> — pass the app UUID\",\n \"resolving a slug means listing every app, which a publish token may not do; the id is on the app's admin page, and `oxyc publish --json` reports it\"\n );\n }\n const { appId, label } = machine.appId\n ? { appId: machine.appId, label: app }\n : await resolveApp(creds, app);\n const checks = await listChecks(creds, appId);\n if (checks.length === 0) {\n throw new CliError(`${label} declares no checks (no function has \"check\": true)`, {\n code: ExitCode.FAILURE,\n hint: `mark a function \"check\": true in oxy-app.json to give it one`\n });\n }\n\n const results: CheckResult[] = [];\n for (const fn of checks) {\n const result = await runOneCheck(creds, appId, fn.name, opts);\n results.push(result);\n if (!opts.json) printResultLine(result);\n }\n\n if (opts.json) {\n const report: ChecksReport = { app: label, appId, checks: results };\n process.stdout.write(`${JSON.stringify(report)}\\n`);\n }\n\n const failed = results.filter((r) => !r.passed);\n if (failed.length > 0) {\n throw new CliError(\n `${failed.length} of ${results.length} check(s) failed: ${failed.map((r) => r.name).join(\", \")}`,\n { code: ExitCode.CHECK_FAILED }\n );\n }\n}\n\n/** The prefix `oxyc publish` mints and the exchange returns. */\nconst PUBLISH_TOKEN_PREFIX = \"oxypublish_\";\n/** Where the three function routes live for each kind of credential. */\nconst ADMIN_SURFACE = \"/api/admin/apps\";\nconst MACHINE_SURFACE = \"/api/customer-apps\";\n\ninterface ResolvedCredentials {\n bearer?: string;\n apiKey?: string;\n surface: string;\n /** Set only when the exchange told us which app the token is scoped to. */\n appId?: string;\n}\n\n/**\n * A stored credential if there is one, a minted one if there is not.\n *\n * Bearer wins when one resolves; otherwise the API key. Neither resolving is\n * not yet an error in CI: a job holding `id-token: write` can mint, so the\n * exchange is tried before giving up. Only when that is unavailable too does\n * this throw the SAME `authError` every other command throws — reusing\n * `ctx.bearer()` for that throw keeps the message and the `oxyc login …` hint\n * defined in exactly one place (`context/resolve.ts`) rather than duplicated\n * here.\n *\n * A publish token — minted here or handed in through `OXY_TOKEN` — reads the\n * machine surface, because the admin one refuses it.\n */\nasync function resolveCredentials(\n ctx: Context,\n target: string,\n app: string\n): Promise<ResolvedCredentials> {\n const bearer = ctx.maybeBearer();\n if (bearer) {\n return {\n bearer,\n surface: bearer.startsWith(PUBLISH_TOKEN_PREFIX) ? MACHINE_SURFACE : ADMIN_SURFACE\n };\n }\n const apiKey = ctx.apiKey();\n if (apiKey) return { apiKey, surface: ADMIN_SURFACE };\n\n if (githubOidcAvailable()) {\n const [orgSlug, ...rest] = app.split(\"/\");\n const appSlug = rest.join(\"/\");\n if (!orgSlug || !appSlug) {\n throw usageError(\n 'trusted publishing needs <app> as \"<org-slug>/<app-slug>\"',\n \"the exchange is keyed by slug; a UUID names an app it cannot verify a publisher for\"\n );\n }\n const minted = await exchangeGithubOidc(target, orgSlug, appSlug);\n // Only this caller needs the id — `oxyc publish` takes the token and goes.\n // So the version check is here, not in the exchange: a deployment without\n // the field can still be published to.\n if (!minted.appId) {\n throw new CliError(\"the OIDC exchange returned no app_id\", {\n code: ExitCode.UNAVAILABLE,\n hint: \"this deployment predates trusted checks — upgrade it, or set OXY_TOKEN and pass the app UUID\"\n });\n }\n return { bearer: minted.token, surface: MACHINE_SURFACE, appId: minted.appId };\n }\n\n // Throws — nothing resolved and nothing can be minted.\n ctx.bearer();\n return { surface: ADMIN_SURFACE };\n}\n\ninterface Creds {\n target: string;\n bearer?: string;\n headers?: Record<string, string>;\n /** `/api/admin/apps` for a human, `/api/customer-apps` for a publish token. */\n surface: string;\n}\n\nfunction ensureOk(response: Awaited<ReturnType<typeof request>>): void {\n if (response.status < 200 || response.status >= 300) throw errorForResponse(response);\n}\n\n/**\n * Resolve `<org-slug>/<app-slug>` to an app id by paging\n * `GET /api/admin/apps` — skipped entirely when `app` is already a UUID.\n */\nasync function resolveApp(creds: Creds, app: string): Promise<{ appId: string; label: string }> {\n if (UUID_RE.test(app)) return { appId: app, label: app };\n\n const [orgSlug, ...rest] = app.split(\"/\");\n const appSlug = rest.join(\"/\");\n\n let offset = 0;\n for (let page = 0; page < MAX_APP_PAGES; page++) {\n const response = await request({\n target: creds.target,\n path: `/api/admin/apps?limit=100&offset=${offset}`,\n method: \"GET\",\n bearer: creds.bearer,\n headers: creds.headers\n });\n ensureOk(response);\n const payload = parseJson(response.body) as AdminAppsPage | undefined;\n const match = (payload?.items ?? []).find(\n (item) => item.org_slug === orgSlug && item.slug === appSlug\n );\n if (match) return { appId: match.id, label: `${orgSlug}/${appSlug}` };\n if (payload?.next_offset == null) break;\n offset = payload.next_offset;\n }\n\n throw new CliError(`no app \"${app}\"`, {\n code: ExitCode.NOT_FOUND,\n hint: '<app> is \"<org-slug>/<app-slug>\" or an app UUID'\n });\n}\n\n/** `GET .../functions`, filtered to `check: true` and sorted by name. */\nasync function listChecks(creds: Creds, appId: string): Promise<FunctionSummary[]> {\n const response = await request({\n target: creds.target,\n path: `${creds.surface}/${appId}/functions`,\n method: \"GET\",\n bearer: creds.bearer,\n headers: creds.headers\n });\n ensureOk(response);\n const payload = (parseJson(response.body) as FunctionSummary[] | undefined) ?? [];\n return payload.filter((fn) => fn.check === true).sort((a, b) => a.name.localeCompare(b.name));\n}\n\n/** POST the run, poll it to a terminal status or `timeoutSeconds`, and score it. */\nasync function runOneCheck(\n creds: Creds,\n appId: string,\n name: string,\n opts: { timeoutSeconds: number; pollMs?: number }\n): Promise<CheckResult> {\n const start = Date.now();\n const runId = await startRun(creds, appId, name);\n const detail = await pollUntilTerminal(creds, appId, runId, opts);\n const durationMs = Date.now() - start;\n\n const answerFailed = parsesToOkFalse(detail.answer);\n const passed = detail.status === \"done\" && !answerFailed;\n const error = passed ? undefined : failureMessage(detail, answerFailed, opts.timeoutSeconds);\n\n return { name, runId, status: detail.status, passed, error, durationMs };\n}\n\nasync function startRun(creds: Creds, appId: string, name: string): Promise<string> {\n const response = await request({\n target: creds.target,\n path: `${creds.surface}/${appId}/functions/${encodeURIComponent(name)}/runs`,\n method: \"POST\",\n body: \"{}\",\n bearer: creds.bearer,\n headers: creds.headers\n });\n ensureOk(response);\n const payload = parseJson(response.body) as { run_id?: string } | undefined;\n if (!payload?.run_id) {\n throw new CliError(`POST .../functions/${name}/runs did not return a run_id`, {\n code: ExitCode.UNAVAILABLE\n });\n }\n return payload.run_id;\n}\n\nasync function getRunDetail(creds: Creds, appId: string, runId: string): Promise<RunDetail> {\n const response = await request({\n target: creds.target,\n path: `${creds.surface}/${appId}/function-runs/${runId}`,\n method: \"GET\",\n bearer: creds.bearer,\n headers: creds.headers\n });\n ensureOk(response);\n return parseJson(response.body) as RunDetail;\n}\n\n/** Poll every `pollMs` (default 2000) until a terminal status, or the client-side timeout. */\nasync function pollUntilTerminal(\n creds: Creds,\n appId: string,\n runId: string,\n opts: { timeoutSeconds: number; pollMs?: number }\n): Promise<RunDetail> {\n const deadline = Date.now() + opts.timeoutSeconds * 1000;\n for (;;) {\n const detail = await getRunDetail(creds, appId, runId);\n if (TERMINAL.has(detail.status)) return detail;\n if (Date.now() >= deadline) return { ...detail, status: \"timed_out\" };\n await sleep(opts.pollMs ?? 2000);\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/** A check fails when its answer parses to an object whose `ok` is `false`. */\nfunction parsesToOkFalse(answer: string | null | undefined): boolean {\n if (!answer) return false;\n const parsed = parseJson(answer);\n return (\n typeof parsed === \"object\" &&\n parsed !== null &&\n !Array.isArray(parsed) &&\n (parsed as Record<string, unknown>).ok === false\n );\n}\n\nfunction failureMessage(detail: RunDetail, answerFailed: boolean, timeoutSeconds: number): string {\n if (detail.error) return detail.error;\n if (detail.status === \"timed_out\") return `timed out after ${timeoutSeconds}s`;\n if (answerFailed) return `answer reported \"ok\": false`;\n if (detail.status === \"cancelled\") return \"run cancelled\";\n return `status ${detail.status}`;\n}\n\nfunction printResultLine(result: CheckResult): void {\n if (process.env.OXYC_QUIET) return;\n const seconds = `${(result.durationMs / 1000).toFixed(1)}s`;\n if (result.passed) {\n process.stderr.write(`${err.green(\"✓\")} ${result.name} ${seconds}\\n`);\n return;\n }\n const reason = (result.error ?? result.status).slice(0, 200);\n process.stderr.write(`${err.red(\"✗\")} ${result.name} failed: ${reason}\\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 // A JSON ARRAY — one document, not one object per line. Both readings are\n // defensible and `--help` used to claim the other one; an array is what\n // `oxyc list --json` and `oxyc openapi` already emit, and what a `| jq`\n // written against this expects.\n //\n // Indented for a human, compact for a pipe, exactly as `runOpenApi` below\n // decides it. Unfiltered this is ~670 objects of eight fields, where the\n // indentation alone is tens of KB of context an agent pays for and no\n // human is reading.\n process.stdout.write(`${JSON.stringify(matches, null, stdoutIsTty() ? 2 : 0)}\\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 · 9 a check failed (\\`oxyc checks run\\`)\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 publish --env dev # build + publish a custom app (draft; --promote for live)\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","// @generated by scripts/emit-version.mjs — do not edit.\n//\n// The single source of truth is `package.json`. `oxyc --version` reads this,\n// so a release is one bump in the manifest and nothing else.\nexport const VERSION = \"0.5.0\";\n","/**\n * The half of `oxy-app.json` that publishing reads, and the two name rules the\n * server enforces on it.\n *\n * `context/target.ts` owns identity and `environments`; this adds `build` and\n * `functions`. Both read the same file and ignore what they do not know, so an\n * SDK field added tomorrow cannot break a publish today.\n */\n\nimport { readAppManifest } from \"../context/target.js\";\n\nexport interface FunctionSpec {\n entry?: string;\n /** Databases `ctx.warehouse.*` writes may target. Absent → no writes. */\n destinations?: string[];\n /** Gate for `ctx.airhouse`, which writes the app's own `app_<writer>` schema. */\n airhouse?: { enabled?: boolean };\n /**\n * `<database>: <reason>` — the explicit exception that lets this function\n * write a CUSTOMER warehouse named in `destinations`. Read-only otherwise.\n */\n customerWarehouseWrites?: Record<string, string>;\n secrets?: { write?: boolean };\n /**\n * A function a release gate may run to verify what it just shipped.\n * `oxyc checks run` runs exactly these, and it is the only function a\n * machine credential is allowed to trigger.\n */\n check?: boolean;\n}\n\nexport interface PublishManifest {\n slug?: string;\n orgSlug?: string;\n build?: { install?: string; command?: string; outDir?: string };\n functions?: Record<string, FunctionSpec>;\n /** OLTP (Postgres) migrations, run on promote. A directory inside the bundle. */\n migrations?: { dir?: string };\n /** Airhouse (DuckLake) migrations for `app_<writer>`, run once each on promote. */\n airhouseMigrations?: { dir?: string };\n}\n\n/**\n * Longest writer name: Postgres caps identifiers at 63 bytes, and the longest\n * derived form is `app_<name>_rw` — `crates/oltp/src/schema.rs` `MAX_NAME_LEN`.\n */\nexport const WRITER_NAME_MAX = 63 - \"app_\".length - \"_rw\".length;\n\n/** `validate_name`, as a sentence to put in an error. */\nexport const WRITER_NAME_SHAPE = `1-${WRITER_NAME_MAX} characters: a lowercase letter, then lowercase letters, digits or underscores`;\n\n/** `app_writer_name`: how a slug becomes a writer, as a sentence. */\nexport const WRITER_NAME_RULE = `\\`-\\` becomes \\`_\\`, and the result must be ${WRITER_NAME_SHAPE}`;\n\n/** `crates/oltp/src/schema.rs` `validate_name`. */\nexport function isValidWriterName(name: string): boolean {\n return new RegExp(`^[a-z][a-z0-9_]{0,${WRITER_NAME_MAX - 1}}$`).test(name);\n}\n\n/**\n * The writer an app owns, DERIVED from its slug — `app_writer_name` in\n * `crates/oltp/src/schema.rs`. `undefined` when the slug cannot back a schema.\n *\n * A slug that already contains `_` is refused rather than normalised: `my_app`\n * would alias the hyphenated sibling `my-app` onto one schema and role.\n */\nexport function appWriterName(slug: string): string | undefined {\n if (slug.includes(\"_\")) return undefined;\n const name = slug.replaceAll(\"-\", \"_\");\n return isValidWriterName(name) ? name : undefined;\n}\n\n/**\n * `<dir>/oxy-app.json`, or `undefined` when there is none. A broken one throws:\n * publishing past it used to ship a bundle with no functions and an identity\n * taken from flags or the directory.\n */\nexport function loadPublishManifest(dir: string): PublishManifest | undefined {\n return readAppManifest(dir) as PublishManifest | undefined;\n}\n\n/** A blank manifest value is no value: `\"install\": \"\"` falls back to the default. */\nfunction orDefault(value: string | undefined, fallback: string): string {\n return value?.trim() ? value : fallback;\n}\n\nexport interface BuildSteps {\n install: string;\n command: string;\n outDir: string;\n}\n\n/**\n * Install / build / output directory. `out` matches the directory the Vite\n * plugin forces, so an identity-only manifest publishes without a `build` block.\n */\nexport function buildSteps(manifest: PublishManifest | undefined): BuildSteps {\n return {\n install: orDefault(manifest?.build?.install, \"pnpm install\"),\n command: orDefault(manifest?.build?.command, \"pnpm build\"),\n outDir: orDefault(manifest?.build?.outDir, \"out\")\n };\n}\n\n/** Declared function names, or an empty list. */\nexport function declaredFunctions(manifest: PublishManifest | undefined): string[] {\n const functions = manifest?.functions;\n return functions && typeof functions === \"object\" ? Object.keys(functions) : [];\n}\n\n/** Source entry relative to the app directory. Default `functions/<name>.ts`. */\nexport function functionEntry(manifest: PublishManifest | undefined, name: string): string {\n return orDefault(manifest?.functions?.[name]?.entry, `functions/${name}.ts`);\n}\n\n/**\n * `^[a-z][a-z0-9-]{0,63}$` — the server's `is_valid_function_name`.\n *\n * A manifest key becomes `functions/<name>.js`, so `../../x` has to be refused\n * before esbuild is told to write there.\n */\nexport function isValidFunctionName(name: string): boolean {\n return /^[a-z][a-z0-9-]{0,63}$/.test(name);\n}\n\n/**\n * The server's `is_valid_slug`: 1–63 lowercase letters, digits and single\n * hyphens, no leading or trailing hyphen.\n *\n * Checked before anything is built, so an author whose bundle never went\n * through the Vite plugin learns about it before uploading rather than after.\n */\nexport function isValidSlug(slug: string): boolean {\n return (\n slug.length > 0 &&\n slug.length <= 63 &&\n /^[a-z0-9-]+$/.test(slug) &&\n !slug.startsWith(\"-\") &&\n !slug.endsWith(\"-\") &&\n !slug.includes(\"--\")\n );\n}\n","/**\n * `oxyc init-ci` — write a GitHub Actions workflow that publishes a custom app\n * with trusted publishing: no stored secret.\n *\n * `id-token: write` is a job-level permission every step in the job can use,\n * so the workflow is TWO jobs. `build` runs the package scripts and holds no\n * credential; `publish` holds the id-token, installs nothing, and does only\n * `oxyc publish --prebuilt` on the artifact `build` produced. Do not add steps\n * to the publish job — that isolation is the security model.\n *\n * It replaced the Rust `oxy init-ci`, whose workflow called a\n * `oxy-hq/publish-action` that was never published, so no workflow it wrote\n * could run.\n */\n\nimport { spawnSync } from \"node:child_process\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join, relative, sep } from \"node:path\";\nimport type { Context } from \"../context/resolve.js\";\nimport { VERSION } from \"../generated/version.js\";\nimport { buildSteps, isValidSlug, loadPublishManifest } from \"../publish/manifest.js\";\nimport * as log from \"../ui/log.js\";\nimport { out } from \"../ui/tty.js\";\nimport { refusal, usageError } from \"../util/errors.js\";\nimport { parseRemoteSlug, repoRoot } from \"../util/git.js\";\n\nexport const WORKFLOW_PATH = \".github/workflows/oxy-publish.yml\";\n\nexport interface InitCiFlags {\n app?: string;\n environment?: string;\n force?: boolean;\n promote?: boolean;\n}\n\nexport interface WorkflowOptions {\n org: string;\n app: string;\n environment: string;\n /** `--env` the publish step targets. */\n env: string;\n /** App directory relative to the repo root, `.` when they are the same. */\n appDir: string;\n outDir: string;\n /** Omit `version:` when package.json pins pnpm, or pnpm/action-setup refuses. */\n pnpmFromPackageJson: boolean;\n /** Whether the manifest declares any `\"check\": true` function to verify with. */\n hasChecks: boolean;\n /** `--promote`: publish to the live channel, and verify it with the checks. */\n promote: boolean;\n nodeVersionFile: boolean;\n cliVersion: string;\n}\n\n/** `org/app` from `--app`, else the manifest in the working directory. */\nfunction resolveApp(cwd: string, flag: string | undefined): { org: string; app: string } {\n const manifest = loadPublishManifest(cwd);\n const [org, app] = flag ? flag.split(\"/\") : [manifest?.orgSlug, manifest?.slug];\n if (!org || !app || (flag !== undefined && flag.split(\"/\").length !== 2)) {\n throw usageError(\n \"which app does this workflow publish?\",\n \"pass --app <org-slug>/<app-slug>, or run it from a directory whose oxy-app.json names both\"\n );\n }\n return { org, app };\n}\n\nfunction packageJsonPinsPnpm(dir: string): boolean {\n try {\n const pkg = JSON.parse(readFileSync(join(dir, \"package.json\"), \"utf8\")) as {\n packageManager?: string;\n };\n return typeof pkg.packageManager === \"string\" && pkg.packageManager.startsWith(\"pnpm@\");\n } catch {\n return false;\n }\n}\n\n/**\n * Refuse any value that is not inert in both YAML and a shell word.\n *\n * Every field below is written unquoted into a `run:` line or a `path:`, and\n * one of those lines runs in the job holding `id-token: write`. The org, the\n * out dir and the app directory come from a committed manifest and a checkout\n * path, so a `$(…)` in any of them would otherwise become code in the job this\n * workflow exists to keep clean. Allowlists, not escaping: a slug, a path and\n * a URL each have a shape, and anything outside it is a mistake worth hearing.\n */\nfunction assertWorkflowSafe(o: WorkflowOptions): void {\n const path = /^(?!\\/)(?!.*(?:^|\\/)\\.\\.(?:\\/|$))[A-Za-z0-9._/-]+$/;\n const checks: Array<[string, string, boolean]> = [\n [\"org\", o.org, isValidSlug(o.org)],\n [\"app\", o.app, isValidSlug(o.app)],\n [\"environment\", o.environment, /^[A-Za-z0-9._-]{1,255}$/.test(o.environment)],\n [\"--env\", o.env, /^[A-Za-z0-9._:/-]+$/.test(o.env)],\n [\"app directory\", o.appDir, path.test(o.appDir)],\n [\"outDir\", o.outDir, path.test(o.outDir)],\n [\"CLI version\", o.cliVersion, /^[0-9A-Za-z.+-]+$/.test(o.cliVersion)]\n ];\n for (const [label, value, ok] of checks) {\n if (!ok) {\n throw usageError(\n `refusing to write ${label} ${JSON.stringify(value)} into a workflow`,\n \"slugs, relative paths and plain URLs only — it is written unquoted into the job that holds id-token: write\"\n );\n }\n }\n}\n\n/** The workflow. Pure, so the job split can be pinned by a test. */\nexport function workflowYaml(o: WorkflowOptions): string {\n assertWorkflowSafe(o);\n const cli = `@oxy-hq/cli@${o.cliVersion}`;\n const workdir = o.appDir === \".\" ? \"\" : `\\n working-directory: ${o.appDir}`;\n const bundlePath = o.appDir === \".\" ? o.outDir : `${o.appDir}/${o.outDir}`;\n const pnpm = o.pnpmFromPackageJson ? \"\" : \"\\n with:\\n version: 10\";\n const node = o.nodeVersionFile ? \"node-version-file: .nvmrc\" : \"node-version: 20\";\n const promote = o.promote ? \" --promote\" : \"\";\n // Two conditions, and the second is the one that is easy to get wrong.\n //\n // A check runs against the app's LIVE build — `trigger_function_job` and the\n // executor both resolve `published_build_id.or(draft_build_id)`, so a run\n // started right after a DRAFT publish executes the previously promoted code\n // and reports on the wrong artifact. Worse, the first workflow to add a check\n // would fail: the live build predates the flag, so `checks run` finds none and\n // exits 1. So the step is emitted only alongside `--promote`, where the build\n // just published IS the one the check runs.\n //\n // And only when there is something to run: `oxyc checks run` on an app that\n // declares no check is an error, not a no-op.\n const checksStep =\n o.hasChecks && o.promote\n ? ` # Runs every function the manifest marks \\`\"check\": true\\` against the\n # build the step above just promoted, and fails the job if any of them does\n # not pass. It mints its own short-lived credential from the same OIDC\n # token — nothing stored, and nothing carried over from the step above.\n - name: Run the app's checks\n env:\n npm_config_ignore_scripts: \"true\"\n run: npx --yes ${cli} checks run ${o.org}/${o.app} --env ${o.env}\n`\n : \"\";\n return `# Generated by \\`oxyc init-ci\\`. Trusted publishing — no stored secret.\n#\n# \\`id-token: write\\` is job-level and visible to every step, so the publish job\n# is isolated: it checks out the commit, downloads what \\`build\\` produced, and\n# publishes it. It runs no package script. Keep it that way — add nothing to it,\n# and pin these actions by SHA.\nname: Publish ${o.org}/${o.app} to Oxy\n\non:\n push:\n branches: [main]\n workflow_dispatch:\n\npermissions:\n contents: read\n\njobs:\n build:\n runs-on: ubuntu-latest\n # No id-token here: this job runs every dependency's install scripts.\n steps:\n - uses: actions/checkout@v4\n with:\n persist-credentials: false\n - uses: pnpm/action-setup@v4${pnpm}\n - uses: actions/setup-node@v4\n with:\n ${node}\n # Runs oxy-app.json's build and bundles its Oxy Functions into the output\n # directory — everything a publish does except the upload.\n - name: Build the bundle\n run: pnpm dlx ${cli} publish --build-only --org ${o.org} --app ${o.app}${workdir}\n - uses: actions/upload-artifact@v4\n with:\n name: oxy-bundle\n path: ${bundlePath}\n # Vite writes \\`.vite/manifest.json\\`; the default drops hidden files.\n include-hidden-files: true\n if-no-files-found: error\n\n publish:\n needs: build\n runs-on: ubuntu-latest\n # Attach required reviewers to this environment in Settings → Environments.\n environment: ${o.environment}\n permissions:\n id-token: write\n contents: read\n steps:\n # For oxy-app.json and the commit the build is recorded against.\n - uses: actions/checkout@v4\n with:\n persist-credentials: false\n - uses: actions/download-artifact@v4\n with:\n name: oxy-bundle\n path: ${bundlePath}\n - uses: actions/setup-node@v4\n with:\n ${node}\n - name: Publish\n env:\n # The CLI's own dependencies run no install scripts in this job.\n npm_config_ignore_scripts: \"true\"\n run: npx --yes ${cli} publish --prebuilt${promote} --dir ${o.outDir} --env ${o.env} --org ${o.org} --app ${o.app}${workdir}\n${checksStep}`;\n}\n\n/** `gh api users/<owner> --jq .id`, when gh is here and answers. */\nfunction ownerId(owner: string): string | undefined {\n try {\n const result = spawnSync(\"gh\", [\"api\", `users/${owner}`, \"--jq\", \".id\"], { encoding: \"utf8\" });\n return result.status === 0 ? result.stdout.trim() || undefined : undefined;\n } catch {\n return undefined;\n }\n}\n\nexport function runInitCi(ctx: Context, flags: InitCiFlags): void {\n const { org, app } = resolveApp(ctx.cwd, flags.app);\n const environment = flags.environment?.trim() || \"oxy-publish\";\n const root = repoRoot(ctx.cwd) ?? ctx.cwd;\n const path = join(root, WORKFLOW_PATH);\n if (existsSync(path) && !flags.force) {\n throw refusal(`${WORKFLOW_PATH} already exists`, { hint: \"pass --force to overwrite it\" });\n }\n\n const appDir = relative(root, ctx.cwd).split(sep).join(\"/\") || \".\";\n const manifest = loadPublishManifest(ctx.cwd);\n const hasChecks = Object.values(manifest?.functions ?? {}).some((fn) => fn?.check === true);\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(\n path,\n workflowYaml({\n org,\n app,\n environment,\n env: ctx.flags.env ?? \"production\",\n appDir,\n outDir: buildSteps(manifest).outDir,\n hasChecks,\n promote: flags.promote === true,\n pnpmFromPackageJson: packageJsonPinsPnpm(root),\n nodeVersionFile: existsSync(join(root, \".nvmrc\")),\n cliVersion: VERSION\n })\n );\n\n const remote = spawnSync(\"git\", [\"remote\", \"get-url\", \"origin\"], { cwd: root, encoding: \"utf8\" });\n const slug = remote.status === 0 ? parseRemoteSlug(remote.stdout) : undefined;\n const [owner = \"<owner>\", repo = \"<repo>\"] = slug?.split(\"/\") ?? [];\n const id = slug ? ownerId(owner) : undefined;\n\n process.stdout.write(`${out.green(\"wrote\")} ${path}\\n\\n`);\n // A manifest with a check and a workflow without the step is the one\n // surprising outcome here, so say it out loud rather than leaving the author\n // to notice a step that was never written.\n if (hasChecks && !flags.promote) {\n log.info(\n \"the manifest declares a check, but this workflow publishes a draft — a check runs the LIVE build, so it would verify the previously promoted one. Re-run with --promote to publish live and verify what this workflow ships.\"\n );\n }\n log.info(\"next: register this workflow as a publisher for the app, then gate the environment\");\n process.stdout.write(\n ` oxyc api /api/customer-apps/<app-id>/publishers --env ${ctx.flags.env ?? \"production\"} -X POST \\\\\\n` +\n ` -f repo_owner=${owner} -F repo_owner_id=${id ?? `<numeric id: gh api users/${owner} --jq .id>`} \\\\\\n` +\n ` -f repo_name=${repo} -f workflow_ref=${WORKFLOW_PATH} -f environment=${environment}\\n\\n` +\n ` <app-id> is ${org}/${app}'s id on its admin page. Then add required reviewers to the\\n` +\n ` '${environment}' environment in Settings → Environments.\\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 oltp status | provision` — an org's OLTP database, from a laptop.\n *\n * A thin client over the admin console's routes, so staff can see and request\n * provisioning without a shell on the server. The Rust `oxy oltp` reads\n * `OXY_DATABASE_URL` and has no `--env`: it only reaches the control plane of\n * the machine it runs on.\n *\n * GET /api/admin/oltp every org, with a database or without\n * GET /api/admin/orgs/{org_id}/oltp one org's store and writers\n * POST /api/admin/orgs/{org_id}/oltp/provision {\"writers\": [\"app:<writer>\", …]}\n *\n * All three sit behind the `PlatformOltp` capability and the admin scope fence,\n * so an org outside a bounded staff grant answers 404 rather than 403. None of\n * them returns a credential.\n */\n\nimport { createInterface } from \"node:readline/promises\";\n\nimport { type ApiResponse, parseJson, request } from \"../api/request.js\";\nimport type { Context } from \"../context/resolve.js\";\nimport {\n appWriterName,\n isValidWriterName,\n WRITER_NAME_RULE,\n WRITER_NAME_SHAPE\n} from \"../publish/manifest.js\";\nimport * as log from \"../ui/log.js\";\nimport { table } from \"../ui/render.js\";\nimport { out } from \"../ui/tty.js\";\nimport { CliError, ExitCode, exitCodeForStatus, usageError } from \"../util/errors.js\";\nimport { orgOrHint, resolveOrgId } from \"./assume.js\";\n\n/** One row of `GET /admin/oltp` — `oxy_oltp::api::admin::TenantRow`. */\ninterface TenantRow {\n org_id: string;\n org_name: string;\n database: string;\n host: string;\n provider: string;\n region: string;\n /** `none` for an org with no database. */\n status: string;\n schemas: Array<{ schema: string; kind: string; analytics_visible: boolean }>;\n analyst_ready: boolean;\n platform_drift: boolean;\n}\n\n/** `oxy_oltp::api::handlers::SchemaInfo`. */\ninterface SchemaInfo {\n schema: string;\n kind: string;\n writer_name: string;\n role: string;\n analytics_visible: boolean;\n}\n\n/** `oxy_oltp::api::handlers::ConnectionInfoResponse` — metadata, never a credential. */\ninterface ConnectionInfo {\n is_provisioned: boolean;\n host: string;\n database: string;\n provider: string;\n project_name: string;\n console_url?: string | null;\n region: string;\n status: string;\n analyst_role: string;\n analyst_ready: boolean;\n platform_schema_version: number;\n expected_platform_schema_version: number;\n schemas: SchemaInfo[];\n}\n\n/**\n * Provisioning creates a project at the provider and its roles, which is slower\n * than a read. The default two-minute client timeout would abandon a call the\n * server is still completing; retrying is safe, but the timeout reads as failure.\n */\nconst PROVISION_TIMEOUT_MS = 5 * 60_000;\n\n/** A writer as the server takes it, and as it was typed. */\nexport interface WriterPlan {\n /** On the wire: `app:<writer>` or `pipeline:<source>`. */\n spec: string;\n typed: string;\n schema: string;\n}\n\n/**\n * `--writer app:<slug>` / `pipeline:<source>` → what the server accepts.\n *\n * The server takes a WRITER NAME, and a slug's hyphens are illegal in one, so\n * `app:store-ops` is derived to `app:store_ops` exactly as the platform derives\n * `ctx.oltp`'s schema. A name already carrying `_` is what the server's own\n * messages print, and is validated as the writer it already is.\n */\nexport function parseWriter(typed: string): WriterPlan {\n const colon = typed.indexOf(\":\");\n const kind = colon < 0 ? \"\" : typed.slice(0, colon);\n const name = colon < 0 ? \"\" : typed.slice(colon + 1).trim();\n if (kind === \"app\") {\n const writer = name.includes(\"_\")\n ? isValidWriterName(name)\n ? name\n : undefined\n : appWriterName(name);\n if (writer === undefined) {\n throw usageError(\n `invalid app writer in --writer ${typed}`,\n `from a slug, ${WRITER_NAME_RULE}`\n );\n }\n return { spec: `app:${writer}`, typed, schema: `app_${writer}` };\n }\n if (kind === \"pipeline\") {\n if (!isValidWriterName(name)) {\n throw usageError(\n `invalid pipeline source in --writer ${typed}`,\n `it must be ${WRITER_NAME_SHAPE}`\n );\n }\n return { spec: `pipeline:${name}`, typed, schema: `raw_${name}` };\n }\n throw usageError(`--writer ${typed} must look like app:<slug> or pipeline:<source>`);\n}\n\n/** Why the server refused, in the terms an operator acts on. */\nfunction refusalReason(status: number): string | undefined {\n switch (status) {\n case 400:\n return \"the server rejected the request as malformed\";\n case 401:\n return \"not authenticated for this target\";\n case 403:\n return (\n \"the OLTP console needs platform staff standing that may operate it — and an active \" +\n \"`oxyc assume` session closes /admin\"\n );\n case 404:\n return \"no such org here — or one outside your staff grant's scope, which answers 404 on purpose\";\n case 409:\n return \"the provisioner refused a state an operator has to resolve\";\n case 503:\n return \"this deployment has no OLTP provider configured — not an Oxy fault\";\n default:\n return undefined;\n }\n}\n\nfunction oltpError(method: string, path: string, response: ApiResponse): CliError {\n const body = response.body.trim();\n const detail = [refusalReason(response.status), body && body !== \"{}\" ? `server: ${body}` : \"\"]\n .filter((line): line is string => Boolean(line))\n .join(\"\\n\");\n return new CliError(`${method} ${path} failed (${response.status})`, {\n code: exitCodeForStatus(response.status),\n detail: detail || undefined,\n remedy: response.status === 401 ? \"oxyc login --env <env>\" : undefined\n });\n}\n\n/** A 2xx JSON body, or the error its status deserves. */\nasync function call<T>(\n ctx: Context,\n method: string,\n path: string,\n opts: { body?: unknown; timeoutMs?: number } = {}\n): Promise<T> {\n const response = await request({\n target: ctx.target(),\n path,\n method,\n bearer: ctx.bearer(),\n body: opts.body === undefined ? undefined : JSON.stringify(opts.body),\n timeoutMs: opts.timeoutMs\n });\n if (response.status < 200 || response.status >= 300) throw oltpError(method, path, response);\n const parsed = parseJson(response.body);\n if (parsed === undefined || parsed === null) {\n throw new CliError(`${method} ${path} did not return JSON`, {\n code: ExitCode.FAILURE,\n detail: response.body.trim().slice(0, 500) || undefined,\n hint: \"the deployment may predate this route — `oxyc routes oltp` lists what it mounts\"\n });\n }\n return parsed as T;\n}\n\nconst orgPath = (orgId: string) => `/api/admin/orgs/${encodeURIComponent(orgId)}/oltp`;\n\nexport async function runOltpStatus(\n ctx: Context,\n org: string | undefined,\n json: boolean\n): Promise<void> {\n const named = orgOrHint(ctx, org);\n if (!named) return listTenants(ctx, json);\n const orgId = await resolveOrgId(ctx, org);\n const info = await call<ConnectionInfo>(ctx, \"GET\", orgPath(orgId));\n if (json) {\n process.stdout.write(`${JSON.stringify(info, null, 2)}\\n`);\n return;\n }\n printStore(named, info);\n}\n\nasync function listTenants(ctx: Context, json: boolean): Promise<void> {\n const rows = await call<TenantRow[]>(ctx, \"GET\", \"/api/admin/oltp\");\n if (!Array.isArray(rows)) {\n throw new CliError(\"GET /api/admin/oltp did not return a list\", { code: ExitCode.FAILURE });\n }\n if (json) {\n process.stdout.write(`${JSON.stringify(rows, null, 2)}\\n`);\n return;\n }\n if (rows.length === 0) {\n log.info(`no organizations are visible to you on ${ctx.target()}`);\n return;\n }\n process.stdout.write(\n `${table(rows, [\n { header: \"ORG\", value: (r) => r.org_name },\n { header: \"ORG ID\", value: (r) => r.org_id },\n { header: \"STATUS\", value: (r) => r.status },\n { header: \"DATABASE\", value: (r) => r.database },\n { header: \"PROVIDER\", value: (r) => [r.provider, r.region].filter(Boolean).join(\" / \") },\n {\n header: \"SCHEMAS\",\n value: (r) =>\n r.schemas\n .map((s) => (s.analytics_visible ? `${s.schema} (analytics)` : s.schema))\n .join(\", \")\n },\n { header: \"NOTES\", value: (r) => tenantNotes(r) }\n ])}\\n`\n );\n const provisioned = rows.filter((r) => r.status !== \"none\").length;\n log.info(`${provisioned} of ${rows.length} org(s) have an OLTP database`);\n}\n\nfunction tenantNotes(row: TenantRow): string {\n if (row.status === \"none\") return \"\";\n const notes: string[] = [];\n if (!row.analyst_ready) notes.push(\"analyst not minted\");\n if (row.platform_drift) notes.push(\"platform objects behind\");\n return notes.join(\", \");\n}\n\nfunction printStore(org: string, info: ConnectionInfo): void {\n if (!info.is_provisioned) {\n process.stdout.write(`no OLTP database for org ${org}\\n`);\n log.hint(`oxyc oltp provision --org ${org} --writer app:<slug>`);\n return;\n }\n const fields: Array<[string, string]> = [\n [\"database\", info.database],\n [\"host\", info.host],\n [\"provider\", [info.provider, info.region].filter(Boolean).join(\" / \")],\n [\"project\", [info.project_name, info.console_url].filter(Boolean).join(\" \")],\n [\"status\", info.status],\n [\"platform\", `v${info.platform_schema_version}/${info.expected_platform_schema_version}`],\n [\n \"analyst\",\n info.analyst_ready\n ? `${info.analyst_role} (ready)`\n : `${info.analyst_role} — NOT MINTED, postgres_managed cannot resolve`\n ]\n ];\n process.stdout.write(`${fields.map(([k, v]) => `${k.padEnd(9)} ${v}`).join(\"\\n\")}\\n`);\n if (info.schemas.length === 0) {\n process.stdout.write(\"\\nno writers yet\\n\");\n return;\n }\n process.stdout.write(\n `\\n${table(info.schemas, [\n { header: \"SCHEMA\", value: (s) => s.schema },\n { header: \"KIND\", value: (s) => s.kind },\n { header: \"WRITER\", value: (s) => s.writer_name },\n { header: \"ROLE\", value: (s) => s.role },\n { header: \"ANALYTICS\", value: (s) => (s.analytics_visible ? \"visible\" : \"hidden\") }\n ])}\\n`\n );\n}\n\nexport async function runOltpProvision(\n ctx: Context,\n org: string | undefined,\n typedWriters: string[],\n flags: { yes?: boolean; json?: boolean }\n): Promise<void> {\n // EVERY USAGE ERROR BEFORE A REQUEST. The server also parses writers before it\n // provisions, but a typo should not first cost an org lookup and a login.\n if (typedWriters.length === 0) {\n throw usageError(\n \"name at least one --writer\",\n \"app:<slug> for a custom app's ctx.oltp store, pipeline:<source> for an Airway pipeline\"\n );\n }\n const writers = new Map<string, WriterPlan>();\n for (const plan of typedWriters.map(parseWriter)) {\n if (!writers.has(plan.spec)) writers.set(plan.spec, plan);\n }\n\n const orgId = await resolveOrgId(ctx, org);\n const current = await call<ConnectionInfo>(ctx, \"GET\", orgPath(orgId));\n printPlan(ctx.target(), orgOrHint(ctx, org), orgId, current, [...writers.values()]);\n if (!flags.yes) await confirm();\n\n const info = await call<ConnectionInfo>(ctx, \"POST\", `${orgPath(orgId)}/provision`, {\n body: { writers: [...writers.keys()] },\n timeoutMs: PROVISION_TIMEOUT_MS\n });\n if (flags.json) {\n process.stdout.write(`${JSON.stringify(info, null, 2)}\\n`);\n return;\n }\n process.stdout.write(`${out.green(`provisioned ${info.database} on ${info.host}`)}\\n`);\n printStore(orgOrHint(ctx, org), info);\n}\n\n/**\n * What is about to happen, on stderr — stdout is the result — and not through\n * `log.info`, which `--quiet` silences: this is what the prompt asks about.\n */\nfunction printPlan(\n target: string,\n org: string,\n orgId: string,\n current: ConnectionInfo,\n writers: WriterPlan[]\n): void {\n const existing = new Set(current.schemas.map((s) => s.schema));\n const lines = [`On ${target}, for org ${org === orgId ? orgId : `${org} (${orgId})`}:`];\n lines.push(\n current.is_provisioned\n ? ` database ${current.database} on ${current.host} — exists, reconciled`\n : \" database a NEW database at the deployment's OLTP provider — a billable resource\"\n );\n for (const w of writers) {\n const from = w.typed === w.spec ? \"\" : ` (from ${w.typed})`;\n const state = existing.has(w.schema) ? \"exists, reconciled\" : \"new schema and read-write role\";\n lines.push(` writer ${w.spec} → ${w.schema}${from} — ${state}`);\n }\n process.stderr.write(`${lines.join(\"\\n\")}\\n`);\n}\n\n/**\n * Never assumes yes. With no terminal to ask, an unconfirmed provision refuses\n * rather than proceeding or hanging on a prompt nobody can answer.\n */\nasync function confirm(): Promise<void> {\n if (!process.stdin.isTTY) {\n throw new CliError(\"provisioning needs --yes when stdin is not a terminal\", {\n code: ExitCode.REFUSED,\n detail: \"it creates a billable database at the deployment's OLTP provider\",\n remedy: \"re-run with --yes once the plan above is what you want\"\n });\n }\n const prompt = createInterface({ input: process.stdin, output: process.stderr });\n let answer: string;\n try {\n answer = (await prompt.question(\"Provision? [y/N] \")).trim().toLowerCase();\n } finally {\n prompt.close();\n }\n if (answer === \"y\" || answer === \"yes\") return;\n throw new CliError(\"not provisioned — the confirmation was declined\", {\n code: ExitCode.REFUSED\n });\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 `oxyc login` bearer and\n * applying guardrails — to the resolved cloud target.\n *\n * It replaced the Rust `oxy proxy`, and the guardrails came across verbatim\n * rather than reinvented, because each one is a decision somebody argued and\n * every one of them is about not writing to a customer's production data from\n * 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 * - a production target is refused without `--yes`\n *\n * An Oxy Function call also gets a W3C trace (the SDK's, or one minted here),\n * and its `request_id` / `trace_id` are printed per call.\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 { randomUUID } from \"node:crypto\";\nimport { once } from \"node:events\";\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 was safe by omission rather than by design: its `reqwest`\n * was built without the `gzip`/`brotli` features, so it never asked 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 // `traceparent` / `tracestate` are the SDK's W3C trace context. The trace a\n // page stamps on its error (`error.traceId`) must be the one the request\n // carried, or that id names a trace that exists nowhere.\n for (const name of [\n \"content-type\",\n \"accept\",\n \"cookie\",\n \"authorization\",\n \"origin\",\n \"referer\",\n \"traceparent\",\n \"tracestate\"\n ]) {\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/**\n * The function name when `path` is an Oxy Function call —\n * `/customer-apps/<org>/<slug>/fn/<name>[/…]`, the one call this proxy\n * annotates with its ids. A bundle asset that merely contains `/fn/` is not.\n */\nexport function functionRoute(path: string): string | undefined {\n const [customerApps, org, slug, fn, name] = (path.split(\"?\")[0] ?? path)\n .split(\"/\")\n .filter(Boolean);\n return customerApps === \"customer-apps\" && org && slug && fn === \"fn\" ? name : undefined;\n}\n\n/**\n * The trace id of a well-formed W3C `traceparent` — version, a non-zero 32-hex\n * trace id, a non-zero 16-hex span id, flags — or `undefined`. Anything else is\n * rejected whole, as the server's extractor would: a printed id must be real.\n */\nexport function traceIdOf(traceparent: string): string | undefined {\n const [version, trace, span, flags, ...rest] = traceparent.split(\"-\");\n const hex = (s: string | undefined, len: number) =>\n s !== undefined && s.length === len && /^[0-9a-f]+$/i.test(s);\n const nonZero = (s: string | undefined) => s !== undefined && /[^0]/.test(s);\n const ok =\n rest.length === 0 &&\n hex(version, 2) &&\n hex(trace, 32) &&\n nonZero(trace) &&\n hex(span, 16) &&\n nonZero(span) &&\n hex(flags, 2);\n return ok ? trace : undefined;\n}\n\n/**\n * Keep a well-formed inbound `traceparent` (the SDK minted it) or mint a sampled\n * one in its place, and return the trace id either way.\n *\n * A rejected header takes its `tracestate` with it (W3C): vendor state from a\n * trace that no longer applies must not ride on the new one. v4 UUIDs carry a\n * version nibble inside both slices, so neither id can come out all-zero.\n */\nexport function ensureTraceparent(headers: Record<string, string>): string {\n const existing = traceIdOf(headers.traceparent ?? \"\");\n if (existing) return existing;\n delete headers.tracestate;\n const traceId = randomUUID().replaceAll(\"-\", \"\");\n const spanId = randomUUID().replaceAll(\"-\", \"\").slice(0, 16);\n headers.traceparent = `00-${traceId}-${spanId}-01`;\n return traceId;\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 a host match is the kind of thing\n * that goes wrong quietly. Testing it through `runProxy` would mean starting a\n * 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 * NOT ON THE ENV NAME, deliberately, which is where the Rust `oxy proxy` this\n * replaced differed: it refused `--env production` whatever URL that resolved\n * to, and so also refused `--target http://localhost:3000` with no `--env`\n * (the name defaulted to production). Here the URL is the truth — an\n * `oxy-app.json` that deliberately points `production` somewhere else is a\n * statement about where production is, and refusing it would make the manifest\n * 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.\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 // The browser going away takes the upstream request with it. Without this\n // an SSE stream nobody reads stays open against the cloud until it ends on\n // its own, which for an agent run is minutes.\n const abort = new AbortController();\n res.on(\"close\", () => {\n if (!res.writableFinished) abort.abort();\n });\n\n try {\n const headers = buildRequestHeaders(req.headers, token, path);\n // A function call gets a trace of its own, minted here when the SDK did\n // not already send one, so the line printed below names the trace an\n // operator would open — the developer who just watched the call fail\n // should not have to find the id by hand.\n const fn = functionRoute(path);\n const traceId = fn ? ensureTraceparent(headers) : undefined;\n const upstream = await fetch(`${target.replace(/\\/+$/, \"\")}${path}`, {\n method,\n headers,\n body: method === \"GET\" || method === \"HEAD\" ? undefined : body,\n redirect: \"manual\",\n signal: abort.signal\n });\n if (fn) {\n // Unconditional, not `log.info`: `--quiet` must not hide the one line\n // this proxy prints that you would paste somewhere else.\n const requestId = upstream.headers.get(\"x-oxy-request-id\") ?? \"-\";\n process.stderr.write(\n ` ↳ ${upstream.status} fn ${fn} request_id=${requestId} trace_id=${traceId}\\n`\n );\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. Waits on\n // `drain` so a slow browser holds the upstream back rather than this\n // process buffering the whole result set on its behalf.\n for await (const chunk of upstream.body as unknown as AsyncIterable<Uint8Array>) {\n if (!res.write(chunk)) await once(res, \"drain\", { signal: abort.signal });\n }\n }\n res.end();\n log.info(`${upstream.status} ${method} ${path}`);\n } catch (cause) {\n if (abort.signal.aborted) {\n log.info(`${out.dim(\"closed\")} ${method} ${path} (the browser went away)`);\n return;\n }\n log.error(`${method} ${path} failed: ${(cause as Error).message}`);\n // Once the status is on the wire there is no error response left to\n // send: a second `writeHead` throws, and a throw in this async handler is\n // an unhandled rejection that exits the whole proxy. Cut the connection\n // instead, so the browser sees a failed response rather than a\n // truncated one that reads as complete.\n if (res.headersSent) {\n res.destroy();\n return;\n }\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 * `.env.local`, then `.env`, loaded into `process.env` without overriding\n * anything already set — so a laptop publish sees what the shell would, and\n * CI's real environment always wins.\n *\n * Each file is looked for in the working directory and then every parent,\n * nearest first, which is how the Rust `dotenv` crate found them: an app under\n * `apps/<org>/<app>/` picks up a repo-root `.env`.\n *\n * `${VAR}` expansion is NOT supported. Nothing a publish reads has needed it,\n * and a half-implemented expander is worse than an honest literal.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\n\n/** The nearest `name` at or above `dir`. */\nfunction findUp(dir: string, name: string): string | undefined {\n let current = dir;\n for (;;) {\n const candidate = join(current, name);\n if (existsSync(candidate)) return candidate;\n const parent = dirname(current);\n if (parent === current) return undefined;\n current = parent;\n }\n}\n\n/** `KEY=value` lines into pairs. Comments, blanks and malformed lines are skipped. */\nexport function parseDotenv(text: string): Array<[string, string]> {\n const pairs: Array<[string, string]> = [];\n for (const raw of text.split(/\\r?\\n/)) {\n const line = raw.trim().replace(/^export\\s+/, \"\");\n if (!line || line.startsWith(\"#\")) continue;\n const eq = line.indexOf(\"=\");\n if (eq <= 0) continue;\n const key = line.slice(0, eq).trim();\n if (!/^[A-Za-z_][A-Za-z0-9_.]*$/.test(key)) continue;\n pairs.push([key, parseValue(line.slice(eq + 1).trim())]);\n }\n return pairs;\n}\n\nfunction parseValue(value: string): string {\n const quote = value[0];\n if ((quote === '\"' || quote === \"'\") && value.length >= 2) {\n const end = value.indexOf(quote, 1);\n if (end > 0) {\n const inner = value.slice(1, end);\n return quote === '\"' ? inner.replace(/\\\\n/g, \"\\n\") : inner;\n }\n }\n // Unquoted: a ` #` starts a trailing comment.\n const hash = value.search(/\\s#/);\n return (hash >= 0 ? value.slice(0, hash) : value).trim();\n}\n\n/** Load both files for `cwd`. Returns the paths that were read. */\nexport function loadDotenv(cwd: string, env: NodeJS.ProcessEnv = process.env): string[] {\n const read: string[] = [];\n for (const name of [\".env.local\", \".env\"]) {\n const path = findUp(cwd, name);\n if (!path) continue;\n let text: string;\n try {\n text = readFileSync(path, \"utf8\");\n } catch {\n continue;\n }\n read.push(path);\n for (const [key, value] of parseDotenv(text)) {\n if (env[key] === undefined) env[key] = value;\n }\n }\n return read;\n}\n","/**\n * Which manifest capability each `ctx.<area>.<op>` needs — the CLI's copy of\n * the fail-closed gates in\n * `crates/app/src/server/api/custom_apps_functions/host.rs`.\n *\n * ONE SOURCE OF TRUTH, AND IT IS NOT THIS FILE. `FunctionCapabilities` in\n * `host.rs` is the struct every gate reads: each `ctx.*` op refuses with\n * `<Area>CapabilityMissing` when its field is false, `check_storage_capability`\n * is the op-by-op split for `ctx.storage`, and `check_write_destination` plus\n * `host/destinations.rs` decide a `ctx.warehouse` / `ctx.tx` write. This file\n * names those fields so `oxyc validate` and `oxyc publish` can answer, before\n * the upload, what the host would answer at the first call.\n *\n * HELD TO THE STRUCT BY A RUST TEST. `cli_capabilities_drift.rs`, beside\n * `host.rs`, `include_str!`s this file and fails when the `hostField` values\n * below stop naming exactly the gate fields `FunctionCapabilities` carries, or\n * when the `storage.*` ops here stop matching `check_storage_capability`'s\n * arms. A gate added to the host without an entry here fails that test; an\n * entry here for a gate the host no longer has fails it too.\n *\n * THE RUST TEST READS TEXT, NOT TYPESCRIPT: after stripping comments it takes\n * every line starting `hostField:` and the `ops: […]` array after it (wrapped\n * across lines or not). Keep those two keys spelled as they are, and keep a\n * `hostField` out of any comment that is not a full-line one.\n */\n\nconst isObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\n/** `spec.<a>.<b> === true`. */\nfunction flag(spec: Record<string, unknown>, a: string, b: string): boolean {\n const block = spec[a];\n return isObject(block) && block[b] === true;\n}\n\nexport interface GatedCapability {\n /** The `FunctionCapabilities` field in host.rs that gates these ops. */\n readonly hostField: string;\n /** The capability as the docs and the host's refusals name it: `storage.write`. */\n readonly manifest: string;\n /** What to add to the function's oxy-app.json entry — the fix. */\n readonly declare: string;\n /**\n * The `ctx` members that need this gate, as paths under `ctx`:\n * `storage.put`, `oltp.*` (every op of that area), `tx` (`ctx.tx(...)` itself).\n */\n readonly ops: readonly string[];\n /**\n * `manifest`: the gate is a flag on the function's entry, and `declares`\n * answers from the manifest alone.\n *\n * `destination`: the gate depends on WHICH database the call names and what\n * kind of store it is — a customer warehouse needs the reason, Airhouse does\n * not, the org's OLTP is refused outright — and only the server knows the\n * kind. `function-engines.ts` answers at publish; offline, `function-lint.ts`\n * checks the `destinations` allowlist and says the rest was skipped.\n */\n readonly gate: \"manifest\" | \"destination\";\n /** True when the function's manifest entry declares the capability. */\n declares(spec: Record<string, unknown>, database?: string): boolean;\n}\n\n/**\n * Every gate in `FunctionCapabilities`, in the struct's order.\n *\n * `storage_retention` and `fetch_max_bytes` are also fields of that struct and\n * are deliberately absent here: a retention policy and a byte ceiling shape a\n * call that is allowed, they never refuse one. The Rust test carries the same\n * two names as its exclusion list, so a third non-gate field has to be added\n * in both places on purpose.\n */\nexport const GATED_CAPABILITIES: readonly GatedCapability[] = [\n {\n hostField: \"secrets_write\",\n manifest: \"secrets.write\",\n declare: '\"secrets\": { \"write\": true }',\n ops: [\"secrets.set\"],\n gate: \"manifest\",\n declares: (spec) => flag(spec, \"secrets\", \"write\")\n },\n {\n hostField: \"email_send\",\n manifest: \"email.send\",\n declare: '\"email\": { \"send\": true }',\n ops: [\"email.send\"],\n gate: \"manifest\",\n declares: (spec) => flag(spec, \"email\", \"send\")\n },\n {\n hostField: \"org_read\",\n manifest: \"org.read\",\n declare: '\"org\": { \"read\": true }',\n ops: [\"org.people\", \"org.places\", \"org.assignments\"],\n gate: \"manifest\",\n declares: (spec) => flag(spec, \"org\", \"read\")\n },\n {\n hostField: \"storage_read\",\n manifest: \"storage.read\",\n declare: '\"storage\": { \"read\": true }',\n ops: [\"storage.getDownloadUrl\", \"storage.get\", \"storage.head\", \"storage.list\", \"storage.copy\"],\n gate: \"manifest\",\n declares: (spec) => flag(spec, \"storage\", \"read\")\n },\n {\n hostField: \"storage_write\",\n manifest: \"storage.write\",\n declare: '\"storage\": { \"write\": true }',\n ops: [\"storage.getUploadUrl\", \"storage.put\", \"storage.delete\", \"storage.copy\"],\n gate: \"manifest\",\n declares: (spec) => flag(spec, \"storage\", \"write\")\n },\n {\n hostField: \"oltp\",\n manifest: \"oltp.enabled\",\n declare: '\"oltp\": { \"enabled\": true }',\n ops: [\"oltp.*\"],\n gate: \"manifest\",\n declares: (spec) => flag(spec, \"oltp\", \"enabled\")\n },\n {\n hostField: \"airhouse\",\n manifest: \"airhouse.enabled\",\n declare: '\"airhouse\": { \"enabled\": true }',\n ops: [\"airhouse.*\"],\n gate: \"manifest\",\n declares: (spec) => flag(spec, \"airhouse\", \"enabled\")\n },\n {\n hostField: \"customer_warehouse_writes\",\n manifest: \"customerWarehouseWrites\",\n declare: '\"customerWarehouseWrites\": { \"<database>\": \"<why this write stays there>\" }',\n ops: [\"warehouse.insert\", \"warehouse.exec\", \"warehouse.upsert\", \"tx\"],\n gate: \"destination\",\n declares: (spec, database) => {\n const writes = spec.customerWarehouseWrites;\n if (database === undefined || !isObject(writes)) return false;\n const reason = writes[database];\n return typeof reason === \"string\" && reason.trim() !== \"\";\n }\n }\n];\n\n/**\n * The `ctx.warehouse` / `ctx.tx` writes, which also need the database in the\n * function's `destinations` — `write_destinations` on the host, checked by\n * `check_write_destination` before any capability: \"an empty allowlist denies\n * every database\". Not a `FunctionCapabilities` field, so not in the map above.\n */\nexport const WRITE_OPS: readonly string[] = GATED_CAPABILITIES.filter(\n (c) => c.gate === \"destination\"\n).flatMap((c) => c.ops);\n\n/** The gates a `ctx` member path needs — usually one; `storage.copy` needs two. */\nexport function capabilitiesFor(member: string): GatedCapability[] {\n const area = member.split(\".\")[0] ?? member;\n return GATED_CAPABILITIES.filter((c) => c.ops.includes(member) || c.ops.includes(`${area}.*`));\n}\n","/**\n * Lexical scans behind `oxyc validate`'s data-placement checks: Airhouse\n * migration SQL, and a function's calls to `ctx.secrets.set`.\n *\n * NOT PARSERS, AND NOT THE AUTHORITY. The server parses an Airhouse migration\n * before it applies it and refuses what it cannot place; these answer earlier,\n * for the common mistakes. So every scan is CONSERVATIVE: comments and string\n * literals are masked before a keyword is matched, a target that cannot be read\n * is skipped rather than guessed at, and where a scan and the server disagree,\n * the server is right.\n */\n\nexport interface ScanHit {\n /** 1-based, in the original text — masking preserves every offset. */\n line: number;\n level: \"error\" | \"warning\";\n message: string;\n}\n\n/** Every character but a newline as a space, so offsets and line numbers survive. */\nfunction blank(text: string): string {\n return text.replace(/[^\\n]/g, \" \");\n}\n\n/** 1-based line of `offset` in `text`; shared with `function-lint.ts`. */\nexport function lineAt(text: string, offset: number): number {\n let line = 1;\n for (let i = 0; i < offset; i++) if (text.charCodeAt(i) === 10) line++;\n return line;\n}\n\nfunction stickyAt(re: RegExp, text: string, at: number): RegExpExecArray | null {\n re.lastIndex = at;\n return re.exec(text);\n}\n\n/** Just past a block comment opened at `open`; SQL nests them, JavaScript does not. */\nfunction closeBlockComment(text: string, open: number, nested: boolean): number {\n let depth = 1;\n let i = open + 2;\n while (i < text.length) {\n if (nested && text.startsWith(\"/*\", i)) {\n depth++;\n i += 2;\n } else if (text.startsWith(\"*/\", i)) {\n depth--;\n i += 2;\n if (depth === 0) return i;\n } else {\n i++;\n }\n }\n return text.length;\n}\n\n// ── SQL ──────────────────────────────────────────────────────────────────────\n\ninterface MaskedSql {\n /** Comments and string literals blanked, quoted identifiers kept: targets are read here. */\n code: string;\n /** `code` with quoted-identifier CONTENTS blanked too: keywords are matched here. */\n bare: string;\n}\n\n/** Just past the quote closing the one at `open`; a doubled quote is an escape. */\nfunction closeDoubled(text: string, open: number, quote: string): number {\n for (let i = open + 1; i < text.length; i++) {\n if (text[i] !== quote) continue;\n if (text[i + 1] === quote) {\n i++;\n continue;\n }\n return i + 1;\n }\n return text.length;\n}\n\nfunction dollarTagAt(text: string, at: number): string | undefined {\n return stickyAt(/\\$(?:[A-Za-z_][A-Za-z0-9_]*)?\\$/y, text, at)?.[0];\n}\n\n/** One masked token: where it ends, and what replaces it in each view. */\nfunction sqlToken(sql: string, i: number): { end: number; code: string; bare: string } | undefined {\n const two = sql.slice(i, i + 2);\n let end: number | undefined;\n if (two === \"--\") {\n const newline = sql.indexOf(\"\\n\", i);\n end = newline < 0 ? sql.length : newline;\n } else if (two === \"/*\") {\n end = closeBlockComment(sql, i, true);\n } else if (sql[i] === \"'\") {\n end = closeDoubled(sql, i, \"'\");\n } else if (sql[i] === \"$\" && dollarTagAt(sql, i)) {\n const tag = dollarTagAt(sql, i) as string;\n const close = sql.indexOf(tag, i + tag.length);\n end = close < 0 ? sql.length : close + tag.length;\n } else if (sql[i] === '\"') {\n // Kept whole for reading a target; only the INSIDE is blanked for keywords,\n // so a prefix's trailing `\\s+` still stops at the opening quote.\n const close = closeDoubled(sql, i, '\"');\n const inner = sql.slice(i + 1, Math.max(i + 1, close - 1));\n const tail = sql.slice(i + 1 + inner.length, close);\n return { end: close, code: sql.slice(i, close), bare: `\"${blank(inner)}${tail}` };\n }\n if (end === undefined) return undefined;\n const masked = blank(sql.slice(i, end));\n return { end, code: masked, bare: masked };\n}\n\nexport function maskSql(sql: string): MaskedSql {\n const code: string[] = [];\n const bare: string[] = [];\n let plain = 0;\n let i = 0;\n while (i < sql.length) {\n const token = sqlToken(sql, i);\n if (!token) {\n i++;\n continue;\n }\n code.push(sql.slice(plain, i), token.code);\n bare.push(sql.slice(plain, i), token.bare);\n i = token.end;\n plain = token.end;\n }\n code.push(sql.slice(plain));\n bare.push(sql.slice(plain));\n return { code: code.join(\"\"), bare: bare.join(\"\") };\n}\n\nconst DUCKLAKE =\n \"DuckLake has no primary keys, unique constraints, indexes or foreign keys, and a table \" +\n \"carrying one fails and leaves the app's Airhouse writer inert\";\n\n/** Leftmost-first, so `CREATE UNIQUE INDEX` is one hit rather than that and `UNIQUE`. */\nconst UNSUPPORTED =\n /\\bCREATE\\s+(?:UNIQUE\\s+)?INDEX\\b|\\bPRIMARY\\s+KEY\\b|\\bUNIQUE\\b|\\bFOREIGN\\s+KEY\\b|\\bREFERENCES\\b/gi;\n\nfunction unsupportedConstraints(sql: string, bare: string): ScanHit[] {\n const hits: ScanHit[] = [];\n const seen = new Set<string>();\n for (const m of bare.matchAll(UNSUPPORTED)) {\n const written = m[0].replace(/\\s+/g, \" \").toUpperCase();\n const line = lineAt(sql, m.index ?? 0);\n // `FOREIGN KEY (a) REFERENCES t (b)` is one constraint spelled with two keywords.\n const key = `${line}:${written === \"REFERENCES\" ? \"FOREIGN KEY\" : written}`;\n if (seen.has(key)) continue;\n seen.add(key);\n hits.push({\n line,\n level: \"error\",\n message: `\\`${written}\\` is not supported on Airhouse: ${DUCKLAKE}`\n });\n }\n return hits;\n}\n\n/** A statement whose target must be `app_<writer>.<name>`. */\ninterface Targeted {\n label: string;\n re: RegExp;\n /** `DROP TABLE a, b` names several. */\n list?: boolean;\n}\n\nconst TARGETED: Targeted[] = [\n {\n label: \"CREATE TABLE\",\n re: /\\bCREATE\\s+(?:OR\\s+REPLACE\\s+)?(?:(?:TEMP|TEMPORARY)\\s+)?TABLE\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?/gi\n },\n {\n label: \"CREATE VIEW\",\n re: /\\bCREATE\\s+(?:OR\\s+REPLACE\\s+)?(?:(?:TEMP|TEMPORARY)\\s+)?VIEW\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?/gi\n },\n { label: \"ALTER TABLE\", re: /\\bALTER\\s+TABLE\\s+(?:IF\\s+EXISTS\\s+)?/gi },\n { label: \"DROP TABLE\", re: /\\bDROP\\s+TABLE\\s+(?:IF\\s+EXISTS\\s+)?/gi, list: true },\n { label: \"DROP VIEW\", re: /\\bDROP\\s+VIEW\\s+(?:IF\\s+EXISTS\\s+)?/gi, list: true },\n { label: \"INSERT INTO\", re: /\\bINSERT\\s+(?:OR\\s+(?:REPLACE|IGNORE)\\s+)?INTO\\s+/gi },\n // Not `ON CONFLICT … DO UPDATE` or an FK's `ON UPDATE`, neither of which has a target.\n { label: \"UPDATE\", re: /(?<!\\b(?:DO|ON)\\s+)\\bUPDATE\\s+/gi },\n { label: \"DELETE FROM\", re: /\\bDELETE\\s+FROM\\s+/gi },\n { label: \"COMMENT ON\", re: /\\bCOMMENT\\s+ON\\s+(?:TABLE|VIEW|COLUMN)\\s+/gi }\n];\n\nconst PART = /\"(?:[^\"]|\"\")*\"|[A-Za-z_][A-Za-z0-9_$]*/y;\nconst DOT = /\\s*\\.\\s*/y;\nconst COMMA = /\\s*,\\s*/y;\n\ninterface Name {\n /** As written, quotes included — what a suggestion should reuse. */\n raw: string[];\n /**\n * Lower-cased, quoted or not: DuckDB matches identifiers case-insensitively\n * either way, so `\"APP_X\".t` names the app's schema and must not be refused.\n */\n parts: string[];\n end: number;\n}\n\nfunction readName(code: string, at: number): Name | undefined {\n const raw: string[] = [];\n const parts: string[] = [];\n let i = at;\n for (;;) {\n const part = stickyAt(PART, code, i);\n if (!part) return undefined;\n const token = part[0];\n raw.push(token);\n parts.push(\n (token.startsWith('\"') ? token.slice(1, -1).replaceAll('\"\"', '\"') : token).toLowerCase()\n );\n i = PART.lastIndex;\n if (!stickyAt(DOT, code, i)) break;\n i = DOT.lastIndex;\n }\n return { raw, parts, end: i };\n}\n\nfunction misplaced(label: string, name: Name, schema: string, column: boolean): string | undefined {\n // A column is `schema.table.column`; everything else is `schema.name`.\n const want = column ? 3 : 2;\n if (name.parts.length === want && name.parts[0] === schema) return undefined;\n const written = `${label} ${name.raw.join(\".\")}`;\n const suggestion = `${schema}.${name.raw.slice(-(want - 1)).join(\".\")}`;\n const what = name.parts.length < want ? \"is unqualified\" : \"is outside the app's schema\";\n return (\n `\\`${written}\\` ${what} — write \\`${suggestion}\\`: the server refuses an Airhouse ` +\n `migration target that is not qualified with \\`${schema}\\``\n );\n}\n\nfunction misplacedTargets(sql: string, masked: MaskedSql, schema: string): ScanHit[] {\n const hits: ScanHit[] = [];\n for (const target of TARGETED) {\n for (const m of masked.bare.matchAll(target.re)) {\n const column = /\\bCOLUMN\\s+$/i.test(m[0]);\n let at = (m.index ?? 0) + m[0].length;\n for (;;) {\n // A target this cannot read — a placeholder, a subquery — is the server's to judge.\n const name = readName(masked.code, at);\n if (!name) break;\n const problem = misplaced(target.label, name, schema, column);\n if (problem) hits.push({ line: lineAt(sql, at), level: \"error\", message: problem });\n if (!target.list || !stickyAt(COMMA, masked.code, name.end)) break;\n at = COMMA.lastIndex;\n }\n }\n }\n return hits;\n}\n\n/**\n * Every placement problem in one Airhouse migration.\n *\n * `schema` is `app_<writer>`, or `undefined` when the slug could not derive one\n * — the target check then has nothing to compare against and is skipped; the\n * caller reports why.\n */\nexport function scanAirhouseMigration(sql: string, schema: string | undefined): ScanHit[] {\n const masked = maskSql(sql);\n const hits = unsupportedConstraints(sql, masked.bare);\n for (const m of masked.bare.matchAll(/\\bCREATE\\s+SCHEMA\\b/gi)) {\n hits.push({\n line: lineAt(sql, m.index ?? 0),\n level: \"warning\",\n message:\n `\\`CREATE SCHEMA\\` is unnecessary — the platform creates ` +\n `${schema ? `\\`${schema}\\`` : \"the app's schema\"} before it applies migrations`\n });\n }\n if (schema !== undefined) hits.push(...misplacedTargets(sql, masked, schema));\n return hits.sort((a, b) => a.line - b.line);\n}\n\n// ── JavaScript / TypeScript ──────────────────────────────────────────────────\n\n/** Just past a quote closing the one at `open`; a backslash escapes. */\nfunction closeEscaped(text: string, open: number, quote: string): number {\n for (let i = open + 1; i < text.length; i++) {\n if (text[i] === \"\\\\\") {\n i++;\n continue;\n }\n if (text[i] === quote) return i + 1;\n // An unterminated '…' or \"…\" ends at the line; a template literal does not.\n if (quote !== \"`\" && text[i] === \"\\n\") return i;\n }\n return text.length;\n}\n\n/** A `/` starts a regex literal only where a value may begin, not after one. */\nfunction regexCanStart(text: string, at: number): boolean {\n let j = at - 1;\n while (j >= 0 && /\\s/.test(text[j] as string)) j--;\n return j < 0 || \"(,=:[!&|?{};\".includes(text[j] as string);\n}\n\nfunction closeRegex(text: string, open: number): number {\n let inClass = false;\n for (let i = open + 1; i < text.length; i++) {\n const c = text[i];\n if (c === \"\\\\\") {\n i++;\n } else if (c === \"\\n\") {\n return open + 1;\n } else if (inClass) {\n if (c === \"]\") inClass = false;\n } else if (c === \"[\") {\n inClass = true;\n } else if (c === \"/\") {\n return i + 1;\n }\n }\n return open + 1;\n}\n\n/**\n * Comments, strings, template literals and regex literals blanked.\n *\n * APPROXIMATE: a template literal is masked whole, `${…}` included, so a call\n * written inside one is not seen. That errs toward silence, which is the side\n * a warning should err on.\n */\nexport function maskJs(source: string): string {\n const out: string[] = [];\n let plain = 0;\n let i = 0;\n while (i < source.length) {\n const c = source[i] as string;\n const two = source.slice(i, i + 2);\n let end: number | undefined;\n if (two === \"//\") {\n const newline = source.indexOf(\"\\n\", i);\n end = newline < 0 ? source.length : newline;\n } else if (two === \"/*\") {\n end = closeBlockComment(source, i, false);\n } else if (c === \"'\" || c === '\"' || c === \"`\") {\n end = closeEscaped(source, i, c);\n } else if (c === \"/\" && regexCanStart(source, i)) {\n end = closeRegex(source, i);\n }\n if (end === undefined) {\n i++;\n continue;\n }\n out.push(source.slice(plain, i), blank(source.slice(i, end)));\n i = end;\n plain = end;\n }\n out.push(source.slice(plain));\n return out.join(\"\");\n}\n\n/** Top-level argument ranges of a call whose `(` ends just before `from`. */\nexport function splitArgs(\n code: string,\n from: number\n): Array<{ start: number; end: number }> | undefined {\n const args: Array<{ start: number; end: number }> = [];\n let depth = 0;\n let start = from;\n for (let i = from; i < code.length; i++) {\n const c = code[i];\n if (c === \"(\" || c === \"[\" || c === \"{\") {\n depth++;\n } else if (c === \")\" || c === \"]\" || c === \"}\") {\n if (depth === 0) {\n args.push({ start, end: i });\n return args;\n }\n depth--;\n } else if (c === \",\" && depth === 0) {\n args.push({ start, end: i });\n start = i + 1;\n }\n }\n return undefined;\n}\n\n/** The value of a plain string literal, or `undefined` for anything computed. */\nexport function literalString(text: string): string | undefined {\n const quoted = /^(['\"])((?:\\\\.|(?!\\1)[^\\\\])*)\\1$/s.exec(text);\n if (quoted) return quoted[2];\n if (/^`[^`]*`$/.test(text) && !text.includes(\"${\")) return text.slice(1, -1);\n return undefined;\n}\n\nconst SECRETS_SET = /\\bctx\\s*\\??\\.\\s*secrets\\s*\\??\\.\\s*set\\s*\\(/g;\n/** A rotated token written back is what `secrets.write` is for. */\nconst CREDENTIAL_KEY = /(token|secret|key|password)/i;\nconst STATE_WORD =\n /^(state|cursor|checkpoint|progress|last|count|counter|cache|offset|watermark)$/i;\n\n/**\n * Whether a key names state, by whole words — `SYNC_CURSOR`, `row-count`,\n * `lastSyncAt` — so `QB_ACCOUNT_ID` is not read as a `count`.\n */\nfunction namesState(key: string): boolean {\n return key\n .replace(/([a-z0-9])([A-Z])/g, \"$1_$2\")\n .split(/[^A-Za-z0-9]+/)\n .some((word) => STATE_WORD.test(word));\n}\nconst STRINGIFY = /\\bJSON\\s*\\??\\.\\s*stringify\\b/;\n\nexport interface SecretsStateHit {\n line: number;\n /** `ctx.secrets.set(<key as written>, …)` */\n call: string;\n /** What gave it away, worded to follow \"stores\". */\n why: string;\n}\n\n/**\n * `ctx.secrets.set` calls that look like state rather than a credential.\n *\n * ONE FILE — the function's entry. A helper module it imports is not followed,\n * so a call made there is not seen.\n */\nexport function secretsUsedAsState(source: string): SecretsStateHit[] {\n const code = maskJs(source);\n const hits: SecretsStateHit[] = [];\n for (const m of code.matchAll(SECRETS_SET)) {\n const args = splitArgs(code, (m.index ?? 0) + m[0].length);\n const keyRange = args?.[0];\n // Unterminated: the bundler reports that, and there is nothing to read here.\n if (!keyRange) continue;\n const keyText = source.slice(keyRange.start, keyRange.end).trim();\n const key = literalString(keyText);\n if (key !== undefined && CREDENTIAL_KEY.test(key)) continue;\n\n const valueRange = args?.[1];\n const value = valueRange ? code.slice(valueRange.start, valueRange.end) : \"\";\n const why = STRINGIFY.test(value)\n ? \"a `JSON.stringify(…)` value\"\n : key !== undefined && namesState(key)\n ? `a key that names state (\\`${key}\\`)`\n : undefined;\n if (why === undefined) continue;\n hits.push({\n line: lineAt(source, m.index ?? 0),\n call: `ctx.secrets.set(${keyText}, …)`,\n why\n });\n }\n return hits;\n}\n","/**\n * The Oxy Functions lint `oxyc validate` and `oxyc publish` run over an app's\n * function sources: the \"works locally, fails closed in prod\" mistakes that a\n * bundle carries silently and the host refuses on the first call.\n *\n * THREE RULES, each mirroring a refusal the platform already makes:\n *\n * - `capability` — a `ctx.<area>.<op>` call whose manifest capability the\n * function does not declare. `capabilities.ts` is the map; `host.rs`'s\n * `FunctionCapabilities` is the truth it is held to.\n * - `isolate-global` — a Node or Web global the isolate does not provide.\n * `internal-docs/customer-apps-functions.md`, \"Limits & safety\": the isolate\n * is bare `deno_core`, so `TextEncoder`/`TextDecoder`, `Blob`, `File`,\n * `FormData`, `crypto.subtle` and `Buffer` are `ReferenceError`s that no\n * `tsc` catches — and `process`, a Node global the same passage rules out\n * (\"only `oxy_functions_ext` ops plus what `BOOTSTRAP_JS` defines\"), which\n * `runtime.rs`'s bootstrap does not define.\n * - `destinations` / `engine` / `customer-warehouse` — a `ctx.warehouse` /\n * `ctx.tx` write to a database the function may not write, or an op the\n * engine refuses by name. The allowlist half is answered here; the half that\n * needs the database's engine is `function-engines.ts`, at publish.\n *\n * LEXICAL, NOT A PARSER, AND NOT THE AUTHORITY — the same footing as\n * `placement-scan.ts`, whose `maskJs` this reuses: comments, strings, template\n * literals and regex literals are blanked before anything is matched, a call\n * is only seen when written on the context by name (`ctx.storage.put(`, or\n * `run.ctx.storage.put(` — a `ctx` handed around in a struct is still the\n * context), and a source that cannot be read is reported as not linted rather\n * than guessed at. Where this and the host disagree, the host is right; a\n * false positive is what `oxyc publish --allow-function-lint` is for.\n *\n * FOLLOWS RELATIVE IMPORTS. The entry alone is often a thin router — the\n * platform canary's `canary.ts` imports every `ctx` call from `steps.ts` — so\n * `./x`, `./x.js` (the TS spelling of `./x.ts`) and `./dir` (its `index.*`) are\n * read too, inside the app directory only, each file once. A package import\n * is not followed: what `@oxy-hq/sdk` does is its own test suite's problem.\n */\n\nimport { readFileSync, statSync } from \"node:fs\";\nimport { dirname, join, relative, resolve, sep } from \"node:path\";\n\nimport { capabilitiesFor, WRITE_OPS } from \"./capabilities.js\";\nimport { functionEntry, type PublishManifest } from \"./manifest.js\";\nimport type { PlacementIssue } from \"./placement.js\";\nimport { lineAt, literalString, maskJs, splitArgs } from \"./placement-scan.js\";\n\nexport type LintRule =\n | \"capability\"\n | \"destinations\"\n | \"isolate-global\"\n | \"engine\"\n | \"customer-warehouse\";\n\nexport interface FunctionLintIssue extends PlacementIssue {\n rule: LintRule;\n /** The function the file belongs to — the manifest entry the fix edits. */\n fn: string;\n}\n\n/** One `ctx.<member>(` call, with what the engine check needs to know. */\nexport interface CtxCall {\n fn: string;\n /** Relative to the app directory. */\n file: string;\n line: number;\n /** `storage.put`, `oltp.query`, `tx`. */\n member: string;\n /** As written, up to and including the `(`: `ctx.storage.put(`. */\n call: string;\n /** The first argument when it is a string literal — the database of a write. */\n database?: string;\n}\n\nexport interface FunctionLintResult {\n issues: FunctionLintIssue[];\n /** `ctx.warehouse` / `ctx.tx` writes, for the engine check that needs the server. */\n writes: CtxCall[];\n /** What was not checked, and why — one line each, deduplicated by the caller. */\n skipped: string[];\n /**\n * Every source that was read, relative to the app directory, each once — so\n * a test claiming an app \"lints clean\" can prove the claim is not vacuous.\n */\n files: string[];\n}\n\n/**\n * A global the isolate does not provide, and what to reach for instead.\n *\n * `member` restricts the match to `<name>.` — `process.env`, `crypto.subtle` —\n * because a bare `process(` is an ordinary function name, and `crypto` itself\n * is not the complaint: `crypto.subtle` is what the docs rule out.\n */\ninterface AbsentGlobal {\n name: string;\n member?: string;\n instead: string;\n}\n\n/** `internal-docs/customer-apps-functions.md` § \"Limits & safety\", plus `process`. */\nexport const ABSENT_GLOBALS: readonly AbsentGlobal[] = [\n {\n name: \"Buffer\",\n instead:\n \"for base64 use `btoa`/`atob` (strings) or `bytesToBase64`/`base64ToBytes` from \" +\n \"`@oxy-hq/sdk` (bytes); pass binary to `ctx.storage.put` / `ctx.email.send` as \" +\n '`{ encoding: \"base64\" }`'\n },\n {\n name: \"TextEncoder\",\n instead: \"pass strings as-is — `ctx.fetch`, `ctx.storage` and `ctx.email.send` take UTF-8 text\"\n },\n {\n name: \"TextDecoder\",\n instead: '`ctx.fetch` decodes as UTF-8 by default; ask for `{ encoding: \"base64\" }` for bytes'\n },\n { name: \"Blob\", instead: \"send a string or a base64 body: `ctx.fetch(url, { body, encoding })`\" },\n { name: \"File\", instead: \"send a string or a base64 body: `ctx.fetch(url, { body, encoding })`\" },\n {\n name: \"FormData\",\n instead: \"encode the form body yourself (`URLSearchParams`, or a multipart string)\"\n },\n {\n name: \"crypto\",\n member: \"subtle\",\n instead: \"use `ctx.crypto` — HMAC sign / verify and a constant-time compare\"\n },\n { name: \"process\", member: \"\", instead: \"read configuration from `ctx.env`\" }\n];\n\nconst MANIFEST = \"oxy-app.json\";\n\nconst isObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\n// ── sources ──────────────────────────────────────────────────────────────────\n\ninterface SourceFile {\n /** Relative to the app directory, `/`-separated. */\n rel: string;\n source: string;\n}\n\nconst EXTENSIONS = [\".ts\", \".tsx\", \".mts\", \".js\", \".mjs\", \".jsx\"];\n/** A bound on the walk, so a pathological tree cannot make `validate` hang. */\nconst MAX_FILES = 200;\n\n/** The file `spec` names from `from`, inside `appDir`, or `undefined`. */\nfunction resolveRelative(appDir: string, from: string, spec: string): string | undefined {\n if (!spec.startsWith(\"./\") && !spec.startsWith(\"../\")) return undefined;\n const base = resolve(dirname(from), spec);\n if (base !== appDir && !base.startsWith(appDir + sep)) return undefined;\n const candidates = [base];\n // `./x.js` is how a TS source spells `./x.ts` under bundler resolution.\n if (/\\.[mc]?jsx?$/.test(base)) {\n candidates.push(base.replace(/\\.([mc]?)js$/, \".$1ts\"), base.replace(/\\.jsx?$/, \".tsx\"));\n }\n for (const ext of EXTENSIONS) candidates.push(base + ext);\n for (const ext of EXTENSIONS) candidates.push(join(base, `index${ext}`));\n for (const candidate of candidates) {\n if (candidate.endsWith(\".d.ts\")) continue;\n try {\n if (statSync(candidate).isFile()) return candidate;\n } catch {\n // Not this spelling; the next may exist.\n }\n }\n return undefined;\n}\n\n/**\n * A quoted specifier at `lastIndex` in the ORIGINAL source, after real\n * whitespace only. Sticky, and applied to the original rather than the masked\n * text on purpose: masking blanks the quotes too, so a `\\s*` matched on the\n * masked code would swallow the whole specifier and land past it.\n */\nconst SPECIFIER_AT = /\\s*(['\"])((?:\\\\.|(?!\\1)[^\\\\\\n])*)\\1/y;\n\n/**\n * The keyword an import specifier follows, found on the MASKED code so a\n * commented-out import is not followed, and read from the original at the\n * same offset, which masking preserves. A keyword not followed by a quote —\n * `Array.from(xs)`, `import.meta`, `import { x }` before its `from` — reads\n * nothing and is skipped.\n */\nconst SPECIFIER_STARTS = [/\\b(?:import|export)\\b[^;]*?\\bfrom\\b/g, /\\bimport\\s*\\(/g, /\\bimport\\b/g];\n\nfunction importSpecifiers(source: string, masked: string): string[] {\n const found: string[] = [];\n for (const re of SPECIFIER_STARTS) {\n for (const m of masked.matchAll(re)) {\n SPECIFIER_AT.lastIndex = (m.index ?? 0) + m[0].length;\n const spec = SPECIFIER_AT.exec(source);\n if (spec?.[2] !== undefined) found.push(spec[2]);\n }\n }\n return found;\n}\n\n/**\n * One app's sources, read once each however many functions reach them.\n *\n * Shared across an app's functions so a helper two entries import is read\n * once and — for the per-file rule, `isolate-global` — reported once. The\n * per-function rules still run per function: which capability an entry lacks\n * is that entry's business.\n */\ninterface SourceCache {\n loaded: Map<string, SourceFile>;\n unreadable: Map<string, string>;\n}\n\n/**\n * The entry and every source it reaches through relative imports.\n *\n * A file that cannot be read lands in `unreadable` with its code, and only the\n * ENTRY's absence is worth a line to the author — a helper that vanished mid\n * edit is the bundler's report to make.\n */\nfunction loadSources(\n appDir: string,\n entry: string,\n cache: SourceCache\n): { files: SourceFile[]; unreadable: Array<{ rel: string; code: string }> } {\n const files: SourceFile[] = [];\n const unreadable: Array<{ rel: string; code: string }> = [];\n const seen = new Set<string>();\n const queue = [resolve(appDir, entry)];\n while (queue.length > 0 && files.length < MAX_FILES) {\n const path = queue.shift() as string;\n if (seen.has(path)) continue;\n seen.add(path);\n const rel = relative(appDir, path).split(sep).join(\"/\");\n let file = cache.loaded.get(path);\n if (file === undefined) {\n const known = cache.unreadable.get(path);\n if (known !== undefined) {\n unreadable.push({ rel, code: known });\n continue;\n }\n try {\n file = { rel, source: readFileSync(path, \"utf8\") };\n cache.loaded.set(path, file);\n } catch (cause) {\n const code = (cause as NodeJS.ErrnoException).code ?? \"EUNKNOWN\";\n cache.unreadable.set(path, code);\n unreadable.push({ rel, code });\n continue;\n }\n }\n files.push(file);\n for (const spec of importSpecifiers(file.source, maskJs(file.source))) {\n const next = resolveRelative(appDir, path, spec);\n if (next !== undefined && !seen.has(next)) queue.push(next);\n }\n }\n return { files, unreadable };\n}\n\n// ── ctx calls ────────────────────────────────────────────────────────────────\n\n/**\n * `ctx.<area>(` or `ctx.<area>.<op>(`, optional-chained or not. `ctx` may be a\n * member of something (`run.ctx.`) but not the tail of a longer name\n * (`myctx.`), and the last segment must be CALLED — `ctx.airhouse.schema` is a\n * property read, which the host never sees.\n */\nconst CTX_CALL =\n /(?<![\\w$])ctx\\s*\\??\\.\\s*([A-Za-z_$][\\w$]*)(?:\\s*\\??\\.\\s*([A-Za-z_$][\\w$]*))?\\s*\\(/g;\n\nfunction ctxCalls(fn: string, file: SourceFile, masked: string): CtxCall[] {\n const calls: CtxCall[] = [];\n for (const m of masked.matchAll(CTX_CALL)) {\n const member = m[2] === undefined ? (m[1] as string) : `${m[1]}.${m[2]}`;\n const at = m.index ?? 0;\n const call: CtxCall = {\n fn,\n file: file.rel,\n line: lineAt(file.source, at),\n member,\n call: `ctx.${member}(`\n };\n if (WRITE_OPS.includes(member)) {\n const first = splitArgs(masked, at + m[0].length)?.[0];\n if (first) {\n const database = literalString(file.source.slice(first.start, first.end).trim());\n if (database !== undefined) call.database = database;\n }\n }\n calls.push(call);\n }\n return calls;\n}\n\n// ── isolate globals ──────────────────────────────────────────────────────────\n\nconst escapeRe = (text: string) => text.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\n/**\n * Does this file declare `name` itself — a `const`, a `function`, an `import`,\n * a parameter? Then a use of it is the author's own value, not the missing\n * global, and reporting it would be a false refusal at exit 1: the one thing\n * this lint must never do. So the check errs WIDE — a shadow anywhere in the\n * file silences the name for the whole file, block scope be damned — and what\n * a miss here costs is a hit, never a refusal.\n *\n * Type-only imports do not count: `import type { Blob }` gives a name to\n * annotate with, not one to call, so `new Blob(` still throws.\n */\nfunction isShadowed(masked: string, name: string): boolean {\n const n = escapeRe(name);\n const declared = new RegExp(\n `\\\\b(?:const|let|var)\\\\s+(?:${n}\\\\b|\\\\{[^}]*\\\\b${n}\\\\b[^}]*\\\\}|\\\\[[^\\\\]]*\\\\b${n}\\\\b[^\\\\]]*\\\\])` +\n `|\\\\b(?:function|class)\\\\s+${n}\\\\b` +\n `|\\\\bimport\\\\s+(?!type\\\\b)[^;]*?\\\\b${n}\\\\b[^;]*?\\\\bfrom\\\\b` +\n `|\\\\bimport\\\\s+(?!type\\\\b)(?:\\\\*\\\\s+as\\\\s+)?${n}\\\\b` +\n // A single arrow parameter without parentheses: `Buffer => …`.\n `|(?<![\\\\w$.])${n}\\\\s*=>`\n );\n return declared.test(masked) || parameterLists(masked).some((list) => bindsName(list, n));\n}\n\n/**\n * Every parenthesised parameter list: after `function`, before `=>`, and a\n * method's `name(…) {`. Lexical, so `if (x) {` reads as a method too — which\n * only ever widens the shadow, never a refusal.\n */\nfunction parameterLists(masked: string): string[] {\n const lists: string[] = [];\n const shapes = [\n /\\bfunction\\b[^(]*\\(([^()]*)\\)/g,\n /\\(([^()]*)\\)\\s*(?::[^=]*?)?=>/g,\n /\\b[\\w$]+\\s*\\(([^()]*)\\)\\s*(?::[^{]*?)?\\{/g\n ];\n for (const re of shapes) for (const m of masked.matchAll(re)) lists.push(m[1] ?? \"\");\n return lists;\n}\n\n/**\n * Does `list` BIND `name` — as a parameter, not as a type (`x: Buffer`,\n * `Array<Buffer>`, `Blob | File`) or a default-value use (`w = Buffer.from(…)`)?\n */\nfunction bindsName(list: string, n: string): boolean {\n return new RegExp(`(?<![:<|&\\\\w$.]\\\\s*)\\\\b${n}\\\\b(?!\\\\s*[.(])`).test(list);\n}\n\n/**\n * The shape that throws. A VALUE use — called, constructed, or a member read —\n * never a type annotation (`body: Blob`), a `typeof` guard, or a property of\n * something else (`node.Buffer`). For a `member` global only `<name>.<member>`\n * counts, and `process.` matches any member.\n */\nfunction absentGlobalShape(global: AbsentGlobal): RegExp {\n const n = escapeRe(global.name);\n if (global.member === undefined) return new RegExp(`(?<![\\\\w$.])(?:new\\\\s+)?${n}\\\\s*[.(]`, \"g\");\n const member = global.member === \"\" ? \"[A-Za-z_$][\\\\w$]*\" : `${escapeRe(global.member)}\\\\b`;\n return new RegExp(`(?<![\\\\w$.])${n}\\\\s*\\\\.\\\\s*${member}`, \"g\");\n}\n\nfunction absentGlobals(fn: string, file: SourceFile, masked: string): FunctionLintIssue[] {\n const issues: FunctionLintIssue[] = [];\n for (const global of ABSENT_GLOBALS) {\n if (isShadowed(masked, global.name)) continue;\n for (const m of masked.matchAll(absentGlobalShape(global))) {\n const written = m[0].replace(/\\s+/g, \"\").replace(/^new/, \"new \");\n const what = global.member ? `${global.name}.${global.member}` : global.name;\n issues.push({\n rule: \"isolate-global\",\n fn,\n level: \"error\",\n file: file.rel,\n path: `line ${lineAt(file.source, m.index ?? 0)}`,\n message:\n `\\`${written}\\` — the Oxy Functions isolate has no \\`${what}\\` (it is bare deno_core, ` +\n `not Node or a browser), so this throws ReferenceError at runtime; ${global.instead}`\n });\n }\n }\n return issues;\n}\n\n// ── capabilities and destinations ────────────────────────────────────────────\n\nfunction capabilityIssues(spec: Record<string, unknown>, call: CtxCall): FunctionLintIssue[] {\n const issues: FunctionLintIssue[] = [];\n for (const cap of capabilitiesFor(call.member)) {\n if (cap.gate !== \"manifest\" || cap.declares(spec)) continue;\n issues.push({\n rule: \"capability\",\n fn: call.fn,\n level: \"error\",\n file: call.file,\n path: `line ${call.line}`,\n message:\n `\\`${call.call}\\` needs the \\`${cap.manifest}\\` capability, which function ` +\n `\\`${call.fn}\\` does not declare — the host refuses the call (fail-closed); add ` +\n `${cap.declare} to functions.${call.fn} in ${MANIFEST}`\n });\n }\n return issues;\n}\n\n/**\n * The allowlist half of `check_write_destination`: a write needs the database\n * in `destinations`, and an empty allowlist denies every database. The kind of\n * store, and the engine, wait for the server.\n */\nfunction destinationIssue(\n spec: Record<string, unknown>,\n call: CtxCall\n): FunctionLintIssue | undefined {\n if (!WRITE_OPS.includes(call.member)) return undefined;\n const destinations = Array.isArray(spec.destinations)\n ? spec.destinations.filter((d): d is string => typeof d === \"string\")\n : [];\n const written = call.database === undefined ? call.call : `${call.call}\"${call.database}\", …)`;\n const at = `functions.${call.fn}.destinations`;\n if (destinations.length === 0) {\n return {\n rule: \"destinations\",\n fn: call.fn,\n level: \"error\",\n file: call.file,\n path: `line ${call.line}`,\n message:\n `\\`${written}\\` is a write, and function \\`${call.fn}\\` declares no \\`destinations\\` — ` +\n `an empty allowlist refuses every database; add \"destinations\": [\"<database>\"] to ` +\n `functions.${call.fn} in ${MANIFEST}`\n };\n }\n if (call.database !== undefined && !destinations.includes(call.database)) {\n return {\n rule: \"destinations\",\n fn: call.fn,\n level: \"error\",\n file: call.file,\n path: `line ${call.line}`,\n message:\n `\\`${written}\\` writes \\`${call.database}\\`, which is not in \\`${at}\\` ` +\n `(${JSON.stringify(destinations)}) — the host refuses a write outside the allowlist; ` +\n `add it there in ${MANIFEST}`\n };\n }\n return undefined;\n}\n\n// ── entry point ──────────────────────────────────────────────────────────────\n\n/**\n * Every lint issue in one app's functions, plus what the server must finish.\n *\n * `skipped` is worded for the author: which function was not read, and that\n * the engine check waits for `oxyc publish`. Nothing here needs a credential.\n */\nexport function lintAppFunctions(\n appDir: string,\n manifest: Record<string, unknown>\n): FunctionLintResult {\n const result: FunctionLintResult = { issues: [], writes: [], skipped: [], files: [] };\n const cache: SourceCache = { loaded: new Map(), unreadable: new Map() };\n // `isolate-global` is a fact about a FILE, not about the function that\n // reached it: scanned once, reported once, credited to the first function.\n const globalsScanned = new Set<string>();\n const functions = isObject(manifest.functions) ? manifest.functions : {};\n for (const [fn, spec] of Object.entries(functions)) {\n if (!isObject(spec) || (spec.entry != null && typeof spec.entry !== \"string\")) continue;\n const entry = functionEntry(manifest as PublishManifest, fn);\n const { files, unreadable } = loadSources(appDir, entry, cache);\n const missingEntry = unreadable.find((u) => u.rel === entry.replace(/^\\.\\//, \"\"));\n if (missingEntry) {\n result.skipped.push(\n `function \\`${fn}\\` was not linted: ${entry} could not be read (${missingEntry.code})`\n );\n continue;\n }\n for (const file of files) {\n const masked = maskJs(file.source);\n if (!globalsScanned.has(file.rel)) {\n globalsScanned.add(file.rel);\n result.files.push(file.rel);\n result.issues.push(...absentGlobals(fn, file, masked));\n }\n for (const call of ctxCalls(fn, file, masked)) {\n result.issues.push(...capabilityIssues(spec, call));\n const destination = destinationIssue(spec, call);\n if (destination) result.issues.push(destination);\n else if (WRITE_OPS.includes(call.member)) result.writes.push(call);\n }\n }\n }\n result.issues.sort((a, b) => a.file.localeCompare(b.file) || lineOf(a) - lineOf(b));\n return result;\n}\n\nconst lineOf = (issue: PlacementIssue) => Number(issue.path.replace(/^line /, \"\")) || 0;\n\n/** `[function-lint/<rule>] file (line N): message` — the shape a warning prints. */\nexport function describeLintIssue(issue: FunctionLintIssue, prefix = \"\"): string {\n return `[function-lint/${issue.rule}] ${prefix}${issue.file} (${issue.path}): ${issue.message}`;\n}\n","/**\n * The half of the Oxy Functions lint that needs the server: what KIND of\n * store each `ctx.warehouse` / `ctx.tx` write lands on, and which engine.\n *\n * The manifest's `destinations` name workspace databases, not their engines,\n * so `oxyc publish` asks the target — `GET /api/{project}/databases`, the\n * `list_databases` route `oxyc routes databases` lists, which answers `name`,\n * `dialect` (the query engine: `postgres`, `duckdb`, `clickhouse`, …) and\n * `db_type` (the `config.yml` kind: `airhouse_managed`, `postgres_managed`,\n * `snowflake`, …). Three refusals the host makes are then answerable before\n * the upload:\n *\n * - `customer-warehouse` — `host/destinations.rs` `destination_write_policy`:\n * Airhouse (`airhouse` / `airhouse_managed`) takes the write; the org's OLTP\n * (`postgres_managed`) is refused with a pointer at `ctx.oltp`; anything else\n * is a customer warehouse, read-only unless the function names it in\n * `customerWarehouseWrites` with a reason.\n * - `engine` for `ctx.warehouse.upsert` — `upsert_support.rs`: it compiles to\n * `INSERT … ON CONFLICT`, which only the `postgres` and `duckdb` dialects\n * parse, so every other dialect is refused by name.\n * - `engine` for `ctx.tx` — Postgres only; another backend rejects the\n * transaction rather than faking it statement by statement.\n *\n * SKIPPED, NEVER GUESSED, when the list cannot be fetched: an unreachable or\n * unauthorised target prints one warning and the publish goes on, because the\n * host still makes every one of these refusals at the first call.\n */\n\nimport { CliError, ExitCode } from \"../util/errors.js\";\nimport { GATED_CAPABILITIES } from \"./capabilities.js\";\nimport { type CtxCall, describeLintIssue, type FunctionLintIssue } from \"./function-lint.js\";\n\n/** The fields of `DatabaseInfo` this reads; the route answers more. */\nexport interface DatabaseEngine {\n name: string;\n dialect: string;\n db_type: string;\n}\n\nconst LOOKUP_TIMEOUT_MS = 30_000;\n\n/** Dialects whose `INSERT … ON CONFLICT` the host lets through (`parses_on_conflict`). */\nexport const UPSERT_DIALECTS: readonly string[] = [\"postgres\", \"duckdb\"];\n/** The one dialect `ctx.tx` opens a transaction on. */\nexport const TX_DIALECTS: readonly string[] = [\"postgres\"];\n/** `destination_kind`: these take a write with no exception. */\nconst AIRHOUSE_TYPES: readonly string[] = [\"airhouse\", \"airhouse_managed\"];\nconst MANAGED_OLTP_TYPE = \"postgres_managed\";\n\n/**\n * The project's databases, or `undefined` with the reason when the target did\n * not answer — a network failure, a 401/403, a body that is not the list. The\n * caller prints the reason once and continues: this check is advisory, and a\n * publish must not fail on a lookup the upload itself does not need.\n */\nexport async function fetchDatabaseEngines(\n target: string,\n project: string,\n token: string\n): Promise<{ databases: DatabaseEngine[] } | { skipped: string }> {\n const url = `${target.replace(/\\/+$/, \"\")}/api/${encodeURIComponent(project)}/databases`;\n let response: Response;\n try {\n response = await fetch(url, {\n headers: { authorization: `Bearer ${token}` },\n signal: AbortSignal.timeout(LOOKUP_TIMEOUT_MS)\n });\n } catch (cause) {\n return { skipped: `GET ${url} failed: ${(cause as Error).message}` };\n }\n if (!response.ok) return { skipped: `GET ${url} answered ${response.status}` };\n let parsed: unknown;\n try {\n parsed = JSON.parse(await response.text());\n } catch {\n return { skipped: `GET ${url} did not answer JSON` };\n }\n if (!Array.isArray(parsed)) return { skipped: `GET ${url} did not answer a list` };\n const databases = parsed.filter(\n (d): d is DatabaseEngine =>\n typeof d === \"object\" &&\n d !== null &&\n typeof (d as DatabaseEngine).name === \"string\" &&\n typeof (d as DatabaseEngine).dialect === \"string\" &&\n typeof (d as DatabaseEngine).db_type === \"string\"\n );\n // A row this cannot read is a database this cannot see, and \"not a database\n // of this project\" would then be a refusal built on a guess — so the whole\n // list is skipped, the same as one that never arrived.\n if (databases.length !== parsed.length) {\n return {\n skipped:\n `GET ${url} answered ${parsed.length - databases.length} row(s) without a string ` +\n \"name, dialect and db_type\"\n };\n }\n return { databases };\n}\n\n/** The gates a write's database decides — one today, and never silently a second. */\nconst DESTINATION_GATES = GATED_CAPABILITIES.filter((c) => c.gate === \"destination\");\nconst DESTINATION_DECLARE = DESTINATION_GATES.map((c) => c.declare).join(\" and \");\n\nfunction issue(call: CtxCall, rule: FunctionLintIssue[\"rule\"], message: string): FunctionLintIssue {\n return { rule, fn: call.fn, level: \"error\", file: call.file, path: `line ${call.line}`, message };\n}\n\n/** `ctx.warehouse.upsert(\"db\", …)` — the call with the database it named. */\nconst written = (call: CtxCall) => `${call.call}\"${call.database}\", …)`;\n\n/**\n * Every refusal the engine list settles for the writes `lintAppFunctions`\n * collected. A write whose database is not a literal has nothing to look up\n * and is the host's to judge.\n */\nexport function checkEngines(\n writes: CtxCall[],\n manifest: Record<string, unknown>,\n databases: DatabaseEngine[]\n): FunctionLintIssue[] {\n const issues: FunctionLintIssue[] = [];\n const functions =\n typeof manifest.functions === \"object\" && manifest.functions !== null\n ? (manifest.functions as Record<string, unknown>)\n : {};\n for (const call of writes) {\n if (call.database === undefined) continue;\n const spec = functions[call.fn];\n if (typeof spec !== \"object\" || spec === null) continue;\n const db = databases.find((d) => d.name === call.database);\n if (!db) {\n issues.push(\n issue(\n call,\n \"destinations\",\n `\\`${written(call)}\\` writes \\`${call.database}\\`, which is not a database of this ` +\n \"project — the host refuses a write to a database that is not configured; check \" +\n \"the name against the workspace's config.yml\"\n )\n );\n continue;\n }\n const kind = kindIssue(call, spec as Record<string, unknown>, db);\n if (kind) issues.push(kind);\n const engine = engineIssue(call, db);\n if (engine) issues.push(engine);\n }\n return issues;\n}\n\nfunction kindIssue(\n call: CtxCall,\n spec: Record<string, unknown>,\n db: DatabaseEngine\n): FunctionLintIssue | undefined {\n if (AIRHOUSE_TYPES.includes(db.db_type)) return undefined;\n if (db.db_type === MANAGED_OLTP_TYPE) {\n return issue(\n call,\n \"customer-warehouse\",\n `\\`${written(call)}\\` writes \\`${db.name}\\`, the org's OLTP store, which \\`ctx.warehouse\\` ` +\n \"and `ctx.tx` reach as the read-only analyst — write this app's own records with \" +\n \"`ctx.oltp` instead (its `app_<writer>` schema needs no destination)\"\n );\n }\n if (DESTINATION_GATES.some((gate) => gate.declares(spec, db.name))) return undefined;\n const tx =\n call.member === \"tx\"\n ? \" (a `ctx.tx` transaction counts as a write even when it only reads — read with \" +\n \"`ctx.warehouse.query` instead)\"\n : \"\";\n return issue(\n call,\n \"customer-warehouse\",\n `\\`${written(call)}\\` writes \\`${db.name}\\` (${db.db_type}), a customer warehouse, and ` +\n \"customer warehouses are read-only to apps — facts belong in `ctx.airhouse`, records in \" +\n `\\`ctx.oltp\\`; if this write has to stay, say why: add ${DESTINATION_DECLARE}` +\n ` to functions.${call.fn} in oxy-app.json${tx}`\n );\n}\n\nfunction engineIssue(call: CtxCall, db: DatabaseEngine): FunctionLintIssue | undefined {\n if (call.member === \"warehouse.upsert\" && !UPSERT_DIALECTS.includes(db.dialect)) {\n return issue(\n call,\n \"engine\",\n `\\`${written(call)}\\` — \\`${db.name}\\` is ${db.dialect}, and \\`upsert\\` compiles to ` +\n \"`INSERT … ON CONFLICT … DO UPDATE`, which only Postgres and DuckDB parse; the host \" +\n \"refuses it by name — use `ctx.warehouse.insert`, or `ctx.warehouse.exec` with this \" +\n \"warehouse's own upsert statement\"\n );\n }\n if (call.member === \"tx\" && !TX_DIALECTS.includes(db.dialect)) {\n return issue(\n call,\n \"engine\",\n `\\`${written(call)}\\` — \\`${db.name}\\` is ${db.dialect}, and \\`ctx.tx\\` is Postgres-only; ` +\n \"the host refuses to open the transaction rather than run the statements one by one — \" +\n \"use `ctx.warehouse.exec` per statement, or `ctx.oltp.tx` for the app's own store\"\n );\n }\n return undefined;\n}\n\n/**\n * The lint's verdict as an error, for a publish that does not carry\n * `--allow-function-lint`. FAILURE (1), the code `oxyc validate` gives a\n * finding: the command ran and the answer is bad. Not REFUSED (8) — nothing\n * would have been destroyed — and not USAGE (2): the invocation was fine.\n */\nexport function functionLintFailure(issues: FunctionLintIssue[], prefix = \"\"): CliError {\n return new CliError(\n `${issues.length} Oxy Function lint problem(s) — the host would refuse these at the first call`,\n {\n code: ExitCode.FAILURE,\n detail: issues.map((issue) => describeLintIssue(issue, prefix)).join(\"\\n\"),\n hint: \"each line above names the file, the line, the call and the fix\",\n remedy:\n \"fix the manifest or the call, then publish again. A false positive? \" +\n \"`oxyc publish --allow-function-lint` publishes with these as warnings — and please \" +\n \"open an issue naming the rule, so the rule gets fixed\"\n }\n );\n}\n","/**\n * `functions/` in a published bundle: reserved for Oxy Functions, bundled here.\n *\n * The serve plane blocks `functions/<child>` for EVERY app, so a frontend file\n * built into that directory is uploaded and then never served. The check runs\n * whether or not the app declares functions; only its severity depends on\n * whether this publish is about to write there.\n */\n\nimport { spawnSync } from \"node:child_process\";\nimport { existsSync, mkdirSync, readdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nimport { CliError, ExitCode } from \"../util/errors.js\";\nimport { isValidFunctionName } from \"./manifest.js\";\n\n/** What sits in `functions/` that this publish did not put there, sorted. */\nexport interface FunctionsDirConflicts {\n /**\n * `<name>.js` for a valid function name no longer declared — plausibly Oxy's\n * own output from an earlier publish. A GUESS from the filename (`main.js`\n * satisfies the grammar too), so it chooses wording only, never severity.\n */\n staleArtifacts: string[];\n /** Anything else: a page, an asset, a bundler chunk, a directory. */\n frontend: string[];\n}\n\nfunction looksLikeOurArtifact(name: string): boolean {\n return name.endsWith(\".js\") && isValidFunctionName(name.slice(0, -\".js\".length));\n}\n\n/**\n * Inspect the reserved directory. An absent directory is the normal case; any\n * other read failure is fatal, because \"could not tell\" must not read as \"no\n * collision\".\n */\nexport function functionsDirConflicts(outFns: string, declared: string[]): FunctionsDirConflicts {\n const expected = new Set(declared.map((name) => `${name}.js`));\n let entries: string[];\n try {\n entries = readdirSync(outFns);\n } catch (cause) {\n if ((cause as NodeJS.ErrnoException).code === \"ENOENT\")\n return { staleArtifacts: [], frontend: [] };\n throw new CliError(\n `cannot inspect the reserved bundle path ${outFns}: ${(cause as Error).message}`\n );\n }\n const conflicts: FunctionsDirConflicts = { staleArtifacts: [], frontend: [] };\n for (const name of entries.filter((entry) => !expected.has(entry))) {\n (looksLikeOurArtifact(name) ? conflicts.staleArtifacts : conflicts.frontend).push(name);\n }\n conflicts.staleArtifacts.sort();\n conflicts.frontend.sort();\n return conflicts;\n}\n\n/** A bounded, stable rendering: five names, then a count. */\nexport function describeEntries(entries: string[]): string {\n const shown = 5;\n const head = entries\n .slice(0, shown)\n .map((entry) => `functions/${entry}`)\n .join(\", \");\n const extra = entries.length - shown;\n return extra > 0 ? `${head} (and ${extra} more)` : head;\n}\n\n/**\n * Enforce the reserved path. Returns a warning to print, or throws.\n *\n * Writing (functions declared): ANY conflict refuses, one message for both\n * buckets. Not writing: one warning — refusing would break a publish that\n * works, over files that are merely unreachable.\n */\nexport function enforceReservedFunctionsDir(\n bundleDir: string,\n declared: string[],\n weWillWrite: boolean\n): string | undefined {\n const conflicts = functionsDirConflicts(join(bundleDir, \"functions\"), declared);\n if (conflicts.frontend.length === 0 && conflicts.staleArtifacts.length === 0) return undefined;\n\n if (!weWillWrite) {\n // Capped per bucket, then joined: capping a merged list lets alphabetical\n // order decide which class of file gets named at all.\n const listed = [conflicts.frontend, conflicts.staleArtifacts]\n .filter((list) => list.length > 0)\n .map(describeEntries)\n .join(\", \");\n return (\n `this bundle declares no Oxy Functions, but its build output contains ${listed}. ` +\n \"`functions/` is reserved in a published bundle — those files will be uploaded and \" +\n \"will NOT be served. Emit them somewhere else.\"\n );\n }\n\n const detail: string[] = [];\n if (conflicts.frontend.length > 0) {\n detail.push(\n ` - ${describeEntries(conflicts.frontend)} — looks like frontend output; emit it somewhere else`\n );\n }\n if (conflicts.staleArtifacts.length > 0) {\n detail.push(\n ` - ${describeEntries(conflicts.staleArtifacts)} — looks like an artifact from a previous ` +\n \"publish, for a function oxy-app.json no longer declares\"\n );\n }\n throw new CliError(\n \"`functions/` is reserved for Oxy Functions in a published bundle, and this build output \" +\n \"already contains files Oxy did not put there\",\n {\n code: ExitCode.REFUSED,\n detail: detail.join(\"\\n\"),\n hint:\n \"publishing would upload them into a path the serve plane blocks — emit them somewhere \" +\n \"else, or clean the build directory and re-publish\"\n }\n );\n}\n\n/** Runs a command, streaming its output; throws when it fails. */\nexport type Runner = (label: string, command: string, args: string[], cwd: string) => void;\n\nexport const spawnRunner: Runner = (label, command, args, cwd) => {\n process.stderr.write(`[${label}] $ ${[command, ...args].join(\" \")}\\n`);\n // The child's stdout goes to OUR stderr: stdout is the result (`--json`).\n const result = spawnSync(command, args, { cwd, stdio: [\"inherit\", 2, 2] });\n if (result.error) throw new CliError(`failed to start \\`${command}\\`: ${result.error.message}`);\n if (result.status !== 0) {\n throw new CliError(\n `\\`${[command, ...args].join(\" \")}\\` failed (exit ${result.status ?? \"signal\"})`\n );\n }\n};\n\n/**\n * esbuild each declared function into `<bundleDir>/functions/<name>.js`.\n *\n * Through the app's own toolchain (`pnpm exec esbuild`) so dependencies resolve\n * exactly as in `pnpm build`, from the app directory. Argv, not a shell string,\n * so an entry path cannot inject into the command line.\n */\nexport function bundleFunctions(\n entries: Array<{ name: string; entry: string }>,\n appDir: string,\n bundleDir: string,\n run: Runner = spawnRunner\n): void {\n if (entries.length === 0) return;\n const outFns = join(bundleDir, \"functions\");\n mkdirSync(outFns, { recursive: true });\n for (const { name, entry } of entries) {\n run(\n `fn:${name}`,\n \"pnpm\",\n [\n \"exec\",\n \"esbuild\",\n entry,\n \"--bundle\",\n \"--format=esm\",\n // The runtime provides `ctx` / `fetch`, not Node built-ins.\n \"--platform=neutral\",\n // Stack traces remap to the author's `.ts` lines…\n \"--sourcemap=inline\",\n // …without shipping every original source file inside the map.\n \"--sources-content=false\",\n `--outfile=${join(outFns, `${name}.js`)}`\n ],\n appDir\n );\n }\n}\n\n/**\n * `--prebuilt`: the bundle was built and its functions bundled elsewhere (a CI\n * build job). Every declared function must already be there — the server does\n * not check, so a missing one would publish fine and 404 at runtime.\n */\nexport function requirePrebuiltFunctions(bundleDir: string, declared: string[]): void {\n const missing = declared.filter(\n (name) => !existsSync(join(bundleDir, \"functions\", `${name}.js`))\n );\n if (missing.length === 0) return;\n throw new CliError(`--prebuilt bundle is missing ${missing.length} declared function(s)`, {\n code: ExitCode.USAGE,\n detail: missing.map((name) => ` functions/${name}.js`).join(\"\\n\"),\n hint: \"build it with `oxyc publish --build-only` first, which bundles them into the output directory\"\n });\n}\n\n/** Validate every declared name before anything is written. */\nexport function validateFunctionNames(declared: string[]): void {\n const bad = declared.find((name) => !isValidFunctionName(name));\n if (bad !== undefined) {\n throw new CliError(`invalid function name ${JSON.stringify(bad)}`, {\n code: ExitCode.USAGE,\n hint: \"function names must match ^[a-z][a-z0-9-]{0,63}$\"\n });\n }\n}\n","/**\n * Where a build came from: git remote, commit and branch, recorded per build so\n * the admin UI can link it back to code.\n *\n * NEVER FAILS A PUBLISH. A `--dir` publish from a directory that is not a\n * checkout, or a runner with no git at all, is legitimate — every git answer\n * here degrades to \"unknown\", and the gaps become warnings.\n */\n\nimport { spawnSync } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\n\n/** One git answer, or `undefined` for any failure including a missing binary. */\nfunction gitAnswer(args: string[], cwd: string): string | undefined {\n try {\n const result = spawnSync(\"git\", args, { cwd, encoding: \"utf8\" });\n if (result.error || result.status !== 0) return undefined;\n return result.stdout.trim() || undefined;\n } catch {\n return undefined;\n }\n}\n\nexport interface GitSource {\n repo?: string;\n commit?: string;\n branch?: string;\n}\n\n/**\n * Remote, HEAD and branch of the checkout at `dir`.\n *\n * A detached HEAD reports no branch rather than the literal `HEAD` that\n * `rev-parse --abbrev-ref` prints — so a CI checkout of a pinned commit falls\n * through to `GITHUB_REF_NAME` instead of recording a branch named \"HEAD\".\n */\nexport function captureGitSource(dir: string): GitSource {\n const branch = gitAnswer([\"rev-parse\", \"--abbrev-ref\", \"HEAD\"], dir);\n return {\n repo: gitAnswer([\"remote\", \"get-url\", \"origin\"], dir),\n commit: gitAnswer([\"rev-parse\", \"HEAD\"], dir),\n branch: branch === \"HEAD\" ? undefined : branch\n };\n}\n\n/**\n * Uncommitted changes under `dir` — staged, unstaged or untracked — or\n * `undefined` when git cannot say.\n *\n * SCOPED TO `dir` by the `-- .` pathspec: many apps share one repo, and a\n * colleague's edit to a different app must not make this warning cry wolf.\n */\nexport function worktreeIsDirty(dir: string): boolean | undefined {\n try {\n const result = spawnSync(\"git\", [\"status\", \"--porcelain\", \"--\", \".\"], {\n cwd: dir,\n encoding: \"utf8\"\n });\n if (result.error || result.status !== 0) return undefined;\n return result.stdout.trim().length > 0;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Strip `userinfo@` from a scheme URL before it is persisted — an\n * `https://x-access-token:<TOKEN>@github.com/…` remote must never reach the\n * database. The scp-like `git@github.com:o/r` form carries no secret.\n */\nexport function sanitizeRemoteUrl(url: string): string {\n const schemeEnd = url.indexOf(\"://\");\n if (schemeEnd < 0) return url;\n const start = schemeEnd + 3;\n const rest = url.slice(start);\n const authorityEnd = rest.includes(\"/\") ? rest.indexOf(\"/\") : rest.length;\n const at = rest.slice(0, authorityEnd).lastIndexOf(\"@\");\n return at < 0 ? url : url.slice(0, start) + rest.slice(at + 1);\n}\n\n/** A field counts only with non-whitespace content: `--repo \"\"` is not provenance. */\nexport function isRecorded(value: string | undefined): boolean {\n return value !== undefined && value.trim().length > 0;\n}\n\nexport type ProvenanceGap = \"no-source\" | \"missing-repo\" | \"missing-commit\" | \"dirty-tree\";\n\n/**\n * Every way the recorded provenance fails to describe what is being shipped.\n *\n * Incompleteness (the same classification the admin list makes) and dirtiness\n * are orthogonal, so both are returned. A dirty tree only matters behind a\n * recorded commit — without one there is no claim for it to contradict.\n */\nexport function provenanceGaps(\n dirty: boolean | undefined,\n commit: string | undefined,\n repo: string | undefined\n): ProvenanceGap[] {\n const hasRepo = isRecorded(repo);\n const hasCommit = isRecorded(commit);\n const gaps: ProvenanceGap[] = [];\n if (!hasRepo && !hasCommit) gaps.push(\"no-source\");\n else if (!hasRepo) gaps.push(\"missing-repo\");\n else if (!hasCommit) gaps.push(\"missing-commit\");\n if (dirty === true && hasCommit) gaps.push(\"dirty-tree\");\n return gaps;\n}\n\nexport const GAP_MESSAGES: Record<ProvenanceGap, string> = {\n \"no-source\":\n \"no git source recorded for this build — nobody will be able to trace it back to code. \" +\n \"Publish from the app's git checkout, or pass --repo/--commit.\",\n \"missing-commit\":\n \"a git repo is recorded for this build but no commit — the link points at a branch, which \" +\n \"moves, so it won't identify the code that is running. Pass --commit, or publish from the checkout.\",\n \"missing-repo\":\n \"a commit is recorded for this build but no git repo — there is nowhere to resolve that sha. \" +\n \"Pass --repo, or publish from the checkout.\",\n \"dirty-tree\":\n \"publishing from a dirty working tree — the commit recorded for this build does NOT contain \" +\n \"the changes you are shipping. Commit and re-publish if this build needs to be reproducible.\"\n};\n\n/**\n * The default build id under GitHub Actions: the commit, qualified by the run.\n *\n * `GITHUB_SHA` alone repeats on \"Re-run all jobs\", and a build id is immutable\n * and cached by id — a reused one is a 409 at best and a merge into a cached\n * build at worst. Each qualifier falls back independently.\n */\nexport function ciBuildId(env: NodeJS.ProcessEnv = process.env): string | undefined {\n const sha = env.GITHUB_SHA?.trim();\n if (!sha) return undefined;\n const run = env.GITHUB_RUN_ID?.trim();\n const attempt = env.GITHUB_RUN_ATTEMPT?.trim();\n if (run && attempt) return `${sha}-${run}.${attempt}`;\n if (run) return `${sha}-${run}`;\n return sha;\n}\n\n/** `--build-id`, else the CI id, else a random one. */\nexport function resolveBuildId(\n flag: string | undefined,\n env: NodeJS.ProcessEnv = process.env\n): string {\n return flag?.trim() || ciBuildId(env) || randomUUID().replaceAll(\"-\", \"\");\n}\n","/**\n * The bundle as a `.tar.gz`, entries at the archive root.\n *\n * WRITTEN HERE rather than taken from a tar package. The format needed is\n * small — POSIX ustar headers, plus a PAX `path` record for a name over 100\n * bytes — and `oxyc` also ships as a Bun-compiled binary, where a dependency\n * that reaches into Node's zlib internals can work under every test (which\n * run on Node) and fail only in the binary. `gzipSync` is public API on both.\n *\n * Symlinks are FOLLOWED and archived as their target's contents, as the Rust\n * client did: a link entry would unpack server-side as an empty file.\n */\n\nimport { readdirSync, readFileSync, realpathSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { gzipSync } from \"node:zlib\";\n\nimport { CliError, ExitCode } from \"../util/errors.js\";\n\nconst BLOCK = 512;\n\nfunction octal(value: number, width: number): string {\n return `${value.toString(8).padStart(width - 1, \"0\")}\\0`;\n}\n\n/** One 512-byte header block. `name` is written raw, truncated to 100 bytes. */\nfunction header(name: Buffer, size: number, mode: number, mtime: number, type: string): Buffer {\n const block = Buffer.alloc(BLOCK);\n name.copy(block, 0, 0, Math.min(name.length, 100));\n block.write(octal(mode, 8), 100, \"ascii\");\n block.write(octal(0, 8), 108, \"ascii\");\n block.write(octal(0, 8), 116, \"ascii\");\n block.write(octal(size, 12), 124, \"ascii\");\n block.write(octal(mtime, 12), 136, \"ascii\");\n block.write(\" \".repeat(8), 148, \"ascii\");\n block.write(type, 156, \"ascii\");\n block.write(\"ustar\\0\", 257, \"ascii\");\n block.write(\"00\", 263, \"ascii\");\n let sum = 0;\n for (const byte of block) sum += byte;\n block.write(`${sum.toString(8).padStart(6, \"0\")}\\0 `, 148, \"ascii\");\n return block;\n}\n\n/** `<len> path=<path>\\n`, where `<len>` counts the whole record including itself. */\nexport function paxPathRecord(path: string): Buffer {\n const body = ` path=${path}\\n`;\n const bodyLength = Buffer.byteLength(body);\n let length = bodyLength + String(bodyLength).length;\n if (String(length).length !== String(bodyLength).length)\n length = bodyLength + String(length).length;\n return Buffer.from(`${length}${body}`);\n}\n\nfunction padding(size: number): Buffer {\n const rest = size % BLOCK;\n return Buffer.alloc(rest === 0 ? 0 : BLOCK - rest);\n}\n\ninterface Entry {\n path: string;\n kind: \"file\" | \"dir\";\n source: string;\n}\n\n/**\n * Every entry under `root`, directories before their contents, sorted so the\n * same tree always produces the same archive. A symlinked directory that\n * points back up the tree is visited once.\n */\nfunction walk(root: string): Entry[] {\n const entries: Entry[] = [];\n const seen = new Set<string>([realpathSync(root)]);\n const visit = (dir: string, prefix: string): void => {\n for (const name of readdirSync(dir).sort()) {\n const source = join(dir, name);\n const path = prefix ? `${prefix}/${name}` : name;\n const stat = statSync(source);\n if (stat.isDirectory()) {\n const real = realpathSync(source);\n if (seen.has(real)) continue;\n seen.add(real);\n entries.push({ path: `${path}/`, kind: \"dir\", source });\n visit(source, path);\n } else if (stat.isFile()) {\n entries.push({ path, kind: \"file\", source });\n }\n }\n };\n visit(root, \"\");\n return entries;\n}\n\nfunction entryBlocks(entry: Entry): Buffer[] {\n const stat = statSync(entry.source);\n const mtime = Math.floor(stat.mtimeMs / 1000);\n const name = Buffer.from(entry.path);\n const blocks: Buffer[] = [];\n if (name.length > 100) {\n const record = paxPathRecord(entry.path);\n blocks.push(header(Buffer.from(\"PaxHeader\"), record.length, 0o644, mtime, \"x\"));\n blocks.push(record, padding(record.length));\n }\n if (entry.kind === \"dir\") {\n blocks.push(header(name, 0, 0o755, mtime, \"5\"));\n return blocks;\n }\n const content = readFileSync(entry.source);\n const mode = stat.mode & 0o111 ? 0o755 : 0o644;\n blocks.push(header(name, content.length, mode, mtime, \"0\"), content, padding(content.length));\n return blocks;\n}\n\n/** Tar and gzip the contents of `dir`. Throws when it is not a directory. */\nexport function tarGzDir(dir: string): Buffer {\n let isDir = false;\n try {\n isDir = statSync(dir).isDirectory();\n } catch {\n isDir = false;\n }\n if (!isDir) {\n throw new CliError(`bundle dir ${dir} does not exist (did the build run?)`, {\n code: ExitCode.USAGE\n });\n }\n const blocks = walk(dir).flatMap(entryBlocks);\n blocks.push(Buffer.alloc(BLOCK * 2));\n return gzipSync(Buffer.concat(blocks));\n}\n","/**\n * `oxyc publish` — build a custom app and ship the bundle to an Oxy deployment.\n *\n * From an app directory: read `oxy-app.json`, build per its `build` block (or\n * the defaults), bundle any Oxy Functions, resolve the project from the\n * target's public `build-config`, and POST the tarball. It replaced the Rust\n * `oxy publish` flag for flag; what it adds:\n *\n * --build-only build and bundle, stop before anything needs a credential\n * --prebuilt with --dir: the functions are already bundled — check, don't rebuild\n * --json the server's result, warnings included, on stdout\n *\n * and trusted publishing: in a GitHub Actions job granted `id-token: write`\n * with no token set, it exchanges the job's OIDC token for a credential scoped\n * to this one app.\n *\n * `--build-only` and `--prebuilt` exist for CI that keeps the credential out of\n * the job that runs package scripts: build there, publish the artifact in a job\n * that installs nothing.\n */\n\nimport { spawnSync } from \"node:child_process\";\nimport { join, resolve, sep } from \"node:path\";\n\nimport type { Context } from \"../context/resolve.js\";\nimport { loadDotenv } from \"../publish/dotenv.js\";\nimport {\n checkEngines,\n fetchDatabaseEngines,\n functionLintFailure\n} from \"../publish/function-engines.js\";\nimport {\n describeLintIssue,\n type FunctionLintIssue,\n type FunctionLintResult,\n lintAppFunctions\n} from \"../publish/function-lint.js\";\nimport {\n bundleFunctions,\n enforceReservedFunctionsDir,\n requirePrebuiltFunctions,\n validateFunctionNames\n} from \"../publish/functions.js\";\nimport {\n buildSteps,\n declaredFunctions,\n functionEntry,\n isValidSlug,\n loadPublishManifest,\n type PublishManifest\n} from \"../publish/manifest.js\";\nimport {\n captureGitSource,\n GAP_MESSAGES,\n isRecorded,\n provenanceGaps,\n resolveBuildId,\n sanitizeRemoteUrl,\n worktreeIsDirty\n} from \"../publish/provenance.js\";\nimport {\n exchangeGithubOidc,\n fetchOrgForProject,\n fetchProject,\n githubOidcAvailable,\n type PublishResult,\n uploadBundle\n} from \"../publish/server.js\";\nimport { tarGzDir } from \"../publish/tarball.js\";\nimport * as log from \"../ui/log.js\";\nimport { out } from \"../ui/tty.js\";\nimport { authError, CliError, ExitCode, usageError } from \"../util/errors.js\";\n\nexport interface PublishFlags {\n app?: string;\n buildId?: string;\n dir?: string;\n promote?: boolean;\n name?: string;\n repo?: string;\n commit?: string;\n branch?: string;\n buildOnly?: boolean;\n prebuilt?: boolean;\n json?: boolean;\n /** Publish past a function lint finding, printing each as a warning that names its rule. */\n allowFunctionLint?: boolean;\n}\n\nfunction envValue(name: string): string | undefined {\n return process.env[name]?.trim() || undefined;\n}\n\n/** `(org, app)` from a working directory shaped `…/apps/<org>/<app>[/…]`. */\nexport function inferOrgApp(cwd: string): { org?: string; app?: string } {\n const parts = cwd.split(sep).filter(Boolean);\n const index = parts.lastIndexOf(\"apps\");\n if (index < 0) return {};\n return { org: parts[index + 1], app: parts[index + 2] };\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/** How this publish will authenticate, decided before anything is built. */\ntype Credential = { kind: \"token\"; token: string } | { kind: \"oidc\" };\n\nfunction resolveCredential(ctx: Context): Credential {\n const token = ctx.maybeBearer();\n if (token) return { kind: \"token\", token };\n if (githubOidcAvailable()) return { kind: \"oidc\" };\n throw authError(ctx.target(), ctx.flags.env ?? \"production\", ctx.flags.tokenEnv ?? \"OXY_TOKEN\");\n}\n\n/** One manifest build step, output to stderr so stdout stays the result. */\nfunction runBuildStep(label: string, command: string, cwd: string, basePath: string): void {\n process.stderr.write(`[${label}] $ ${command}\\n`);\n const result = spawnSync(\"sh\", [\"-c\", command], {\n cwd,\n stdio: [\"inherit\", 2, 2],\n env: { ...process.env, OXY_APP_BASE_PATH: basePath }\n });\n if (result.error) throw new CliError(`failed to start \\`${command}\\`: ${result.error.message}`);\n if (result.status !== 0) {\n throw new CliError(`build step \\`${command}\\` failed (exit ${result.status ?? \"signal\"})`);\n }\n}\n\ninterface Identity {\n org?: string;\n app: string;\n}\n\n/** flag → env → manifest → directory, for each half. */\nfunction resolveIdentity(ctx: Context, flags: PublishFlags, manifest?: PublishManifest): Identity {\n const inferred = inferOrgApp(ctx.cwd);\n const org = ctx.flags.org ?? envValue(\"OXY_ORG\") ?? manifest?.orgSlug ?? inferred.org;\n const app = flags.app ?? envValue(\"OXY_APP\") ?? manifest?.slug ?? inferred.app;\n if (!app) throw usageError(\"missing app\", \"set oxy-app.json `slug`, --app, or OXY_APP\");\n if (!isValidSlug(app)) {\n throw usageError(\n `invalid app slug ${JSON.stringify(app)}`,\n \"1-63 lowercase letters, digits and single hyphens — no leading, trailing or double hyphen, no underscore\"\n );\n }\n return { org, app };\n}\n\n/** Build from source (unless --dir), then check and bundle `functions/`. */\nfunction prepareBundle(\n ctx: Context,\n flags: PublishFlags,\n manifest: PublishManifest | undefined,\n identity: Identity\n): string {\n const declared = declaredFunctions(manifest);\n validateFunctionNames(declared);\n\n let bundleDir: string;\n if (flags.dir) {\n bundleDir = resolve(ctx.cwd, flags.dir);\n } else {\n if (!identity.org) {\n throw usageError(\n \"missing org: the app's base path needs it\",\n \"set oxy-app.json `orgSlug`, --org, OXY_ORG, or --project (a workspace determines its org), or publish a pre-built bundle with --dir\"\n );\n }\n const steps = buildSteps(manifest);\n const basePath = `/customer-apps/${identity.org}/${identity.app}/`;\n runBuildStep(\"install\", steps.install, ctx.cwd, basePath);\n runBuildStep(\"build\", steps.command, ctx.cwd, basePath);\n bundleDir = join(ctx.cwd, steps.outDir);\n }\n\n const warning = enforceReservedFunctionsDir(bundleDir, declared, declared.length > 0);\n if (warning) log.warn(warning);\n\n if (flags.prebuilt) {\n requirePrebuiltFunctions(bundleDir, declared);\n } else {\n const entries = declared.map((name) => ({ name, entry: functionEntry(manifest, name) }));\n bundleFunctions(entries, ctx.cwd, bundleDir);\n }\n return bundleDir;\n}\n\n/**\n * The lint's findings: fail closed, or — with `--allow-function-lint` — a\n * warning each, naming the rule so a false positive can be reported by name.\n *\n * `skipped` lines are warnings either way: a function that was not read was\n * not linted, and saying so is what keeps a clean run honest.\n */\nfunction reportFunctionLint(\n issues: FunctionLintIssue[],\n skipped: string[],\n allow: boolean | undefined\n): void {\n for (const line of skipped) log.warn(`function lint: ${line}`);\n if (issues.length === 0) return;\n if (allow) {\n for (const issue of issues) log.warn(describeLintIssue(issue));\n return;\n }\n throw functionLintFailure(issues);\n}\n\n/**\n * The engine half of the lint, once the project and a credential are known.\n *\n * ADVISORY: a lookup that fails prints one warning and the publish goes on —\n * the host refuses every one of these at the first call anyway, and a publish\n * must not fail on a request the upload itself does not make.\n */\nasync function lintEngines(\n lint: FunctionLintResult,\n manifest: PublishManifest,\n target: string,\n project: string,\n token: string,\n allow: boolean | undefined\n): Promise<void> {\n if (lint.writes.length === 0) return;\n const engines = await fetchDatabaseEngines(target, project, token);\n if (\"skipped\" in engines) {\n log.warn(\n \"function lint: the engine check (`upsert` and `ctx.tx` dialects, customer-warehouse \" +\n `writes) was skipped — could not list the project's databases: ${engines.skipped}`\n );\n return;\n }\n const issues = checkEngines(lint.writes, manifest as Record<string, unknown>, engines.databases);\n reportFunctionLint(issues, [], allow);\n}\n\ninterface Provenance {\n repo?: string;\n commit?: string;\n branch?: string;\n}\n\n/** Flags win, then the checkout, then the CI variables; every gap is a warning. */\nfunction resolveProvenance(cwd: string, flags: PublishFlags): Provenance {\n const git = captureGitSource(cwd);\n const repoSource = flags.repo ?? git.repo;\n const provenance = {\n repo: repoSource === undefined ? undefined : sanitizeRemoteUrl(repoSource),\n commit: flags.commit ?? git.commit ?? envValue(\"GITHUB_SHA\"),\n branch: flags.branch ?? git.branch ?? envValue(\"GITHUB_REF_NAME\")\n };\n // Only ask git about dirt when there is a recorded commit for it to contradict.\n const dirty = isRecorded(provenance.commit) ? worktreeIsDirty(cwd) : undefined;\n for (const gap of provenanceGaps(dirty, provenance.commit, provenance.repo)) {\n log.warn(GAP_MESSAGES[gap]);\n }\n return provenance;\n}\n\n/** The credential for the upload itself — the OIDC exchange happens here, last. */\nasync function uploadToken(\n ctx: Context,\n credential: Credential,\n identity: Identity\n): Promise<string> {\n if (credential.kind === \"token\") return credential.token;\n if (!identity.org || UUID.test(identity.org)) {\n throw usageError(\n \"trusted publishing needs the org SLUG\",\n \"set oxy-app.json `orgSlug` or pass --org <slug> — the exchange is registered by slug\"\n );\n }\n log.info(\"exchanging the GitHub OIDC token for a publish credential\");\n return (await exchangeGithubOidc(ctx.target(), identity.org, identity.app)).token;\n}\n\nfunction printResult(\n target: string,\n identity: Identity,\n result: PublishResult,\n asJson: boolean\n): void {\n for (const warning of result.warnings ?? []) log.warn(warning);\n if (asJson) {\n process.stdout.write(`${JSON.stringify(result, null, 2)}\\n`);\n return;\n }\n const org = result.org_slug ?? identity.org ?? \"\";\n const headline = result.is_new_app\n ? `Registered new app ${org}/${identity.app} (id ${result.app_id})`\n : `Published new version of ${org}/${identity.app} (id ${result.app_id})`;\n process.stdout.write(\n `${out.green(headline)}\\n` +\n ` build ${result.build_id} → ${result.channel} channel · ${target}${result.url}\\n`\n );\n}\n\nexport async function runPublish(ctx: Context, flags: PublishFlags): Promise<void> {\n if (flags.prebuilt && !flags.dir) {\n throw usageError(\"--prebuilt needs --dir\", \"it names a bundle that was built elsewhere\");\n }\n if (flags.prebuilt && flags.buildOnly) {\n throw usageError(\"--prebuilt and --build-only together do nothing\", \"drop one\");\n }\n\n for (const path of loadDotenv(ctx.cwd)) log.info(`loaded ${path}`);\n const manifest = loadPublishManifest(ctx.cwd);\n const identity = resolveIdentity(ctx, flags, manifest);\n const projectPin = ctx.flags.project ?? envValue(\"OXY_PROJECT\");\n\n // Decided before the build, so a missing login fails in a second rather\n // than after a two-minute install.\n const credential = flags.buildOnly ? undefined : resolveCredential(ctx);\n if (!identity.org && projectPin) {\n identity.org = await fetchOrgForProject(ctx.target(), projectPin);\n }\n\n // Before the build, like the credential: a capability the manifest lacks is\n // a one-line fix, and learning about it after a two-minute install is how\n // it used to be learned — in production, at the first call.\n const lint = manifest\n ? lintAppFunctions(ctx.cwd, manifest as Record<string, unknown>)\n : undefined;\n if (lint) reportFunctionLint(lint.issues, lint.skipped, flags.allowFunctionLint);\n\n const bundleDir = prepareBundle(ctx, flags, manifest, identity);\n if (flags.buildOnly || !credential) {\n if (lint && lint.writes.length > 0) {\n log.info(\n \"function lint: the engine check (`upsert` and `ctx.tx` dialects, customer-warehouse \" +\n \"writes) needs the server — the publishing job runs it before the upload\"\n );\n }\n if (flags.json) process.stdout.write(`${JSON.stringify({ bundle_dir: bundleDir }, null, 2)}\\n`);\n else process.stdout.write(`${out.green(\"built\")} ${bundleDir}\\n`);\n return;\n }\n\n const target = ctx.target();\n let project = projectPin;\n if (!project) {\n if (!identity.org) {\n throw usageError(\n \"missing org: needed to look up the project\",\n \"set oxy-app.json `orgSlug`, --org or OXY_ORG, or pass --project <uuid>\"\n );\n }\n project = await fetchProject(target, identity.org, identity.app);\n }\n\n const buildId = resolveBuildId(flags.buildId);\n const provenance = resolveProvenance(ctx.cwd, flags);\n const tarball = tarGzDir(bundleDir);\n const channel = flags.promote ? \"published\" : \"draft\";\n const who = identity.org\n ? `${identity.org}/${identity.app}`\n : `${identity.app} → workspace ${project}`;\n log.info(`publishing ${who} (${tarball.length} bytes) → ${target} [${channel}]`);\n\n const token = await uploadToken(ctx, credential, identity);\n if (lint && manifest) {\n await lintEngines(lint, manifest, target, project, token, flags.allowFunctionLint);\n }\n let result: PublishResult;\n try {\n result = await uploadBundle({\n target,\n token,\n tarball,\n fields: [\n [\"app\", identity.app],\n [\"project\", project],\n [\"build_id\", buildId],\n [\"channel\", channel],\n // Optional: a pre-built bundle pinned to a project lets the server infer it.\n [\"org\", identity.org],\n [\"name\", flags.name],\n [\"source_repo\", provenance.repo],\n [\"commit_sha\", provenance.commit],\n [\"branch\", provenance.branch]\n ]\n });\n } catch (cause) {\n if (cause instanceof CliError && cause.code === ExitCode.AUTH && credential.kind === \"token\") {\n throw new CliError(cause.message, {\n code: cause.code,\n detail: cause.detail,\n hint: `publishing needs app-admin rights on the org — \\`oxyc whoami --env ${ctx.flags.env ?? \"production\"}\\` shows yours`\n });\n }\n throw cause;\n }\n printResult(target, identity, result, Boolean(flags.json));\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 = \"cd3188a91f93402a\";\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 { tmpdir } from \"node:os\";\nimport { dirname, join, resolve, sep } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { CliError, ExitCode } from \"../util/errors.js\";\nimport {\n ASSET_DIRS,\n embeddedAssetsDir,\n extractEmbeddedAssets,\n REINSTALL_REMEDY\n} 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 * Why a path will not still be there tomorrow, phrased for an error message —\n * or `undefined` when it looks durable.\n *\n * ONLY `skills install` needs this, and only because it SYMLINKS. Every other\n * command reads its assets and is done; a link outlives the process and is read\n * months later by something that is not this tool. Run under `npx`, the package\n * lives in npm's `_npx` cache, so `oxyc skills install` reports six skills\n * linked, in green, and every one of them dangles the moment npm reclaims that\n * cache — Claude Code then silently stops loading them, and `~/.claude/skills/`\n * still looks populated. That is the exact failure `commands/skills.ts` opens by\n * describing: links out of a tree that had to persist forever, and did not.\n *\n * WHAT IS DELIBERATELY NOT MATCHED is as important as what is. A compiled\n * binary unpacks its assets into `<cache>/oxyc/assets/<digest>/`\n * (`template/embedded.ts`) — a cache directory, and a perfectly supported place\n * to link out of, because the curl install has nowhere else to put them and the\n * path is stable for as long as that build is installed. It is EXEMPTED BY\n * NAME, first and unconditionally, rather than left to the rules below to miss:\n * `cacheDir()` is `$XDG_CACHE_HOME` or `$HOME/.cache`, both of which a sandbox\n * or an ephemeral container can perfectly well place under the temp dir — and\n * then the last rule here would refuse the one install shape that has nowhere\n * else to keep its assets, quoting a remedy (`npm install -g`) that is not even\n * how that user installed. Everything else matches package-manager EXEC caches\n * specifically, never \"somewhere under a cache dir\", which is why `dlx` and\n * `_npx` are exact path segments.\n *\n * The escape hatch already exists and needs no flag: `OXYC_SKILLS_DIR` pointing\n * at a durable copy is checked here like any other source, so a setup this\n * heuristic misjudges has a one-line way past it.\n */\nexport function ephemeralSourceReason(path: string): string | undefined {\n const full = resolve(path);\n\n // The compiled binary's own unpacked assets — supported, and checked before\n // anything else so no later rule can take it away.\n const assets = resolve(embeddedAssetsDir());\n if (full === assets || full.startsWith(assets + sep)) return undefined;\n\n const segments = full.split(sep);\n // npm's `npx` cache: ~/.npm/_npx/<hash>/node_modules/...\n if (segments.includes(\"_npx\")) return \"an `npx` cache directory\";\n // `pnpm dlx` / `yarn dlx` unpack into a `dlx` directory under the store.\n if (segments.includes(\"dlx\")) return \"a `dlx` cache directory\";\n // `yarn dlx` and some `bunx` paths land straight in the system temp dir.\n if (full.startsWith(resolve(tmpdir()) + sep)) return \"a temporary directory\";\n return undefined;\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 { ephemeralSourceReason, 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 // REFUSED BEFORE ANY LINK IS MADE, because the alternative is worse than a\n // failure: `npx @oxy-hq/cli skills install` links out of npm's throwaway\n // cache, prints six green `linked` rows, and leaves six dangling entries the\n // moment npm reclaims it. Claude Code just stops loading them — no error, and\n // `~/.claude/skills/` still looks full.\n //\n // Refusing rather than COPYING, which is the friendlier-looking option and a\n // trap: real directories at those names are exactly what `linkOne` below\n // rightly declines to clobber, so a copy here would wedge every later\n // `skills install` from a proper global install. One upfront no beats a\n // permanent block.\n const ephemeral = ephemeralSourceReason(source);\n if (ephemeral) {\n throw refusal(`refusing to link skills out of ${ephemeral}`, {\n hint:\n \"the links would work now and break silently later — `oxyc skills install` \" +\n \"writes symlinks that something else reads months from now, so the source \" +\n \"has to outlive this process.\",\n detail: ` source: ${source}`,\n remedy: \"npm install -g @oxy-hq/cli && oxyc skills install\"\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 * The data-placement checks `oxyc validate` runs over an `oxy-app.json`.\n *\n * THE SHAPE OF THE DATA PICKS THE STORE. Append-only facts and history go to\n * the workspace's Airhouse through `ctx.airhouse`, in the app's own\n * `app_<writer>` schema; records the app edits go to org OLTP (`ctx.oltp`);\n * files go to `ctx.storage`; a customer warehouse is read-only, written only\n * under a declared, reasoned exception.\n *\n * ADVISORY. Each rule mirrors a refusal the platform makes at publish or\n * promote, and answers before a bundle is built. The server is the authority:\n * where the two disagree, it is right.\n */\n\nimport { readdirSync, readFileSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nimport {\n appWriterName,\n functionEntry,\n type PublishManifest,\n WRITER_NAME_RULE\n} from \"./manifest.js\";\nimport { scanAirhouseMigration, secretsUsedAsState } from \"./placement-scan.js\";\n\nexport interface PlacementIssue {\n level: \"error\" | \"warning\";\n /** Relative to the app directory: `oxy-app.json`, a function's source, or a migration. */\n file: string;\n /** A manifest key path, or `line N`. */\n path: string;\n message: string;\n}\n\nconst MANIFEST = \"oxy-app.json\";\n\nconst isObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst error = (file: string, path: string, message: string): PlacementIssue => ({\n level: \"error\",\n file,\n path,\n message\n});\n\nconst warning = (file: string, path: string, message: string): PlacementIssue => ({\n level: \"warning\",\n file,\n path,\n message\n});\n\n/** The writer the platform will derive from the slug, or why it cannot. */\ntype Writer =\n | { kind: \"derived\"; schema: string }\n | { kind: \"underivable\"; why: string }\n | { kind: \"unknown\" };\n\nfunction writerFor(slug: string | undefined): Writer {\n if (slug === undefined) return { kind: \"unknown\" };\n const name = appWriterName(slug);\n if (name !== undefined) return { kind: \"derived\", schema: `app_${name}` };\n return {\n kind: \"underivable\",\n why: slug.includes(\"_\")\n ? `the slug \\`${slug}\\` contains \\`_\\`, and a slug containing \\`_\\` cannot back a ` +\n \"schema — it would share one with its hyphenated twin\"\n : `the slug \\`${slug}\\` cannot derive a writer: ${WRITER_NAME_RULE}`\n };\n}\n\n/**\n * Every placement issue in one app.\n *\n * `slug` is passed rather than read, because a manifest without one still\n * publishes — under `--app`, or from an `apps/<org>/<app>/` directory — and the\n * caller is what knows which applies.\n */\nexport function checkAppPlacement(\n appDir: string,\n manifest: Record<string, unknown>,\n slug: string | undefined\n): PlacementIssue[] {\n const issues: PlacementIssue[] = [];\n const writer = writerFor(slug);\n let usesSchema = false;\n\n const functions = isObject(manifest.functions) ? manifest.functions : {};\n for (const [name, spec] of Object.entries(functions)) {\n if (!isObject(spec)) {\n issues.push(error(MANIFEST, `functions.${name}`, \"must be an object\"));\n continue;\n }\n checkWarehouseWrites(name, spec, issues);\n usesSchema = checkAirhouseGate(name, spec, writer, issues) || usesSchema;\n checkSecretsAsState(appDir, manifest, name, spec, issues);\n }\n usesSchema = checkAirhouseMigrations(appDir, manifest, writer, issues) || usesSchema;\n\n if (usesSchema && writer.kind === \"unknown\") {\n issues.push(\n warning(\n MANIFEST,\n \"slug\",\n \"`ctx.airhouse` and Airhouse migrations use the schema `app_<writer>`, derived from the \" +\n \"app slug, and no slug is known here — set `slug` in oxy-app.json so it can be checked\"\n )\n );\n }\n return issues;\n}\n\nfunction checkWarehouseWrites(\n fn: string,\n spec: Record<string, unknown>,\n issues: PlacementIssue[]\n): void {\n const writes = spec.customerWarehouseWrites;\n if (writes == null) return;\n const path = `functions.${fn}.customerWarehouseWrites`;\n if (!isObject(writes)) {\n issues.push(\n error(\n MANIFEST,\n path,\n \"must be an object mapping a database to the reason this function may write to it\"\n )\n );\n return;\n }\n const destinations = Array.isArray(spec.destinations) ? spec.destinations : [];\n for (const [database, reason] of Object.entries(writes)) {\n const at = `${path}.${database}`;\n if (typeof reason !== \"string\" || !reason.trim()) {\n issues.push(\n error(\n MANIFEST,\n at,\n \"the reason must be a non-empty string — an exception to read-only customer \" +\n \"warehouses has to say why it exists\"\n )\n );\n } else if (!destinations.includes(database)) {\n issues.push(\n error(\n MANIFEST,\n at,\n `\\`${database}\\` is not in this function's \\`destinations\\`, so the function cannot ` +\n \"write to it — an exception for a database the function cannot write is dead config\"\n )\n );\n } else {\n issues.push(\n warning(\n MANIFEST,\n at,\n `function \\`${fn}\\` writes to customer warehouse \\`${database}\\` (reason: ` +\n `${reason.trim()}) — customer warehouses are read-only by default; facts and ` +\n \"history belong in `ctx.airhouse`, records in `ctx.oltp`\"\n )\n );\n }\n }\n}\n\n/** True when this function turns `ctx.airhouse` on. */\nfunction checkAirhouseGate(\n fn: string,\n spec: Record<string, unknown>,\n writer: Writer,\n issues: PlacementIssue[]\n): boolean {\n const gate = spec.airhouse;\n if (gate == null) return false;\n const path = `functions.${fn}.airhouse`;\n if (!isObject(gate)) {\n issues.push(error(MANIFEST, path, 'must be an object: `{ \"enabled\": true }`'));\n return false;\n }\n if (gate.enabled != null && typeof gate.enabled !== \"boolean\") {\n issues.push(error(MANIFEST, `${path}.enabled`, \"must be true or false\"));\n return false;\n }\n if (gate.enabled !== true) return false;\n if (writer.kind === \"underivable\") {\n issues.push(\n error(\n MANIFEST,\n `${path}.enabled`,\n \"`ctx.airhouse` writes the app's own schema `app_<writer>`, whose writer is derived \" +\n `from the app slug — and ${writer.why}`\n )\n );\n }\n return true;\n}\n\nfunction checkSecretsAsState(\n appDir: string,\n manifest: Record<string, unknown>,\n fn: string,\n spec: Record<string, unknown>,\n issues: PlacementIssue[]\n): void {\n if (spec.entry != null && typeof spec.entry !== \"string\") {\n issues.push(error(MANIFEST, `functions.${fn}.entry`, \"must be a string\"));\n return;\n }\n const entry = functionEntry(manifest as PublishManifest, fn);\n let source: string;\n try {\n source = readFileSync(join(appDir, entry), \"utf8\");\n } catch (cause) {\n const code = (cause as NodeJS.ErrnoException).code ?? \"EUNKNOWN\";\n issues.push(\n warning(\n MANIFEST,\n `functions.${fn}`,\n `not scanned for \\`ctx.secrets.set\\`: ${entry} could not be read (${code})`\n )\n );\n return;\n }\n for (const hit of secretsUsedAsState(source)) {\n issues.push(\n warning(\n entry,\n `line ${hit.line}`,\n `function \\`${fn}\\` stores ${hit.why} with \\`${hit.call}\\` — secrets hold credentials; ` +\n \"state that changes belongs in `ctx.oltp` (records) or `ctx.airhouse` (facts)\"\n )\n );\n }\n}\n\n/**\n * `migrations.dir`'s rule on the server (`normalize_dir`): a plain relative\n * directory, since it is matched as a prefix inside the bundle.\n */\nfunction normalizeDir(dir: string): string | undefined {\n const trimmed = dir.trim().replace(/^\\/+|\\/+$/g, \"\");\n if (\n trimmed === \"\" ||\n dir.startsWith(\"/\") ||\n dir.includes(\"\\\\\") ||\n trimmed.split(\"/\").some((c) => c === \"..\" || c === \".\" || c === \"\")\n ) {\n return undefined;\n }\n return trimmed;\n}\n\n/** The declared directory, normalised, or `undefined` after reporting why not. */\nfunction declaredDir(\n manifest: Record<string, unknown>,\n issues: PlacementIssue[]\n): string | undefined {\n const block = manifest.airhouseMigrations;\n if (!isObject(block)) {\n issues.push(\n error(MANIFEST, \"airhouseMigrations\", 'must be an object: `{ \"dir\": \"airhouse-migrations\" }`')\n );\n return undefined;\n }\n if (typeof block.dir !== \"string\" || !block.dir.trim()) {\n issues.push(\n error(\n MANIFEST,\n \"airhouseMigrations.dir\",\n \"is required — the directory of `.sql` files applied, once each and in filename \" +\n \"order, to the app's Airhouse schema at promote\"\n )\n );\n return undefined;\n }\n const dir = normalizeDir(block.dir);\n if (dir === undefined) {\n issues.push(\n error(\n MANIFEST,\n \"airhouseMigrations.dir\",\n `\\`${block.dir}\\` is not a safe path inside the bundle — use a plain relative directory ` +\n 'such as \"airhouse-migrations\"'\n )\n );\n return undefined;\n }\n const oltp = manifest.migrations;\n if (isObject(oltp) && typeof oltp.dir === \"string\" && normalizeDir(oltp.dir) === dir) {\n issues.push(\n error(\n MANIFEST,\n \"airhouseMigrations.dir\",\n `\\`${dir}\\` is also \\`migrations.dir\\` — OLTP migrations run on Postgres and Airhouse ` +\n \"migrations on DuckLake, so each needs its own directory\"\n )\n );\n return undefined;\n }\n return dir;\n}\n\n/**\n * Where the directory is in the SOURCE tree.\n *\n * The server reads it from the built bundle, so it may live at the app root,\n * under `public/` (which Vite copies to the bundle root), or already in the\n * build output.\n */\nfunction locateDir(appDir: string, dir: string, outDir: string): string | undefined {\n const candidates = new Set([dir, `public/${dir}`, `${outDir.replace(/\\/+$/, \"\")}/${dir}`]);\n for (const candidate of candidates) {\n try {\n if (statSync(join(appDir, candidate)).isDirectory()) return candidate;\n } catch {\n // Not here; the next candidate may be.\n }\n }\n return undefined;\n}\n\n/** `*.sql` under `root`, as paths relative to it — the server's `collect`, which recurses. */\nfunction sqlFiles(root: string, prefix = \"\"): string[] {\n const found: string[] = [];\n for (const entry of readdirSync(join(root, prefix), { withFileTypes: true })) {\n const rel = prefix ? `${prefix}/${entry.name}` : entry.name;\n if (entry.isDirectory()) found.push(...sqlFiles(root, rel));\n // Case-sensitive, as the server's is.\n else if (entry.name.endsWith(\".sql\")) found.push(rel);\n }\n return found;\n}\n\n/** True when the app declares Airhouse migrations. */\nfunction checkAirhouseMigrations(\n appDir: string,\n manifest: Record<string, unknown>,\n writer: Writer,\n issues: PlacementIssue[]\n): boolean {\n if (manifest.airhouseMigrations == null) return false;\n const dir = declaredDir(manifest, issues);\n if (dir === undefined) return true;\n if (writer.kind === \"underivable\") {\n issues.push(\n error(\n MANIFEST,\n \"airhouseMigrations\",\n \"Airhouse migrations run in the app's own schema `app_<writer>`, whose writer is \" +\n `derived from the app slug — and ${writer.why}`\n )\n );\n }\n\n const build = isObject(manifest.build) ? manifest.build : {};\n const outDir = typeof build.outDir === \"string\" && build.outDir.trim() ? build.outDir : \"out\";\n const found = locateDir(appDir, dir, outDir);\n if (found === undefined) {\n issues.push(\n error(\n MANIFEST,\n \"airhouseMigrations.dir\",\n `\\`${dir}\\` does not exist — looked for ${dir}/, public/${dir}/ and ${outDir}/${dir}/ ` +\n \"in the app directory\"\n )\n );\n return true;\n }\n\n let files: string[];\n try {\n files = sqlFiles(join(appDir, found)).sort();\n } catch (cause) {\n issues.push(\n error(\n MANIFEST,\n \"airhouseMigrations.dir\",\n `\\`${found}\\` could not be read: ${(cause as Error).message}`\n )\n );\n return true;\n }\n if (files.length === 0) {\n issues.push(\n error(\n MANIFEST,\n \"airhouseMigrations.dir\",\n `\\`${found}\\` holds no \\`.sql\\` files — the platform refuses a declared migrations ` +\n \"directory with nothing in it\"\n )\n );\n return true;\n }\n\n const schema = writer.kind === \"derived\" ? writer.schema : undefined;\n for (const rel of files) {\n const file = `${found}/${rel}`;\n const sql = readFileSync(join(appDir, file), \"utf8\");\n for (const hit of scanAirhouseMigration(sql, schema)) {\n issues.push({ level: hit.level, file, path: `line ${hit.line}`, message: hit.message });\n }\n }\n return true;\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 { dirname, 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 { lintAppFunctions } from \"../publish/function-lint.js\";\nimport { checkAppPlacement } from \"../publish/placement.js\";\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\";\nimport { inferOrgApp } from \"./publish.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\n/**\n * The custom-app manifest, checked for DATA PLACEMENT rather than against a\n * schema: none is generated for it — the SDK's type is its only definition —\n * so `publish/placement.ts` checks where the app's data goes instead.\n */\nconst APP_MANIFEST = \"oxy-app.json\";\n\n/** Matched on the basename, for the reason `schemaFor` gives. */\nfunction isAppManifest(path: string): boolean {\n return (path.split(\"\\\\\").join(\"/\").split(\"/\").pop() ?? path) === APP_MANIFEST;\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 (entry.name !== APP_MANIFEST) {\n if (extname(entry.name) !== \".yml\" && extname(entry.name) !== \".yaml\") continue;\n if (!schemaFor(rel)) continue;\n }\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 warnings: Finding[],\n notes: Set<string>\n): Finding[] | SkipCode {\n const schema = schemaFor(rel);\n const manifest = isAppManifest(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 && !manifest) return KIND_UNKNOWN;\n const validate = schema ? compiled.get(schema) : undefined;\n if (schema && !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 // The manifest arm, past the same filesystem guards: `validate` is undefined\n // here only when `schema` was, which the guard above allows for `oxy-app.json`.\n if (!validate) return validateAppManifest(root, rel, warnings, notes);\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] ?? \"\") && !isAppManifest(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), APP_MANIFEST].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 warnings: Finding[] = [];\n const notes = new Set<string>();\n const checked: string[] = [];\n const unchecked: SkippedFile<SkipCode>[] = [];\n for (const rel of files) {\n const result = validateFile(root, rel, compiled, warnings, notes);\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 reportWarnings(warnings);\n reportNotes(notes);\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 reportWarnings(warnings);\n reportNotes(notes);\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 * An `oxy-app.json`: where its data goes, and what its functions call — not\n * its schema.\n *\n * Errors come back as findings and fail the run like a schema violation;\n * warnings are collected for `reportWarnings` and do not. Unparsable JSON is a\n * `(parse)` finding, the YAML arm's rule — not the throw `readAppManifest`\n * makes, which would end the walk at the first broken manifest.\n *\n * The function lint runs beside the placement check on the same manifest. Its\n * offline half — capabilities, isolate globals, the `destinations` allowlist —\n * is answered here; the half that needs the database's engine is `publish`'s,\n * and `notes` says so once, rather than reporting a clean run as complete.\n */\nfunction validateAppManifest(\n root: string,\n rel: string,\n warnings: Finding[],\n notes: Set<string>\n): Finding[] {\n const full = join(root, rel);\n let parsed: unknown;\n try {\n parsed = JSON.parse(readFileSync(full, \"utf8\"));\n } catch (cause) {\n return [{ file: rel, path: \"(parse)\", message: (cause as Error).message.split(\"\\n\")[0] ?? \"\" }];\n }\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n return [{ file: rel, path: \"(root)\", message: \"the top level must be an object\" }];\n }\n const manifest = parsed as Record<string, unknown>;\n const appDir = dirname(full);\n // `publish`'s order, minus the flags and env it has and this does not.\n const slug =\n typeof manifest.slug === \"string\" && manifest.slug.trim()\n ? manifest.slug\n : inferOrgApp(appDir).app;\n\n const prefix = dirname(rel) === \".\" ? \"\" : `${dirname(rel)}/`;\n const findings: Finding[] = [];\n for (const issue of checkAppPlacement(appDir, manifest, slug)) {\n const finding = { file: `${prefix}${issue.file}`, path: issue.path, message: issue.message };\n (issue.level === \"error\" ? findings : warnings).push(finding);\n }\n\n const lint = lintAppFunctions(appDir, manifest);\n for (const issue of lint.issues) {\n findings.push({\n file: `${prefix}${issue.file}`,\n path: issue.path,\n message: `[function-lint/${issue.rule}] ${issue.message}`\n });\n }\n for (const line of lint.skipped) notes.add(`${prefix}${APP_MANIFEST}: ${line}`);\n if (lint.writes.length > 0) {\n notes.add(\n `${prefix}${APP_MANIFEST}: the engine half of the function lint (\\`upsert\\` and ` +\n \"`ctx.tx` dialects, customer-warehouse writes) needs the server and is skipped offline — \" +\n \"`oxyc publish` runs it before the upload\"\n );\n }\n return findings;\n}\n\n/**\n * Warnings from the manifest checks: printed, never counted as problems.\n *\n * On stderr in both modes, the channel every other warning here takes, so\n * `--json` keeps one document on stdout and its shape does not move.\n */\nfunction reportWarnings(warnings: Finding[]): void {\n for (const w of warnings) log.warn(`${w.file} (${w.path}): ${w.message}`);\n}\n\n/**\n * What the function lint did NOT do, once each.\n *\n * `info`, not `warn`: a skipped engine check is the ordinary offline case, not\n * a degraded run — but it is said, because a clean `validate` on a function\n * that upserts into ClickHouse is not a clean publish.\n */\nfunction reportNotes(notes: Set<string>): void {\n for (const note of notes) log.info(note);\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 { loadForTargetResolution, 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\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 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 // Read here rather than up front: a broken oxy-app.json is an error, and\n // it must not fail a command that never resolves a target (`oxyc list`).\n const manifest = loadForTargetResolution(cwd, flags.target);\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 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 { runChecks } from \"./commands/checks.js\";\nimport { runList, runPath } from \"./commands/customers.js\";\nimport { runOpenApi, runRoutes, runSchema } from \"./commands/discover.js\";\nimport { runGuide } from \"./commands/guide.js\";\nimport { runInitCi } from \"./commands/init-ci.js\";\nimport { runLaunch } from \"./commands/launch.js\";\nimport { runOltpProvision, runOltpStatus } from \"./commands/oltp.js\";\nimport { runProxy } from \"./commands/proxy.js\";\nimport { runPublish } from \"./commands/publish.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 { VERSION } from \"./generated/version.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 the Rust `oxy login`\n * accepted 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 // From `package.json`, via `scripts/emit-version.mjs`. It was a literal, so\n // `oxyc --version` was a second copy of the version that a release bump did\n // not touch — worst for the standalone binary, where `--version` is the\n // only way to tell what you have.\n .version(VERSION)\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 the matching endpoints as a JSON array\")\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, as the Rust `oxy login`'s `--env` was. 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. Checked here because this is\n // 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 — --org takes a slug, a UUID, or an org URL\")\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 // Both together refuse. Silently preferring one is the wrong call when\n // the verb is destructive: a caller who typed both meant something, and\n // 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 const oltp = program\n .command(\"oltp\")\n .description(\"an org's OLTP database (ctx.oltp) — status, and provisioning, for staff\");\n\n withGlobals(\n oltp\n .command(\"status\")\n .description(\"every org's OLTP state — or, with --org, one org's store and writers\")\n .option(\"--json\", \"emit the server's response\")\n ).action(async (opts: Record<string, unknown>) => {\n await runOltpStatus(\n createContext(globals(opts)),\n opts.org as string | undefined,\n Boolean(opts.json)\n );\n });\n\n withGlobals(\n oltp\n .command(\"provision\")\n .description(\"create or reconcile an org's OLTP database and writers — a billable resource\")\n // `--org` comes from `withGlobals`, as it does for `assume`.\n .option(\"--writer <app:slug|pipeline:source>\", \"a writer to ensure (repeatable)\", collect, [])\n .option(\"--yes\", \"provision without asking\")\n .option(\"--json\", \"emit the server's response\")\n ).action(async (opts: Record<string, unknown>) => {\n await runOltpProvision(\n createContext(globals(opts)),\n opts.org as string | undefined,\n opts.writer as string[],\n { yes: opts.yes as boolean | undefined, json: opts.json as boolean | undefined }\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 const checks = program\n .command(\"checks\")\n .description('run an app\\'s checks (functions marked \"check\": true)');\n withGlobals(\n checks\n .command(\"run <app>\")\n .description(\"run every check of <org>/<app> (or an app id) and wait for results\")\n .option(\"--json\", \"emit results as JSON\")\n .option(\"--timeout <seconds>\", \"per-check timeout\", \"300\")\n ).action(async (app: string, opts: Record<string, unknown>) => {\n await runChecks(createContext(globals(opts)), app, {\n json: Boolean(opts.json),\n timeoutSeconds: Number(opts.timeout)\n });\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 the customers as a JSON array\")\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: side-effecting calls are HELD, tracking events are\\n\" +\n \"DROPPED, auth endpoints reach the backend unauthenticated so sign-in works, and\\n\" +\n \"the cached token is a fallback that never overrides a real browser session.\\n\" +\n \"\\nEach Oxy Function call prints `↳ <status> fn <name> request_id=… trace_id=…`.\\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 withGlobals(\n program\n .command(\"publish\")\n .description(\"build a custom app and publish its bundle (a draft, unless --promote)\")\n .option(\n \"--app <slug>\",\n \"app slug (default: OXY_APP, then oxy-app.json slug, then apps/<org>/<app>/)\"\n )\n .option(\"--build-id <id>\", \"unique per publish (default: the CI run, else random)\")\n .option(\"--dir <path>\", \"publish this pre-built directory instead of running the build\")\n .option(\"--promote\", \"publish straight to the live channel\")\n .option(\"--name <name>\", \"display name override for the app\")\n .option(\"--repo <url>\", \"git remote to record (default: the checkout's origin)\")\n .option(\"--commit <sha>\", \"commit to record (default: HEAD, or GITHUB_SHA)\")\n .option(\"--branch <name>\", \"branch to record (default: the checkout's, or GITHUB_REF_NAME)\")\n .option(\"--build-only\", \"build and bundle functions, then stop — no credential needed\")\n .option(\n \"--prebuilt\",\n \"with --dir: its functions are already bundled; check them, don't rebuild\"\n )\n .option(\"--json\", \"print the server's result as JSON\")\n .option(\n \"--allow-function-lint\",\n \"publish past an Oxy Function lint finding; each prints as a warning naming its rule\"\n )\n .addHelpText(\n \"after\",\n \"\\n--org takes a slug or a UUID (default: OXY_ORG, then oxy-app.json orgSlug, then\\n\" +\n \"the apps/<org>/<app>/ directory). --project pins the workspace; otherwise it is\\n\" +\n \"resolved from the target. .env.local and .env are loaded without overriding.\\n\" +\n \"\\nAuth: the --token-env variable, then `oxyc login`'s cache — or, in a GitHub\\n\" +\n \"Actions job with `id-token: write` and neither, trusted publishing via OIDC.\\n\" +\n \"\\nBefore the build, each Oxy Function's source is linted for what the host refuses\\n\" +\n \"at the first call: a `ctx.*` call whose capability the manifest lacks, a global\\n\" +\n \"the isolate does not have (Buffer, TextEncoder, process, …), a write outside\\n\" +\n \"`destinations`; before the upload, with the target's database list, an `upsert`\\n\" +\n \"or `ctx.tx` on an engine that refuses it and a customer-warehouse write with no\\n\" +\n \"`customerWarehouseWrites` reason. `--allow-function-lint` is the way past a\\n\" +\n \"false positive — please open an issue naming the rule.\\n\"\n )\n ).action(async (opts: Record<string, unknown>) => {\n await runPublish(createContext(globals(opts)), {\n app: opts.app as string | undefined,\n buildId: opts.buildId as string | undefined,\n dir: opts.dir as string | undefined,\n promote: opts.promote as boolean | undefined,\n name: opts.name as string | undefined,\n repo: opts.repo as string | undefined,\n commit: opts.commit as string | undefined,\n branch: opts.branch as string | undefined,\n buildOnly: opts.buildOnly as boolean | undefined,\n prebuilt: opts.prebuilt as boolean | undefined,\n json: opts.json as boolean | undefined,\n allowFunctionLint: opts.allowFunctionLint as boolean | undefined\n });\n });\n\n withGlobals(\n program\n .command(\"init-ci\")\n .description(\n \"write a GitHub Actions workflow that publishes this app with trusted publishing\"\n )\n .option(\"--app <org/app>\", \"the app to publish (default: this directory's oxy-app.json)\")\n .option(\"--environment <name>\", \"GitHub environment the publish job runs in\", \"oxy-publish\")\n .option(\"--force\", \"overwrite an existing workflow\")\n .option(\n \"--promote\",\n \"publish straight to the live channel, and verify it with the app's checks\"\n )\n ).action((opts: Record<string, unknown>) => {\n runInitCi(createContext(globals(opts)), {\n app: opts.app as string | undefined,\n environment: opts.environment as string | undefined,\n force: opts.force as boolean | undefined,\n promote: opts.promote as boolean | undefined\n });\n });\n\n program\n .command(\"validate\")\n .description(\"check a workspace's YAML against the schemas, and oxy-app.json's data placement\")\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 \"\\nEach oxy-app.json is checked for where its data goes: customerWarehouseWrites,\\n\" +\n \"airhouse, airhouseMigrations (DuckLake-safe, schema-qualified SQL) and secrets\\n\" +\n \"used as state. Its functions' sources are linted for a `ctx.*` call whose\\n\" +\n \"capability the manifest lacks, a global the isolate does not have (Buffer,\\n\" +\n \"TextEncoder, process, …) and a write outside `destinations`; the engine half\\n\" +\n \"(upsert / ctx.tx dialect, customer-warehouse writes) needs the server and runs\\n\" +\n \"in `oxyc publish`. Warnings go to stderr; the server is the authority.\\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\n9 a check ran and failed or timed out (\\`oxyc checks run\\`)\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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"}