apphx 1.1.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +50 -182
- package/benchmarks/peer-context-worker.mjs +186 -0
- package/benchmarks/peer-context.mjs +150 -0
- package/dist/apple-types.js.map +1 -1
- package/dist/cli.js +370 -118
- package/dist/cli.js.map +1 -1
- package/dist/config.js +42 -4
- package/dist/config.js.map +1 -1
- package/dist/dependencies.js +455 -16
- package/dist/dependencies.js.map +1 -1
- package/dist/export-options.js +44 -2
- package/dist/export-options.js.map +1 -1
- package/dist/flutter.js +13 -25
- package/dist/flutter.js.map +1 -1
- package/dist/go-dependencies.js +389 -0
- package/dist/go-dependencies.js.map +1 -0
- package/dist/inbox.js +7 -8
- package/dist/inbox.js.map +1 -1
- package/dist/integrations.js +3 -3
- package/dist/isolation.js +190 -0
- package/dist/isolation.js.map +1 -0
- package/dist/macos.js +57 -0
- package/dist/macos.js.map +1 -0
- package/dist/mygo-build.js +55 -0
- package/dist/mygo-build.js.map +1 -0
- package/dist/policy.js +35 -0
- package/dist/policy.js.map +1 -0
- package/dist/preflight.js +1 -1
- package/dist/process.js +3 -3
- package/dist/project-profiles.js +163 -0
- package/dist/project-profiles.js.map +1 -0
- package/dist/proof.js +33 -0
- package/dist/proof.js.map +1 -0
- package/dist/remote.js +1 -1
- package/dist/runner.js +269 -287
- package/dist/runner.js.map +1 -1
- package/dist/scheduler.js +0 -3
- package/dist/scheduler.js.map +1 -1
- package/dist/schemas.js +156 -44
- package/dist/schemas.js.map +1 -1
- package/dist/store.js +166 -44
- package/dist/store.js.map +1 -1
- package/dist/vendor/obfuscator/dist/cli.js +72 -0
- package/dist/vendor/obfuscator/dist/cli.js.map +1 -0
- package/dist/vendor/obfuscator/dist/code.js +585 -0
- package/dist/vendor/obfuscator/dist/code.js.map +1 -0
- package/dist/vendor/obfuscator/dist/common.js +262 -0
- package/dist/vendor/obfuscator/dist/common.js.map +1 -0
- package/dist/vendor/obfuscator/dist/config.js +123 -0
- package/dist/vendor/obfuscator/dist/config.js.map +1 -0
- package/dist/vendor/obfuscator/dist/content.js +89 -0
- package/dist/vendor/obfuscator/dist/content.js.map +1 -0
- package/dist/vendor/obfuscator/dist/obfuscate.js +93 -0
- package/dist/vendor/obfuscator/dist/obfuscate.js.map +1 -0
- package/dist/vendor/obfuscator/dist/png.js +283 -0
- package/dist/vendor/obfuscator/dist/png.js.map +1 -0
- package/dist/vendor/obfuscator/dist/project.js +159 -0
- package/dist/vendor/obfuscator/dist/project.js.map +1 -0
- package/dist/vendor/obfuscator/dist/resources.js +335 -0
- package/dist/vendor/obfuscator/dist/resources.js.map +1 -0
- package/dist/vendor/obfuscator/package.json +22 -0
- package/dist/workspace.js +113 -0
- package/dist/workspace.js.map +1 -0
- package/evals/control.mjs +73 -0
- package/evals/expectations.mjs +37 -0
- package/evals/host.mjs +51 -0
- package/evals/oracle.mjs +80 -0
- package/evals/policy.mjs +268 -0
- package/examples/android-java.factory.json +18 -0
- package/examples/android-java.json +16 -0
- package/examples/existing-project.factory.json +18 -0
- package/examples/existing-project.json +17 -0
- package/examples/expo.eas.json +17 -0
- package/examples/expo.factory.json +18 -0
- package/examples/expo.json +16 -0
- package/examples/factory.json +0 -2
- package/examples/flutter.factory.json +13 -0
- package/examples/flutter.json +16 -0
- package/examples/luggage.json +5 -3
- package/examples/mygo-web.factory.json +18 -0
- package/examples/mygo-web.json +16 -0
- package/examples/mygo.factory.json +18 -0
- package/examples/mygo.json +16 -0
- package/examples/react-native.factory.json +18 -0
- package/examples/react-native.json +16 -0
- package/examples/runtime/android-java/app/build.gradle +7 -0
- package/examples/runtime/android-java/app/src/main/AndroidManifest.xml +8 -0
- package/examples/runtime/android-java/app/src/main/java/dev/apphx/runtime/MainActivity.java +44 -0
- package/examples/runtime/android-java/sdk-build.mjs +29 -0
- package/examples/runtime/android-java/settings.gradle +2 -0
- package/examples/runtime/android-ui.mjs +70 -0
- package/examples/runtime/mygo-native/go.mod +13 -0
- package/examples/runtime/mygo-native/go.sum +10 -0
- package/examples/runtime/mygo-native/main.go +173 -0
- package/examples/runtime/mygo-native/main_test.go +14 -0
- package/examples/runtime/mygo-native/mygo.json +1 -0
- package/examples/runtime/mygo-web/bun.lock +15 -0
- package/examples/runtime/mygo-web/go.mod +9 -0
- package/examples/runtime/mygo-web/go.sum +8 -0
- package/examples/runtime/mygo-web/index.html +1 -0
- package/examples/runtime/mygo-web/main.go +60 -0
- package/examples/runtime/mygo-web/mygo.config.ts +10 -0
- package/examples/runtime/mygo-web/package.json +1 -0
- package/examples/runtime/mygo-web/src/main.ts +23 -0
- package/examples/runtime/mygo-web/src/mygo.ts +14 -0
- package/examples/swift.factory.json +18 -0
- package/examples/swift.json +16 -0
- package/examples/uni-app.factory.json +18 -0
- package/examples/uni-app.json +16 -0
- package/package.json +12 -5
- package/scripts/bundle-obfuscator.mjs +19 -0
- package/scripts/runtime-smoke.mjs +209 -0
- package/skills/apphx/SKILL.md +94 -17
- package/skills/apphx/resources/google-play-research-result.json +6 -0
- package/skills/apphx/resources/local-research-result.json +6 -0
- package/skills/apphx/resources/requirement.json +5 -8
- package/skills/apphx/resources/research-result.json +5 -14
- package/skills/apphx/resources/review-result.json +1 -1
- package/dist/apple.js +0 -900
- package/dist/apple.js.map +0 -1
package/dist/runner.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.js","names":[],"sources":["../src/runner.ts"],"sourcesContent":["import { mkdirSync, readFileSync, readdirSync, lstatSync, rmSync, cpSync, existsSync, mkdtempSync, renameSync, constants } from 'node:fs';\nimport { join, relative, delimiter } from 'node:path';\nimport { createHash, randomUUID } from 'node:crypto';\nimport { run, executionEnvironment, processGroupAlive } from './process.js';\nimport { shipApple, pollApple } from './apple.js';\nimport { inside, expandArgv } from './config.js';\nimport { checkPrerequisites } from './preflight.js';\nimport { flutterEnvironment, prepareFlutter } from './flutter.js';\nimport { prepareExportOptions } from './export-options.js';\nimport { GENERATED_PATHS, dependencyDigest, isGeneratedPath, validateLocalDependencies } from './dependencies.js';\nimport { ResearchSchema, ReviewSchema, toError } from './schemas.js';\nimport type { Job, HostStage, Stage } from './schemas.js';\nimport type { Run, RunOptions } from './process.js';\nimport type { Store } from './store.js';\n\nconst REQUIRED_POLICY_RULES = ['2.1', '2.3.1', '2.5.19', '4.2', '4.2.6', '4.3', '5.1.1'];\n\nexport function sourceDigest(root: string, omitGenerated = true): string {\n if (lstatSync(root).isSymbolicLink()) throw new Error('A source or screenshot root cannot be a symlink');\n if (omitGenerated) {\n for (const path of GENERATED_PATHS) inside(root, path);\n validateLocalDependencies(root);\n }\n const hash = createHash('sha256');\n function visit(directory: string): void {\n for (const entry of readdirSync(directory).sort()) {\n const path = join(directory, entry);\n if (omitGenerated && isGeneratedPath(relative(root, path))) continue;\n const stat = lstatSync(path);\n if (stat.isSymbolicLink()) throw new Error(`Source symlink is not permitted: ${relative(root, path)}`);\n if (stat.isDirectory()) visit(path);\n else if (stat.isFile()) hash.update(relative(root, path)).update('\\0').update(`${stat.size}:${stat.mode & 0o777}\\0`).update(readFileSync(path));\n }\n }\n visit(root);\n return hash.digest('hex');\n}\n\nfunction requireDependencyProof(job: Job): void {\n if (!job.verifiedDependencyDigest) throw Object.assign(new Error('Dependency resolution proof is missing; retry this stopped task to re-run verification'), { code: 'SETUP_REQUIRED' });\n if (dependencyDigest(job.workspace) !== job.verifiedDependencyDigest) throw Object.assign(new Error('Dependency resolution changed since verification; re-verification is required'), { code: 'EVIDENCE_CHANGED' });\n}\n\nexport function parseVerdict(text: string): unknown {\n const content = text.trim().replace(/^```(?:json)?\\s*\\n?/, '').replace(/\\n?```$/, '');\n try { return JSON.parse(content); }\n catch { throw new Error('Host did not return a JSON verdict; no approval was inferred from text or an exit code'); }\n}\n\nexport function parseResearch(text: string) {\n const research = ResearchSchema.parse(parseVerdict(text));\n const cited = new Set();\n for (const source of Array.isArray(research?.policySources) ? research.policySources : []) {\n if (typeof source?.url !== 'string') continue;\n try {\n const url = new URL(source.url);\n if (url.protocol === 'https:' && url.hostname === 'developer.apple.com') cited.add(source.rule);\n } catch {}\n }\n if (typeof research?.viable !== 'boolean' || !REQUIRED_POLICY_RULES.every(rule => cited.has(rule)) || typeof research.distinctness !== 'string' || !research.distinctness.trim() || !Array.isArray(research.plan) || !research.plan.length || research.plan.some(step => typeof step !== 'string' || !step.trim())) {\n throw new Error('Research verdict requires boolean viability, all required official policy references, distinctness reasoning and a concrete implementation plan');\n }\n return research;\n}\nfunction prepareWorkspace(store: Store, job: Job): void {\n if (!job.baseJobId || job.basePrepared) return;\n const base = store.get(job.baseJobId);\n if (!job.baseDigest || sourceDigest(base.workspace) !== job.baseDigest) throw Object.assign(new Error('Predecessor source changed since intake; refusing to copy unverified code'), { code: 'SETUP_REQUIRED' });\n if (existsSync(job.workspace)) {\n if (sourceDigest(job.workspace) !== job.baseDigest) throw Object.assign(new Error('Uninitialized successor workspace differs from its verified predecessor; inspect it before retrying'), { code: 'SETUP_REQUIRED' });\n } else {\n mkdirSync(job.config.workspaceRoot, { recursive: true, mode: 0o700 });\n const staging = mkdtempSync(join(job.config.workspaceRoot, `.${job.id}.base-`));\n const prepared = join(staging, 'source');\n try {\n cpSync(base.workspace, prepared, { recursive: true, force: false, errorOnExist: true, mode: constants.COPYFILE_FICLONE,\n filter: path => !isGeneratedPath(relative(base.workspace, path)) });\n if (sourceDigest(prepared) !== job.baseDigest || sourceDigest(base.workspace) !== job.baseDigest) throw new Error('Predecessor changed while copying; no successor was initialized');\n renameSync(prepared, job.workspace);\n } finally { rmSync(staging, { recursive: true, force: true }); }\n }\n store.update(job.id, { basePrepared: true });\n}\n\n\nfunction taskPrompt(job: Job): string {\n return `You are the native host of an embedded Flutter app Harness. Use your own context, tools and native delegation in ${job.workspace}; never launch another coding-agent CLI. Implement only this product. Never hide functionality from App Review or use obfuscation to imitate distinct utility. Do not upload, submit, push, read publisher credentials or change factory state. These instructions constrain this workflow, not arbitrary host tools: the workspace is not a security sandbox. Complete real implementations, not placeholders.\\nImmutable product requirements:\\n${JSON.stringify(job.spec, null, 2)}\\nPrevious verification/review failure (repair the mechanism, never weaken acceptance):\\n${job.feedback ?? job.error ?? 'none'}\\nPersisted execution logs:\\n${JSON.stringify(job.logs.slice(-3))}\\nContinue existing work. Only actual deterministic checks performed by the Harness establish verification; host claims do not.\\n`;\n}\n\nexport interface TurnOptions { buildOnly?: boolean }\nexport interface HostAction {\n job: Job;\n action: 'host' | 'step' | 'wait' | 'done';\n turn?: { id: string; stage: HostStage; prompt: string; cwd: string; environment: Record<string, string> };\n}\n\nfunction assertTurnPermission(job: Job, options: TurnOptions): void {\n if (options.buildOnly && (job.config.allowSubmit || job.config.allowRelease)) throw new Error('--build-only refuses this task with snapshotted publication permission');\n}\n\nfunction contextDigest(job: Job): string {\n return createHash('sha256').update(JSON.stringify({\n spec: job.spec, requestSpec: job.requestSpec, config: job.config, workspace: job.workspace,\n stage: job.stage, research: job.research, feedback: job.feedback, logs: job.logs,\n verifiedDigest: job.verifiedDigest, verifiedDependencyDigest: job.verifiedDependencyDigest,\n screenshotDigest: job.screenshotDigest, verifiedAt: job.verifiedAt,\n })).digest('hex');\n}\n\nfunction deadlineExpired(job: Job): boolean {\n return Date.now() - job.createdAt > job.config.maxJobHours * 3600000;\n}\n\nfunction requireReviewProof(job: Job): void {\n try {\n if (!job.verifiedDigest || sourceDigest(job.workspace) !== job.verifiedDigest) throw new Error('Source changed since verification; stale evidence cannot approve a release');\n requireDependencyProof(job);\n if (job.spec.apple?.screenshotsDir && sourceDigest(inside(job.workspace, job.spec.apple.screenshotsDir), false) !== job.screenshotDigest) throw new Error('Screenshots changed since runtime verification; stale evidence cannot approve a release');\n } catch (cause) {\n const error = toError(cause);\n if (error.code !== 'SETUP_REQUIRED') error.code = 'EVIDENCE_CHANGED';\n throw error;\n }\n}\n\nfunction hostAction(store: Store, job: Job): HostAction {\n const turn = job.turn!;\n let instruction: string;\n if (turn.stage === 'research') {\n const portfolio = store.list().filter(value => value.id !== job.id).map(value => ({ id: value.spec.id, purpose: value.spec.purpose, audience: value.spec.audience, differentiators: value.spec.differentiators }));\n instruction = `Research only with your own host tools. Retrieve the current official Apple review guidelines at https://developer.apple.com/app-store/review/guidelines/ and assess rules ${REQUIRED_POLICY_RULES.join(', ')}, offline persistence/backup and distinct utility against portfolio ${JSON.stringify(portfolio)}. Assess content ownership and submitting account compliance with rule 4.2.6; report unknowns rather than inventing attestations. Return a typed JSON result {\"viable\":boolean,\"policySources\":[{\"rule\":\"4.2\",\"url\":\"https://developer.apple.com/...\"}],\"distinctness\":\"specific reasoning\",\"risks\":[\"...\"],\"plan\":[\"concrete step\"]}. Cite all required rules. These host-supplied citations are not independently verified policy evidence. Do not promise App Store approval.`;\n } else if (turn.stage === 'build') {\n instruction = `Research plan: ${JSON.stringify(job.research)}\\nCreate a complete iOS Flutter project in this cwd if absent. Implement the entire product, persistence and validated backup/restore, accessibility and realistic empty/error states. Include real integration_test and test_driver acceptance workflows and real simulator screenshots under the requested screenshots directory; never fake screenshots or bypass tests. Use the returned environment with your own tools. The configured SDK, if any, is external to source; keep development caches task-local. Frozen checks: ${JSON.stringify(job.config.verification)}. Complete this turn without a result payload when source is ready; the Harness will then run verification, not infer success.`;\n } else {\n instruction = `Use a native independent reviewer with a fresh context when your host supports one. Review actual source and acceptance tests read-only; do not edit files. If independent review is unavailable, disclose that limitation rather than claim a separate reviewer. Verified source: ${job.verifiedDigest}; dependency resolution: ${job.verifiedDependencyDigest}; actual checks: ${JSON.stringify(job.config.verification)}. Reject incomplete workflows, data loss, untested backup/corrupt import, fake screenshots, accessibility failures, placeholders, misleading legal claims, weak tests, hidden features and repetitive products. Return typed JSON {\"approved\":boolean,\"findings\":[\"blocking issue\"],\"acceptanceEvidence\":[{\"requirement\":\"exact acceptance string\",\"evidence\":\"file/symbol + observed command or scenario\"}]}. Cover every acceptance requirement. Host reviewer identity is advisory; the Harness gates only typed results and unchanged deterministic evidence.`;\n }\n // Host-visible JSON carries only task overrides, never inherited credential values.\n const environment = flutterEnvironment(job.config, job.workspace, { CI: '1' });\n if (job.config.toolchain) {\n environment.FLUTTER_ROOT = job.config.toolchain.flutterSdk;\n environment.PATH = `${join(job.config.toolchain.flutterSdk, 'bin')}${process.env.PATH ? `${delimiter}${process.env.PATH}` : ''}`;\n }\n return { job, action: 'host', turn: { id: turn.id, stage: turn.stage, prompt: taskPrompt(job) + instruction, cwd: job.workspace, environment: Object.fromEntries(Object.entries(environment).filter((entry): entry is [string, string] => entry[1] !== undefined)) } };\n}\n\nfunction repair(job: Job, message: string): Partial<Job> {\n return {\n stage: 'build', status: (job.attempts[job.stage] ?? 0) >= job.config.maxAttempts ? 'failed' : 'waiting',\n turn: null, review: null, verifiedDigest: null, verifiedDependencyDigest: null, screenshotDigest: null, verifiedAt: undefined,\n artifact: null, ipaPath: null, archiveDigest: null, feedback: message, error: message,\n nextAt: Date.now() + job.config.retryDelayMs,\n };\n}\n\nexport async function nextTurn(store: Store, id: string, options: TurnOptions = {}): Promise<HostAction> {\n store.acquire();\n try {\n let job = store.get(id);\n assertTurnPermission(job, options);\n if (job.turn) {\n if (job.status !== 'running' || job.stage !== job.turn.stage || contextDigest(job) !== job.turn.contextDigest) throw new Error('Active host turn context changed; abandon its token before requesting another turn');\n if (deadlineExpired(job)) {\n const claimed = job.turn;\n job = store.transition(id, current => {\n assertTurnPermission(current, options);\n if (current.turn?.id !== claimed.id || contextDigest(current) !== claimed.contextDigest) throw new Error('Host turn changed while checking its deadline; inspect the current task');\n return { turn: null, status: 'failed', error: 'Task wall-clock limit reached; the expired host turn cannot resume' };\n });\n return { job, action: 'done' };\n }\n return hostAction(store, job);\n }\n if (job.groups.length && !job.manualRecovery) return { job, action: 'step' };\n if (['failed', 'ready', 'built', 'approved', 'released'].includes(job.status)) return { job, action: 'done' };\n const eligible = ['queued', 'waiting'].includes(job.status) || (job.status === 'blocked' && job.blockedReason?.kind === 'prerequisite');\n if (!eligible || job.nextAt > Date.now() || job.manualRecovery) return { job, action: 'wait' };\n if (!['research', 'build', 'review'].includes(job.stage)) return { job, action: 'step' };\n if (deadlineExpired(job) || job.hostTurns >= job.config.maxHostTurns || (job.attempts[job.stage] ?? 0) >= job.config.maxAttempts) {\n job = store.transition(id, current => {\n assertTurnPermission(current, options);\n return { status: 'failed', error: 'Host turn, stage attempt or task wall-clock limit reached; no further host work will start' };\n });\n return { job, action: 'done' };\n }\n try {\n if (job.stage === 'review') requireReviewProof(job);\n prepareWorkspace(store, job);\n mkdirSync(job.workspace, { recursive: true, mode: 0o700 });\n } catch (cause) {\n const error = toError(cause);\n job = store.update(id, error.code === 'SETUP_REQUIRED' || job.stage !== 'review'\n ? { status: 'blocked', error: error.message }\n : repair(job, error.message));\n return { job, action: 'wait' };\n }\n job = store.transition(id, current => {\n assertTurnPermission(current, options);\n const eligible = ['queued', 'waiting'].includes(current.status) || (current.status === 'blocked' && current.blockedReason?.kind === 'prerequisite');\n if (current.turn || contextDigest(current) !== contextDigest(job) || current.nextAt > Date.now() || !eligible || current.groups.length || current.manualRecovery) throw new Error('Task changed before the host turn could be claimed');\n if (deadlineExpired(current) || current.hostTurns >= current.config.maxHostTurns || (current.attempts[current.stage] ?? 0) >= current.config.maxAttempts) return { status: 'failed', error: 'Host turn, stage attempt or task wall-clock limit reached; no further host work will start' };\n if (current.stage === 'review') requireReviewProof(current);\n const turn = { id: randomUUID(), stage: current.stage as HostStage, createdAt: Date.now(), contextDigest: contextDigest(current) };\n return { turn, hostTurns: current.hostTurns + 1, attempts: { ...current.attempts, [current.stage]: (current.attempts[current.stage] ?? 0) + 1 }, status: 'running', blockedReason: null, error: null };\n });\n return job.turn ? hostAction(store, job) : { job, action: 'done' };\n } finally { store.release(); }\n}\n\nexport function completeTurn(store: Store, id: string, turnId: string, result?: unknown, options: TurnOptions = {}): Job {\n return store.transition(id, job => {\n assertTurnPermission(job, options);\n if (!job.turn || job.turn.id !== turnId || job.turn.stage !== job.stage || job.status !== 'running') throw new Error('Stale, replayed or wrong-phase host turn; use next to inspect the active token');\n if (contextDigest(job) !== job.turn.contextDigest) throw new Error('Host turn context changed; abandon this stale token before continuing');\n if (job.groups.length || job.manualRecovery) throw new Error('Command recovery must finish before completing a host turn');\n if (deadlineExpired(job)) return { turn: null, status: 'failed', error: 'Task wall-clock limit reached; the expired host result was not accepted' };\n let patch: Partial<Job>;\n if (job.stage === 'research') {\n const research = parseResearch(JSON.stringify(ResearchSchema.parse(result)));\n patch = research.viable ? { stage: 'build', research } : { status: 'failed', research, error: 'Research rejected this product; no replacement product or review evasion will be attempted' };\n } else if (job.stage === 'build') {\n if (result !== undefined) throw new Error('Build completion accepts no result payload; actual deterministic verification is required');\n const project = inside(job.workspace, 'pubspec.yaml');\n if (!lstatSync(project).isFile()) throw new Error('Build completion requires a regular pubspec.yaml in the task workspace');\n patch = { stage: 'verify', verifiedDigest: null, verifiedDependencyDigest: null, screenshotDigest: null, verifiedAt: undefined, review: null, artifact: null, ipaPath: null, archiveDigest: null };\n } else {\n const review = ReviewSchema.parse(result);\n if (!job.spec.acceptance.every(requirement => review.acceptanceEvidence.some(item => item.requirement === requirement))) throw new Error('Review verdict must cover each acceptance requirement with concrete evidence');\n try { requireReviewProof(job); }\n catch (cause) { return repair(job, toError(cause).message); }\n if (!review.approved || review.findings.length) return { ...repair(job, `Independent review rejected the artifact: ${JSON.stringify(review)}`), review };\n patch = { stage: 'package', review };\n }\n store.event(id, { completedTurn: turnId, stage: job.stage });\n return { status: 'queued', nextAt: Date.now(), error: null, turn: null, ...patch };\n });\n}\n\nexport function abandonTurn(store: Store, id: string, turnId: string, options: TurnOptions = {}): Job {\n return store.transition(id, job => {\n assertTurnPermission(job, options);\n if (!job.turn || job.turn.id !== turnId) throw new Error('Stale or replayed host turn; no active claim was abandoned');\n if (job.groups.length || job.manualRecovery) throw new Error('Command recovery must finish before abandoning a host turn');\n store.event(id, { abandonedTurn: turnId, stage: job.turn.stage });\n return { turn: null, status: 'queued', nextAt: Date.now(), error: null };\n });\n}\n\nfunction next(store: Store, job: Job, stage: Stage, extra: Partial<Job> = {}): Job {\n return store.update(job.id, { stage, status: 'queued', nextAt: Date.now(), error: null, groups: [], ...extra });\n}\n\nexport async function executeStep(store: Store, job: Job, { signal }: { signal?: AbortSignal } = {}): Promise<Job> {\n const config = job.config;\n if (['research', 'build', 'review'].includes(job.stage) || job.turn) throw new Error(`Stage ${job.stage} belongs to a native host turn; use next and complete`);\n if (signal?.aborted) return store.update(job.id, { status: 'waiting', nextAt: Date.now(), error: 'Worker was interrupted before this stage started' });\n if (!config.allowLocalExecution) return store.update(job.id, { status: 'blocked', error: config.executionWarning ?? 'Local execution is disabled. Explicitly enable allowLocalExecution only for trusted deterministic commands in a dedicated account or VM.' });\n if (deadlineExpired(job) && !['publish', 'monitor'].includes(job.stage)) {\n return store.update(job.id, { status: 'failed', error: 'Task wall-clock limit reached; no further work will start' });\n }\n const attemptNumber = (job.attempts[job.stage] ?? 0) + 1;\n let attempts = { ...job.attempts };\n let attemptCharged = false;\n const developerEnv = flutterEnvironment(config, job.workspace, executionEnvironment(config));\n const verifierEnv = flutterEnvironment(config, job.workspace, executionEnvironment(config), true);\n const environment = ['verify', 'package'].includes(job.stage) ? verifierEnv : developerEnv;\n const logPath = join(config.stateDir, 'logs', job.id, `${job.stage}-${attemptNumber}-${Date.now()}.log`);\n store.update(job.id, { logs: [...job.logs, logPath] });\n const exec: Run = async (argv: string[], options: RunOptions = {}) => {\n let pid: number | undefined;\n try {\n const effectiveEnv = options.env ?? environment;\n const command = effectiveEnv.FLUTTER_ROOT && ['flutter', 'dart'].includes(argv[0]) ? [join(effectiveEnv.FLUTTER_ROOT, 'bin', argv[0]), ...argv.slice(1)] : argv;\n const result = await run(command, {\n cwd: job.workspace, env: effectiveEnv, timeoutMs: config.timeoutMs, signal, logPath, ...options,\n onSpawn: (value, metadata) => {\n pid = value;\n const current = store.get(job.id);\n store.update(job.id, { groups: [...current.groups, value], commands: { ...current.commands, [value]: metadata }, recoveryStage: job.stage });\n options.onSpawn?.(value, metadata);\n },\n });\n if (pid && processGroupAlive(pid)) {\n try { process.kill(process.platform === 'win32' ? pid : -pid, 'SIGTERM'); } catch {}\n throw new Error('Command left background processes; termination was requested and replay will wait for the owned group to exit');\n }\n return result;\n } finally {\n const current = store.get(job.id);\n const groups = current.groups.filter(processGroupAlive);\n const commands = Object.fromEntries(Object.entries(current.commands ?? {}).filter(([pid]) => groups.includes(Number(pid))));\n store.update(job.id, { groups, commands, recoveryStage: groups.length ? current.recoveryStage ?? job.stage : undefined });\n }\n };\n try {\n prepareWorkspace(store, job);\n mkdirSync(job.workspace, { recursive: true, mode: 0o700 });\n if (job.stage === 'verify' || job.stage === 'package') {\n await checkPrerequisites(config.verification.prerequisites ?? [], { cwd: job.workspace, env: environment, run: exec, signal });\n }\n if ((job.attempts[job.stage] ?? 0) >= config.maxAttempts && !['publish', 'monitor'].includes(job.stage)) return store.update(job.id, { status: 'failed', error: `Attempt limit reached at ${job.stage}` });\n if (config.toolchain && ['verify', 'package'].includes(job.stage)) {\n const toolchain = await prepareFlutter(job, { run: exec, env: developerEnv, signal });\n if (toolchain) store.update(job.id, { toolchain });\n }\n attempts = { ...attempts, [job.stage]: attemptNumber };\n store.update(job.id, { attempts });\n attemptCharged = true;\n if (job.stage === 'verify') {\n if (config.toolchain) {\n const dependencies = await exec(['flutter', 'pub', 'get']);\n if (dependencies.code !== 0) throw new Error(`Verification dependency resolution failed: ${dependencies.stderr.slice(-4000)}`);\n }\n const before = sourceDigest(job.workspace);\n const dependenciesBefore = dependencyDigest(job.workspace);\n for (const argv of [...config.verification.checks, ...config.verification.runtime]) {\n const result = await exec(expandArgv(argv, executionEnvironment(config)));\n if (result.code !== 0) throw new Error(`Verification failed (${result.code}) ${JSON.stringify(argv)}:\\n${result.stderr.slice(-5000)}\\n${result.stdout.slice(-5000)}`);\n }\n if (sourceDigest(job.workspace) !== before) throw new Error('Verification changed source files; the new revision must be verified again');\n if (dependencyDigest(job.workspace) !== dependenciesBefore) throw new Error('Verification changed dependency resolution; the new resolution must be verified again');\n const screenshotDigest = job.spec.apple?.screenshotsDir ? sourceDigest(inside(job.workspace, job.spec.apple.screenshotsDir), false) : null;\n return next(store, job, 'review', { verifiedDigest: before, verifiedDependencyDigest: dependenciesBefore, screenshotDigest, verifiedAt: new Date().toISOString() });\n }\n if (job.stage === 'package') {\n requireReviewProof(job);\n if (!job.review?.approved || job.review.findings.length) throw new Error('Packaging requires an approved host review');\n if (process.platform !== 'darwin') throw Object.assign(new Error('iOS packaging requires the Mac worker; use the SSH controller from Linux'), { code: 'SETUP_REQUIRED' });\n const target = config.packageTarget;\n if (config.allowSubmit && target !== 'ipa') throw Object.assign(new Error('Only a verified IPA can enter publication'), { code: 'SETUP_REQUIRED' });\n const output = inside(job.workspace, target === 'ipa' ? 'build/ios/ipa' : 'build/ios/iphonesimulator');\n if (target === 'ipa' && !config.apple?.exportOptionsPlist) throw Object.assign(new Error('Configure apple.exportOptionsPlist and valid local signing before IPA packaging'), { code: 'SETUP_REQUIRED' });\n const apple = job.spec.apple;\n if (target === 'ipa' && (!apple?.version || !apple.buildNumber)) throw Object.assign(new Error('apple.version and apple.buildNumber are required for signing'), { code: 'SETUP_REQUIRED' });\n let exportOptions: { directory: string; path: string } | undefined;\n let built;\n try {\n if (target === 'ipa') exportOptions = await prepareExportOptions(config.apple!.exportOptionsPlist!, config.stateDir, exec);\n store.update(job.id, { artifact: null, ipaPath: null, archiveDigest: null });\n rmSync(output, { recursive: true, force: true });\n const command = target === 'ipa'\n ? ['flutter', 'build', 'ipa', '--release', '--build-name', apple!.version!, '--build-number', apple!.buildNumber!, '--export-options-plist', exportOptions!.path]\n : ['flutter', 'build', 'ios', '--simulator', '--debug', '--no-pub'];\n built = await exec(command);\n } finally { if (exportOptions) rmSync(exportOptions.directory, { recursive: true, force: true }); }\n if (built.code !== 0) throw new Error(`iOS ${target} build failed: ${built.stderr.slice(-5000)}`);\n if (sourceDigest(job.workspace) !== job.verifiedDigest) throw Object.assign(new Error('Packaging changed source; re-verification is required'), { code: 'EVIDENCE_CHANGED' });\n requireDependencyProof(job);\n const products = readdirSync(output).filter(name => name.endsWith(target === 'ipa' ? '.ipa' : '.app'));\n if (products.length !== 1) throw new Error(`Expected exactly one ${target === 'ipa' ? 'IPA' : 'simulator app'} in ${relative(job.workspace, output)}`);\n const path = inside(job.workspace, join(relative(job.workspace, output), products[0]));\n const digest = target === 'ipa' ? createHash('sha256').update(readFileSync(path)).digest('hex') : sourceDigest(path, false);\n const artifact = { kind: target === 'ipa' ? 'ipa' as const : 'ios-simulator' as const, path, digest, createdAt: new Date().toISOString() };\n if (!config.allowSubmit) return store.update(job.id, { status: 'built', artifact, error: null });\n return next(store, job, 'publish', { artifact, ipaPath: path, archiveDigest: digest });\n }\n if (job.stage === 'publish') {\n if (!config.allowSubmit) throw Object.assign(new Error('This task has no upload/submission permission'), { code: 'SETUP_REQUIRED' });\n if (!job.ipaPath || !job.archiveDigest) throw new Error('Publication requires a completed verified IPA artifact');\n if (sourceDigest(job.workspace) !== job.verifiedDigest || createHash('sha256').update(readFileSync(job.ipaPath)).digest('hex') !== job.archiveDigest) throw new Error('Source or archive changed after verification; refusing publication');\n requireDependencyProof(job);\n const spec = structuredClone(job.spec);\n if (spec.apple?.screenshotsDir) spec.apple.screenshotsDir = inside(job.workspace, spec.apple.screenshotsDir);\n if (spec.apple?.screenshotsDir && sourceDigest(spec.apple.screenshotsDir, false) !== job.screenshotDigest) throw new Error('Screenshots changed after runtime verification; refusing to upload different assets');\n const receipt = await shipApple({ spec, ipaPath: job.ipaPath, state: store.get(job.id).receipt, save: receipt => { store.update(job.id, { receipt }); }, run: exec, signal, allowRelease: config.allowRelease });\n return next(store, job, 'monitor', { receipt, status: 'waiting', nextAt: Date.now() + config.pollMs });\n }\n if (job.stage === 'monitor') {\n const result = await pollApple({ spec: job.spec, state: job.receipt, signal });\n if (result.status === 'approved' && (result.available || !config.allowRelease)) return store.update(job.id, { status: result.available ? 'released' : 'approved', appleReview: result, error: null });\n if (result.status === 'rejected') {\n return store.update(job.id, { status: 'blocked', appleReview: result, error: 'Apple rejected this version. Rejection message details are not available through this API; do not invent feedback. Supply the actual App Review message with the feedback command to resume repairs.' });\n }\n return store.update(job.id, { status: 'waiting', appleReview: result, attempts: { ...attempts, monitor: 0 }, nextAt: Date.now() + config.pollMs, error: null });\n }\n throw new Error(`Unknown task stage ${job.stage}`);\n } catch (cause) {\n const error = toError(cause);\n if (error.code === 'PROCESS_CLEANUP_BLOCKED') return store.update(job.id, { status: 'blocked', blockedReason: null, manualRecovery: error.message, error: error.message });\n if (signal?.aborted) return store.update(job.id, { status: 'waiting', attempts: { ...attempts, [job.stage]: job.attempts[job.stage] ?? 0 }, nextAt: Date.now(), error: error.message });\n if (error.code === 'PREREQUISITE_FAILED' && error.prerequisite) return store.update(job.id, { status: 'blocked', blockedReason: { kind: 'prerequisite', stage: job.stage, prerequisite: error.prerequisite }, attempts: { ...job.attempts }, nextAt: Date.now() + config.pollMs, error: error.message });\n if (!attemptCharged) return store.update(job.id, { status: 'blocked', blockedReason: null, attempts: { ...job.attempts }, nextAt: Date.now(), error: error.message });\n const blocked = (error.code === 'ENOENT' && error.syscall?.startsWith('spawn')) || /SETUP_REQUIRED|UNSUPPORTED|APPLE_WRITE_UNCERTAIN|APPLE_STATE_|PROCESS_CLEANUP_BLOCKED/.test(error.code ?? '');\n if (blocked) return store.update(job.id, { status: 'blocked', error: error.message });\n if (error.code === 'APPLE_PROCESSING' || error.code === 'APPLE_RATE_LIMIT') return store.update(job.id, { status: 'waiting', attempts: { ...attempts, [job.stage]: Math.max(0, (attempts[job.stage] ?? 0) - 1) }, error: error.message, nextAt: Date.now() + config.pollMs });\n const receipt = store.get(job.id).receipt;\n const publicationRecovery = ['publish', 'monitor'].includes(job.stage) && (job.stage === 'monitor' || !!(receipt.upload || receipt.pending || receipt.buildId || receipt.submissionId || receipt.versionId || Object.keys(receipt.effects ?? {}).length));\n if (publicationRecovery && error.transient === true) return store.update(job.id, { status: 'waiting', error: error.message, nextAt: Date.now() + config.pollMs });\n if (job.stage === 'monitor' || (publicationRecovery && error.code?.startsWith('APPLE_'))) return store.update(job.id, { status: 'blocked', error: error.message });\n const charged = attempts[job.stage] ?? 0;\n const exhausted = error.code === 'BUDGET' || charged >= config.maxAttempts;\n if (job.stage === 'verify' || (job.stage === 'package' && error.code === 'EVIDENCE_CHANGED')) return store.update(job.id, { ...repair({ ...job, attempts }, error.message), status: exhausted ? 'failed' : 'waiting', nextAt: Date.now() + config.retryDelayMs * charged });\n return store.update(job.id, { status: exhausted ? 'failed' : 'waiting', error: error.message, feedback: error.message, nextAt: Date.now() + config.retryDelayMs * charged });\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"runner.js","names":[],"sources":["../src/runner.ts"],"sourcesContent":["import { mkdirSync, readFileSync, readdirSync, lstatSync, rmSync, existsSync } from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport { basename, dirname, isAbsolute, join, relative, resolve, delimiter, sep } from 'node:path';\nimport { createHash, randomUUID } from 'node:crypto';\nimport { run, executionEnvironment, processGroupAlive } from './process.js';\nimport { canonicalPath, inside, expandArgv } from './config.js';\nimport { checkPrerequisites } from './preflight.js';\nimport { flutterEnvironment, prepareFlutter } from './flutter.js';\nimport { prepareExportOptions, prepareNativeExportCommands } from './export-options.js';\nimport { dependencyDigest, generatedModulePaths, isGeneratedPath } from './dependencies.js';\nimport { ReviewSchema, SpecSchema, toError, validateJobConfig } from './schemas.js';\nimport type { Job, HostStage, Stage } from './schemas.js';\nimport type { Run, RunOptions, RunResult } from './process.js';\nimport type { Store } from './store.js';\nimport { sourceDigest, prepareWorkspace, projectDirectory, artifactOutputPath } from './workspace.js';\nimport { parseResearch, researchPrompt, reviewInstructions } from './policy.js';\nimport { assertProject, buildInstructions } from './project-profiles.js';\nimport { closestOwnedGoWorkspace } from './go-dependencies.js';\nimport { validateMacOSArtifact } from './macos.js';\nimport { validateMyGoPackaging, validateMyGoCommand } from './mygo-build.js';\nimport { invalidateVerification } from './proof.js';\nimport { prepareIsolatedCommand, type IsolatedCommand, type IsolationCapabilities } from './isolation.js';\n\nfunction requireDependencyProof(job: Job): void {\n if (!job.verifiedDependencyDigest) throw Object.assign(new Error('Dependency resolution proof is missing; retry this stopped task to re-run verification'), { code: 'SETUP_REQUIRED' });\n if (dependencyDigest(job.workspace, job.spec.framework, job.spec.project?.directory) !== job.verifiedDependencyDigest) throw Object.assign(new Error('Dependency resolution changed since verification; re-verification is required'), { code: 'EVIDENCE_CHANGED' });\n}\n\nfunction taskPrompt(job: Job): string {\n return `You are the native host of an embedded multi-stack app Harness. Use your own context, tools and native delegation in ${projectDirectory(job)}; never launch another coding-agent CLI. Preserve the requested framework and existing architecture. Implement only this product. Never hide functionality from users or reviewers. Do not upload, submit, push, read publisher credentials or change factory state. Remote build commands belong only to the explicitly authorized Harness packaging profile, not host turns. The workspace is not a security sandbox. Complete real implementations, not placeholders.\\nImmutable product requirements:\\n${JSON.stringify(job.spec, null, 2)}\\nPrevious verification/review failure (repair the mechanism, never weaken acceptance):\\n${job.feedback ?? job.error ?? 'none'}\\nPersisted execution logs:\\n${JSON.stringify(job.logs.slice(-3))}\\nContinue existing work. Only actual deterministic checks performed by the Harness establish verification; host claims do not.\\n`;\n}\n\nexport interface TurnOptions { buildOnly?: boolean }\nexport interface HostAction {\n job: Job;\n action: 'host' | 'step' | 'wait' | 'done';\n turn?: { id: string; stage: HostStage; prompt: string; cwd: string; environment: Record<string, string> };\n}\n\nfunction assertTurnPermission(_job: Job, _options: TurnOptions): void {\n // No publication permission exists in this build; the flag remains accepted for CLI compatibility.\n}\n\nfunction contextDigest(job: Job): string {\n return createHash('sha256').update(JSON.stringify({\n spec: job.spec, requestSpec: job.requestSpec, config: job.config, workspace: job.workspace,\n stage: job.stage, research: job.research, feedback: job.feedback, logs: job.logs,\n verifiedDigest: job.verifiedDigest, verifiedDependencyDigest: job.verifiedDependencyDigest,\n screenshotDigest: job.screenshotDigest, verifiedAt: job.verifiedAt,\n })).digest('hex');\n}\n\nfunction deadlineExpired(job: Job): boolean {\n return Date.now() - job.createdAt > job.config.maxJobHours * 3600000;\n}\n\nfunction requireReviewProof(job: Job): void {\n try {\n if (!job.verifiedDigest || sourceDigest(job.workspace, true, job.spec.framework, job.spec.project?.directory) !== job.verifiedDigest) throw new Error('Source changed since verification; stale evidence cannot approve a handoff');\n requireDependencyProof(job);\n if (job.spec.screenshotsDir && sourceDigest(inside(projectDirectory(job), job.spec.screenshotsDir), false) !== job.screenshotDigest) throw new Error('Screenshots changed since runtime verification; stale evidence cannot approve a handoff');\n } catch (cause) {\n const error = toError(cause);\n if (error.code !== 'SETUP_REQUIRED') error.code = 'EVIDENCE_CHANGED';\n throw error;\n }\n}\n\nfunction hostAction(store: Store, job: Job): HostAction {\n const turn = job.turn!;\n let instruction: string;\n if (turn.stage === 'research') {\n const portfolio = store.list().filter(value => value.id !== job.id && value.spec.channel === job.spec.channel && value.spec.id !== job.spec.id).map(value => ({ id: value.spec.id, purpose: value.spec.purpose, audience: value.spec.audience, differentiators: value.spec.differentiators }));\n instruction = researchPrompt(job, portfolio);\n } else if (turn.stage === 'build') {\n instruction = `Research plan: ${JSON.stringify(job.research)}\\n${buildInstructions(job.spec)} Implement the entire requested product, accessibility and realistic empty/error states. Add genuine device/simulator acceptance workflows and real screenshots when requested; never fake screenshots or bypass tests. Do not add unrequested offline/backup/account features. Use the returned environment with your tools. Frozen verification and packaging: ${JSON.stringify({ verification: job.config.verification, packaging: job.config.packaging, packageTarget: job.config.packageTarget })}. Complete this turn without a result payload when source is ready; the Harness will then execute verification, not infer success.`;\n } else {\n instruction = reviewInstructions(job);\n }\n // Host-visible JSON carries only task overrides, never inherited credential values.\n const environment = job.spec.framework === 'flutter' ? flutterEnvironment(job.config, job.workspace, { CI: '1' }) : { CI: '1' } as NodeJS.ProcessEnv;\n if (job.spec.framework === 'mygo') Object.assign(environment, { GOENV: 'off', GOTOOLCHAIN: 'local', GOFLAGS: '-mod=readonly', GOWORK: closestOwnedGoWorkspace(job.workspace, job.spec.project?.directory) ?? 'off' });\n if (job.spec.framework === 'flutter' && job.config.toolchain) {\n environment.FLUTTER_ROOT = job.config.toolchain.flutterSdk;\n environment.PATH = `${join(job.config.toolchain.flutterSdk, 'bin')}${process.env.PATH ? `${delimiter}${process.env.PATH}` : ''}`;\n }\n return { job, action: 'host', turn: { id: turn.id, stage: turn.stage, prompt: taskPrompt(job) + instruction, cwd: projectDirectory(job), environment: Object.fromEntries(Object.entries(environment).filter((entry): entry is [string, string] => entry[1] !== undefined)) } };\n}\n\nfunction repair(job: Job, message: string): Partial<Job> {\n return {\n stage: 'build', status: (job.attempts[job.stage] ?? 0) >= job.config.maxAttempts ? 'failed' : 'waiting',\n ...invalidateVerification(), turn: null, feedback: message, error: message,\n nextAt: Date.now() + job.config.retryDelayMs,\n };\n}\n\nexport async function nextTurn(store: Store, id: string, options: TurnOptions = {}): Promise<HostAction> {\n store.acquire();\n try {\n let job = store.get(id);\n assertTurnPermission(job, options);\n if (job.turn) {\n if (job.status !== 'running' || job.stage !== job.turn.stage || contextDigest(job) !== job.turn.contextDigest) throw new Error('Active host turn context changed; abandon its token before requesting another turn');\n if (deadlineExpired(job)) {\n const claimed = job.turn;\n job = store.transition(id, current => {\n assertTurnPermission(current, options);\n if (current.turn?.id !== claimed.id || contextDigest(current) !== claimed.contextDigest) throw new Error('Host turn changed while checking its deadline; inspect the current task');\n return { turn: null, status: 'failed', error: 'Task wall-clock limit reached; the expired host turn cannot resume' };\n });\n return { job, action: 'done' };\n }\n return hostAction(store, job);\n }\n if (job.groups.length && !job.manualRecovery) return { job, action: 'step' };\n if (['failed', 'ready', 'built'].includes(job.status)) return { job, action: 'done' };\n const eligible = ['queued', 'waiting'].includes(job.status) || (job.status === 'blocked' && job.blockedReason?.kind === 'prerequisite');\n if (!eligible || job.nextAt > Date.now() || job.manualRecovery) return { job, action: 'wait' };\n if (!['research', 'build', 'review'].includes(job.stage)) return { job, action: 'step' };\n if (deadlineExpired(job) || job.hostTurns >= job.config.maxHostTurns || (job.attempts[job.stage] ?? 0) >= job.config.maxAttempts) {\n job = store.transition(id, current => {\n assertTurnPermission(current, options);\n return { status: 'failed', error: 'Host turn, stage attempt or task wall-clock limit reached; no further host work will start' };\n });\n return { job, action: 'done' };\n }\n try {\n if (job.stage === 'review') requireReviewProof(job);\n prepareWorkspace(store, job);\n mkdirSync(projectDirectory(job), { recursive: true, mode: 0o700 });\n } catch (cause) {\n const error = toError(cause);\n job = store.update(id, error.code === 'SETUP_REQUIRED' || job.stage !== 'review'\n ? { status: 'blocked', error: error.message }\n : repair(job, error.message));\n return { job, action: 'wait' };\n }\n job = store.transition(id, current => {\n assertTurnPermission(current, options);\n const eligible = ['queued', 'waiting'].includes(current.status) || (current.status === 'blocked' && current.blockedReason?.kind === 'prerequisite');\n if (current.turn || contextDigest(current) !== contextDigest(job) || current.nextAt > Date.now() || !eligible || current.groups.length || current.manualRecovery) throw new Error('Task changed before the host turn could be claimed');\n if (deadlineExpired(current) || current.hostTurns >= current.config.maxHostTurns || (current.attempts[current.stage] ?? 0) >= current.config.maxAttempts) return { status: 'failed', error: 'Host turn, stage attempt or task wall-clock limit reached; no further host work will start' };\n if (current.stage === 'review') requireReviewProof(current);\n const turn = { id: randomUUID(), stage: current.stage as HostStage, createdAt: Date.now(), contextDigest: contextDigest(current) };\n return { turn, hostTurns: current.hostTurns + 1, attempts: { ...current.attempts, [current.stage]: (current.attempts[current.stage] ?? 0) + 1 }, status: 'running', blockedReason: null, error: null };\n });\n return job.turn ? hostAction(store, job) : { job, action: 'done' };\n } finally { store.release(); }\n}\n\nexport function completeTurn(store: Store, id: string, turnId: string, result?: unknown, options: TurnOptions = {}): Job {\n return store.transition(id, job => {\n assertTurnPermission(job, options);\n if (!job.turn || job.turn.id !== turnId || job.turn.stage !== job.stage || job.status !== 'running') throw new Error('Stale, replayed or wrong-phase host turn; use next to inspect the active token');\n if (contextDigest(job) !== job.turn.contextDigest) throw new Error('Host turn context changed; abandon this stale token before continuing');\n if (job.groups.length || job.manualRecovery) throw new Error('Command recovery must finish before completing a host turn');\n if (deadlineExpired(job)) return { turn: null, status: 'failed', error: 'Task wall-clock limit reached; the expired host result was not accepted' };\n let patch: Partial<Job>;\n if (job.stage === 'research') {\n const research = parseResearch(JSON.stringify(result), job.spec.channel);\n patch = research.viable ? { stage: 'build', research } : { status: 'failed', research, error: 'Research rejected this product; no replacement product will be attempted' };\n } else if (job.stage === 'build') {\n if (result !== undefined) throw new Error('Build completion accepts no result payload; actual deterministic verification is required');\n assertProject(projectDirectory(job), job.spec);\n patch = { ...invalidateVerification(), stage: job.config.obfuscation ? 'obfuscate' : 'verify' };\n } else {\n const review = ReviewSchema.parse(result);\n if (!job.spec.acceptance.every(requirement => review.acceptanceEvidence.some(item => item.requirement === requirement))) throw new Error('Review verdict must cover each acceptance requirement with concrete evidence');\n try { requireReviewProof(job); }\n catch (cause) { return repair(job, toError(cause).message); }\n if (!review.approved || review.findings.length) return { ...repair(job, `Independent review rejected the artifact: ${JSON.stringify(review)}`), review };\n patch = { stage: 'package', review };\n }\n store.event(id, { completedTurn: turnId, stage: job.stage });\n return { status: 'queued', nextAt: Date.now(), error: null, turn: null, ...patch };\n });\n}\n\nexport function abandonTurn(store: Store, id: string, turnId: string, options: TurnOptions = {}): Job {\n return store.transition(id, job => {\n assertTurnPermission(job, options);\n if (!job.turn || job.turn.id !== turnId) throw new Error('Stale or replayed host turn; no active claim was abandoned');\n if (job.groups.length || job.manualRecovery) throw new Error('Command recovery must finish before abandoning a host turn');\n store.event(id, { abandonedTurn: turnId, stage: job.turn.stage });\n return { turn: null, status: 'queued', nextAt: Date.now(), error: null };\n });\n}\n\nfunction next(store: Store, job: Job, stage: Stage, extra: Partial<Job> = {}): Job {\n return store.update(job.id, { stage, status: 'queued', nextAt: Date.now(), error: null, groups: [], ...extra });\n}\n\nexport async function executeStep(store: Store, job: Job, { signal }: { signal?: AbortSignal } = {}): Promise<Job> {\n const config = job.config;\n if (['research', 'build', 'review'].includes(job.stage) || job.turn) throw new Error(`Stage ${job.stage} belongs to a native host turn; use next and complete`);\n if (signal?.aborted) return store.update(job.id, { status: 'waiting', nextAt: Date.now(), error: 'Worker was interrupted before this stage started' });\n if (!config.allowLocalExecution) return store.update(job.id, { status: 'blocked', error: config.executionWarning ?? 'Local execution is disabled. Explicitly enable allowLocalExecution only for trusted deterministic commands in a dedicated account or VM.' });\n if (deadlineExpired(job)) return store.update(job.id, { status: 'failed', error: 'Task wall-clock limit reached; no further work will start' });\n const attemptNumber = (job.attempts[job.stage] ?? 0) + 1;\n let attempts = { ...job.attempts };\n let attemptCharged = false;\n const developerEnv = job.spec.framework === 'flutter' ? flutterEnvironment(config, job.workspace, executionEnvironment(config)) : executionEnvironment(config);\n const verifierEnv = job.spec.framework === 'flutter' ? flutterEnvironment(config, job.workspace, executionEnvironment(config), true) : developerEnv;\n const environment = ['verify', 'package'].includes(job.stage) ? verifierEnv : developerEnv;\n const logPath = join(config.stateDir, 'logs', job.id, `${job.stage}-${attemptNumber}-${Date.now()}.log`);\n store.update(job.id, { logs: [...job.logs, logPath] });\n const readableFiles = new Set<string>();\n const trackedRun = async (argv: string[], options: RunOptions = {}, capabilities: IsolationCapabilities = {}): Promise<RunResult> => {\n let pid: number | undefined;\n let isolated: IsolatedCommand | undefined;\n try {\n const effectiveEnv = options.env ?? environment;\n if (job.spec.framework === 'mygo') validateMyGoCommand(config, argv);\n const command = effectiveEnv.FLUTTER_ROOT && ['flutter', 'dart'].includes(argv[0]) ? [join(effectiveEnv.FLUTTER_ROOT, 'bin', argv[0]), ...argv.slice(1)] : argv;\n const cwd = options.cwd ?? projectDirectory(job);\n if (config.isolation && ['obfuscate', 'verify', 'package'].includes(job.stage)) {\n isolated = prepareIsolatedCommand(command, {\n config, workspace: job.workspace, cwd, env: effectiveEnv,\n readableFiles: [...readableFiles, ...(capabilities.readableFiles ?? [])],\n writableDirectories: capabilities.writableDirectories,\n });\n }\n const result = await run(isolated?.argv ?? command, {\n timeoutMs: config.timeoutMs, signal, logPath, ...options, cwd, env: isolated?.env ?? effectiveEnv,\n onSpawn: (value, metadata) => {\n pid = value;\n const current = store.get(job.id);\n store.update(job.id, { groups: [...current.groups, value], commands: { ...current.commands, [value]: metadata }, recoveryStage: job.stage });\n options.onSpawn?.(value, metadata);\n },\n });\n if (pid && processGroupAlive(pid)) {\n try { process.kill(process.platform === 'win32' ? pid : -pid, 'SIGTERM'); } catch {}\n throw new Error('Command left background processes; termination was requested and replay will wait for the owned group to exit');\n }\n return result;\n } finally {\n try {\n const current = store.get(job.id);\n const groups = current.groups.filter(processGroupAlive);\n const commands = Object.fromEntries(Object.entries(current.commands ?? {}).filter(([pid]) => groups.includes(Number(pid))));\n store.update(job.id, { groups, commands, recoveryStage: groups.length ? current.recoveryStage ?? job.stage : undefined });\n } finally { isolated?.cleanup(); }\n }\n };\n const exec: Run = (argv, options) => trackedRun(argv, options);\n const utilityExec: Run = (argv, options) => {\n if (!config.isolation) return trackedRun(argv, options);\n if (argv[0] !== '/usr/bin/plutil') throw Object.assign(new Error('Unexpected isolated export utility'), { code: 'SETUP_REQUIRED' });\n const file = resolve(options?.cwd ?? projectDirectory(job), argv[argv.length - 1]!);\n const actual = canonicalPath(file), state = canonicalPath(config.stateDir), directory = dirname(actual);\n const within = (root: string, target: string): boolean => {\n const path = relative(root, target);\n return path === '' || path !== '..' && !path.startsWith(`..${sep}`) && !isAbsolute(path);\n };\n if (within(job.workspace, file) && !within(job.workspace, actual)\n && !config.isolation.readOnlyPaths.some(root => within(root, actual))) throw Object.assign(new Error('Workspace export options cannot grant access to an unapproved external file'), { code: 'SETUP_REQUIRED' });\n const snapshot = dirname(directory) === state && basename(directory).startsWith('export-options-') && basename(actual) === 'ExportOptions.plist';\n if (within(state, actual) && !snapshot || within(canonicalPath(config.workspaceRoot), actual) && !within(job.workspace, actual)\n || config.configPath && actual === canonicalPath(config.configPath)) throw Object.assign(new Error('Export utility cannot read protected control state or another task'), { code: 'SETUP_REQUIRED' });\n const writing = argv[1] === '-convert' && argv[2] === 'xml1';\n if (writing && !snapshot) throw Object.assign(new Error('Export utility writes require a harness-owned snapshot'), { code: 'SETUP_REQUIRED' });\n return trackedRun([...argv.slice(0, -1), actual], options, {\n readableFiles: within(job.workspace, actual) ? [] : [actual],\n writableDirectories: writing ? [directory] : [],\n });\n };\n const removeArtifact = async (output: string): Promise<void> => {\n if (!config.isolation) { rmSync(output, { recursive: true, force: true }); return; }\n const result = await exec(['/bin/rm', '-rf', '--', output]);\n if (result.code !== 0) throw Object.assign(new Error(`Isolated artifact cleanup was denied: ${result.stderr || result.stdout}`), { code: 'SETUP_REQUIRED' });\n };\n try {\n validateJobConfig(job.spec, config);\n if (job.spec.framework === 'mygo') validateMyGoPackaging(config);\n prepareWorkspace(store, job);\n mkdirSync(projectDirectory(job), { recursive: true, mode: 0o700 });\n if (job.spec.framework === 'mygo') {\n Object.assign(developerEnv, {\n GOENV: 'off', GOTOOLCHAIN: 'local', GOFLAGS: '-mod=readonly',\n GOWORK: closestOwnedGoWorkspace(job.workspace, job.spec.project?.directory) ?? 'off',\n GOCACHE: developerEnv.GOCACHE ?? join(config.stateDir, 'verification-cache', 'go-build'),\n GOMODCACHE: developerEnv.GOMODCACHE ?? join(config.stateDir, 'verification-cache', 'go-mod'),\n });\n for (const key of ['MYGO_UPDATER_PRIVATE_KEY', 'MYGO_WINDOWS_CERTIFICATE_PASSWORD', 'MYGO_CLI_BINARY', 'MYGO_LDFLAGS', 'MYGO_GENERATE', 'MYGO_INSPECTOR']) delete developerEnv[key];\n }\n if (job.stage === 'verify' || job.stage === 'package') {\n await checkPrerequisites(config.verification.prerequisites ?? [], { cwd: projectDirectory(job), env: environment, run: exec, signal });\n }\n if ((job.attempts[job.stage] ?? 0) >= config.maxAttempts) return store.update(job.id, { status: 'failed', error: `Attempt limit reached at ${job.stage}` });\n if (job.spec.framework === 'flutter' && config.toolchain && ['verify', 'package'].includes(job.stage)) {\n const toolchain = await prepareFlutter(job, { run: exec, env: developerEnv, signal });\n if (toolchain) store.update(job.id, { toolchain });\n }\n attempts = { ...attempts, [job.stage]: attemptNumber };\n store.update(job.id, { attempts });\n attemptCharged = true;\n if (job.stage === 'verify') {\n if (job.spec.framework === 'flutter' && config.toolchain) {\n const dependencies = await exec(['flutter', 'pub', 'get']);\n if (dependencies.code !== 0) throw new Error(`Verification dependency resolution failed: ${dependencies.stderr.slice(-4000)}`);\n }\n const before = sourceDigest(job.workspace, true, job.spec.framework, job.spec.project?.directory);\n const dependenciesBefore = dependencyDigest(job.workspace, job.spec.framework, job.spec.project?.directory);\n for (const argv of [...config.verification.checks, ...config.verification.runtime]) {\n const result = await exec(expandArgv(argv, executionEnvironment(config)));\n if (result.code !== 0) throw new Error(`Verification failed (${result.code}) ${JSON.stringify(argv)}:\\n${result.stderr.slice(-5000)}\\n${result.stdout.slice(-5000)}`);\n }\n if (sourceDigest(job.workspace, true, job.spec.framework, job.spec.project?.directory) !== before) throw new Error('Verification changed source files; the new revision must be verified again');\n if (dependencyDigest(job.workspace, job.spec.framework, job.spec.project?.directory) !== dependenciesBefore) throw new Error('Verification changed dependency resolution; the new resolution must be verified again');\n const screenshotDigest = job.spec.screenshotsDir ? sourceDigest(inside(projectDirectory(job), job.spec.screenshotsDir), false) : null;\n return next(store, job, 'review', { verifiedDigest: before, verifiedDependencyDigest: dependenciesBefore, screenshotDigest, verifiedAt: new Date().toISOString() });\n }\n if (job.stage === 'obfuscate') {\n const obfuscation = job.config.obfuscation;\n if (!obfuscation) throw Object.assign(new Error('Obfuscation stage requires config.obfuscation'), { code: 'SETUP_REQUIRED' });\n const expanded = expandArgv(obfuscation.command, environment);\n // The default command resolves to the private obfuscator bundled inside this package, so it\n // works for global installs, local dependency installs and the macOS sandbox alike.\n const bundled = fileURLToPath(new URL('./vendor/obfuscator/dist/cli.js', import.meta.url));\n const resolved = expanded[0] === 'obfuscator' && existsSync(bundled) ? [process.execPath, bundled, ...expanded.slice(1)] : expanded;\n const argv = [\n ...resolved,\n '--project', projectDirectory(job),\n '--config', obfuscation.configPath,\n '--framework', job.spec.framework,\n ...(obfuscation.seed ? ['--seed', obfuscation.seed] : []),\n ];\n const result = await trackedRun(argv, {}, { readableFiles: [obfuscation.configPath] });\n if (result.code !== 0) throw new Error(`Obfuscation failed (${result.code}) ${JSON.stringify(argv)}:\\n${result.stderr.slice(-5000)}\\n${result.stdout.slice(-5000)}`);\n return next(store, job, 'verify');\n }\n if (job.stage === 'package') {\n requireReviewProof(job);\n if (!job.review?.approved || job.review.findings.length) throw new Error('Packaging requires an approved host review');\n const target = config.packageTarget;\n const project = projectDirectory(job);\n const profile = config.packaging;\n if (job.cloudBuildPending) throw Object.assign(new Error('A previous cloud build may have remote effects. Reconcile it with the provider before creating a new task; this build will not be replayed.'), { code: 'SETUP_REQUIRED' });\n if (['ios', 'macos'].includes(job.spec.platform) && profile?.provider !== 'cloud' && process.platform !== 'darwin') throw Object.assign(new Error(`Local ${job.spec.platform} packaging requires a macOS worker`), { code: 'SETUP_REQUIRED' });\n let path: string;\n store.update(job.id, { artifact: null, ipaPath: null, archiveDigest: null });\n if (profile) {\n const output = artifactOutputPath(project, profile.artifactPath);\n const outputRelative = relative(job.workspace, output).split(sep).join('/');\n let generated = isGeneratedPath(profile.artifactPath, job.spec.framework);\n if (!generated) for (const module of generatedModulePaths(job.workspace, job.spec.framework, job.spec.project?.directory)) if (outputRelative.startsWith(`${module}/`)) { generated = true; break; }\n if (!generated || !/(?:^|\\/)(?:build|dist|unpackage)(?:\\/|$)/.test(profile.artifactPath) || /(?:^|\\/)(?:node_modules|\\.git|\\.gradle|\\.factory-cache|Pods)(?:\\/|$)/.test(profile.artifactPath)) throw Object.assign(new Error('packaging.artifactPath must name an exact generated build/dist/unpackage artifact, never source or dependency caches'), { code: 'SETUP_REQUIRED' });\n if (!output.endsWith(target === 'simulator' || target === 'app' ? '.app' : `.${target}`)) throw Object.assign(new Error(`packaging.artifactPath must end in ${target === 'simulator' || target === 'app' ? '.app' : `.${target}`}`), { code: 'SETUP_REQUIRED' });\n const prepared = await prepareNativeExportCommands(profile.commands.map(argv => expandArgv(argv, executionEnvironment(config))), project, config.stateDir, utilityExec);\n try {\n for (const file of prepared.readableFiles) readableFiles.add(file);\n await removeArtifact(output);\n if (profile.provider === 'cloud') store.update(job.id, { cloudBuildPending: true });\n for (const argv of prepared.commands) {\n const result = await exec(argv);\n if (result.code !== 0) throw new Error(`Packaging failed (${result.code}) ${JSON.stringify(argv)}:\\n${result.stderr.slice(-5000)}\\n${result.stdout.slice(-5000)}`);\n }\n path = artifactOutputPath(project, profile.artifactPath);\n } finally {\n for (const file of prepared.readableFiles) readableFiles.delete(file);\n prepared.cleanup();\n }\n } else {\n const output = artifactOutputPath(project, target === 'ipa' ? 'build/ios/ipa' : target === 'simulator' ? 'build/ios/iphonesimulator' : target === 'apk' ? 'build/app/outputs/flutter-apk' : 'build/app/outputs/bundle/release');\n if (target === 'ipa' && !config.apple?.exportOptionsPlist) throw Object.assign(new Error('Configure apple.exportOptionsPlist and valid local signing before IPA packaging'), { code: 'SETUP_REQUIRED' });\n if (target === 'ipa' && !job.spec.apple?.buildNumber) throw Object.assign(new Error('apple.buildNumber is required for IPA signing'), { code: 'SETUP_REQUIRED' });\n let exportOptions: { directory: string; path: string } | undefined;\n try {\n if (target === 'ipa') {\n exportOptions = await prepareExportOptions(config.apple!.exportOptionsPlist!, config.stateDir, utilityExec);\n readableFiles.add(exportOptions.path);\n }\n await removeArtifact(output);\n const argv = target === 'ipa'\n ? ['flutter', 'build', 'ipa', '--release', '--build-name', job.spec.version, '--build-number', job.spec.apple!.buildNumber!, '--export-options-plist', exportOptions!.path]\n : target === 'simulator' ? ['flutter', 'build', 'ios', '--simulator', '--debug', '--no-pub']\n : ['flutter', 'build', target === 'apk' ? 'apk' : 'appbundle', '--release', '--no-pub', '--build-name', job.spec.version];\n const built = await exec(argv);\n if (built.code !== 0) throw new Error(`${job.spec.framework} ${target} build failed: ${built.stderr.slice(-5000)}`);\n } finally {\n if (exportOptions) {\n readableFiles.delete(exportOptions.path);\n rmSync(exportOptions.directory, { recursive: true, force: true });\n }\n }\n const products = readdirSync(output).filter(name => name.endsWith(target === 'simulator' ? '.app' : `.${target}`));\n if (products.length !== 1) throw new Error(`Expected exactly one ${target} artifact in ${relative(job.workspace, output)}`);\n path = artifactOutputPath(project, join(relative(project, output), products[0]));\n }\n requireReviewProof(job);\n const stat = lstatSync(path);\n const bundle = target === 'simulator' || target === 'app';\n if (stat.isSymbolicLink() || (bundle ? !stat.isDirectory() || readdirSync(path).length === 0 : !stat.isFile() || stat.size === 0)) throw new Error('Packaging did not produce a nonempty regular artifact of the requested kind');\n if (target === 'app' || target === 'dmg') await validateMacOSArtifact(path, target, exec);\n const digest = bundle ? sourceDigest(path, false) : createHash('sha256').update(readFileSync(path)).digest('hex');\n const artifact = { kind: target === 'simulator' ? 'ios-simulator' as const : target === 'app' ? 'macos-app' as const : target, path, digest, createdAt: new Date().toISOString() };\n return store.update(job.id, { status: 'built', artifact, cloudBuildPending: false, error: null });\n }\n throw new Error(`Unknown task stage ${job.stage}`);\n } catch (cause) {\n const error = toError(cause);\n if (store.get(job.id).cloudBuildPending) return store.update(job.id, { status: 'blocked', blockedReason: null, error: `Cloud build outcome requires provider reconciliation; automatic replay is forbidden. ${error.message}` });\n if (error.code === 'PROCESS_CLEANUP_BLOCKED') return store.update(job.id, { status: 'blocked', blockedReason: null, manualRecovery: error.message, error: error.message });\n if (signal?.aborted) return store.update(job.id, { status: 'waiting', attempts: { ...attempts, [job.stage]: job.attempts[job.stage] ?? 0 }, nextAt: Date.now(), error: error.message });\n if (error.code === 'PREREQUISITE_FAILED' && error.prerequisite) return store.update(job.id, { status: 'blocked', blockedReason: { kind: 'prerequisite', stage: job.stage, prerequisite: error.prerequisite }, attempts: { ...job.attempts }, nextAt: Date.now() + config.pollMs, error: error.message });\n if (!attemptCharged) return store.update(job.id, { status: 'blocked', blockedReason: null, attempts: { ...job.attempts }, nextAt: Date.now(), error: error.message });\n const blocked = (error.code === 'ENOENT' && error.syscall?.startsWith('spawn')) || /SETUP_REQUIRED|UNSUPPORTED|PROCESS_CLEANUP_BLOCKED/.test(error.code ?? '');\n if (blocked) return store.update(job.id, { status: 'blocked', error: error.message });\n const charged = attempts[job.stage] ?? 0;\n const exhausted = error.code === 'BUDGET' || charged >= config.maxAttempts;\n if (job.stage === 'verify' || (job.stage === 'package' && error.code === 'EVIDENCE_CHANGED')) return store.update(job.id, { ...repair({ ...job, attempts }, error.message), status: exhausted ? 'failed' : 'waiting', nextAt: Date.now() + config.retryDelayMs * charged });\n return store.update(job.id, { status: exhausted ? 'failed' : 'waiting', error: error.message, feedback: error.message, nextAt: Date.now() + config.retryDelayMs * charged });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAuBA,SAAS,uBAAuB,KAAgB;CAC9C,IAAI,CAAC,IAAI,0BAA0B,MAAM,OAAO,uBAAO,IAAI,MAAM,wFAAwF,GAAG,EAAE,MAAM,iBAAiB,CAAC;CACtL,IAAI,iBAAiB,IAAI,WAAW,IAAI,KAAK,WAAW,IAAI,KAAK,SAAS,SAAS,MAAM,IAAI,0BAA0B,MAAM,OAAO,uBAAO,IAAI,MAAM,+EAA+E,GAAG,EAAE,MAAM,mBAAmB,CAAC;AACrQ;AAEA,SAAS,WAAW,KAAkB;CACpC,OAAO,wHAAwH,iBAAiB,GAAG,EAAE,6eAA6e,KAAK,UAAU,IAAI,MAAM,MAAM,CAAC,EAAE,2FAA2F,IAAI,YAAY,IAAI,SAAS,OAAO,+BAA+B,KAAK,UAAU,IAAI,KAAK,MAAM,EAAE,CAAC,EAAE;AACv2B;AAaA,SAAS,cAAc,KAAkB;CACvC,OAAO,WAAW,QAAQ,CAAC,CAAC,OAAO,KAAK,UAAU;EAChD,MAAM,IAAI;EAAM,aAAa,IAAI;EAAa,QAAQ,IAAI;EAAQ,WAAW,IAAI;EACjF,OAAO,IAAI;EAAO,UAAU,IAAI;EAAU,UAAU,IAAI;EAAU,MAAM,IAAI;EAC5E,gBAAgB,IAAI;EAAgB,0BAA0B,IAAI;EAClE,kBAAkB,IAAI;EAAkB,YAAY,IAAI;CAC1D,CAAC,CAAC,CAAC,CAAC,OAAO,KAAK;AAClB;AAEA,SAAS,gBAAgB,KAAmB;CAC1C,OAAO,KAAK,IAAI,IAAI,IAAI,YAAY,IAAI,OAAO,cAAc;AAC/D;AAEA,SAAS,mBAAmB,KAAgB;CAC1C,IAAI;EACF,IAAI,CAAC,IAAI,kBAAkB,aAAa,IAAI,WAAW,MAAM,IAAI,KAAK,WAAW,IAAI,KAAK,SAAS,SAAS,MAAM,IAAI,gBAAgB,MAAM,IAAI,MAAM,4EAA4E;EAClO,uBAAuB,GAAG;EAC1B,IAAI,IAAI,KAAK,kBAAkB,aAAa,OAAO,iBAAiB,GAAG,GAAG,IAAI,KAAK,cAAc,GAAG,KAAK,MAAM,IAAI,kBAAkB,MAAM,IAAI,MAAM,yFAAyF;CAChP,SAAS,OAAO;EACd,MAAM,QAAQ,QAAQ,KAAK;EAC3B,IAAI,MAAM,SAAS,kBAAkB,MAAM,OAAO;EAClD,MAAM;CACR;AACF;AAEA,SAAS,WAAW,OAAc,KAAsB;CACtD,MAAM,OAAO,IAAI;CACjB,IAAI;CACJ,IAAI,KAAK,UAAU,YAAY;EAC7B,MAAM,YAAY,MAAM,KAAK,CAAC,CAAC,QAAO,UAAS,MAAM,OAAO,IAAI,MAAM,MAAM,KAAK,YAAY,IAAI,KAAK,WAAW,MAAM,KAAK,OAAO,IAAI,KAAK,EAAE,CAAC,CAAC,KAAI,WAAU;GAAE,IAAI,MAAM,KAAK;GAAI,SAAS,MAAM,KAAK;GAAS,UAAU,MAAM,KAAK;GAAU,iBAAiB,MAAM,KAAK;EAAgB,EAAE;EAC7R,cAAc,eAAe,KAAK,SAAS;CAC7C,OAAO,IAAI,KAAK,UAAU,SACxB,cAAc,kBAAkB,KAAK,UAAU,IAAI,QAAQ,EAAE,IAAI,kBAAkB,IAAI,IAAI,EAAE,mWAAmW,KAAK,UAAU;EAAE,cAAc,IAAI,OAAO;EAAc,WAAW,IAAI,OAAO;EAAW,eAAe,IAAI,OAAO;CAAc,CAAC,EAAE;MAEpkB,cAAc,mBAAmB,GAAG;CAGtC,MAAM,cAAc,IAAI,KAAK,cAAc,YAAY,mBAAmB,IAAI,QAAQ,IAAI,WAAW,EAAE,IAAI,IAAI,CAAC,IAAI,EAAE,IAAI,IAAI;CAC9H,IAAI,IAAI,KAAK,cAAc,QAAQ,OAAO,OAAO,aAAa;EAAE,OAAO;EAAO,aAAa;EAAS,SAAS;EAAiB,QAAQ,wBAAwB,IAAI,WAAW,IAAI,KAAK,SAAS,SAAS,KAAK;CAAM,CAAC;CACpN,IAAI,IAAI,KAAK,cAAc,aAAa,IAAI,OAAO,WAAW;EAC5D,YAAY,eAAe,IAAI,OAAO,UAAU;EAChD,YAAY,OAAO,GAAG,KAAK,IAAI,OAAO,UAAU,YAAY,KAAK,IAAI,QAAQ,IAAI,OAAO,GAAG,YAAY,QAAQ,IAAI,SAAS;CAC9H;CACA,OAAO;EAAE;EAAK,QAAQ;EAAQ,MAAM;GAAE,IAAI,KAAK;GAAI,OAAO,KAAK;GAAO,QAAQ,WAAW,GAAG,IAAI;GAAa,KAAK,iBAAiB,GAAG;GAAG,aAAa,OAAO,YAAY,OAAO,QAAQ,WAAW,CAAC,CAAC,QAAQ,UAAqC,MAAM,OAAO,KAAA,CAAS,CAAC;EAAE;CAAE;AAC/Q;AAEA,SAAS,OAAO,KAAU,SAA+B;CACvD,OAAO;EACL,OAAO;EAAS,SAAS,IAAI,SAAS,IAAI,UAAU,MAAM,IAAI,OAAO,cAAc,WAAW;EAC9F,GAAG,uBAAuB;EAAG,MAAM;EAAM,UAAU;EAAS,OAAO;EACnE,QAAQ,KAAK,IAAI,IAAI,IAAI,OAAO;CAClC;AACF;AAEA,eAAsB,SAAS,OAAc,IAAY,UAAuB,CAAC,GAAwB;CACvG,MAAM,QAAQ;CACd,IAAI;EACF,IAAI,MAAM,MAAM,IAAI,EAAE;EAEtB,IAAI,IAAI,MAAM;GACZ,IAAI,IAAI,WAAW,aAAa,IAAI,UAAU,IAAI,KAAK,SAAS,cAAc,GAAG,MAAM,IAAI,KAAK,eAAe,MAAM,IAAI,MAAM,oFAAoF;GACnN,IAAI,gBAAgB,GAAG,GAAG;IACxB,MAAM,UAAU,IAAI;IACpB,MAAM,MAAM,WAAW,KAAI,YAAW;KAEpC,IAAI,QAAQ,MAAM,OAAO,QAAQ,MAAM,cAAc,OAAO,MAAM,QAAQ,eAAe,MAAM,IAAI,MAAM,yEAAyE;KAClL,OAAO;MAAE,MAAM;MAAM,QAAQ;MAAU,OAAO;KAAqE;IACrH,CAAC;IACD,OAAO;KAAE;KAAK,QAAQ;IAAO;GAC/B;GACA,OAAO,WAAW,OAAO,GAAG;EAC9B;EACA,IAAI,IAAI,OAAO,UAAU,CAAC,IAAI,gBAAgB,OAAO;GAAE;GAAK,QAAQ;EAAO;EAC3E,IAAI;GAAC;GAAU;GAAS;EAAO,CAAC,CAAC,SAAS,IAAI,MAAM,GAAG,OAAO;GAAE;GAAK,QAAQ;EAAO;EAEpF,IAAI,EADa,CAAC,UAAU,SAAS,CAAC,CAAC,SAAS,IAAI,MAAM,KAAM,IAAI,WAAW,aAAa,IAAI,eAAe,SAAS,mBACvG,IAAI,SAAS,KAAK,IAAI,KAAK,IAAI,gBAAgB,OAAO;GAAE;GAAK,QAAQ;EAAO;EAC7F,IAAI,CAAC;GAAC;GAAY;GAAS;EAAQ,CAAC,CAAC,SAAS,IAAI,KAAK,GAAG,OAAO;GAAE;GAAK,QAAQ;EAAO;EACvF,IAAI,gBAAgB,GAAG,KAAK,IAAI,aAAa,IAAI,OAAO,iBAAiB,IAAI,SAAS,IAAI,UAAU,MAAM,IAAI,OAAO,aAAa;GAChI,MAAM,MAAM,WAAW,KAAI,YAAW;IAEpC,OAAO;KAAE,QAAQ;KAAU,OAAO;IAA6F;GACjI,CAAC;GACD,OAAO;IAAE;IAAK,QAAQ;GAAO;EAC/B;EACA,IAAI;GACF,IAAI,IAAI,UAAU,UAAU,mBAAmB,GAAG;GAClD,iBAAiB,OAAO,GAAG;GAC3B,UAAU,iBAAiB,GAAG,GAAG;IAAE,WAAW;IAAM,MAAM;GAAM,CAAC;EACnE,SAAS,OAAO;GACd,MAAM,QAAQ,QAAQ,KAAK;GAC3B,MAAM,MAAM,OAAO,IAAI,MAAM,SAAS,oBAAoB,IAAI,UAAU,WACpE;IAAE,QAAQ;IAAW,OAAO,MAAM;GAAQ,IAC1C,OAAO,KAAK,MAAM,OAAO,CAAC;GAC9B,OAAO;IAAE;IAAK,QAAQ;GAAO;EAC/B;EACA,MAAM,MAAM,WAAW,KAAI,YAAW;GAEpC,MAAM,WAAW,CAAC,UAAU,SAAS,CAAC,CAAC,SAAS,QAAQ,MAAM,KAAM,QAAQ,WAAW,aAAa,QAAQ,eAAe,SAAS;GACpI,IAAI,QAAQ,QAAQ,cAAc,OAAO,MAAM,cAAc,GAAG,KAAK,QAAQ,SAAS,KAAK,IAAI,KAAK,CAAC,YAAY,QAAQ,OAAO,UAAU,QAAQ,gBAAgB,MAAM,IAAI,MAAM,oDAAoD;GACtO,IAAI,gBAAgB,OAAO,KAAK,QAAQ,aAAa,QAAQ,OAAO,iBAAiB,QAAQ,SAAS,QAAQ,UAAU,MAAM,QAAQ,OAAO,aAAa,OAAO;IAAE,QAAQ;IAAU,OAAO;GAA6F;GACzR,IAAI,QAAQ,UAAU,UAAU,mBAAmB,OAAO;GAE1D,OAAO;IAAE,MAAA;KADM,IAAI,WAAW;KAAG,OAAO,QAAQ;KAAoB,WAAW,KAAK,IAAI;KAAG,eAAe,cAAc,OAAO;IACnH;IAAG,WAAW,QAAQ,YAAY;IAAG,UAAU;KAAE,GAAG,QAAQ;MAAW,QAAQ,SAAS,QAAQ,SAAS,QAAQ,UAAU,KAAK;IAAE;IAAG,QAAQ;IAAW,eAAe;IAAM,OAAO;GAAK;EACvM,CAAC;EACD,OAAO,IAAI,OAAO,WAAW,OAAO,GAAG,IAAI;GAAE;GAAK,QAAQ;EAAO;CACnE,UAAU;EAAE,MAAM,QAAQ;CAAG;AAC/B;AAEA,SAAgB,aAAa,OAAc,IAAY,QAAgB,QAAkB,UAAuB,CAAC,GAAQ;CACvH,OAAO,MAAM,WAAW,KAAI,QAAO;EAEjC,IAAI,CAAC,IAAI,QAAQ,IAAI,KAAK,OAAO,UAAU,IAAI,KAAK,UAAU,IAAI,SAAS,IAAI,WAAW,WAAW,MAAM,IAAI,MAAM,gFAAgF;EACrM,IAAI,cAAc,GAAG,MAAM,IAAI,KAAK,eAAe,MAAM,IAAI,MAAM,uEAAuE;EAC1I,IAAI,IAAI,OAAO,UAAU,IAAI,gBAAgB,MAAM,IAAI,MAAM,4DAA4D;EACzH,IAAI,gBAAgB,GAAG,GAAG,OAAO;GAAE,MAAM;GAAM,QAAQ;GAAU,OAAO;EAA0E;EAClJ,IAAI;EACJ,IAAI,IAAI,UAAU,YAAY;GAC5B,MAAM,WAAW,cAAc,KAAK,UAAU,MAAM,GAAG,IAAI,KAAK,OAAO;GACvE,QAAQ,SAAS,SAAS;IAAE,OAAO;IAAS;GAAS,IAAI;IAAE,QAAQ;IAAU;IAAU,OAAO;GAA2E;EAC3K,OAAO,IAAI,IAAI,UAAU,SAAS;GAChC,IAAI,WAAW,KAAA,GAAW,MAAM,IAAI,MAAM,2FAA2F;GACrI,cAAc,iBAAiB,GAAG,GAAG,IAAI,IAAI;GAC7C,QAAQ;IAAE,GAAG,uBAAuB;IAAG,OAAO,IAAI,OAAO,cAAc,cAAc;GAAS;EAChG,OAAO;GACL,MAAM,SAAS,aAAa,MAAM,MAAM;GACxC,IAAI,CAAC,IAAI,KAAK,WAAW,OAAM,gBAAe,OAAO,mBAAmB,MAAK,SAAQ,KAAK,gBAAgB,WAAW,CAAC,GAAG,MAAM,IAAI,MAAM,8EAA8E;GACvN,IAAI;IAAE,mBAAmB,GAAG;GAAG,SACxB,OAAO;IAAE,OAAO,OAAO,KAAK,QAAQ,KAAK,CAAC,CAAC,OAAO;GAAG;GAC5D,IAAI,CAAC,OAAO,YAAY,OAAO,SAAS,QAAQ,OAAO;IAAE,GAAG,OAAO,KAAK,6CAA6C,KAAK,UAAU,MAAM,GAAG;IAAG;GAAO;GACvJ,QAAQ;IAAE,OAAO;IAAW;GAAO;EACrC;EACA,MAAM,MAAM,IAAI;GAAE,eAAe;GAAQ,OAAO,IAAI;EAAM,CAAC;EAC3D,OAAO;GAAE,QAAQ;GAAU,QAAQ,KAAK,IAAI;GAAG,OAAO;GAAM,MAAM;GAAM,GAAG;EAAM;CACnF,CAAC;AACH;AAEA,SAAgB,YAAY,OAAc,IAAY,QAAgB,UAAuB,CAAC,GAAQ;CACpG,OAAO,MAAM,WAAW,KAAI,QAAO;EAEjC,IAAI,CAAC,IAAI,QAAQ,IAAI,KAAK,OAAO,QAAQ,MAAM,IAAI,MAAM,4DAA4D;EACrH,IAAI,IAAI,OAAO,UAAU,IAAI,gBAAgB,MAAM,IAAI,MAAM,4DAA4D;EACzH,MAAM,MAAM,IAAI;GAAE,eAAe;GAAQ,OAAO,IAAI,KAAK;EAAM,CAAC;EAChE,OAAO;GAAE,MAAM;GAAM,QAAQ;GAAU,QAAQ,KAAK,IAAI;GAAG,OAAO;EAAK;CACzE,CAAC;AACH;AAEA,SAAS,KAAK,OAAc,KAAU,OAAc,QAAsB,CAAC,GAAQ;CACjF,OAAO,MAAM,OAAO,IAAI,IAAI;EAAE;EAAO,QAAQ;EAAU,QAAQ,KAAK,IAAI;EAAG,OAAO;EAAM,QAAQ,CAAC;EAAG,GAAG;CAAM,CAAC;AAChH;AAEA,eAAsB,YAAY,OAAc,KAAU,EAAE,WAAqC,CAAC,GAAiB;CACjH,MAAM,SAAS,IAAI;CACnB,IAAI;EAAC;EAAY;EAAS;CAAQ,CAAC,CAAC,SAAS,IAAI,KAAK,KAAK,IAAI,MAAM,MAAM,IAAI,MAAM,SAAS,IAAI,MAAM,sDAAsD;CAC9J,IAAI,QAAQ,SAAS,OAAO,MAAM,OAAO,IAAI,IAAI;EAAE,QAAQ;EAAW,QAAQ,KAAK,IAAI;EAAG,OAAO;CAAmD,CAAC;CACrJ,IAAI,CAAC,OAAO,qBAAqB,OAAO,MAAM,OAAO,IAAI,IAAI;EAAE,QAAQ;EAAW,OAAO,OAAO,oBAAoB;CAA2I,CAAC;CAChQ,IAAI,gBAAgB,GAAG,GAAG,OAAO,MAAM,OAAO,IAAI,IAAI;EAAE,QAAQ;EAAU,OAAO;CAA4D,CAAC;CAC9I,MAAM,iBAAiB,IAAI,SAAS,IAAI,UAAU,KAAK;CACvD,IAAI,WAAW,EAAE,GAAG,IAAI,SAAS;CACjC,IAAI,iBAAiB;CACrB,MAAM,eAAe,IAAI,KAAK,cAAc,YAAY,mBAAmB,QAAQ,IAAI,WAAW,qBAAqB,MAAM,CAAC,IAAI,qBAAqB,MAAM;CAC7J,MAAM,cAAc,IAAI,KAAK,cAAc,YAAY,mBAAmB,QAAQ,IAAI,WAAW,qBAAqB,MAAM,GAAG,IAAI,IAAI;CACvI,MAAM,cAAc,CAAC,UAAU,SAAS,CAAC,CAAC,SAAS,IAAI,KAAK,IAAI,cAAc;CAC9E,MAAM,UAAU,KAAK,OAAO,UAAU,QAAQ,IAAI,IAAI,GAAG,IAAI,MAAM,GAAG,cAAc,GAAG,KAAK,IAAI,EAAE,KAAK;CACvG,MAAM,OAAO,IAAI,IAAI,EAAE,MAAM,CAAC,GAAG,IAAI,MAAM,OAAO,EAAE,CAAC;CACrD,MAAM,gCAAgB,IAAI,IAAY;CACtC,MAAM,aAAa,OAAO,MAAgB,UAAsB,CAAC,GAAG,eAAsC,CAAC,MAA0B;EACnI,IAAI;EACJ,IAAI;EACJ,IAAI;GACF,MAAM,eAAe,QAAQ,OAAO;GACpC,IAAI,IAAI,KAAK,cAAc,QAAQ,oBAAoB,QAAQ,IAAI;GACnE,MAAM,UAAU,aAAa,gBAAgB,CAAC,WAAW,MAAM,CAAC,CAAC,SAAS,KAAK,EAAE,IAAI,CAAC,KAAK,aAAa,cAAc,OAAO,KAAK,EAAE,GAAG,GAAG,KAAK,MAAM,CAAC,CAAC,IAAI;GAC3J,MAAM,MAAM,QAAQ,OAAO,iBAAiB,GAAG;GAC/C,IAAI,OAAO,aAAa;IAAC;IAAa;IAAU;GAAS,CAAC,CAAC,SAAS,IAAI,KAAK,GAC3E,WAAW,uBAAuB,SAAS;IACzC;IAAQ,WAAW,IAAI;IAAW;IAAK,KAAK;IAC5C,eAAe,CAAC,GAAG,eAAe,GAAI,aAAa,iBAAiB,CAAC,CAAE;IACvE,qBAAqB,aAAa;GACpC,CAAC;GAEH,MAAM,SAAS,MAAM,IAAI,UAAU,QAAQ,SAAS;IAClD,WAAW,OAAO;IAAW;IAAQ;IAAS,GAAG;IAAS;IAAK,KAAK,UAAU,OAAO;IACrF,UAAU,OAAO,aAAa;KAC5B,MAAM;KACN,MAAM,UAAU,MAAM,IAAI,IAAI,EAAE;KAChC,MAAM,OAAO,IAAI,IAAI;MAAE,QAAQ,CAAC,GAAG,QAAQ,QAAQ,KAAK;MAAG,UAAU;OAAE,GAAG,QAAQ;QAAW,QAAQ;MAAS;MAAG,eAAe,IAAI;KAAM,CAAC;KAC3I,QAAQ,UAAU,OAAO,QAAQ;IACnC;GACF,CAAC;GACD,IAAI,OAAO,kBAAkB,GAAG,GAAG;IACjC,IAAI;KAAE,QAAQ,KAAK,QAAQ,aAAa,UAAU,MAAM,CAAC,KAAK,SAAS;IAAG,QAAQ,CAAC;IACnF,MAAM,IAAI,MAAM,+GAA+G;GACjI;GACA,OAAO;EACT,UAAU;GACR,IAAI;IACF,MAAM,UAAU,MAAM,IAAI,IAAI,EAAE;IAChC,MAAM,SAAS,QAAQ,OAAO,OAAO,iBAAiB;IACtD,MAAM,WAAW,OAAO,YAAY,OAAO,QAAQ,QAAQ,YAAY,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,OAAO,SAAS,OAAO,GAAG,CAAC,CAAC,CAAC;IAC1H,MAAM,OAAO,IAAI,IAAI;KAAE;KAAQ;KAAU,eAAe,OAAO,SAAS,QAAQ,iBAAiB,IAAI,QAAQ,KAAA;IAAU,CAAC;GAC1H,UAAU;IAAE,UAAU,QAAQ;GAAG;EACnC;CACF;CACA,MAAM,QAAa,MAAM,YAAY,WAAW,MAAM,OAAO;CAC7D,MAAM,eAAoB,MAAM,YAAY;EAC1C,IAAI,CAAC,OAAO,WAAW,OAAO,WAAW,MAAM,OAAO;EACtD,IAAI,KAAK,OAAO,mBAAmB,MAAM,OAAO,uBAAO,IAAI,MAAM,oCAAoC,GAAG,EAAE,MAAM,iBAAiB,CAAC;EAClI,MAAM,OAAO,QAAQ,SAAS,OAAO,iBAAiB,GAAG,GAAG,KAAK,KAAK,SAAS,EAAG;EAClF,MAAM,SAAS,cAAc,IAAI,GAAG,QAAQ,cAAc,OAAO,QAAQ,GAAG,YAAY,QAAQ,MAAM;EACtG,MAAM,UAAU,MAAc,WAA4B;GACxD,MAAM,OAAO,SAAS,MAAM,MAAM;GAClC,OAAO,SAAS,MAAM,SAAS,QAAQ,CAAC,KAAK,WAAW,KAAK,KAAK,KAAK,CAAC,WAAW,IAAI;EACzF;EACA,IAAI,OAAO,IAAI,WAAW,IAAI,KAAK,CAAC,OAAO,IAAI,WAAW,MAAM,KAC3D,CAAC,OAAO,UAAU,cAAc,MAAK,SAAQ,OAAO,MAAM,MAAM,CAAC,GAAG,MAAM,OAAO,uBAAO,IAAI,MAAM,6EAA6E,GAAG,EAAE,MAAM,iBAAiB,CAAC;EACjN,MAAM,WAAW,QAAQ,SAAS,MAAM,SAAS,SAAS,SAAS,CAAC,CAAC,WAAW,iBAAiB,KAAK,SAAS,MAAM,MAAM;EAC3H,IAAI,OAAO,OAAO,MAAM,KAAK,CAAC,YAAY,OAAO,cAAc,OAAO,aAAa,GAAG,MAAM,KAAK,CAAC,OAAO,IAAI,WAAW,MAAM,KACzH,OAAO,cAAc,WAAW,cAAc,OAAO,UAAU,GAAG,MAAM,OAAO,uBAAO,IAAI,MAAM,oEAAoE,GAAG,EAAE,MAAM,iBAAiB,CAAC;EACtM,MAAM,UAAU,KAAK,OAAO,cAAc,KAAK,OAAO;EACtD,IAAI,WAAW,CAAC,UAAU,MAAM,OAAO,uBAAO,IAAI,MAAM,wDAAwD,GAAG,EAAE,MAAM,iBAAiB,CAAC;EAC7I,OAAO,WAAW,CAAC,GAAG,KAAK,MAAM,GAAG,EAAE,GAAG,MAAM,GAAG,SAAS;GACzD,eAAe,OAAO,IAAI,WAAW,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM;GAC3D,qBAAqB,UAAU,CAAC,SAAS,IAAI,CAAC;EAChD,CAAC;CACH;CACA,MAAM,iBAAiB,OAAO,WAAkC;EAC9D,IAAI,CAAC,OAAO,WAAW;GAAE,OAAO,QAAQ;IAAE,WAAW;IAAM,OAAO;GAAK,CAAC;GAAG;EAAQ;EACnF,MAAM,SAAS,MAAM,KAAK;GAAC;GAAW;GAAO;GAAM;EAAM,CAAC;EAC1D,IAAI,OAAO,SAAS,GAAG,MAAM,OAAO,uBAAO,IAAI,MAAM,yCAAyC,OAAO,UAAU,OAAO,QAAQ,GAAG,EAAE,MAAM,iBAAiB,CAAC;CAC7J;CACA,IAAI;EACF,kBAAkB,IAAI,MAAM,MAAM;EAClC,IAAI,IAAI,KAAK,cAAc,QAAQ,sBAAsB,MAAM;EAC/D,iBAAiB,OAAO,GAAG;EAC3B,UAAU,iBAAiB,GAAG,GAAG;GAAE,WAAW;GAAM,MAAM;EAAM,CAAC;EACjE,IAAI,IAAI,KAAK,cAAc,QAAQ;GACjC,OAAO,OAAO,cAAc;IAC1B,OAAO;IAAO,aAAa;IAAS,SAAS;IAC7C,QAAQ,wBAAwB,IAAI,WAAW,IAAI,KAAK,SAAS,SAAS,KAAK;IAC/E,SAAS,aAAa,WAAW,KAAK,OAAO,UAAU,sBAAsB,UAAU;IACvF,YAAY,aAAa,cAAc,KAAK,OAAO,UAAU,sBAAsB,QAAQ;GAC7F,CAAC;GACD,KAAK,MAAM,OAAO;IAAC;IAA4B;IAAqC;IAAmB;IAAgB;IAAiB;GAAgB,GAAG,OAAO,aAAa;EACjL;EACA,IAAI,IAAI,UAAU,YAAY,IAAI,UAAU,WAC1C,MAAM,mBAAmB,OAAO,aAAa,iBAAiB,CAAC,GAAG;GAAE,KAAK,iBAAiB,GAAG;GAAG,KAAK;GAAa,KAAK;GAAM;EAAO,CAAC;EAEvI,KAAK,IAAI,SAAS,IAAI,UAAU,MAAM,OAAO,aAAa,OAAO,MAAM,OAAO,IAAI,IAAI;GAAE,QAAQ;GAAU,OAAO,4BAA4B,IAAI;EAAQ,CAAC;EAC1J,IAAI,IAAI,KAAK,cAAc,aAAa,OAAO,aAAa,CAAC,UAAU,SAAS,CAAC,CAAC,SAAS,IAAI,KAAK,GAAG;GACrG,MAAM,YAAY,MAAM,eAAe,KAAK;IAAE,KAAK;IAAM,KAAK;IAAc;GAAO,CAAC;GACpF,IAAI,WAAW,MAAM,OAAO,IAAI,IAAI,EAAE,UAAU,CAAC;EACnD;EACA,WAAW;GAAE,GAAG;IAAW,IAAI,QAAQ;EAAc;EACrD,MAAM,OAAO,IAAI,IAAI,EAAE,SAAS,CAAC;EACjC,iBAAiB;EACjB,IAAI,IAAI,UAAU,UAAU;GAC1B,IAAI,IAAI,KAAK,cAAc,aAAa,OAAO,WAAW;IACxD,MAAM,eAAe,MAAM,KAAK;KAAC;KAAW;KAAO;IAAK,CAAC;IACzD,IAAI,aAAa,SAAS,GAAG,MAAM,IAAI,MAAM,8CAA8C,aAAa,OAAO,MAAM,IAAK,GAAG;GAC/H;GACA,MAAM,SAAS,aAAa,IAAI,WAAW,MAAM,IAAI,KAAK,WAAW,IAAI,KAAK,SAAS,SAAS;GAChG,MAAM,qBAAqB,iBAAiB,IAAI,WAAW,IAAI,KAAK,WAAW,IAAI,KAAK,SAAS,SAAS;GAC1G,KAAK,MAAM,QAAQ,CAAC,GAAG,OAAO,aAAa,QAAQ,GAAG,OAAO,aAAa,OAAO,GAAG;IAClF,MAAM,SAAS,MAAM,KAAK,WAAW,MAAM,qBAAqB,MAAM,CAAC,CAAC;IACxE,IAAI,OAAO,SAAS,GAAG,MAAM,IAAI,MAAM,wBAAwB,OAAO,KAAK,IAAI,KAAK,UAAU,IAAI,EAAE,KAAK,OAAO,OAAO,MAAM,IAAK,EAAE,IAAI,OAAO,OAAO,MAAM,IAAK,GAAG;GACtK;GACA,IAAI,aAAa,IAAI,WAAW,MAAM,IAAI,KAAK,WAAW,IAAI,KAAK,SAAS,SAAS,MAAM,QAAQ,MAAM,IAAI,MAAM,4EAA4E;GAC/L,IAAI,iBAAiB,IAAI,WAAW,IAAI,KAAK,WAAW,IAAI,KAAK,SAAS,SAAS,MAAM,oBAAoB,MAAM,IAAI,MAAM,uFAAuF;GAEpN,OAAO,KAAK,OAAO,KAAK,UAAU;IAAE,gBAAgB;IAAQ,0BAA0B;IAAoB,kBADjF,IAAI,KAAK,iBAAiB,aAAa,OAAO,iBAAiB,GAAG,GAAG,IAAI,KAAK,cAAc,GAAG,KAAK,IAAI;IACL,6BAAY,IAAI,KAAK,EAAA,CAAE,YAAY;GAAE,CAAC;EACpK;EACA,IAAI,IAAI,UAAU,aAAa;GAC7B,MAAM,cAAc,IAAI,OAAO;GAC/B,IAAI,CAAC,aAAa,MAAM,OAAO,uBAAO,IAAI,MAAM,+CAA+C,GAAG,EAAE,MAAM,iBAAiB,CAAC;GAC5H,MAAM,WAAW,WAAW,YAAY,SAAS,WAAW;GAG5D,MAAM,UAAU,cAAc,IAAI,IAAI,mCAAmC,YAAY,GAAG,CAAC;GAEzF,MAAM,OAAO;IACX,GAFe,SAAS,OAAO,gBAAgB,WAAW,OAAO,IAAI;KAAC,QAAQ;KAAU;KAAS,GAAG,SAAS,MAAM,CAAC;IAAC,IAAI;IAGzH;IAAa,iBAAiB,GAAG;IACjC;IAAY,YAAY;IACxB;IAAe,IAAI,KAAK;IACxB,GAAI,YAAY,OAAO,CAAC,UAAU,YAAY,IAAI,IAAI,CAAC;GACzD;GACA,MAAM,SAAS,MAAM,WAAW,MAAM,CAAC,GAAG,EAAE,eAAe,CAAC,YAAY,UAAU,EAAE,CAAC;GACrF,IAAI,OAAO,SAAS,GAAG,MAAM,IAAI,MAAM,uBAAuB,OAAO,KAAK,IAAI,KAAK,UAAU,IAAI,EAAE,KAAK,OAAO,OAAO,MAAM,IAAK,EAAE,IAAI,OAAO,OAAO,MAAM,IAAK,GAAG;GACnK,OAAO,KAAK,OAAO,KAAK,QAAQ;EAClC;EACA,IAAI,IAAI,UAAU,WAAW;GAC3B,mBAAmB,GAAG;GACtB,IAAI,CAAC,IAAI,QAAQ,YAAY,IAAI,OAAO,SAAS,QAAQ,MAAM,IAAI,MAAM,4CAA4C;GACrH,MAAM,SAAS,OAAO;GACtB,MAAM,UAAU,iBAAiB,GAAG;GACpC,MAAM,UAAU,OAAO;GACvB,IAAI,IAAI,mBAAmB,MAAM,OAAO,uBAAO,IAAI,MAAM,6IAA6I,GAAG,EAAE,MAAM,iBAAiB,CAAC;GACnO,IAAI,CAAC,OAAO,OAAO,CAAC,CAAC,SAAS,IAAI,KAAK,QAAQ,KAAK,SAAS,aAAa,WAAW,QAAQ,aAAa,UAAU,MAAM,OAAO,uBAAO,IAAI,MAAM,SAAS,IAAI,KAAK,SAAS,mCAAmC,GAAG,EAAE,MAAM,iBAAiB,CAAC;GAC7O,IAAI;GACJ,MAAM,OAAO,IAAI,IAAI;IAAE,UAAU;IAAM,SAAS;IAAM,eAAe;GAAK,CAAC;GAC3E,IAAI,SAAS;IACX,MAAM,SAAS,mBAAmB,SAAS,QAAQ,YAAY;IAC/D,MAAM,iBAAiB,SAAS,IAAI,WAAW,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,GAAG;IAC1E,IAAI,YAAY,gBAAgB,QAAQ,cAAc,IAAI,KAAK,SAAS;IACxE,IAAI,CAAC,WAAgB;UAAA,MAAM,UAAU,qBAAqB,IAAI,WAAW,IAAI,KAAK,WAAW,IAAI,KAAK,SAAS,SAAS,GAAG,IAAI,eAAe,WAAW,GAAG,OAAO,EAAE,GAAG;MAAE,YAAY;MAAM;KAAO;;IACnM,IAAI,CAAC,aAAa,CAAC,2CAA2C,KAAK,QAAQ,YAAY,KAAK,uEAAuE,KAAK,QAAQ,YAAY,GAAG,MAAM,OAAO,uBAAO,IAAI,MAAM,sHAAsH,GAAG,EAAE,MAAM,iBAAiB,CAAC;IAChX,IAAI,CAAC,OAAO,SAAS,WAAW,eAAe,WAAW,QAAQ,SAAS,IAAI,QAAQ,GAAG,MAAM,OAAO,uBAAO,IAAI,MAAM,sCAAsC,WAAW,eAAe,WAAW,QAAQ,SAAS,IAAI,UAAU,GAAG,EAAE,MAAM,iBAAiB,CAAC;IAC/P,MAAM,WAAW,MAAM,4BAA4B,QAAQ,SAAS,KAAI,SAAQ,WAAW,MAAM,qBAAqB,MAAM,CAAC,CAAC,GAAG,SAAS,OAAO,UAAU,WAAW;IACtK,IAAI;KACF,KAAK,MAAM,QAAQ,SAAS,eAAe,cAAc,IAAI,IAAI;KACjE,MAAM,eAAe,MAAM;KAC3B,IAAI,QAAQ,aAAa,SAAS,MAAM,OAAO,IAAI,IAAI,EAAE,mBAAmB,KAAK,CAAC;KAClF,KAAK,MAAM,QAAQ,SAAS,UAAU;MACpC,MAAM,SAAS,MAAM,KAAK,IAAI;MAC9B,IAAI,OAAO,SAAS,GAAG,MAAM,IAAI,MAAM,qBAAqB,OAAO,KAAK,IAAI,KAAK,UAAU,IAAI,EAAE,KAAK,OAAO,OAAO,MAAM,IAAK,EAAE,IAAI,OAAO,OAAO,MAAM,IAAK,GAAG;KACnK;KACA,OAAO,mBAAmB,SAAS,QAAQ,YAAY;IACzD,UAAU;KACR,KAAK,MAAM,QAAQ,SAAS,eAAe,cAAc,OAAO,IAAI;KACpE,SAAS,QAAQ;IACnB;GACF,OAAO;IACL,MAAM,SAAS,mBAAmB,SAAS,WAAW,QAAQ,kBAAkB,WAAW,cAAc,8BAA8B,WAAW,QAAQ,kCAAkC,kCAAkC;IAC9N,IAAI,WAAW,SAAS,CAAC,OAAO,OAAO,oBAAoB,MAAM,OAAO,uBAAO,IAAI,MAAM,iFAAiF,GAAG,EAAE,MAAM,iBAAiB,CAAC;IACvM,IAAI,WAAW,SAAS,CAAC,IAAI,KAAK,OAAO,aAAa,MAAM,OAAO,uBAAO,IAAI,MAAM,+CAA+C,GAAG,EAAE,MAAM,iBAAiB,CAAC;IAChK,IAAI;IACJ,IAAI;KACF,IAAI,WAAW,OAAO;MACpB,gBAAgB,MAAM,qBAAqB,OAAO,MAAO,oBAAqB,OAAO,UAAU,WAAW;MAC1G,cAAc,IAAI,cAAc,IAAI;KACtC;KACA,MAAM,eAAe,MAAM;KAK3B,MAAM,QAAQ,MAAM,KAJP,WAAW,QACpB;MAAC;MAAW;MAAS;MAAO;MAAa;MAAgB,IAAI,KAAK;MAAS;MAAkB,IAAI,KAAK,MAAO;MAAc;MAA0B,cAAe;KAAI,IACxK,WAAW,cAAc;MAAC;MAAW;MAAS;MAAO;MAAe;MAAW;KAAU,IACvF;MAAC;MAAW;MAAS,WAAW,QAAQ,QAAQ;MAAa;MAAa;MAAY;MAAgB,IAAI,KAAK;KAAO,CAC/F;KAC7B,IAAI,MAAM,SAAS,GAAG,MAAM,IAAI,MAAM,GAAG,IAAI,KAAK,UAAU,GAAG,OAAO,iBAAiB,MAAM,OAAO,MAAM,IAAK,GAAG;IACpH,UAAU;KACR,IAAI,eAAe;MACjB,cAAc,OAAO,cAAc,IAAI;MACvC,OAAO,cAAc,WAAW;OAAE,WAAW;OAAM,OAAO;MAAK,CAAC;KAClE;IACF;IACA,MAAM,WAAW,YAAY,MAAM,CAAC,CAAC,QAAO,SAAQ,KAAK,SAAS,WAAW,cAAc,SAAS,IAAI,QAAQ,CAAC;IACjH,IAAI,SAAS,WAAW,GAAG,MAAM,IAAI,MAAM,wBAAwB,OAAO,eAAe,SAAS,IAAI,WAAW,MAAM,GAAG;IAC1H,OAAO,mBAAmB,SAAS,KAAK,SAAS,SAAS,MAAM,GAAG,SAAS,EAAE,CAAC;GACjF;GACA,mBAAmB,GAAG;GACtB,MAAM,OAAO,UAAU,IAAI;GAC3B,MAAM,SAAS,WAAW,eAAe,WAAW;GACpD,IAAI,KAAK,eAAe,MAAM,SAAS,CAAC,KAAK,YAAY,KAAK,YAAY,IAAI,CAAC,CAAC,WAAW,IAAI,CAAC,KAAK,OAAO,KAAK,KAAK,SAAS,IAAI,MAAM,IAAI,MAAM,6EAA6E;GAChO,IAAI,WAAW,SAAS,WAAW,OAAO,MAAM,sBAAsB,MAAM,QAAQ,IAAI;GACxF,MAAM,SAAS,SAAS,aAAa,MAAM,KAAK,IAAI,WAAW,QAAQ,CAAC,CAAC,OAAO,aAAa,IAAI,CAAC,CAAC,CAAC,OAAO,KAAK;GAChH,MAAM,WAAW;IAAE,MAAM,WAAW,cAAc,kBAA2B,WAAW,QAAQ,cAAuB;IAAQ;IAAM;IAAQ,4BAAW,IAAI,KAAK,EAAA,CAAE,YAAY;GAAE;GACjL,OAAO,MAAM,OAAO,IAAI,IAAI;IAAE,QAAQ;IAAS;IAAU,mBAAmB;IAAO,OAAO;GAAK,CAAC;EAClG;EACA,MAAM,IAAI,MAAM,sBAAsB,IAAI,OAAO;CACnD,SAAS,OAAO;EACd,MAAM,QAAQ,QAAQ,KAAK;EAC3B,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC,CAAC,mBAAmB,OAAO,MAAM,OAAO,IAAI,IAAI;GAAE,QAAQ;GAAW,eAAe;GAAM,OAAO,wFAAwF,MAAM;EAAU,CAAC;EAC/N,IAAI,MAAM,SAAS,2BAA2B,OAAO,MAAM,OAAO,IAAI,IAAI;GAAE,QAAQ;GAAW,eAAe;GAAM,gBAAgB,MAAM;GAAS,OAAO,MAAM;EAAQ,CAAC;EACzK,IAAI,QAAQ,SAAS,OAAO,MAAM,OAAO,IAAI,IAAI;GAAE,QAAQ;GAAW,UAAU;IAAE,GAAG;KAAW,IAAI,QAAQ,IAAI,SAAS,IAAI,UAAU;GAAE;GAAG,QAAQ,KAAK,IAAI;GAAG,OAAO,MAAM;EAAQ,CAAC;EACtL,IAAI,MAAM,SAAS,yBAAyB,MAAM,cAAc,OAAO,MAAM,OAAO,IAAI,IAAI;GAAE,QAAQ;GAAW,eAAe;IAAE,MAAM;IAAgB,OAAO,IAAI;IAAO,cAAc,MAAM;GAAa;GAAG,UAAU,EAAE,GAAG,IAAI,SAAS;GAAG,QAAQ,KAAK,IAAI,IAAI,OAAO;GAAQ,OAAO,MAAM;EAAQ,CAAC;EACvS,IAAI,CAAC,gBAAgB,OAAO,MAAM,OAAO,IAAI,IAAI;GAAE,QAAQ;GAAW,eAAe;GAAM,UAAU,EAAE,GAAG,IAAI,SAAS;GAAG,QAAQ,KAAK,IAAI;GAAG,OAAO,MAAM;EAAQ,CAAC;EAEpK,IADiB,MAAM,SAAS,YAAY,MAAM,SAAS,WAAW,OAAO,KAAM,qDAAqD,KAAK,MAAM,QAAQ,EAAE,GAChJ,OAAO,MAAM,OAAO,IAAI,IAAI;GAAE,QAAQ;GAAW,OAAO,MAAM;EAAQ,CAAC;EACpF,MAAM,UAAU,SAAS,IAAI,UAAU;EACvC,MAAM,YAAY,MAAM,SAAS,YAAY,WAAW,OAAO;EAC/D,IAAI,IAAI,UAAU,YAAa,IAAI,UAAU,aAAa,MAAM,SAAS,oBAAqB,OAAO,MAAM,OAAO,IAAI,IAAI;GAAE,GAAG,OAAO;IAAE,GAAG;IAAK;GAAS,GAAG,MAAM,OAAO;GAAG,QAAQ,YAAY,WAAW;GAAW,QAAQ,KAAK,IAAI,IAAI,OAAO,eAAe;EAAQ,CAAC;EAC1Q,OAAO,MAAM,OAAO,IAAI,IAAI;GAAE,QAAQ,YAAY,WAAW;GAAW,OAAO,MAAM;GAAS,UAAU,MAAM;GAAS,QAAQ,KAAK,IAAI,IAAI,OAAO,eAAe;EAAQ,CAAC;CAC7K;AACF"}
|
package/dist/scheduler.js
CHANGED
|
@@ -35,12 +35,10 @@ async function drainCommandGroups(store) {
|
|
|
35
35
|
if (failure) throw failure;
|
|
36
36
|
}
|
|
37
37
|
async function runStep(store, config, id, options = {}) {
|
|
38
|
-
if (options.buildOnly && (config.allowSubmit || config.allowRelease)) throw new Error("--build-only refuses configurations with upload or release enabled");
|
|
39
38
|
store.acquire();
|
|
40
39
|
try {
|
|
41
40
|
const initial = store.get(id);
|
|
42
41
|
if (initial.turn) throw new Error("An active host turn must be completed or abandoned before a deterministic step");
|
|
43
|
-
if (options.buildOnly && (initial.config.allowSubmit || initial.config.allowRelease)) throw new Error("--build-only refuses this task with snapshotted publication permission");
|
|
44
42
|
await drainCommandGroups(store);
|
|
45
43
|
if (!initial.groups.length && !options.signal?.aborted) {
|
|
46
44
|
if ([
|
|
@@ -55,7 +53,6 @@ async function runStep(store, config, id, options = {}) {
|
|
|
55
53
|
"build",
|
|
56
54
|
"review"
|
|
57
55
|
].includes(current.stage)) return false;
|
|
58
|
-
if (options.buildOnly && (current.config.allowSubmit || current.config.allowRelease)) throw new Error("--build-only refuses this task with snapshotted publication permission");
|
|
59
56
|
return true;
|
|
60
57
|
}, excluded);
|
|
61
58
|
if (job) try {
|
package/dist/scheduler.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scheduler.js","names":[],"sources":["../src/scheduler.ts"],"sourcesContent":["import { executeStep } from './runner.js';\nimport { terminateOwnedProcessGroup } from './process.js';\nimport { toError, type Config, type Job } from './schemas.js';\nimport type { Store } from './store.js';\n\nasync function drainCommandGroups(store: Store): Promise<void> {\n let failure: Error | undefined;\n for (const job of store.list()) {\n const groups: number[] = [], commands: Job['commands'] = {};\n let manualRecovery = job.manualRecovery ?? null;\n for (const pid of job.groups) {\n const command = job.commands[pid];\n try { await terminateOwnedProcessGroup(pid, command?.identity); }\n catch (cause) {\n const error = toError(cause);\n failure ??= error;\n manualRecovery ??= error.message;\n groups.push(pid);\n if (command) commands[pid] = command;\n }\n }\n if (job.groups.length || manualRecovery) {\n store.update(job.id, {\n groups, commands, recoveryStage: groups.length ? job.recoveryStage ?? job.stage : undefined,\n ...(manualRecovery ? { status: 'blocked', blockedReason: null, manualRecovery, error: manualRecovery } : {}),\n });\n }\n if (manualRecovery) failure ??= Object.assign(new Error(manualRecovery), { code: 'PROCESS_CLEANUP_BLOCKED' });\n }\n if (failure) throw failure;\n}\n\nexport async function runStep(store: Store, config: Config, id: string, options: { signal?: AbortSignal; buildOnly?: boolean } = {}): Promise<Job> {\n
|
|
1
|
+
{"version":3,"file":"scheduler.js","names":[],"sources":["../src/scheduler.ts"],"sourcesContent":["import { executeStep } from './runner.js';\nimport { terminateOwnedProcessGroup } from './process.js';\nimport { toError, type Config, type Job } from './schemas.js';\nimport type { Store } from './store.js';\n\nasync function drainCommandGroups(store: Store): Promise<void> {\n let failure: Error | undefined;\n for (const job of store.list()) {\n const groups: number[] = [], commands: Job['commands'] = {};\n let manualRecovery = job.manualRecovery ?? null;\n for (const pid of job.groups) {\n const command = job.commands[pid];\n try { await terminateOwnedProcessGroup(pid, command?.identity); }\n catch (cause) {\n const error = toError(cause);\n failure ??= error;\n manualRecovery ??= error.message;\n groups.push(pid);\n if (command) commands[pid] = command;\n }\n }\n if (job.groups.length || manualRecovery) {\n store.update(job.id, {\n groups, commands, recoveryStage: groups.length ? job.recoveryStage ?? job.stage : undefined,\n ...(manualRecovery ? { status: 'blocked', blockedReason: null, manualRecovery, error: manualRecovery } : {}),\n });\n }\n if (manualRecovery) failure ??= Object.assign(new Error(manualRecovery), { code: 'PROCESS_CLEANUP_BLOCKED' });\n }\n if (failure) throw failure;\n}\n\nexport async function runStep(store: Store, config: Config, id: string, options: { signal?: AbortSignal; buildOnly?: boolean } = {}): Promise<Job> {\n store.acquire();\n try {\n const initial = store.get(id);\n if (initial.turn) throw new Error('An active host turn must be completed or abandoned before a deterministic step');\n // A crashed invocation may still own children even though its queue lock is free.\n // Drain them before shared Flutter/Apple tooling can be used by any new stage.\n await drainCommandGroups(store);\n if (!initial.groups.length && !options.signal?.aborted) {\n if (['research', 'build', 'review'].includes(initial.stage)) throw new Error(`Stage ${initial.stage} belongs to the host; use next and complete, not step`);\n const excluded = new Set(store.list().filter(job => job.id !== id).map(job => job.id));\n const job = store.next(current => {\n if (current.id !== id || current.turn || ['research', 'build', 'review'].includes(current.stage)) return false;\n return true;\n }, excluded);\n if (job) {\n try { await executeStep(store, job, { signal: options.signal }); }\n catch (cause) {\n store.update(id, { stage: job.stage, status: 'blocked', blockedReason: null, error: `Stage ${job.stage} stopped unexpectedly: ${toError(cause).message}` });\n }\n }\n }\n } finally {\n try { await drainCommandGroups(store); }\n finally { store.release(); }\n }\n return store.get(id);\n}\n"],"mappings":";;;;AAKA,eAAe,mBAAmB,OAA6B;CAC7D,IAAI;CACJ,KAAK,MAAM,OAAO,MAAM,KAAK,GAAG;EAC9B,MAAM,SAAmB,CAAC,GAAG,WAA4B,CAAC;EAC1D,IAAI,iBAAiB,IAAI,kBAAkB;EAC3C,KAAK,MAAM,OAAO,IAAI,QAAQ;GAC5B,MAAM,UAAU,IAAI,SAAS;GAC7B,IAAI;IAAE,MAAM,2BAA2B,KAAK,SAAS,QAAQ;GAAG,SACzD,OAAO;IACZ,MAAM,QAAQ,QAAQ,KAAK;IAC3B,YAAY;IACZ,mBAAmB,MAAM;IACzB,OAAO,KAAK,GAAG;IACf,IAAI,SAAS,SAAS,OAAO;GAC/B;EACF;EACA,IAAI,IAAI,OAAO,UAAU,gBACvB,MAAM,OAAO,IAAI,IAAI;GACnB;GAAQ;GAAU,eAAe,OAAO,SAAS,IAAI,iBAAiB,IAAI,QAAQ,KAAA;GAClF,GAAI,iBAAiB;IAAE,QAAQ;IAAW,eAAe;IAAM;IAAgB,OAAO;GAAe,IAAI,CAAC;EAC5G,CAAC;EAEH,IAAI,gBAAgB,YAAY,OAAO,OAAO,IAAI,MAAM,cAAc,GAAG,EAAE,MAAM,0BAA0B,CAAC;CAC9G;CACA,IAAI,SAAS,MAAM;AACrB;AAEA,eAAsB,QAAQ,OAAc,QAAgB,IAAY,UAAyD,CAAC,GAAiB;CACjJ,MAAM,QAAQ;CACd,IAAI;EACF,MAAM,UAAU,MAAM,IAAI,EAAE;EAC5B,IAAI,QAAQ,MAAM,MAAM,IAAI,MAAM,gFAAgF;EAGlH,MAAM,mBAAmB,KAAK;EAC9B,IAAI,CAAC,QAAQ,OAAO,UAAU,CAAC,QAAQ,QAAQ,SAAS;GACtD,IAAI;IAAC;IAAY;IAAS;GAAQ,CAAC,CAAC,SAAS,QAAQ,KAAK,GAAG,MAAM,IAAI,MAAM,SAAS,QAAQ,MAAM,sDAAsD;GAC1J,MAAM,WAAW,IAAI,IAAI,MAAM,KAAK,CAAC,CAAC,QAAO,QAAO,IAAI,OAAO,EAAE,CAAC,CAAC,KAAI,QAAO,IAAI,EAAE,CAAC;GACrF,MAAM,MAAM,MAAM,MAAK,YAAW;IAChC,IAAI,QAAQ,OAAO,MAAM,QAAQ,QAAQ;KAAC;KAAY;KAAS;IAAQ,CAAC,CAAC,SAAS,QAAQ,KAAK,GAAG,OAAO;IACzG,OAAO;GACT,GAAG,QAAQ;GACX,IAAI,KACF,IAAI;IAAE,MAAM,YAAY,OAAO,KAAK,EAAE,QAAQ,QAAQ,OAAO,CAAC;GAAG,SAC1D,OAAO;IACZ,MAAM,OAAO,IAAI;KAAE,OAAO,IAAI;KAAO,QAAQ;KAAW,eAAe;KAAM,OAAO,SAAS,IAAI,MAAM,yBAAyB,QAAQ,KAAK,CAAC,CAAC;IAAU,CAAC;GAC5J;EAEJ;CACF,UAAU;EACR,IAAI;GAAE,MAAM,mBAAmB,KAAK;EAAG,UAC/B;GAAE,MAAM,QAAQ;EAAG;CAC7B;CACA,OAAO,MAAM,IAAI,EAAE;AACrB"}
|
package/dist/schemas.js
CHANGED
|
@@ -1,14 +1,47 @@
|
|
|
1
1
|
import { AppleReceiptSchema } from "./apple-types.js";
|
|
2
|
+
import { validateMyGoPackaging } from "./mygo-build.js";
|
|
2
3
|
import { z } from "zod";
|
|
4
|
+
import "node:fs";
|
|
5
|
+
import { isAbsolute, win32 } from "node:path";
|
|
3
6
|
// src/schemas.ts
|
|
4
7
|
const text = z.string().min(1).refine((value) => value.trim().length > 0 && !value.includes("\0"), "Expected non-empty text without NUL characters");
|
|
5
8
|
const count = z.number().int().nonnegative().safe();
|
|
6
9
|
const positive = z.number().positive().finite();
|
|
7
10
|
const command = z.array(text).min(1);
|
|
11
|
+
function relativeProjectPath(value, allowRoot = false) {
|
|
12
|
+
if (allowRoot && value === ".") return true;
|
|
13
|
+
return !isAbsolute(value) && !win32.isAbsolute(value) && !/[\\:*?\[\]]/.test(value) && value.split("/").every((part) => part !== "" && part !== "." && part !== "..");
|
|
14
|
+
}
|
|
15
|
+
const FrameworkSchema = z.enum([
|
|
16
|
+
"flutter",
|
|
17
|
+
"android-java",
|
|
18
|
+
"swift",
|
|
19
|
+
"react-native",
|
|
20
|
+
"expo",
|
|
21
|
+
"uni-app",
|
|
22
|
+
"mygo"
|
|
23
|
+
]);
|
|
24
|
+
const PlatformSchema = z.enum([
|
|
25
|
+
"ios",
|
|
26
|
+
"android",
|
|
27
|
+
"macos"
|
|
28
|
+
]);
|
|
29
|
+
const ChannelSchema = z.enum([
|
|
30
|
+
"local",
|
|
31
|
+
"app-store",
|
|
32
|
+
"google-play"
|
|
33
|
+
]);
|
|
34
|
+
const PackageTargetSchema = z.enum([
|
|
35
|
+
"simulator",
|
|
36
|
+
"ipa",
|
|
37
|
+
"apk",
|
|
38
|
+
"aab",
|
|
39
|
+
"app",
|
|
40
|
+
"dmg"
|
|
41
|
+
]);
|
|
8
42
|
const AppleSpecSchema = z.strictObject({
|
|
9
43
|
appId: text.optional(),
|
|
10
44
|
bundleId: text.optional(),
|
|
11
|
-
version: text.optional(),
|
|
12
45
|
buildNumber: text.optional(),
|
|
13
46
|
locale: text.optional(),
|
|
14
47
|
description: text.optional(),
|
|
@@ -19,7 +52,6 @@ const AppleSpecSchema = z.strictObject({
|
|
|
19
52
|
copyright: text.optional(),
|
|
20
53
|
whatsNew: text.optional(),
|
|
21
54
|
storefrontCountry: text.optional(),
|
|
22
|
-
screenshotsDir: text.optional(),
|
|
23
55
|
manualSetupConfirmed: z.boolean().optional(),
|
|
24
56
|
contact: z.strictObject({
|
|
25
57
|
firstName: text.optional(),
|
|
@@ -28,12 +60,20 @@ const AppleSpecSchema = z.strictObject({
|
|
|
28
60
|
phone: text.optional()
|
|
29
61
|
}).optional()
|
|
30
62
|
});
|
|
31
|
-
const
|
|
63
|
+
const SpecObject = z.strictObject({
|
|
32
64
|
id: text.regex(/^[a-z][a-z0-9-]{1,62}$/),
|
|
33
65
|
name: text,
|
|
34
66
|
purpose: text,
|
|
35
67
|
audience: text,
|
|
36
|
-
framework:
|
|
68
|
+
framework: FrameworkSchema,
|
|
69
|
+
platform: PlatformSchema,
|
|
70
|
+
channel: ChannelSchema.default("local"),
|
|
71
|
+
version: text.default("1.0.0"),
|
|
72
|
+
project: z.strictObject({
|
|
73
|
+
sourceDir: text.optional(),
|
|
74
|
+
directory: text.refine((value) => relativeProjectPath(value, true), "project.directory must be a relative in-root directory without traversal").default(".")
|
|
75
|
+
}).optional(),
|
|
76
|
+
screenshotsDir: text.optional(),
|
|
37
77
|
differentiators: z.array(text).min(1),
|
|
38
78
|
acceptance: z.array(text).min(1),
|
|
39
79
|
constraints: z.array(text).optional(),
|
|
@@ -41,15 +81,69 @@ const SpecSchema = z.strictObject({
|
|
|
41
81
|
hiddenFeatures: z.literal(false).optional(),
|
|
42
82
|
reviewBypass: z.literal(false).optional()
|
|
43
83
|
});
|
|
44
|
-
|
|
84
|
+
function refineSpec(value, context) {
|
|
85
|
+
if (value.framework === "android-java" && value.platform !== "android") context.addIssue({
|
|
86
|
+
code: "custom",
|
|
87
|
+
path: ["platform"],
|
|
88
|
+
message: "android-java requires platform=android"
|
|
89
|
+
});
|
|
90
|
+
if (value.framework === "swift" && value.platform !== "ios") context.addIssue({
|
|
91
|
+
code: "custom",
|
|
92
|
+
path: ["platform"],
|
|
93
|
+
message: "swift requires platform=ios"
|
|
94
|
+
});
|
|
95
|
+
if (value.framework === "mygo" && value.platform !== "macos") context.addIssue({
|
|
96
|
+
code: "custom",
|
|
97
|
+
path: ["platform"],
|
|
98
|
+
message: "mygo requires platform=macos"
|
|
99
|
+
});
|
|
100
|
+
if (value.platform === "macos" && value.framework !== "mygo") context.addIssue({
|
|
101
|
+
code: "custom",
|
|
102
|
+
path: ["framework"],
|
|
103
|
+
message: "macos currently requires framework=mygo"
|
|
104
|
+
});
|
|
105
|
+
if (value.platform === "macos" && value.channel !== "local") context.addIssue({
|
|
106
|
+
code: "custom",
|
|
107
|
+
path: ["channel"],
|
|
108
|
+
message: "macos currently supports local delivery only"
|
|
109
|
+
});
|
|
110
|
+
if (value.channel === "app-store" && value.platform !== "ios") context.addIssue({
|
|
111
|
+
code: "custom",
|
|
112
|
+
path: ["channel"],
|
|
113
|
+
message: "app-store requires platform=ios"
|
|
114
|
+
});
|
|
115
|
+
if (value.channel === "google-play" && value.platform !== "android") context.addIssue({
|
|
116
|
+
code: "custom",
|
|
117
|
+
path: ["channel"],
|
|
118
|
+
message: "google-play requires platform=android"
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
const SpecSchema = SpecObject.superRefine(refineSpec);
|
|
122
|
+
const RequirementSchema = SpecObject.extend({ baseJobId: z.uuid().optional() }).superRefine((value, context) => {
|
|
123
|
+
refineSpec(value, context);
|
|
124
|
+
if (value.baseJobId && value.project?.sourceDir) context.addIssue({
|
|
125
|
+
code: "custom",
|
|
126
|
+
path: ["project", "sourceDir"],
|
|
127
|
+
message: "project.sourceDir and baseJobId are mutually exclusive"
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
const ObfuscationConfigSchema = z.strictObject({
|
|
131
|
+
command: z.array(command.element).min(1).default(["obfuscator"]),
|
|
132
|
+
configPath: text,
|
|
133
|
+
seed: text.optional()
|
|
134
|
+
});
|
|
45
135
|
const ConfigSchema = z.strictObject({
|
|
46
136
|
configPath: text.optional(),
|
|
47
137
|
stateDir: text,
|
|
48
138
|
workspaceRoot: text,
|
|
49
139
|
allowLocalExecution: z.boolean().default(false),
|
|
50
|
-
|
|
51
|
-
allowRelease: z.boolean().default(false),
|
|
140
|
+
allowCloudBuild: z.boolean().default(false),
|
|
52
141
|
executionEnv: z.array(text.regex(/^[A-Z][A-Z0-9_]*$/).refine((value) => !/^(ASC_|APPLE_|FASTLANE_|MATCH_)/.test(value), "Publisher credentials must not be passed to host or verification tools")).default([]),
|
|
142
|
+
isolation: z.strictObject({
|
|
143
|
+
mode: z.literal("macos-sandbox"),
|
|
144
|
+
readOnlyPaths: z.array(text).default([]),
|
|
145
|
+
network: z.enum(["deny", "allow"]).default("deny")
|
|
146
|
+
}).optional(),
|
|
53
147
|
timeoutMs: positive.default(9e5),
|
|
54
148
|
maxAttempts: positive.int().default(3),
|
|
55
149
|
maxHostTurns: positive.int().default(16),
|
|
@@ -67,31 +161,41 @@ const ConfigSchema = z.strictObject({
|
|
|
67
161
|
}),
|
|
68
162
|
toolchain: z.strictObject({ flutterSdk: text }).optional(),
|
|
69
163
|
apple: z.strictObject({ exportOptionsPlist: text.optional() }).optional(),
|
|
70
|
-
packageTarget:
|
|
71
|
-
executionWarning: text.optional()
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
});
|
|
81
|
-
if (value.allowRelease && !value.allowSubmit) context.addIssue({
|
|
164
|
+
packageTarget: PackageTargetSchema,
|
|
165
|
+
executionWarning: text.optional(),
|
|
166
|
+
obfuscation: ObfuscationConfigSchema.optional(),
|
|
167
|
+
packaging: z.strictObject({
|
|
168
|
+
commands: z.array(command).min(1),
|
|
169
|
+
artifactPath: text.refine((value) => relativeProjectPath(value), "artifactPath must be an exact project-relative file or directory without traversal or wildcards"),
|
|
170
|
+
provider: z.enum(["local", "cloud"]).default("local")
|
|
171
|
+
}).optional()
|
|
172
|
+
}).superRefine((value, context) => {
|
|
173
|
+
if (value.packaging?.provider === "cloud" && !value.allowCloudBuild) context.addIssue({
|
|
82
174
|
code: "custom",
|
|
83
|
-
path: ["
|
|
84
|
-
message: "
|
|
175
|
+
path: ["allowCloudBuild"],
|
|
176
|
+
message: "Cloud packaging requires explicit allowCloudBuild=true"
|
|
85
177
|
});
|
|
86
178
|
});
|
|
179
|
+
function validateJobConfig(spec, config) {
|
|
180
|
+
if (!{
|
|
181
|
+
ios: ["simulator", "ipa"],
|
|
182
|
+
android: ["apk", "aab"],
|
|
183
|
+
macos: ["app", "dmg"]
|
|
184
|
+
}[spec.platform].includes(config.packageTarget)) throw new Error(`packageTarget=${config.packageTarget} does not match platform=${spec.platform}`);
|
|
185
|
+
if (spec.channel === "google-play" && config.packageTarget !== "aab") throw new Error("Google Play requires packageTarget=aab");
|
|
186
|
+
if (config.toolchain && spec.framework !== "flutter") throw new Error("toolchain.flutterSdk is only supported for framework=flutter");
|
|
187
|
+
if (spec.framework !== "flutter" && !config.packaging) throw new Error(`${spec.framework} requires owner-configured packaging.commands and packaging.artifactPath`);
|
|
188
|
+
if (config.packaging?.provider === "cloud" && !config.allowCloudBuild) throw new Error("Cloud packaging requires explicit allowCloudBuild=true");
|
|
189
|
+
if (spec.platform === "macos" && (config.allowCloudBuild || config.packaging?.provider === "cloud")) throw new Error("macos currently supports local build-only delivery; notarization and uploads are not part of this tool");
|
|
190
|
+
if (spec.framework === "mygo") validateMyGoPackaging(config, spec.screenshotsDir);
|
|
191
|
+
}
|
|
87
192
|
const StageSchema = z.enum([
|
|
88
193
|
"research",
|
|
89
194
|
"build",
|
|
195
|
+
"obfuscate",
|
|
90
196
|
"verify",
|
|
91
197
|
"review",
|
|
92
|
-
"package"
|
|
93
|
-
"publish",
|
|
94
|
-
"monitor"
|
|
198
|
+
"package"
|
|
95
199
|
]);
|
|
96
200
|
const StatusSchema = z.enum([
|
|
97
201
|
"queued",
|
|
@@ -100,9 +204,7 @@ const StatusSchema = z.enum([
|
|
|
100
204
|
"blocked",
|
|
101
205
|
"failed",
|
|
102
206
|
"ready",
|
|
103
|
-
"built"
|
|
104
|
-
"approved",
|
|
105
|
-
"released"
|
|
207
|
+
"built"
|
|
106
208
|
]);
|
|
107
209
|
const ToolchainSchema = z.strictObject({
|
|
108
210
|
source: text,
|
|
@@ -124,10 +226,6 @@ const PrerequisiteSchema = z.strictObject({
|
|
|
124
226
|
});
|
|
125
227
|
const ResearchSchema = z.strictObject({
|
|
126
228
|
viable: z.boolean(),
|
|
127
|
-
policySources: z.array(z.strictObject({
|
|
128
|
-
rule: text,
|
|
129
|
-
url: z.url()
|
|
130
|
-
})),
|
|
131
229
|
distinctness: text,
|
|
132
230
|
risks: z.array(text).optional(),
|
|
133
231
|
plan: z.array(text).min(1)
|
|
@@ -141,21 +239,18 @@ const ReviewSchema = z.strictObject({
|
|
|
141
239
|
}))
|
|
142
240
|
});
|
|
143
241
|
const ArtifactSchema = z.strictObject({
|
|
144
|
-
kind: z.enum([
|
|
242
|
+
kind: z.enum([
|
|
243
|
+
"ios-simulator",
|
|
244
|
+
"ipa",
|
|
245
|
+
"apk",
|
|
246
|
+
"aab",
|
|
247
|
+
"macos-app",
|
|
248
|
+
"dmg"
|
|
249
|
+
]),
|
|
145
250
|
path: text,
|
|
146
251
|
digest: text.regex(/^[a-f0-9]{64}$/),
|
|
147
252
|
createdAt: z.iso.datetime()
|
|
148
253
|
});
|
|
149
|
-
const ApplePollResultSchema = z.strictObject({
|
|
150
|
-
status: z.enum([
|
|
151
|
-
"waiting",
|
|
152
|
-
"approved",
|
|
153
|
-
"rejected"
|
|
154
|
-
]),
|
|
155
|
-
detail: text,
|
|
156
|
-
distributionReady: z.boolean().optional(),
|
|
157
|
-
available: z.boolean().optional()
|
|
158
|
-
});
|
|
159
254
|
const InboxEntrySchema = z.strictObject({
|
|
160
255
|
source: text,
|
|
161
256
|
digest: text.nullable(),
|
|
@@ -197,6 +292,11 @@ const JobSchema = z.object({
|
|
|
197
292
|
baseJobId: z.uuid().optional(),
|
|
198
293
|
baseDigest: text.regex(/^[a-f0-9]{64}$/).optional(),
|
|
199
294
|
basePrepared: z.boolean().optional(),
|
|
295
|
+
automaticBase: z.literal(true).optional(),
|
|
296
|
+
sourceDirectory: text.refine(isAbsolute, "sourceDirectory must be absolute").optional(),
|
|
297
|
+
importDigest: text.regex(/^[a-f0-9]{64}$/).optional(),
|
|
298
|
+
importPrepared: z.boolean().optional(),
|
|
299
|
+
cloudBuildPending: z.boolean().optional(),
|
|
200
300
|
recoveryStage: StageSchema.optional(),
|
|
201
301
|
blockedReason: z.strictObject({
|
|
202
302
|
kind: z.literal("prerequisite"),
|
|
@@ -217,16 +317,28 @@ const JobSchema = z.object({
|
|
|
217
317
|
verifiedDependencyDigest: text.regex(/^[a-f0-9]{64}$/).nullable().optional(),
|
|
218
318
|
screenshotDigest: text.nullable().optional(),
|
|
219
319
|
verifiedAt: text.optional(),
|
|
320
|
+
obfuscationBase: z.strictObject({
|
|
321
|
+
digest: text.regex(/^[a-f0-9]{64}$/),
|
|
322
|
+
path: text
|
|
323
|
+
}).optional(),
|
|
324
|
+
obfuscationDigest: text.regex(/^[a-f0-9]{64}$/).optional(),
|
|
325
|
+
obfuscationReport: z.strictObject({
|
|
326
|
+
changedFiles: count,
|
|
327
|
+
transforms: z.record(text, count),
|
|
328
|
+
skipped: z.strictObject({
|
|
329
|
+
generated: count,
|
|
330
|
+
unsupported: count
|
|
331
|
+
})
|
|
332
|
+
}).optional(),
|
|
220
333
|
review: ReviewSchema.nullable().optional(),
|
|
221
334
|
ipaPath: text.nullable().optional(),
|
|
222
335
|
archiveDigest: text.nullable().optional(),
|
|
223
336
|
artifact: ArtifactSchema.nullable().optional(),
|
|
224
|
-
appleReview: ApplePollResultSchema.optional(),
|
|
225
337
|
externalChecks: z.unknown().optional()
|
|
226
338
|
}).passthrough();
|
|
227
339
|
function toError(value) {
|
|
228
340
|
return value instanceof Error ? value : new Error(String(value));
|
|
229
341
|
}
|
|
230
|
-
export {
|
|
342
|
+
export { AppleSpecSchema, ArtifactSchema, ChannelSchema, CommandMetadataSchema, ConfigSchema, FrameworkSchema, HostStageSchema, HostTurnSchema, InboxEntrySchema, JobSchema, ObfuscationConfigSchema, PackageTargetSchema, PlatformSchema, PrerequisiteSchema, ProcessIdentitySchema, RequirementSchema, ResearchSchema, ReviewSchema, SpecSchema, StageSchema, StatusSchema, ToolchainSchema, toError, validateJobConfig };
|
|
231
343
|
|
|
232
344
|
//# sourceMappingURL=schemas.js.map
|