@toon-protocol/rig 4.5.0 → 4.7.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.
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/objects.ts","../src/repo-reader.ts","../src/object-fetch.ts","../src/read-pipeline.ts","../src/materialize.ts","../src/npub.ts","../src/routes.ts","../src/push.ts","../src/ci/nip-c1-events.ts","../src/ci/secrets.ts","../src/ci/trust.ts","../src/ci/workflows.ts","../src/cli/daemon-session.ts","../src/cli/errors.ts","../src/cli/ci-status.ts","../src/cli/git-config.ts","../src/cli/remote.ts"],"sourcesContent":["/**\n * Pure git object construction and SHA-1 envelope hashing.\n *\n * Promoted from `packages/rig-web/tests/e2e/seed/lib/git-builder.ts` (#223) —\n * the proven seed pipeline builders, now the core of the Git-to-TOON write\n * path. Everything here is pure: no network, no signing, no payments.\n * Upload/publish lives with the Publisher (#226).\n *\n * Git object format: `<type> <size>\\0<content>`. The SHA-1 is computed over\n * the full envelope (header + NUL + content); the `body` (content only) is\n * what gets uploaded to Arweave.\n */\n\nimport { createHash } from 'node:crypto';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** All git object types TOON can carry. */\nexport type GitObjectType = 'blob' | 'tree' | 'commit' | 'tag';\n\nexport interface GitObject {\n /** SHA-1 hex digest computed over full git envelope */\n sha: string;\n /** Full git object (header + null + content) */\n buffer: Buffer;\n /** Body only (content after the null byte) — this is what gets uploaded */\n body: Buffer;\n}\n\n/**\n * The storage upstream's FREE per-item ceiling, in bytes.\n *\n * Read live from `https://upload.ardrive.io/`, which publishes it twice and\n * agreeing (2026-09-06):\n *\n * { \"freeUploadLimitBytes\": 107520,\n * \"freeTier\": { \"maxItemBytes\": 107520, ... } }\n *\n * The old value was `95 * 1024` (97,280) described as a \"95KB safety margin\n * under the 100KB free tier\". The service publishes no 100KB limit — the\n * figure was never upstream's — so the margin refused ~10 KiB of objects the\n * upstream would have taken for free (#102).\n *\n * This is a PRICING boundary, not a cap. An object at or under it rides the\n * free tier; a larger one is uploaded and PAID FOR through the store route's\n * per-KiB schedule (ADR 0065) — `g.toon.relay.store` advertises\n * `{price: \"1001\", pricePerKib: \"10\"}`, and that per-KiB term exists precisely\n * because size costs the serving node money. Nothing rejects on size.\n */\nexport const FREE_TIER_MAX_ITEM_BYTES = 107_520;\n\n/**\n * @deprecated Renamed to {@link FREE_TIER_MAX_ITEM_BYTES}, and no longer a\n * maximum: objects above it upload as paid writes rather than erroring. Kept\n * as an alias so the 4.x export keeps resolving.\n */\nexport const MAX_OBJECT_SIZE = FREE_TIER_MAX_ITEM_BYTES;\n\n/**\n * Git's universal empty-blob SHA-1: the object for a zero-byte file.\n *\n * It is the ONLY zero-byte object git can produce (trees, commits, and tags\n * are never empty) and it always has this exact constant value. The store\n * rejects a zero-byte kind:5094 blob upload as malformed (F00), so `rig` never\n * uploads this object — it is skipped on push and synthesized locally on\n * clone/fetch (both keyed off an ACTUAL zero-length body, never a heuristic).\n */\nexport const EMPTY_BLOB_SHA = 'e69de29bb2d1d6434b8b29ae775ad8c2e48c5391';\n\n// ---------------------------------------------------------------------------\n// Envelope hashing\n// ---------------------------------------------------------------------------\n\n/**\n * Wrap a raw object body in the git envelope (`<type> <size>\\0`) and compute\n * its SHA-1. This is exactly what `git hash-object -t <type>` does.\n */\nexport function hashGitObject(type: GitObjectType, body: Buffer): GitObject {\n const header = Buffer.from(`${type} ${body.length}\\0`);\n const fullObject = Buffer.concat([header, body]);\n const sha = createHash('sha1').update(fullObject).digest('hex');\n return { sha, buffer: fullObject, body };\n}\n\n// ---------------------------------------------------------------------------\n// Git object construction\n// ---------------------------------------------------------------------------\n\n/**\n * Construct a git blob object and compute its SHA-1.\n *\n * Format: blob <size>\\0<content>\n * SHA is over the full envelope; body is content only (for upload).\n */\nexport function createGitBlob(content: string): GitObject {\n return hashGitObject('blob', Buffer.from(content, 'utf-8'));\n}\n\n/**\n * Construct a git tree object from sorted entries.\n *\n * Format: tree <size>\\0<entries>\n * Each entry: <mode> <name>\\0<20-byte-raw-sha1>\n * Entries MUST be sorted by name (byte-wise).\n */\nexport function createGitTree(\n entries: { mode: string; name: string; sha: string }[]\n): GitObject {\n // Git sorts tree entries by raw byte order (NOT locale-aware)\n const sorted = [...entries].sort((a, b) =>\n a.name < b.name ? -1 : a.name > b.name ? 1 : 0\n );\n\n const entryBuffers: Buffer[] = [];\n for (const entry of sorted) {\n const modeAndName = Buffer.from(`${entry.mode} ${entry.name}\\0`);\n // Raw 20-byte SHA-1 (NOT hex)\n const rawSha = Buffer.from(entry.sha, 'hex');\n entryBuffers.push(Buffer.concat([modeAndName, rawSha]));\n }\n\n return hashGitObject('tree', Buffer.concat(entryBuffers));\n}\n\n/**\n * Construct a git commit object.\n *\n * Format: commit <size>\\0tree <tree-sha>\\n[parent ...]\\nauthor ...\\ncommitter ...\\n\\n<message>\n * Tree/parent SHAs are hex-encoded (40 chars) in commits, unlike tree entries.\n */\nexport function createGitCommit(opts: {\n treeSha: string;\n parentSha?: string;\n authorName: string;\n authorPubkey: string;\n message: string;\n timestamp: number;\n}): GitObject {\n const lines = [\n `tree ${opts.treeSha}`,\n ...(opts.parentSha ? [`parent ${opts.parentSha}`] : []),\n `author ${opts.authorName} <${opts.authorPubkey}@nostr> ${opts.timestamp} +0000`,\n `committer ${opts.authorName} <${opts.authorPubkey}@nostr> ${opts.timestamp} +0000`,\n '',\n opts.message,\n ];\n return hashGitObject('commit', Buffer.from(lines.join('\\n'), 'utf-8'));\n}\n\n/**\n * Construct an annotated git tag object.\n *\n * Format: tag <size>\\0object <sha>\\ntype <type>\\ntag <name>\\ntagger ...\\n\\n<message>\n * The tagged object is usually a commit, but git allows tagging any object\n * type (including another tag).\n */\nexport function createGitTag(opts: {\n /** SHA-1 of the object being tagged (hex, 40 chars) */\n objectSha: string;\n /** Type of the tagged object (usually 'commit') */\n objectType: GitObjectType;\n /** Tag name, e.g. 'v1.0.0' */\n tagName: string;\n taggerName: string;\n taggerPubkey: string;\n message: string;\n timestamp: number;\n}): GitObject {\n const lines = [\n `object ${opts.objectSha}`,\n `type ${opts.objectType}`,\n `tag ${opts.tagName}`,\n `tagger ${opts.taggerName} <${opts.taggerPubkey}@nostr> ${opts.timestamp} +0000`,\n '',\n opts.message,\n ];\n return hashGitObject('tag', Buffer.from(lines.join('\\n'), 'utf-8'));\n}\n","/**\n * GitRepoReader — read a local repository via `execFile` git plumbing.\n *\n * Real git gives perfect fidelity (packfiles, delta chains, exotic history)\n * with zero new deps — no isomorphic-git. Everything here is read-only and\n * injection-safe:\n *\n * - child processes are spawned with `execFile`/`spawn` and argument\n * ARRAYS — never a shell, never string interpolation;\n * - every caller-supplied revision/range is validated against strict\n * regexes that (among other things) reject a leading `-`, so a value\n * like `--upload-pack=…` can never be parsed as an option;\n * - `--` terminators are appended where git supports them so nothing\n * user-supplied can be re-interpreted as a pathspec.\n *\n * Push planning/publishing live in follow-up tickets of epic\n * toon-client#222 — this module only reads.\n */\n\nimport { execFile, spawn } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport type { GitObjectType } from './objects.js';\n\nconst execFileAsync = promisify(execFile);\n\n/** Generous cap for plumbing stdout (rev-list on big repos, format-patch). */\nconst MAX_BUFFER = 256 * 1024 * 1024;\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** A single ref from `git for-each-ref` (branches + tags). */\nexport interface GitRef {\n /** Full refname, e.g. `refs/heads/main` or `refs/tags/v1.0.0`. */\n refname: string;\n /**\n * SHA the ref points at. For annotated tags this is the TAG object's SHA\n * (the peeled commit is in {@link peeledSha}); for branches and\n * lightweight tags it is the commit SHA.\n */\n sha: string;\n /** Type of the referenced object: `commit`, or `tag` for annotated tags. */\n type: GitObjectType;\n /** For annotated tags: the peeled (target) object SHA. */\n peeledSha?: string;\n}\n\n/** Result of {@link GitRepoReader.listRefs}. */\nexport interface RepoRefs {\n /**\n * Full refname HEAD points at (e.g. `refs/heads/main`), or `undefined`\n * when HEAD is detached.\n */\n head?: string;\n refs: GitRef[];\n}\n\n/** One object streamed out of `git cat-file --batch`. */\nexport interface ReadGitObject {\n /** Full 40-hex SHA-1. */\n sha: string;\n type: GitObjectType;\n /** Raw object body (content only, no envelope header). May be binary. */\n body: Buffer;\n}\n\n/** Result of {@link GitRepoReader.readObjects}. */\nexport interface ReadObjectsResult {\n /** Objects found, in input order (minus missing ones). */\n objects: ReadGitObject[];\n /** Requested SHAs not present in the repository. */\n missing: string[];\n}\n\n/** One object from `rev-list --objects`: SHA plus the path it was reached by. */\nexport interface ObjectWithPath {\n /** Full 40-hex SHA-1. */\n sha: string;\n /**\n * Path the object was first reached by (blobs and non-root trees);\n * `undefined` for commits, root trees, and tag objects.\n */\n path?: string;\n}\n\n/** One object's metadata from `cat-file --batch-check`. */\nexport interface ObjectStat {\n sha: string;\n type: GitObjectType;\n /** Object body size in bytes (content only, no envelope header). */\n size: number;\n}\n\n/** Result of {@link GitRepoReader.statObjects}. */\nexport interface StatObjectsResult {\n /** Stats found, in input order (minus missing ones). */\n objects: ObjectStat[];\n /** Requested SHAs not present in the repository. */\n missing: string[];\n}\n\n/** Error from a git child process, carrying exit code and stderr. */\nexport class GitError extends Error {\n constructor(\n message: string,\n /** Process exit code (undefined when the process failed to spawn). */\n public readonly exitCode: number | undefined,\n /** Captured stderr, trimmed. */\n public readonly stderr: string\n ) {\n super(message);\n this.name = 'GitError';\n }\n}\n\n// ---------------------------------------------------------------------------\n// Argument validation (injection defense)\n// ---------------------------------------------------------------------------\n\n/** Full 40-hex SHA-1. */\nconst FULL_SHA_RE = /^[0-9a-f]{40}$/;\n\n/**\n * One revision token: a SHA prefix (4–40 hex) or a refname-ish word with an\n * optional `^`/`~<n>` ancestry suffix. Must start with an alphanumeric, so a\n * leading `-` (option injection) is impossible; `@{…}`, whitespace, and other\n * revspec exotica are deliberately rejected.\n */\nconst REV_TOKEN_RE = /^[A-Za-z0-9][A-Za-z0-9._/-]*(?:[~^][0-9]*)*$/;\n\nfunction isValidRevision(rev: string): boolean {\n if (rev.length === 0 || rev.length > 1024) return false;\n if (!REV_TOKEN_RE.test(rev)) return false;\n // Refname rules git enforces that our charset alone doesn't:\n if (rev.includes('..')) return false; // range separator / invalid in refnames\n if (rev.endsWith('.lock') || rev.endsWith('/') || rev.endsWith('.')) return false;\n return true;\n}\n\nfunction assertRevision(rev: string, what: string): void {\n if (!isValidRevision(rev)) {\n throw new Error(\n `${what} is not a valid git revision (got ${JSON.stringify(rev)}); ` +\n 'expected a SHA or simple refname — options/ranges are rejected'\n );\n }\n}\n\nfunction assertFullSha(sha: string, what: string): void {\n if (!FULL_SHA_RE.test(sha)) {\n throw new Error(\n `${what} is not a full 40-hex SHA-1 (got ${JSON.stringify(sha)})`\n );\n }\n}\n\n/**\n * A revision range for format-patch: `<rev>`, `<rev>..<rev>`, or\n * `<rev>...<rev>` where each side passes {@link isValidRevision}.\n */\nfunction assertRange(range: string, what: string): void {\n const parts = range.split(/\\.{2,3}/);\n const separators = range.match(/\\.{2,3}/g) ?? [];\n const ok =\n parts.length <= 2 &&\n separators.length === parts.length - 1 &&\n parts.every((p) => isValidRevision(p));\n if (!ok) {\n throw new Error(\n `${what} is not a valid revision range (got ${JSON.stringify(range)}); ` +\n 'expected <rev>, <rev>..<rev>, or <rev>...<rev>'\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// cat-file --batch incremental parser\n// ---------------------------------------------------------------------------\n\nconst OBJECT_TYPES: ReadonlySet<string> = new Set(['blob', 'tree', 'commit', 'tag']);\n\n/**\n * Incremental parser for `git cat-file --batch` output:\n * `<sha> <type> <size>\\n<body>\\n` per found object, `<name> missing\\n` for\n * absent ones. Bodies are raw bytes (possibly binary) and may be split\n * across arbitrary chunk boundaries, so parsing is strictly size-driven.\n */\nclass BatchParser {\n private buf: Buffer = Buffer.alloc(0);\n private pending: { sha: string; type: GitObjectType; size: number } | null = null;\n\n readonly objects: ReadGitObject[] = [];\n readonly missing: string[] = [];\n\n push(chunk: Buffer): void {\n this.buf = this.buf.length === 0 ? chunk : Buffer.concat([this.buf, chunk]);\n this.drain();\n }\n\n /** True when no partially-parsed record remains. */\n isComplete(): boolean {\n return this.pending === null && this.buf.length === 0;\n }\n\n private drain(): void {\n for (;;) {\n if (this.pending) {\n // Need body + trailing LF before the record is complete.\n const needed = this.pending.size + 1;\n if (this.buf.length < needed) return;\n const body = Buffer.from(this.buf.subarray(0, this.pending.size));\n this.objects.push({ sha: this.pending.sha, type: this.pending.type, body });\n this.buf = this.buf.subarray(needed);\n this.pending = null;\n continue;\n }\n\n const nl = this.buf.indexOf(0x0a);\n if (nl === -1) return;\n const header = this.buf.subarray(0, nl).toString('utf-8');\n this.buf = this.buf.subarray(nl + 1);\n\n const [name, second, third] = header.split(' ');\n if (name && second === 'missing' && third === undefined) {\n this.missing.push(name);\n continue;\n }\n if (name && second && third !== undefined && OBJECT_TYPES.has(second)) {\n const size = Number.parseInt(third, 10);\n if (Number.isSafeInteger(size) && size >= 0) {\n this.pending = { sha: name, type: second as GitObjectType, size };\n continue;\n }\n }\n throw new GitError(\n `unexpected cat-file --batch header: ${JSON.stringify(header)}`,\n undefined,\n ''\n );\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// GitRepoReader\n// ---------------------------------------------------------------------------\n\n/**\n * Read-only view of a local git repository via git plumbing commands.\n *\n * All methods throw {@link GitError} when the underlying git process fails\n * unexpectedly, and plain `Error` when a caller-supplied argument fails\n * validation (before any process is spawned).\n */\nexport class GitRepoReader {\n constructor(\n /** Absolute or relative path to the repository worktree (or .git dir). */\n public readonly repoPath: string\n ) {}\n\n /** Run git with argument-array safety; resolves stdout as UTF-8. */\n private async git(\n args: string[],\n opts: { allowExitCodes?: number[] } = {}\n ): Promise<{ stdout: string; exitCode: number }> {\n try {\n const { stdout } = await execFileAsync('git', args, {\n cwd: this.repoPath,\n maxBuffer: MAX_BUFFER,\n encoding: 'utf-8',\n });\n return { stdout, exitCode: 0 };\n } catch (err) {\n const e = err as NodeJS.ErrnoException & {\n code?: number | string;\n stdout?: string;\n stderr?: string;\n };\n const exitCode = typeof e.code === 'number' ? e.code : undefined;\n if (exitCode !== undefined && opts.allowExitCodes?.includes(exitCode)) {\n return { stdout: e.stdout ?? '', exitCode };\n }\n throw new GitError(\n `git ${args[0]} failed${exitCode !== undefined ? ` (exit ${exitCode})` : ''}: ` +\n `${(e.stderr ?? e.message ?? '').trim()}`,\n exitCode,\n (e.stderr ?? '').trim()\n );\n }\n }\n\n /**\n * List all branches and tags plus the symbolic HEAD.\n *\n * Annotated tags report the tag object's SHA/type with the peeled target\n * in `peeledSha`. A detached HEAD is tolerated (`head` is `undefined`).\n */\n async listRefs(): Promise<RepoRefs> {\n const format = '%(refname)%00%(objectname)%00%(objecttype)%00%(*objectname)';\n const [refsRes, headRes] = await Promise.all([\n this.git(['for-each-ref', `--format=${format}`, 'refs/heads', 'refs/tags']),\n // Exit 1 = detached HEAD (or unborn branch pointer oddities) — tolerated.\n this.git(['symbolic-ref', '--quiet', 'HEAD'], { allowExitCodes: [1] }),\n ]);\n\n const refs: GitRef[] = [];\n for (const line of refsRes.stdout.split('\\n')) {\n if (!line) continue;\n const [refname, sha, objecttype, peeled] = line.split('\\0');\n if (!refname || !sha || !objecttype || !OBJECT_TYPES.has(objecttype)) {\n throw new GitError(`unexpected for-each-ref line: ${JSON.stringify(line)}`, undefined, '');\n }\n refs.push({\n refname,\n sha,\n type: objecttype as GitObjectType,\n ...(peeled ? { peeledSha: peeled } : {}),\n });\n }\n\n const head = headRes.exitCode === 0 ? headRes.stdout.trim() || undefined : undefined;\n return { head, refs };\n }\n\n /**\n * SHAs of every object reachable from `want` but not from `have`\n * (`git rev-list --objects <want…> --not <have…>`), i.e. the push delta.\n *\n * Haves that don't exist locally (e.g. remote tips we never fetched) are\n * filtered out first via one `cat-file --batch-check` pass — rev-list\n * would otherwise die on them.\n */\n async objectsBetween(want: string[], have: string[]): Promise<string[]> {\n const objects = await this.objectsBetweenWithPaths(want, have);\n return objects.map((o) => o.sha);\n }\n\n /**\n * Like {@link objectsBetween} but keeps the path each object was reached\n * by (`rev-list --objects` emits `<sha> <path>` for blobs and non-root\n * trees) — used by push planning to report actionable oversize errors.\n */\n async objectsBetweenWithPaths(\n want: string[],\n have: string[]\n ): Promise<ObjectWithPath[]> {\n for (const w of want) assertRevision(w, 'want');\n for (const h of have) assertRevision(h, 'have');\n if (want.length === 0) return [];\n\n const knownHaves = await this.filterExisting(have);\n\n const args = ['rev-list', '--objects', ...want];\n if (knownHaves.length > 0) args.push('--not', ...knownHaves);\n args.push('--'); // nothing user-supplied can become a pathspec\n const { stdout } = await this.git(args);\n\n const objects: ObjectWithPath[] = [];\n for (const line of stdout.split('\\n')) {\n if (!line) continue;\n // `--objects` lines are `<sha>` or `<sha> <path>`.\n const spaceIdx = line.indexOf(' ');\n if (spaceIdx === -1) {\n objects.push({ sha: line });\n } else {\n const path = line.slice(spaceIdx + 1);\n objects.push({\n sha: line.slice(0, spaceIdx),\n ...(path ? { path } : {}),\n });\n }\n }\n return objects;\n }\n\n /**\n * List every blob (file) reachable from a ref's root tree, recursively,\n * with the path it is served at (#368: the ar.io site manifest join key).\n * Uses `git ls-tree -r -z` — NUL-terminated records so binary/spaced paths\n * survive verbatim, and no path quoting to undo. Submodule (`commit`)\n * gitlink entries and directories are excluded; only real file blobs remain.\n */\n async listBlobs(rev: string): Promise<{ path: string; sha: string }[]> {\n assertRevision(rev, 'ref');\n const { stdout } = await this.git(['ls-tree', '-r', '-z', rev, '--']);\n const blobs: { path: string; sha: string }[] = [];\n for (const record of stdout.split('\\0')) {\n if (!record) continue;\n // `<mode> SP <type> SP <sha> TAB <path>`\n const tab = record.indexOf('\\t');\n if (tab === -1) {\n throw new GitError(\n `unexpected ls-tree record: ${JSON.stringify(record)}`,\n undefined,\n ''\n );\n }\n const meta = record.slice(0, tab);\n const path = record.slice(tab + 1);\n const [, type, sha] = meta.split(' ');\n if (type !== 'blob') continue; // trees are flattened by -r; skip gitlinks\n if (!sha || !FULL_SHA_RE.test(sha)) {\n throw new GitError(\n `unexpected ls-tree object id: ${JSON.stringify(record)}`,\n undefined,\n ''\n );\n }\n blobs.push({ path, sha });\n }\n return blobs;\n }\n\n /** Run git feeding `input` on stdin; resolves collected stdout bytes. */\n private runWithStdin(args: string[], input: string): Promise<Buffer> {\n return new Promise<Buffer>((resolve, reject) => {\n const child = spawn('git', args, {\n cwd: this.repoPath,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n const out: Buffer[] = [];\n let stderr = '';\n child.stdout.on('data', (chunk: Buffer) => out.push(chunk));\n child.stderr.on('data', (chunk: Buffer) => {\n stderr += chunk.toString('utf-8');\n });\n child.on('error', (err) => {\n reject(new GitError(`failed to spawn git ${args[0]}: ${err.message}`, undefined, ''));\n });\n child.on('close', (code) => {\n if (code !== 0) {\n return reject(\n new GitError(`git ${args[0]} failed (exit ${code}): ${stderr.trim()}`, code ?? undefined, stderr.trim())\n );\n }\n resolve(Buffer.concat(out));\n });\n child.stdin.on('error', () => {\n // Child died before consuming stdin; 'close' surfaces the failure.\n });\n child.stdin.write(input);\n child.stdin.end();\n });\n }\n\n /** Of the given revisions, keep only those resolvable locally. */\n private async filterExisting(revs: string[]): Promise<string[]> {\n if (revs.length === 0) return [];\n const { missing } = await this.batchCheck(revs);\n const missingSet = new Set(missing);\n return revs.filter((r) => !missingSet.has(r));\n }\n\n /** One `cat-file --batch-check` pass; returns names reported missing. */\n private async batchCheck(names: string[]): Promise<{ missing: string[] }> {\n const stdout = await this.runWithStdin(\n ['cat-file', '--batch-check'],\n names.join('\\n') + '\\n'\n );\n const missing: string[] = [];\n for (const line of stdout.toString('utf-8').split('\\n')) {\n if (line.endsWith(' missing')) missing.push(line.slice(0, -' missing'.length));\n }\n return { missing };\n }\n\n /**\n * Object metadata (type + body size) for a batch of SHAs via one\n * `cat-file --batch-check` pass — no bodies are read. Missing objects are\n * reported, not thrown.\n */\n async statObjects(shas: string[]): Promise<StatObjectsResult> {\n for (const sha of shas) assertFullSha(sha, 'sha');\n if (shas.length === 0) return { objects: [], missing: [] };\n\n const stdout = await this.runWithStdin(\n ['cat-file', '--batch-check'],\n shas.join('\\n') + '\\n'\n );\n\n const objects: ObjectStat[] = [];\n const missing: string[] = [];\n for (const line of stdout.toString('utf-8').split('\\n')) {\n if (!line) continue;\n if (line.endsWith(' missing')) {\n missing.push(line.slice(0, -' missing'.length));\n continue;\n }\n const [sha, type, sizeStr] = line.split(' ');\n const size = Number.parseInt(sizeStr ?? '', 10);\n if (\n !sha ||\n !type ||\n !OBJECT_TYPES.has(type) ||\n !Number.isSafeInteger(size) ||\n size < 0\n ) {\n throw new GitError(\n `unexpected cat-file --batch-check line: ${JSON.stringify(line)}`,\n undefined,\n ''\n );\n }\n objects.push({ sha, type: type as GitObjectType, size });\n }\n return { objects, missing };\n }\n\n /**\n * Read raw object bodies via a single streaming `git cat-file --batch`\n * child process. Bodies may be binary and are parsed size-driven across\n * chunk boundaries. Missing objects are reported, not thrown.\n */\n async readObjects(shas: string[]): Promise<ReadObjectsResult> {\n for (const sha of shas) assertFullSha(sha, 'sha');\n if (shas.length === 0) return { objects: [], missing: [] };\n\n const parser = new BatchParser();\n await new Promise<void>((resolve, reject) => {\n const child = spawn('git', ['cat-file', '--batch'], {\n cwd: this.repoPath,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n let stderr = '';\n let parseError: Error | null = null;\n\n child.stderr.on('data', (chunk: Buffer) => {\n stderr += chunk.toString('utf-8');\n });\n child.stdout.on('data', (chunk: Buffer) => {\n if (parseError) return;\n try {\n parser.push(chunk);\n } catch (err) {\n parseError = err as Error;\n child.kill();\n }\n });\n child.on('error', (err) => {\n reject(new GitError(`failed to spawn git cat-file: ${err.message}`, undefined, ''));\n });\n child.on('close', (code) => {\n if (parseError) return reject(parseError);\n if (code !== 0) {\n return reject(\n new GitError(`git cat-file --batch failed (exit ${code}): ${stderr.trim()}`, code ?? undefined, stderr.trim())\n );\n }\n if (!parser.isComplete()) {\n return reject(\n new GitError('git cat-file --batch output ended mid-record', code ?? undefined, stderr.trim())\n );\n }\n resolve();\n });\n\n child.stdin.on('error', () => {\n // Child died before consuming stdin; 'close' will surface the error.\n });\n child.stdin.write(shas.join('\\n') + '\\n');\n child.stdin.end();\n });\n\n return { objects: parser.objects, missing: parser.missing };\n }\n\n /**\n * `git merge-base --is-ancestor <a> <b>` — true when `a` is an ancestor\n * of `b` (fast-forward check / force detection). Exit codes other than\n * 0/1 (e.g. unknown revisions) throw.\n */\n async isAncestor(a: string, b: string): Promise<boolean> {\n assertRevision(a, 'ancestor candidate');\n assertRevision(b, 'descendant candidate');\n const { exitCode } = await this.git(\n ['merge-base', '--is-ancestor', a, b],\n { allowExitCodes: [1] }\n );\n return exitCode === 0;\n }\n\n /**\n * `git format-patch --stdout <range>` — the full mbox-formatted patch\n * series text (empty string when the range selects no commits).\n */\n async formatPatch(range: string): Promise<string> {\n assertRange(range, 'range');\n const { stdout } = await this.git(['format-patch', '--stdout', range, '--']);\n return stdout;\n }\n\n /**\n * Parent SHAs for a batch of commit SHAs via one\n * `git rev-list --no-walk=unsorted --parents` pass. Root commits map to an\n * empty array. Used to derive the kind:1617 `commit`/`parent-commit` tag\n * pairs for exactly the commits a format-patch series carries.\n */\n async commitParents(shas: string[]): Promise<Map<string, string[]>> {\n for (const sha of shas) assertFullSha(sha, 'sha');\n if (shas.length === 0) return new Map();\n const { stdout } = await this.git([\n 'rev-list',\n '--no-walk=unsorted',\n '--parents',\n ...shas,\n '--',\n ]);\n const parents = new Map<string, string[]>();\n for (const line of stdout.split('\\n')) {\n if (!line) continue;\n const [sha, ...rest] = line.split(' ');\n if (!sha || !FULL_SHA_RE.test(sha) || rest.some((p) => !FULL_SHA_RE.test(p))) {\n throw new GitError(\n `unexpected rev-list --parents line: ${JSON.stringify(line)}`,\n undefined,\n ''\n );\n }\n parents.set(sha, rest);\n }\n return parents;\n }\n\n /**\n * Resolve a ref/revision to a full SHA via `git rev-parse --verify`.\n * Throws {@link GitError} when the name doesn't resolve.\n */\n async resolveRef(name: string): Promise<string> {\n assertRevision(name, 'ref name');\n const { stdout } = await this.git(['rev-parse', '--verify', '--quiet', name]);\n const sha = stdout.trim();\n if (!FULL_SHA_RE.test(sha)) {\n throw new GitError(\n `rev-parse --verify returned unexpected output for ${JSON.stringify(name)}: ${JSON.stringify(sha)}`,\n undefined,\n ''\n );\n }\n return sha;\n }\n}\n","/**\n * The Git-from-TOON READ pipeline core (#278): download git object bodies\n * from Arweave gateways, verify them against their SHA-1, and walk the\n * object graph to prove a ref closure is complete.\n *\n * This is the CLI counterpart of rig-web's proven browser read path\n * (`web/arweave-client.ts` + `web/git-objects.ts` + the commit walker) — the\n * logic is mirrored, not imported, because the SPA package is not a library.\n *\n * Everything here is FREE (reads only: Arweave gateway GETs + the GraphQL\n * Git-SHA resolver) and pure of git — materializing objects into a real\n * repository lives in ./materialize.ts.\n *\n * INTEGRITY IS NON-NEGOTIABLE: an Arweave upload stores the object BODY\n * (content after the envelope NUL). Re-wrapping the body as each of the four\n * git object types and comparing the envelope SHA-1 against the expected SHA\n * both AUTHENTICATES the bytes and DISCOVERS the object's type in one step —\n * a body that matches under no type is rejected as corrupt/tampered, never\n * written.\n */\n\nimport {\n ARWEAVE_FETCH_TIMEOUT_MS,\n ARWEAVE_GATEWAYS,\n isValidArweaveTxId,\n} from '@toon-protocol/arweave';\nimport { hashGitObject, type GitObjectType } from './objects.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** A downloaded git object: SHA-verified body + the type that verified it. */\nexport interface FetchedObject {\n /** Full 40-hex SHA-1 (verified against the body). */\n sha: string;\n type: GitObjectType;\n /** Raw object body (content only, no envelope header). May be binary. */\n body: Buffer;\n}\n\n/** WHATWG-fetch seam (injectable for tests). */\nexport type FetchLike = (\n url: string,\n init?: { signal?: AbortSignal }\n) => Promise<{\n ok: boolean;\n arrayBuffer(): Promise<ArrayBuffer>;\n}>;\n\nexport interface GatewayFetchOptions {\n /** Ordered gateway base URLs (default: the shared preference list). */\n gateways?: readonly string[];\n /** fetch implementation (default: global fetch). */\n fetchFn?: FetchLike;\n /** Per-request timeout in milliseconds. */\n timeoutMs?: number;\n}\n\nexport interface DownloadOptions extends GatewayFetchOptions {\n /** Maximum concurrent gateway downloads (default {@link DEFAULT_CONCURRENCY}). */\n concurrency?: number;\n /** Progress callback, called once per finished object. */\n onObject?: (done: number, total: number) => void;\n}\n\n/** Result of {@link downloadGitObjects}. */\nexport interface DownloadResult {\n /** SHA → verified object, for every SHA that could be downloaded. */\n objects: Map<string, FetchedObject>;\n /** SHAs whose txId 404'd/errored on EVERY gateway (propagation lag). */\n unavailable: { sha: string; txId: string }[];\n}\n\n/** Default parallel-download cap. */\nexport const DEFAULT_CONCURRENCY = 8;\n\n/**\n * A downloaded body did not hash to its expected SHA under ANY git object\n * type — corrupt or tampered content. The clone/fetch pipelines treat this\n * as a hard failure: nothing is written.\n */\nexport class ObjectIntegrityError extends Error {\n constructor(\n /** The objects that failed verification. */\n public readonly objects: { sha: string; txId: string }[]\n ) {\n super(\n `${objects.length} downloaded object(s) failed SHA-1 verification — ` +\n 'the gateway content does not match the announced git SHA(s): ' +\n objects.map((o) => `${o.sha} (tx ${o.txId})`).join(', ') +\n '. Refusing to write corrupt/tampered objects.'\n );\n this.name = 'ObjectIntegrityError';\n }\n}\n\n// ---------------------------------------------------------------------------\n// Verification (SHA check == type discovery)\n// ---------------------------------------------------------------------------\n\nconst OBJECT_TYPES: readonly GitObjectType[] = [\n 'blob',\n 'tree',\n 'commit',\n 'tag',\n];\n\n/**\n * Verify a downloaded body against its expected SHA-1 by trying the four git\n * envelope types. Returns the verified object, or null when no type matches\n * (corrupt/tampered bytes).\n */\nexport function verifyObjectBody(\n expectedSha: string,\n bytes: Uint8Array\n): FetchedObject | null {\n const body = Buffer.from(bytes);\n for (const type of OBJECT_TYPES) {\n if (hashGitObject(type, body).sha === expectedSha) {\n return { sha: expectedSha, type, body };\n }\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Gateway download (fallback chain, mirrors rig-web's fetchArweaveObject)\n// ---------------------------------------------------------------------------\n\n/**\n * Fetch raw bytes for an Arweave tx id, trying each gateway in preference\n * order. Returns null when every gateway fails (404 / error / timeout).\n */\nexport async function fetchTxBytes(\n txId: string,\n options: GatewayFetchOptions = {}\n): Promise<Uint8Array | null> {\n if (!isValidArweaveTxId(txId)) return null;\n const gateways = options.gateways ?? ARWEAVE_GATEWAYS;\n const fetchFn = options.fetchFn ?? (fetch as FetchLike);\n const timeoutMs = options.timeoutMs ?? ARWEAVE_FETCH_TIMEOUT_MS;\n\n for (const gateway of gateways) {\n try {\n const response = await fetchFn(`${gateway}/${txId}`, {\n signal: AbortSignal.timeout(timeoutMs),\n });\n if (!response.ok) continue;\n return new Uint8Array(await response.arrayBuffer());\n } catch {\n // Network error, timeout, or other failure — try the next gateway.\n }\n }\n return null;\n}\n\n/**\n * Download + verify a batch of git objects (sha → Arweave txId) with a\n * concurrency cap and per-gateway fallback.\n *\n * Objects that 404 on every gateway are reported in `unavailable` (Arweave\n * propagation lag — the caller decides whether that is fatal). Objects whose\n * bytes fail SHA-1 verification throw {@link ObjectIntegrityError}: corrupt\n * content is NEVER returned.\n */\nexport async function downloadGitObjects(\n entries: Iterable<[sha: string, txId: string]>,\n options: DownloadOptions = {}\n): Promise<DownloadResult> {\n const queue = [...entries];\n const total = queue.length;\n const concurrency = Math.max(1, options.concurrency ?? DEFAULT_CONCURRENCY);\n\n const objects = new Map<string, FetchedObject>();\n const unavailable: { sha: string; txId: string }[] = [];\n const corrupt: { sha: string; txId: string }[] = [];\n let done = 0;\n\n const worker = async (): Promise<void> => {\n for (;;) {\n const next = queue.shift();\n if (!next) return;\n const [sha, txId] = next;\n const bytes = await fetchTxBytes(txId, options);\n if (bytes === null) {\n unavailable.push({ sha, txId });\n } else {\n const verified = verifyObjectBody(sha, bytes);\n if (verified === null) {\n corrupt.push({ sha, txId });\n } else {\n objects.set(sha, verified);\n }\n }\n done += 1;\n options.onObject?.(done, total);\n }\n };\n\n await Promise.all(\n Array.from({ length: Math.min(concurrency, total) }, () => worker())\n );\n\n if (corrupt.length > 0) throw new ObjectIntegrityError(corrupt);\n return { objects, unavailable };\n}\n\n// ---------------------------------------------------------------------------\n// Object-graph references (mirrors rig-web's git-objects parsing)\n// ---------------------------------------------------------------------------\n\nconst FULL_SHA_RE = /^[0-9a-f]{40}$/;\n\n/** Submodule (gitlink) tree-entry mode: references a commit in ANOTHER repo. */\nconst GITLINK_MODE = '160000';\n\nfunction bytesToHex(bytes: Uint8Array): string {\n let hex = '';\n for (const byte of bytes) hex += byte.toString(16).padStart(2, '0');\n return hex;\n}\n\n/**\n * SHAs an object references inside the SAME repository:\n * - commit → its tree + parents\n * - tree → entry SHAs, EXCEPT gitlinks (mode 160000: submodule commits\n * live in another repository and are never present — git fsck\n * skips them too)\n * - tag → the tagged object\n * - blob → nothing\n */\nexport function referencedShas(object: FetchedObject): string[] {\n switch (object.type) {\n case 'blob':\n return [];\n case 'tree': {\n const refs: string[] = [];\n const data = object.body;\n let offset = 0;\n while (offset < data.length) {\n const spaceIdx = data.indexOf(0x20, offset);\n if (spaceIdx === -1) break;\n const mode = data.subarray(offset, spaceIdx).toString('utf-8');\n const nulIdx = data.indexOf(0x00, spaceIdx + 1);\n if (nulIdx === -1 || nulIdx + 21 > data.length) break;\n const sha = bytesToHex(data.subarray(nulIdx + 1, nulIdx + 21));\n if (mode !== GITLINK_MODE) refs.push(sha);\n offset = nulIdx + 21;\n }\n return refs;\n }\n case 'commit': {\n const refs: string[] = [];\n const text = object.body.toString('utf-8');\n const headerEnd = text.indexOf('\\n\\n');\n const header = headerEnd === -1 ? text : text.slice(0, headerEnd);\n for (const line of header.split('\\n')) {\n if (line.startsWith('tree ')) refs.push(line.slice(5).trim());\n else if (line.startsWith('parent ')) refs.push(line.slice(7).trim());\n }\n return refs.filter((sha) => FULL_SHA_RE.test(sha));\n }\n case 'tag': {\n const text = object.body.toString('utf-8');\n const match = /^object ([0-9a-f]{40})$/m.exec(text);\n return match?.[1] ? [match[1]] : [];\n }\n }\n}\n\n/** Result of {@link walkClosure}. */\nexport interface ClosureResult {\n /** Every SHA reachable from the tips that lives in `objects`. */\n reachable: Set<string>;\n /** Reachable SHAs found NEITHER in `objects` nor in `presentLocally`. */\n missing: string[];\n}\n\n/**\n * Walk the object graph from the ref tips over the downloaded object set and\n * report which reachable SHAs are missing. `presentLocally` marks SHAs that\n * already exist in the destination repository — the walk does not descend\n * into them (a consistent local repo carries its own closure; the same\n * assumption `git fetch` makes).\n */\nexport function walkClosure(\n tips: Iterable<string>,\n objects: ReadonlyMap<string, FetchedObject>,\n presentLocally: ReadonlySet<string> = new Set()\n): ClosureResult {\n const reachable = new Set<string>();\n const missing = new Set<string>();\n const stack = [...new Set(tips)];\n\n while (stack.length > 0) {\n const sha = stack.pop() as string;\n if (reachable.has(sha) || missing.has(sha)) continue;\n if (presentLocally.has(sha)) continue; // local closure assumed complete\n const object = objects.get(sha);\n if (!object) {\n missing.add(sha);\n continue;\n }\n reachable.add(sha);\n for (const ref of referencedShas(object)) {\n if (!reachable.has(ref) && !missing.has(ref)) stack.push(ref);\n }\n }\n\n return { reachable, missing: [...missing] };\n}\n","/**\n * The shared clone/fetch object-collection engine (#278).\n *\n * Given the remote's ref tips and its kind:30618 sha→Arweave-txId map, gather\n * every object the refs need:\n *\n * 1. download the mapped objects the destination repo doesn't already have\n * (parallel, gateway fallback chain, SHA-verified — ./object-fetch.ts);\n * 2. walk the object graph from the tips (./object-fetch.ts walkClosure) —\n * the local repository's objects count as present (git fetch's own\n * assumption: a consistent repo carries its own closure);\n * 3. SHAs the map doesn't cover are resolved through the Arweave GraphQL\n * Git-SHA resolver (RemoteState.resolveMissing) and downloaded, looping\n * until the closure is complete or no progress can be made.\n *\n * The result separates FATAL gaps (reachable objects that could not be\n * obtained — usually Arweave gateway propagation lag, 10–20 min for fresh\n * pushes) from harmless ones (mapped-but-unreachable objects, e.g. history\n * that was force-pushed away). Corrupt objects throw ObjectIntegrityError\n * from the download layer and never surface here.\n */\n\nimport {\n downloadGitObjects,\n walkClosure,\n type DownloadOptions,\n type FetchedObject,\n} from './object-fetch.js';\nimport { EMPTY_BLOB_SHA } from './objects.js';\n\n/** A reachable object that could not be obtained. */\nexport interface MissingObject {\n sha: string;\n /** The txId that failed on every gateway, or null when no txId resolved. */\n txId: string | null;\n}\n\nexport interface CollectRepoObjectsOptions extends DownloadOptions {\n /** Ref tip SHAs (commits or annotated tags) the closure must reach. */\n tips: string[];\n /** kind:30618 `arweave` tag map: git SHA → Arweave txId. */\n shaToTxId: ReadonlyMap<string, string>;\n /** GraphQL fallback for SHAs the map doesn't cover (RemoteState.resolveMissing). */\n resolveMissing: (shas: string[]) => Promise<Map<string, string>>;\n /** SHAs already present in the destination repository (fetch delta). */\n presentLocally?: ReadonlySet<string>;\n}\n\nexport interface CollectRepoObjectsResult {\n /** Verified objects to write, keyed by SHA. */\n objects: Map<string, FetchedObject>;\n /** Reachable SHAs that could not be obtained — FATAL for clone/fetch. */\n missing: MissingObject[];\n /** Mapped-but-unreachable SHAs that failed to download — warn only. */\n skippedUnavailable: { sha: string; txId: string }[];\n}\n\n/** Iteration cap: closure depth of NEW unmapped SHAs per pass; generous. */\nconst MAX_PASSES = 64;\n\n/** Collect (download + verify + close over) the objects the ref tips need. */\nexport async function collectRepoObjects(\n options: CollectRepoObjectsOptions\n): Promise<CollectRepoObjectsResult> {\n const { tips, shaToTxId, resolveMissing } = options;\n const present = options.presentLocally ?? new Set<string>();\n\n /** All txId knowledge: the 30618 map + GraphQL-resolved additions. */\n const txIds = new Map<string, string>(shaToTxId);\n /** SHAs we already asked the GraphQL resolver about (avoid re-queries). */\n const resolverAsked = new Set<string>();\n /** SHAs whose download failed on every gateway. */\n const undownloadable = new Map<string, string>();\n const objects = new Map<string, FetchedObject>();\n\n // Pass 0: bulk-download everything the map covers that isn't local yet.\n const initial: [string, string][] = [];\n for (const [sha, txId] of txIds) {\n if (!present.has(sha)) initial.push([sha, txId]);\n }\n const bulk = await downloadGitObjects(initial, options);\n for (const [sha, object] of bulk.objects) objects.set(sha, object);\n for (const { sha, txId } of bulk.unavailable) undownloadable.set(sha, txId);\n\n // Iterate: close over the tips; resolve + download whatever is still open.\n for (let pass = 0; pass < MAX_PASSES; pass++) {\n const closure = walkClosure(tips, objects, present);\n const open = closure.missing.filter((sha) => !undownloadable.has(sha));\n if (open.length === 0) break;\n\n // Resolve txIds for open SHAs we haven't asked the resolver about.\n const toResolve = open.filter(\n (sha) => !txIds.has(sha) && !resolverAsked.has(sha)\n );\n for (const sha of toResolve) resolverAsked.add(sha);\n if (toResolve.length > 0) {\n const resolved = await resolveMissing(toResolve);\n for (const [sha, txId] of resolved) txIds.set(sha, txId);\n }\n\n // Download open SHAs that now have a txId and no failed attempt yet.\n const batch: [string, string][] = [];\n for (const sha of open) {\n const txId = txIds.get(sha);\n if (txId !== undefined && !objects.has(sha)) batch.push([sha, txId]);\n }\n if (batch.length === 0) break; // no progress possible\n const result = await downloadGitObjects(batch, options);\n for (const [sha, object] of result.objects) objects.set(sha, object);\n for (const { sha, txId } of result.unavailable)\n undownloadable.set(sha, txId);\n if (result.objects.size === 0) break; // every attempt failed — stop\n }\n\n // The git empty blob is never uploaded (the store rejects zero-byte\n // content; `rig push` skips it), so a tree that references it reports it\n // \"missing\" here even though it is a git constant. Synthesize it locally —\n // a zero-byte blob body always hashes to EMPTY_BLOB_SHA — instead of\n // erroring, so an empty file reconstructs bit-identically (git fsck clean).\n // Keyed off the EXACT constant SHA: the honest lag-error still fires for any\n // genuinely-missing non-empty object.\n let finalClosure = walkClosure(tips, objects, present);\n if (\n finalClosure.missing.includes(EMPTY_BLOB_SHA) &&\n !present.has(EMPTY_BLOB_SHA)\n ) {\n objects.set(EMPTY_BLOB_SHA, {\n sha: EMPTY_BLOB_SHA,\n type: 'blob',\n body: Buffer.alloc(0),\n });\n finalClosure = walkClosure(tips, objects, present);\n }\n\n // Final accounting.\n const missing: MissingObject[] = finalClosure.missing.map((sha) => ({\n sha,\n txId: txIds.get(sha) ?? null,\n }));\n const reachable = finalClosure.reachable;\n const skippedUnavailable = [...undownloadable]\n .filter(\n ([sha]) => !reachable.has(sha) && !finalClosure.missing.includes(sha)\n )\n .map(([sha, txId]) => ({ sha, txId }));\n\n return { objects, missing, skippedUnavailable };\n}\n\n/**\n * The honest propagation-lag error text: which SHAs are unobtainable and why\n * retrying later is the expected remedy.\n */\nexport function missingObjectsMessage(\n missing: MissingObject[],\n context: string\n): string {\n const listed = missing\n .slice(0, 20)\n .map(\n (m) =>\n ` ${m.sha}${m.txId ? ` (tx ${m.txId})` : ' (no Arweave tx found)'}`\n )\n .join('\\n');\n const more =\n missing.length > 20 ? `\\n … and ${missing.length - 20} more` : '';\n return (\n `${context}: ${missing.length} required object(s) could not be downloaded:\\n` +\n `${listed}${more}\\n` +\n 'Recently pushed objects can take 10-20 minutes to become fetchable from ' +\n 'Arweave gateways — if this repo was just pushed, retry in a few minutes. ' +\n 'Nothing was written.'\n );\n}\n","/**\n * Materialize downloaded git objects into a REAL repository (#278).\n *\n * Objects are written through git's own plumbing — `git hash-object -w\n * --stdin -t <type>` with the raw body on stdin — so git computes, validates\n * (syntax checks for trees/commits/tags), stores (loose object + zlib), and\n * RETURNS the SHA. The returned SHA is compared against the expected one:\n * a second, independent integrity gate after ./object-fetch.ts's envelope\n * verification. Refs land via `git update-ref`, HEAD via `git symbolic-ref`.\n *\n * Same injection posture as GitRepoReader: child processes use\n * `execFile`/`spawn` with argument ARRAYS (never a shell), and refnames are\n * validated with `git check-ref-format` semantics before use.\n */\n\nimport { execFile, spawn } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport type { FetchedObject } from './object-fetch.js';\n\nconst execFileAsync = promisify(execFile);\n\n/** A written object's SHA disagreed with what `git hash-object` computed. */\nexport class ObjectWriteMismatchError extends Error {\n constructor(\n public readonly expectedSha: string,\n public readonly writtenSha: string\n ) {\n super(\n `git hash-object wrote ${writtenSha} where ${expectedSha} was expected — ` +\n 'object content does not round-trip; aborting'\n );\n this.name = 'ObjectWriteMismatchError';\n }\n}\n\n/** Full 40-hex SHA-1. */\nconst FULL_SHA_RE = /^[0-9a-f]{40}$/;\n\n/**\n * Conservative refname validation (superset-safe subset of\n * `git check-ref-format`): must start `refs/`, no component may start with\n * `-` or `.`, no `..`, no control/space/git-special characters, no trailing\n * `/`, `.`, or `.lock`. Rejecting odd-but-legal names is fine — these\n * refnames come from relay events, and a hostile relay must not be able to\n * smuggle options or path traversal into git invocations.\n */\nexport function isSafeRefname(refname: string): boolean {\n if (!refname.startsWith('refs/') || refname.length > 1024) return false;\n // eslint-disable-next-line no-control-regex -- explicit control-char reject\n if (/[\\u0000-\\u0020~^:?*[\\\\\\u007f]/.test(refname)) return false;\n if (refname.includes('..') || refname.includes('@{')) return false;\n if (refname.endsWith('/') || refname.endsWith('.')) return false;\n for (const part of refname.split('/')) {\n if (part === '' || part.startsWith('.') || part.startsWith('-'))\n return false;\n if (part.endsWith('.lock')) return false;\n }\n return true;\n}\n\nfunction assertSafeRefname(refname: string): void {\n if (!isSafeRefname(refname)) {\n throw new Error(\n `unsafe ref name from remote state: ${JSON.stringify(refname)} — refusing`\n );\n }\n}\n\nfunction assertFullSha(sha: string): void {\n if (!FULL_SHA_RE.test(sha)) {\n throw new Error(`not a full 40-hex SHA-1: ${JSON.stringify(sha)}`);\n }\n}\n\n/** Run git with argument-array safety in `repoPath`. */\nexport async function runGit(\n repoPath: string,\n args: string[]\n): Promise<string> {\n try {\n const { stdout } = await execFileAsync('git', args, {\n cwd: repoPath,\n encoding: 'utf-8',\n maxBuffer: 64 * 1024 * 1024,\n });\n return stdout;\n } catch (err) {\n const e = err as {\n code?: number | string;\n stderr?: string;\n message?: string;\n };\n throw new Error(\n `git ${args[0]} failed${typeof e.code === 'number' ? ` (exit ${e.code})` : ''}: ` +\n `${(e.stderr ?? e.message ?? '').trim()}`\n );\n }\n}\n\n/**\n * Write one object via `git hash-object -w --stdin -t <type>` (binary-safe\n * stdin) and verify the SHA git computed matches the expected one.\n */\nexport async function writeGitObject(\n repoPath: string,\n object: FetchedObject\n): Promise<void> {\n assertFullSha(object.sha);\n const written = await new Promise<string>((resolve, reject) => {\n const child = spawn(\n 'git',\n ['hash-object', '-w', '--stdin', '-t', object.type],\n { cwd: repoPath, stdio: ['pipe', 'pipe', 'pipe'] }\n );\n let stdout = '';\n let stderr = '';\n child.stdout.on('data', (chunk: Buffer) => {\n stdout += chunk.toString('utf-8');\n });\n child.stderr.on('data', (chunk: Buffer) => {\n stderr += chunk.toString('utf-8');\n });\n child.on('error', (err) => {\n reject(new Error(`failed to spawn git hash-object: ${err.message}`));\n });\n child.on('close', (code) => {\n if (code !== 0) {\n return reject(\n new Error(`git hash-object failed (exit ${code}): ${stderr.trim()}`)\n );\n }\n resolve(stdout.trim());\n });\n child.stdin.on('error', () => {\n // Child died before consuming stdin; 'close' surfaces the failure.\n });\n child.stdin.write(object.body);\n child.stdin.end();\n });\n if (written !== object.sha) {\n throw new ObjectWriteMismatchError(object.sha, written);\n }\n}\n\n/** Write a batch of verified objects into the repository (sequential). */\nexport async function writeGitObjects(\n repoPath: string,\n objects: Iterable<FetchedObject>\n): Promise<number> {\n let count = 0;\n for (const object of objects) {\n await writeGitObject(repoPath, object);\n count += 1;\n }\n return count;\n}\n\n/** `git update-ref <refname> <sha>` with refname/SHA validation. */\nexport async function updateRef(\n repoPath: string,\n refname: string,\n sha: string\n): Promise<void> {\n assertSafeRefname(refname);\n assertFullSha(sha);\n await runGit(repoPath, ['update-ref', refname, sha]);\n}\n\n/** Point HEAD at a branch via `git symbolic-ref HEAD <refname>`. */\nexport async function setHeadSymref(\n repoPath: string,\n refname: string\n): Promise<void> {\n assertSafeRefname(refname);\n await runGit(repoPath, ['symbolic-ref', 'HEAD', refname]);\n}\n","/**\n * Minimal bech32 npub encoding/decoding for Nostr pubkeys (BIP-173 / NIP-19),\n * dependency-free. Mirrors rig-web's proven `web/npub.ts` — the CLI must not\n * import from the SPA package, so the ~100 lines live here too (#278: `rig\n * clone` accepts `<owner-npub-or-hex>/<repo-id>` addresses).\n */\n\nconst BECH32_CHARSET = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l';\n\nfunction bech32Polymod(values: number[]): number {\n const GEN = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3];\n let chk = 1;\n for (const v of values) {\n const b = chk >> 25;\n chk = ((chk & 0x1ffffff) << 5) ^ v;\n for (let i = 0; i < 5; i++) {\n chk ^= (b >> i) & 1 ? (GEN[i] as number) : 0;\n }\n }\n return chk;\n}\n\nfunction bech32HrpExpand(hrp: string): number[] {\n const ret: number[] = [];\n for (let i = 0; i < hrp.length; i++) {\n ret.push(hrp.charCodeAt(i) >> 5);\n }\n ret.push(0);\n for (let i = 0; i < hrp.length; i++) {\n ret.push(hrp.charCodeAt(i) & 31);\n }\n return ret;\n}\n\nfunction bech32CreateChecksum(hrp: string, data: number[]): number[] {\n const values = bech32HrpExpand(hrp).concat(data).concat([0, 0, 0, 0, 0, 0]);\n const polymod = bech32Polymod(values) ^ 1;\n const ret: number[] = [];\n for (let i = 0; i < 6; i++) {\n ret.push((polymod >> (5 * (5 - i))) & 31);\n }\n return ret;\n}\n\nfunction convertBits(\n data: number[],\n fromBits: number,\n toBits: number,\n pad: boolean\n): number[] {\n let acc = 0;\n let bits = 0;\n const ret: number[] = [];\n const maxv = (1 << toBits) - 1;\n for (const value of data) {\n acc = (acc << fromBits) | value;\n bits += fromBits;\n while (bits >= toBits) {\n bits -= toBits;\n ret.push((acc >> bits) & maxv);\n }\n }\n if (pad && bits > 0) {\n ret.push((acc << (toBits - bits)) & maxv);\n }\n return ret;\n}\n\nfunction hexToBytes(hex: string): number[] {\n const bytes: number[] = [];\n for (let i = 0; i < hex.length; i += 2) {\n bytes.push(parseInt(hex.slice(i, i + 2), 16));\n }\n return bytes;\n}\n\n/** Encode a 64-char hex pubkey as an `npub1…` bech32 string. */\nexport function hexToNpub(hexPubkey: string): string {\n const hrp = 'npub';\n const bytes = hexToBytes(hexPubkey);\n const words = convertBits(bytes, 8, 5, true);\n const checksum = bech32CreateChecksum(hrp, words);\n const combined = words.concat(checksum);\n return hrp + '1' + combined.map((d) => BECH32_CHARSET[d]).join('');\n}\n\n/**\n * Decode an `npub1…` bech32 string back to a 64-char hex pubkey.\n * Throws on malformed input (prefix, length, charset, checksum, padding).\n */\nexport function npubToHex(npub: string): string {\n const lower = npub.toLowerCase();\n if (lower !== npub && npub.toUpperCase() !== npub) {\n throw new Error('npub: mixed case');\n }\n if (!lower.startsWith('npub1')) {\n throw new Error('npub: invalid prefix');\n }\n if (lower.length !== 63) {\n throw new Error('npub: invalid length');\n }\n\n const data: number[] = [];\n for (let i = 5; i < lower.length; i++) {\n const idx = BECH32_CHARSET.indexOf(lower[i] as string);\n if (idx === -1) throw new Error('npub: invalid character');\n data.push(idx);\n }\n\n // Verify checksum\n const hrpExpanded = bech32HrpExpand('npub');\n if (bech32Polymod(hrpExpanded.concat(data)) !== 1) {\n throw new Error('npub: invalid checksum');\n }\n\n // Strip 6-word checksum, convert 5-bit words back to 8-bit bytes\n const words = data.slice(0, -6);\n const bytes = convertBits(words, 5, 8, false);\n\n if (bytes.length !== 32) {\n throw new Error('npub: invalid data length');\n }\n\n // Validate trailing bits are zero\n const totalBits = words.length * 5;\n const trailingBits = totalBits - bytes.length * 8;\n if (trailingBits > 0) {\n const lastWord = words[words.length - 1] as number;\n const mask = (1 << trailingBits) - 1;\n if ((lastWord & mask) !== 0) {\n throw new Error('npub: non-zero padding bits');\n }\n }\n\n return bytes.map((b) => b.toString(16).padStart(2, '0')).join('');\n}\n\nconst HEX64_RE = /^[0-9a-f]{64}$/;\n\n/**\n * Normalize a repo-owner reference to a 64-char hex pubkey: accepts lowercase\n * hex verbatim or an `npub1…` string. Throws a caller-facing error otherwise.\n */\nexport function ownerToHex(owner: string): string {\n if (HEX64_RE.test(owner)) return owner;\n if (owner.startsWith('npub1')) {\n try {\n return npubToHex(owner);\n } catch (err) {\n throw new Error(\n `invalid owner ${JSON.stringify(owner)}: ${err instanceof Error ? err.message : String(err)}`\n );\n }\n }\n throw new Error(\n `invalid owner ${JSON.stringify(owner)}: expected a 64-char lowercase hex pubkey or an npub1… string`\n );\n}\n","/**\n * Wire shapes of the toon-clientd `/git/*` control routes (epic #222).\n *\n * These are the JSON request/response types the daemon serves (bigints as\n * decimal strings, Maps as plain records) — defined HERE, in the dependency\n * root, so both sides of the route can share them: the `rig` CLI (#229)\n * consumes them as a plain-fetch client, and `@toon-protocol/client-mcp`\n * (which depends on this package for the planner — the reverse import would\n * be circular) can adopt them for its `control-api.ts` declarations. TYPES\n * ONLY plus two pure serializers; no transport code lives here.\n *\n * Keep in byte-for-byte sync with\n * `packages/client-mcp/src/control-api.ts` (`Git*` shapes) and\n * `packages/client-mcp/src/daemon/routes.ts` (error envelopes: 409\n * `non_fast_forward` carries `refs`, 413 `oversize_objects` carries\n * `objects`, 503 `bootstrapping` / 402 `insufficient_gas` are retryable).\n */\n\nimport type { PublishReceipt } from './publisher.js';\nimport type { PlannedObject, PushPlan, PushResult, RefUpdate } from './push.js';\n\n/** One planned ref update (JSON-safe as-is). */\nexport type GitRefUpdate = RefUpdate;\n\n/** One object scheduled for upload (JSON-safe as-is). */\nexport type GitPlannedObject = PlannedObject;\n\n/**\n * `POST /git/estimate` — plan a push (local git plumbing + remote-state read)\n * and price it WITHOUT paying anything. The same body (plus `confirm`) drives\n * `POST /git/push`.\n */\nexport interface GitEstimateRequest {\n /** Path to the local git repository (worktree or .git dir). Must exist. */\n repoPath: string;\n /** Repository identifier (NIP-34 `d` tag). The daemon identity is the owner. */\n repoId: string;\n /**\n * Full refnames to push (e.g. `[\"refs/heads/main\"]`). Default: every local\n * branch and tag.\n */\n refspecs?: string[];\n /** Allow non-fast-forward updates (default false → 409 `non_fast_forward`). */\n force?: boolean;\n /**\n * Relay URLs to read remote state from and publish to. Plural from day one\n * (forward-compat); defaults to the daemon's config-seeded relay.\n */\n relayUrls?: string[];\n /** Repo name/description for the first-push kind:30617 announcement. */\n announcement?: { name?: string; description?: string };\n}\n\n/** Pre-push fee table (all fees in base/micro units, decimal strings). */\nexport interface GitFeeEstimate {\n objectCount: number;\n totalObjectBytes: number;\n /** objectCount × the store route's flat price. */\n uploadFee: string;\n /** Events to publish (refs event + announcement on first push). */\n eventCount: number;\n /** eventCount × per-event fee. */\n eventFees: string;\n /** uploadFee + eventFees. */\n totalFee: string;\n /**\n * Zero-byte objects (the git empty blob) excluded from the upload — the\n * store rejects zero-byte content as malformed, so they are skipped on push\n * and reconstructed on clone/fetch. Optional for wire compatibility with\n * daemons predating the empty-blob handling. Default 0.\n */\n skippedEmptyCount?: number;\n}\n\n/** Serialized `PushPlan` — everything a confirm UI needs. */\nexport interface GitEstimateResponse {\n repoId: string;\n refUpdates: GitRefUpdate[];\n /** Full new ref state to publish (HEAD target first). */\n newRefs: Record<string, string>;\n headSymref: string | null;\n objects: GitPlannedObject[];\n /** sha→txId hints known WITHOUT uploading (remote tags + resolver finds). */\n knownShaToTxId: Record<string, string>;\n /** True when no kind:30617 exists yet — the push announces first. */\n announceNeeded: boolean;\n announcement: { name: string; description: string };\n estimate: GitFeeEstimate;\n}\n\n/**\n * `POST /git/push` — plan + execute: upload the delta to Arweave and publish\n * the cumulative kind:30618 (+ kind:30617 on first push). PERMANENT + PAID.\n */\nexport interface GitPushRequest extends GitEstimateRequest {\n /** Must be literally `true` — a push spends channel funds irreversibly. */\n confirm: boolean;\n}\n\n/** One object-upload step result. */\nexport interface GitUploadStep {\n sha: string;\n txId: string;\n /** '0' when skipped (already on Arweave — content-addressed resume). */\n feePaid: string;\n skipped: boolean;\n}\n\n/** Receipt for one published event. */\nexport interface GitPublishReceipt {\n eventId: string;\n feePaid: string;\n}\n\n/** Serialized `PushResult` — per-step receipts + total fees actually paid. */\nexport interface GitPushResponse {\n repoId: string;\n refUpdates: GitRefUpdate[];\n /** Per-object results, in plan order. */\n uploads: GitUploadStep[];\n /** kind:30617 receipt, or null when the repo was already announced. */\n announceReceipt: GitPublishReceipt | null;\n /** kind:30618 (cumulative refs + arweave map) receipt. */\n refsReceipt: GitPublishReceipt;\n /** Full sha→txId map published in the refs event. */\n arweaveMap: Record<string, string>;\n /** Total fees actually paid (uploads + events), base units, decimal. */\n totalFeePaid: string;\n /** The pre-push estimate the push ran under (compare against totalFeePaid). */\n estimate: GitFeeEstimate;\n}\n\n// ---------------------------------------------------------------------------\n// Single-event git publishes (`/git/issue|comment|patch|status`, #231)\n// ---------------------------------------------------------------------------\n\n/** NIP-34 repository address: the owner+id pair behind `a` tags. */\nexport interface GitRepoAddr {\n /** Repository owner's Nostr pubkey (64-char hex) — author of kind:30617/30618. */\n ownerPubkey: string;\n /** Repository identifier (NIP-34 `d` tag). */\n repoId: string;\n}\n\n/** `POST /git/issue` — publish a kind:1621 issue against a repo. PAID. */\nexport interface GitIssueRequest {\n repoAddr: GitRepoAddr;\n /** Issue title (`subject` tag). */\n title: string;\n /** Issue body (Markdown content). */\n body: string;\n /** Labels (`t` tags). */\n labels?: string[];\n}\n\n/** `POST /git/comment` — publish a kind:1622 comment on an issue/patch. PAID. */\nexport interface GitCommentRequest {\n repoAddr: GitRepoAddr;\n /** Event id of the issue or patch being commented on. */\n rootEventId: string;\n /** Comment body (Markdown content). */\n body: string;\n /**\n * Pubkey of the TARGET event's author (NIP-34 `p` threading tag — not the\n * comment author). Defaults to the repo owner.\n */\n parentAuthorPubkey?: string;\n /** `e`-tag marker (default 'root': commenting directly on the issue/patch). */\n marker?: 'root' | 'reply';\n}\n\n/**\n * `POST /git/patch` — publish a kind:1617 patch. Supply EXACTLY ONE of\n * `patchText` (literal `git format-patch` output) or `repoPath`+`range`\n * (the daemon runs `git format-patch --stdout <range>` locally). PAID.\n */\nexport interface GitPatchRequest {\n repoAddr: GitRepoAddr;\n /** Patch/PR title (`subject` tag). */\n title: string;\n /**\n * PR body/cover text (`description` tag). Kept OUT of the event content so\n * `git am` still consumes the patch text verbatim (#280).\n */\n description?: string;\n /** Literal patch text. Mutually exclusive with `repoPath`+`range`. */\n patchText?: string;\n /** Local repository to run format-patch in. Requires `range`. */\n repoPath?: string;\n /** Revision range for format-patch (`<rev>`, `<rev>..<rev>`, `<rev>...<rev>`). */\n range?: string;\n /** Commit/parent pairs for `commit`/`parent-commit` tags. */\n commits?: { sha: string; parentSha: string }[];\n /** Branch name for the `t` tag. */\n branch?: string;\n}\n\nexport type GitStatusValue = 'open' | 'applied' | 'closed' | 'draft';\n\n/** `POST /git/status` — publish a kind:1630-1633 status event. PAID. */\nexport interface GitStatusRequest {\n repoAddr: GitRepoAddr;\n /** Event id of the issue/patch whose status is being set. */\n targetEventId: string;\n /** open → 1630, applied → 1631, closed → 1632, draft → 1633. */\n status: GitStatusValue;\n /** Pubkey of the target event's author (`p` tag), when known. */\n targetPubkey?: string;\n}\n\n/**\n * Response of the single-event git publishes (issue/comment/patch/status):\n * a publish receipt plus the NIP-34 kind that was published. Daemon\n * responses extend the full `POST /publish` receipt, so the channel fields\n * (`channelId`/`nonce`/…) are present there; they are optional here because\n * the CLI's standalone path publishes through the embedded client and has\n * no channel wire shape to report.\n */\nexport interface GitEventResponse {\n /** Event ID as accepted by the relay. */\n eventId: string;\n /** Fee actually paid for this publish, base units, decimal string. */\n feePaid: string;\n /** The NIP-34 kind that was published. */\n kind: number;\n /** Channel the claim was signed against (daemon responses). */\n channelId?: string;\n /** Channel nonce after this publish (daemon responses). */\n nonce?: number;\n /** FULFILL response data (base64), when the backend returned any. */\n data?: string;\n /** Spendable channel balance after this write, when known. */\n channelBalanceAfter?: string;\n}\n\n/**\n * Uniform error envelope of non-2xx control-route responses. Structured\n * errors put extra fields at the top level: `non_fast_forward` (409) adds\n * `refs`, `oversize_objects` (413) adds `objects`.\n */\nexport interface GitErrorEnvelope {\n error: string;\n detail?: string;\n /** True when the caller should retry (e.g. daemon still bootstrapping). */\n retryable?: boolean;\n [extra: string]: unknown;\n}\n\n// ---------------------------------------------------------------------------\n// Serializers (pure) — the exact mapping the daemon routes apply; used by the\n// CLI's standalone mode so both surfaces emit identical wire JSON.\n// ---------------------------------------------------------------------------\n\n/** Serialize a plan's fee estimate onto the wire (bigints → strings). */\nexport function serializeFeeEstimate(plan: PushPlan): GitFeeEstimate {\n return {\n objectCount: plan.estimate.objectCount,\n totalObjectBytes: plan.estimate.totalObjectBytes,\n uploadFee: plan.estimate.uploadFee.toString(),\n eventCount: plan.estimate.eventCount,\n eventFees: plan.estimate.eventFees.toString(),\n totalFee: plan.estimate.totalFee.toString(),\n ...(plan.estimate.skippedEmptyCount > 0\n ? { skippedEmptyCount: plan.estimate.skippedEmptyCount }\n : {}),\n };\n}\n\n/** Serialize a PushPlan onto the wire (bigints → strings, Maps → records). */\nexport function serializePushPlan(plan: PushPlan): GitEstimateResponse {\n return {\n repoId: plan.repoId,\n refUpdates: plan.refUpdates,\n newRefs: plan.newRefs,\n headSymref: plan.headSymref,\n objects: plan.objects,\n knownShaToTxId: Object.fromEntries(plan.knownShaToTxId),\n announceNeeded: plan.announceNeeded,\n announcement: plan.announcement,\n estimate: serializeFeeEstimate(plan),\n };\n}\n\n/**\n * Serialize a standalone {@link PublishReceipt} into the wire shape the\n * daemon's single-event `/git/*` routes answer with, so `--json` consumers\n * see one `GitEventResponse` shape regardless of publisher mode.\n */\nexport function serializeEventReceipt(\n kind: number,\n receipt: PublishReceipt\n): GitEventResponse {\n return {\n eventId: receipt.eventId,\n feePaid: receipt.feePaid.toString(),\n kind,\n };\n}\n\n/** Serialize a PushResult onto the wire (bigints → strings, Maps → records). */\nexport function serializePushResult(\n plan: PushPlan,\n result: PushResult\n): GitPushResponse {\n return {\n repoId: plan.repoId,\n refUpdates: plan.refUpdates,\n uploads: result.uploads.map((u) => ({\n sha: u.sha,\n txId: u.txId,\n feePaid: u.feePaid.toString(),\n skipped: u.skipped,\n })),\n announceReceipt: result.announceReceipt\n ? {\n eventId: result.announceReceipt.eventId,\n feePaid: result.announceReceipt.feePaid.toString(),\n }\n : null,\n refsReceipt: {\n eventId: result.refsReceipt.eventId,\n feePaid: result.refsReceipt.feePaid.toString(),\n },\n arweaveMap: Object.fromEntries(result.arweaveMap),\n totalFeePaid: result.totalFeePaid.toString(),\n estimate: serializeFeeEstimate(plan),\n };\n}\n","/**\n * Push planner/executor — the core of `rig push` (epic #222, ticket #226).\n *\n * `planPush` is network-free (relay/Arweave-wise — it only runs local git\n * plumbing through GitRepoReader plus one injectable async resolver step):\n * it classifies every ref update, computes the object delta against what the\n * remote already stores, hard-errors on oversize objects, and prices the\n * push. The returned {@link PushPlan} carries everything a confirm UI needs.\n *\n * `executePush` spends money: it uploads the planned objects through a\n * {@link Publisher} (ref-tip objects last, so a crashed push never leads to\n * a state where a discoverable tip's history is missing), then publishes ONE\n * cumulative kind:30618 whose `arweave` tags are the MERGE of the remote's\n * existing sha→txId map and the new uploads — kind:30618 is NIP-33\n * replaceable, so dropping prior tags would orphan earlier hints — and whose\n * `r` tags are the full new ref state. On a first push it publishes the\n * kind:30617 announcement before the refs event.\n *\n * Resume safety: uploads are content-addressed (Git-SHA-tagged), so re-running\n * `executePush` after a crash is safe — it consults the merged\n * remote + planned sha→txId map before paying for any upload, and a re-plan\n * with fresh remote state (whose `resolveMissing` finds the already-uploaded\n * objects via GraphQL) skips them entirely.\n */\n\nimport { buildRepoAnnouncement, buildRepoRefs } from './nip34-events.js';\nimport {\n EMPTY_BLOB_SHA,\n MAX_OBJECT_SIZE,\n type GitObjectType,\n} from './objects.js';\nimport {\n uploadChargeFor,\n type FeeRates,\n type PublishReceipt,\n type Publisher,\n} from './publisher.js';\nimport { GitError, type GitRef, type GitRepoReader } from './repo-reader.js';\nimport type { RemoteState } from './remote-state.js';\n\n// ---------------------------------------------------------------------------\n// Errors\n// ---------------------------------------------------------------------------\n\n/** A ref update rejected because it is not a fast-forward. */\nexport interface RejectedRefUpdate {\n refname: string;\n localSha: string;\n remoteSha: string;\n}\n\n/** Thrown by {@link planPush} when a non-fast-forward update lacks `force`. */\nexport class NonFastForwardError extends Error {\n constructor(\n /** The refs that would need `--force` to update. */\n public readonly refs: RejectedRefUpdate[]\n ) {\n super(\n `non-fast-forward update rejected for ${refs\n .map((r) => r.refname)\n .join(', ')} — re-run with force to overwrite the remote ref(s)`\n );\n this.name = 'NonFastForwardError';\n }\n}\n\n/**\n * One object exceeding the old hard upload cap.\n *\n * @deprecated Nothing produces this any more (#102). Size is priced, not\n * refused, so there is no \"oversize\" class of object to report. Retained so\n * the 4.x type export keeps resolving.\n */\nexport interface OversizeObject {\n sha: string;\n type: GitObjectType;\n /** Body size in bytes. */\n size: number;\n /** Path the object was reached by (blobs / non-root trees), if known. */\n path?: string;\n}\n\n/**\n * @deprecated NEVER THROWN as of #102. `planPush` used to reject any object\n * over a hard 95 KiB cap; the store route prices per KiB, so a large object is\n * now a more expensive upload rather than a refusal, and there is nothing left\n * to throw. Retained so the 4.x export keeps resolving — a `catch` for it is\n * dead code and can be removed.\n */\nexport class OversizeObjectsError extends Error {\n constructor(\n /** The offending objects with paths and sizes. */\n public readonly objects: OversizeObject[]\n ) {\n super(\n `${objects.length} object(s) exceed the ${MAX_OBJECT_SIZE} byte upload limit: ` +\n objects.map((o) => `${o.path ?? o.sha} (${o.size} bytes)`).join(', ')\n );\n this.name = 'OversizeObjectsError';\n }\n}\n\n// ---------------------------------------------------------------------------\n// Plan types\n// ---------------------------------------------------------------------------\n\n/** How a ref moves relative to the remote. */\nexport type RefUpdateKind =\n /** Ref does not exist on the remote yet. */\n | 'new'\n /** Remote tip is an ancestor of the local tip. */\n | 'fast-forward'\n /** Non-fast-forward, allowed because `force` was set. */\n | 'forced'\n /** Local and remote tips already match — nothing to push. */\n | 'up-to-date';\n\n/** One planned ref update (deletions are out of scope in v1). */\nexport interface RefUpdate {\n /** Full refname, e.g. `refs/heads/main`. */\n refname: string;\n /** Local tip SHA (tag object SHA for annotated tags). */\n localSha: string;\n /** Remote tip SHA, or null when the ref is new. */\n remoteSha: string | null;\n kind: RefUpdateKind;\n}\n\n/** One object scheduled for upload. */\nexport interface PlannedObject {\n sha: string;\n type: GitObjectType;\n /** Body size in bytes (what the upload fee is charged on). */\n size: number;\n /** Path the object was reached by, if any (blobs / non-root trees). */\n path?: string;\n /** True when this SHA is the tip of a planned ref update (uploaded last). */\n isRefTip: boolean;\n}\n\n/** Pre-push fee estimate — render this in the confirm table. */\nexport interface PushFeeEstimate {\n /** Number of objects to upload. */\n objectCount: number;\n /** Total bytes across all planned object bodies. */\n totalObjectBytes: number;\n /** objectCount × the store route's flat price — smallest asset unit. */\n uploadFee: bigint;\n /** Number of events to publish (refs event + announcement on first push). */\n eventCount: number;\n /** eventCount × eventFee (smallest asset unit). */\n eventFees: bigint;\n /** uploadFee + eventFees. */\n totalFee: bigint;\n /**\n * Objects excluded from the upload because their body is zero bytes — the\n * git empty blob, which the store rejects as malformed (F00). Reconstructed\n * locally on clone/fetch, so nothing is lost; surfaced here so the fee table\n * can report the skip honestly.\n */\n skippedEmptyCount: number;\n}\n\n/** Everything `executePush` (and a confirm UI) needs. */\nexport interface PushPlan {\n repoId: string;\n /** Every considered ref with its classification (incl. up-to-date). */\n refUpdates: RefUpdate[];\n /**\n * Full new ref state to publish as `r` tags: the remote's refs overlaid\n * with the planned updates (refs not being pushed are preserved — v1\n * never deletes). Ordered with the HEAD target first, which is what\n * `buildRepoRefs` derives the HEAD symref tag from.\n */\n newRefs: Record<string, string>;\n /** HEAD symref target for the new state (first key of {@link newRefs}). */\n headSymref: string | null;\n /**\n * Objects to upload, dependency-safe order: ref-tip objects last so a\n * crashed push never uploads a tip whose history is missing.\n */\n objects: PlannedObject[];\n /**\n * Zero-byte objects (the git empty blob) excluded from {@link objects}: the\n * store rejects a zero-byte kind:5094 upload as malformed (F00), so `rig`\n * never uploads it — the commit/tree still references it and clone/fetch\n * synthesizes it locally. Kept for honest receipts, never uploaded.\n */\n skippedEmptyObjects: PlannedObject[];\n /**\n * sha→txId hints known WITHOUT uploading: the remote's `arweave` tags\n * plus anything `resolveMissing` found. Merged into the published\n * kind:30618 so prior hints are never dropped.\n */\n knownShaToTxId: Map<string, string>;\n /** True when no kind:30617 exists yet — executePush announces first. */\n announceNeeded: boolean;\n /** Announcement metadata used when {@link announceNeeded}. */\n announcement: { name: string; description: string };\n estimate: PushFeeEstimate;\n}\n\nexport interface PlanPushOptions {\n repoReader: GitRepoReader;\n remoteState: RemoteState;\n /** Fee rates from `Publisher.getFeeRates()`. */\n feeRates: FeeRates;\n /** Repository identifier (NIP-34 `d` tag). */\n repoId: string;\n /**\n * Full refnames to push (e.g. `['refs/heads/main']`). Defaults to every\n * local branch and tag. Refs that don't exist locally are an error\n * (deletions are out of scope in v1).\n */\n refs?: string[];\n /** Allow non-fast-forward updates (default false → hard error). */\n force?: boolean;\n /** Repo name/description for the first-push announcement. */\n announcement?: { name?: string; description?: string };\n /**\n * Async resolver for SHAs the remote's `arweave` tags don't cover —\n * consulted before deciding to re-upload. Defaults to\n * `remoteState.resolveMissing` (GraphQL fallback); injectable so the\n * planner core stays testable without network.\n */\n resolveMissing?: (shas: string[]) => Promise<Map<string, string>>;\n}\n\n// ---------------------------------------------------------------------------\n// planPush\n// ---------------------------------------------------------------------------\n\n/**\n * Classify ref updates, compute the object delta, enforce the size limit,\n * and price the push. Throws {@link NonFastForwardError} /\n * {@link OversizeObjectsError} (both carry structured data for UIs).\n */\nexport async function planPush(options: PlanPushOptions): Promise<PushPlan> {\n const { repoReader, remoteState, feeRates, repoId, force = false } = options;\n const resolveMissing =\n options.resolveMissing ?? remoteState.resolveMissing.bind(remoteState);\n\n // 1. Select and classify refs. -------------------------------------------\n const { head, refs: localRefs } = await repoReader.listRefs();\n const localByName = new Map(localRefs.map((r) => [r.refname, r]));\n\n let selected: GitRef[];\n if (options.refs !== undefined) {\n selected = options.refs.map((name) => {\n const ref = localByName.get(name);\n if (!ref) {\n throw new Error(\n `ref ${JSON.stringify(name)} does not exist locally ` +\n '(ref deletion is out of scope in v1)'\n );\n }\n return ref;\n });\n } else {\n selected = localRefs;\n }\n\n const refUpdates: RefUpdate[] = [];\n const rejected: RejectedRefUpdate[] = [];\n for (const ref of selected) {\n const remoteSha = remoteState.refs.get(ref.refname) ?? null;\n if (remoteSha === null) {\n refUpdates.push({\n refname: ref.refname,\n localSha: ref.sha,\n remoteSha,\n kind: 'new',\n });\n continue;\n }\n if (remoteSha === ref.sha) {\n refUpdates.push({\n refname: ref.refname,\n localSha: ref.sha,\n remoteSha,\n kind: 'up-to-date',\n });\n continue;\n }\n let fastForward = false;\n try {\n fastForward = await repoReader.isAncestor(remoteSha, ref.sha);\n } catch (err) {\n // Remote tip unknown locally (never fetched) or not a commit-ish —\n // we can't prove ancestry, so treat it as non-fast-forward.\n if (!(err instanceof GitError)) throw err;\n fastForward = false;\n }\n if (fastForward) {\n refUpdates.push({\n refname: ref.refname,\n localSha: ref.sha,\n remoteSha,\n kind: 'fast-forward',\n });\n } else if (force) {\n refUpdates.push({\n refname: ref.refname,\n localSha: ref.sha,\n remoteSha,\n kind: 'forced',\n });\n } else {\n rejected.push({ refname: ref.refname, localSha: ref.sha, remoteSha });\n }\n }\n if (rejected.length > 0) throw new NonFastForwardError(rejected);\n\n const updates = refUpdates.filter((u) => u.kind !== 'up-to-date');\n\n // 2. Object delta: reachable from the new tips, minus what the remote has.\n const wantTips = [...new Set(updates.map((u) => u.localSha))];\n const haveTips = [...new Set(remoteState.refs.values())];\n const delta =\n wantTips.length > 0\n ? await repoReader.objectsBetweenWithPaths(wantTips, haveTips)\n : [];\n\n const knownShaToTxId = new Map(remoteState.shaToTxId);\n let candidates = delta.filter((o) => !knownShaToTxId.has(o.sha));\n if (candidates.length > 0) {\n // The remote's `arweave` tags may lag reality (e.g. a crashed push\n // uploaded objects but never published the refs event) — resolve the\n // gaps before paying to re-upload content-addressed data.\n const resolved = await resolveMissing(candidates.map((o) => o.sha));\n for (const [sha, txId] of resolved) knownShaToTxId.set(sha, txId);\n candidates = candidates.filter((o) => !knownShaToTxId.has(o.sha));\n }\n\n // 3. Sizes + oversize hard error. -----------------------------------------\n const pathBySha = new Map(candidates.map((c) => [c.sha, c.path]));\n const { objects: stats, missing } = await repoReader.statObjects(\n candidates.map((c) => c.sha)\n );\n if (missing.length > 0) {\n throw new Error(\n `objects vanished from the local repository during planning: ${missing.join(', ')}`\n );\n }\n\n // No size gate. An object larger than FREE_TIER_MAX_ITEM_BYTES is not an\n // error — it is simply a paid upload: the store route prices per KiB\n // (ADR 0065), so size is charged for rather than refused (#102). The fee\n // table the caller confirms already reflects the per-KiB cost, so an\n // expensive object is visible before anything is spent.\n\n // 4. Split off the empty blob, then order the rest ref-tips-last. ----------\n // The git empty blob uploads as an empty kind:5094 `i` value, which the\n // store rejects as malformed (F00). Skip it: it is reconstructed locally on\n // clone/fetch. Keyed off the EXACT empty-blob constant SHA — NOT a\n // `size === 0` heuristic, which would also match the (distinct, valid) empty\n // TREE object `4b825dc6…` and silently drop it (it is not synthesized on\n // read). An object whose SHA is EMPTY_BLOB_SHA is provably the empty blob.\n const tipShas = new Set(updates.map((u) => u.localSha));\n const planned: PlannedObject[] = [];\n const skippedEmptyObjects: PlannedObject[] = [];\n for (const stat of stats) {\n const path = pathBySha.get(stat.sha);\n const object: PlannedObject = {\n ...stat,\n ...(path ? { path } : {}),\n isRefTip: tipShas.has(stat.sha),\n };\n if (stat.sha === EMPTY_BLOB_SHA) skippedEmptyObjects.push(object);\n else planned.push(object);\n }\n const objects = [\n ...planned.filter((o) => !o.isRefTip),\n ...planned.filter((o) => o.isRefTip),\n ];\n\n // 5. Full new ref state (remote refs overlaid with updates), HEAD first. --\n const newRefsMap = new Map(remoteState.refs);\n for (const update of updates) newRefsMap.set(update.refname, update.localSha);\n\n const headSymref =\n head && newRefsMap.has(head)\n ? head\n : remoteState.headSymref && newRefsMap.has(remoteState.headSymref)\n ? remoteState.headSymref\n : ([...newRefsMap.keys()][0] ?? null);\n\n const newRefs: Record<string, string> = {};\n const headSha = headSymref ? newRefsMap.get(headSymref) : undefined;\n if (headSymref && headSha) newRefs[headSymref] = headSha;\n for (const [refname, sha] of newRefsMap) {\n if (refname !== headSymref) newRefs[refname] = sha;\n }\n\n // 6. Fee estimate. ---------------------------------------------------------\n // A price is a schedule per route (ADR 0065): a flat base per packet, plus\n // an optional per-KiB slope a metered store route publishes. `uploadChargeFor`\n // is the one rule for both, so the confirm table equals what is paid.\n const announceNeeded = !remoteState.announced;\n const totalObjectBytes = objects.reduce((sum, o) => sum + o.size, 0);\n // Per object: the store route's base price plus, on a metered route (ADR\n // 0065 schedule), its per-KiB rate over the sealed payload — the same rule\n // the client applies to the claim, so the table still equals what is paid.\n const uploadFee = objects.reduce(\n (sum, o) => sum + uploadChargeFor(feeRates, o.size),\n 0n\n );\n const eventCount = 1 + (announceNeeded ? 1 : 0);\n const eventFees = BigInt(eventCount) * feeRates.eventFee;\n\n return {\n repoId,\n refUpdates,\n newRefs,\n headSymref,\n objects,\n skippedEmptyObjects,\n knownShaToTxId,\n announceNeeded,\n announcement: {\n name: options.announcement?.name ?? repoId,\n description: options.announcement?.description ?? '',\n },\n estimate: {\n objectCount: objects.length,\n totalObjectBytes,\n uploadFee,\n eventCount,\n eventFees,\n totalFee: uploadFee + eventFees,\n skippedEmptyCount: skippedEmptyObjects.length,\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// executePush\n// ---------------------------------------------------------------------------\n\n/** Result of one object-upload step. */\nexport interface UploadStepResult {\n sha: string;\n txId: string;\n /** 0n when skipped (already uploaded — content-addressed resume). */\n feePaid: bigint;\n /** True when the object was already on Arweave and nothing was paid. */\n skipped: boolean;\n}\n\n/** Result of the whole push. */\nexport interface PushResult {\n /** Per-object results, in plan order. */\n uploads: UploadStepResult[];\n /** kind:30617 receipt, or null when the repo was already announced. */\n announceReceipt: PublishReceipt | null;\n /** kind:30618 (cumulative refs + arweave map) receipt. */\n refsReceipt: PublishReceipt;\n /**\n * The full sha→txId map published in the refs event: remote hints +\n * resolver finds + this push's uploads.\n */\n arweaveMap: Map<string, string>;\n /** Total fees actually paid (uploads + events), smallest asset unit. */\n totalFeePaid: bigint;\n}\n\nexport interface ExecutePushOptions {\n plan: PushPlan;\n publisher: Publisher;\n /**\n * Remote state — pass a FRESH fetch when resuming after a crash so its\n * `shaToTxId` (and `announced`) reflect what the previous attempt already\n * paid for.\n */\n remoteState: RemoteState;\n repoReader: GitRepoReader;\n /** Relay URLs to publish events to (plural from day one; size 1 today). */\n relayUrls: string[];\n}\n\n/** How many object bodies to hold in memory at once between read and upload. */\nconst READ_BATCH_SIZE = 100;\n\n/**\n * Execute a {@link PushPlan}: upload objects (ref tips last), then publish\n * the kind:30617 announcement (first push only) and ONE cumulative\n * kind:30618 whose `arweave` tags merge every known sha→txId hint with the\n * new uploads and whose `r` tags carry the full new ref state.\n *\n * Safe to re-run after a crash: SHAs already present in the merged\n * remote + plan map are skipped without paying.\n */\nexport async function executePush(\n options: ExecutePushOptions\n): Promise<PushResult> {\n const { plan, publisher, remoteState, repoReader, relayUrls } = options;\n\n // Merged sha→txId map: remote hints (fresh on resume) + plan-time finds.\n // Consulted before every upload — this is the resume-safety check.\n const merged = new Map([...remoteState.shaToTxId, ...plan.knownShaToTxId]);\n\n const resultBySha = new Map<string, UploadStepResult>();\n let totalFeePaid = 0n;\n\n const pending: PlannedObject[] = [];\n for (const object of plan.objects) {\n const knownTxId = merged.get(object.sha);\n if (knownTxId !== undefined) {\n resultBySha.set(object.sha, {\n sha: object.sha,\n txId: knownTxId,\n feePaid: 0n,\n skipped: true,\n });\n } else {\n pending.push(object);\n }\n }\n\n // Upload in plan order (ref tips are already last), reading bodies in\n // batches so memory stays bounded on large pushes.\n for (let i = 0; i < pending.length; i += READ_BATCH_SIZE) {\n const batch = pending.slice(i, i + READ_BATCH_SIZE);\n const { objects: read, missing } = await repoReader.readObjects(\n batch.map((o) => o.sha)\n );\n if (missing.length > 0) {\n throw new Error(\n `objects vanished from the local repository during push: ${missing.join(', ')}`\n );\n }\n const bodyBySha = new Map(read.map((r) => [r.sha, r.body]));\n for (const object of batch) {\n const body = bodyBySha.get(object.sha);\n if (!body) {\n throw new Error(\n `internal: cat-file returned no body for ${object.sha}`\n );\n }\n const receipt = await publisher.uploadGitObject({\n sha: object.sha,\n type: object.type,\n body,\n repoId: plan.repoId,\n // #368: the path the blob was reached by drives its Content-Type; a\n // non-blob object (no path) uploads as octet-stream.\n ...(object.path ? { path: object.path } : {}),\n });\n merged.set(object.sha, receipt.txId);\n totalFeePaid += receipt.feePaid;\n resultBySha.set(object.sha, {\n sha: object.sha,\n txId: receipt.txId,\n feePaid: receipt.feePaid,\n skipped: false,\n });\n }\n }\n\n // Announcement (first push only) goes before the refs event so a repo is\n // never referenced by an `a` tag before its kind:30617 exists. Re-check\n // the (fresh-on-resume) remote state so a crashed push doesn't announce\n // twice.\n let announceReceipt: PublishReceipt | null = null;\n if (plan.announceNeeded && !remoteState.announced) {\n const announceEvent = buildRepoAnnouncement(\n plan.repoId,\n plan.announcement.name,\n plan.announcement.description\n );\n announceReceipt = await publisher.publishEvent(announceEvent, relayUrls);\n totalFeePaid += announceReceipt.feePaid;\n }\n\n // ONE cumulative kind:30618: full ref state + MERGED arweave map (NIP-33\n // replaceable — dropping prior tags would orphan earlier sha→txId hints).\n const refsEvent = buildRepoRefs(\n plan.repoId,\n plan.newRefs,\n Object.fromEntries(merged)\n );\n const refsReceipt = await publisher.publishEvent(refsEvent, relayUrls);\n totalFeePaid += refsReceipt.feePaid;\n\n const uploads = plan.objects.map((o) => {\n const step = resultBySha.get(o.sha);\n if (!step) {\n throw new Error(`internal: no upload result recorded for ${o.sha}`);\n }\n return step;\n });\n\n return {\n uploads,\n announceReceipt,\n refsReceipt,\n arweaveMap: merged,\n totalFeePaid,\n };\n}\n","/**\n * NIP-C1 (Nostr CI) event builders + parsers — the wire layer of rig's\n * relay-native CI (rig#125, slice 1). The spec is vendored at\n * docs/specs/nip-c1.md; this module adopts it VERBATIM for kinds, tags,\n * content, and ordering rules, so ngit tooling keeps reading rig's events and\n * rig keeps reading ngit-ci's.\n *\n * Builders return UnsignedEvent (the Publisher signs — see ../publisher.ts,\n * the same posture as ../nip34-events.ts). Parsers take a read-side\n * NostrEvent and return `null` on ANY malformed shape: the relay is\n * permissionless, so a consumer must never let a hand-crafted event smuggle a\n * meaning the spec does not give it (an unknown `X` policy is NOT automatic\n * service; a request naming another coordinator is NOT ours; a trigger whose\n * `a` tags name two repo ids is NOT a run).\n *\n * rig's deliberate departures from the ngit reference, all within the spec:\n * - `[\"software\",\"rig\",\"<version>\"]` on the Advertisement;\n * - Advertisement policy `M=maintainer-request`, `X=request-required`,\n * `B=out-of-band` (the coordinator is funded by its operator);\n * - logs/artifacts are TOON store gateway URLs, not Blossom (the tag\n * shapes are identical — only the URL host differs);\n * - PR context may carry `K`/`k` = 1617: `rig pr create` publishes NIP-34\n * patches, so a 1617 is the PR shape rig's own contributors produce.\n */\n\nimport type { UnsignedEvent } from '../nip34-events.js';\nimport type { NostrEvent } from '../remote-state.js';\n\n// ---------------------------------------------------------------------------\n// Kinds + constants\n// ---------------------------------------------------------------------------\n\nexport const CI_ADVERTISEMENT_KIND = 19843;\nexport const CI_SERVICE_REQUEST_KIND = 9843;\nexport const CI_SERVICE_STOP_KIND = 9844;\nexport const CI_SECRET_UPDATE_KIND = 29846;\nexport const CI_MANUAL_TRIGGER_KIND = 9840;\nexport const CI_JOB_RESULT_KIND = 9841;\nexport const CI_WORKFLOW_RESULT_KIND = 9842;\nexport const CI_WORKFLOW_PROGRESS_KIND = 39842;\n\n/** The one runner family rig supports (`W` tag / `R` prefix). */\nexport const CI_RUNNER_FAMILY = 'act';\n/** The `software` tag name rig advertises under. */\nexport const CI_SOFTWARE = 'rig';\n\n/** NIP-40 bound on Advertisement + Progress lifetime (seconds). */\nexport const CI_MAX_ADVERTISEMENT_TTL = 30 * 60;\nexport const CI_MAX_PROGRESS_TTL = 30 * 60;\n\n/** Kind of the NIP-34 repository announcement the `a` coordinates point at. */\nconst REPO_ANNOUNCEMENT_KIND = 30617;\n\nexport type CiConclusion =\n | 'success'\n | 'failure'\n | 'neutral'\n | 'cancelled'\n | 'skipped'\n | 'timed_out'\n | 'startup_failure';\n\nconst CONCLUSIONS: ReadonlySet<string> = new Set<CiConclusion>([\n 'success',\n 'failure',\n 'neutral',\n 'cancelled',\n 'skipped',\n 'timed_out',\n 'startup_failure',\n]);\n\nexport function isCiConclusion(value: string): value is CiConclusion {\n return CONCLUSIONS.has(value);\n}\n\nexport type CiProgressStatus = 'queued' | 'in_progress' | 'concluded';\n\nconst PROGRESS_STATUSES: ReadonlySet<string> = new Set<CiProgressStatus>([\n 'queued',\n 'in_progress',\n 'concluded',\n]);\n\n/** Normalized trigger reasons rig runs (`schedule` is out of scope). */\nexport type CiTriggerReason = 'push' | 'pull_request' | 'manual';\n\nconst TRIGGER_REASONS: ReadonlySet<string> = new Set<CiTriggerReason>([\n 'push',\n 'pull_request',\n 'manual',\n]);\n\nexport type CiAdmissionPolicy =\n 'operator-selected' | 'maintainer-request' | 'open';\nexport type CiExecutionPolicy = 'automatic' | 'request-required';\nexport type CiBillingPolicy = 'not-required' | 'out-of-band';\n\nconst ADMISSIONS: ReadonlySet<string> = new Set<CiAdmissionPolicy>([\n 'operator-selected',\n 'maintainer-request',\n 'open',\n]);\nconst EXECUTIONS: ReadonlySet<string> = new Set<CiExecutionPolicy>([\n 'automatic',\n 'request-required',\n]);\nconst BILLINGS: ReadonlySet<string> = new Set<CiBillingPolicy>([\n 'not-required',\n 'out-of-band',\n]);\n\n// ---------------------------------------------------------------------------\n// Repo address\n// ---------------------------------------------------------------------------\n\n/** Repo address string `30617:<owner-hex>:<repo-id>`. */\nexport type RepoAddress = string;\n\nconst HEX64 = /^[0-9a-f]{64}$/;\n/** A git object id: SHA-1 (40 hex) or SHA-256 (64 hex). */\nconst GIT_OID = /^[0-9a-f]{40}(?:[0-9a-f]{24})?$/;\nconst REPO_ADDR_RE = /^30617:([0-9a-fA-F]{64}):(.+)$/;\n\nexport function repoAddress(ownerPubkey: string, repoId: string): RepoAddress {\n return `${REPO_ANNOUNCEMENT_KIND}:${ownerPubkey.toLowerCase()}:${repoId}`;\n}\n\nexport function parseRepoAddress(\n a: string\n): { ownerPubkey: string; repoId: string } | null {\n const m = REPO_ADDR_RE.exec(a);\n if (!m) return null;\n return {\n ownerPubkey: (m[1] as string).toLowerCase(),\n repoId: m[2] as string,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Trigger context (the common + trigger-context tags every CI event carries)\n// ---------------------------------------------------------------------------\n\nexport interface CiWorkflowRef {\n /** Workflow file path, relative to the repo root (`w` tag). */\n path: string;\n /** SHA-256 (hex) of the workflow file content at the run's commit. */\n sha256: string;\n}\n\n/**\n * NIP-22 PR context of a `pull_request` run: the PR event as root (`E`/`K`/\n * `P`) and the PR or PR-update event that supplied the commit as parent\n * (`e`/`k`/`p`). `prKind`/`sourceKind` 1617 is rig's departure — see the\n * module header.\n */\nexport interface CiPrContext {\n prEventId: string;\n prAuthor: string;\n prKind: 1617 | 1618;\n sourceEventId: string;\n sourceAuthor: string;\n sourceKind: 1617 | 1618 | 1619;\n}\n\nexport interface CiTriggerContext {\n /** The repo the run is for — the FIRST `a` tag. */\n repoAddr: RepoAddress;\n /** Further `a` tags: the same repo id under other maintainers' announcements. */\n extraRepoAddrs?: string[];\n /** The commit the workflow ran against — the FIRST `c` tag. */\n commit: string;\n /** Extra `c` tags: annotated tag object ids peeling to `commit`. */\n tagObjectIds?: string[];\n workflow: CiWorkflowRef;\n reason: CiTriggerReason;\n /** `r` tag — push runs (and optionally manual runs); never with `pr`. */\n ref?: string;\n pr?: CiPrContext;\n}\n\n/** The frozen request-provenance quote a run carries (`q … service-request|manual-trigger`). */\nexport type CiProvenance =\n | {\n kind: 'service-request';\n eventId: string;\n relayUrl: string;\n pubkey: string;\n }\n | {\n kind: 'manual-trigger';\n eventId: string;\n relayUrl: string;\n pubkey: string;\n };\n\nconst PROVENANCE_MARKERS: ReadonlySet<string> = new Set([\n 'service-request',\n 'manual-trigger',\n]);\n\ninterface TriggerTagOptions {\n /** Manual Triggers carry no `o` (they are always `manual`). */\n omitReason?: boolean;\n /** Manual Triggers' ONLY lowercase `p` is the coordinator. */\n omitPrParentAuthor?: boolean;\n}\n\nfunction triggerTags(\n trigger: Omit<CiTriggerContext, 'reason'> & { reason?: CiTriggerReason },\n opts: TriggerTagOptions = {}\n): string[][] {\n const tags: string[][] = [['a', trigger.repoAddr]];\n for (const a of trigger.extraRepoAddrs ?? []) tags.push(['a', a]);\n tags.push(['c', trigger.commit]);\n for (const c of trigger.tagObjectIds ?? []) tags.push(['c', c]);\n tags.push(['w', trigger.workflow.path, trigger.workflow.sha256]);\n if (!opts.omitReason && trigger.reason !== undefined) {\n tags.push(['o', trigger.reason]);\n }\n if (trigger.pr) {\n tags.push(['E', trigger.pr.prEventId]);\n tags.push(['K', String(trigger.pr.prKind)]);\n tags.push(['P', trigger.pr.prAuthor]);\n tags.push(['e', trigger.pr.sourceEventId]);\n tags.push(['k', String(trigger.pr.sourceKind)]);\n if (!opts.omitPrParentAuthor) tags.push(['p', trigger.pr.sourceAuthor]);\n } else if (trigger.ref !== undefined) {\n // A pull_request run carries NO git-ref `r` tag (NIP-C1 trigger context).\n tags.push(['r', trigger.ref]);\n }\n return tags;\n}\n\n/** The common + trigger-context tags (`a*`, `c*`, `w`, `o`, then `r` | `E K P e k p`). */\nexport function commonTriggerTags(trigger: CiTriggerContext): string[][] {\n return triggerTags(trigger);\n}\n\nfunction values(tags: string[][], name: string): string[][] {\n return tags.filter((t) => t[0] === name);\n}\n\nfunction single(tags: string[][], name: string): string[] | null {\n const found = values(tags, name);\n return found.length === 1 ? (found[0] as string[]) : null;\n}\n\nfunction optionalSingle(\n tags: string[][],\n name: string\n): string[] | null | undefined {\n const found = values(tags, name);\n if (found.length === 0) return undefined;\n return found.length === 1 ? (found[0] as string[]) : null;\n}\n\nfunction parsePrKind(value: string | undefined, allowUpdate: boolean) {\n if (value === '1617') return 1617 as const;\n if (value === '1618') return 1618 as const;\n if (allowUpdate && value === '1619') return 1619 as const;\n return null;\n}\n\n/**\n * Parse the common + trigger-context tags. `defaultReason` supplies the\n * reason when no `o` tag is present (Manual Triggers omit it and are always\n * `manual`); without it a missing `o` is malformed.\n */\nexport function parseCiTriggerContext(\n tags: string[][],\n opts: { defaultReason?: CiTriggerReason } = {}\n): CiTriggerContext | null {\n const aTags = values(tags, 'a');\n if (aTags.length === 0) return null;\n const addrs: string[] = [];\n let repoId: string | null = null;\n for (const t of aTags) {\n const parsed = t[1] === undefined ? null : parseRepoAddress(t[1]);\n if (!parsed) return null;\n // Every `a` MUST describe the same <repo-id>.\n if (repoId !== null && parsed.repoId !== repoId) return null;\n repoId = parsed.repoId;\n addrs.push(repoAddress(parsed.ownerPubkey, parsed.repoId));\n }\n\n const cTags = values(tags, 'c');\n if (cTags.length === 0) return null;\n const commits: string[] = [];\n for (const t of cTags) {\n const c = t[1]?.toLowerCase();\n if (c === undefined || !GIT_OID.test(c)) return null;\n commits.push(c);\n }\n\n const w = single(tags, 'w');\n if (\n !w ||\n w.length < 3 ||\n !w[1] ||\n !HEX64.test((w[2] as string).toLowerCase())\n )\n return null;\n\n const o = optionalSingle(tags, 'o');\n if (o === null) return null;\n let reason: CiTriggerReason;\n if (o === undefined) {\n if (opts.defaultReason === undefined) return null;\n reason = opts.defaultReason;\n } else {\n const v = o[1] ?? '';\n if (!TRIGGER_REASONS.has(v)) return null;\n reason = v as CiTriggerReason;\n }\n\n const trigger: CiTriggerContext = {\n repoAddr: addrs[0] as string,\n commit: commits[0] as string,\n workflow: { path: w[1], sha256: (w[2] as string).toLowerCase() },\n reason,\n };\n if (addrs.length > 1) trigger.extraRepoAddrs = addrs.slice(1);\n if (commits.length > 1) trigger.tagObjectIds = commits.slice(1);\n\n const E = optionalSingle(tags, 'E');\n if (E === null) return null;\n if (E !== undefined) {\n const K = single(tags, 'K');\n const P = single(tags, 'P');\n const prKind = parsePrKind(K?.[1], false) as 1617 | 1618 | null;\n const prEventId = E[1]?.toLowerCase();\n const prAuthor = P?.[1]?.toLowerCase();\n if (\n prKind === null ||\n prEventId === undefined ||\n !HEX64.test(prEventId) ||\n prAuthor === undefined ||\n !HEX64.test(prAuthor)\n ) {\n return null;\n }\n const e = optionalSingle(tags, 'e');\n const k = optionalSingle(tags, 'k');\n const p = optionalSingle(tags, 'p');\n if (e === null || k === null || p === null) return null;\n let sourceEventId = prEventId;\n let sourceKind: 1617 | 1618 | 1619 = prKind;\n if (e !== undefined) {\n const id = e[1]?.toLowerCase();\n if (id === undefined || !HEX64.test(id)) return null;\n sourceEventId = id;\n const parsedKind = parsePrKind(k?.[1], true);\n if (k !== undefined && parsedKind === null) return null;\n sourceKind = parsedKind ?? prKind;\n }\n // The manual-trigger PR form carries no parent `p` (its only lowercase\n // `p` is the coordinator, stripped by parseCiManualTrigger before we get\n // here); the source author then defaults to the PR author.\n let sourceAuthor = prAuthor;\n if (p !== undefined) {\n const author = p[1]?.toLowerCase();\n if (author === undefined || !HEX64.test(author)) return null;\n sourceAuthor = author;\n }\n trigger.pr = {\n prEventId,\n prAuthor,\n prKind,\n sourceEventId,\n sourceAuthor,\n sourceKind,\n };\n if (values(tags, 'r').some((t) => t[1]?.startsWith('refs/'))) return null;\n } else {\n const refs = values(tags, 'r').filter((t) => t[1]?.startsWith('refs/'));\n if (refs.length > 1) return null;\n if (refs.length === 1) trigger.ref = (refs[0] as string[])[1] as string;\n }\n return trigger;\n}\n\nfunction provenanceTag(p: CiProvenance): string[] {\n return ['q', p.eventId, p.relayUrl, p.pubkey, p.kind];\n}\n\nfunction parseProvenance(tags: string[][]): CiProvenance | null | undefined {\n const quotes = values(tags, 'q').filter(\n (t) => t[4] !== undefined && PROVENANCE_MARKERS.has(t[4])\n );\n if (quotes.length === 0) return undefined;\n if (quotes.length > 1) return null;\n const q = quotes[0] as string[];\n const eventId = q[1]?.toLowerCase();\n const pubkey = q[3]?.toLowerCase();\n if (\n eventId === undefined ||\n !HEX64.test(eventId) ||\n pubkey === undefined ||\n !HEX64.test(pubkey)\n ) {\n return null;\n }\n return {\n kind: q[4] as CiProvenance['kind'],\n eventId,\n relayUrl: q[2] ?? '',\n pubkey,\n };\n}\n\n// ---------------------------------------------------------------------------\n// kind:19843 — Coordinator Advertisement\n// ---------------------------------------------------------------------------\n\nexport interface CiAdvertisementInput {\n version: string;\n /** Accepted `act` selectors (emitted as `R = act:<selector>`). */\n selectors: string[];\n admission: CiAdmissionPolicy;\n execution: CiExecutionPolicy;\n billing?: CiBillingPolicy;\n secretsKey?: { pubkey: string; inboxRelays: string[] };\n /** NIP-40 expiration: > created_at, ≤ created_at + 30 min. */\n expiresAt: number;\n}\n\nexport interface CiAdvertisement {\n eventId: string;\n pubkey: string;\n createdAt: number;\n version: string;\n /** Supported runner families (`W`), case-folded + deduplicated. */\n families: string[];\n /** Accepted `<family>:<selector>` values (`R`), case-folded + deduplicated. */\n selectors: string[];\n admission: CiAdmissionPolicy;\n execution: CiExecutionPolicy;\n billing?: CiBillingPolicy;\n secretsKey?: { pubkey: string; inboxRelays: string[] };\n expiresAt: number;\n}\n\nfunction now(): number {\n return Math.floor(Date.now() / 1000);\n}\n\nfunction assertExpiration(\n createdAt: number,\n expiresAt: number,\n maxTtl: number\n): void {\n if (!Number.isInteger(expiresAt) || expiresAt <= createdAt) {\n throw new Error('expiration must be later than created_at');\n }\n if (expiresAt - createdAt > maxTtl) {\n throw new Error(\n `expiration must be no more than ${maxTtl}s after created_at`\n );\n }\n}\n\nfunction foldUnique(items: Iterable<string>): string[] {\n const out: string[] = [];\n const seen = new Set<string>();\n for (const raw of items) {\n const v = raw.toLowerCase();\n if (!seen.has(v)) {\n seen.add(v);\n out.push(v);\n }\n }\n return out;\n}\n\nexport function buildCiAdvertisement(\n input: CiAdvertisementInput,\n createdAt: number = now()\n): UnsignedEvent {\n const selectors = foldUnique(input.selectors);\n if (selectors.length === 0) {\n throw new Error('an advertisement needs at least one runner selector');\n }\n if (input.secretsKey && input.secretsKey.inboxRelays.length === 0) {\n throw new Error('secrets-key needs at least one secret-inbox relay');\n }\n assertExpiration(createdAt, input.expiresAt, CI_MAX_ADVERTISEMENT_TTL);\n const tags: string[][] = [\n ['software', CI_SOFTWARE, input.version],\n ['W', CI_RUNNER_FAMILY],\n ...selectors.map((s) => ['R', `${CI_RUNNER_FAMILY}:${s}`]),\n ['M', input.admission],\n ['X', input.execution],\n ];\n if (input.billing) tags.push(['B', input.billing]);\n if (input.secretsKey) {\n tags.push([\n 'secrets-key',\n 'nip44-v2',\n input.secretsKey.pubkey.toLowerCase(),\n ...input.secretsKey.inboxRelays,\n ]);\n }\n tags.push(['expiration', String(input.expiresAt)]);\n return {\n kind: CI_ADVERTISEMENT_KIND,\n content: '',\n tags,\n created_at: createdAt,\n };\n}\n\nexport function parseCiAdvertisement(ev: NostrEvent): CiAdvertisement | null {\n if (ev.kind !== CI_ADVERTISEMENT_KIND || ev.content !== '') return null;\n const { tags } = ev;\n if (values(tags, 'd').length > 0) return null;\n const M = single(tags, 'M');\n const X = single(tags, 'X');\n const exp = single(tags, 'expiration');\n if (!M || !X || !exp) return null;\n if (!ADMISSIONS.has(M[1] ?? '') || !EXECUTIONS.has(X[1] ?? '')) return null;\n const B = optionalSingle(tags, 'B');\n if (B === null || (B !== undefined && !BILLINGS.has(B[1] ?? ''))) return null;\n const expiresAt = Number(exp[1]);\n if (!Number.isInteger(expiresAt) || expiresAt <= ev.created_at) return null;\n\n const families = foldUnique(\n values(tags, 'W')\n .map((t) => t[1] ?? '')\n .filter((v) => v !== '')\n );\n const selectors = foldUnique(\n values(tags, 'R')\n .map((t) => t[1] ?? '')\n .filter((v) => v !== '')\n );\n if (families.length === 0 || selectors.length === 0) return null;\n // Every R's family must be advertised and every family must have an R.\n const covered = new Set<string>();\n for (const s of selectors) {\n const family = s.slice(0, s.indexOf(':'));\n if (!family || !families.includes(family)) return null;\n covered.add(family);\n }\n if (covered.size !== families.length) return null;\n\n const software = optionalSingle(tags, 'software');\n if (software === null) return null;\n\n const sk = optionalSingle(tags, 'secrets-key');\n if (sk === null) return null;\n let secretsKey: CiAdvertisement['secretsKey'];\n if (sk !== undefined) {\n const pubkey = sk[2]?.toLowerCase();\n const inboxRelays = sk.slice(3).filter((u) => /^wss?:\\/\\//i.test(u));\n if (\n sk[1] !== 'nip44-v2' ||\n pubkey === undefined ||\n !HEX64.test(pubkey) ||\n inboxRelays.length === 0\n ) {\n return null;\n }\n secretsKey = { pubkey, inboxRelays };\n }\n\n const result: CiAdvertisement = {\n eventId: ev.id,\n pubkey: ev.pubkey.toLowerCase(),\n createdAt: ev.created_at,\n version: software?.[2] ?? '',\n families,\n selectors,\n admission: M[1] as CiAdmissionPolicy,\n execution: X[1] as CiExecutionPolicy,\n expiresAt,\n };\n if (B !== undefined) result.billing = B[1] as CiBillingPolicy;\n if (secretsKey) result.secretsKey = secretsKey;\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// kind:9843 / 9844 — Service Request / Stop\n// ---------------------------------------------------------------------------\n\nexport interface ServiceControl {\n kind: 'request' | 'stop';\n eventId: string;\n pubkey: string;\n createdAt: number;\n repoAddr: RepoAddress;\n coordinatorPubkey: string;\n relayHint?: string;\n}\n\nfunction buildServiceControl(\n kind: number,\n repoAddr: RepoAddress,\n coordinatorPubkey: string,\n relayHint: string | undefined,\n createdAt: number\n): UnsignedEvent {\n const a = relayHint ? ['a', repoAddr, relayHint] : ['a', repoAddr];\n return {\n kind,\n content: '',\n tags: [a, ['p', coordinatorPubkey.toLowerCase()]],\n created_at: createdAt,\n };\n}\n\nexport function buildCiServiceRequest(\n repoAddr: RepoAddress,\n coordinatorPubkey: string,\n relayHint?: string,\n createdAt: number = now()\n): UnsignedEvent {\n return buildServiceControl(\n CI_SERVICE_REQUEST_KIND,\n repoAddr,\n coordinatorPubkey,\n relayHint,\n createdAt\n );\n}\n\nexport function buildCiServiceStop(\n repoAddr: RepoAddress,\n coordinatorPubkey: string,\n relayHint?: string,\n createdAt: number = now()\n): UnsignedEvent {\n return buildServiceControl(\n CI_SERVICE_STOP_KIND,\n repoAddr,\n coordinatorPubkey,\n relayHint,\n createdAt\n );\n}\n\nexport function parseCiServiceControl(ev: NostrEvent): ServiceControl | null {\n if (ev.kind !== CI_SERVICE_REQUEST_KIND && ev.kind !== CI_SERVICE_STOP_KIND)\n return null;\n if (ev.content !== '') return null;\n const { tags } = ev;\n if (values(tags, 'd').length > 0 || values(tags, 'expiration').length > 0)\n return null;\n const a = single(tags, 'a');\n const p = single(tags, 'p');\n if (!a || !p) return null;\n const addr = a[1] === undefined ? null : parseRepoAddress(a[1]);\n const coordinator = p[1]?.toLowerCase();\n if (!addr || coordinator === undefined || !HEX64.test(coordinator))\n return null;\n const control: ServiceControl = {\n kind: ev.kind === CI_SERVICE_REQUEST_KIND ? 'request' : 'stop',\n eventId: ev.id,\n pubkey: ev.pubkey.toLowerCase(),\n createdAt: ev.created_at,\n repoAddr: repoAddress(addr.ownerPubkey, addr.repoId),\n coordinatorPubkey: coordinator,\n };\n if (a[2]) control.relayHint = a[2];\n return control;\n}\n\n/**\n * NIP-C1 total order for controls (and secret updates): a greater\n * `created_at` is later; at equal timestamps the lexicographically LOWER\n * event id is later. Returns <0 when `a` is earlier than `b`.\n */\nexport function controlOrder(\n a: { createdAt: number; eventId: string },\n b: { createdAt: number; eventId: string }\n): number {\n if (a.createdAt !== b.createdAt) return a.createdAt - b.createdAt;\n if (a.eventId === b.eventId) return 0;\n return a.eventId < b.eventId ? 1 : -1;\n}\n\nexport interface SelectServiceRequestsOptions {\n coordinatorPubkey: string;\n /** When given, controls for other repo addresses are ignored. */\n repoAddr?: RepoAddress;\n /** Current owner ∪ maintainers (lowercase hex) — the accepted requesters. */\n authorized: Set<string>;\n /**\n * Extra requester pubkeys the operator explicitly accepts (NIP-C1: \"an\n * operator MAY explicitly accept other requester pubkeys\"). Their Requests\n * count, but they stay non-maintainers: their Stops close only their own\n * Requests, and runs they cause carry lower trust.\n */\n acceptedRequesters?: Set<string>;\n}\n\nexport interface SelectedServiceRequests {\n /** The newest accepted, unstopped Request — service is eligible iff non-null. */\n active: ServiceControl | null;\n /** Every accepted Request still open, earliest first. */\n open: ServiceControl[];\n}\n\n/**\n * Reduce the Service Request / Stop history for one coordinator + repo\n * perspective under the default policy (only current maintainers' Requests\n * are accepted). A maintainer's Stop closes every earlier Request; any other\n * author's Stop closes only that author's own earlier Requests — so a removed\n * maintainer keeps the author-local effect but loses the repo-wide one.\n */\nexport function selectServiceRequests(\n controls: ServiceControl[],\n opts: SelectServiceRequestsOptions\n): SelectedServiceRequests {\n const coordinator = opts.coordinatorPubkey.toLowerCase();\n const authorized = new Set([...opts.authorized].map((p) => p.toLowerCase()));\n const accepted = new Set([\n ...authorized,\n ...[...(opts.acceptedRequesters ?? [])].map((p) => p.toLowerCase()),\n ]);\n const relevant = controls\n .filter(\n (c) =>\n c.coordinatorPubkey.toLowerCase() === coordinator &&\n (opts.repoAddr === undefined || c.repoAddr === opts.repoAddr)\n )\n .sort(controlOrder);\n\n let open: ServiceControl[] = [];\n for (const control of relevant) {\n const author = control.pubkey.toLowerCase();\n if (control.kind === 'request') {\n if (accepted.has(author)) open.push(control);\n continue;\n }\n open = authorized.has(author)\n ? []\n : open.filter((r) => r.pubkey.toLowerCase() !== author);\n }\n return {\n active: open.length > 0 ? (open[open.length - 1] as ServiceControl) : null,\n open,\n };\n}\n\n// ---------------------------------------------------------------------------\n// kind:9840 — Manual Trigger\n// ---------------------------------------------------------------------------\n\nexport interface CiManualTrigger {\n eventId: string;\n pubkey: string;\n createdAt: number;\n coordinatorPubkey: string;\n trigger: Omit<CiTriggerContext, 'reason'>;\n}\n\nexport function buildCiManualTrigger(\n coordinatorPubkey: string,\n trigger: Omit<CiTriggerContext, 'reason'>,\n createdAt: number = now()\n): UnsignedEvent {\n return {\n kind: CI_MANUAL_TRIGGER_KIND,\n content: '',\n tags: [\n ['p', coordinatorPubkey.toLowerCase()],\n ...triggerTags(trigger, { omitReason: true, omitPrParentAuthor: true }),\n ],\n created_at: createdAt,\n };\n}\n\n/**\n * Parse a Manual Trigger. With `coordinatorPubkey` given, a request addressed\n * to any other coordinator is ignored (`null`). The ONLY lowercase `p` on a\n * Manual Trigger is the coordinator — a second one is malformed.\n */\nexport function parseCiManualTrigger(\n ev: NostrEvent,\n coordinatorPubkey?: string\n): CiManualTrigger | null {\n if (ev.kind !== CI_MANUAL_TRIGGER_KIND || ev.content !== '') return null;\n const p = single(ev.tags, 'p');\n const coordinator = p?.[1]?.toLowerCase();\n if (!p || coordinator === undefined || !HEX64.test(coordinator)) return null;\n if (\n coordinatorPubkey !== undefined &&\n coordinator !== coordinatorPubkey.toLowerCase()\n )\n return null;\n if (values(ev.tags, 'o').length > 0) return null;\n const rest = ev.tags.filter((t) => t[0] !== 'p');\n const parsed = parseCiTriggerContext(rest, { defaultReason: 'manual' });\n if (!parsed) return null;\n const { reason: _reason, ...trigger } = parsed;\n return {\n eventId: ev.id,\n pubkey: ev.pubkey.toLowerCase(),\n createdAt: ev.created_at,\n coordinatorPubkey: coordinator,\n trigger,\n };\n}\n\n// ---------------------------------------------------------------------------\n// kind:29846 — Repository Secret Update (envelope only; ../ci/secrets.ts\n// owns the NIP-44 payload)\n// ---------------------------------------------------------------------------\n\nexport interface CiSecretUpdateArgs {\n repoAddr: RepoAddress;\n coordinatorPubkey: string;\n advertisementId: string;\n advertisementRelayHint?: string;\n senderPubkey: string;\n recipientPubkey: string;\n ciphertext: string;\n createdAt: number;\n}\n\nexport interface CiSecretUpdate {\n eventId: string;\n pubkey: string;\n createdAt: number;\n repoAddr: RepoAddress;\n coordinatorPubkey: string;\n advertisementId: string;\n senderPubkey: string;\n recipientPubkey: string;\n ciphertext: string;\n}\n\nconst SECRET_UPDATE_TAGS = ['a', 'p', 'e', 'sender', 'recipient', 'encryption'];\n\nexport function buildCiSecretUpdate(args: CiSecretUpdateArgs): UnsignedEvent {\n return {\n kind: CI_SECRET_UPDATE_KIND,\n content: args.ciphertext,\n tags: [\n ['a', args.repoAddr],\n ['p', args.coordinatorPubkey.toLowerCase()],\n [\n 'e',\n args.advertisementId,\n args.advertisementRelayHint ?? '',\n 'secrets-key',\n ],\n ['sender', args.senderPubkey.toLowerCase()],\n ['recipient', args.recipientPubkey.toLowerCase()],\n ['encryption', 'nip44-v2'],\n ],\n created_at: args.createdAt,\n };\n}\n\nexport function parseCiSecretUpdate(ev: NostrEvent): CiSecretUpdate | null {\n if (ev.kind !== CI_SECRET_UPDATE_KIND) return null;\n if (ev.content === '' || ev.content.length > 100 * 1024) return null;\n const { tags } = ev;\n if (tags.length !== SECRET_UPDATE_TAGS.length) return null;\n for (const name of SECRET_UPDATE_TAGS) {\n if (values(tags, name).length !== 1) return null;\n }\n const a = single(tags, 'a') as string[];\n const p = single(tags, 'p') as string[];\n const e = single(tags, 'e') as string[];\n const sender = single(tags, 'sender') as string[];\n const recipient = single(tags, 'recipient') as string[];\n const encryption = single(tags, 'encryption') as string[];\n\n const addr = a[1] === undefined ? null : parseRepoAddress(a[1]);\n if (!addr || addr.ownerPubkey !== ev.pubkey.toLowerCase()) return null;\n const coordinator = p[1]?.toLowerCase();\n const advertisementId = e[1]?.toLowerCase();\n const senderPubkey = sender[1]?.toLowerCase();\n const recipientPubkey = recipient[1]?.toLowerCase();\n if (\n coordinator === undefined ||\n !HEX64.test(coordinator) ||\n advertisementId === undefined ||\n !HEX64.test(advertisementId) ||\n e[3] !== 'secrets-key' ||\n senderPubkey === undefined ||\n !HEX64.test(senderPubkey) ||\n recipientPubkey === undefined ||\n !HEX64.test(recipientPubkey) ||\n encryption[1] !== 'nip44-v2'\n ) {\n return null;\n }\n return {\n eventId: ev.id,\n pubkey: ev.pubkey.toLowerCase(),\n createdAt: ev.created_at,\n repoAddr: repoAddress(addr.ownerPubkey, addr.repoId),\n coordinatorPubkey: coordinator,\n advertisementId,\n senderPubkey,\n recipientPubkey,\n ciphertext: ev.content,\n };\n}\n\n// ---------------------------------------------------------------------------\n// kind:9841 — Job Result\n// ---------------------------------------------------------------------------\n\nexport interface CiArtifact {\n url: string;\n filename: string;\n name: string;\n}\n\nexport interface CiJobResultInput {\n trigger: CiTriggerContext;\n /** `39842:<coordinator>:<runId>` — the run's Workflow Progress address. */\n progressAddress: string;\n /** Relay the Progress event was published to (the `q` relay hint). */\n relayUrl: string;\n jobId: string;\n name?: string;\n conclusion: CiConclusion;\n logsUrl: string;\n logTail: string;\n logOmittedBytes: number;\n artifacts?: CiArtifact[];\n queuedAt?: number;\n startedAt?: number;\n exitCode?: number;\n runsOn?: string[];\n /** MAY be carried on a Job Result (never a service-request by rig's coordinator). */\n provenance?: CiProvenance;\n}\n\nexport interface CiJobResult {\n eventId: string;\n pubkey: string;\n createdAt: number;\n trigger: CiTriggerContext;\n progressAddress: string;\n jobId: string;\n name?: string;\n conclusion: CiConclusion;\n logsUrl?: string;\n logTail: string;\n logOmittedBytes: number;\n artifacts: CiArtifact[];\n queuedAt?: number;\n startedAt?: number;\n exitCode?: number;\n runsOn: string[];\n provenance?: CiProvenance;\n}\n\nconst LOG_TAIL_HEADER = /^\\[log-tail omitted=(\\d+)\\]\\n?/;\n\nconst PROGRESS_ADDR_RE = /^39842:[0-9a-f]{64}:.+$/i;\n\nexport function buildCiJobResult(\n input: CiJobResultInput,\n createdAt: number = now()\n): UnsignedEvent {\n const tags: string[][] = [\n ...commonTriggerTags(input.trigger),\n ['q', input.progressAddress, input.relayUrl],\n ['job', input.jobId],\n ];\n if (input.name !== undefined) tags.push(['name', input.name]);\n tags.push(['conclusion', input.conclusion]);\n tags.push(['logs', input.logsUrl]);\n for (const a of input.artifacts ?? []) {\n tags.push(['artifact', a.url, a.filename, a.name]);\n }\n if (input.queuedAt !== undefined)\n tags.push(['queued_at', String(input.queuedAt)]);\n if (input.startedAt !== undefined)\n tags.push(['started_at', String(input.startedAt)]);\n if (input.exitCode !== undefined)\n tags.push(['exit_code', String(input.exitCode)]);\n if (input.runsOn && input.runsOn.length > 0)\n tags.push(['runs_on', ...input.runsOn]);\n if (input.provenance) tags.push(provenanceTag(input.provenance));\n return {\n kind: CI_JOB_RESULT_KIND,\n content: `[log-tail omitted=${input.logOmittedBytes}]\\n${input.logTail}`,\n tags,\n created_at: createdAt,\n };\n}\n\nfunction optionalInt(\n tags: string[][],\n name: string\n): number | null | undefined {\n const t = optionalSingle(tags, name);\n if (t === null) return null;\n if (t === undefined) return undefined;\n const n = Number(t[1]);\n return Number.isInteger(n) ? n : null;\n}\n\nexport function parseCiJobResult(ev: NostrEvent): CiJobResult | null {\n if (ev.kind !== CI_JOB_RESULT_KIND) return null;\n const { tags } = ev;\n const trigger = parseCiTriggerContext(tags);\n if (!trigger) return null;\n const progress = values(tags, 'q').filter(\n (t) => t[1] !== undefined && PROGRESS_ADDR_RE.test(t[1])\n );\n if (progress.length !== 1) return null;\n const job = single(tags, 'job');\n const conclusion = single(tags, 'conclusion');\n if (!job || !job[1] || !conclusion || !isCiConclusion(conclusion[1] ?? ''))\n return null;\n const name = optionalSingle(tags, 'name');\n const logs = optionalSingle(tags, 'logs');\n if (name === null || logs === null) return null;\n const queuedAt = optionalInt(tags, 'queued_at');\n const startedAt = optionalInt(tags, 'started_at');\n const exitCode = optionalInt(tags, 'exit_code');\n if (queuedAt === null || startedAt === null || exitCode === null) return null;\n const runsOn = optionalSingle(tags, 'runs_on');\n if (runsOn === null) return null;\n const provenance = parseProvenance(tags);\n if (provenance === null) return null;\n\n const artifacts: CiArtifact[] = [];\n for (const t of values(tags, 'artifact')) {\n if (!t[1] || t[2] === undefined || t[3] === undefined) return null;\n artifacts.push({ url: t[1], filename: t[2], name: t[3] });\n }\n\n const header = LOG_TAIL_HEADER.exec(ev.content);\n const logOmittedBytes = header ? Number(header[1]) : 0;\n const logTail = header ? ev.content.slice(header[0].length) : ev.content;\n\n const result: CiJobResult = {\n eventId: ev.id,\n pubkey: ev.pubkey.toLowerCase(),\n createdAt: ev.created_at,\n trigger,\n progressAddress: (progress[0] as string[])[1] as string,\n jobId: job[1],\n conclusion: conclusion[1] as CiConclusion,\n logTail,\n logOmittedBytes,\n artifacts,\n runsOn: runsOn ? runsOn.slice(1) : [],\n };\n if (name?.[1] !== undefined) result.name = name[1];\n if (logs?.[1]) result.logsUrl = logs[1];\n if (queuedAt !== undefined) result.queuedAt = queuedAt;\n if (startedAt !== undefined) result.startedAt = startedAt;\n if (exitCode !== undefined) result.exitCode = exitCode;\n if (provenance) result.provenance = provenance;\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// kind:9842 — Workflow Result\n// ---------------------------------------------------------------------------\n\n/** A `q` quote of one Job Result (job id as the marker). */\nexport interface CiJobQuote {\n eventId: string;\n relayUrl: string;\n pubkey: string;\n jobId: string;\n}\n\nexport interface CiWorkflowResultInput {\n trigger: CiTriggerContext;\n runId: string;\n conclusion: CiConclusion;\n queuedAt?: number;\n startedAt?: number;\n provenance?: CiProvenance;\n jobs: CiJobQuote[];\n}\n\nexport interface CiWorkflowResult {\n eventId: string;\n pubkey: string;\n createdAt: number;\n trigger: CiTriggerContext;\n runId: string;\n conclusion: CiConclusion;\n queuedAt?: number;\n startedAt?: number;\n provenance?: CiProvenance;\n jobs: CiJobQuote[];\n}\n\nfunction jobQuoteTag(j: CiJobQuote): string[] {\n return ['q', j.eventId, j.relayUrl, j.pubkey, j.jobId];\n}\n\nfunction parseJobQuotes(tags: string[][]): CiJobQuote[] | null {\n const jobs: CiJobQuote[] = [];\n for (const t of values(tags, 'q')) {\n const marker = t[4];\n if (marker === undefined || PROVENANCE_MARKERS.has(marker)) continue;\n if (t[1] !== undefined && PROGRESS_ADDR_RE.test(t[1])) continue;\n const eventId = t[1]?.toLowerCase();\n const pubkey = t[3]?.toLowerCase();\n if (\n eventId === undefined ||\n !HEX64.test(eventId) ||\n pubkey === undefined ||\n !HEX64.test(pubkey) ||\n marker === ''\n ) {\n return null;\n }\n jobs.push({ eventId, relayUrl: t[2] ?? '', pubkey, jobId: marker });\n }\n return jobs;\n}\n\nexport function buildCiWorkflowResult(\n input: CiWorkflowResultInput,\n createdAt: number = now()\n): UnsignedEvent {\n const tags: string[][] = [\n ...commonTriggerTags(input.trigger),\n ['r', input.runId],\n ['conclusion', input.conclusion],\n ];\n if (input.queuedAt !== undefined)\n tags.push(['queued_at', String(input.queuedAt)]);\n if (input.startedAt !== undefined)\n tags.push(['started_at', String(input.startedAt)]);\n if (input.provenance) tags.push(provenanceTag(input.provenance));\n for (const j of input.jobs) tags.push(jobQuoteTag(j));\n return {\n kind: CI_WORKFLOW_RESULT_KIND,\n content: '',\n tags,\n created_at: createdAt,\n };\n}\n\nexport function parseCiWorkflowResult(ev: NostrEvent): CiWorkflowResult | null {\n if (ev.kind !== CI_WORKFLOW_RESULT_KIND || ev.content !== '') return null;\n const { tags } = ev;\n const trigger = parseCiTriggerContext(tags);\n if (!trigger) return null;\n // On push results the git ref and the run id share `r`; the run id is the\n // one NOT starting with `refs/`.\n const runIds = values(tags, 'r').filter(\n (t) => t[1] && !t[1].startsWith('refs/')\n );\n if (runIds.length !== 1) return null;\n const conclusion = single(tags, 'conclusion');\n if (!conclusion || !isCiConclusion(conclusion[1] ?? '')) return null;\n const queuedAt = optionalInt(tags, 'queued_at');\n const startedAt = optionalInt(tags, 'started_at');\n if (queuedAt === null || startedAt === null) return null;\n const provenance = parseProvenance(tags);\n if (provenance === null) return null;\n const jobs = parseJobQuotes(tags);\n if (!jobs) return null;\n\n const result: CiWorkflowResult = {\n eventId: ev.id,\n pubkey: ev.pubkey.toLowerCase(),\n createdAt: ev.created_at,\n trigger,\n runId: (runIds[0] as string[])[1] as string,\n conclusion: conclusion[1] as CiConclusion,\n jobs,\n };\n if (queuedAt !== undefined) result.queuedAt = queuedAt;\n if (startedAt !== undefined) result.startedAt = startedAt;\n if (provenance) result.provenance = provenance;\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// kind:39842 — Workflow Progress\n// ---------------------------------------------------------------------------\n\nexport interface CiWorkflowProgressInput extends Omit<\n CiWorkflowResultInput,\n 'conclusion'\n> {\n status: CiProgressStatus;\n /** Required iff `status === 'concluded'`. */\n conclusion?: CiConclusion;\n /** Capacity rounds before start (queued only). */\n queue?: number;\n /** Job ids currently executing. */\n inProgress?: string[];\n /** NIP-40 expiration: > created_at, ≤ created_at + 30 min. */\n expiresAt: number;\n}\n\nexport interface CiWorkflowProgress {\n eventId: string;\n pubkey: string;\n createdAt: number;\n trigger: CiTriggerContext;\n runId: string;\n status: CiProgressStatus;\n conclusion?: CiConclusion;\n queue?: number;\n inProgress: string[];\n queuedAt?: number;\n startedAt?: number;\n expiresAt: number;\n provenance?: CiProvenance;\n jobs: CiJobQuote[];\n}\n\nexport function buildCiWorkflowProgress(\n input: CiWorkflowProgressInput,\n createdAt: number = now()\n): UnsignedEvent {\n if (input.status === 'concluded' && input.conclusion === undefined) {\n throw new Error('a concluded progress event needs a conclusion');\n }\n if (input.status !== 'concluded' && input.conclusion !== undefined) {\n throw new Error('only a concluded progress event may carry a conclusion');\n }\n assertExpiration(createdAt, input.expiresAt, CI_MAX_PROGRESS_TTL);\n const tags: string[][] = [\n ...commonTriggerTags(input.trigger),\n ['d', input.runId],\n ['status', input.status],\n ];\n if (input.queue !== undefined) tags.push(['queue', String(input.queue)]);\n if (input.inProgress && input.inProgress.length > 0) {\n tags.push(['in-progress', ...input.inProgress]);\n }\n if (input.conclusion !== undefined)\n tags.push(['conclusion', input.conclusion]);\n if (input.queuedAt !== undefined)\n tags.push(['queued_at', String(input.queuedAt)]);\n if (input.startedAt !== undefined)\n tags.push(['started_at', String(input.startedAt)]);\n tags.push(['expiration', String(input.expiresAt)]);\n // A queued standing-service marker MUST omit the service-request quote:\n // final authorization is only selected at runner handoff.\n if (\n input.provenance &&\n !(input.status === 'queued' && input.provenance.kind === 'service-request')\n ) {\n tags.push(provenanceTag(input.provenance));\n }\n for (const j of input.jobs) tags.push(jobQuoteTag(j));\n return {\n kind: CI_WORKFLOW_PROGRESS_KIND,\n content: '',\n tags,\n created_at: createdAt,\n };\n}\n\nexport function parseCiWorkflowProgress(\n ev: NostrEvent\n): CiWorkflowProgress | null {\n if (ev.kind !== CI_WORKFLOW_PROGRESS_KIND || ev.content !== '') return null;\n const { tags } = ev;\n const trigger = parseCiTriggerContext(tags);\n if (!trigger) return null;\n const d = single(tags, 'd');\n const status = single(tags, 'status');\n const exp = single(tags, 'expiration');\n if (!d || !d[1] || !status || !PROGRESS_STATUSES.has(status[1] ?? '') || !exp)\n return null;\n const expiresAt = Number(exp[1]);\n if (!Number.isInteger(expiresAt)) return null;\n const conclusion = optionalSingle(tags, 'conclusion');\n if (conclusion === null) return null;\n if (status[1] === 'concluded') {\n if (!conclusion || !isCiConclusion(conclusion[1] ?? '')) return null;\n } else if (conclusion !== undefined) {\n return null;\n }\n const queue = optionalInt(tags, 'queue');\n const queuedAt = optionalInt(tags, 'queued_at');\n const startedAt = optionalInt(tags, 'started_at');\n if (queue === null || queuedAt === null || startedAt === null) return null;\n const inProgress = optionalSingle(tags, 'in-progress');\n if (inProgress === null) return null;\n const provenance = parseProvenance(tags);\n if (provenance === null) return null;\n const jobs = parseJobQuotes(tags);\n if (!jobs) return null;\n\n const result: CiWorkflowProgress = {\n eventId: ev.id,\n pubkey: ev.pubkey.toLowerCase(),\n createdAt: ev.created_at,\n trigger,\n runId: d[1],\n status: status[1] as CiProgressStatus,\n inProgress: inProgress ? inProgress.slice(1) : [],\n expiresAt,\n jobs,\n };\n if (conclusion?.[1] !== undefined)\n result.conclusion = conclusion[1] as CiConclusion;\n if (queue !== undefined) result.queue = queue;\n if (queuedAt !== undefined) result.queuedAt = queuedAt;\n if (startedAt !== undefined) result.startedAt = startedAt;\n if (provenance) result.provenance = provenance;\n return result;\n}\n","/**\n * Repository Secret Update payloads (rig#125): the NIP-44 v2 ciphertext a\n * kind:29846 carries, its plaintext rules, and the per-name ordering that\n * turns a stream of updates into the coordinator's secret inventory.\n * docs/specs/nip-c1.md \"Repository Secret Update\" is the contract.\n *\n * The maintainer signs the OUTER event with their identity but encrypts\n * with a FRESH per-submission sender key to the coordinator's advertised\n * `secrets-key` (a short-lived transport key, never the coordinator's\n * signing key). The plaintext repeats only two bindings — `author` and\n * `created_at` — so captured ciphertext cannot be re-signed into another\n * maintainer's authority or moved to a newer ordering position; the rest is\n * authenticated by the outer signature and not duplicated.\n *\n * The inventory keeps a value-or-tombstone per name with the update's\n * `(created_at, event id)` so that out-of-order or duplicate relay delivery\n * can never resurrect an older value (a remove is an ordering tombstone).\n * rig persists this inventory under the coordinator's state dir (slice 4);\n * the bunker-sealed storage mode NIP-C1 defines is out of scope.\n */\n\nimport { v2 as nip44 } from 'nostr-tools/nip44';\nimport { generateSecretKey, getPublicKey } from 'nostr-tools/pure';\nimport { controlOrder } from './nip-c1-events.js';\n\nexport const SECRET_NAME_RE = /^[A-Z_][A-Z0-9_]*$/;\n/** Names a coordinator never injects into jobs (NIP-C1 reserved). */\nexport const RESERVED_SECRET_NAMES: readonly string[] = [\n 'WORKFLOW_SECRETS_DECRYPTION_BUNKER',\n];\n\nexport const MAX_SECRET_NAMES = 100;\nexport const MAX_SECRET_VALUE_BYTES = 16_384;\nexport const MAX_SECRET_PLAINTEXT_BYTES = 65_535;\nexport const MAX_SECRET_CIPHERTEXT_BYTES = 100 * 1024;\n\nexport interface SecretUpdatePlaintext {\n author: string;\n created_at: number;\n set: Record<string, string>;\n remove: string[];\n}\n\nconst HEX64 = /^[0-9a-f]{64}$/i;\n\nfunction utf8Bytes(s: string): number {\n return Buffer.byteLength(s, 'utf-8');\n}\n\nfunction assertName(name: string): void {\n if (!SECRET_NAME_RE.test(name)) {\n throw new Error(`invalid secret name ${JSON.stringify(name)}`);\n }\n if (RESERVED_SECRET_NAMES.includes(name)) {\n throw new Error(`secret name ${name} is reserved`);\n }\n}\n\n/**\n * Validate the plaintext SHAPE + limits (not the outer bindings — see\n * {@link validateSecretUpdate}). Throws on any violation; returns the\n * narrowed value.\n */\nexport function assertSecretUpdateShape(value: unknown): SecretUpdatePlaintext {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error('secret update plaintext must be a JSON object');\n }\n const keys = Object.keys(value).sort();\n if (keys.join(',') !== 'author,created_at,remove,set') {\n throw new Error(\n 'secret update plaintext must contain exactly author, created_at, set, and remove'\n );\n }\n const { author, created_at, set, remove } = value as Record<string, unknown>;\n if (typeof author !== 'string' || !HEX64.test(author)) {\n throw new Error('secret update author must be a 64-hex pubkey');\n }\n if (typeof created_at !== 'number' || !Number.isInteger(created_at)) {\n throw new Error('secret update created_at must be an integer');\n }\n if (set === null || typeof set !== 'object' || Array.isArray(set)) {\n throw new Error('secret update set must be an object');\n }\n if (!Array.isArray(remove) || !remove.every((n) => typeof n === 'string')) {\n throw new Error('secret update remove must be an array of names');\n }\n const setNames = Object.keys(set as Record<string, unknown>);\n const removeNames = remove as string[];\n if (setNames.length === 0 && removeNames.length === 0) {\n throw new Error('secret update needs a non-empty set or remove');\n }\n if (setNames.length + removeNames.length > MAX_SECRET_NAMES) {\n throw new Error(\n `secret update may name at most ${MAX_SECRET_NAMES} secrets`\n );\n }\n for (const name of [...setNames, ...removeNames]) assertName(name);\n const removeSet = new Set(removeNames);\n if (removeSet.size !== removeNames.length) {\n throw new Error('secret update remove lists a name twice');\n }\n for (const name of setNames) {\n if (removeSet.has(name)) {\n throw new Error(`secret ${name} appears in both set and remove`);\n }\n const v = (set as Record<string, unknown>)[name];\n if (typeof v !== 'string' || v === '') {\n throw new Error(`secret ${name} value must be a non-empty string`);\n }\n if (utf8Bytes(v) > MAX_SECRET_VALUE_BYTES) {\n throw new Error(\n `secret ${name} value exceeds ${MAX_SECRET_VALUE_BYTES} bytes`\n );\n }\n }\n return {\n author: author.toLowerCase(),\n created_at,\n set: set as Record<string, string>,\n remove: removeNames,\n };\n}\n\n/** Bind a decrypted plaintext to its outer event: author + created_at MUST match. */\nexport function validateSecretUpdate(\n plain: SecretUpdatePlaintext,\n outer: { pubkey: string; created_at: number }\n): void {\n if (plain.author.toLowerCase() !== outer.pubkey.toLowerCase()) {\n throw new Error('secret update author does not match the signing pubkey');\n }\n if (plain.created_at !== outer.created_at) {\n throw new Error(\n 'secret update created_at does not match the event timestamp'\n );\n }\n}\n\n/**\n * The canonical plaintext JSON — shape, per-name and per-value limits, and\n * the whole-plaintext bound all enforced. This is the one place every\n * NIP-C1 secret-update limit lives: the CLI runs it before touching a relay\n * or wallet, and {@link encryptSecretUpdate} runs it on what it encrypts.\n */\nexport function serializeSecretUpdate(plain: SecretUpdatePlaintext): string {\n const json = JSON.stringify(assertSecretUpdateShape(plain));\n if (utf8Bytes(json) > MAX_SECRET_PLAINTEXT_BYTES) {\n throw new Error(\n `secret update plaintext exceeds ${MAX_SECRET_PLAINTEXT_BYTES} bytes`\n );\n }\n return json;\n}\n\n/** Encrypt one update (NIP-44 v2) from a fresh sender key to the advertised recipient. */\nexport function encryptSecretUpdate(\n plain: SecretUpdatePlaintext,\n senderSecretKey: Uint8Array,\n recipientPubkey: string\n): string {\n const json = serializeSecretUpdate(plain);\n const key = nip44.utils.getConversationKey(senderSecretKey, recipientPubkey);\n return nip44.encrypt(json, key);\n}\n\n/**\n * Decrypt + validate one update with the recipient (secrets-key) secret key\n * and the event's `sender` pubkey. Bounds the ciphertext BEFORE decrypting\n * (nostr-tools asks callers to) and the plaintext after.\n */\nexport function decryptSecretUpdate(\n ciphertext: string,\n recipientSecretKey: Uint8Array,\n senderPubkey: string\n): SecretUpdatePlaintext {\n if (utf8Bytes(ciphertext) > MAX_SECRET_CIPHERTEXT_BYTES) {\n throw new Error('secret update ciphertext exceeds 100 KiB');\n }\n const key = nip44.utils.getConversationKey(recipientSecretKey, senderPubkey);\n const json = nip44.decrypt(ciphertext, key);\n if (utf8Bytes(json) > MAX_SECRET_PLAINTEXT_BYTES) {\n throw new Error(\n `secret update plaintext exceeds ${MAX_SECRET_PLAINTEXT_BYTES} bytes`\n );\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(json);\n } catch {\n throw new Error('secret update plaintext is not JSON');\n }\n return assertSecretUpdateShape(parsed);\n}\n\n// ---------------------------------------------------------------------------\n// Inventory\n// ---------------------------------------------------------------------------\n\nexport interface SecretInventoryEntry {\n /** The value, or `null` for a remove tombstone. */\n value: string | null;\n /** Ordering position of the update that last touched this name. */\n createdAt: number;\n eventId: string;\n /** The maintainer whose update supplied this entry. */\n origin: string;\n}\n\nexport type SecretInventory = Record<string, SecretInventoryEntry>;\n\n/**\n * Apply one accepted update to an inventory (immutably). Per name, the\n * NIP-C1 total order decides: an update only replaces an entry it is LATER\n * than, so replaying an old event — or a remove that arrived before the set\n * it tombstones — never resurrects a stale value.\n */\nexport function applySecretUpdate(\n inventory: SecretInventory,\n plain: SecretUpdatePlaintext,\n eventId: string\n): SecretInventory {\n const next: SecretInventory = { ...inventory };\n const position = { createdAt: plain.created_at, eventId };\n const isLater = (name: string): boolean => {\n const existing = next[name];\n return existing === undefined || controlOrder(position, existing) > 0;\n };\n for (const [name, value] of Object.entries(plain.set)) {\n if (isLater(name)) {\n next[name] = { value, ...position, origin: plain.author };\n }\n }\n for (const name of plain.remove) {\n if (isLater(name)) {\n next[name] = { value: null, ...position, origin: plain.author };\n }\n }\n return next;\n}\n\n/** The injectable name → value map (tombstones dropped). */\nexport function effectiveSecrets(\n inventory: SecretInventory\n): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [name, entry] of Object.entries(inventory)) {\n if (entry.value !== null) out[name] = entry.value;\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Redaction\n// ---------------------------------------------------------------------------\n\n/**\n * Strings shorter than this are never redacted: nothing that short is a\n * secret, and masking `1` or `us` would rewrite every timestamp and exit\n * code in a log. Applies to whole values and to the lines of a multi-line\n * value alike.\n */\nexport const MIN_REDACTED_BYTES = 4;\n\n/**\n * Everything to mask for a set of injected values: each value; each line of\n * a multi-line value (a PEM key or JSON blob is printed line by line, often\n * indented); and the URL-encoded and JSON-escaped forms tools print in error\n * messages (`git clone https://user:p%40ss@…`, `console.log(JSON.stringify(\n * env))`). Longest first, so a target that contains another is never left\n * half visible.\n */\nexport function redactionTargets(values: Iterable<string>): string[] {\n const targets = new Set<string>();\n const add = (s: string): void => {\n if (utf8Bytes(s) >= MIN_REDACTED_BYTES) targets.add(s);\n };\n for (const value of values) {\n const pieces = [value, ...value.split(/\\r?\\n/).map((line) => line.trim())];\n for (const piece of pieces) {\n if (piece === '') continue;\n add(piece);\n add(encodeURIComponent(piece));\n add(JSON.stringify(piece).slice(1, -1));\n }\n }\n return [...targets].sort((a, b) => b.length - a.length);\n}\n\nfunction escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/**\n * Replace every occurrence of every {@link redactionTargets redaction target}\n * in `text` with `***`, in one pass. The coordinator runs job logs and its\n * own log lines through this before they reach the store, the relay, or the\n * operator: act masks secrets in its own output, but no Runner is trusted\n * to, and the 9841 log tail is a public event.\n */\nexport function redactSecretValues(\n text: string,\n values: Iterable<string>\n): string {\n const targets = redactionTargets(values);\n if (targets.length === 0) return text;\n const pattern = new RegExp(targets.map(escapeRegExp).join('|'), 'g');\n return text.replace(pattern, '***');\n}\n\n/** Whether `bytes` (a file about to be uploaded) contain any redaction target. */\nexport function containsSecretValue(\n bytes: Uint8Array,\n values: Iterable<string>\n): boolean {\n const buf = Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n return redactionTargets(values).some((t) => buf.includes(t, 0, 'utf-8'));\n}\n\n/** A fresh NIP-44 recipient (secrets-key) or sender keypair. */\nexport function generateSecretsKey(): {\n secretKey: Uint8Array;\n pubkey: string;\n} {\n const secretKey = generateSecretKey();\n return { secretKey, pubkey: getPublicKey(secretKey) };\n}\n","/**\n * NIP-C1 trust levels (rig#125): how a run's results relate to the repo's\n * maintainers, derived ONLY from Service Requests / Stops and the repo's\n * declared maintainers — never from anything the coordinator asserts about\n * itself. The relay is permissionless, so a stranger's coordinator can\n * publish a green 9842 for anyone's commit; this is the consumer-side filter\n * (the same posture as #287's authorized status authors) that lets\n * `rig ci status --require-ci-trust` and rig-web tell whose CI they are\n * looking at.\n *\n * maintainer-directed the run's frozen provenance quote names a\n * maintainer: a manual trigger they signed, or a\n * Service Request they signed that we have SEEN\n * and that targets this run's publisher;\n * operationally-associated no qualifying quote, but at run time an\n * accepted, unstopped maintainer Request stood for\n * this publisher (it was authorized, just silent);\n * seen-in-network the publisher is itself a maintainer, or SOME\n * pubkey (not a maintainer) requested its service\n * for this repo — e.g. a contributor running their\n * own coordinator against a repo they don't own;\n * no-known-context nothing ties the publisher to the repo.\n */\n\nimport {\n selectServiceRequests,\n type CiProvenance,\n type ServiceControl,\n} from './nip-c1-events.js';\n\nexport type CiTrustLevel =\n | 'maintainer-directed'\n | 'operationally-associated'\n | 'seen-in-network'\n | 'no-known-context';\n\n/** Strongest first. */\nexport const CI_TRUST_ORDER: readonly CiTrustLevel[] = [\n 'maintainer-directed',\n 'operationally-associated',\n 'seen-in-network',\n 'no-known-context',\n];\n\nexport function isCiTrustLevel(value: string): value is CiTrustLevel {\n return (CI_TRUST_ORDER as readonly string[]).includes(value);\n}\n\nexport interface DeriveTrustLevelArgs {\n /** The run's 9842/39842 signer — the coordinator. */\n publisherPubkey: string;\n /** The run's frozen `q … service-request|manual-trigger` quote, if any. */\n provenance?: CiProvenance;\n /** Owner ∪ maintainers of the repo (hex, any case). */\n authorized: Set<string>;\n /** Every 9843/9844 seen for this repo address (any coordinator). */\n controls: ServiceControl[];\n /** The run's `created_at` — requests are evaluated as of this instant. */\n runCreatedAt: number;\n}\n\nexport function deriveTrustLevel(args: DeriveTrustLevelArgs): CiTrustLevel {\n const publisher = args.publisherPubkey.toLowerCase();\n const authorized = new Set([...args.authorized].map((p) => p.toLowerCase()));\n const forPublisher = args.controls.filter(\n (c) => c.coordinatorPubkey.toLowerCase() === publisher\n );\n\n const prov = args.provenance;\n if (prov && authorized.has(prov.pubkey.toLowerCase())) {\n if (prov.kind === 'manual-trigger') return 'maintainer-directed';\n const quoted = prov.eventId.toLowerCase();\n if (\n forPublisher.some(\n (c) =>\n c.kind === 'request' &&\n c.eventId.toLowerCase() === quoted &&\n c.pubkey.toLowerCase() === prov.pubkey.toLowerCase()\n )\n ) {\n return 'maintainer-directed';\n }\n }\n\n const standing = selectServiceRequests(\n forPublisher.filter((c) => c.createdAt <= args.runCreatedAt),\n { coordinatorPubkey: publisher, authorized }\n );\n if (standing.active) return 'operationally-associated';\n\n if (authorized.has(publisher)) return 'seen-in-network';\n if (forPublisher.some((c) => c.kind === 'request')) return 'seen-in-network';\n\n return 'no-known-context';\n}\n\n/** True when `level` is at least as strong as `required`. */\nexport function trustAtLeast(\n level: CiTrustLevel,\n required: CiTrustLevel\n): boolean {\n return CI_TRUST_ORDER.indexOf(level) <= CI_TRUST_ORDER.indexOf(required);\n}\n","/**\n * Workflow discovery and trigger matching (rig#125).\n *\n * Workflows are GitHub-Actions-syntax files the coordinator reads out of a\n * MATERIALIZED checkout (never from the relay, never from GitHub): first\n * `.github/workflows/*.yml|yaml`, then `.ngit/act/workflows/*.yml|yaml` so\n * repos already on ngit CI are served as-is. Each is identified on every\n * NIP-C1 event by its path and the SHA-256 of its bytes (the `w` tag), so a\n * consumer can verify exactly which file ran.\n *\n * Only the `on:` clause and the job list are interpreted here — enough to\n * decide WHETHER a workflow runs for a push/pull-request trigger and which\n * job ids to expect. Everything else in the file is act's business\n * (./act-runner.ts). Parsing never throws: a malformed file comes back with\n * `parseError` set so the coordinator can publish an honest\n * `startup_failure` for it instead of silently skipping it.\n */\n\nimport { createHash } from 'node:crypto';\nimport { readdir, readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { parse as parseYaml } from 'yaml';\n\n/** Where workflows live, in scan order (relative to the checkout root). */\nexport const WORKFLOW_DIRS = [\n '.github/workflows',\n '.ngit/act/workflows',\n] as const;\n\nconst WORKFLOW_FILE_RE = /\\.ya?ml$/i;\n\n/** Branch/tag filters of a `push:` or `pull_request:` trigger. */\nexport interface RefFilters {\n branches?: string[];\n tags?: string[];\n}\n\nexport interface WorkflowTriggers {\n push?: RefFilters;\n pull_request?: RefFilters;\n workflow_dispatch?: boolean;\n}\n\nexport interface WorkflowJob {\n id: string;\n name?: string;\n runsOn?: string[];\n}\n\nexport interface DiscoveredWorkflow {\n /** Path relative to the checkout root, forward slashes. */\n path: string;\n /** Lowercase hex SHA-256 of the file's exact bytes. */\n sha256: string;\n name?: string;\n triggers: WorkflowTriggers;\n jobs: WorkflowJob[];\n /** Set when the file could not be understood; `triggers`/`jobs` are then empty. */\n parseError?: string;\n}\n\n/** Lowercase hex SHA-256 of `bytes`. */\nexport function sha256Hex(bytes: Uint8Array | string): string {\n return createHash('sha256').update(bytes).digest('hex');\n}\n\n// ---------------------------------------------------------------------------\n// Parsing\n// ---------------------------------------------------------------------------\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction stringList(value: unknown): string[] | undefined {\n if (typeof value === 'string') return [value];\n if (Array.isArray(value)) {\n return value.filter((v): v is string => typeof v === 'string');\n }\n return undefined;\n}\n\nfunction refFilters(value: unknown): RefFilters {\n if (!isRecord(value)) return {};\n const out: RefFilters = {};\n const branches = stringList(value['branches']);\n const tags = stringList(value['tags']);\n if (branches) out.branches = branches;\n if (tags) out.tags = tags;\n return out;\n}\n\n/** Interpret every GitHub shape of `on:` (string, list, map). */\nfunction parseTriggers(on: unknown): WorkflowTriggers {\n const triggers: WorkflowTriggers = {};\n const enable = (name: unknown, options: unknown): void => {\n if (name === 'push') triggers.push = refFilters(options);\n else if (name === 'pull_request')\n triggers.pull_request = refFilters(options);\n else if (name === 'workflow_dispatch') triggers.workflow_dispatch = true;\n };\n if (typeof on === 'string') enable(on, undefined);\n else if (Array.isArray(on)) for (const name of on) enable(name, undefined);\n else if (isRecord(on)) {\n for (const [name, options] of Object.entries(on)) enable(name, options);\n }\n return triggers;\n}\n\nfunction parseJobs(jobs: unknown): WorkflowJob[] {\n if (!isRecord(jobs)) return [];\n const out: WorkflowJob[] = [];\n for (const [id, spec] of Object.entries(jobs)) {\n const job: WorkflowJob = { id };\n if (isRecord(spec)) {\n if (typeof spec['name'] === 'string') job.name = spec['name'];\n const runsOn = stringList(spec['runs-on']);\n if (runsOn) job.runsOn = runsOn;\n }\n out.push(job);\n }\n return out;\n}\n\n/**\n * Parse one workflow file's bytes. Never throws — see the module header.\n * YAML 1.1 loaders read the unquoted `on` key as boolean `true`; the `yaml`\n * package (YAML 1.2) keeps it a string, but a file re-saved by such a loader\n * carries a literal `true:` key, so both spellings are honoured.\n */\nexport function parseWorkflow(\n path: string,\n content: string | Uint8Array\n): DiscoveredWorkflow {\n const text =\n typeof content === 'string'\n ? content\n : Buffer.from(content).toString('utf-8');\n const base: DiscoveredWorkflow = {\n path,\n sha256: sha256Hex(content),\n triggers: {},\n jobs: [],\n };\n let doc: unknown;\n try {\n doc = parseYaml(text, { strict: false, uniqueKeys: false });\n } catch (err) {\n return {\n ...base,\n parseError: err instanceof Error ? err.message : String(err),\n };\n }\n if (!isRecord(doc)) {\n return { ...base, parseError: 'workflow is not a YAML mapping' };\n }\n const on = doc['on'] ?? doc['true'];\n if (on === undefined || on === null) {\n return { ...base, parseError: 'workflow has no `on:` trigger clause' };\n }\n const out = {\n ...base,\n triggers: parseTriggers(on),\n jobs: parseJobs(doc['jobs']),\n };\n if (typeof doc['name'] === 'string') out.name = doc['name'];\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Discovery\n// ---------------------------------------------------------------------------\n\n/**\n * Every workflow file under {@link WORKFLOW_DIRS} in `checkoutDir`, in a\n * stable order (directory order, then filename). Missing directories are\n * simply empty.\n */\nexport async function discoverWorkflows(\n checkoutDir: string\n): Promise<DiscoveredWorkflow[]> {\n const found: DiscoveredWorkflow[] = [];\n for (const dir of WORKFLOW_DIRS) {\n let names: string[];\n try {\n names = await readdir(join(checkoutDir, dir));\n } catch {\n continue;\n }\n for (const name of names.filter((n) => WORKFLOW_FILE_RE.test(n)).sort()) {\n const rel = `${dir}/${name}`;\n const bytes = await readFile(join(checkoutDir, dir, name));\n found.push(parseWorkflow(rel, bytes));\n }\n }\n return found;\n}\n\n// ---------------------------------------------------------------------------\n// Trigger matching (GitHub filter-pattern semantics)\n// ---------------------------------------------------------------------------\n\n/**\n * Compile one GitHub filter pattern: `*` matches within a path segment,\n * `**` matches across segments, `?` one character, `+` one or more of the\n * preceding character; everything else is literal.\n */\nfunction patternToRegExp(pattern: string): RegExp {\n let re = '';\n for (let i = 0; i < pattern.length; i++) {\n const ch = pattern[i] as string;\n if (ch === '*') {\n if (pattern[i + 1] === '*') {\n re += '.*';\n i++;\n } else {\n re += '[^/]*';\n }\n } else if (ch === '?') {\n re += '[^/]';\n } else if (ch === '+') {\n re += '+';\n } else {\n re += ch.replace(/[.\\\\^$|()[\\]{}]/g, '\\\\$&');\n }\n }\n return new RegExp(`^${re}$`);\n}\n\n/**\n * GitHub's `branches`/`tags` filter rule: patterns are applied in order, a\n * `!` pattern excludes, and a name is included only if the LAST matching\n * pattern was positive. A negation can never include on its own.\n */\nexport function refMatchesPatterns(\n shortName: string,\n patterns: string[]\n): boolean {\n let included = false;\n for (const pattern of patterns) {\n const negated = pattern.startsWith('!');\n const body = negated ? pattern.slice(1) : pattern;\n if (patternToRegExp(body).test(shortName)) included = !negated;\n }\n return included;\n}\n\n/**\n * Does `wf` run for a push that moved `ref` (`refs/heads/...` or\n * `refs/tags/...`)? Mirrors GitHub: no filters → every ref; a `branches`\n * filter alone → only branches; a `tags` filter alone → only tags.\n */\nexport function matchesPush(wf: DiscoveredWorkflow, ref: string): boolean {\n if (wf.parseError !== undefined || !wf.triggers.push) return false;\n const { branches, tags } = wf.triggers.push;\n if (!branches && !tags) return true;\n if (ref.startsWith('refs/heads/')) {\n return (\n branches !== undefined &&\n refMatchesPatterns(ref.slice('refs/heads/'.length), branches)\n );\n }\n if (ref.startsWith('refs/tags/')) {\n return (\n tags !== undefined &&\n refMatchesPatterns(ref.slice('refs/tags/'.length), tags)\n );\n }\n return false;\n}\n\n/**\n * Does `wf` run for a pull request against `baseRef` (a `refs/heads/...` ref\n * or a bare branch name)? With a `branches` filter and no known base the\n * match cannot be proven, so the workflow does not run.\n */\nexport function matchesPullRequest(\n wf: DiscoveredWorkflow,\n baseRef?: string\n): boolean {\n if (wf.parseError !== undefined || !wf.triggers.pull_request) return false;\n const { branches } = wf.triggers.pull_request;\n if (!branches) return true;\n if (baseRef === undefined) return false;\n const short = baseRef.startsWith('refs/heads/')\n ? baseRef.slice('refs/heads/'.length)\n : baseRef;\n return refMatchesPatterns(short, branches);\n}\n","/**\n * Daemon-as-accelerator delegation for paid rig commands (#279).\n *\n * Standalone remains the DEFAULT and the guarantee: every paid command works\n * with no daemon anywhere. But standalone pays a fixed bootstrap tax (relay\n * discovery, peer negotiation, channel resume) on every invocation, while a\n * running `toon-clientd` already holds all of that state warm. When the\n * daemon holds the SAME identity, the pre-#279 nonce guard refused outright\n * (two writers would race the payment channel's cumulative-claim watermark).\n * #279 refines that: the same-identity case now DELEGATES the operation to\n * the daemon's loopback `/git/*` routes — one process (the daemon) owns the\n * watermark, which is exactly the safety property the refusal protected, and\n * the command finishes in daemon time instead of bootstrap time.\n *\n * Decision matrix ({@link resolvePaidSession}):\n *\n * daemon reachable + SAME identity → delegate (`path: 'daemon'`)\n * daemon reachable + other identity → standalone (its channels are keyed\n * to its own pubkey — no shared state)\n * daemon unreachable / not a daemon → standalone\n *\n * TRUST BOUNDARY: the daemon is trusted only because it is (a) loopback and\n * (b) proven to hold the same identity — the `GET /status` identity check\n * happens BEFORE any request body is sent. A same-identity daemon already\n * holds the mnemonic-derived keys and the channel, so delegating adds no\n * authority it does not have.\n *\n * Commands the daemon has NO route for — `rig fund`, `rig balance`,\n * `rig channel open|close|settle` — always run standalone; the on-chain\n * channel mutations among them still REFUSE under a same-identity daemon\n * (the nonce guard in ../standalone/nonce-guard.ts), because close/settle\n * must not race the daemon's live claims.\n *\n * The `DaemonGitClient` is a plain-fetch client, deliberately NOT built on\n * `@toon-protocol/client-mcp`'s ControlClient — that package depends on this\n * one (its daemon Publisher wraps our planner), so importing it back would\n * be circular. Route conventions (loopback base URL, JSON bodies, the error\n * envelope with structured 409 `non_fast_forward` / 413 `oversize_objects`\n * payloads) are mirrored here; the wire types live in `../routes.ts` for\n * client-mcp to adopt. Same duplication contract as\n * `../standalone/nonce-guard.ts` — keep in sync.\n */\n\nimport { defaultDaemonPort, standaloneForced } from '../standalone/nonce-guard.js';\nimport type {\n GitCommentRequest,\n GitErrorEnvelope,\n GitEstimateRequest,\n GitEstimateResponse,\n GitEventResponse,\n GitIssueRequest,\n GitPatchRequest,\n GitPushRequest,\n GitPushResponse,\n GitStatusRequest,\n} from '../routes.js';\nimport { resolveIdentity, type IdentitySourceKind } from './identity.js';\nimport type {\n LoadStandalone,\n StandaloneContext,\n} from './standalone-context.js';\n\n// ---------------------------------------------------------------------------\n// Daemon probe (GET /status — identity check BEFORE anything is sent)\n// ---------------------------------------------------------------------------\n\n/** Result of probing the toon-clientd loopback `/status`. */\nexport interface DaemonProbe {\n /** Control API base URL probed, e.g. `http://127.0.0.1:8787`. */\n baseUrl: string;\n /** True when `/status` answered 200 with parseable JSON. */\n reachable: boolean;\n /** `identity.nostrPubkey` from the status body (when reachable). */\n identity?: string;\n /** `ready` from the status body (channel open, publish-ready). */\n ready?: boolean;\n /** Daemon's default relay URL (`relay.url`). */\n relayUrl?: string;\n /**\n * Daemon's flat per-event publish fee (`feePerEvent`, base units, decimal\n * string) — what the single-event subcommands quote before confirming.\n */\n feePerEvent?: string;\n /**\n * Optional-route capabilities the daemon advertises (`capabilities` in the\n * `/status` body, #306). `'git'` means the `/git/*` write path exists. A\n * daemon older than the field itself omits it entirely — so an UNDEFINED or\n * absent-of-`'git'` value must be read as \"no git support\" (fail closed),\n * NOT delegated to (it would 404 mid-operation).\n */\n capabilities?: string[];\n}\n\n/**\n * True when the probed daemon advertises the `/git/*` write path (#306).\n * Fails closed: a daemon that predates the `capabilities` field reports\n * `undefined` here, which is treated as \"no git routes\" so rig raises a clear\n * upgrade error instead of delegating into a mid-operation 404.\n */\nexport function daemonSupportsGit(probe: DaemonProbe): boolean {\n return Array.isArray(probe.capabilities) && probe.capabilities.includes('git');\n}\n\n/** Injectable probe signature (tests fake this instead of the network). */\nexport type ProbeDaemon = (\n env: NodeJS.ProcessEnv,\n fetchImpl: typeof fetch\n) => Promise<DaemonProbe>;\n\n/** Loopback control API base URL (port: `TOON_CLIENT_HTTP_PORT`, else 8787). */\nexport function daemonBaseUrl(env: NodeJS.ProcessEnv): string {\n const raw = env['TOON_CLIENT_HTTP_PORT'];\n const parsed = raw ? Number(raw) : NaN;\n const port =\n Number.isFinite(parsed) && parsed > 0 ? parsed : defaultDaemonPort();\n return `http://127.0.0.1:${port}`;\n}\n\n/**\n * Probe `GET /status` on the loopback control API. Anything short of a 200\n * with JSON (no listener, timeout, some other local service) reports\n * unreachable — the caller then runs standalone.\n */\nexport async function probeDaemon(\n env: NodeJS.ProcessEnv,\n fetchImpl: typeof fetch,\n timeoutMs = 1500\n): Promise<DaemonProbe> {\n const baseUrl = daemonBaseUrl(env);\n try {\n const res = await fetchImpl(`${baseUrl}/status`, {\n signal: AbortSignal.timeout(timeoutMs),\n });\n if (!res.ok) return { baseUrl, reachable: false };\n const body = (await res.json()) as {\n ready?: unknown;\n identity?: { nostrPubkey?: unknown };\n relay?: { url?: unknown };\n feePerEvent?: unknown;\n capabilities?: unknown;\n };\n const probe: DaemonProbe = { baseUrl, reachable: true };\n const pubkey = body?.identity?.nostrPubkey;\n if (typeof pubkey === 'string' && pubkey !== '') probe.identity = pubkey;\n if (typeof body?.ready === 'boolean') probe.ready = body.ready;\n if (typeof body?.relay?.url === 'string' && body.relay.url !== '') {\n probe.relayUrl = body.relay.url;\n }\n if (typeof body?.feePerEvent === 'string' && body.feePerEvent !== '') {\n probe.feePerEvent = body.feePerEvent;\n }\n // Only keep string entries — an old daemon omits the field entirely, and\n // daemonSupportsGit() reads a missing/garbage value as \"no git routes\".\n if (Array.isArray(body?.capabilities)) {\n probe.capabilities = body.capabilities.filter(\n (c): c is string => typeof c === 'string'\n );\n }\n return probe;\n } catch {\n return { baseUrl, reachable: false };\n }\n}\n\n// ---------------------------------------------------------------------------\n// /git/* loopback client (plain fetch — see module doc for the no-import rule)\n// ---------------------------------------------------------------------------\n\n/** The daemon answered a `/git/*` route with a non-2xx error envelope. */\nexport class DaemonRouteError extends Error {\n constructor(\n /** HTTP status code (409 non_fast_forward, 413 oversize_objects, …). */\n public readonly status: number,\n /** The parsed error envelope (structured payloads at the top level). */\n public readonly envelope: GitErrorEnvelope\n ) {\n super(envelope.detail ?? envelope.error);\n this.name = 'DaemonRouteError';\n }\n}\n\n/**\n * A same-identity daemon holds the identity but is too old to serve the\n * `/git/*` routes (#306 — version skew: git routes added in #227, delegation\n * in #279). Raised at the capability pre-flight (no `'git'` in `/status`\n * `capabilities`), and as defense-in-depth when a git route still 404s despite\n * a positive probe. NOT auto-fell-back to standalone on purpose: a\n * same-identity daemon holding the identity makes the #228 nonce guard REFUSE\n * standalone anyway (both writers would race the channel's cumulative-claim\n * watermark) — so the only correct, non-racy resolution is upgrading or\n * stopping the daemon.\n */\nexport class DaemonTooOldForGitError extends Error {\n constructor(\n /** Control API base URL the stale daemon answered on. */\n public readonly baseUrl: string,\n /** The shared Nostr pubkey (hex), when known — shortened in the message. */\n public readonly pubkey?: string\n ) {\n const holds =\n pubkey !== undefined && pubkey !== ''\n ? ` holds this identity (${pubkey.slice(0, 8)}…)`\n : ' holds this identity';\n super(\n `toon-clientd at ${baseUrl}${holds} but is too old to handle git ` +\n 'operations (missing /git routes). Upgrade the daemon ' +\n '(npm i -g @toon-protocol/client-mcp@latest, then restart it) — or ' +\n 'stop it to let rig run standalone.'\n );\n this.name = 'DaemonTooOldForGitError';\n }\n}\n\n/** The daemon vanished between the identity probe and the operation. */\nexport class DaemonUnreachableError extends Error {\n constructor(\n public readonly baseUrl: string,\n cause: unknown\n ) {\n super(\n `toon-clientd stopped answering at ${baseUrl} after the identity ` +\n `probe — nothing was paid. Re-run: rig falls back to standalone ` +\n `automatically when no daemon responds` +\n (cause instanceof Error ? ` (${cause.message})` : '')\n );\n this.name = 'DaemonUnreachableError';\n }\n}\n\nexport class DaemonGitClient {\n constructor(\n private readonly baseUrl: string,\n private readonly fetchImpl: typeof fetch,\n /** Shared identity pubkey, for the too-old error message on a 404. */\n private readonly pubkey?: string\n ) {}\n\n gitEstimate(req: GitEstimateRequest): Promise<GitEstimateResponse> {\n return this.post<GitEstimateResponse>('/git/estimate', req);\n }\n\n gitPush(req: GitPushRequest): Promise<GitPushResponse> {\n return this.post<GitPushResponse>('/git/push', req);\n }\n\n gitIssue(req: GitIssueRequest): Promise<GitEventResponse> {\n return this.post<GitEventResponse>('/git/issue', req);\n }\n\n gitComment(req: GitCommentRequest): Promise<GitEventResponse> {\n return this.post<GitEventResponse>('/git/comment', req);\n }\n\n gitPatch(req: GitPatchRequest): Promise<GitEventResponse> {\n return this.post<GitEventResponse>('/git/patch', req);\n }\n\n gitStatus(req: GitStatusRequest): Promise<GitEventResponse> {\n return this.post<GitEventResponse>('/git/status', req);\n }\n\n private async post<T>(path: string, body: unknown): Promise<T> {\n let res: Response;\n try {\n res = await this.fetchImpl(`${this.baseUrl}${path}`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(body),\n });\n } catch (err) {\n throw new DaemonUnreachableError(this.baseUrl, err);\n }\n // Defense in depth (#306): a 404 on a `/git/*` route means the route is\n // not registered — a daemon too old for the git write path, despite the\n // capability pre-flight having (wrongly) passed. Surface the same\n // actionable upgrade error rather than the opaque \"HTTP 404\" envelope.\n if (res.status === 404) {\n throw new DaemonTooOldForGitError(this.baseUrl, this.pubkey);\n }\n const text = await res.text();\n let parsed: unknown;\n try {\n parsed = text === '' ? {} : JSON.parse(text);\n } catch {\n throw new DaemonRouteError(res.status, {\n error: 'invalid_response',\n detail: `daemon returned non-JSON (HTTP ${res.status}): ${text.slice(0, 200)}`,\n });\n }\n if (!res.ok) {\n const envelope =\n parsed && typeof parsed === 'object' && 'error' in parsed\n ? (parsed as GitErrorEnvelope)\n : { error: 'http_error', detail: `HTTP ${res.status}` };\n throw new DaemonRouteError(res.status, envelope);\n }\n return parsed as T;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Paid-session resolution (the decision matrix)\n// ---------------------------------------------------------------------------\n\n/** Which transport a paid command ran on (stderr line + `--json` field). */\nexport type SessionPath = 'daemon' | 'standalone';\n\n/** The delegated fast path: a same-identity daemon owns the operation. */\nexport interface DaemonSession {\n path: 'daemon';\n client: DaemonGitClient;\n baseUrl: string;\n /** Locally-resolved identity (source tier + pubkey — never the phrase). */\n identity: {\n pubkey: string;\n source: IdentitySourceKind;\n sourceLabel: string;\n };\n /** Daemon's flat per-event fee (base units, decimal), when reported. */\n feePerEvent?: string;\n /** Daemon's configured relay URL, when reported (mismatch warning). */\n daemonRelayUrl?: string;\n}\n\n/** The default path: the embedded, nonce-guarded standalone context. */\nexport interface StandaloneSession {\n path: 'standalone';\n ctx: StandaloneContext;\n}\n\nexport type PaidSession = DaemonSession | StandaloneSession;\n\nexport interface ResolveSessionOptions {\n env: NodeJS.ProcessEnv;\n /** Working directory (identity `.env` walk / standalone loader). */\n cwd: string;\n /** Stderr line sink (the chosen-path line always prints here). */\n warn(line: string): void;\n /** Standalone factory (`deps.loadStandalone ?? defaultLoadStandalone`). */\n loadStandalone: LoadStandalone;\n /** Relay-origin for the standalone #264 network bootstrap, when resolved. */\n relayUrl?: string;\n /** Fetch impl for probe + delegated requests (tests). Default: global. */\n fetchImpl?: typeof fetch;\n /** Probe override (tests). Default: {@link probeDaemon}. */\n probeDaemon?: ProbeDaemon;\n}\n\n/**\n * Decide how this paid command pays (see the module-doc matrix) and return a\n * ready session. The chosen path is announced on stderr either way, BEFORE\n * the expensive work starts. Identity is confirmed against the daemon's\n * `/status` before anything else is sent to it.\n */\nexport async function resolvePaidSession(\n options: ResolveSessionOptions\n): Promise<PaidSession> {\n const fetchImpl = options.fetchImpl ?? fetch;\n\n // Force-standalone override (RIG_STANDALONE / `rig --standalone`): skip the\n // daemon probe outright and run embedded, even when a same-identity daemon\n // is up and supports the /git routes. The user has explicitly opted out of\n // delegation; createStandaloneContext skips the same-identity refusal too,\n // and the NonceLock still guards against concurrent standalone processes.\n if (standaloneForced(options.env)) {\n options.warn(\n 'rig: paid path: standalone (RIG_STANDALONE set — toon-clientd bypassed)'\n );\n const ctx = await options.loadStandalone({\n env: options.env,\n cwd: options.cwd,\n warn: options.warn,\n ...(options.relayUrl !== undefined ? { relayUrl: options.relayUrl } : {}),\n });\n return { path: 'standalone', ctx };\n }\n\n const probe = await (options.probeDaemon ?? probeDaemon)(\n options.env,\n fetchImpl\n );\n\n if (probe.reachable && probe.identity !== undefined) {\n // Local identity resolution only happens when there is a daemon to\n // compare against — the standalone loader resolves it itself otherwise.\n const identity = await resolveIdentity({\n env: options.env,\n cwd: options.cwd,\n warn: options.warn,\n });\n if (identity.pubkey === probe.identity) {\n // Capability pre-flight (#306): a same-identity daemon that predates the\n // `/git/*` routes (older client-mcp) has `/status` but 404s every git\n // route. Delegating would dead-end with an opaque 404, and blindly\n // falling back to standalone is unsafe — the #228 nonce guard REFUSES\n // standalone while a same-identity daemon is up (cumulative-claim race).\n // Fail closed with a clear upgrade/stop remediation instead.\n if (!daemonSupportsGit(probe)) {\n throw new DaemonTooOldForGitError(probe.baseUrl, identity.pubkey);\n }\n options.warn(\n `rig: paid path: daemon — toon-clientd at ${probe.baseUrl} holds ` +\n `this identity (${identity.pubkey.slice(0, 8)}…), delegating`\n );\n return {\n path: 'daemon',\n client: new DaemonGitClient(probe.baseUrl, fetchImpl, identity.pubkey),\n baseUrl: probe.baseUrl,\n identity: {\n pubkey: identity.pubkey,\n source: identity.source,\n sourceLabel: identity.sourceLabel,\n },\n ...(probe.feePerEvent !== undefined\n ? { feePerEvent: probe.feePerEvent }\n : {}),\n ...(probe.relayUrl !== undefined\n ? { daemonRelayUrl: probe.relayUrl }\n : {}),\n };\n }\n options.warn(\n `rig: paid path: standalone — the toon-clientd at ${probe.baseUrl} ` +\n `runs a different identity (${probe.identity.slice(0, 8)}…), no ` +\n 'shared channel state'\n );\n } else {\n options.warn(\n `rig: paid path: standalone (no toon-clientd at ${probe.baseUrl})`\n );\n }\n\n const ctx = await options.loadStandalone({\n env: options.env,\n cwd: options.cwd,\n warn: options.warn,\n ...(options.relayUrl !== undefined ? { relayUrl: options.relayUrl } : {}),\n });\n return { path: 'standalone', ctx };\n}\n","/**\n * Error UX for the `rig` commands: map structured planner/publisher errors\n * to actionable terminal output (and a machine-readable envelope for\n * `--json`). The CLI is standalone-only (#248), so everything here is either\n * a local planner error, an identity/config-chain error, or a tagged error\n * surfaced from the embedded publisher (matched by name — those classes live\n * behind the lazy `@toon-protocol/client` dynamic import).\n */\n\nimport { MAX_OBJECT_SIZE } from '../objects.js';\nimport {\n NonFastForwardError,\n OversizeObjectsError,\n type OversizeObject,\n type RejectedRefUpdate,\n} from '../push.js';\nimport { GitError } from '../repo-reader.js';\nimport {\n DaemonRouteError,\n DaemonTooOldForGitError,\n DaemonUnreachableError,\n} from './daemon-session.js';\nimport { MissingIdentityError } from './identity.js';\nimport type { CliIo } from './output.js';\n\n/** Normalized error description: terminal lines + `--json` envelope. */\nexport interface DescribedError {\n /** Stable machine code. */\n code: string;\n /** Human-facing lines (message first, remediation after). */\n lines: string[];\n /** Machine envelope for `--json` output (structured payload included). */\n json: Record<string, unknown>;\n}\n\n/**\n * A command could not resolve the NIP-34 repo address\n * (`30617:<ownerPubkey>:<repoId>`) from flags or the `toon.*` git config\n * keys `rig init` writes.\n */\nexport class UnconfiguredRepoAddressError extends Error {\n constructor(\n /** Which half of the address is missing. */\n public readonly missing: 'repository id' | 'repository owner'\n ) {\n super(\n `no ${missing} configured — this command addresses the repo as ` +\n '30617:<ownerPubkey>:<repoId>. Run `rig init` once inside the repo ' +\n '(it writes toon.repoid/toon.owner to the local git config), or ' +\n `pass ${missing === 'repository id' ? '--repo-id <id>' : '--owner <pubkey>'} ` +\n \"explicitly (use --owner for repos you don't own).\"\n );\n this.name = 'UnconfiguredRepoAddressError';\n }\n}\n\n/** A relay URL (flag, `rig remote add`, or a remote's stored URL) is junk. */\nexport class InvalidRelayUrlError extends Error {\n constructor(\n public readonly url: string,\n /** What was being resolved, e.g. `remote \"origin\"`. */\n context: string\n ) {\n super(\n `${context}: ${JSON.stringify(url)} is not a relay URL — relays are ` +\n 'ws://, wss://, http://, or https://'\n );\n this.name = 'InvalidRelayUrlError';\n }\n}\n\n/** A paid command addressed a git remote that is not configured. */\nexport class UnknownRemoteError extends Error {\n constructor(public readonly remote: string) {\n super(\n `no remote named ${JSON.stringify(remote)} is configured — ` +\n '`rig remote list` shows configured remotes; add it with ' +\n `\\`rig remote add ${remote} <relay-url>\\``\n );\n this.name = 'UnknownRemoteError';\n }\n}\n\n/**\n * The addressed git remote carries multiple URLs (`git remote set-url --add`\n * done by hand). rig publishes to exactly one relay per paid command, so this\n * is refused BEFORE anything is fetched, uploaded, or paid (the #243\n * single-relay guard, extended to remotes).\n */\nexport class MultiUrlRemoteError extends Error {\n constructor(\n public readonly remote: string,\n public readonly urls: string[]\n ) {\n super(\n `remote ${JSON.stringify(remote)} has ${urls.length} URLs ` +\n `(${urls.join(', ')}) — rig supports one relay URL per remote. ` +\n `Fix it with \\`git remote set-url ${remote} <relay-url>\\`. ` +\n 'Nothing was uploaded, published, or paid.'\n );\n this.name = 'MultiUrlRemoteError';\n }\n}\n\n/** No relay resolved: no --relay, no usable remote, no legacy toon.relay. */\nexport class NoOriginConfiguredError extends Error {\n constructor(\n /** URL of an existing `origin` remote that is NOT a relay, if any. */\n nonRelayOriginUrl?: string\n ) {\n super(\n 'no origin configured — run `rig remote add origin <relay-url>` ' +\n '(or pass --relay <url> for a one-off publish).' +\n (nonRelayOriginUrl !== undefined\n ? `\\nThe existing \"origin\" remote (${nonRelayOriginUrl}) is not a ` +\n 'relay URL, so rig ignores it — add the relay under another ' +\n 'name (`rig remote add toon <relay-url>`) and target it ' +\n 'explicitly (`rig push toon` / `--remote toon`).'\n : '')\n );\n this.name = 'NoOriginConfiguredError';\n }\n}\n\n/** A rig command ran outside any git repository. */\nexport class NotAGitRepositoryError extends Error {\n constructor(cwd: string) {\n super(\n `not a git repository: ${cwd}\\n` +\n 'rig can create one for you: re-run `rig init --git-init` (in a ' +\n 'terminal, plain `rig init` offers the same via a prompt). Or run ' +\n '`git init` yourself first, then re-run.'\n );\n this.name = 'NotAGitRepositoryError';\n }\n}\n\nfunction nonFastForwardLines(refs: RejectedRefUpdate[]): string[] {\n return [\n 'Push rejected: non-fast-forward update for:',\n ...refs.map(\n (r) =>\n ` ${r.refname} remote ${r.remoteSha.slice(0, 7)} is not an ancestor of local ${r.localSha.slice(0, 7)}`\n ),\n 'The remote moved since your last push. Re-run with --force to overwrite it',\n 'WARNING: --force rewrites the published ref history for every reader of this repo.',\n ];\n}\n\nfunction oversizeLines(objects: OversizeObject[]): string[] {\n return [\n `Push rejected: ${objects.length} object(s) exceed the ${MAX_OBJECT_SIZE}-byte (95KB) upload limit:`,\n ...objects.map((o) => ` ${o.path ?? o.sha} ${o.type}, ${o.size} bytes`),\n 'Objects over 95KB are a hard error in v1 — split or remove the file(s) from history to push.',\n 'Large-object support is tracked in toon-client#235.',\n ];\n}\n\n/**\n * Normalize any command-path error for rendering. `command` names the rig\n * subcommand for the generic \"rig <command> failed\" lines.\n */\nexport function describeError(err: unknown, command = 'push'): DescribedError {\n if (err instanceof UnconfiguredRepoAddressError) {\n return {\n code: 'unconfigured_repo_address',\n lines: err.message.split('\\n'),\n json: { error: 'unconfigured_repo_address', detail: err.message },\n };\n }\n if (err instanceof NotAGitRepositoryError) {\n return {\n code: 'not_a_git_repository',\n lines: err.message.split('\\n'),\n json: { error: 'not_a_git_repository', detail: err.message },\n };\n }\n if (err instanceof InvalidRelayUrlError) {\n return {\n code: 'invalid_relay_url',\n lines: err.message.split('\\n'),\n json: { error: 'invalid_relay_url', detail: err.message, url: err.url },\n };\n }\n if (err instanceof UnknownRemoteError) {\n return {\n code: 'unknown_remote',\n lines: err.message.split('\\n'),\n json: {\n error: 'unknown_remote',\n detail: err.message,\n remote: err.remote,\n },\n };\n }\n if (err instanceof MultiUrlRemoteError) {\n return {\n code: 'multi_url_remote',\n lines: err.message.split('\\n'),\n json: {\n error: 'multi_url_remote',\n detail: err.message,\n remote: err.remote,\n urls: err.urls,\n },\n };\n }\n if (err instanceof NoOriginConfiguredError) {\n return {\n code: 'no_origin_configured',\n lines: err.message.split('\\n'),\n json: { error: 'no_origin_configured', detail: err.message },\n };\n }\n if (err instanceof MissingIdentityError) {\n return {\n code: 'missing_identity',\n lines: err.message.split('\\n'),\n json: { error: 'missing_identity', detail: err.message },\n };\n }\n if (err instanceof NonFastForwardError) {\n return {\n code: 'non_fast_forward',\n lines: nonFastForwardLines(err.refs),\n json: { error: 'non_fast_forward', detail: err.message, refs: err.refs },\n };\n }\n if (err instanceof OversizeObjectsError) {\n return {\n code: 'oversize_objects',\n lines: oversizeLines(err.objects),\n json: {\n error: 'oversize_objects',\n detail: err.message,\n objects: err.objects,\n },\n };\n }\n if (err instanceof GitError) {\n return {\n code: 'git_error',\n lines: [`git failed: ${err.message}`],\n json: { error: 'git_error', detail: err.message },\n };\n }\n // `rig name` (#367): the optional `@ar.io/sdk` dependency is not installed.\n // Matched by name (the class lives in name.ts) so tsup chunk duplication can\n // never break instanceof — same rationale as the standalone-path errors below.\n if (err instanceof Error && err.name === 'ArnsSdkUnavailableError') {\n return {\n code: 'arns_sdk_unavailable',\n lines: err.message.split('\\n'),\n json: { error: 'arns_sdk_unavailable', detail: err.message },\n };\n }\n // `rig name` (#376): `@ar.io/sdk` IS installed but its API surface doesn't\n // match — kept distinct from \"not installed\" so the remediation (upgrade,\n // not install) is right. Matched by name for the same chunk-duplication\n // rationale as above.\n if (err instanceof Error && err.name === 'ArnsSdkIncompatibleError') {\n return {\n code: 'arns_sdk_incompatible',\n lines: err.message.split('\\n'),\n json: { error: 'arns_sdk_incompatible', detail: err.message },\n };\n }\n\n // Delegated-daemon path (#279): the daemon's /git/* error envelope carries\n // the same structured payloads the local planner throws — render them\n // identically so the two paths are indistinguishable to the user.\n if (err instanceof DaemonRouteError) {\n const envelope = err.envelope;\n if (\n envelope.error === 'non_fast_forward' &&\n Array.isArray(envelope['refs'])\n ) {\n return {\n code: 'non_fast_forward',\n lines: nonFastForwardLines(envelope['refs'] as RejectedRefUpdate[]),\n json: { ...envelope },\n };\n }\n if (\n envelope.error === 'oversize_objects' &&\n Array.isArray(envelope['objects'])\n ) {\n return {\n code: 'oversize_objects',\n lines: oversizeLines(envelope['objects'] as OversizeObject[]),\n json: { ...envelope },\n };\n }\n const retryHint =\n envelope.retryable === true\n ? ['The daemon reports this as retryable — re-run shortly.']\n : [];\n return {\n code: envelope.error,\n lines: [\n `daemon rejected the operation (HTTP ${err.status}): ` +\n (envelope.detail ?? envelope.error),\n ...retryHint,\n ],\n json: { ...envelope },\n };\n }\n if (err instanceof DaemonUnreachableError) {\n return {\n code: 'daemon_unreachable',\n lines: err.message.split('\\n'),\n json: { error: 'daemon_unreachable', detail: err.message },\n };\n }\n // Version skew (#306): a same-identity daemon too old for the /git/* routes.\n // The message already carries the upgrade + stop-daemon remediation.\n if (err instanceof DaemonTooOldForGitError) {\n return {\n code: 'daemon_too_old_for_git',\n lines: err.message.split('\\n'),\n json: {\n error: 'daemon_too_old_for_git',\n detail: err.message,\n baseUrl: err.baseUrl,\n ...(err.pubkey !== undefined ? { pubkey: err.pubkey } : {}),\n },\n };\n }\n\n // Standalone-path tagged errors (matched by name — the classes live behind\n // the optional dynamic import).\n const name = err instanceof Error ? err.name : '';\n const message = err instanceof Error ? err.message : String(err);\n if (name === 'DaemonIdentityConflictError') {\n return {\n code: 'daemon_identity_conflict',\n lines: [\n message,\n 'Paid writes delegate to a same-identity daemon automatically; ' +\n 'seeing this means the daemon appeared mid-run or this operation ' +\n 'has no daemon route — stop the daemon and re-run.',\n ],\n json: { error: 'daemon_identity_conflict', detail: message },\n };\n }\n if (name === 'MissingUplinkError') {\n return {\n code: 'missing_uplink',\n lines: [message],\n json: { error: 'missing_uplink', detail: message },\n };\n }\n // Peer→channel map corruption (#262) — matched by name so tsup chunk\n // duplication between the cli and standalone entries can't break instanceof.\n if (name === 'ChannelMapCorruptError') {\n return {\n code: 'channel_map_corrupt',\n lines: [message],\n json: { error: 'channel_map_corrupt', detail: message },\n };\n }\n // Settle attempted before the challenge window elapsed (#263) — the client\n // throws this retryable error BEFORE spending gas; surface when to retry.\n if (name === 'SettleTooEarlyError') {\n const settleableAt = (err as { settleableAt?: unknown }).settleableAt;\n return {\n code: 'settle_too_early',\n lines: [\n message,\n 'The settlement challenge window is still open — nothing was spent. ' +\n 'Re-run `rig channel settle` after the settleable time.',\n ],\n json: {\n error: 'settle_too_early',\n detail: message,\n ...(typeof settleableAt === 'string' ? { settleableAt } : {}),\n },\n };\n }\n\n // The #278 read path — matched by name (same tsup chunk-duplication\n // rationale as above; the classes live in clone.ts / object-fetch.ts /\n // materialize.ts).\n if (name === 'RepoNotFoundError') {\n return {\n code: 'repo_not_found',\n lines: message.split('\\n'),\n json: { error: 'repo_not_found', detail: message },\n };\n }\n if (name === 'MissingRemoteObjectsError') {\n const missing = (err as { missing?: unknown }).missing;\n return {\n code: 'missing_remote_objects',\n lines: message.split('\\n'),\n json: {\n error: 'missing_remote_objects',\n detail: message,\n ...(Array.isArray(missing) ? { missing } : {}),\n },\n };\n }\n if (name === 'ObjectIntegrityError' || name === 'ObjectWriteMismatchError') {\n return {\n code: 'object_integrity',\n lines: message.split('\\n'),\n json: { error: 'object_integrity', detail: message },\n };\n }\n\n return {\n code: 'error',\n lines: [`rig ${command} failed: ${message}`],\n json: { error: 'error', detail: message },\n };\n}\n\n/**\n * The one command-error emitter (#265): the machine envelope (tagged with\n * the command name) goes to stdout via `emitJson` when `--json` is active,\n * and the human-facing lines ALWAYS go to stderr — so JSON consumers get the\n * parseable envelope while a human tailing stderr still sees the detail.\n * Returns the exit code (always 1) so callers can `return emitCliError(…)`.\n */\nexport function emitCliError(\n io: CliIo,\n json: boolean,\n command: string,\n err: unknown\n): 1 {\n const described = describeError(err, command);\n if (json) io.emitJson({ command, ...described.json });\n for (const line of described.lines) io.err(line);\n return 1;\n}\n","/**\n * `rig ci status <commit>` — the FREE read side of relay-native CI (#125):\n * every NIP-C1 run (kind:9842 Workflow Result / kind:39842 Workflow\n * Progress) and job (kind:9841 Job Result) a relay holds for one commit of\n * one repo, with each run's trust level derived from the repo's maintainers\n * (kind:30617) and the Service Request / Stop history (kind:9843/9844).\n *\n * It is the one-command merge gate: exit 0 only when every COUNTED run has\n * concluded green. A run counts when it is the latest attempt by its\n * publisher for its workflow, survives `--workflow` and\n * `--require-ci-trust`, and — since the relay is permissionless — a\n * stranger's coordinator can never make a commit green under a trust\n * requirement it does not meet. A commit with no concluded run is NOT green\n * (exit 1, \"no concluded run\"), so a gate cannot pass by accident.\n *\n * Like the #278 tracker reads: no identity, no payment, reads may target\n * several relays (merged by event id), and `--json` emits exactly one\n * document.\n */\n\nimport { parseArgs } from 'node:util';\nimport { REPOSITORY_ANNOUNCEMENT_KIND } from '@toon-protocol/core/nip34';\nimport {\n CI_JOB_RESULT_KIND,\n CI_SERVICE_REQUEST_KIND,\n CI_SERVICE_STOP_KIND,\n CI_WORKFLOW_PROGRESS_KIND,\n CI_WORKFLOW_RESULT_KIND,\n parseCiJobResult,\n parseCiServiceControl,\n parseCiWorkflowProgress,\n parseCiWorkflowResult,\n repoAddress,\n type CiArtifact,\n type CiConclusion,\n type CiPrContext,\n type CiProgressStatus,\n type CiProvenance,\n type CiTriggerReason,\n type CiWorkflowRef,\n type ServiceControl,\n} from '../ci/nip-c1-events.js';\nimport {\n CI_TRUST_ORDER,\n deriveTrustLevel,\n isCiTrustLevel,\n trustAtLeast,\n type CiTrustLevel,\n} from '../ci/trust.js';\nimport { runGit } from '../materialize.js';\nimport { authorizedStatusAuthors } from '../nip34-events.js';\nimport { hexToNpub, ownerToHex } from '../npub.js';\nimport {\n defaultWebSocketFactory,\n queryRelay,\n type NostrEvent,\n type NostrFilter,\n type WebSocketFactory,\n} from '../remote-state.js';\nimport {\n emitCliError,\n InvalidRelayUrlError,\n UnconfiguredRepoAddressError,\n} from './errors.js';\nimport { readToonConfig, resolveRepoRoot } from './git-config.js';\nimport type { ReadCommandDeps } from './read-seams.js';\nimport { resolveRelays } from './remote.js';\n\n// ---------------------------------------------------------------------------\n// Usage\n// ---------------------------------------------------------------------------\n\nexport const CI_STATUS_USAGE = `Usage: rig ci status <commit> [options]\n\nShow every CI run and job for <commit> — FREE (relay reads only). <commit>\nis a full 40-hex SHA, or any local revision (HEAD, a branch, a short SHA)\nwhen run inside the repository. Exit status is the gate: 0 when every\ncounted run concluded green (success/neutral/skipped); 1 when any counted\nrun failed, timed out, was cancelled, or failed to start, when a run is\nstill queued/in progress, or when the commit has no concluded run at all.\n\nA run counts when it is its publisher's latest attempt for its workflow.\nTrust levels (NIP-C1, derived from the repo's maintainers and Service\nRequests): maintainer-directed > operationally-associated > seen-in-network\n> no-known-context. With --require-ci-trust, runs below that level are\ndropped before counting — so an unknown coordinator's green never gates.\n\nOptions:\n --require-ci-trust <level> minimum trust level to count a run\n --workflow <path> only runs of this workflow file\n --repo-id <id> repository id / NIP-34 d-tag (default: git config)\n --owner <pubkey> repository owner (npub or 64-char hex; default: git config)\n --remote <name> read via this configured git remote (default: origin)\n --relay <url> ad-hoc relay override; repeatable — reads are merged\n --json machine-readable envelope (exactly one JSON document)\n -h, --help show this help`;\n\n// ---------------------------------------------------------------------------\n// Types (the JSON envelope)\n// ---------------------------------------------------------------------------\n\nexport interface CiStatusJob {\n jobId: string;\n name?: string;\n conclusion: CiConclusion;\n logsUrl?: string;\n artifacts: CiArtifact[];\n exitCode?: number;\n queuedAt?: number;\n startedAt?: number;\n /** The 9841's `created_at`: when the runner published this conclusion. */\n concludedAt: number;\n eventId: string;\n publisher: string;\n}\n\n/**\n * A `pull_request` run's NIP-22 context (the PR as root, the PR or PR Update\n * that supplied the commit as parent) plus whether the PR author is the repo\n * owner or a declared maintainer — derived here from the 30617, never from\n * anything the coordinator asserts (#130).\n */\nexport interface CiStatusPullRequest extends CiPrContext {\n authorIsMaintainer: boolean;\n}\n\nexport interface CiStatusRun {\n runId: string;\n coordinator: string;\n workflow: CiWorkflowRef;\n reason: CiTriggerReason;\n status: CiProgressStatus;\n conclusion?: CiConclusion;\n trust: CiTrustLevel;\n createdAt: number;\n startedAt?: number;\n queuedAt?: number;\n provenance?: CiProvenance;\n /** Present exactly when the run was triggered by a pull request. */\n pr?: CiStatusPullRequest;\n jobs: CiStatusJob[];\n /** Event id of the 9842 (concluded) or the latest 39842. */\n eventId: string;\n}\n\nexport interface CiStatusSummary {\n counted: number;\n green: number;\n red: number;\n pending: number;\n}\n\nexport interface CiStatusReport {\n command: 'ci status';\n commit: string;\n repo: { owner: string; repoId: string };\n relays: string[];\n requiredTrust: CiTrustLevel | null;\n runs: CiStatusRun[];\n summary: CiStatusSummary;\n ok: boolean;\n /** Why `ok` is false, for humans and logs. */\n reason?: string;\n}\n\nconst GREEN: ReadonlySet<CiConclusion> = new Set([\n 'success',\n 'neutral',\n 'skipped',\n]);\n\n// ---------------------------------------------------------------------------\n// Flags\n// ---------------------------------------------------------------------------\n\ninterface StatusFlags {\n json: boolean;\n help: boolean;\n relay: string[];\n remote?: string;\n repoId?: string;\n owner?: string;\n requireTrust?: CiTrustLevel;\n workflow?: string;\n}\n\nconst STATUS_OPTIONS = {\n json: { type: 'boolean', default: false },\n relay: { type: 'string', multiple: true },\n remote: { type: 'string' },\n 'repo-id': { type: 'string' },\n owner: { type: 'string' },\n 'require-ci-trust': { type: 'string' },\n workflow: { type: 'string' },\n help: { type: 'boolean', short: 'h', default: false },\n} as const;\n\nconst FULL_SHA_RE = /^[0-9a-f]{40}$/;\nconst WS_URL_RE = /^wss?:\\/\\//i;\nconst RELAY_TIMEOUT_MS = 10_000;\n\n/** Query every relay with every filter; merge by id; throw only if ALL fail. */\nasync function queryAll(\n relays: string[],\n filters: NostrFilter[],\n webSocketFactory: WebSocketFactory\n): Promise<NostrEvent[]> {\n const jobs = relays.flatMap((relay) =>\n filters.map((filter) =>\n queryRelay(relay, filter, RELAY_TIMEOUT_MS, webSocketFactory)\n )\n );\n const results = await Promise.allSettled(jobs);\n const byId = new Map<string, NostrEvent>();\n let failures = 0;\n let firstError: unknown;\n for (const result of results) {\n if (result.status === 'rejected') {\n failures += 1;\n firstError ??= result.reason;\n continue;\n }\n for (const event of result.value) {\n if (typeof event.id === 'string' && !byId.has(event.id))\n byId.set(event.id, event);\n }\n }\n if (failures === results.length && results.length > 0) {\n throw firstError instanceof Error\n ? firstError\n : new Error(String(firstError));\n }\n return [...byId.values()];\n}\n\n// ---------------------------------------------------------------------------\n// Pure assembly (exported for tests)\n// ---------------------------------------------------------------------------\n\nexport interface AssembleStatusOptions {\n commit: string;\n ownerPubkey: string;\n repoId: string;\n /** Owner ∪ declared maintainers (lowercase hex). */\n authorized: Set<string>;\n events: NostrEvent[];\n requireTrust?: CiTrustLevel;\n workflow?: string;\n}\n\n/**\n * Turn relay events into the run list + verdict. Runs are keyed by\n * (publisher, runId): a 9842 marks the run concluded; otherwise the newest\n * 39842 (by created_at) gives its status. Jobs attach by the 9841's quoted\n * progress address. Per (publisher, workflow path) only the LATEST attempt\n * (by created_at, ties → lowest id) counts.\n */\nexport function assembleCiStatus(opts: AssembleStatusOptions): {\n runs: CiStatusRun[];\n summary: CiStatusSummary;\n ok: boolean;\n reason?: string;\n} {\n const repoAddr = repoAddress(opts.ownerPubkey, opts.repoId);\n const commit = opts.commit.toLowerCase();\n\n const controls: ServiceControl[] = [];\n const results = new Map<string, ReturnType<typeof parseCiWorkflowResult>>();\n const progresses = new Map<\n string,\n NonNullable<ReturnType<typeof parseCiWorkflowProgress>>\n >();\n const jobs: NonNullable<ReturnType<typeof parseCiJobResult>>[] = [];\n\n for (const ev of opts.events) {\n switch (ev.kind) {\n case CI_SERVICE_REQUEST_KIND:\n case CI_SERVICE_STOP_KIND: {\n const c = parseCiServiceControl(ev);\n if (c && c.repoAddr === repoAddr) controls.push(c);\n break;\n }\n case CI_WORKFLOW_RESULT_KIND: {\n const r = parseCiWorkflowResult(ev);\n if (\n !r ||\n r.trigger.repoAddr !== repoAddr ||\n r.trigger.commit !== commit\n )\n break;\n const key = `${r.pubkey}:${r.runId}`;\n const prev = results.get(key);\n if (\n !prev ||\n r.createdAt > prev.createdAt ||\n (r.createdAt === prev.createdAt && r.eventId < prev.eventId)\n ) {\n results.set(key, r);\n }\n break;\n }\n case CI_WORKFLOW_PROGRESS_KIND: {\n const p = parseCiWorkflowProgress(ev);\n if (\n !p ||\n p.trigger.repoAddr !== repoAddr ||\n p.trigger.commit !== commit\n )\n break;\n const key = `${p.pubkey}:${p.runId}`;\n const prev = progresses.get(key);\n if (\n !prev ||\n p.createdAt > prev.createdAt ||\n (p.createdAt === prev.createdAt && p.eventId < prev.eventId)\n ) {\n progresses.set(key, p);\n }\n break;\n }\n case CI_JOB_RESULT_KIND: {\n const j = parseCiJobResult(ev);\n if (j && j.trigger.repoAddr === repoAddr && j.trigger.commit === commit)\n jobs.push(j);\n break;\n }\n default:\n break;\n }\n }\n\n const runs: CiStatusRun[] = [];\n const keys = new Set([...results.keys(), ...progresses.keys()]);\n for (const key of keys) {\n const result = results.get(key) ?? null;\n const progress = progresses.get(key) ?? null;\n const base = result ?? progress;\n if (!base) continue;\n const progressAddress = `${CI_WORKFLOW_PROGRESS_KIND}:${base.pubkey}:${base.runId}`;\n const runJobs = jobs\n .filter(\n (j) => j.progressAddress.toLowerCase() === progressAddress.toLowerCase()\n )\n .sort(\n (a, b) => (a.startedAt ?? a.createdAt) - (b.startedAt ?? b.createdAt)\n )\n .map<CiStatusJob>((j) => ({\n jobId: j.jobId,\n ...(j.name !== undefined ? { name: j.name } : {}),\n conclusion: j.conclusion,\n ...(j.logsUrl !== undefined ? { logsUrl: j.logsUrl } : {}),\n artifacts: j.artifacts,\n ...(j.exitCode !== undefined ? { exitCode: j.exitCode } : {}),\n ...(j.queuedAt !== undefined ? { queuedAt: j.queuedAt } : {}),\n ...(j.startedAt !== undefined ? { startedAt: j.startedAt } : {}),\n concludedAt: j.createdAt,\n eventId: j.eventId,\n publisher: j.pubkey,\n }));\n const provenance = result?.provenance ?? progress?.provenance;\n const trust = deriveTrustLevel({\n publisherPubkey: base.pubkey,\n ...(provenance ? { provenance } : {}),\n authorized: opts.authorized,\n controls,\n runCreatedAt: base.createdAt,\n });\n const status: CiProgressStatus = result\n ? 'concluded'\n : (progress as NonNullable<typeof progress>).status;\n const conclusion = result ? result.conclusion : progress?.conclusion;\n const startedAt = result?.startedAt ?? progress?.startedAt;\n const queuedAt = result?.queuedAt ?? progress?.queuedAt;\n runs.push({\n runId: base.runId,\n coordinator: base.pubkey,\n workflow: base.trigger.workflow,\n reason: base.trigger.reason,\n status,\n ...(conclusion !== undefined ? { conclusion } : {}),\n trust,\n createdAt: base.createdAt,\n ...(startedAt !== undefined ? { startedAt } : {}),\n ...(queuedAt !== undefined ? { queuedAt } : {}),\n ...(provenance ? { provenance } : {}),\n ...(base.trigger.pr\n ? {\n pr: {\n ...base.trigger.pr,\n authorIsMaintainer: opts.authorized.has(\n base.trigger.pr.prAuthor.toLowerCase()\n ),\n },\n }\n : {}),\n jobs: runJobs,\n eventId: base.eventId,\n });\n }\n runs.sort(\n (a, b) => b.createdAt - a.createdAt || (a.eventId < b.eventId ? -1 : 1)\n );\n\n // Latest attempt per (publisher, workflow path) is the one that counts.\n const latestByWorkflow = new Map<string, CiStatusRun>();\n for (const run of runs) {\n const k = `${run.coordinator}:${run.workflow.path}`;\n if (!latestByWorkflow.has(k)) latestByWorkflow.set(k, run); // runs are newest-first\n }\n const counted = [...latestByWorkflow.values()].filter(\n (run) =>\n (opts.workflow === undefined || run.workflow.path === opts.workflow) &&\n (opts.requireTrust === undefined ||\n trustAtLeast(run.trust, opts.requireTrust))\n );\n\n let green = 0;\n let red = 0;\n let pending = 0;\n for (const run of counted) {\n if (run.status !== 'concluded' || run.conclusion === undefined)\n pending += 1;\n else if (GREEN.has(run.conclusion)) green += 1;\n else red += 1;\n }\n const summary: CiStatusSummary = {\n counted: counted.length,\n green,\n red,\n pending,\n };\n let reason: string | undefined;\n if (counted.length === 0) {\n reason =\n runs.length === 0\n ? 'no CI runs found for this commit'\n : 'no run meets the workflow/trust requirement';\n } else if (red > 0) {\n reason = `${red} run(s) concluded red`;\n } else if (pending > 0) {\n reason = `${pending} run(s) not concluded yet`;\n }\n const ok = counted.length > 0 && red === 0 && pending === 0;\n return { runs, summary, ok, ...(reason !== undefined ? { reason } : {}) };\n}\n\n// ---------------------------------------------------------------------------\n// Command\n// ---------------------------------------------------------------------------\n\n/** Run `rig ci status …` (free); returns the process exit code. */\nexport async function runCiStatus(\n args: string[],\n deps: ReadCommandDeps\n): Promise<number> {\n const { io } = deps;\n let flags: StatusFlags;\n let commitArg: string;\n try {\n const { values, positionals } = parseArgs({\n args,\n options: STATUS_OPTIONS,\n allowPositionals: true,\n });\n flags = {\n json: values.json === true,\n help: values.help === true,\n relay: values.relay ?? [],\n };\n if (values.remote !== undefined) flags.remote = values.remote;\n if (values['repo-id'] !== undefined) flags.repoId = values['repo-id'];\n if (values.owner !== undefined) flags.owner = ownerToHex(values.owner);\n if (values.workflow !== undefined)\n flags.workflow = values.workflow.replace(/^\\.\\//, '');\n if (values['require-ci-trust'] !== undefined) {\n const level = values['require-ci-trust'];\n if (!isCiTrustLevel(level)) {\n throw new Error(\n `--require-ci-trust must be one of ${CI_TRUST_ORDER.join(' | ')} (got ${JSON.stringify(level)})`\n );\n }\n flags.requireTrust = level;\n }\n if (flags.help) {\n io.out(CI_STATUS_USAGE);\n return 0;\n }\n if (positionals.length !== 1) {\n throw new Error(\n positionals.length === 0\n ? '<commit> is required'\n : `expected exactly one <commit>, got ${positionals.length}`\n );\n }\n commitArg = positionals[0] as string;\n } catch (err) {\n io.err(err instanceof Error ? err.message : String(err));\n io.err(CI_STATUS_USAGE);\n return 2;\n }\n\n try {\n // ── Repo address + relays (best-effort git config; flags stand alone) ──\n let repoRoot: string | undefined;\n let toonConfig: { repoId?: string; owner?: string; relays: string[] } = {\n relays: [],\n };\n try {\n repoRoot = await resolveRepoRoot(deps.cwd);\n toonConfig = await readToonConfig(repoRoot);\n } catch {\n // Not inside a git repo — flags must carry everything.\n }\n const repoId = flags.repoId ?? toonConfig.repoId;\n if (!repoId) throw new UnconfiguredRepoAddressError('repository id');\n const owner = flags.owner ?? toonConfig.owner;\n if (!owner) throw new UnconfiguredRepoAddressError('repository owner');\n\n let commit = commitArg.toLowerCase();\n if (!FULL_SHA_RE.test(commit)) {\n if (repoRoot === undefined) {\n throw new Error(\n `<commit> must be a full 40-hex SHA outside a git repository (got ${JSON.stringify(commitArg)})`\n );\n }\n commit = (\n await runGit(repoRoot, [\n 'rev-parse',\n '--verify',\n `${commitArg}^{commit}`,\n ])\n ).trim();\n }\n\n const resolved = await resolveRelays({\n relayFlags: flags.relay,\n remoteName: flags.remote,\n repoRoot,\n toonRelays: toonConfig.relays,\n });\n const relays = resolved.relays.filter((url) => WS_URL_RE.test(url));\n if (relays.length === 0) {\n throw new InvalidRelayUrlError(\n resolved.relays[0] ?? '',\n 'reads need a ws:// or wss:// relay'\n );\n }\n const webSocketFactory = deps.webSocketFactory ?? defaultWebSocketFactory;\n const repoAddr = repoAddress(owner, repoId);\n\n // ── Reads ──────────────────────────────────────────────────────────────\n const events = await queryAll(\n relays,\n [\n {\n kinds: [\n CI_WORKFLOW_RESULT_KIND,\n CI_WORKFLOW_PROGRESS_KIND,\n CI_JOB_RESULT_KIND,\n ],\n '#a': [repoAddr],\n '#c': [commit],\n },\n {\n kinds: [CI_SERVICE_REQUEST_KIND, CI_SERVICE_STOP_KIND],\n '#a': [repoAddr],\n },\n {\n kinds: [REPOSITORY_ANNOUNCEMENT_KIND],\n authors: [owner],\n '#d': [repoId],\n },\n ],\n webSocketFactory\n );\n // Authority: the owner's own latest 30617 for this d-tag; owner-only when\n // absent (an unresolved announcement never widens authority).\n let announce: NostrEvent | null = null;\n for (const ev of events) {\n if (\n ev.kind !== REPOSITORY_ANNOUNCEMENT_KIND ||\n ev.pubkey.toLowerCase() !== owner\n )\n continue;\n if (!ev.tags.some((t) => t[0] === 'd' && t[1] === repoId)) continue;\n if (\n announce === null ||\n ev.created_at > announce.created_at ||\n (ev.created_at === announce.created_at && ev.id < announce.id)\n ) {\n announce = ev;\n }\n }\n const authorized = authorizedStatusAuthors(owner, announce?.tags ?? []);\n\n const assembled = assembleCiStatus({\n commit,\n ownerPubkey: owner,\n repoId,\n authorized,\n events,\n ...(flags.requireTrust !== undefined\n ? { requireTrust: flags.requireTrust }\n : {}),\n ...(flags.workflow !== undefined ? { workflow: flags.workflow } : {}),\n });\n\n const report: CiStatusReport = {\n command: 'ci status',\n commit,\n repo: { owner, repoId },\n relays,\n requiredTrust: flags.requireTrust ?? null,\n runs: assembled.runs,\n summary: assembled.summary,\n ok: assembled.ok,\n ...(assembled.reason !== undefined ? { reason: assembled.reason } : {}),\n };\n\n if (flags.json) {\n io.emitJson(report);\n } else {\n for (const line of renderStatus(report)) io.out(line);\n }\n return report.ok ? 0 : 1;\n } catch (err) {\n return emitCliError(io, flags.json, 'ci status', err);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Rendering\n// ---------------------------------------------------------------------------\n\nfunction glyph(run: CiStatusRun): string {\n if (run.status !== 'concluded' || run.conclusion === undefined) return '…';\n return GREEN.has(run.conclusion) ? '✓' : '✗';\n}\n\n/** ` pull request <id> by <npub> (author is a maintainer)[ via update <id>]` */\nfunction pullRequestLine(pr: CiStatusPullRequest): string {\n const who = pr.authorIsMaintainer\n ? 'author is a maintainer'\n : 'author is not a maintainer';\n const via =\n pr.sourceEventId !== pr.prEventId ? ` via update ${pr.sourceEventId}` : '';\n return ` pull request ${pr.prEventId} by ${shortNpub(pr.prAuthor)} (${who})${via}`;\n}\n\nfunction shortNpub(hex: string): string {\n try {\n const npub = hexToNpub(hex);\n return `${npub.slice(0, 12)}…${npub.slice(-4)}`;\n } catch {\n return `${hex.slice(0, 12)}…`;\n }\n}\n\n/** ` took 12s` from a start instant to an end instant; '' when unknown. */\nfunction tookSuffix(startedAt: number | undefined, endedAt: number): string {\n if (startedAt === undefined) return '';\n return ` took ${Math.max(0, endedAt - startedAt)}s`;\n}\n\n/**\n * Human lines: one per run (newest first) with its wall-clock time once\n * concluded, jobs indented with their durations, then the verdict.\n */\nexport function renderStatus(report: CiStatusReport): string[] {\n const lines: string[] = [];\n lines.push(\n `CI for ${report.commit.slice(0, 12)} in 30617:${report.repo.owner}:${report.repo.repoId}`\n );\n if (report.runs.length === 0) {\n lines.push(' (no runs)');\n }\n for (const run of report.runs) {\n const state =\n run.status === 'concluded' ? (run.conclusion ?? 'concluded') : run.status;\n const took =\n run.status === 'concluded'\n ? tookSuffix(run.startedAt, run.createdAt)\n : '';\n lines.push(\n `${glyph(run)} ${state.padEnd(15)} ${run.workflow.path} ${run.reason} ` +\n `coordinator ${shortNpub(run.coordinator)} trust ${run.trust}${took}`\n );\n for (const job of run.jobs) {\n const extra = job.exitCode !== undefined ? ` (exit ${job.exitCode})` : '';\n lines.push(\n ` ${job.conclusion.padEnd(15)} ${job.name ?? job.jobId}${extra}` +\n tookSuffix(job.startedAt, job.concludedAt)\n );\n }\n if (run.pr) lines.push(pullRequestLine(run.pr));\n }\n const s = report.summary;\n const verdict = report.ok\n ? 'GREEN'\n : `NOT GREEN — ${report.reason ?? 'see runs'}`;\n lines.push(\n `${verdict} (counted ${s.counted}: ${s.green} green, ${s.red} red, ${s.pending} pending` +\n (report.requiredTrust ? `; trust ≥ ${report.requiredTrust}` : '') +\n ')'\n );\n return lines;\n}\n","/**\n * Repo-local `rig` configuration, persisted in git's own storage:\n *\n * toon.repoid NIP-34 repository identifier (`d` tag)\n * toon.owner repository owner's Nostr pubkey (hex) — the identity that\n * signs kind:30617/30618 (`a`-tag `30617:<owner>:<repoId>`)\n * toon.relay relay URL(s), multi-valued — DEPRECATED since #249 (relays\n * live in real git remotes now; the key stays readable as a\n * fallback and is removed in v0.3)\n *\n * plus the REAL git remotes (`remote.<name>.url`) that #249 maps relays onto:\n * `rig remote add origin <relay-url>` is `git remote add`, so `git remote -v`\n * shows rig's relays and plain git tooling round-trips them.\n *\n * All access goes through `execFile git` with argument arrays (same\n * injection posture as GitRepoReader — never a shell).\n */\n\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\n\nconst execFileAsync = promisify(execFile);\n\n/** The rig-relevant git config keys of one repository. */\nexport interface ToonRepoConfig {\n repoId?: string;\n owner?: string;\n relays: string[];\n}\n\nasync function git(\n repoPath: string,\n args: string[],\n allowExitCodes: number[] = []\n): Promise<{ stdout: string; exitCode: number }> {\n try {\n const { stdout } = await execFileAsync('git', args, {\n cwd: repoPath,\n encoding: 'utf-8',\n });\n return { stdout, exitCode: 0 };\n } catch (err) {\n const e = err as NodeJS.ErrnoException & {\n code?: number | string;\n stdout?: string;\n stderr?: string;\n };\n const exitCode = typeof e.code === 'number' ? e.code : undefined;\n if (exitCode !== undefined && allowExitCodes.includes(exitCode)) {\n return { stdout: e.stdout ?? '', exitCode };\n }\n throw new Error(\n `git ${args.join(' ')} failed${exitCode !== undefined ? ` (exit ${exitCode})` : ''}: ` +\n `${(e.stderr ?? e.message ?? '').trim()}`\n );\n }\n}\n\n/**\n * Resolve the repository worktree root for `cwd` via\n * `git rev-parse --show-toplevel`. Throws a clear error when `cwd` is not\n * inside a git repository.\n */\nexport async function resolveRepoRoot(cwd: string): Promise<string> {\n try {\n const { stdout } = await execFileAsync(\n 'git',\n ['rev-parse', '--show-toplevel'],\n { cwd, encoding: 'utf-8' }\n );\n const root = stdout.trim();\n if (!root) throw new Error('empty rev-parse output');\n return root;\n } catch (err) {\n const e = err as { stderr?: string; message?: string };\n throw new Error(\n `not a git repository (run rig inside a repo): ${(e.stderr ?? e.message ?? '').trim()}`\n );\n }\n}\n\n/**\n * `git init` in `dir` — create a fresh repository there (never a shell). Runs\n * ONLY in `dir` itself, never a parent, and is idempotent (git init on an\n * existing repo is a no-op). Used by `rig init` when it offers to create the\n * repo for the user (consent-gated), mirroring how it offers to mint an\n * identity on a cold start.\n *\n * The initial branch is forced to `main`, deterministically — a stock git\n * without `init.defaultBranch=main` would otherwise create `master`, and every\n * rig doc/quickstart says `main` (so `rig push origin main` / `rig checkout\n * main` would then fail against a repo whose only branch is `master`). git\n * ≥ 2.28 takes `--initial-branch=main`; older git falls back to pointing the\n * unborn HEAD at `refs/heads/main` (no commits yet, so this just renames the\n * pending branch).\n */\nexport async function initGitRepository(dir: string): Promise<void> {\n try {\n await git(dir, ['init', '--initial-branch=main']);\n } catch {\n await git(dir, ['init']);\n await git(dir, ['symbolic-ref', 'HEAD', 'refs/heads/main']);\n }\n}\n\n/** Read the `toon.*` git config keys of the repository at `repoPath`. */\nexport async function readToonConfig(repoPath: string): Promise<ToonRepoConfig> {\n // exit 1 = key unset (git config --get convention) — tolerated everywhere.\n const [repoId, owner, relays] = await Promise.all([\n git(repoPath, ['config', '--get', 'toon.repoid'], [1]),\n git(repoPath, ['config', '--get', 'toon.owner'], [1]),\n git(repoPath, ['config', '--get-all', 'toon.relay'], [1]),\n ]);\n const config: ToonRepoConfig = {\n relays: relays.stdout\n .split('\\n')\n .map((l) => l.trim())\n .filter(Boolean),\n };\n const id = repoId.stdout.trim();\n if (repoId.exitCode === 0 && id) config.repoId = id;\n const own = owner.stdout.trim();\n if (owner.exitCode === 0 && own) config.owner = own;\n return config;\n}\n\n/** One configured git remote: its name + (possibly multiple) fetch URLs. */\nexport interface GitRemoteInfo {\n name: string;\n urls: string[];\n}\n\n/**\n * URLs of the git remote `name` (`remote.<name>.url`, multi-valued when\n * `git remote set-url --add` was used). `[]` when the remote does not exist.\n */\nexport async function getGitRemoteUrls(\n repoPath: string,\n name: string\n): Promise<string[]> {\n // exit 1 = key unset / invalid key — either way, no such remote.\n const { stdout } = await git(\n repoPath,\n ['config', '--get-all', `remote.${name}.url`],\n [1]\n );\n return stdout\n .split('\\n')\n .map((l) => l.trim())\n .filter(Boolean);\n}\n\n/** All configured git remotes with their URLs (`git remote -v` data). */\nexport async function listGitRemotes(\n repoPath: string\n): Promise<GitRemoteInfo[]> {\n const { stdout } = await git(repoPath, ['remote']);\n const names = stdout\n .split('\\n')\n .map((l) => l.trim())\n .filter(Boolean);\n const remotes: GitRemoteInfo[] = [];\n for (const name of names) {\n remotes.push({ name, urls: await getGitRemoteUrls(repoPath, name) });\n }\n return remotes;\n}\n\n/** The repo-local git author identity (`user.name` + `user.email`). */\nexport interface GitAuthorConfig {\n name?: string;\n email?: string;\n}\n\n/**\n * Read the repository's LOCAL `user.name` / `user.email` (never `--global`).\n * A `--local --get` miss is exit 1 (tolerated) and yields `undefined` — so\n * this reports only what THIS repo overrides, not any inherited global value.\n */\nexport async function readGitAuthor(\n repoPath: string\n): Promise<GitAuthorConfig> {\n const [name, email] = await Promise.all([\n git(repoPath, ['config', '--local', '--get', 'user.name'], [1]),\n git(repoPath, ['config', '--local', '--get', 'user.email'], [1]),\n ]);\n const config: GitAuthorConfig = {};\n const n = name.stdout.trim();\n if (name.exitCode === 0 && n) config.name = n;\n const e = email.stdout.trim();\n if (email.exitCode === 0 && e) config.email = e;\n return config;\n}\n\n/**\n * Set the repository's LOCAL git author identity — `git config --local`, so it\n * overrides any global `user.name`/`user.email` FOR THIS REPO ONLY and never\n * touches `~/.gitconfig`. On a rig repo the nostr key is the identity, so the\n * commit author == push signer == nostr identity (a coherent authorship chain\n * baked into the git objects on Arweave).\n */\nexport async function setGitAuthor(\n repoPath: string,\n author: { name: string; email: string }\n): Promise<void> {\n await git(repoPath, ['config', '--local', 'user.name', author.name]);\n await git(repoPath, ['config', '--local', 'user.email', author.email]);\n}\n\n/** `git remote add <name> <url>` — real git remote storage, never a shell. */\nexport async function addGitRemote(\n repoPath: string,\n name: string,\n url: string\n): Promise<void> {\n await git(repoPath, ['remote', 'add', name, url]);\n}\n\n/** `git remote remove <name>`. */\nexport async function removeGitRemote(\n repoPath: string,\n name: string\n): Promise<void> {\n await git(repoPath, ['remote', 'remove', name]);\n}\n\n/**\n * Persist the `toon.*` keys (repo-local config). Only supplied fields are\n * written; `relays` replaces the whole multi-valued list.\n */\nexport async function writeToonConfig(\n repoPath: string,\n config: { repoId?: string; owner?: string; relays?: string[] }\n): Promise<void> {\n if (config.repoId !== undefined) {\n await git(repoPath, ['config', 'toon.repoid', config.repoId]);\n }\n if (config.owner !== undefined) {\n await git(repoPath, ['config', 'toon.owner', config.owner]);\n }\n if (config.relays !== undefined && config.relays.length > 0) {\n // Replace the whole list: unset-all (exit 5 = key did not exist) + re-add.\n await git(repoPath, ['config', '--unset-all', 'toon.relay'], [5]);\n for (const relay of config.relays) {\n await git(repoPath, ['config', '--add', 'toon.relay', relay]);\n }\n }\n}\n","/**\n * Relays as origins (#249): the `rig remote` subcommand and the relay\n * resolution every paid command shares.\n *\n * Remotes are stored as REAL git remotes (`git remote add/remove` under the\n * hood), so `git remote -v` shows them and plain git tooling round-trips the\n * config — no parallel store. Paid commands resolve their relay as:\n *\n * 1. `--relay <url>` ad-hoc override, bypasses remotes\n * 2. a named remote `rig push <remote>` / `--remote <name>`\n * 3. the `origin` remote the default target\n * 4. git config `toon.relay` DEPRECATED v0.1 fallback (one-line nudge;\n * the key is removed in v0.3)\n * 5. error \"no origin configured — run `rig remote\n * add origin <relay-url>`\"\n *\n * A remote with multiple URLs (`git remote set-url --add` done by hand) is\n * refused BEFORE anything is fetched, uploaded, or paid: rig publishes to\n * exactly one relay per paid command (the #243 single-relay guard). One\n * carve-out: a default `origin` whose URLs are ALL non-relay is a plain git\n * remote — it is skipped like any single non-relay origin, never refused.\n */\n\nimport { parseArgs } from 'node:util';\nimport {\n emitCliError,\n InvalidRelayUrlError,\n MultiUrlRemoteError,\n NoOriginConfiguredError,\n NotAGitRepositoryError,\n UnknownRemoteError,\n} from './errors.js';\nimport {\n addGitRemote,\n getGitRemoteUrls,\n listGitRemotes,\n readToonConfig,\n removeGitRemote,\n resolveRepoRoot,\n} from './git-config.js';\nimport type { CliIo } from './push.js';\n\n// ---------------------------------------------------------------------------\n// Relay URL validation\n// ---------------------------------------------------------------------------\n\nconst RELAY_PROTOCOLS = new Set(['ws:', 'wss:', 'http:', 'https:']);\n\n/** True when `url` parses and uses a relay scheme (ws/wss/http/https). */\nexport function isRelayUrl(url: string): boolean {\n try {\n return RELAY_PROTOCOLS.has(new URL(url).protocol);\n } catch {\n return false;\n }\n}\n\n/** Throw {@link InvalidRelayUrlError} unless `url` is a relay URL. */\nexport function assertRelayUrl(url: string, context: string): void {\n if (!isRelayUrl(url)) throw new InvalidRelayUrlError(url, context);\n}\n\n// ---------------------------------------------------------------------------\n// Relay resolution (shared by push + the event commands)\n// ---------------------------------------------------------------------------\n\n/** Where the resolved relay came from. */\nexport type RelaySource = 'relay-flag' | 'remote' | 'toon.relay';\n\nexport interface ResolvedRelays {\n /** Relay URLs to publish to (paid commands still enforce exactly one). */\n relays: string[];\n source: RelaySource;\n /** The git remote that supplied the URL (source === 'remote'). */\n remoteName?: string;\n /** One-line stderr note (toon.relay deprecation), when applicable. */\n nudge?: string;\n}\n\nexport interface ResolveRelaysOptions {\n /** `--relay` flag values (may be >1 — the command-level guard refuses). */\n relayFlags: string[];\n /** Explicitly requested remote (`rig push <remote>` / `--remote <name>`). */\n remoteName?: string | undefined;\n /** Repo worktree root; undefined when not inside a git repository. */\n repoRoot?: string | undefined;\n /** Deprecated `git config toon.relay` values (v0.1 fallback). */\n toonRelays: string[];\n}\n\n/**\n * Resolve the relay(s) for a paid command. Throws (before any payment):\n * {@link UnknownRemoteError}, {@link MultiUrlRemoteError},\n * {@link InvalidRelayUrlError}, {@link NoOriginConfiguredError}.\n */\nexport async function resolveRelays(\n opts: ResolveRelaysOptions\n): Promise<ResolvedRelays> {\n // 1. Ad-hoc --relay override: bypasses the configured remotes entirely.\n if (opts.relayFlags.length > 0) {\n return { relays: opts.relayFlags, source: 'relay-flag' };\n }\n\n // 2. Explicitly named remote: must exist, carry ONE URL, and be a relay.\n if (opts.remoteName !== undefined) {\n const urls =\n opts.repoRoot !== undefined\n ? await getGitRemoteUrls(opts.repoRoot, opts.remoteName)\n : [];\n if (urls.length === 0) throw new UnknownRemoteError(opts.remoteName);\n if (urls.length > 1) throw new MultiUrlRemoteError(opts.remoteName, urls);\n const url = urls[0] as string;\n assertRelayUrl(url, `remote ${JSON.stringify(opts.remoteName)}`);\n return { relays: urls, source: 'remote', remoteName: opts.remoteName };\n }\n\n // 3. Default remote: origin — when it looks like a relay. A PURELY\n // non-relay origin (e.g. a GitHub clone URL, even one with several\n // mirror push URLs) is skipped, not an error: rig shares git's remote\n // namespace, so pre-existing git origins must not break paid commands\n // that can still resolve via toon.relay. But the moment ANY of a\n // multi-URL origin's URLs is relay-shaped, the publish target is\n // ambiguous — refuse before anything is fetched, uploaded, or paid\n // (the #243 single-relay guard).\n let nonRelayOriginUrl: string | undefined;\n if (opts.repoRoot !== undefined) {\n const urls = await getGitRemoteUrls(opts.repoRoot, 'origin');\n if (urls.length === 1 && isRelayUrl(urls[0] as string)) {\n return { relays: urls, source: 'remote', remoteName: 'origin' };\n }\n if (urls.length > 1 && urls.some(isRelayUrl)) {\n throw new MultiUrlRemoteError('origin', urls);\n }\n // Reachable only when every remaining URL is non-relay (single relay URL\n // returned above; multi-URL with any relay URL threw above), so urls[0]\n // is guaranteed non-relay — NoOriginConfiguredError's message relies on\n // that (\"the existing origin is not a relay URL\").\n if (urls.length > 0) nonRelayOriginUrl = urls[0] as string;\n }\n\n // 4. Deprecated v0.1 fallback: git config toon.relay (nudges to migrate).\n if (opts.toonRelays.length > 0) {\n return {\n relays: opts.toonRelays,\n source: 'toon.relay',\n nudge:\n 'note: git config toon.relay is deprecated (removed in v0.3) — ' +\n `migrate: rig remote add origin ${opts.toonRelays[0]}`,\n };\n }\n\n // 5. Nothing resolved.\n throw new NoOriginConfiguredError(nonRelayOriginUrl);\n}\n\n/**\n * Refusal line for >1 resolved relays: the StandalonePublisher publishes to\n * exactly one relay per paid command, and multiple can arrive without\n * explicit intent (repeated --relay flags, a multi-valued toon.relay).\n * `nothingHappened` names what was NOT done, e.g. 'Nothing was uploaded or\n * paid.'\n */\nexport function singleRelayRefusal(\n resolved: ResolvedRelays,\n nothingHappened: string\n): string {\n const fix =\n resolved.source === 'relay-flag'\n ? 'pass exactly one --relay <url>'\n : 'trim git config toon.relay to one URL (better: migrate — ' +\n '`rig remote add origin <relay-url>`)';\n return (\n `rig publishes to a single relay, but ${resolved.relays.length} are ` +\n `configured (${resolved.relays.join(', ')}) — ${fix}. ${nothingHappened}`\n );\n}\n\n// ---------------------------------------------------------------------------\n// rig remote <add|remove|list>\n// ---------------------------------------------------------------------------\n\nexport const REMOTE_USAGE = `Usage: rig remote <add|remove|list> [args] [options]\n\nManage the relays this repo publishes to. Remotes are stored as REAL git\nremotes (\\`git remote -v\\` shows them; plain git tooling round-trips). Paid\ncommands publish via the \"origin\" remote by default; \\`rig push <remote>\\`\nand \\`--remote <name>\\` target another one. Free — nothing is published or\npaid.\n\nCommands:\n add <name> <relay-url> add a remote pointing at a relay (the URL must be\n ws://, wss://, http://, or https://)\n remove <name> remove a remote\n list list remote names + URLs (the default subcommand)\n\nOptions:\n --json machine-readable envelope (all subcommands)\n -h, --help show this help`;\n\n/** Deps subset `rig remote` needs (free — no publisher, no identity). */\nexport interface RemoteDeps {\n io: CliIo;\n cwd: string;\n}\n\n/** Run `rig remote …`; returns the process exit code. */\nexport async function runRemote(\n args: string[],\n deps: RemoteDeps\n): Promise<number> {\n const { io } = deps;\n\n let sub: string | undefined;\n let rest: string[];\n let json: boolean;\n try {\n const { values, positionals } = parseArgs({\n args,\n options: {\n json: { type: 'boolean', default: false },\n help: { type: 'boolean', short: 'h', default: false },\n },\n allowPositionals: true,\n });\n if (values.help) {\n io.out(REMOTE_USAGE);\n return 0;\n }\n json = values.json ?? false;\n [sub, ...rest] = positionals;\n } catch (err) {\n io.err(err instanceof Error ? err.message : String(err));\n io.err(REMOTE_USAGE);\n return 2;\n }\n\n // Argument-shape validation (exit 2) before touching the repository.\n switch (sub) {\n case undefined:\n case 'list':\n if (rest.length > 0) {\n io.err(`rig remote list takes no arguments (got ${rest.join(' ')})`);\n io.err(REMOTE_USAGE);\n return 2;\n }\n break;\n case 'add': {\n if (rest.length !== 2) {\n io.err('usage: rig remote add <name> <relay-url>');\n io.err(REMOTE_USAGE);\n return 2;\n }\n const url = rest[1] as string;\n if (!isRelayUrl(url)) {\n io.err(\n `cannot add remote: ${JSON.stringify(url)} is not a relay URL — ` +\n 'relays are ws://, wss://, http://, or https://'\n );\n return 2;\n }\n break;\n }\n case 'remove':\n if (rest.length !== 1) {\n io.err('usage: rig remote remove <name>');\n io.err(REMOTE_USAGE);\n return 2;\n }\n break;\n default:\n io.err(`unknown rig remote subcommand: ${sub}`);\n io.err(REMOTE_USAGE);\n return 2;\n }\n\n try {\n let repoRoot: string;\n try {\n repoRoot = await resolveRepoRoot(deps.cwd);\n } catch {\n throw new NotAGitRepositoryError(deps.cwd);\n }\n\n switch (sub) {\n case undefined:\n case 'list': {\n const remotes = await listGitRemotes(repoRoot);\n if (json) {\n io.emitJson({ command: 'remote', remotes });\n return 0;\n }\n if (remotes.length === 0) {\n io.out(\n 'no remotes configured — add one: rig remote add origin <relay-url>'\n );\n return 0;\n }\n for (const remote of remotes) {\n for (const url of remote.urls) {\n io.out(\n `${remote.name}\\t${url}` +\n (isRelayUrl(url) ? '' : '\\t(not a relay URL — ignored by rig)')\n );\n }\n if (remote.urls.length > 1) {\n io.err(\n `warning: remote \"${remote.name}\" has ${remote.urls.length} ` +\n 'URLs — rig supports one relay URL per remote (fix with ' +\n `\\`git remote set-url ${remote.name} <relay-url>\\`)`\n );\n }\n }\n return 0;\n }\n\n case 'add': {\n const [name, url] = rest as [string, string];\n const existing = await getGitRemoteUrls(repoRoot, name);\n if (existing.length > 0) {\n const detail =\n `remote ${JSON.stringify(name)} already exists ` +\n `(${existing.join(', ')}) — nothing changed. Point it ` +\n `somewhere else with \\`git remote set-url ${name} <relay-url>\\`, ` +\n `or \\`rig remote remove ${name}\\` first.`;\n if (json) {\n io.emitJson({\n command: 'remote',\n error: 'remote_exists',\n detail,\n remote: name,\n urls: existing,\n });\n }\n io.err(detail);\n return 1;\n }\n await addGitRemote(repoRoot, name, url);\n if (!json) io.out(`Added remote ${name} → ${url}`);\n if (name === 'origin') {\n if (!json) {\n io.out(\n '`rig push` and the event commands now publish here by default.'\n );\n }\n const toonConfig = await readToonConfig(repoRoot);\n if (toonConfig.relays.length > 0) {\n io.err(\n `note: git config toon.relay (${toonConfig.relays.join(', ')}) ` +\n 'is deprecated and now shadowed by the origin remote — drop ' +\n 'it with `git config --unset-all toon.relay` (the key is ' +\n 'removed in v0.3).'\n );\n }\n }\n if (json) {\n io.emitJson({ command: 'remote', action: 'add', name, url });\n }\n return 0;\n }\n\n case 'remove': {\n const name = rest[0] as string;\n const existing = await getGitRemoteUrls(repoRoot, name);\n if (existing.length === 0) {\n const detail =\n `no remote named ${JSON.stringify(name)} — ` +\n '`rig remote list` shows configured remotes.';\n if (json) {\n io.emitJson({\n command: 'remote',\n error: 'unknown_remote',\n detail,\n remote: name,\n });\n }\n io.err(detail);\n return 1;\n }\n await removeGitRemote(repoRoot, name);\n if (json) {\n io.emitJson({ command: 'remote', action: 'remove', name });\n } else {\n io.out(`Removed remote ${name}`);\n }\n return 0;\n }\n\n /* v8 ignore next 2 -- unreachable: validated above */\n default:\n return 2;\n }\n } catch (err) {\n return emitCliError(io, json, 'remote', err);\n }\n}\n"],"mappings":"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","names":["OBJECT_TYPES","FULL_SHA_RE","execFile","spawn","promisify","execFileAsync","FULL_SHA_RE","assertFullSha","values","HEX64","values","createHash","ctx","parseArgs","execFile","promisify","execFileAsync","values","FULL_SHA_RE","values","parseArgs"]}