apphx 0.0.0-stage → 1.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/LICENSE +21 -0
- package/README.md +181 -2
- package/dist/apple-types.js +45 -0
- package/dist/apple-types.js.map +1 -0
- package/dist/apple.js +900 -0
- package/dist/apple.js.map +1 -0
- package/dist/cli.js +414 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.js +80 -0
- package/dist/config.js.map +1 -0
- package/dist/dependencies.js +157 -0
- package/dist/dependencies.js.map +1 -0
- package/dist/export-options.js +49 -0
- package/dist/export-options.js.map +1 -0
- package/dist/flutter.js +171 -0
- package/dist/flutter.js.map +1 -0
- package/dist/inbox.js +128 -0
- package/dist/inbox.js.map +1 -0
- package/dist/integrations.js +435 -0
- package/dist/integrations.js.map +1 -0
- package/dist/preflight.js +43 -0
- package/dist/preflight.js.map +1 -0
- package/dist/process.js +260 -0
- package/dist/process.js.map +1 -0
- package/dist/remote.js +143 -0
- package/dist/remote.js.map +1 -0
- package/dist/requirements.js +37 -0
- package/dist/requirements.js.map +1 -0
- package/dist/runner.js +722 -0
- package/dist/runner.js.map +1 -0
- package/dist/scheduler.js +83 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/schemas.js +232 -0
- package/dist/schemas.js.map +1 -0
- package/dist/store.js +361 -0
- package/dist/store.js.map +1 -0
- package/examples/factory.json +28 -0
- package/examples/luggage.json +39 -0
- package/examples/remote.json +6 -0
- package/package.json +30 -3
- package/skills/apple-app-factory/LICENSE +21 -0
- package/skills/apple-app-factory/SKILL.md +103 -0
- package/skills/apple-app-factory/resources/requirement.json +39 -0
- package/skills/apple-app-factory/resources/research-result.json +21 -0
- package/skills/apple-app-factory/resources/review-result.json +7 -0
|
@@ -0,0 +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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"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { toError } from "./schemas.js";
|
|
2
|
+
import { terminateOwnedProcessGroup } from "./process.js";
|
|
3
|
+
import { executeStep } from "./runner.js";
|
|
4
|
+
// src/scheduler.ts
|
|
5
|
+
async function drainCommandGroups(store) {
|
|
6
|
+
let failure;
|
|
7
|
+
for (const job of store.list()) {
|
|
8
|
+
const groups = [], commands = {};
|
|
9
|
+
let manualRecovery = job.manualRecovery ?? null;
|
|
10
|
+
for (const pid of job.groups) {
|
|
11
|
+
const command = job.commands[pid];
|
|
12
|
+
try {
|
|
13
|
+
await terminateOwnedProcessGroup(pid, command?.identity);
|
|
14
|
+
} catch (cause) {
|
|
15
|
+
const error = toError(cause);
|
|
16
|
+
failure ??= error;
|
|
17
|
+
manualRecovery ??= error.message;
|
|
18
|
+
groups.push(pid);
|
|
19
|
+
if (command) commands[pid] = command;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
if (job.groups.length || manualRecovery) store.update(job.id, {
|
|
23
|
+
groups,
|
|
24
|
+
commands,
|
|
25
|
+
recoveryStage: groups.length ? job.recoveryStage ?? job.stage : void 0,
|
|
26
|
+
...manualRecovery ? {
|
|
27
|
+
status: "blocked",
|
|
28
|
+
blockedReason: null,
|
|
29
|
+
manualRecovery,
|
|
30
|
+
error: manualRecovery
|
|
31
|
+
} : {}
|
|
32
|
+
});
|
|
33
|
+
if (manualRecovery) failure ??= Object.assign(new Error(manualRecovery), { code: "PROCESS_CLEANUP_BLOCKED" });
|
|
34
|
+
}
|
|
35
|
+
if (failure) throw failure;
|
|
36
|
+
}
|
|
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
|
+
store.acquire();
|
|
40
|
+
try {
|
|
41
|
+
const initial = store.get(id);
|
|
42
|
+
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
|
+
await drainCommandGroups(store);
|
|
45
|
+
if (!initial.groups.length && !options.signal?.aborted) {
|
|
46
|
+
if ([
|
|
47
|
+
"research",
|
|
48
|
+
"build",
|
|
49
|
+
"review"
|
|
50
|
+
].includes(initial.stage)) throw new Error(`Stage ${initial.stage} belongs to the host; use next and complete, not step`);
|
|
51
|
+
const excluded = new Set(store.list().filter((job) => job.id !== id).map((job) => job.id));
|
|
52
|
+
const job = store.next((current) => {
|
|
53
|
+
if (current.id !== id || current.turn || [
|
|
54
|
+
"research",
|
|
55
|
+
"build",
|
|
56
|
+
"review"
|
|
57
|
+
].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
|
+
return true;
|
|
60
|
+
}, excluded);
|
|
61
|
+
if (job) try {
|
|
62
|
+
await executeStep(store, job, { signal: options.signal });
|
|
63
|
+
} catch (cause) {
|
|
64
|
+
store.update(id, {
|
|
65
|
+
stage: job.stage,
|
|
66
|
+
status: "blocked",
|
|
67
|
+
blockedReason: null,
|
|
68
|
+
error: `Stage ${job.stage} stopped unexpectedly: ${toError(cause).message}`
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
} finally {
|
|
73
|
+
try {
|
|
74
|
+
await drainCommandGroups(store);
|
|
75
|
+
} finally {
|
|
76
|
+
store.release();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return store.get(id);
|
|
80
|
+
}
|
|
81
|
+
export { runStep };
|
|
82
|
+
|
|
83
|
+
//# sourceMappingURL=scheduler.js.map
|
|
@@ -0,0 +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 if (options.buildOnly && (config.allowSubmit || config.allowRelease)) throw new Error('--build-only refuses configurations with upload or release enabled');\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 if (options.buildOnly && (initial.config.allowSubmit || initial.config.allowRelease)) throw new Error('--build-only refuses this task with snapshotted publication permission');\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 if (options.buildOnly && (current.config.allowSubmit || current.config.allowRelease)) throw new Error('--build-only refuses this task with snapshotted publication permission');\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,IAAI,QAAQ,cAAc,OAAO,eAAe,OAAO,eAAe,MAAM,IAAI,MAAM,oEAAoE;CAC1J,MAAM,QAAQ;CACd,IAAI;EACF,MAAM,UAAU,MAAM,IAAI,EAAE;EAC5B,IAAI,QAAQ,MAAM,MAAM,IAAI,MAAM,gFAAgF;EAClH,IAAI,QAAQ,cAAc,QAAQ,OAAO,eAAe,QAAQ,OAAO,eAAe,MAAM,IAAI,MAAM,wEAAwE;EAG9K,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,IAAI,QAAQ,cAAc,QAAQ,OAAO,eAAe,QAAQ,OAAO,eAAe,MAAM,IAAI,MAAM,wEAAwE;IAC9K,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
ADDED
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { AppleReceiptSchema } from "./apple-types.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
// src/schemas.ts
|
|
4
|
+
const text = z.string().min(1).refine((value) => value.trim().length > 0 && !value.includes("\0"), "Expected non-empty text without NUL characters");
|
|
5
|
+
const count = z.number().int().nonnegative().safe();
|
|
6
|
+
const positive = z.number().positive().finite();
|
|
7
|
+
const command = z.array(text).min(1);
|
|
8
|
+
const AppleSpecSchema = z.strictObject({
|
|
9
|
+
appId: text.optional(),
|
|
10
|
+
bundleId: text.optional(),
|
|
11
|
+
version: text.optional(),
|
|
12
|
+
buildNumber: text.optional(),
|
|
13
|
+
locale: text.optional(),
|
|
14
|
+
description: text.optional(),
|
|
15
|
+
keywords: text.optional(),
|
|
16
|
+
supportUrl: text.optional(),
|
|
17
|
+
privacyPolicyUrl: text.optional(),
|
|
18
|
+
reviewNotes: text.optional(),
|
|
19
|
+
copyright: text.optional(),
|
|
20
|
+
whatsNew: text.optional(),
|
|
21
|
+
storefrontCountry: text.optional(),
|
|
22
|
+
screenshotsDir: text.optional(),
|
|
23
|
+
manualSetupConfirmed: z.boolean().optional(),
|
|
24
|
+
contact: z.strictObject({
|
|
25
|
+
firstName: text.optional(),
|
|
26
|
+
lastName: text.optional(),
|
|
27
|
+
email: text.optional(),
|
|
28
|
+
phone: text.optional()
|
|
29
|
+
}).optional()
|
|
30
|
+
});
|
|
31
|
+
const SpecSchema = z.strictObject({
|
|
32
|
+
id: text.regex(/^[a-z][a-z0-9-]{1,62}$/),
|
|
33
|
+
name: text,
|
|
34
|
+
purpose: text,
|
|
35
|
+
audience: text,
|
|
36
|
+
framework: z.literal("flutter"),
|
|
37
|
+
differentiators: z.array(text).min(1),
|
|
38
|
+
acceptance: z.array(text).min(1),
|
|
39
|
+
constraints: z.array(text).optional(),
|
|
40
|
+
apple: AppleSpecSchema.optional(),
|
|
41
|
+
hiddenFeatures: z.literal(false).optional(),
|
|
42
|
+
reviewBypass: z.literal(false).optional()
|
|
43
|
+
});
|
|
44
|
+
const RequirementSchema = SpecSchema.extend({ baseJobId: z.uuid().optional() });
|
|
45
|
+
const ConfigSchema = z.strictObject({
|
|
46
|
+
configPath: text.optional(),
|
|
47
|
+
stateDir: text,
|
|
48
|
+
workspaceRoot: text,
|
|
49
|
+
allowLocalExecution: z.boolean().default(false),
|
|
50
|
+
allowSubmit: z.boolean().default(false),
|
|
51
|
+
allowRelease: z.boolean().default(false),
|
|
52
|
+
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([]),
|
|
53
|
+
timeoutMs: positive.default(9e5),
|
|
54
|
+
maxAttempts: positive.int().default(3),
|
|
55
|
+
maxHostTurns: positive.int().default(16),
|
|
56
|
+
maxJobHours: positive.default(24),
|
|
57
|
+
retryDelayMs: positive.default(3e4),
|
|
58
|
+
pollMs: positive.default(3e5),
|
|
59
|
+
inbox: z.strictObject({
|
|
60
|
+
directory: text,
|
|
61
|
+
pollMs: positive.default(2e3)
|
|
62
|
+
}).optional(),
|
|
63
|
+
verification: z.strictObject({
|
|
64
|
+
prerequisites: z.array(command).default([]),
|
|
65
|
+
checks: z.array(command).min(1),
|
|
66
|
+
runtime: z.array(command).min(1)
|
|
67
|
+
}),
|
|
68
|
+
toolchain: z.strictObject({ flutterSdk: text }).optional(),
|
|
69
|
+
apple: z.strictObject({ exportOptionsPlist: text.optional() }).optional(),
|
|
70
|
+
packageTarget: z.enum(["simulator", "ipa"]).optional(),
|
|
71
|
+
executionWarning: text.optional()
|
|
72
|
+
}).transform((value) => ({
|
|
73
|
+
...value,
|
|
74
|
+
packageTarget: value.packageTarget ?? (value.allowSubmit ? "ipa" : "simulator")
|
|
75
|
+
})).superRefine((value, context) => {
|
|
76
|
+
if (value.allowSubmit && value.packageTarget !== "ipa") context.addIssue({
|
|
77
|
+
code: "custom",
|
|
78
|
+
path: ["packageTarget"],
|
|
79
|
+
message: "Submission requires packageTarget=ipa; simulator builds cannot be uploaded"
|
|
80
|
+
});
|
|
81
|
+
if (value.allowRelease && !value.allowSubmit) context.addIssue({
|
|
82
|
+
code: "custom",
|
|
83
|
+
path: ["allowRelease"],
|
|
84
|
+
message: "allowRelease requires allowSubmit"
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
const StageSchema = z.enum([
|
|
88
|
+
"research",
|
|
89
|
+
"build",
|
|
90
|
+
"verify",
|
|
91
|
+
"review",
|
|
92
|
+
"package",
|
|
93
|
+
"publish",
|
|
94
|
+
"monitor"
|
|
95
|
+
]);
|
|
96
|
+
const StatusSchema = z.enum([
|
|
97
|
+
"queued",
|
|
98
|
+
"running",
|
|
99
|
+
"waiting",
|
|
100
|
+
"blocked",
|
|
101
|
+
"failed",
|
|
102
|
+
"ready",
|
|
103
|
+
"built",
|
|
104
|
+
"approved",
|
|
105
|
+
"released"
|
|
106
|
+
]);
|
|
107
|
+
const ToolchainSchema = z.strictObject({
|
|
108
|
+
source: text,
|
|
109
|
+
frameworkRevision: text,
|
|
110
|
+
engineRevision: text,
|
|
111
|
+
ready: z.boolean()
|
|
112
|
+
});
|
|
113
|
+
const ProcessIdentitySchema = z.strictObject({ token: text });
|
|
114
|
+
const CommandMetadataSchema = z.strictObject({
|
|
115
|
+
deadline: z.number().finite(),
|
|
116
|
+
identity: ProcessIdentitySchema,
|
|
117
|
+
termAt: z.number().finite().optional(),
|
|
118
|
+
killAt: z.number().finite().optional()
|
|
119
|
+
});
|
|
120
|
+
const PrerequisiteSchema = z.strictObject({
|
|
121
|
+
argv: z.array(text).optional(),
|
|
122
|
+
reason: text,
|
|
123
|
+
path: text.optional()
|
|
124
|
+
});
|
|
125
|
+
const ResearchSchema = z.strictObject({
|
|
126
|
+
viable: z.boolean(),
|
|
127
|
+
policySources: z.array(z.strictObject({
|
|
128
|
+
rule: text,
|
|
129
|
+
url: z.url()
|
|
130
|
+
})),
|
|
131
|
+
distinctness: text,
|
|
132
|
+
risks: z.array(text).optional(),
|
|
133
|
+
plan: z.array(text).min(1)
|
|
134
|
+
});
|
|
135
|
+
const ReviewSchema = z.strictObject({
|
|
136
|
+
approved: z.boolean(),
|
|
137
|
+
findings: z.array(text),
|
|
138
|
+
acceptanceEvidence: z.array(z.strictObject({
|
|
139
|
+
requirement: text,
|
|
140
|
+
evidence: text
|
|
141
|
+
}))
|
|
142
|
+
});
|
|
143
|
+
const ArtifactSchema = z.strictObject({
|
|
144
|
+
kind: z.enum(["ios-simulator", "ipa"]),
|
|
145
|
+
path: text,
|
|
146
|
+
digest: text.regex(/^[a-f0-9]{64}$/),
|
|
147
|
+
createdAt: z.iso.datetime()
|
|
148
|
+
});
|
|
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
|
+
const InboxEntrySchema = z.strictObject({
|
|
160
|
+
source: text,
|
|
161
|
+
digest: text.nullable(),
|
|
162
|
+
status: z.enum(["accepted", "error"]),
|
|
163
|
+
jobId: text.nullable(),
|
|
164
|
+
error: z.string().nullable(),
|
|
165
|
+
observedAt: z.number().finite()
|
|
166
|
+
});
|
|
167
|
+
const HostStageSchema = z.enum([
|
|
168
|
+
"research",
|
|
169
|
+
"build",
|
|
170
|
+
"review"
|
|
171
|
+
]);
|
|
172
|
+
const HostTurnSchema = z.strictObject({
|
|
173
|
+
id: z.uuid(),
|
|
174
|
+
stage: HostStageSchema,
|
|
175
|
+
createdAt: z.number().finite(),
|
|
176
|
+
contextDigest: text.regex(/^[a-f0-9]{64}$/)
|
|
177
|
+
});
|
|
178
|
+
const JobSchema = z.object({
|
|
179
|
+
id: text,
|
|
180
|
+
spec: SpecSchema,
|
|
181
|
+
requestSpec: SpecSchema.nullable(),
|
|
182
|
+
requestSpecError: text.nullable().default(null),
|
|
183
|
+
config: ConfigSchema,
|
|
184
|
+
stage: StageSchema,
|
|
185
|
+
status: StatusSchema,
|
|
186
|
+
createdAt: z.number().finite(),
|
|
187
|
+
updatedAt: z.number().finite(),
|
|
188
|
+
nextAt: z.number().finite(),
|
|
189
|
+
attempts: z.partialRecord(StageSchema, count),
|
|
190
|
+
hostTurns: count,
|
|
191
|
+
turn: HostTurnSchema.nullable().optional(),
|
|
192
|
+
groups: z.array(z.number().int()),
|
|
193
|
+
commands: z.record(z.string(), CommandMetadataSchema).default({}),
|
|
194
|
+
receipt: AppleReceiptSchema,
|
|
195
|
+
logs: z.array(text),
|
|
196
|
+
workspace: text,
|
|
197
|
+
baseJobId: z.uuid().optional(),
|
|
198
|
+
baseDigest: text.regex(/^[a-f0-9]{64}$/).optional(),
|
|
199
|
+
basePrepared: z.boolean().optional(),
|
|
200
|
+
recoveryStage: StageSchema.optional(),
|
|
201
|
+
blockedReason: z.strictObject({
|
|
202
|
+
kind: z.literal("prerequisite"),
|
|
203
|
+
stage: StageSchema,
|
|
204
|
+
prerequisite: PrerequisiteSchema
|
|
205
|
+
}).nullable().optional(),
|
|
206
|
+
manualRecovery: z.string().nullable().optional(),
|
|
207
|
+
error: z.string().nullable().optional(),
|
|
208
|
+
feedback: z.string().optional(),
|
|
209
|
+
research: ResearchSchema.optional(),
|
|
210
|
+
policyEvidence: z.strictObject({
|
|
211
|
+
url: z.url(),
|
|
212
|
+
fetchedAt: text,
|
|
213
|
+
sha256: text
|
|
214
|
+
}).optional(),
|
|
215
|
+
toolchain: ToolchainSchema.optional(),
|
|
216
|
+
verifiedDigest: text.nullable().optional(),
|
|
217
|
+
verifiedDependencyDigest: text.regex(/^[a-f0-9]{64}$/).nullable().optional(),
|
|
218
|
+
screenshotDigest: text.nullable().optional(),
|
|
219
|
+
verifiedAt: text.optional(),
|
|
220
|
+
review: ReviewSchema.nullable().optional(),
|
|
221
|
+
ipaPath: text.nullable().optional(),
|
|
222
|
+
archiveDigest: text.nullable().optional(),
|
|
223
|
+
artifact: ArtifactSchema.nullable().optional(),
|
|
224
|
+
appleReview: ApplePollResultSchema.optional(),
|
|
225
|
+
externalChecks: z.unknown().optional()
|
|
226
|
+
}).passthrough();
|
|
227
|
+
function toError(value) {
|
|
228
|
+
return value instanceof Error ? value : new Error(String(value));
|
|
229
|
+
}
|
|
230
|
+
export { ApplePollResultSchema, AppleSpecSchema, ArtifactSchema, CommandMetadataSchema, ConfigSchema, HostStageSchema, HostTurnSchema, InboxEntrySchema, JobSchema, PrerequisiteSchema, ProcessIdentitySchema, RequirementSchema, ResearchSchema, ReviewSchema, SpecSchema, StageSchema, StatusSchema, ToolchainSchema, toError };
|
|
231
|
+
|
|
232
|
+
//# sourceMappingURL=schemas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemas.js","names":[],"sources":["../src/schemas.ts"],"sourcesContent":["import { z } from 'zod';\nimport { AppleReceiptSchema } from './apple-types.js';\n\nconst text = z.string().min(1).refine(value => value.trim().length > 0 && !value.includes('\\0'), 'Expected non-empty text without NUL characters');\nconst count = z.number().int().nonnegative().safe();\nconst positive = z.number().positive().finite();\nconst command = z.array(text).min(1);\n\n\nexport const AppleSpecSchema = z.strictObject({\n appId: text.optional(), bundleId: text.optional(), version: text.optional(), buildNumber: text.optional(), locale: text.optional(),\n description: text.optional(), keywords: text.optional(), supportUrl: text.optional(), privacyPolicyUrl: text.optional(), reviewNotes: text.optional(),\n copyright: text.optional(), whatsNew: text.optional(), storefrontCountry: text.optional(), screenshotsDir: text.optional(), manualSetupConfirmed: z.boolean().optional(),\n contact: z.strictObject({ firstName: text.optional(), lastName: text.optional(), email: text.optional(), phone: text.optional() }).optional(),\n});\nexport type AppleSpec = z.infer<typeof AppleSpecSchema>;\nexport const SpecSchema = z.strictObject({\n id: text.regex(/^[a-z][a-z0-9-]{1,62}$/), name: text, purpose: text, audience: text,\n framework: z.literal('flutter'), differentiators: z.array(text).min(1), acceptance: z.array(text).min(1),\n constraints: z.array(text).optional(), apple: AppleSpecSchema.optional(),\n hiddenFeatures: z.literal(false).optional(), reviewBypass: z.literal(false).optional(),\n});\nexport type Spec = z.infer<typeof SpecSchema>;\nexport const RequirementSchema = SpecSchema.extend({ baseJobId: z.uuid().optional() });\n\nexport const ConfigSchema = z.strictObject({\n configPath: text.optional(), stateDir: text, workspaceRoot: text,\n allowLocalExecution: z.boolean().default(false), allowSubmit: z.boolean().default(false), allowRelease: z.boolean().default(false),\n 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([]),\n timeoutMs: positive.default(900000), maxAttempts: positive.int().default(3), maxHostTurns: positive.int().default(16), maxJobHours: positive.default(24),\n retryDelayMs: positive.default(30000), pollMs: positive.default(300000),\n inbox: z.strictObject({ directory: text, pollMs: positive.default(2000) }).optional(),\n verification: z.strictObject({ prerequisites: z.array(command).default([]), checks: z.array(command).min(1), runtime: z.array(command).min(1) }),\n toolchain: z.strictObject({ flutterSdk: text }).optional(),\n apple: z.strictObject({ exportOptionsPlist: text.optional() }).optional(),\n packageTarget: z.enum(['simulator', 'ipa']).optional(), executionWarning: text.optional(),\n}).transform(value => ({ ...value, packageTarget: value.packageTarget ?? (value.allowSubmit ? 'ipa' as const : 'simulator' as const) })).superRefine((value, context) => {\n if (value.allowSubmit && value.packageTarget !== 'ipa') context.addIssue({ code: 'custom', path: ['packageTarget'], message: 'Submission requires packageTarget=ipa; simulator builds cannot be uploaded' });\n if (value.allowRelease && !value.allowSubmit) context.addIssue({ code: 'custom', path: ['allowRelease'], message: 'allowRelease requires allowSubmit' });\n});\nexport type Config = z.infer<typeof ConfigSchema>;\nexport const StageSchema = z.enum(['research', 'build', 'verify', 'review', 'package', 'publish', 'monitor']);\nexport type Stage = z.infer<typeof StageSchema>;\nexport const StatusSchema = z.enum(['queued', 'running', 'waiting', 'blocked', 'failed', 'ready', 'built', 'approved', 'released']);\nexport type Status = z.infer<typeof StatusSchema>;\nexport const ToolchainSchema = z.strictObject({ source: text, frameworkRevision: text, engineRevision: text, ready: z.boolean() });\nexport type Toolchain = z.infer<typeof ToolchainSchema>;\nexport const ProcessIdentitySchema = z.strictObject({ token: text });\nexport type ProcessIdentity = z.infer<typeof ProcessIdentitySchema>;\nexport const CommandMetadataSchema = z.strictObject({ deadline: z.number().finite(), identity: ProcessIdentitySchema, termAt: z.number().finite().optional(), killAt: z.number().finite().optional() });\nexport type CommandMetadata = z.infer<typeof CommandMetadataSchema>;\nexport const PrerequisiteSchema = z.strictObject({ argv: z.array(text).optional(), reason: text, path: text.optional() });\nexport type Prerequisite = z.infer<typeof PrerequisiteSchema>;\nexport const ResearchSchema = z.strictObject({\n viable: z.boolean(), policySources: z.array(z.strictObject({ rule: text, url: z.url() })), distinctness: text, risks: z.array(text).optional(), plan: z.array(text).min(1),\n});\nexport type Research = z.infer<typeof ResearchSchema>;\nexport const ReviewSchema = z.strictObject({ approved: z.boolean(), findings: z.array(text), acceptanceEvidence: z.array(z.strictObject({ requirement: text, evidence: text })) });\nexport type Review = z.infer<typeof ReviewSchema>;\nexport const ArtifactSchema = z.strictObject({ kind: z.enum(['ios-simulator', 'ipa']), path: text, digest: text.regex(/^[a-f0-9]{64}$/), createdAt: z.iso.datetime() });\nexport type Artifact = z.infer<typeof ArtifactSchema>;\nexport const ApplePollResultSchema = z.strictObject({ status: z.enum(['waiting', 'approved', 'rejected']), detail: text, distributionReady: z.boolean().optional(), available: z.boolean().optional() });\nexport const InboxEntrySchema = z.strictObject({\n source: text, digest: text.nullable(), status: z.enum(['accepted', 'error']), jobId: text.nullable(),\n error: z.string().nullable(), observedAt: z.number().finite(),\n});\nexport type InboxEntry = z.infer<typeof InboxEntrySchema>;\nexport const HostStageSchema = z.enum(['research', 'build', 'review']);\nexport type HostStage = z.infer<typeof HostStageSchema>;\nexport const HostTurnSchema = z.strictObject({\n id: z.uuid(), stage: HostStageSchema, createdAt: z.number().finite(), contextDigest: text.regex(/^[a-f0-9]{64}$/),\n});\nexport type HostTurn = z.infer<typeof HostTurnSchema>;\nexport const JobSchema = z.object({\n id: text, spec: SpecSchema, requestSpec: SpecSchema.nullable(), requestSpecError: text.nullable().default(null), config: ConfigSchema, stage: StageSchema, status: StatusSchema,\n createdAt: z.number().finite(), updatedAt: z.number().finite(), nextAt: z.number().finite(),\n attempts: z.partialRecord(StageSchema, count), hostTurns: count, turn: HostTurnSchema.nullable().optional(), groups: z.array(z.number().int()),\n commands: z.record(z.string(), CommandMetadataSchema).default({}), receipt: AppleReceiptSchema, logs: z.array(text), workspace: text,\n baseJobId: z.uuid().optional(), baseDigest: text.regex(/^[a-f0-9]{64}$/).optional(), basePrepared: z.boolean().optional(),\n recoveryStage: StageSchema.optional(),\n blockedReason: z.strictObject({ kind: z.literal('prerequisite'), stage: StageSchema, prerequisite: PrerequisiteSchema }).nullable().optional(),\n manualRecovery: z.string().nullable().optional(), error: z.string().nullable().optional(), feedback: z.string().optional(),\n research: ResearchSchema.optional(), policyEvidence: z.strictObject({ url: z.url(), fetchedAt: text, sha256: text }).optional(),\n toolchain: ToolchainSchema.optional(), verifiedDigest: text.nullable().optional(), verifiedDependencyDigest: text.regex(/^[a-f0-9]{64}$/).nullable().optional(), screenshotDigest: text.nullable().optional(), verifiedAt: text.optional(),\n review: ReviewSchema.nullable().optional(), ipaPath: text.nullable().optional(), archiveDigest: text.nullable().optional(), artifact: ArtifactSchema.nullable().optional(),\n appleReview: ApplePollResultSchema.optional(), externalChecks: z.unknown().optional(),\n}).passthrough();\nexport type Job = z.infer<typeof JobSchema>;\n\nexport type FactoryError = Error & { code?: string; syscall?: string; prerequisite?: Prerequisite; httpStatus?: number | null; outcome?: string; transient?: boolean };\nexport function toError(value: unknown): FactoryError {\n return value instanceof Error ? value : new Error(String(value));\n}\n"],"mappings":"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"}
|