@fro.bot/harness 1.15.13 → 1.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +2 -2
- package/dist/cli.mjs.map +1 -1
- package/package.json +5 -5
- package/provenance.json +4 -3
package/dist/cli.mjs
CHANGED
|
@@ -597,7 +597,7 @@ function getProvenance() {
|
|
|
597
597
|
const parsed = JSON.parse(raw);
|
|
598
598
|
if (!isValidHarnessConfig(parsed)) throw new Error("Invalid harness.config.json shape");
|
|
599
599
|
return {
|
|
600
|
-
baseVersion: parsed.base_version ?? "1.
|
|
600
|
+
baseVersion: parsed.base_version ?? "1.16.0",
|
|
601
601
|
integrationRefs: (parsed.integrationRefs ?? []).map((ref) => ({
|
|
602
602
|
ref,
|
|
603
603
|
resolvedSha: "dev"
|
|
@@ -607,7 +607,7 @@ function getProvenance() {
|
|
|
607
607
|
};
|
|
608
608
|
} catch {}
|
|
609
609
|
return {
|
|
610
|
-
baseVersion: "1.
|
|
610
|
+
baseVersion: "1.16.0",
|
|
611
611
|
integrationRefs: [],
|
|
612
612
|
integrationCommit: null,
|
|
613
613
|
buildSha: "dev"
|
package/dist/cli.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.mjs","names":["isValidHarnessConfig","packageRoot"],"sources":["../src/sources.ts","../src/integrate.ts","../src/integrate-command.ts","../src/provenance.ts","../src/resolve-binary.ts","../src/cli.ts"],"sourcesContent":["/**\n * Integration source resolution — maps each configured ref to git fetch refs.\n *\n * Ported from cortexkit/orw src/index.ts parseSource (MIT).\n * Adapted for CI/non-interactive use: no launchd, no desktop, no interactive prompts.\n *\n * Supported input forms:\n * - Local branch name (no https:// prefix) → refs/heads/<b>\n * - GitHub branch URL (https://github.com/owner/repo/tree/<branch>) → refs/heads/<branch>\n * - GitHub PR URL (https://github.com/owner/repo/pull/N) → refs/pull/N/head\n *\n * Throws on empty input or unsupported URL forms.\n */\n\nexport interface IntegrationSource {\n /** Human-readable label for log output and the merge prompt. */\n readonly label: string\n /** Git remote URL for the source repository. */\n readonly repo: string\n /** The ref to fetch from the remote (e.g. refs/pull/N/head, refs/heads/<b>). */\n readonly fetchRef: string\n /** The local remote-tracking ref to store the fetched ref under. */\n readonly fetch: string\n /** The ref to merge (same as fetch; kept separate for prompt rendering). */\n readonly merge: string\n}\n\n/**\n * Maps a single integration source input to a typed IntegrationSource.\n *\n * @param input - A PR URL, branch URL, or local branch name from config.\n * @param sourceRepo - The default source repo URL (used for local branch names).\n */\nexport function parseSource(input: string, sourceRepo: string): IntegrationSource {\n const value = input.trim()\n if (value.length === 0) throw new Error('Empty integration source in config branches')\n\n if (!value.startsWith('https://github.com/')) {\n // Local branch name — fetch from the source repo.\n return {\n label: value,\n repo: sourceRepo,\n fetchRef: `refs/heads/${value}`,\n fetch: `refs/remotes/watch/local/${value}`,\n merge: `refs/remotes/watch/local/${value}`,\n }\n }\n\n const url = new URL(value)\n const parts = url.pathname.split('/').filter(Boolean)\n const owner = parts[0]\n const repo = parts[1]\n if (owner === undefined || repo === undefined) throw new Error(`Unsupported GitHub source URL: ${value}`)\n\n if (parts.length >= 4 && parts[2] === 'tree') {\n const branch = decodeURIComponent(parts.slice(3).join('/'))\n const slug = watchSlug(owner, repo)\n const ref = `refs/remotes/watch/${slug}/${branch}`\n return {\n label: `${owner}/${repo}:${branch}`,\n repo: `https://github.com/${owner}/${repo}.git`,\n fetchRef: `refs/heads/${branch}`,\n fetch: ref,\n merge: ref,\n }\n }\n\n if (parts.length >= 4 && parts[2] === 'pull') {\n const number = parts[3] ?? ''\n if (!/^\\d+$/.test(number)) {\n throw new Error(`Unsupported GitHub pull request URL: ${value}`)\n }\n const slug = watchSlug(owner, repo)\n const ref = `refs/remotes/watch/${slug}/pr-${number}`\n return {\n label: `${owner}/${repo}#${number}`,\n repo: `https://github.com/${owner}/${repo}.git`,\n fetchRef: `refs/pull/${number}/head`,\n fetch: ref,\n merge: ref,\n }\n }\n\n throw new Error(`Unsupported GitHub integration source URL: ${value}`)\n}\n\n/**\n * Maps an array of integration source inputs to typed IntegrationSources.\n *\n * @param refs - Array of PR URLs, branch URLs, or local branch names.\n * @param sourceRepo - The default source repo URL (used for local branch names).\n */\nexport function resolveSources(refs: readonly string[], sourceRepo: string): IntegrationSource[] {\n return refs.map(input => parseSource(input, sourceRepo))\n}\n\nfunction watchSlug(owner: string, repo: string): string {\n return `${owner}-${repo}`.replaceAll(/[^\\w.-]/g, '-')\n}\n","/**\n * Integration engine — orw-embedded LLM merge onto the release tag.\n *\n * Ported from cortexkit/orw src/index.ts check/prep/render/verifyBuild (MIT).\n * Adapted for CI/non-interactive use: no launchd, no desktop, no interactive prompts.\n *\n * The actual opencode run LLM merge is NOT unit-tested here — it requires a live\n * opencode binary + model + network. Unit tests cover the fail-hard/freeze/provenance\n * contract via injected adapters (cloneRepo, fetchRef, runMerge, buildCli, verifyVersion).\n *\n * Fail-hard contract: any failure (merge unresolved, build fail, version mismatch)\n * returns {ok:false, error} and writes NO provenance manifest. The manifest is the\n * single source of truth — it is only written after all steps succeed (freeze).\n */\n\n// IntegrationRefRecord is the canonical type — defined once in provenance.ts.\nimport type {IntegrationRefRecord} from './provenance.js'\nimport type {IntegrationSource} from './sources.js'\nimport {execFile} from 'node:child_process'\nimport fs from 'node:fs/promises'\nimport path from 'node:path'\nimport process from 'node:process'\nimport {promisify} from 'node:util'\nimport {resolveSources} from './sources.js'\n\n// Re-export so callers that previously imported from integrate.ts still work.\nexport type {IntegrationRefRecord} from './provenance.js'\n\n// ---------------------------------------------------------------------------\n// Provenance manifest types\n// ---------------------------------------------------------------------------\n\nexport interface ProvenanceManifest {\n readonly baseVersion: string\n readonly integrationRefs: readonly IntegrationRefRecord[]\n readonly integrationCommit: string\n readonly buildSha: string\n}\n\n// ---------------------------------------------------------------------------\n// Integration config\n// ---------------------------------------------------------------------------\n\nexport interface IntegrationConfig {\n readonly baseVersion: string\n readonly releaseRepo: string\n readonly integrationRefs: readonly string[]\n readonly agent: string\n readonly model: string\n readonly opencodeBin: string\n readonly workDir: string\n readonly promptPath: string\n}\n\n// ---------------------------------------------------------------------------\n// Injectable adapters (dependency injection for testability)\n// ---------------------------------------------------------------------------\n\nexport interface IntegrationAdapters {\n /** Clone the release repo into workDir. */\n cloneRepo: (repoUrl: string, workDir: string) => Promise<void>\n /** Fetch tags from origin. */\n fetchTags: (workDir: string) => Promise<void>\n /** Fetch a single integration ref into a local tracking ref. */\n fetchRef: (workDir: string, remoteUrl: string, fetchRef: string, localRef: string) => Promise<void>\n /** Create/reset the integration branch to the release tag. */\n createBranch: (workDir: string, branch: string, tag: string) => Promise<void>\n /** Run the LLM merge via opencode run. */\n runMerge: (workDir: string, opencodeBin: string, agent: string, model: string, prompt: string) => Promise<void>\n /** Build the native CLI in the work repo. */\n buildCli: (workDir: string, version: string, channel: string) => Promise<void>\n /** Verify the built CLI --version matches the expected version. */\n verifyVersion: (workDir: string, expectedVersion: string) => Promise<void>\n /** Commit the integrated working tree (after LLM merge) so HEAD contains the merge. */\n commitIntegration: (workDir: string, message: string) => Promise<void>\n /** Get the current HEAD commit SHA of the work repo. */\n getCommitSha: (workDir: string) => Promise<string>\n}\n\n// ---------------------------------------------------------------------------\n// Integration result\n// ---------------------------------------------------------------------------\n\nexport type IntegrationResult =\n | {readonly ok: true; readonly manifest: ProvenanceManifest}\n | {readonly ok: false; readonly error: string}\n\n// ---------------------------------------------------------------------------\n// Provenance manifest I/O (single source of truth)\n// ---------------------------------------------------------------------------\n\nconst MANIFEST_FILENAME = 'provenance.json'\n\n/**\n * Writes the provenance manifest to the given directory.\n * This is the freeze step — called only after all integration steps succeed.\n */\nexport async function writeProvenanceManifest(dir: string, manifest: ProvenanceManifest): Promise<void> {\n await fs.mkdir(dir, {recursive: true})\n await fs.writeFile(path.join(dir, MANIFEST_FILENAME), `${JSON.stringify(manifest, null, 2)}\\n`, 'utf8')\n}\n\n/**\n * Type guard: validates that an unknown value has the shape of a ProvenanceManifest.\n * Treats malformed/partial JSON as invalid rather than silently returning partial data.\n */\nfunction isValidProvenanceManifest(value: unknown): value is ProvenanceManifest {\n if (value === null || typeof value !== 'object') return false\n const v = value as Record<string, unknown>\n if (typeof v.baseVersion !== 'string' || v.baseVersion.length === 0) return false\n if (!Array.isArray(v.integrationRefs)) return false\n if (typeof v.integrationCommit !== 'string' || v.integrationCommit.length === 0) return false\n if (typeof v.buildSha !== 'string') return false\n return true\n}\n\n/**\n * Reads the provenance manifest from the given directory.\n * Returns null if the manifest does not exist or has an invalid shape.\n * Uses isValidProvenanceManifest to guard against malformed/partial manifests.\n */\nexport async function readProvenanceManifest(dir: string): Promise<ProvenanceManifest | null> {\n const manifestPath = path.join(dir, MANIFEST_FILENAME)\n try {\n const raw = await fs.readFile(manifestPath, 'utf8')\n const parsed: unknown = JSON.parse(raw)\n if (!isValidProvenanceManifest(parsed)) {\n return null\n }\n return parsed\n } catch {\n return null\n }\n}\n\n// ---------------------------------------------------------------------------\n// Prompt rendering (adapted from orw render())\n// ---------------------------------------------------------------------------\n\nfunction integrationBranch(version: string): string {\n return `integrate/v${version}`\n}\n\nasync function renderPrompt(\n promptPath: string,\n workDir: string,\n baseVersion: string,\n releaseRepo: string,\n sources: IntegrationSource[],\n): Promise<string> {\n const tag = `v${baseVersion}`\n const branch = integrationBranch(baseVersion)\n const channel = 'latest'\n const tpl = await fs.readFile(promptPath, 'utf8')\n const vars: Record<string, string> = {\n repo: workDir,\n tag,\n version: baseVersion,\n channel,\n branches: sources.map(s => s.label).join(', '),\n branch,\n merges: sources.map(s => s.merge).join(', then '),\n sources: sources.map(s => `${s.label} -> ${s.merge}`).join('\\n- '),\n release_repo: releaseRepo,\n base: 'dev',\n release_url: `https://github.com/${releaseRepo}/releases/tag/${tag}`,\n }\n return Object.entries(vars).reduce((text, [key, value]) => text.replaceAll(`{{${key}}}`, value), tpl)\n}\n\nconst execFileAsync = promisify(execFile)\n\nasync function gitExec(args: string[], cwd?: string): Promise<string> {\n const {stdout} = await execFileAsync('git', args, {cwd, encoding: 'utf8'})\n return stdout.trim()\n}\n\nexport function makeRealAdapters(): IntegrationAdapters {\n return {\n cloneRepo: async (repoUrl, workDir) => {\n await fs.rm(workDir, {recursive: true, force: true})\n await fs.mkdir(path.dirname(workDir), {recursive: true})\n await gitExec(['clone', repoUrl, workDir])\n },\n\n fetchTags: async workDir => {\n await gitExec(['fetch', 'origin', '--tags'], workDir)\n },\n\n fetchRef: async (workDir, remoteUrl, fetchRef, localRef) => {\n await gitExec(['fetch', remoteUrl, `${fetchRef}:${localRef}`], workDir)\n },\n\n createBranch: async (workDir, branch, tag) => {\n // Reset or create the integration branch at the release tag.\n try {\n await gitExec(['checkout', '-B', branch, `refs/tags/${tag}`], workDir)\n } catch {\n await gitExec(['checkout', '-b', branch, `refs/tags/${tag}`], workDir)\n }\n },\n\n runMerge: async (workDir, opencodeBin, agent, model, prompt) => {\n // Run opencode run synchronously — do NOT use background:true.\n // Poll to terminal state; the non-interactive tool exits when done.\n await execFileAsync(opencodeBin, ['run', '--agent', agent, '--model', model, prompt], {\n cwd: workDir,\n encoding: 'utf8',\n timeout: 30 * 60 * 1000, // 30-minute hard timeout\n })\n },\n\n buildCli: async (workDir, version, channel) => {\n await execFileAsync('bun', ['run', 'build', '--', '--single'], {\n cwd: path.join(workDir, 'packages', 'opencode'),\n encoding: 'utf8',\n env: {\n ...process.env,\n OPENCODE_CHANNEL: channel,\n OPENCODE_VERSION: version,\n },\n timeout: 20 * 60 * 1000, // 20-minute hard timeout\n })\n },\n\n verifyVersion: async (workDir, expectedVersion) => {\n const cliPath = resolveCliPath(workDir)\n const {stdout} = await execFileAsync(cliPath, ['--version'], {\n encoding: 'utf8',\n timeout: 30_000,\n })\n const actual = stdout.trim()\n if (actual !== expectedVersion) {\n throw new Error(`Built CLI reported version ${actual}, expected ${expectedVersion}`)\n }\n },\n\n commitIntegration: async (workDir, message) => {\n // Stage all changes (new, modified, deleted) from the LLM merge.\n await gitExec(\n [\n '-c',\n 'user.name=fro-bot harness integrate',\n '-c',\n 'user.email=github-actions[bot]@users.noreply.github.com',\n 'add',\n '-A',\n ],\n workDir,\n )\n // Commit with --no-verify to skip any hooks in the cloned upstream repo.\n await gitExec(\n [\n '-c',\n 'user.name=fro-bot harness integrate',\n '-c',\n 'user.email=github-actions[bot]@users.noreply.github.com',\n 'commit',\n '--no-verify',\n '-m',\n message,\n ],\n workDir,\n )\n },\n\n getCommitSha: async workDir => {\n return gitExec(['rev-parse', 'HEAD'], workDir)\n },\n }\n}\n\nfunction resolveCliPath(workDir: string): string {\n const os = process.platform === 'win32' ? 'windows' : process.platform\n const arch = process.arch\n const name = `opencode-${os}-${arch}`\n const binary = process.platform === 'win32' ? 'opencode.exe' : 'opencode'\n return path.join(workDir, 'packages', 'opencode', 'dist', name, 'bin', binary)\n}\n\n// ---------------------------------------------------------------------------\n// Core integration orchestration\n// ---------------------------------------------------------------------------\n\n/**\n * Runs the full integration pipeline:\n * clone → fetch tags → fetch refs → create branch → LLM merge → build → verify → freeze\n *\n * On any failure: returns {ok:false, error} and writes NO manifest (fail-hard contract).\n * On success: writes the provenance manifest to workDir and returns {ok:true, manifest}.\n *\n * @param config - Integration configuration (base version, refs, model, etc.)\n * @param adapters - Injectable adapters for each step (real or stubbed for tests).\n */\nexport async function runIntegration(\n config: IntegrationConfig,\n adapters: IntegrationAdapters,\n): Promise<IntegrationResult> {\n const {baseVersion, releaseRepo, integrationRefs, agent, model, opencodeBin, workDir, promptPath} = config\n const tag = `v${baseVersion}`\n const branch = integrationBranch(baseVersion)\n const channel = 'latest'\n\n // Resolve sources — wrap in try/catch so invalid refs return {ok:false} instead of throwing.\n let sources: IntegrationSource[]\n try {\n sources = resolveSources(integrationRefs, `https://github.com/${releaseRepo}.git`)\n } catch (error) {\n return {ok: false, error: `Resolve sources failed: ${errorMessage(error)}`}\n }\n\n // Step 1: Clone the release repo.\n try {\n await adapters.cloneRepo(`https://github.com/${releaseRepo}.git`, workDir)\n } catch (error) {\n return {ok: false, error: `Clone failed: ${errorMessage(error)}`}\n }\n\n // Step 2: Fetch tags.\n try {\n await adapters.fetchTags(workDir)\n } catch (error) {\n return {ok: false, error: `Fetch tags failed: ${errorMessage(error)}`}\n }\n\n // Step 3: Fetch each integration ref.\n for (const source of sources) {\n try {\n await adapters.fetchRef(workDir, source.repo, source.fetchRef, source.fetch)\n } catch (error) {\n return {ok: false, error: `Fetch ref ${source.label} failed: ${errorMessage(error)}`}\n }\n }\n\n // Step 4: Create/reset the integration branch at the release tag.\n try {\n await adapters.createBranch(workDir, branch, tag)\n } catch (error) {\n return {ok: false, error: `Create branch ${branch} at ${tag} failed: ${errorMessage(error)}`}\n }\n\n // Step 5: Run the LLM merge (only when there are refs to merge).\n if (sources.length > 0) {\n let prompt: string\n try {\n prompt = await renderPrompt(promptPath, workDir, baseVersion, releaseRepo, sources)\n } catch (error) {\n return {ok: false, error: `Render merge prompt failed: ${errorMessage(error)}`}\n }\n\n try {\n await adapters.runMerge(workDir, opencodeBin, agent, model, prompt)\n } catch (error) {\n return {ok: false, error: `LLM merge failed: ${errorMessage(error)}`}\n }\n\n // Step 5.5: Commit the integrated working tree so HEAD contains the merge.\n // Without this, getCommitSha (Step 8) returns the bare tag SHA and\n // git archive would ship the pre-merge tree.\n try {\n await adapters.commitIntegration(workDir, `integrate: apply LLM merge onto v${baseVersion}`)\n } catch (error) {\n return {ok: false, error: `Commit integration failed: ${errorMessage(error)}`}\n }\n\n // Step 6: Build the native CLI.\n try {\n await adapters.buildCli(workDir, baseVersion, channel)\n } catch (error) {\n return {ok: false, error: `Build CLI failed: ${errorMessage(error)}`}\n }\n\n // Step 7: Verify --version matches the base.\n try {\n await adapters.verifyVersion(workDir, baseVersion)\n } catch (error) {\n return {ok: false, error: `Version verification failed: ${errorMessage(error)}`}\n }\n }\n\n // Step 8: Capture the frozen integration commit SHA.\n let integrationCommit: string\n try {\n integrationCommit = await adapters.getCommitSha(workDir)\n } catch (error) {\n return {ok: false, error: `Get commit SHA failed: ${errorMessage(error)}`}\n }\n\n // Step 9: Build the provenance manifest and freeze it.\n // Per-ref SHA resolution is tracked separately; all refs share the integration commit for now.\n const manifest: ProvenanceManifest = {\n baseVersion,\n integrationRefs: sources.map((s, i) => ({\n ref: integrationRefs[i] ?? s.label,\n resolvedSha: integrationCommit,\n })),\n integrationCommit,\n buildSha: 'dev', // replaced by the per-platform build job at publish time\n }\n\n try {\n await writeProvenanceManifest(workDir, manifest)\n } catch (error) {\n return {ok: false, error: `Write provenance manifest failed: ${errorMessage(error)}`}\n }\n\n return {ok: true, manifest}\n}\n\nfunction errorMessage(err: unknown): string {\n if (err instanceof Error) return err.message\n return String(err)\n}\n","/**\n * integrate-command.ts — `harness integrate` subcommand implementation.\n *\n * Reads harness.config.json for: baseVersion, releaseRepo, integrationRefs,\n * agent, model, opencodeBin. Parses --work-dir, --prompt-path, --out from argv.\n * Assembles IntegrationConfig and calls runIntegration(config, makeRealAdapters()).\n *\n * On {ok:true}: packages a clean merged source snapshot (via git archive) plus\n * provenance.json into a single artifact at --out using atomic staging.\n *\n * Exit codes: 0 on {ok:true} + artifact written, 1 on {ok:false} or exception.\n * Error output: one-line message only — no stack traces, no secrets.\n *\n * No classes; functions only; explicit boolean checks; no as-any.\n */\n\nimport type {IntegrationConfig} from './integrate.js'\nimport {execFileSync, execSync} from 'node:child_process'\nimport {copyFileSync, mkdirSync, mkdtempSync, readFileSync, renameSync, rmSync} from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\nimport {fileURLToPath} from 'node:url'\nimport {makeRealAdapters, runIntegration} from './integrate.js'\n\n// ---------------------------------------------------------------------------\n// Config file shape\n// ---------------------------------------------------------------------------\n\ninterface HarnessConfig {\n readonly release_repo: string\n readonly base_version: string\n readonly integrationRefs: readonly string[]\n readonly agent: string\n readonly model: string\n readonly opencode_bin?: string\n}\n\nfunction isValidHarnessConfig(value: unknown): value is HarnessConfig {\n if (value === null || typeof value !== 'object') return false\n const v = value as Record<string, unknown>\n if (typeof v.release_repo !== 'string' || v.release_repo.length === 0) return false\n if (typeof v.base_version !== 'string' || v.base_version.length === 0) return false\n if (!Array.isArray(v.integrationRefs)) return false\n if (!v.integrationRefs.every((el: unknown) => typeof el === 'string' && el.length > 0)) return false\n if (typeof v.agent !== 'string' || v.agent.length === 0) return false\n if (typeof v.model !== 'string' || v.model.length === 0) return false\n if (v.opencode_bin !== undefined && typeof v.opencode_bin !== 'string') return false\n return true\n}\n\n// ---------------------------------------------------------------------------\n// Default config path (relative to this file's package root)\n// ---------------------------------------------------------------------------\n\nconst packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')\nexport const DEFAULT_CONFIG_PATH = path.join(packageRoot, 'harness.config.json')\n\n// ---------------------------------------------------------------------------\n// Flag parsing\n// ---------------------------------------------------------------------------\n\ninterface ParsedFlags {\n readonly workDir: string | undefined\n readonly promptPath: string | undefined\n readonly out: string | undefined\n}\n\nfunction parseFlags(argv: readonly string[]): ParsedFlags | null {\n let workDir: string | undefined\n let promptPath: string | undefined\n let out: string | undefined\n\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i]\n if (arg === '--work-dir' || arg === '--prompt-path' || arg === '--out') {\n const next = argv[i + 1]\n if (next === undefined || next.startsWith('--')) {\n console.error(`[integrate] ${arg} requires a value`)\n return null\n }\n if (arg === '--work-dir') {\n workDir = next\n } else if (arg === '--prompt-path') {\n promptPath = next\n } else {\n out = next\n }\n i++\n }\n }\n\n return {workDir, promptPath, out}\n}\n\n// ---------------------------------------------------------------------------\n// Artifact packaging\n// ---------------------------------------------------------------------------\n\n/**\n * Packages a clean merged source snapshot plus provenance.json into a single\n * tar artifact at outPath using atomic staging.\n *\n * Steps:\n * 1. Create a temp staging dir.\n * 2. Run `git archive --format=tar --output=<tmp>/source.tar <integrationCommit>` in workDir.\n * 3. Extract source.tar into <tmp>/tree, copy provenance.json into <tmp>/tree.\n * 4. Re-tar <tmp>/tree → <tmp>/artifact.tar.\n * 5. Ensure outPath parent dir exists, then atomically rename <tmp>/artifact.tar → outPath.\n * 6. Clean the temp dir in a finally block.\n *\n * ATOMIC: the rename only happens after the artifact is fully built. Any error\n * before the rename leaves outPath untouched.\n *\n * @param workDir - The integration work directory (contains the git repo + provenance.json).\n * @param integrationCommit - The commit SHA to archive (the frozen integration commit).\n * @param outPath - Destination path for the final artifact tar.\n */\nexport async function packageArtifact(workDir: string, integrationCommit: string, outPath: string): Promise<void> {\n // Belt-and-suspenders guard: fail loudly if the working tree has uncommitted tracked changes.\n // After FIX 1 commits the merge, tracked changes should always be committed.\n // Untracked files (e.g. provenance.json written by the harness) are intentionally excluded\n // from this check — they are copied into the artifact separately.\n // `git status --porcelain` lines starting with '??' are untracked; we only care about the rest.\n const statusOutput = execSync('git status --porcelain', {cwd: workDir, encoding: 'utf8'})\n const trackedDirtyLines = statusOutput.split('\\n').filter(line => line.length > 0 && !line.startsWith('??'))\n if (trackedDirtyLines.length > 0) {\n throw new Error(\n `[integrate] Working tree has uncommitted tracked changes before git archive — these would be excluded from the artifact:\\n${trackedDirtyLines.join('\\n')}`,\n )\n }\n\n const tmpStaging = mkdtempSync(path.join(os.tmpdir(), 'harness-artifact-'))\n try {\n const sourceTar = path.join(tmpStaging, 'source.tar')\n const treeDir = path.join(tmpStaging, 'tree')\n const artifactTar = path.join(tmpStaging, 'artifact.tar')\n\n // Step 2: Extract the clean merged source tree from the integration commit.\n execFileSync('git', ['archive', '--format=tar', `--output=${sourceTar}`, integrationCommit], {\n cwd: workDir,\n stdio: ['ignore', 'ignore', 'pipe'],\n })\n\n // Step 3a: Extract source.tar into tree dir.\n mkdirSync(treeDir, {recursive: true})\n execFileSync('tar', ['xf', sourceTar, '-C', treeDir], {\n stdio: ['ignore', 'ignore', 'pipe'],\n })\n\n // Step 3b: Copy provenance.json from workDir into the tree.\n copyFileSync(path.join(workDir, 'provenance.json'), path.join(treeDir, 'provenance.json'))\n\n // Step 4: Re-tar the tree (with provenance.json included) into artifact.tar.\n execFileSync('tar', ['cf', artifactTar, '-C', treeDir, '.'], {\n stdio: ['ignore', 'ignore', 'pipe'],\n })\n\n // Step 5: Ensure outPath parent exists, then atomically promote the artifact.\n mkdirSync(path.dirname(outPath), {recursive: true})\n renameSync(artifactTar, outPath)\n } finally {\n // Always clean the temp dir, even on error. Ignore cleanup failures.\n try {\n rmSync(tmpStaging, {recursive: true, force: true})\n } catch {\n // Intentionally swallowed — cleanup failure must not mask the real error.\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Main command\n// ---------------------------------------------------------------------------\n\n/**\n * Implements `harness integrate`.\n *\n * @param argv - CLI arguments (everything after \"integrate\").\n * @param configPath - Path to harness.config.json (defaults to package root; injectable for tests).\n * @param _packageArtifact - Injectable override for packageArtifact (for unit tests; defaults to the real impl).\n * @returns Exit code: 0 on success, 1 on failure.\n */\nexport async function cmdIntegrate(\n argv: readonly string[],\n configPath: string = DEFAULT_CONFIG_PATH,\n _packageArtifact: typeof packageArtifact = packageArtifact,\n): Promise<number> {\n // Parse flags.\n const flags = parseFlags(argv)\n if (flags === null) return 1\n\n // Validate required flags.\n if (flags.workDir === undefined) {\n console.error('[integrate] Missing required flag: --work-dir <dir>')\n return 1\n }\n if (flags.promptPath === undefined) {\n console.error('[integrate] Missing required flag: --prompt-path <path>')\n return 1\n }\n if (flags.out === undefined) {\n console.error('[integrate] Missing required flag: --out <path>')\n return 1\n }\n\n const workDir = flags.workDir\n const outPath = flags.out\n\n // Read harness.config.json.\n let rawConfig: unknown\n try {\n const raw = readFileSync(configPath, 'utf8')\n rawConfig = JSON.parse(raw)\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error)\n console.error(`[integrate] Failed to read config: ${msg}`)\n return 1\n }\n\n if (!isValidHarnessConfig(rawConfig)) {\n console.error('[integrate] Invalid harness.config.json shape')\n return 1\n }\n\n const config: IntegrationConfig = {\n baseVersion: rawConfig.base_version,\n releaseRepo: rawConfig.release_repo,\n integrationRefs: rawConfig.integrationRefs,\n agent: rawConfig.agent,\n model: rawConfig.model,\n opencodeBin: rawConfig.opencode_bin ?? 'opencode',\n workDir,\n promptPath: flags.promptPath,\n }\n\n // Run the integration and package the artifact.\n try {\n const result = await runIntegration(config, makeRealAdapters())\n if (result.ok === true) {\n await _packageArtifact(workDir, result.manifest.integrationCommit, outPath)\n return 0\n }\n console.error(`[integrate] ${result.error}`)\n return 1\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error)\n console.error(`[integrate] ${msg}`)\n return 1\n }\n}\n","/**\n * Provenance manifest for the harness binary.\n *\n * The manifest is the single source of truth written by the integration engine\n * and read by the CLI commands (info, patches, doctor).\n *\n * baseVersion — the upstream OpenCode release tag this binary is based on.\n * integrationRefs — ordered list of integration refs carried onto the base tag,\n * each with the resolved commit SHA and optional metadata.\n * integrationCommit — the frozen integration commit SHA produced by the LLM merge.\n * buildSha — the git SHA of the harness build, or 'dev' in the scaffold.\n */\nimport {readFileSync} from 'node:fs'\nimport path from 'node:path'\nimport {fileURLToPath} from 'node:url'\n\nexport interface IntegrationRefRecord {\n readonly ref: string\n readonly resolvedSha: string\n readonly reason?: string\n readonly upstreamStatus?: string\n}\n\nexport interface Provenance {\n readonly baseVersion: string\n readonly integrationRefs: readonly IntegrationRefRecord[]\n readonly integrationCommit: string | null\n readonly buildSha: string\n}\n\nconst packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')\n\n/**\n * Type guard: validates that an unknown value has the shape of a Provenance manifest.\n * Treats malformed JSON as an explicit error rather than silently returning partial data.\n */\nexport function isValidProvenance(value: unknown): value is Provenance {\n if (value === null || typeof value !== 'object') return false\n const v = value as Record<string, unknown>\n if (typeof v.baseVersion !== 'string' || v.baseVersion.length === 0) return false\n if (!Array.isArray(v.integrationRefs)) return false\n if (v.integrationCommit !== null && typeof v.integrationCommit !== 'string') return false\n if (typeof v.buildSha !== 'string') return false\n return true\n}\n\n/**\n * Type guard: validates that an unknown value has the shape of a harness.config.json.\n */\nfunction isValidHarnessConfig(value: unknown): value is {base_version?: string; integrationRefs?: string[]} {\n if (value === null || typeof value !== 'object') return false\n const v = value as Record<string, unknown>\n if (v.base_version !== undefined && typeof v.base_version !== 'string') return false\n if (v.integrationRefs !== undefined && !Array.isArray(v.integrationRefs)) return false\n return true\n}\n\n/**\n * Returns the provenance for the current harness binary.\n *\n * Resolution order:\n * 1. Bundled provenance.json (written by the integration engine at build time).\n * 2. harness.config.json (dev scaffold — shows configured refs without a frozen commit).\n * 3. Hardcoded dev placeholder (no config file present).\n *\n * The integration engine writes provenance.json at build time; this function reads\n * it at runtime, making the manifest available without additional filesystem reads\n * in production.\n */\nexport function getProvenance(): Provenance {\n // 1. Try bundled provenance.json (written by the integration engine).\n try {\n const manifestPath = path.join(packageRoot, 'provenance.json')\n const raw = readFileSync(manifestPath, 'utf8')\n const parsed: unknown = JSON.parse(raw)\n if (isValidProvenance(parsed)) {\n return parsed\n }\n // Malformed manifest — fall through to dev scaffold.\n } catch {\n // No bundled manifest — fall through.\n }\n\n // 2. Fall back to harness.config.json for the dev scaffold.\n try {\n const configPath = path.join(packageRoot, 'harness.config.json')\n const raw = readFileSync(configPath, 'utf8')\n const parsed: unknown = JSON.parse(raw)\n if (!isValidHarnessConfig(parsed)) {\n // Malformed config — fall through to hardcoded placeholder.\n throw new Error('Invalid harness.config.json shape')\n }\n const baseVersion = parsed.base_version ?? '1.15.13'\n const integrationRefs: IntegrationRefRecord[] = (parsed.integrationRefs ?? []).map(ref => ({\n ref,\n resolvedSha: 'dev',\n }))\n return {\n baseVersion,\n integrationRefs,\n integrationCommit: null,\n buildSha: 'dev',\n }\n } catch {\n // No config file — return hardcoded placeholder.\n }\n\n return {\n baseVersion: '1.15.13',\n integrationRefs: [],\n integrationCommit: null,\n buildSha: 'dev',\n }\n}\n\n/**\n * Formats provenance as a human-readable string for `harness info`.\n */\nexport function formatProvenance(p: Provenance): string {\n const lines: string[] = [\n `harness (patched OpenCode)`,\n ` base: ${p.baseVersion}`,\n ` integration commit: ${p.integrationCommit ?? '(unbuilt/dev scaffold)'}`,\n ` build sha: ${p.buildSha}`,\n ]\n if (p.integrationRefs.length > 0) {\n lines.push(` integration refs:`)\n for (const r of p.integrationRefs) {\n const meta = r.upstreamStatus === undefined ? '' : ` [${r.upstreamStatus}]`\n lines.push(` - ${r.ref}${meta}`)\n if (r.reason !== undefined) {\n lines.push(` reason: ${r.reason}`)\n }\n }\n } else {\n lines.push(` integration refs: (none — dev scaffold)`)\n }\n return lines.join('\\n')\n}\n","/**\n * Resolves the patched OpenCode binary for the current host.\n *\n * Resolution order (precedence, highest to lowest):\n * 0. OPENCODE_PATH env override — always honoured; marks isBuilt: false.\n * 1. Host-platform optionalDependencies binary (the real harness-built artifact).\n * Resolved via Node module resolution (createRequire) so pnpm/npm hoisting\n * is handled correctly — the platform package may be hoisted outside the\n * local node_modules tree.\n * 2. PATH fallback (`opencode` on PATH) — ONLY when an explicit dev escape hatch\n * is active: HARNESS_ALLOW_PATH_FALLBACK=1 or OPENCODE_PATH is set.\n * In published/production use (no escape hatch), a missing platform binary\n * is a hard error with an actionable message.\n *\n * The integrity check in step 1 is a basic executable-probe (--version succeeds).\n * A full cryptographic integrity check (npm provenance) is enforced by the\n * postinstall resolver at install time; this runtime check is a belt-and-suspenders\n * guard against a corrupted or missing binary.\n */\n\nimport {execFileSync} from 'node:child_process'\nimport {createRequire} from 'node:module'\nimport path from 'node:path'\nimport process from 'node:process'\nimport {binaryPathInPackage, getHostPlatformInfo} from './platform.js'\n\n/**\n * Result of binary resolution.\n *\n * resolved — true when a usable binary was found.\n * path — the resolved binary path or command name.\n * isBuilt — true when the binary is a real harness-built artifact.\n * false in the dev scaffold (falls back to opencode on PATH).\n */\nexport interface ResolvedBinary {\n readonly resolved: boolean\n readonly path: string\n readonly isBuilt: boolean\n}\n\n/**\n * Attempts to resolve the host-platform binary from the installed\n * @fro.bot/harness-<os>-<arch> optionalDependencies package.\n *\n * Uses Node module resolution (createRequire) to locate the package, which\n * correctly handles pnpm/npm hoisting — the platform package may be installed\n * outside the local node_modules tree.\n *\n * Returns the binary path if found and executable, or null otherwise.\n */\nfunction resolveOptionalDepBinary(): string | null {\n const platformResult = getHostPlatformInfo()\n if (!platformResult.ok) {\n // Unsupported platform — no platform binary available.\n return null\n }\n\n const info = platformResult.info\n\n // Resolve the platform package via Node module resolution.\n // This handles pnpm/npm hoisting correctly — the package may not be in\n // a local node_modules directory.\n const require = createRequire(import.meta.url)\n let platformPkgRoot: string\n try {\n const pkgJsonPath = require.resolve(`${info.packageName}/package.json`)\n platformPkgRoot = path.dirname(pkgJsonPath)\n } catch {\n // Platform package not installed (optional dependency absent).\n return null\n }\n\n const binaryPath = binaryPathInPackage(platformPkgRoot, info)\n\n // Basic executable probe — confirm the binary runs before returning it.\n try {\n execFileSync(binaryPath, ['--version'], {\n encoding: 'utf8',\n timeout: 10_000,\n stdio: ['ignore', 'pipe', 'pipe'],\n })\n return binaryPath\n } catch {\n return null\n }\n}\n\n/**\n * Returns true when an explicit dev escape hatch is active.\n *\n * The escape hatch allows PATH fallback in local/dev/unbuilt environments.\n * It is NEVER active in published/production use (no env set by default).\n *\n * Escape hatches:\n * - HARNESS_ALLOW_PATH_FALLBACK=1 — explicit opt-in for dev/CI without platform binary.\n * - OPENCODE_PATH set — explicit override already provided; PATH fallback is moot.\n */\nfunction isDevEscapeHatchActive(): boolean {\n return (\n process.env.HARNESS_ALLOW_PATH_FALLBACK === '1' ||\n (process.env.OPENCODE_PATH !== undefined && process.env.OPENCODE_PATH.length > 0)\n )\n}\n\n/**\n * Resolves the patched OpenCode binary for the current host.\n *\n * Resolution order:\n * 0. OPENCODE_PATH env override.\n * 1. Host-platform optionalDependencies binary (isBuilt: true).\n * 2. PATH fallback — ONLY when HARNESS_ALLOW_PATH_FALLBACK=1 (dev escape hatch).\n * In production (no escape hatch), missing platform binary → throws with remediation.\n *\n * @throws {Error} when no platform binary is found and no dev escape hatch is active.\n */\nexport function resolveBinary(): ResolvedBinary {\n // 0. Explicit override — always wins.\n const override = process.env.OPENCODE_PATH\n if (override !== undefined && override.length > 0) {\n return {resolved: true, path: override, isBuilt: false}\n }\n\n // 1. Host-platform optionalDependencies binary.\n const optionalBinary = resolveOptionalDepBinary()\n if (optionalBinary !== null) {\n return {resolved: true, path: optionalBinary, isBuilt: true}\n }\n\n // 2. No platform binary found.\n // In dev/unbuilt environments with an explicit escape hatch, fall back to PATH.\n // In production (no escape hatch), fail closed with an actionable error.\n if (isDevEscapeHatchActive()) {\n return {resolved: true, path: 'opencode', isBuilt: false}\n }\n\n // Determine which platform package was expected for the error message.\n const platformResult = getHostPlatformInfo()\n const expectedPkg = platformResult.ok ? platformResult.info.packageName : '@fro.bot/harness-<os>-<arch>'\n\n throw new Error(\n `[harness] Platform binary not found. Expected package: ${expectedPkg}\\n` +\n ` Remediation: ensure ${expectedPkg} is installed as an optionalDependency,\\n` +\n ` or set OPENCODE_PATH to an explicit binary path,\\n` +\n ` or set HARNESS_ALLOW_PATH_FALLBACK=1 to use opencode on PATH (dev only).`,\n )\n}\n\n/**\n * Checks whether the resolved binary is present and runnable by invoking it\n * with `--version`. Returns the version string on success, or null on failure.\n */\nexport function probeBinary(binaryPath: string): string | null {\n try {\n const output = execFileSync(binaryPath, ['--version'], {\n encoding: 'utf8',\n timeout: 10_000,\n stdio: ['ignore', 'pipe', 'pipe'],\n })\n return output.trim()\n } catch {\n return null\n }\n}\n","#!/usr/bin/env node\n/**\n * harness CLI — patched OpenCode binary with provenance/operability commands.\n *\n * Subcommand disambiguation:\n * Reserved harness subcommands: info, patches, doctor\n * --version / --help: harness-own (prints provenance / usage)\n * Everything else: passed through to the resolved patched binary.\n *\n * This is the ONLY entry point for the @fro.bot/harness package.\n * No classes; functions only; explicit boolean checks; no as-any.\n */\n\nimport {spawnSync} from 'node:child_process'\nimport process from 'node:process'\nimport {cmdIntegrate} from './integrate-command.js'\nimport {formatProvenance, getProvenance} from './provenance.js'\nimport {probeBinary, resolveBinary} from './resolve-binary.js'\n\nfunction printUsage(): void {\n console.log(`harness — patched OpenCode binary (Fro Bot integration)\n\nUsage:\n harness <opencode-args...> Pass through to the patched OpenCode binary\n harness info Print provenance (base version, integration refs, build sha)\n harness patches List configured integration refs\n harness doctor Check the resolved binary is present and runnable\n harness integrate Run the LLM merge integration pipeline\n --work-dir <dir> (required) Working directory for the clone\n --prompt-path <path> (required) Path to the merge prompt template\n --out <path> (required) Artifact output path\n harness --version Print harness provenance version\n harness --help Print this help\n\nReserved subcommands (info, patches, doctor, integrate) are handled by harness itself.\nAll other arguments are forwarded to the patched OpenCode binary.`)\n}\n\nfunction cmdInfo(): void {\n const p = getProvenance()\n console.log(formatProvenance(p))\n}\n\nfunction cmdPatches(): void {\n const p = getProvenance()\n if (p.integrationRefs.length === 0) {\n console.log('No integration refs configured (dev scaffold).')\n return\n }\n console.log('Integration refs:')\n for (const r of p.integrationRefs) {\n const status = r.upstreamStatus === undefined ? '' : ` [${r.upstreamStatus}]`\n console.log(` - ${r.ref}${status}`)\n if (r.reason !== undefined) {\n console.log(` reason: ${r.reason}`)\n }\n }\n if (p.integrationCommit !== null) {\n console.log(`\\nFrozen integration commit: ${p.integrationCommit}`)\n }\n}\n\nfunction cmdDoctor(): number {\n let binary\n try {\n binary = resolveBinary()\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error)\n console.error(`\\n[FAIL] ${msg}`)\n return 1\n }\n\n const p = getProvenance()\n\n console.log(`harness doctor`)\n console.log(` base version: ${p.baseVersion}`)\n console.log(` integration commit: ${p.integrationCommit ?? '(unbuilt/dev scaffold)'}`)\n console.log(` build sha: ${p.buildSha}`)\n console.log(` binary path: ${binary.path}`)\n console.log(` is built artifact: ${binary.isBuilt}`)\n\n // In production (isBuilt: false with no dev escape hatch), fail with remediation.\n if (!binary.isBuilt && process.env.HARNESS_ALLOW_PATH_FALLBACK !== '1' && process.env.OPENCODE_PATH === undefined) {\n console.error('\\n[FAIL] Binary is not a built harness artifact.')\n console.error(\n ' Install the platform package or set OPENCODE_PATH / HARNESS_ALLOW_PATH_FALLBACK=1 for dev use.',\n )\n return 1\n }\n\n const version = probeBinary(binary.path)\n if (version === null) {\n console.error(`\\n[FAIL] Binary not runnable: ${binary.path}`)\n console.error(' Ensure opencode is on PATH or set OPENCODE_PATH.')\n return 1\n }\n\n console.log(` binary version: ${version}`)\n\n // Verify binary version matches provenance baseVersion when we have a built artifact.\n if (binary.isBuilt && version !== p.baseVersion) {\n console.error(\n `\\n[FAIL] Binary version mismatch: binary reports '${version}', provenance expects '${p.baseVersion}'.`,\n )\n console.error(' Reinstall @fro.bot/harness or check the platform package version.')\n return 1\n }\n\n console.log('\\n[OK] Binary is present and runnable.')\n return 0\n}\n\nfunction cmdPassthrough(args: readonly string[]): number {\n let binary\n try {\n binary = resolveBinary()\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error)\n console.error(`[harness] ${msg}`)\n return 1\n }\n\n const result = spawnSync(binary.path, [...args], {\n stdio: 'inherit',\n env: process.env,\n })\n\n if (result.error !== undefined) {\n console.error(`[harness] Failed to spawn ${binary.path}: ${result.error.message}`)\n return 1\n }\n\n return result.status ?? 1\n}\n\nasync function main(): Promise<void> {\n const args = process.argv.slice(2)\n\n // --help: harness-own\n if (args[0] === '--help' || args[0] === '-h') {\n printUsage()\n process.exit(0)\n }\n\n // --version: harness-own provenance version\n if (args[0] === '--version' || args[0] === '-v') {\n const p = getProvenance()\n console.log(`@fro.bot/harness base:${p.baseVersion} build:${p.buildSha}`)\n process.exit(0)\n }\n\n const subcommand = args[0]\n\n if (subcommand === 'info') {\n cmdInfo()\n process.exit(0)\n }\n\n if (subcommand === 'patches') {\n cmdPatches()\n process.exit(0)\n }\n\n if (subcommand === 'doctor') {\n const code = cmdDoctor()\n process.exit(code)\n }\n\n if (subcommand === 'integrate') {\n const code = await cmdIntegrate(args.slice(1))\n process.exit(code)\n }\n\n // Anything not in the reserved set passes through.\n // This includes no-args (which opencode handles as its own help/default).\n const code = cmdPassthrough(args)\n process.exit(code)\n}\n\nmain().catch(error => {\n const msg = error instanceof Error ? error.message : String(error)\n console.error(`[harness] Unexpected error: ${msg}`)\n process.exit(1)\n})\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.mjs","names":["isValidHarnessConfig","packageRoot"],"sources":["../src/sources.ts","../src/integrate.ts","../src/integrate-command.ts","../src/provenance.ts","../src/resolve-binary.ts","../src/cli.ts"],"sourcesContent":["/**\n * Integration source resolution — maps each configured ref to git fetch refs.\n *\n * Ported from cortexkit/orw src/index.ts parseSource (MIT).\n * Adapted for CI/non-interactive use: no launchd, no desktop, no interactive prompts.\n *\n * Supported input forms:\n * - Local branch name (no https:// prefix) → refs/heads/<b>\n * - GitHub branch URL (https://github.com/owner/repo/tree/<branch>) → refs/heads/<branch>\n * - GitHub PR URL (https://github.com/owner/repo/pull/N) → refs/pull/N/head\n *\n * Throws on empty input or unsupported URL forms.\n */\n\nexport interface IntegrationSource {\n /** Human-readable label for log output and the merge prompt. */\n readonly label: string\n /** Git remote URL for the source repository. */\n readonly repo: string\n /** The ref to fetch from the remote (e.g. refs/pull/N/head, refs/heads/<b>). */\n readonly fetchRef: string\n /** The local remote-tracking ref to store the fetched ref under. */\n readonly fetch: string\n /** The ref to merge (same as fetch; kept separate for prompt rendering). */\n readonly merge: string\n}\n\n/**\n * Maps a single integration source input to a typed IntegrationSource.\n *\n * @param input - A PR URL, branch URL, or local branch name from config.\n * @param sourceRepo - The default source repo URL (used for local branch names).\n */\nexport function parseSource(input: string, sourceRepo: string): IntegrationSource {\n const value = input.trim()\n if (value.length === 0) throw new Error('Empty integration source in config branches')\n\n if (!value.startsWith('https://github.com/')) {\n // Local branch name — fetch from the source repo.\n return {\n label: value,\n repo: sourceRepo,\n fetchRef: `refs/heads/${value}`,\n fetch: `refs/remotes/watch/local/${value}`,\n merge: `refs/remotes/watch/local/${value}`,\n }\n }\n\n const url = new URL(value)\n const parts = url.pathname.split('/').filter(Boolean)\n const owner = parts[0]\n const repo = parts[1]\n if (owner === undefined || repo === undefined) throw new Error(`Unsupported GitHub source URL: ${value}`)\n\n if (parts.length >= 4 && parts[2] === 'tree') {\n const branch = decodeURIComponent(parts.slice(3).join('/'))\n const slug = watchSlug(owner, repo)\n const ref = `refs/remotes/watch/${slug}/${branch}`\n return {\n label: `${owner}/${repo}:${branch}`,\n repo: `https://github.com/${owner}/${repo}.git`,\n fetchRef: `refs/heads/${branch}`,\n fetch: ref,\n merge: ref,\n }\n }\n\n if (parts.length >= 4 && parts[2] === 'pull') {\n const number = parts[3] ?? ''\n if (!/^\\d+$/.test(number)) {\n throw new Error(`Unsupported GitHub pull request URL: ${value}`)\n }\n const slug = watchSlug(owner, repo)\n const ref = `refs/remotes/watch/${slug}/pr-${number}`\n return {\n label: `${owner}/${repo}#${number}`,\n repo: `https://github.com/${owner}/${repo}.git`,\n fetchRef: `refs/pull/${number}/head`,\n fetch: ref,\n merge: ref,\n }\n }\n\n throw new Error(`Unsupported GitHub integration source URL: ${value}`)\n}\n\n/**\n * Maps an array of integration source inputs to typed IntegrationSources.\n *\n * @param refs - Array of PR URLs, branch URLs, or local branch names.\n * @param sourceRepo - The default source repo URL (used for local branch names).\n */\nexport function resolveSources(refs: readonly string[], sourceRepo: string): IntegrationSource[] {\n return refs.map(input => parseSource(input, sourceRepo))\n}\n\nfunction watchSlug(owner: string, repo: string): string {\n return `${owner}-${repo}`.replaceAll(/[^\\w.-]/g, '-')\n}\n","/**\n * Integration engine — orw-embedded LLM merge onto the release tag.\n *\n * Ported from cortexkit/orw src/index.ts check/prep/render/verifyBuild (MIT).\n * Adapted for CI/non-interactive use: no launchd, no desktop, no interactive prompts.\n *\n * The actual opencode run LLM merge is NOT unit-tested here — it requires a live\n * opencode binary + model + network. Unit tests cover the fail-hard/freeze/provenance\n * contract via injected adapters (cloneRepo, fetchRef, runMerge, buildCli, verifyVersion).\n *\n * Fail-hard contract: any failure (merge unresolved, build fail, version mismatch)\n * returns {ok:false, error} and writes NO provenance manifest. The manifest is the\n * single source of truth — it is only written after all steps succeed (freeze).\n */\n\n// IntegrationRefRecord is the canonical type — defined once in provenance.ts.\nimport type {IntegrationRefRecord} from './provenance.js'\nimport type {IntegrationSource} from './sources.js'\nimport {execFile} from 'node:child_process'\nimport fs from 'node:fs/promises'\nimport path from 'node:path'\nimport process from 'node:process'\nimport {promisify} from 'node:util'\nimport {resolveSources} from './sources.js'\n\n// Re-export so callers that previously imported from integrate.ts still work.\nexport type {IntegrationRefRecord} from './provenance.js'\n\n// ---------------------------------------------------------------------------\n// Provenance manifest types\n// ---------------------------------------------------------------------------\n\nexport interface ProvenanceManifest {\n readonly baseVersion: string\n readonly integrationRefs: readonly IntegrationRefRecord[]\n readonly integrationCommit: string\n readonly buildSha: string\n}\n\n// ---------------------------------------------------------------------------\n// Integration config\n// ---------------------------------------------------------------------------\n\nexport interface IntegrationConfig {\n readonly baseVersion: string\n readonly releaseRepo: string\n readonly integrationRefs: readonly string[]\n readonly agent: string\n readonly model: string\n readonly opencodeBin: string\n readonly workDir: string\n readonly promptPath: string\n}\n\n// ---------------------------------------------------------------------------\n// Injectable adapters (dependency injection for testability)\n// ---------------------------------------------------------------------------\n\nexport interface IntegrationAdapters {\n /** Clone the release repo into workDir. */\n cloneRepo: (repoUrl: string, workDir: string) => Promise<void>\n /** Fetch tags from origin. */\n fetchTags: (workDir: string) => Promise<void>\n /** Fetch a single integration ref into a local tracking ref. */\n fetchRef: (workDir: string, remoteUrl: string, fetchRef: string, localRef: string) => Promise<void>\n /** Create/reset the integration branch to the release tag. */\n createBranch: (workDir: string, branch: string, tag: string) => Promise<void>\n /** Run the LLM merge via opencode run. */\n runMerge: (workDir: string, opencodeBin: string, agent: string, model: string, prompt: string) => Promise<void>\n /** Build the native CLI in the work repo. */\n buildCli: (workDir: string, version: string, channel: string) => Promise<void>\n /** Verify the built CLI --version matches the expected version. */\n verifyVersion: (workDir: string, expectedVersion: string) => Promise<void>\n /** Commit the integrated working tree (after LLM merge) so HEAD contains the merge. */\n commitIntegration: (workDir: string, message: string) => Promise<void>\n /** Get the current HEAD commit SHA of the work repo. */\n getCommitSha: (workDir: string) => Promise<string>\n}\n\n// ---------------------------------------------------------------------------\n// Integration result\n// ---------------------------------------------------------------------------\n\nexport type IntegrationResult =\n | {readonly ok: true; readonly manifest: ProvenanceManifest}\n | {readonly ok: false; readonly error: string}\n\n// ---------------------------------------------------------------------------\n// Provenance manifest I/O (single source of truth)\n// ---------------------------------------------------------------------------\n\nconst MANIFEST_FILENAME = 'provenance.json'\n\n/**\n * Writes the provenance manifest to the given directory.\n * This is the freeze step — called only after all integration steps succeed.\n */\nexport async function writeProvenanceManifest(dir: string, manifest: ProvenanceManifest): Promise<void> {\n await fs.mkdir(dir, {recursive: true})\n await fs.writeFile(path.join(dir, MANIFEST_FILENAME), `${JSON.stringify(manifest, null, 2)}\\n`, 'utf8')\n}\n\n/**\n * Type guard: validates that an unknown value has the shape of a ProvenanceManifest.\n * Treats malformed/partial JSON as invalid rather than silently returning partial data.\n */\nfunction isValidProvenanceManifest(value: unknown): value is ProvenanceManifest {\n if (value === null || typeof value !== 'object') return false\n const v = value as Record<string, unknown>\n if (typeof v.baseVersion !== 'string' || v.baseVersion.length === 0) return false\n if (!Array.isArray(v.integrationRefs)) return false\n if (typeof v.integrationCommit !== 'string' || v.integrationCommit.length === 0) return false\n if (typeof v.buildSha !== 'string') return false\n return true\n}\n\n/**\n * Reads the provenance manifest from the given directory.\n * Returns null if the manifest does not exist or has an invalid shape.\n * Uses isValidProvenanceManifest to guard against malformed/partial manifests.\n */\nexport async function readProvenanceManifest(dir: string): Promise<ProvenanceManifest | null> {\n const manifestPath = path.join(dir, MANIFEST_FILENAME)\n try {\n const raw = await fs.readFile(manifestPath, 'utf8')\n const parsed: unknown = JSON.parse(raw)\n if (!isValidProvenanceManifest(parsed)) {\n return null\n }\n return parsed\n } catch {\n return null\n }\n}\n\n// ---------------------------------------------------------------------------\n// Prompt rendering (adapted from orw render())\n// ---------------------------------------------------------------------------\n\nfunction integrationBranch(version: string): string {\n return `integrate/v${version}`\n}\n\nasync function renderPrompt(\n promptPath: string,\n workDir: string,\n baseVersion: string,\n releaseRepo: string,\n sources: IntegrationSource[],\n): Promise<string> {\n const tag = `v${baseVersion}`\n const branch = integrationBranch(baseVersion)\n const channel = 'latest'\n const tpl = await fs.readFile(promptPath, 'utf8')\n const vars: Record<string, string> = {\n repo: workDir,\n tag,\n version: baseVersion,\n channel,\n branches: sources.map(s => s.label).join(', '),\n branch,\n merges: sources.map(s => s.merge).join(', then '),\n sources: sources.map(s => `${s.label} -> ${s.merge}`).join('\\n- '),\n release_repo: releaseRepo,\n base: 'dev',\n release_url: `https://github.com/${releaseRepo}/releases/tag/${tag}`,\n }\n return Object.entries(vars).reduce((text, [key, value]) => text.replaceAll(`{{${key}}}`, value), tpl)\n}\n\nconst execFileAsync = promisify(execFile)\n\nasync function gitExec(args: string[], cwd?: string): Promise<string> {\n const {stdout} = await execFileAsync('git', args, {cwd, encoding: 'utf8'})\n return stdout.trim()\n}\n\nexport function makeRealAdapters(): IntegrationAdapters {\n return {\n cloneRepo: async (repoUrl, workDir) => {\n await fs.rm(workDir, {recursive: true, force: true})\n await fs.mkdir(path.dirname(workDir), {recursive: true})\n await gitExec(['clone', repoUrl, workDir])\n },\n\n fetchTags: async workDir => {\n await gitExec(['fetch', 'origin', '--tags'], workDir)\n },\n\n fetchRef: async (workDir, remoteUrl, fetchRef, localRef) => {\n await gitExec(['fetch', remoteUrl, `${fetchRef}:${localRef}`], workDir)\n },\n\n createBranch: async (workDir, branch, tag) => {\n // Reset or create the integration branch at the release tag.\n try {\n await gitExec(['checkout', '-B', branch, `refs/tags/${tag}`], workDir)\n } catch {\n await gitExec(['checkout', '-b', branch, `refs/tags/${tag}`], workDir)\n }\n },\n\n runMerge: async (workDir, opencodeBin, agent, model, prompt) => {\n // Run opencode run synchronously — do NOT use background:true.\n // Poll to terminal state; the non-interactive tool exits when done.\n await execFileAsync(opencodeBin, ['run', '--agent', agent, '--model', model, prompt], {\n cwd: workDir,\n encoding: 'utf8',\n timeout: 30 * 60 * 1000, // 30-minute hard timeout\n })\n },\n\n buildCli: async (workDir, version, channel) => {\n await execFileAsync('bun', ['run', 'build', '--', '--single'], {\n cwd: path.join(workDir, 'packages', 'opencode'),\n encoding: 'utf8',\n env: {\n ...process.env,\n OPENCODE_CHANNEL: channel,\n OPENCODE_VERSION: version,\n },\n timeout: 20 * 60 * 1000, // 20-minute hard timeout\n })\n },\n\n verifyVersion: async (workDir, expectedVersion) => {\n const cliPath = resolveCliPath(workDir)\n const {stdout} = await execFileAsync(cliPath, ['--version'], {\n encoding: 'utf8',\n timeout: 30_000,\n })\n const actual = stdout.trim()\n if (actual !== expectedVersion) {\n throw new Error(`Built CLI reported version ${actual}, expected ${expectedVersion}`)\n }\n },\n\n commitIntegration: async (workDir, message) => {\n // Stage all changes (new, modified, deleted) from the LLM merge.\n await gitExec(\n [\n '-c',\n 'user.name=fro-bot harness integrate',\n '-c',\n 'user.email=github-actions[bot]@users.noreply.github.com',\n 'add',\n '-A',\n ],\n workDir,\n )\n // Commit with --no-verify to skip any hooks in the cloned upstream repo.\n await gitExec(\n [\n '-c',\n 'user.name=fro-bot harness integrate',\n '-c',\n 'user.email=github-actions[bot]@users.noreply.github.com',\n 'commit',\n '--no-verify',\n '-m',\n message,\n ],\n workDir,\n )\n },\n\n getCommitSha: async workDir => {\n return gitExec(['rev-parse', 'HEAD'], workDir)\n },\n }\n}\n\nfunction resolveCliPath(workDir: string): string {\n const os = process.platform === 'win32' ? 'windows' : process.platform\n const arch = process.arch\n const name = `opencode-${os}-${arch}`\n const binary = process.platform === 'win32' ? 'opencode.exe' : 'opencode'\n return path.join(workDir, 'packages', 'opencode', 'dist', name, 'bin', binary)\n}\n\n// ---------------------------------------------------------------------------\n// Core integration orchestration\n// ---------------------------------------------------------------------------\n\n/**\n * Runs the full integration pipeline:\n * clone → fetch tags → fetch refs → create branch → LLM merge → build → verify → freeze\n *\n * On any failure: returns {ok:false, error} and writes NO manifest (fail-hard contract).\n * On success: writes the provenance manifest to workDir and returns {ok:true, manifest}.\n *\n * @param config - Integration configuration (base version, refs, model, etc.)\n * @param adapters - Injectable adapters for each step (real or stubbed for tests).\n */\nexport async function runIntegration(\n config: IntegrationConfig,\n adapters: IntegrationAdapters,\n): Promise<IntegrationResult> {\n const {baseVersion, releaseRepo, integrationRefs, agent, model, opencodeBin, workDir, promptPath} = config\n const tag = `v${baseVersion}`\n const branch = integrationBranch(baseVersion)\n const channel = 'latest'\n\n // Resolve sources — wrap in try/catch so invalid refs return {ok:false} instead of throwing.\n let sources: IntegrationSource[]\n try {\n sources = resolveSources(integrationRefs, `https://github.com/${releaseRepo}.git`)\n } catch (error) {\n return {ok: false, error: `Resolve sources failed: ${errorMessage(error)}`}\n }\n\n // Step 1: Clone the release repo.\n try {\n await adapters.cloneRepo(`https://github.com/${releaseRepo}.git`, workDir)\n } catch (error) {\n return {ok: false, error: `Clone failed: ${errorMessage(error)}`}\n }\n\n // Step 2: Fetch tags.\n try {\n await adapters.fetchTags(workDir)\n } catch (error) {\n return {ok: false, error: `Fetch tags failed: ${errorMessage(error)}`}\n }\n\n // Step 3: Fetch each integration ref.\n for (const source of sources) {\n try {\n await adapters.fetchRef(workDir, source.repo, source.fetchRef, source.fetch)\n } catch (error) {\n return {ok: false, error: `Fetch ref ${source.label} failed: ${errorMessage(error)}`}\n }\n }\n\n // Step 4: Create/reset the integration branch at the release tag.\n try {\n await adapters.createBranch(workDir, branch, tag)\n } catch (error) {\n return {ok: false, error: `Create branch ${branch} at ${tag} failed: ${errorMessage(error)}`}\n }\n\n // Step 5: Run the LLM merge (only when there are refs to merge).\n if (sources.length > 0) {\n let prompt: string\n try {\n prompt = await renderPrompt(promptPath, workDir, baseVersion, releaseRepo, sources)\n } catch (error) {\n return {ok: false, error: `Render merge prompt failed: ${errorMessage(error)}`}\n }\n\n try {\n await adapters.runMerge(workDir, opencodeBin, agent, model, prompt)\n } catch (error) {\n return {ok: false, error: `LLM merge failed: ${errorMessage(error)}`}\n }\n\n // Step 5.5: Commit the integrated working tree so HEAD contains the merge.\n // Without this, getCommitSha (Step 8) returns the bare tag SHA and\n // git archive would ship the pre-merge tree.\n try {\n await adapters.commitIntegration(workDir, `integrate: apply LLM merge onto v${baseVersion}`)\n } catch (error) {\n return {ok: false, error: `Commit integration failed: ${errorMessage(error)}`}\n }\n\n // Step 6: Build the native CLI.\n try {\n await adapters.buildCli(workDir, baseVersion, channel)\n } catch (error) {\n return {ok: false, error: `Build CLI failed: ${errorMessage(error)}`}\n }\n\n // Step 7: Verify --version matches the base.\n try {\n await adapters.verifyVersion(workDir, baseVersion)\n } catch (error) {\n return {ok: false, error: `Version verification failed: ${errorMessage(error)}`}\n }\n }\n\n // Step 8: Capture the frozen integration commit SHA.\n let integrationCommit: string\n try {\n integrationCommit = await adapters.getCommitSha(workDir)\n } catch (error) {\n return {ok: false, error: `Get commit SHA failed: ${errorMessage(error)}`}\n }\n\n // Step 9: Build the provenance manifest and freeze it.\n // Per-ref SHA resolution is tracked separately; all refs share the integration commit for now.\n const manifest: ProvenanceManifest = {\n baseVersion,\n integrationRefs: sources.map((s, i) => ({\n ref: integrationRefs[i] ?? s.label,\n resolvedSha: integrationCommit,\n })),\n integrationCommit,\n buildSha: 'dev', // replaced by the per-platform build job at publish time\n }\n\n try {\n await writeProvenanceManifest(workDir, manifest)\n } catch (error) {\n return {ok: false, error: `Write provenance manifest failed: ${errorMessage(error)}`}\n }\n\n return {ok: true, manifest}\n}\n\nfunction errorMessage(err: unknown): string {\n if (err instanceof Error) return err.message\n return String(err)\n}\n","/**\n * integrate-command.ts — `harness integrate` subcommand implementation.\n *\n * Reads harness.config.json for: baseVersion, releaseRepo, integrationRefs,\n * agent, model, opencodeBin. Parses --work-dir, --prompt-path, --out from argv.\n * Assembles IntegrationConfig and calls runIntegration(config, makeRealAdapters()).\n *\n * On {ok:true}: packages a clean merged source snapshot (via git archive) plus\n * provenance.json into a single artifact at --out using atomic staging.\n *\n * Exit codes: 0 on {ok:true} + artifact written, 1 on {ok:false} or exception.\n * Error output: one-line message only — no stack traces, no secrets.\n *\n * No classes; functions only; explicit boolean checks; no as-any.\n */\n\nimport type {IntegrationConfig} from './integrate.js'\nimport {execFileSync, execSync} from 'node:child_process'\nimport {copyFileSync, mkdirSync, mkdtempSync, readFileSync, renameSync, rmSync} from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\nimport {fileURLToPath} from 'node:url'\nimport {makeRealAdapters, runIntegration} from './integrate.js'\n\n// ---------------------------------------------------------------------------\n// Config file shape\n// ---------------------------------------------------------------------------\n\ninterface HarnessConfig {\n readonly release_repo: string\n readonly base_version: string\n readonly integrationRefs: readonly string[]\n readonly agent: string\n readonly model: string\n readonly opencode_bin?: string\n}\n\nfunction isValidHarnessConfig(value: unknown): value is HarnessConfig {\n if (value === null || typeof value !== 'object') return false\n const v = value as Record<string, unknown>\n if (typeof v.release_repo !== 'string' || v.release_repo.length === 0) return false\n if (typeof v.base_version !== 'string' || v.base_version.length === 0) return false\n if (!Array.isArray(v.integrationRefs)) return false\n if (!v.integrationRefs.every((el: unknown) => typeof el === 'string' && el.length > 0)) return false\n if (typeof v.agent !== 'string' || v.agent.length === 0) return false\n if (typeof v.model !== 'string' || v.model.length === 0) return false\n if (v.opencode_bin !== undefined && typeof v.opencode_bin !== 'string') return false\n return true\n}\n\n// ---------------------------------------------------------------------------\n// Default config path (relative to this file's package root)\n// ---------------------------------------------------------------------------\n\nconst packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')\nexport const DEFAULT_CONFIG_PATH = path.join(packageRoot, 'harness.config.json')\n\n// ---------------------------------------------------------------------------\n// Flag parsing\n// ---------------------------------------------------------------------------\n\ninterface ParsedFlags {\n readonly workDir: string | undefined\n readonly promptPath: string | undefined\n readonly out: string | undefined\n}\n\nfunction parseFlags(argv: readonly string[]): ParsedFlags | null {\n let workDir: string | undefined\n let promptPath: string | undefined\n let out: string | undefined\n\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i]\n if (arg === '--work-dir' || arg === '--prompt-path' || arg === '--out') {\n const next = argv[i + 1]\n if (next === undefined || next.startsWith('--')) {\n console.error(`[integrate] ${arg} requires a value`)\n return null\n }\n if (arg === '--work-dir') {\n workDir = next\n } else if (arg === '--prompt-path') {\n promptPath = next\n } else {\n out = next\n }\n i++\n }\n }\n\n return {workDir, promptPath, out}\n}\n\n// ---------------------------------------------------------------------------\n// Artifact packaging\n// ---------------------------------------------------------------------------\n\n/**\n * Packages a clean merged source snapshot plus provenance.json into a single\n * tar artifact at outPath using atomic staging.\n *\n * Steps:\n * 1. Create a temp staging dir.\n * 2. Run `git archive --format=tar --output=<tmp>/source.tar <integrationCommit>` in workDir.\n * 3. Extract source.tar into <tmp>/tree, copy provenance.json into <tmp>/tree.\n * 4. Re-tar <tmp>/tree → <tmp>/artifact.tar.\n * 5. Ensure outPath parent dir exists, then atomically rename <tmp>/artifact.tar → outPath.\n * 6. Clean the temp dir in a finally block.\n *\n * ATOMIC: the rename only happens after the artifact is fully built. Any error\n * before the rename leaves outPath untouched.\n *\n * @param workDir - The integration work directory (contains the git repo + provenance.json).\n * @param integrationCommit - The commit SHA to archive (the frozen integration commit).\n * @param outPath - Destination path for the final artifact tar.\n */\nexport async function packageArtifact(workDir: string, integrationCommit: string, outPath: string): Promise<void> {\n // Belt-and-suspenders guard: fail loudly if the working tree has uncommitted tracked changes.\n // After FIX 1 commits the merge, tracked changes should always be committed.\n // Untracked files (e.g. provenance.json written by the harness) are intentionally excluded\n // from this check — they are copied into the artifact separately.\n // `git status --porcelain` lines starting with '??' are untracked; we only care about the rest.\n const statusOutput = execSync('git status --porcelain', {cwd: workDir, encoding: 'utf8'})\n const trackedDirtyLines = statusOutput.split('\\n').filter(line => line.length > 0 && !line.startsWith('??'))\n if (trackedDirtyLines.length > 0) {\n throw new Error(\n `[integrate] Working tree has uncommitted tracked changes before git archive — these would be excluded from the artifact:\\n${trackedDirtyLines.join('\\n')}`,\n )\n }\n\n const tmpStaging = mkdtempSync(path.join(os.tmpdir(), 'harness-artifact-'))\n try {\n const sourceTar = path.join(tmpStaging, 'source.tar')\n const treeDir = path.join(tmpStaging, 'tree')\n const artifactTar = path.join(tmpStaging, 'artifact.tar')\n\n // Step 2: Extract the clean merged source tree from the integration commit.\n execFileSync('git', ['archive', '--format=tar', `--output=${sourceTar}`, integrationCommit], {\n cwd: workDir,\n stdio: ['ignore', 'ignore', 'pipe'],\n })\n\n // Step 3a: Extract source.tar into tree dir.\n mkdirSync(treeDir, {recursive: true})\n execFileSync('tar', ['xf', sourceTar, '-C', treeDir], {\n stdio: ['ignore', 'ignore', 'pipe'],\n })\n\n // Step 3b: Copy provenance.json from workDir into the tree.\n copyFileSync(path.join(workDir, 'provenance.json'), path.join(treeDir, 'provenance.json'))\n\n // Step 4: Re-tar the tree (with provenance.json included) into artifact.tar.\n execFileSync('tar', ['cf', artifactTar, '-C', treeDir, '.'], {\n stdio: ['ignore', 'ignore', 'pipe'],\n })\n\n // Step 5: Ensure outPath parent exists, then atomically promote the artifact.\n mkdirSync(path.dirname(outPath), {recursive: true})\n renameSync(artifactTar, outPath)\n } finally {\n // Always clean the temp dir, even on error. Ignore cleanup failures.\n try {\n rmSync(tmpStaging, {recursive: true, force: true})\n } catch {\n // Intentionally swallowed — cleanup failure must not mask the real error.\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Main command\n// ---------------------------------------------------------------------------\n\n/**\n * Implements `harness integrate`.\n *\n * @param argv - CLI arguments (everything after \"integrate\").\n * @param configPath - Path to harness.config.json (defaults to package root; injectable for tests).\n * @param _packageArtifact - Injectable override for packageArtifact (for unit tests; defaults to the real impl).\n * @returns Exit code: 0 on success, 1 on failure.\n */\nexport async function cmdIntegrate(\n argv: readonly string[],\n configPath: string = DEFAULT_CONFIG_PATH,\n _packageArtifact: typeof packageArtifact = packageArtifact,\n): Promise<number> {\n // Parse flags.\n const flags = parseFlags(argv)\n if (flags === null) return 1\n\n // Validate required flags.\n if (flags.workDir === undefined) {\n console.error('[integrate] Missing required flag: --work-dir <dir>')\n return 1\n }\n if (flags.promptPath === undefined) {\n console.error('[integrate] Missing required flag: --prompt-path <path>')\n return 1\n }\n if (flags.out === undefined) {\n console.error('[integrate] Missing required flag: --out <path>')\n return 1\n }\n\n const workDir = flags.workDir\n const outPath = flags.out\n\n // Read harness.config.json.\n let rawConfig: unknown\n try {\n const raw = readFileSync(configPath, 'utf8')\n rawConfig = JSON.parse(raw)\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error)\n console.error(`[integrate] Failed to read config: ${msg}`)\n return 1\n }\n\n if (!isValidHarnessConfig(rawConfig)) {\n console.error('[integrate] Invalid harness.config.json shape')\n return 1\n }\n\n const config: IntegrationConfig = {\n baseVersion: rawConfig.base_version,\n releaseRepo: rawConfig.release_repo,\n integrationRefs: rawConfig.integrationRefs,\n agent: rawConfig.agent,\n model: rawConfig.model,\n opencodeBin: rawConfig.opencode_bin ?? 'opencode',\n workDir,\n promptPath: flags.promptPath,\n }\n\n // Run the integration and package the artifact.\n try {\n const result = await runIntegration(config, makeRealAdapters())\n if (result.ok === true) {\n await _packageArtifact(workDir, result.manifest.integrationCommit, outPath)\n return 0\n }\n console.error(`[integrate] ${result.error}`)\n return 1\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error)\n console.error(`[integrate] ${msg}`)\n return 1\n }\n}\n","/**\n * Provenance manifest for the harness binary.\n *\n * The manifest is the single source of truth written by the integration engine\n * and read by the CLI commands (info, patches, doctor).\n *\n * baseVersion — the upstream OpenCode release tag this binary is based on.\n * integrationRefs — ordered list of integration refs carried onto the base tag,\n * each with the resolved commit SHA and optional metadata.\n * integrationCommit — the frozen integration commit SHA produced by the LLM merge.\n * buildSha — the git SHA of the harness build, or 'dev' in the scaffold.\n */\nimport {readFileSync} from 'node:fs'\nimport path from 'node:path'\nimport {fileURLToPath} from 'node:url'\n\nexport interface IntegrationRefRecord {\n readonly ref: string\n readonly resolvedSha: string\n readonly reason?: string\n readonly upstreamStatus?: string\n}\n\nexport interface Provenance {\n readonly baseVersion: string\n readonly integrationRefs: readonly IntegrationRefRecord[]\n readonly integrationCommit: string | null\n readonly buildSha: string\n}\n\nconst packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')\n\n/**\n * Type guard: validates that an unknown value has the shape of a Provenance manifest.\n * Treats malformed JSON as an explicit error rather than silently returning partial data.\n */\nexport function isValidProvenance(value: unknown): value is Provenance {\n if (value === null || typeof value !== 'object') return false\n const v = value as Record<string, unknown>\n if (typeof v.baseVersion !== 'string' || v.baseVersion.length === 0) return false\n if (!Array.isArray(v.integrationRefs)) return false\n if (v.integrationCommit !== null && typeof v.integrationCommit !== 'string') return false\n if (typeof v.buildSha !== 'string') return false\n return true\n}\n\n/**\n * Type guard: validates that an unknown value has the shape of a harness.config.json.\n */\nfunction isValidHarnessConfig(value: unknown): value is {base_version?: string; integrationRefs?: string[]} {\n if (value === null || typeof value !== 'object') return false\n const v = value as Record<string, unknown>\n if (v.base_version !== undefined && typeof v.base_version !== 'string') return false\n if (v.integrationRefs !== undefined && !Array.isArray(v.integrationRefs)) return false\n return true\n}\n\n/**\n * Returns the provenance for the current harness binary.\n *\n * Resolution order:\n * 1. Bundled provenance.json (written by the integration engine at build time).\n * 2. harness.config.json (dev scaffold — shows configured refs without a frozen commit).\n * 3. Hardcoded dev placeholder (no config file present).\n *\n * The integration engine writes provenance.json at build time; this function reads\n * it at runtime, making the manifest available without additional filesystem reads\n * in production.\n */\nexport function getProvenance(): Provenance {\n // 1. Try bundled provenance.json (written by the integration engine).\n try {\n const manifestPath = path.join(packageRoot, 'provenance.json')\n const raw = readFileSync(manifestPath, 'utf8')\n const parsed: unknown = JSON.parse(raw)\n if (isValidProvenance(parsed)) {\n return parsed\n }\n // Malformed manifest — fall through to dev scaffold.\n } catch {\n // No bundled manifest — fall through.\n }\n\n // 2. Fall back to harness.config.json for the dev scaffold.\n try {\n const configPath = path.join(packageRoot, 'harness.config.json')\n const raw = readFileSync(configPath, 'utf8')\n const parsed: unknown = JSON.parse(raw)\n if (!isValidHarnessConfig(parsed)) {\n // Malformed config — fall through to hardcoded placeholder.\n throw new Error('Invalid harness.config.json shape')\n }\n const baseVersion = parsed.base_version ?? '1.16.0'\n const integrationRefs: IntegrationRefRecord[] = (parsed.integrationRefs ?? []).map(ref => ({\n ref,\n resolvedSha: 'dev',\n }))\n return {\n baseVersion,\n integrationRefs,\n integrationCommit: null,\n buildSha: 'dev',\n }\n } catch {\n // No config file — return hardcoded placeholder.\n }\n\n return {\n baseVersion: '1.16.0',\n integrationRefs: [],\n integrationCommit: null,\n buildSha: 'dev',\n }\n}\n\n/**\n * Formats provenance as a human-readable string for `harness info`.\n */\nexport function formatProvenance(p: Provenance): string {\n const lines: string[] = [\n `harness (patched OpenCode)`,\n ` base: ${p.baseVersion}`,\n ` integration commit: ${p.integrationCommit ?? '(unbuilt/dev scaffold)'}`,\n ` build sha: ${p.buildSha}`,\n ]\n if (p.integrationRefs.length > 0) {\n lines.push(` integration refs:`)\n for (const r of p.integrationRefs) {\n const meta = r.upstreamStatus === undefined ? '' : ` [${r.upstreamStatus}]`\n lines.push(` - ${r.ref}${meta}`)\n if (r.reason !== undefined) {\n lines.push(` reason: ${r.reason}`)\n }\n }\n } else {\n lines.push(` integration refs: (none — dev scaffold)`)\n }\n return lines.join('\\n')\n}\n","/**\n * Resolves the patched OpenCode binary for the current host.\n *\n * Resolution order (precedence, highest to lowest):\n * 0. OPENCODE_PATH env override — always honoured; marks isBuilt: false.\n * 1. Host-platform optionalDependencies binary (the real harness-built artifact).\n * Resolved via Node module resolution (createRequire) so pnpm/npm hoisting\n * is handled correctly — the platform package may be hoisted outside the\n * local node_modules tree.\n * 2. PATH fallback (`opencode` on PATH) — ONLY when an explicit dev escape hatch\n * is active: HARNESS_ALLOW_PATH_FALLBACK=1 or OPENCODE_PATH is set.\n * In published/production use (no escape hatch), a missing platform binary\n * is a hard error with an actionable message.\n *\n * The integrity check in step 1 is a basic executable-probe (--version succeeds).\n * A full cryptographic integrity check (npm provenance) is enforced by the\n * postinstall resolver at install time; this runtime check is a belt-and-suspenders\n * guard against a corrupted or missing binary.\n */\n\nimport {execFileSync} from 'node:child_process'\nimport {createRequire} from 'node:module'\nimport path from 'node:path'\nimport process from 'node:process'\nimport {binaryPathInPackage, getHostPlatformInfo} from './platform.js'\n\n/**\n * Result of binary resolution.\n *\n * resolved — true when a usable binary was found.\n * path — the resolved binary path or command name.\n * isBuilt — true when the binary is a real harness-built artifact.\n * false in the dev scaffold (falls back to opencode on PATH).\n */\nexport interface ResolvedBinary {\n readonly resolved: boolean\n readonly path: string\n readonly isBuilt: boolean\n}\n\n/**\n * Attempts to resolve the host-platform binary from the installed\n * @fro.bot/harness-<os>-<arch> optionalDependencies package.\n *\n * Uses Node module resolution (createRequire) to locate the package, which\n * correctly handles pnpm/npm hoisting — the platform package may be installed\n * outside the local node_modules tree.\n *\n * Returns the binary path if found and executable, or null otherwise.\n */\nfunction resolveOptionalDepBinary(): string | null {\n const platformResult = getHostPlatformInfo()\n if (!platformResult.ok) {\n // Unsupported platform — no platform binary available.\n return null\n }\n\n const info = platformResult.info\n\n // Resolve the platform package via Node module resolution.\n // This handles pnpm/npm hoisting correctly — the package may not be in\n // a local node_modules directory.\n const require = createRequire(import.meta.url)\n let platformPkgRoot: string\n try {\n const pkgJsonPath = require.resolve(`${info.packageName}/package.json`)\n platformPkgRoot = path.dirname(pkgJsonPath)\n } catch {\n // Platform package not installed (optional dependency absent).\n return null\n }\n\n const binaryPath = binaryPathInPackage(platformPkgRoot, info)\n\n // Basic executable probe — confirm the binary runs before returning it.\n try {\n execFileSync(binaryPath, ['--version'], {\n encoding: 'utf8',\n timeout: 10_000,\n stdio: ['ignore', 'pipe', 'pipe'],\n })\n return binaryPath\n } catch {\n return null\n }\n}\n\n/**\n * Returns true when an explicit dev escape hatch is active.\n *\n * The escape hatch allows PATH fallback in local/dev/unbuilt environments.\n * It is NEVER active in published/production use (no env set by default).\n *\n * Escape hatches:\n * - HARNESS_ALLOW_PATH_FALLBACK=1 — explicit opt-in for dev/CI without platform binary.\n * - OPENCODE_PATH set — explicit override already provided; PATH fallback is moot.\n */\nfunction isDevEscapeHatchActive(): boolean {\n return (\n process.env.HARNESS_ALLOW_PATH_FALLBACK === '1' ||\n (process.env.OPENCODE_PATH !== undefined && process.env.OPENCODE_PATH.length > 0)\n )\n}\n\n/**\n * Resolves the patched OpenCode binary for the current host.\n *\n * Resolution order:\n * 0. OPENCODE_PATH env override.\n * 1. Host-platform optionalDependencies binary (isBuilt: true).\n * 2. PATH fallback — ONLY when HARNESS_ALLOW_PATH_FALLBACK=1 (dev escape hatch).\n * In production (no escape hatch), missing platform binary → throws with remediation.\n *\n * @throws {Error} when no platform binary is found and no dev escape hatch is active.\n */\nexport function resolveBinary(): ResolvedBinary {\n // 0. Explicit override — always wins.\n const override = process.env.OPENCODE_PATH\n if (override !== undefined && override.length > 0) {\n return {resolved: true, path: override, isBuilt: false}\n }\n\n // 1. Host-platform optionalDependencies binary.\n const optionalBinary = resolveOptionalDepBinary()\n if (optionalBinary !== null) {\n return {resolved: true, path: optionalBinary, isBuilt: true}\n }\n\n // 2. No platform binary found.\n // In dev/unbuilt environments with an explicit escape hatch, fall back to PATH.\n // In production (no escape hatch), fail closed with an actionable error.\n if (isDevEscapeHatchActive()) {\n return {resolved: true, path: 'opencode', isBuilt: false}\n }\n\n // Determine which platform package was expected for the error message.\n const platformResult = getHostPlatformInfo()\n const expectedPkg = platformResult.ok ? platformResult.info.packageName : '@fro.bot/harness-<os>-<arch>'\n\n throw new Error(\n `[harness] Platform binary not found. Expected package: ${expectedPkg}\\n` +\n ` Remediation: ensure ${expectedPkg} is installed as an optionalDependency,\\n` +\n ` or set OPENCODE_PATH to an explicit binary path,\\n` +\n ` or set HARNESS_ALLOW_PATH_FALLBACK=1 to use opencode on PATH (dev only).`,\n )\n}\n\n/**\n * Checks whether the resolved binary is present and runnable by invoking it\n * with `--version`. Returns the version string on success, or null on failure.\n */\nexport function probeBinary(binaryPath: string): string | null {\n try {\n const output = execFileSync(binaryPath, ['--version'], {\n encoding: 'utf8',\n timeout: 10_000,\n stdio: ['ignore', 'pipe', 'pipe'],\n })\n return output.trim()\n } catch {\n return null\n }\n}\n","#!/usr/bin/env node\n/**\n * harness CLI — patched OpenCode binary with provenance/operability commands.\n *\n * Subcommand disambiguation:\n * Reserved harness subcommands: info, patches, doctor\n * --version / --help: harness-own (prints provenance / usage)\n * Everything else: passed through to the resolved patched binary.\n *\n * This is the ONLY entry point for the @fro.bot/harness package.\n * No classes; functions only; explicit boolean checks; no as-any.\n */\n\nimport {spawnSync} from 'node:child_process'\nimport process from 'node:process'\nimport {cmdIntegrate} from './integrate-command.js'\nimport {formatProvenance, getProvenance} from './provenance.js'\nimport {probeBinary, resolveBinary} from './resolve-binary.js'\n\nfunction printUsage(): void {\n console.log(`harness — patched OpenCode binary (Fro Bot integration)\n\nUsage:\n harness <opencode-args...> Pass through to the patched OpenCode binary\n harness info Print provenance (base version, integration refs, build sha)\n harness patches List configured integration refs\n harness doctor Check the resolved binary is present and runnable\n harness integrate Run the LLM merge integration pipeline\n --work-dir <dir> (required) Working directory for the clone\n --prompt-path <path> (required) Path to the merge prompt template\n --out <path> (required) Artifact output path\n harness --version Print harness provenance version\n harness --help Print this help\n\nReserved subcommands (info, patches, doctor, integrate) are handled by harness itself.\nAll other arguments are forwarded to the patched OpenCode binary.`)\n}\n\nfunction cmdInfo(): void {\n const p = getProvenance()\n console.log(formatProvenance(p))\n}\n\nfunction cmdPatches(): void {\n const p = getProvenance()\n if (p.integrationRefs.length === 0) {\n console.log('No integration refs configured (dev scaffold).')\n return\n }\n console.log('Integration refs:')\n for (const r of p.integrationRefs) {\n const status = r.upstreamStatus === undefined ? '' : ` [${r.upstreamStatus}]`\n console.log(` - ${r.ref}${status}`)\n if (r.reason !== undefined) {\n console.log(` reason: ${r.reason}`)\n }\n }\n if (p.integrationCommit !== null) {\n console.log(`\\nFrozen integration commit: ${p.integrationCommit}`)\n }\n}\n\nfunction cmdDoctor(): number {\n let binary\n try {\n binary = resolveBinary()\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error)\n console.error(`\\n[FAIL] ${msg}`)\n return 1\n }\n\n const p = getProvenance()\n\n console.log(`harness doctor`)\n console.log(` base version: ${p.baseVersion}`)\n console.log(` integration commit: ${p.integrationCommit ?? '(unbuilt/dev scaffold)'}`)\n console.log(` build sha: ${p.buildSha}`)\n console.log(` binary path: ${binary.path}`)\n console.log(` is built artifact: ${binary.isBuilt}`)\n\n // In production (isBuilt: false with no dev escape hatch), fail with remediation.\n if (!binary.isBuilt && process.env.HARNESS_ALLOW_PATH_FALLBACK !== '1' && process.env.OPENCODE_PATH === undefined) {\n console.error('\\n[FAIL] Binary is not a built harness artifact.')\n console.error(\n ' Install the platform package or set OPENCODE_PATH / HARNESS_ALLOW_PATH_FALLBACK=1 for dev use.',\n )\n return 1\n }\n\n const version = probeBinary(binary.path)\n if (version === null) {\n console.error(`\\n[FAIL] Binary not runnable: ${binary.path}`)\n console.error(' Ensure opencode is on PATH or set OPENCODE_PATH.')\n return 1\n }\n\n console.log(` binary version: ${version}`)\n\n // Verify binary version matches provenance baseVersion when we have a built artifact.\n if (binary.isBuilt && version !== p.baseVersion) {\n console.error(\n `\\n[FAIL] Binary version mismatch: binary reports '${version}', provenance expects '${p.baseVersion}'.`,\n )\n console.error(' Reinstall @fro.bot/harness or check the platform package version.')\n return 1\n }\n\n console.log('\\n[OK] Binary is present and runnable.')\n return 0\n}\n\nfunction cmdPassthrough(args: readonly string[]): number {\n let binary\n try {\n binary = resolveBinary()\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error)\n console.error(`[harness] ${msg}`)\n return 1\n }\n\n const result = spawnSync(binary.path, [...args], {\n stdio: 'inherit',\n env: process.env,\n })\n\n if (result.error !== undefined) {\n console.error(`[harness] Failed to spawn ${binary.path}: ${result.error.message}`)\n return 1\n }\n\n return result.status ?? 1\n}\n\nasync function main(): Promise<void> {\n const args = process.argv.slice(2)\n\n // --help: harness-own\n if (args[0] === '--help' || args[0] === '-h') {\n printUsage()\n process.exit(0)\n }\n\n // --version: harness-own provenance version\n if (args[0] === '--version' || args[0] === '-v') {\n const p = getProvenance()\n console.log(`@fro.bot/harness base:${p.baseVersion} build:${p.buildSha}`)\n process.exit(0)\n }\n\n const subcommand = args[0]\n\n if (subcommand === 'info') {\n cmdInfo()\n process.exit(0)\n }\n\n if (subcommand === 'patches') {\n cmdPatches()\n process.exit(0)\n }\n\n if (subcommand === 'doctor') {\n const code = cmdDoctor()\n process.exit(code)\n }\n\n if (subcommand === 'integrate') {\n const code = await cmdIntegrate(args.slice(1))\n process.exit(code)\n }\n\n // Anything not in the reserved set passes through.\n // This includes no-args (which opencode handles as its own help/default).\n const code = cmdPassthrough(args)\n process.exit(code)\n}\n\nmain().catch(error => {\n const msg = error instanceof Error ? error.message : String(error)\n console.error(`[harness] Unexpected error: ${msg}`)\n process.exit(1)\n})\n"],"mappings":";;;;;;;;;;;;;;;;;;AAiCA,SAAgB,YAAY,OAAe,YAAuC;CAChF,MAAM,QAAQ,MAAM,KAAK;CACzB,IAAI,MAAM,WAAW,GAAG,MAAM,IAAI,MAAM,6CAA6C;CAErF,IAAI,CAAC,MAAM,WAAW,qBAAqB,GAEzC,OAAO;EACL,OAAO;EACP,MAAM;EACN,UAAU,cAAc;EACxB,OAAO,4BAA4B;EACnC,OAAO,4BAA4B;CACrC;CAIF,MAAM,QAAQ,IADE,IAAI,KACJ,EAAE,SAAS,MAAM,GAAG,EAAE,OAAO,OAAO;CACpD,MAAM,QAAQ,MAAM;CACpB,MAAM,OAAO,MAAM;CACnB,IAAI,UAAU,KAAA,KAAa,SAAS,KAAA,GAAW,MAAM,IAAI,MAAM,kCAAkC,OAAO;CAExG,IAAI,MAAM,UAAU,KAAK,MAAM,OAAO,QAAQ;EAC5C,MAAM,SAAS,mBAAmB,MAAM,MAAM,CAAC,EAAE,KAAK,GAAG,CAAC;EAE1D,MAAM,MAAM,sBADC,UAAU,OAAO,IACO,EAAE,GAAG;EAC1C,OAAO;GACL,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG;GAC3B,MAAM,sBAAsB,MAAM,GAAG,KAAK;GAC1C,UAAU,cAAc;GACxB,OAAO;GACP,OAAO;EACT;CACF;CAEA,IAAI,MAAM,UAAU,KAAK,MAAM,OAAO,QAAQ;EAC5C,MAAM,SAAS,MAAM,MAAM;EAC3B,IAAI,CAAC,QAAQ,KAAK,MAAM,GACtB,MAAM,IAAI,MAAM,wCAAwC,OAAO;EAGjE,MAAM,MAAM,sBADC,UAAU,OAAO,IACO,EAAE,MAAM;EAC7C,OAAO;GACL,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG;GAC3B,MAAM,sBAAsB,MAAM,GAAG,KAAK;GAC1C,UAAU,aAAa,OAAO;GAC9B,OAAO;GACP,OAAO;EACT;CACF;CAEA,MAAM,IAAI,MAAM,8CAA8C,OAAO;AACvE;;;;;;;AAQA,SAAgB,eAAe,MAAyB,YAAyC;CAC/F,OAAO,KAAK,KAAI,UAAS,YAAY,OAAO,UAAU,CAAC;AACzD;AAEA,SAAS,UAAU,OAAe,MAAsB;CACtD,OAAO,GAAG,MAAM,GAAG,OAAO,WAAW,YAAY,GAAG;AACtD;;;ACPA,MAAM,oBAAoB;;;;;AAM1B,eAAsB,wBAAwB,KAAa,UAA6C;CACtG,MAAM,GAAG,MAAM,KAAK,EAAC,WAAW,KAAI,CAAC;CACrC,MAAM,GAAG,UAAU,KAAK,KAAK,KAAK,iBAAiB,GAAG,GAAG,KAAK,UAAU,UAAU,MAAM,CAAC,EAAE,KAAK,MAAM;AACxG;AAuCA,SAAS,kBAAkB,SAAyB;CAClD,OAAO,cAAc;AACvB;AAEA,eAAe,aACb,YACA,SACA,aACA,aACA,SACiB;CACjB,MAAM,MAAM,IAAI;CAChB,MAAM,SAAS,kBAAkB,WAAW;CAC5C,MAAM,UAAU;CAChB,MAAM,MAAM,MAAM,GAAG,SAAS,YAAY,MAAM;CAChD,MAAM,OAA+B;EACnC,MAAM;EACN;EACA,SAAS;EACT;EACA,UAAU,QAAQ,KAAI,MAAK,EAAE,KAAK,EAAE,KAAK,IAAI;EAC7C;EACA,QAAQ,QAAQ,KAAI,MAAK,EAAE,KAAK,EAAE,KAAK,SAAS;EAChD,SAAS,QAAQ,KAAI,MAAK,GAAG,EAAE,MAAM,MAAM,EAAE,OAAO,EAAE,KAAK,MAAM;EACjE,cAAc;EACd,MAAM;EACN,aAAa,sBAAsB,YAAY,gBAAgB;CACjE;CACA,OAAO,OAAO,QAAQ,IAAI,EAAE,QAAQ,MAAM,CAAC,KAAK,WAAW,KAAK,WAAW,KAAK,IAAI,KAAK,KAAK,GAAG,GAAG;AACtG;AAEA,MAAM,gBAAgB,UAAU,QAAQ;AAExC,eAAe,QAAQ,MAAgB,KAA+B;CACpE,MAAM,EAAC,WAAU,MAAM,cAAc,OAAO,MAAM;EAAC;EAAK,UAAU;CAAM,CAAC;CACzE,OAAO,OAAO,KAAK;AACrB;AAEA,SAAgB,mBAAwC;CACtD,OAAO;EACL,WAAW,OAAO,SAAS,YAAY;GACrC,MAAM,GAAG,GAAG,SAAS;IAAC,WAAW;IAAM,OAAO;GAAI,CAAC;GACnD,MAAM,GAAG,MAAM,KAAK,QAAQ,OAAO,GAAG,EAAC,WAAW,KAAI,CAAC;GACvD,MAAM,QAAQ;IAAC;IAAS;IAAS;GAAO,CAAC;EAC3C;EAEA,WAAW,OAAM,YAAW;GAC1B,MAAM,QAAQ;IAAC;IAAS;IAAU;GAAQ,GAAG,OAAO;EACtD;EAEA,UAAU,OAAO,SAAS,WAAW,UAAU,aAAa;GAC1D,MAAM,QAAQ;IAAC;IAAS;IAAW,GAAG,SAAS,GAAG;GAAU,GAAG,OAAO;EACxE;EAEA,cAAc,OAAO,SAAS,QAAQ,QAAQ;GAE5C,IAAI;IACF,MAAM,QAAQ;KAAC;KAAY;KAAM;KAAQ,aAAa;IAAK,GAAG,OAAO;GACvE,QAAQ;IACN,MAAM,QAAQ;KAAC;KAAY;KAAM;KAAQ,aAAa;IAAK,GAAG,OAAO;GACvE;EACF;EAEA,UAAU,OAAO,SAAS,aAAa,OAAO,OAAO,WAAW;GAG9D,MAAM,cAAc,aAAa;IAAC;IAAO;IAAW;IAAO;IAAW;IAAO;GAAM,GAAG;IACpF,KAAK;IACL,UAAU;IACV,SAAS,OAAU;GACrB,CAAC;EACH;EAEA,UAAU,OAAO,SAAS,SAAS,YAAY;GAC7C,MAAM,cAAc,OAAO;IAAC;IAAO;IAAS;IAAM;GAAU,GAAG;IAC7D,KAAK,KAAK,KAAK,SAAS,YAAY,UAAU;IAC9C,UAAU;IACV,KAAK;KACH,GAAG,QAAQ;KACX,kBAAkB;KAClB,kBAAkB;IACpB;IACA,SAAS,OAAU;GACrB,CAAC;EACH;EAEA,eAAe,OAAO,SAAS,oBAAoB;GAEjD,MAAM,EAAC,WAAU,MAAM,cADP,eAAe,OACY,GAAG,CAAC,WAAW,GAAG;IAC3D,UAAU;IACV,SAAS;GACX,CAAC;GACD,MAAM,SAAS,OAAO,KAAK;GAC3B,IAAI,WAAW,iBACb,MAAM,IAAI,MAAM,8BAA8B,OAAO,aAAa,iBAAiB;EAEvF;EAEA,mBAAmB,OAAO,SAAS,YAAY;GAE7C,MAAM,QACJ;IACE;IACA;IACA;IACA;IACA;IACA;GACF,GACA,OACF;GAEA,MAAM,QACJ;IACE;IACA;IACA;IACA;IACA;IACA;IACA;IACA;GACF,GACA,OACF;EACF;EAEA,cAAc,OAAM,YAAW;GAC7B,OAAO,QAAQ,CAAC,aAAa,MAAM,GAAG,OAAO;EAC/C;CACF;AACF;AAEA,SAAS,eAAe,SAAyB;CAG/C,MAAM,OAAO,YAFF,QAAQ,aAAa,UAAU,YAAY,QAAQ,SAElC,GADf,QAAQ;CAErB,MAAM,SAAS,QAAQ,aAAa,UAAU,iBAAiB;CAC/D,OAAO,KAAK,KAAK,SAAS,YAAY,YAAY,QAAQ,MAAM,OAAO,MAAM;AAC/E;;;;;;;;;;;AAgBA,eAAsB,eACpB,QACA,UAC4B;CAC5B,MAAM,EAAC,aAAa,aAAa,iBAAiB,OAAO,OAAO,aAAa,SAAS,eAAc;CACpG,MAAM,MAAM,IAAI;CAChB,MAAM,SAAS,kBAAkB,WAAW;CAC5C,MAAM,UAAU;CAGhB,IAAI;CACJ,IAAI;EACF,UAAU,eAAe,iBAAiB,sBAAsB,YAAY,KAAK;CACnF,SAAS,OAAO;EACd,OAAO;GAAC,IAAI;GAAO,OAAO,2BAA2B,aAAa,KAAK;EAAG;CAC5E;CAGA,IAAI;EACF,MAAM,SAAS,UAAU,sBAAsB,YAAY,OAAO,OAAO;CAC3E,SAAS,OAAO;EACd,OAAO;GAAC,IAAI;GAAO,OAAO,iBAAiB,aAAa,KAAK;EAAG;CAClE;CAGA,IAAI;EACF,MAAM,SAAS,UAAU,OAAO;CAClC,SAAS,OAAO;EACd,OAAO;GAAC,IAAI;GAAO,OAAO,sBAAsB,aAAa,KAAK;EAAG;CACvE;CAGA,KAAK,MAAM,UAAU,SACnB,IAAI;EACF,MAAM,SAAS,SAAS,SAAS,OAAO,MAAM,OAAO,UAAU,OAAO,KAAK;CAC7E,SAAS,OAAO;EACd,OAAO;GAAC,IAAI;GAAO,OAAO,aAAa,OAAO,MAAM,WAAW,aAAa,KAAK;EAAG;CACtF;CAIF,IAAI;EACF,MAAM,SAAS,aAAa,SAAS,QAAQ,GAAG;CAClD,SAAS,OAAO;EACd,OAAO;GAAC,IAAI;GAAO,OAAO,iBAAiB,OAAO,MAAM,IAAI,WAAW,aAAa,KAAK;EAAG;CAC9F;CAGA,IAAI,QAAQ,SAAS,GAAG;EACtB,IAAI;EACJ,IAAI;GACF,SAAS,MAAM,aAAa,YAAY,SAAS,aAAa,aAAa,OAAO;EACpF,SAAS,OAAO;GACd,OAAO;IAAC,IAAI;IAAO,OAAO,+BAA+B,aAAa,KAAK;GAAG;EAChF;EAEA,IAAI;GACF,MAAM,SAAS,SAAS,SAAS,aAAa,OAAO,OAAO,MAAM;EACpE,SAAS,OAAO;GACd,OAAO;IAAC,IAAI;IAAO,OAAO,qBAAqB,aAAa,KAAK;GAAG;EACtE;EAKA,IAAI;GACF,MAAM,SAAS,kBAAkB,SAAS,oCAAoC,aAAa;EAC7F,SAAS,OAAO;GACd,OAAO;IAAC,IAAI;IAAO,OAAO,8BAA8B,aAAa,KAAK;GAAG;EAC/E;EAGA,IAAI;GACF,MAAM,SAAS,SAAS,SAAS,aAAa,OAAO;EACvD,SAAS,OAAO;GACd,OAAO;IAAC,IAAI;IAAO,OAAO,qBAAqB,aAAa,KAAK;GAAG;EACtE;EAGA,IAAI;GACF,MAAM,SAAS,cAAc,SAAS,WAAW;EACnD,SAAS,OAAO;GACd,OAAO;IAAC,IAAI;IAAO,OAAO,gCAAgC,aAAa,KAAK;GAAG;EACjF;CACF;CAGA,IAAI;CACJ,IAAI;EACF,oBAAoB,MAAM,SAAS,aAAa,OAAO;CACzD,SAAS,OAAO;EACd,OAAO;GAAC,IAAI;GAAO,OAAO,0BAA0B,aAAa,KAAK;EAAG;CAC3E;CAIA,MAAM,WAA+B;EACnC;EACA,iBAAiB,QAAQ,KAAK,GAAG,OAAO;GACtC,KAAK,gBAAgB,MAAM,EAAE;GAC7B,aAAa;EACf,EAAE;EACF;EACA,UAAU;CACZ;CAEA,IAAI;EACF,MAAM,wBAAwB,SAAS,QAAQ;CACjD,SAAS,OAAO;EACd,OAAO;GAAC,IAAI;GAAO,OAAO,qCAAqC,aAAa,KAAK;EAAG;CACtF;CAEA,OAAO;EAAC,IAAI;EAAM;CAAQ;AAC5B;AAEA,SAAS,aAAa,KAAsB;CAC1C,IAAI,eAAe,OAAO,OAAO,IAAI;CACrC,OAAO,OAAO,GAAG;AACnB;;;ACvXA,SAASA,uBAAqB,OAAwC;CACpE,IAAI,UAAU,QAAQ,OAAO,UAAU,UAAU,OAAO;CACxD,MAAM,IAAI;CACV,IAAI,OAAO,EAAE,iBAAiB,YAAY,EAAE,aAAa,WAAW,GAAG,OAAO;CAC9E,IAAI,OAAO,EAAE,iBAAiB,YAAY,EAAE,aAAa,WAAW,GAAG,OAAO;CAC9E,IAAI,CAAC,MAAM,QAAQ,EAAE,eAAe,GAAG,OAAO;CAC9C,IAAI,CAAC,EAAE,gBAAgB,OAAO,OAAgB,OAAO,OAAO,YAAY,GAAG,SAAS,CAAC,GAAG,OAAO;CAC/F,IAAI,OAAO,EAAE,UAAU,YAAY,EAAE,MAAM,WAAW,GAAG,OAAO;CAChE,IAAI,OAAO,EAAE,UAAU,YAAY,EAAE,MAAM,WAAW,GAAG,OAAO;CAChE,IAAI,EAAE,iBAAiB,KAAA,KAAa,OAAO,EAAE,iBAAiB,UAAU,OAAO;CAC/E,OAAO;AACT;AAMA,MAAMC,gBAAc,KAAK,QAAQ,KAAK,QAAQ,cAAc,OAAO,KAAK,GAAG,CAAC,GAAG,IAAI;AACnF,MAAa,sBAAsB,KAAK,KAAKA,eAAa,qBAAqB;AAY/E,SAAS,WAAW,MAA6C;CAC/D,IAAI;CACJ,IAAI;CACJ,IAAI;CAEJ,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;EACpC,MAAM,MAAM,KAAK;EACjB,IAAI,QAAQ,gBAAgB,QAAQ,mBAAmB,QAAQ,SAAS;GACtE,MAAM,OAAO,KAAK,IAAI;GACtB,IAAI,SAAS,KAAA,KAAa,KAAK,WAAW,IAAI,GAAG;IAC/C,QAAQ,MAAM,eAAe,IAAI,kBAAkB;IACnD,OAAO;GACT;GACA,IAAI,QAAQ,cACV,UAAU;QACL,IAAI,QAAQ,iBACjB,aAAa;QAEb,MAAM;GAER;EACF;CACF;CAEA,OAAO;EAAC;EAAS;EAAY;CAAG;AAClC;;;;;;;;;;;;;;;;;;;;AAyBA,eAAsB,gBAAgB,SAAiB,mBAA2B,SAAgC;CAOhH,MAAM,oBADe,SAAS,0BAA0B;EAAC,KAAK;EAAS,UAAU;CAAM,CAClD,EAAE,MAAM,IAAI,EAAE,QAAO,SAAQ,KAAK,SAAS,KAAK,CAAC,KAAK,WAAW,IAAI,CAAC;CAC3G,IAAI,kBAAkB,SAAS,GAC7B,MAAM,IAAI,MACR,6HAA6H,kBAAkB,KAAK,IAAI,GAC1J;CAGF,MAAM,aAAa,YAAY,KAAK,KAAK,GAAG,OAAO,GAAG,mBAAmB,CAAC;CAC1E,IAAI;EACF,MAAM,YAAY,KAAK,KAAK,YAAY,YAAY;EACpD,MAAM,UAAU,KAAK,KAAK,YAAY,MAAM;EAC5C,MAAM,cAAc,KAAK,KAAK,YAAY,cAAc;EAGxD,aAAa,OAAO;GAAC;GAAW;GAAgB,YAAY;GAAa;EAAiB,GAAG;GAC3F,KAAK;GACL,OAAO;IAAC;IAAU;IAAU;GAAM;EACpC,CAAC;EAGD,UAAU,SAAS,EAAC,WAAW,KAAI,CAAC;EACpC,aAAa,OAAO;GAAC;GAAM;GAAW;GAAM;EAAO,GAAG,EACpD,OAAO;GAAC;GAAU;GAAU;EAAM,EACpC,CAAC;EAGD,aAAa,KAAK,KAAK,SAAS,iBAAiB,GAAG,KAAK,KAAK,SAAS,iBAAiB,CAAC;EAGzF,aAAa,OAAO;GAAC;GAAM;GAAa;GAAM;GAAS;EAAG,GAAG,EAC3D,OAAO;GAAC;GAAU;GAAU;EAAM,EACpC,CAAC;EAGD,UAAU,KAAK,QAAQ,OAAO,GAAG,EAAC,WAAW,KAAI,CAAC;EAClD,WAAW,aAAa,OAAO;CACjC,UAAU;EAER,IAAI;GACF,OAAO,YAAY;IAAC,WAAW;IAAM,OAAO;GAAI,CAAC;EACnD,QAAQ,CAER;CACF;AACF;;;;;;;;;AAcA,eAAsB,aACpB,MACA,aAAqB,qBACrB,mBAA2C,iBAC1B;CAEjB,MAAM,QAAQ,WAAW,IAAI;CAC7B,IAAI,UAAU,MAAM,OAAO;CAG3B,IAAI,MAAM,YAAY,KAAA,GAAW;EAC/B,QAAQ,MAAM,qDAAqD;EACnE,OAAO;CACT;CACA,IAAI,MAAM,eAAe,KAAA,GAAW;EAClC,QAAQ,MAAM,yDAAyD;EACvE,OAAO;CACT;CACA,IAAI,MAAM,QAAQ,KAAA,GAAW;EAC3B,QAAQ,MAAM,iDAAiD;EAC/D,OAAO;CACT;CAEA,MAAM,UAAU,MAAM;CACtB,MAAM,UAAU,MAAM;CAGtB,IAAI;CACJ,IAAI;EACF,MAAM,MAAM,aAAa,YAAY,MAAM;EAC3C,YAAY,KAAK,MAAM,GAAG;CAC5B,SAAS,OAAO;EACd,MAAM,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;EACjE,QAAQ,MAAM,sCAAsC,KAAK;EACzD,OAAO;CACT;CAEA,IAAI,CAACD,uBAAqB,SAAS,GAAG;EACpC,QAAQ,MAAM,+CAA+C;EAC7D,OAAO;CACT;CAEA,MAAM,SAA4B;EAChC,aAAa,UAAU;EACvB,aAAa,UAAU;EACvB,iBAAiB,UAAU;EAC3B,OAAO,UAAU;EACjB,OAAO,UAAU;EACjB,aAAa,UAAU,gBAAgB;EACvC;EACA,YAAY,MAAM;CACpB;CAGA,IAAI;EACF,MAAM,SAAS,MAAM,eAAe,QAAQ,iBAAiB,CAAC;EAC9D,IAAI,OAAO,OAAO,MAAM;GACtB,MAAM,iBAAiB,SAAS,OAAO,SAAS,mBAAmB,OAAO;GAC1E,OAAO;EACT;EACA,QAAQ,MAAM,eAAe,OAAO,OAAO;EAC3C,OAAO;CACT,SAAS,OAAO;EACd,MAAM,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;EACjE,QAAQ,MAAM,eAAe,KAAK;EAClC,OAAO;CACT;AACF;;;;;;;;;;;;;;;AC3NA,MAAM,cAAc,KAAK,QAAQ,KAAK,QAAQ,cAAc,OAAO,KAAK,GAAG,CAAC,GAAG,IAAI;;;;;AAMnF,SAAgB,kBAAkB,OAAqC;CACrE,IAAI,UAAU,QAAQ,OAAO,UAAU,UAAU,OAAO;CACxD,MAAM,IAAI;CACV,IAAI,OAAO,EAAE,gBAAgB,YAAY,EAAE,YAAY,WAAW,GAAG,OAAO;CAC5E,IAAI,CAAC,MAAM,QAAQ,EAAE,eAAe,GAAG,OAAO;CAC9C,IAAI,EAAE,sBAAsB,QAAQ,OAAO,EAAE,sBAAsB,UAAU,OAAO;CACpF,IAAI,OAAO,EAAE,aAAa,UAAU,OAAO;CAC3C,OAAO;AACT;;;;AAKA,SAAS,qBAAqB,OAA8E;CAC1G,IAAI,UAAU,QAAQ,OAAO,UAAU,UAAU,OAAO;CACxD,MAAM,IAAI;CACV,IAAI,EAAE,iBAAiB,KAAA,KAAa,OAAO,EAAE,iBAAiB,UAAU,OAAO;CAC/E,IAAI,EAAE,oBAAoB,KAAA,KAAa,CAAC,MAAM,QAAQ,EAAE,eAAe,GAAG,OAAO;CACjF,OAAO;AACT;;;;;;;;;;;;;AAcA,SAAgB,gBAA4B;CAE1C,IAAI;EAEF,MAAM,MAAM,aADS,KAAK,KAAK,aAAa,iBACR,GAAG,MAAM;EAC7C,MAAM,SAAkB,KAAK,MAAM,GAAG;EACtC,IAAI,kBAAkB,MAAM,GAC1B,OAAO;CAGX,QAAQ,CAER;CAGA,IAAI;EAEF,MAAM,MAAM,aADO,KAAK,KAAK,aAAa,qBACR,GAAG,MAAM;EAC3C,MAAM,SAAkB,KAAK,MAAM,GAAG;EACtC,IAAI,CAAC,qBAAqB,MAAM,GAE9B,MAAM,IAAI,MAAM,mCAAmC;EAOrD,OAAO;GACL,aANkB,OAAO,gBAAgB;GAOzC,kBAN+C,OAAO,mBAAmB,CAAC,GAAG,KAAI,SAAQ;IACzF;IACA,aAAa;GACf,EAGgB;GACd,mBAAmB;GACnB,UAAU;EACZ;CACF,QAAQ,CAER;CAEA,OAAO;EACL,aAAa;EACb,iBAAiB,CAAC;EAClB,mBAAmB;EACnB,UAAU;CACZ;AACF;;;;AAKA,SAAgB,iBAAiB,GAAuB;CACtD,MAAM,QAAkB;EACtB;EACA,yBAAyB,EAAE;EAC3B,yBAAyB,EAAE,qBAAqB;EAChD,yBAAyB,EAAE;CAC7B;CACA,IAAI,EAAE,gBAAgB,SAAS,GAAG;EAChC,MAAM,KAAK,qBAAqB;EAChC,KAAK,MAAM,KAAK,EAAE,iBAAiB;GACjC,MAAM,OAAO,EAAE,mBAAmB,KAAA,IAAY,KAAK,KAAK,EAAE,eAAe;GACzE,MAAM,KAAK,SAAS,EAAE,MAAM,MAAM;GAClC,IAAI,EAAE,WAAW,KAAA,GACf,MAAM,KAAK,iBAAiB,EAAE,QAAQ;EAE1C;CACF,OACE,MAAM,KAAK,6CAA6C;CAE1D,OAAO,MAAM,KAAK,IAAI;AACxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACxFA,SAAS,2BAA0C;CACjD,MAAM,iBAAiB,oBAAoB;CAC3C,IAAI,CAAC,eAAe,IAElB,OAAO;CAGT,MAAM,OAAO,eAAe;CAK5B,MAAM,UAAU,cAAc,OAAO,KAAK,GAAG;CAC7C,IAAI;CACJ,IAAI;EACF,MAAM,cAAc,QAAQ,QAAQ,GAAG,KAAK,YAAY,cAAc;EACtE,kBAAkB,KAAK,QAAQ,WAAW;CAC5C,QAAQ;EAEN,OAAO;CACT;CAEA,MAAM,aAAa,oBAAoB,iBAAiB,IAAI;CAG5D,IAAI;EACF,aAAa,YAAY,CAAC,WAAW,GAAG;GACtC,UAAU;GACV,SAAS;GACT,OAAO;IAAC;IAAU;IAAQ;GAAM;EAClC,CAAC;EACD,OAAO;CACT,QAAQ;EACN,OAAO;CACT;AACF;;;;;;;;;;;AAYA,SAAS,yBAAkC;CACzC,OACE,QAAQ,IAAI,gCAAgC,OAC3C,QAAQ,IAAI,kBAAkB,KAAA,KAAa,QAAQ,IAAI,cAAc,SAAS;AAEnF;;;;;;;;;;;;AAaA,SAAgB,gBAAgC;CAE9C,MAAM,WAAW,QAAQ,IAAI;CAC7B,IAAI,aAAa,KAAA,KAAa,SAAS,SAAS,GAC9C,OAAO;EAAC,UAAU;EAAM,MAAM;EAAU,SAAS;CAAK;CAIxD,MAAM,iBAAiB,yBAAyB;CAChD,IAAI,mBAAmB,MACrB,OAAO;EAAC,UAAU;EAAM,MAAM;EAAgB,SAAS;CAAI;CAM7D,IAAI,uBAAuB,GACzB,OAAO;EAAC,UAAU;EAAM,MAAM;EAAY,SAAS;CAAK;CAI1D,MAAM,iBAAiB,oBAAoB;CAC3C,MAAM,cAAc,eAAe,KAAK,eAAe,KAAK,cAAc;CAE1E,MAAM,IAAI,MACR,0DAA0D,YAAY,0BAC3C,YAAY,wKAGzC;AACF;;;;;AAMA,SAAgB,YAAY,YAAmC;CAC7D,IAAI;EAMF,OALe,aAAa,YAAY,CAAC,WAAW,GAAG;GACrD,UAAU;GACV,SAAS;GACT,OAAO;IAAC;IAAU;IAAQ;GAAM;EAClC,CACY,EAAE,KAAK;CACrB,QAAQ;EACN,OAAO;CACT;AACF;;;;;;;;;;;;;;AC/IA,SAAS,aAAmB;CAC1B,QAAQ,IAAI;;;;;;;;;;;;;;;kEAeoD;AAClE;AAEA,SAAS,UAAgB;CACvB,MAAM,IAAI,cAAc;CACxB,QAAQ,IAAI,iBAAiB,CAAC,CAAC;AACjC;AAEA,SAAS,aAAmB;CAC1B,MAAM,IAAI,cAAc;CACxB,IAAI,EAAE,gBAAgB,WAAW,GAAG;EAClC,QAAQ,IAAI,gDAAgD;EAC5D;CACF;CACA,QAAQ,IAAI,mBAAmB;CAC/B,KAAK,MAAM,KAAK,EAAE,iBAAiB;EACjC,MAAM,SAAS,EAAE,mBAAmB,KAAA,IAAY,KAAK,KAAK,EAAE,eAAe;EAC3E,QAAQ,IAAI,OAAO,EAAE,MAAM,QAAQ;EACnC,IAAI,EAAE,WAAW,KAAA,GACf,QAAQ,IAAI,eAAe,EAAE,QAAQ;CAEzC;CACA,IAAI,EAAE,sBAAsB,MAC1B,QAAQ,IAAI,gCAAgC,EAAE,mBAAmB;AAErE;AAEA,SAAS,YAAoB;CAC3B,IAAI;CACJ,IAAI;EACF,SAAS,cAAc;CACzB,SAAS,OAAO;EACd,MAAM,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;EACjE,QAAQ,MAAM,YAAY,KAAK;EAC/B,OAAO;CACT;CAEA,MAAM,IAAI,cAAc;CAExB,QAAQ,IAAI,gBAAgB;CAC5B,QAAQ,IAAI,yBAAyB,EAAE,aAAa;CACpD,QAAQ,IAAI,yBAAyB,EAAE,qBAAqB,0BAA0B;CACtF,QAAQ,IAAI,yBAAyB,EAAE,UAAU;CACjD,QAAQ,IAAI,yBAAyB,OAAO,MAAM;CAClD,QAAQ,IAAI,yBAAyB,OAAO,SAAS;CAGrD,IAAI,CAAC,OAAO,WAAW,QAAQ,IAAI,gCAAgC,OAAO,QAAQ,IAAI,kBAAkB,KAAA,GAAW;EACjH,QAAQ,MAAM,kDAAkD;EAChE,QAAQ,MACN,uGACF;EACA,OAAO;CACT;CAEA,MAAM,UAAU,YAAY,OAAO,IAAI;CACvC,IAAI,YAAY,MAAM;EACpB,QAAQ,MAAM,iCAAiC,OAAO,MAAM;EAC5D,QAAQ,MAAM,yDAAyD;EACvE,OAAO;CACT;CAEA,QAAQ,IAAI,yBAAyB,SAAS;CAG9C,IAAI,OAAO,WAAW,YAAY,EAAE,aAAa;EAC/C,QAAQ,MACN,qDAAqD,QAAQ,yBAAyB,EAAE,YAAY,GACtG;EACA,QAAQ,MAAM,0EAA0E;EACxF,OAAO;CACT;CAEA,QAAQ,IAAI,wCAAwC;CACpD,OAAO;AACT;AAEA,SAAS,eAAe,MAAiC;CACvD,IAAI;CACJ,IAAI;EACF,SAAS,cAAc;CACzB,SAAS,OAAO;EACd,MAAM,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;EACjE,QAAQ,MAAM,aAAa,KAAK;EAChC,OAAO;CACT;CAEA,MAAM,SAAS,UAAU,OAAO,MAAM,CAAC,GAAG,IAAI,GAAG;EAC/C,OAAO;EACP,KAAK,QAAQ;CACf,CAAC;CAED,IAAI,OAAO,UAAU,KAAA,GAAW;EAC9B,QAAQ,MAAM,6BAA6B,OAAO,KAAK,IAAI,OAAO,MAAM,SAAS;EACjF,OAAO;CACT;CAEA,OAAO,OAAO,UAAU;AAC1B;AAEA,eAAe,OAAsB;CACnC,MAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;CAGjC,IAAI,KAAK,OAAO,YAAY,KAAK,OAAO,MAAM;EAC5C,WAAW;EACX,QAAQ,KAAK,CAAC;CAChB;CAGA,IAAI,KAAK,OAAO,eAAe,KAAK,OAAO,MAAM;EAC/C,MAAM,IAAI,cAAc;EACxB,QAAQ,IAAI,yBAAyB,EAAE,YAAY,SAAS,EAAE,UAAU;EACxE,QAAQ,KAAK,CAAC;CAChB;CAEA,MAAM,aAAa,KAAK;CAExB,IAAI,eAAe,QAAQ;EACzB,QAAQ;EACR,QAAQ,KAAK,CAAC;CAChB;CAEA,IAAI,eAAe,WAAW;EAC5B,WAAW;EACX,QAAQ,KAAK,CAAC;CAChB;CAEA,IAAI,eAAe,UAAU;EAC3B,MAAM,OAAO,UAAU;EACvB,QAAQ,KAAK,IAAI;CACnB;CAEA,IAAI,eAAe,aAAa;EAC9B,MAAM,OAAO,MAAM,aAAa,KAAK,MAAM,CAAC,CAAC;EAC7C,QAAQ,KAAK,IAAI;CACnB;CAIA,MAAM,OAAO,eAAe,IAAI;CAChC,QAAQ,KAAK,IAAI;AACnB;AAEA,KAAK,EAAE,OAAM,UAAS;CACpB,MAAM,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;CACjE,QAAQ,MAAM,+BAA+B,KAAK;CAClD,QAAQ,KAAK,CAAC;AAChB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fro.bot/harness",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.16.0",
|
|
4
4
|
"description": "Published patched-OpenCode binary with orw-embedded LLM-merge integration — the default OpenCode for Fro Bot",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"opencode",
|
|
@@ -39,9 +39,9 @@
|
|
|
39
39
|
"access": "public"
|
|
40
40
|
},
|
|
41
41
|
"optionalDependencies": {
|
|
42
|
-
"@fro.bot/harness-linux-x64": "1.
|
|
43
|
-
"@fro.bot/harness-linux-arm64": "1.
|
|
44
|
-
"@fro.bot/harness-darwin-x64": "1.
|
|
45
|
-
"@fro.bot/harness-darwin-arm64": "1.
|
|
42
|
+
"@fro.bot/harness-linux-x64": "1.16.0",
|
|
43
|
+
"@fro.bot/harness-linux-arm64": "1.16.0",
|
|
44
|
+
"@fro.bot/harness-darwin-x64": "1.16.0",
|
|
45
|
+
"@fro.bot/harness-darwin-arm64": "1.16.0"
|
|
46
46
|
}
|
|
47
47
|
}
|
package/provenance.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"baseVersion": "1.
|
|
3
|
-
"
|
|
4
|
-
"
|
|
2
|
+
"baseVersion": "1.16.0",
|
|
3
|
+
"integrationRefs": [],
|
|
4
|
+
"integrationCommit": "6cb74317a6efacd656483cb0489d8e7e3701c12e",
|
|
5
|
+
"buildSha": "d36a21ccc4417a15be016b660cfe7cd47fdf1dd2"
|
|
5
6
|
}
|