apphx 2.0.1 → 2.1.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 +10 -8
- package/dist/cli.js +41 -11
- package/dist/cli.js.map +1 -1
- package/dist/config.js +4 -2
- package/dist/config.js.map +1 -1
- package/dist/integrations.js +154 -95
- package/dist/integrations.js.map +1 -1
- package/dist/notify.js +267 -0
- package/dist/notify.js.map +1 -0
- package/dist/runner.js +119 -20
- package/dist/runner.js.map +1 -1
- package/dist/schemas.js +57 -2
- package/dist/schemas.js.map +1 -1
- package/dist/vendor/obfuscator/dist/config.js +119 -6
- package/dist/vendor/obfuscator/dist/config.js.map +1 -1
- package/dist/vendor/obfuscator/dist/dfa.js +528 -0
- package/dist/vendor/obfuscator/dist/dfa.js.map +1 -0
- package/dist/vendor/obfuscator/dist/flutter.js +3266 -0
- package/dist/vendor/obfuscator/dist/flutter.js.map +1 -0
- package/dist/vendor/obfuscator/dist/image-utils.js +335 -0
- package/dist/vendor/obfuscator/dist/image-utils.js.map +1 -0
- package/dist/vendor/obfuscator/dist/junk.js +1501 -0
- package/dist/vendor/obfuscator/dist/junk.js.map +1 -0
- package/dist/vendor/obfuscator/dist/lexicon-data.js +972 -0
- package/dist/vendor/obfuscator/dist/lexicon-data.js.map +1 -0
- package/dist/vendor/obfuscator/dist/obfuscate.js +51 -2
- package/dist/vendor/obfuscator/dist/obfuscate.js.map +1 -1
- package/dist/vendor/obfuscator/dist/objc-symbols.js +1819 -0
- package/dist/vendor/obfuscator/dist/objc-symbols.js.map +1 -0
- package/dist/vendor/obfuscator/dist/project-identity.js +852 -0
- package/dist/vendor/obfuscator/dist/project-identity.js.map +1 -0
- package/dist/vendor/obfuscator/dist/string-encrypt.js +330 -0
- package/dist/vendor/obfuscator/dist/string-encrypt.js.map +1 -0
- package/examples/android-java.factory.json +40 -5
- package/examples/expo.factory.json +68 -5
- package/examples/flutter.factory.json +40 -4
- package/examples/luggage.json +1 -0
- package/examples/multi-role-agents.md +129 -0
- package/examples/mygo.factory.json +54 -4
- package/examples/queue-loop-demo.md +146 -0
- package/examples/react-native.factory.json +58 -5
- package/examples/roles.example.json +31 -0
- package/examples/swift.factory.json +60 -5
- package/examples/uni-app.factory.json +58 -5
- package/package.json +1 -1
- package/skills/apphx/SKILL.md +39 -4
- package/skills/apphx/resources/requirement.json +1 -0
- package/skills/apphx-obfuscator/LICENSE +21 -0
- package/skills/apphx-obfuscator/SKILL.md +72 -0
package/README.md
CHANGED
|
@@ -20,13 +20,15 @@ $apphx 接管我的 Java Android 项目,完成真实验收,只做本地构
|
|
|
20
20
|
|
|
21
21
|
其他宿主先用 `apphx hosts` 查看安装方式;通常为 `apphx install <host>`:
|
|
22
22
|
|
|
23
|
-
| 宿主 | 启动工作流 |
|
|
24
|
-
| --- | --- |
|
|
25
|
-
| Codex | `$apphx <需求>` |
|
|
26
|
-
| Claude Code / Cursor | `/apphx <需求>` |
|
|
27
|
-
| Pi | `/skill:apphx <需求>` |
|
|
28
|
-
| Gemini / OpenCode / DeepSeek | 请加载 apphx skill,随后描述需求 |
|
|
29
|
-
| Hermes | `apphx install hermes --global` 后使用 `/apphx <需求>` |
|
|
23
|
+
| 宿主 | 启动工作流 | 直接触发混淆 |
|
|
24
|
+
| --- | --- | --- |
|
|
25
|
+
| Codex | `$apphx <需求>` | `$apphx-obfuscator <需求>` |
|
|
26
|
+
| Claude Code / Cursor | `/apphx <需求>` | `/apphx-obfuscator <需求>` |
|
|
27
|
+
| Pi | `/skill:apphx <需求>` | `/skill:apphx-obfuscator <需求>` |
|
|
28
|
+
| Gemini / OpenCode / DeepSeek | 请加载 apphx skill,随后描述需求 | 请加载 apphx-obfuscator skill |
|
|
29
|
+
| Hermes | `apphx install hermes --global` 后使用 `/apphx <需求>` | 同上安装后使用 `/apphx-obfuscator <需求>` |
|
|
30
|
+
|
|
31
|
+
`apphx install <host>` 会同时安装 `apphx` 与 `apphx-obfuscator` 两个 skill;后者让 agent 直接运行确定性混淆器:`apphx obfuscator <project> --config <rules.json> [--framework <stack>] [--seed <text>]`,规则结构与流水线 `obfuscation` 阶段一致,覆盖 ObjC/Swift 符号改名、XOR 字符串加密、Flutter 符号/资源混淆、DFA 敏感词过滤、垃圾代码与清理、工程身份改名和图片变换。
|
|
30
32
|
|
|
31
33
|
项目本地安装 CLI 时,使用原包管理器的 `pnpm exec apphx`、`yarn exec apphx` 或 `npm exec --offline --package=apphx -- apphx`;Skill 不会替你下载 CLI。
|
|
32
34
|
|
|
@@ -65,7 +67,7 @@ apphx 只负责在本地产出并验证 iOS/Android/macOS 包;App Store / Goog
|
|
|
65
67
|
- **IPA 导出**:内置 Flutter 导出及配置中可识别的 `xcodebuild -exportArchive` 使用检查后的本地导出配置快照,拒绝 `destination=upload`。任意自定义脚本仍须信任审查;这不是脚本沙箱。
|
|
66
68
|
- **默认值与云构建**:不传技术栈时,`init` 默认 Flutter/iOS/simulator;`android-java` 默认 Android/APK,Expo 默认 iOS/IPA。远程云编译另需 `allowCloudBuild`;不确定的远程结果先对账,不自动重放。
|
|
67
69
|
- **升级旧数据**:先结束活跃任务,保留 `.factory`、配置和迁移备份。新需求显式带 `platform`,配置带 `packageTarget`;`version`、`screenshotsDir` 放在需求顶层。队列 v3 保留历史与回执、清除旧证明;重新验收后再继续。1.0 用户须在升级 CLI 前用原 `app-factory uninstall` 安全卸载未修改的旧 Skill,再安装新 `apphx` Skill;不要覆盖修改过的安装。
|
|
68
|
-
- **宿主与调度**:更新、卸载时保持原 `--project` / `--global` 作用域。Hermes 项目级安装还需你手动授予信任;定时任务应唤醒宿主、续跑同一任务并避免重叠,不能只定时执行 `next
|
|
70
|
+
- **宿主与调度**:更新、卸载时保持原 `--project` / `--global` 作用域。Hermes 项目级安装还需你手动授予信任;定时任务应唤醒宿主、续跑同一任务并避免重叠,不能只定时执行 `next`。多任务(单任务同理)在 agent 内循环用 `apphx next --any` 取最早到期的可推进任务:`host` 回合做完即 `complete`,`step` 执行一次 `apphx step JOB_ID`,重复直到 `idle`(附最早下次唤醒时间)。详见 [Hermes 调度文档](https://hermes-agent.nousresearch.com/docs/user-guide/features/cron)。
|
|
69
71
|
|
|
70
72
|
已安装的工作流需显式更新或卸载;这些操作不会删除应用代码、配置或任务数据:
|
|
71
73
|
|
package/dist/cli.js
CHANGED
|
@@ -8,12 +8,13 @@ import { Store } from "./store.js";
|
|
|
8
8
|
import { prepareIsolatedCommand, removeConfinedPath } from "./isolation.js";
|
|
9
9
|
import { assertProject, doctorCommands } from "./project-profiles.js";
|
|
10
10
|
import { invalidateVerification, verificationConfigChanged } from "./proof.js";
|
|
11
|
-
import { abandonTurn, completeTurn, nextTurn } from "./runner.js";
|
|
11
|
+
import { abandonTurn, completeTurn, nextQueueTurn, nextTurn } from "./runner.js";
|
|
12
12
|
import { runStep } from "./scheduler.js";
|
|
13
13
|
import { hosts, inspectIntegration, installIntegration, uninstallIntegration, updateIntegration } from "./integrations.js";
|
|
14
14
|
import { MAX_INPUT_BYTES, parseRequirement, readInputFile } from "./requirements.js";
|
|
15
15
|
import { scanInbox, submitRequirement } from "./inbox.js";
|
|
16
16
|
import { dispatchRemote } from "./remote.js";
|
|
17
|
+
import { notifyBuiltJobs, notifyJob } from "./notify.js";
|
|
17
18
|
import { existsSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs";
|
|
18
19
|
import { spawnSync } from "node:child_process";
|
|
19
20
|
import { dirname, join, resolve } from "node:path";
|
|
@@ -30,6 +31,7 @@ const view = (job) => ({
|
|
|
30
31
|
platform: job.spec.platform,
|
|
31
32
|
channel: job.spec.channel,
|
|
32
33
|
version: job.spec.version,
|
|
34
|
+
priority: job.spec.priority,
|
|
33
35
|
stage: job.stage,
|
|
34
36
|
status: job.status,
|
|
35
37
|
hostTurns: job.hostTurns,
|
|
@@ -297,7 +299,7 @@ const help = `apphx <command> [--config factory.json] [--build-only]
|
|
|
297
299
|
--package-target <target> simulator|ipa|apk|aab|app|dmg (MyGo app; Expo iOS ipa)
|
|
298
300
|
doctor [spec.json] Check configured prerequisites and optional stack tools
|
|
299
301
|
enqueue <spec.json|-> Persist requirements and return a task ID
|
|
300
|
-
next <id
|
|
302
|
+
next [<id>|--any] Resume a host turn, show the next deterministic action, or pick the next actionable queued task (--any)
|
|
301
303
|
complete <id> <turn> [json|-] Record research/review, or finish the host's build turn
|
|
302
304
|
abandon <id> <turn> Abandon a host turn without resetting its budget
|
|
303
305
|
step <id> Execute one obfuscation, verification or packaging stage
|
|
@@ -308,6 +310,7 @@ const help = `apphx <command> [--config factory.json] [--build-only]
|
|
|
308
310
|
scan [--observe] Validate or ingest inbox files; never start an agent
|
|
309
311
|
inbox Read durable intake results
|
|
310
312
|
reconcile-intake <id> <json|-> Restore a legacy request identity from original input
|
|
313
|
+
notify [<id>|--any] Email the author for built, gate-passed tasks (--any sweeps all unnotified)
|
|
311
314
|
remote <command> Call an installed Mac CLI over SSH (build-only)
|
|
312
315
|
obfuscator <project> Run the bundled deterministic obfuscator on a project copy
|
|
313
316
|
--config <file> Obfuscator options as JSON (required)
|
|
@@ -340,6 +343,7 @@ async function main() {
|
|
|
340
343
|
platform: { type: "string" },
|
|
341
344
|
"package-target": { type: "string" },
|
|
342
345
|
observe: { type: "boolean" },
|
|
346
|
+
any: { type: "boolean" },
|
|
343
347
|
version: {
|
|
344
348
|
type: "boolean",
|
|
345
349
|
short: "v"
|
|
@@ -380,13 +384,22 @@ async function main() {
|
|
|
380
384
|
"global"
|
|
381
385
|
],
|
|
382
386
|
enqueue: ["config", "build-only"],
|
|
383
|
-
next: [
|
|
387
|
+
next: [
|
|
388
|
+
"config",
|
|
389
|
+
"build-only",
|
|
390
|
+
"any"
|
|
391
|
+
],
|
|
384
392
|
complete: ["config", "build-only"],
|
|
385
393
|
abandon: ["config", "build-only"],
|
|
386
394
|
step: ["config", "build-only"],
|
|
387
395
|
status: ["config", "build-only"],
|
|
388
396
|
events: ["config", "build-only"],
|
|
389
397
|
retry: ["config", "build-only"],
|
|
398
|
+
notify: [
|
|
399
|
+
"config",
|
|
400
|
+
"build-only",
|
|
401
|
+
"any"
|
|
402
|
+
],
|
|
390
403
|
submit: ["config", "build-only"],
|
|
391
404
|
scan: [
|
|
392
405
|
"config",
|
|
@@ -435,14 +448,16 @@ async function main() {
|
|
|
435
448
|
}
|
|
436
449
|
if (command === "install" || command === "update" || command === "uninstall") {
|
|
437
450
|
arity(args, 1, 1, `${command} <host> [--project <directory> | --global]`);
|
|
438
|
-
|
|
451
|
+
(command === "install" ? installIntegration : command === "update" ? updateIntegration : uninstallIntegration)(args[0], scope);
|
|
452
|
+
print(["apphx", "apphx-obfuscator"].map((skill) => inspectIntegration(args[0], scope, skill)));
|
|
439
453
|
return;
|
|
440
454
|
}
|
|
441
455
|
if (command === "doctor" && values.host) {
|
|
442
456
|
arity(args, 0, 0, "doctor --host <host> [--project <directory> | --global]");
|
|
443
|
-
const
|
|
444
|
-
|
|
445
|
-
|
|
457
|
+
const host = values.host;
|
|
458
|
+
const results = ["apphx", "apphx-obfuscator"].map((skill) => inspectIntegration(host, scope, skill));
|
|
459
|
+
print(results);
|
|
460
|
+
if (!results[0].installed) process.exitCode = 2;
|
|
446
461
|
return;
|
|
447
462
|
}
|
|
448
463
|
if (command === "doctor" && (values.project || values.global)) throw new Error("--project and --global require doctor --host <host>");
|
|
@@ -591,10 +606,15 @@ async function main() {
|
|
|
591
606
|
arity(args, 1, 1, "events <id>");
|
|
592
607
|
print(store.events(args[0]));
|
|
593
608
|
} else if (command === "next") {
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
609
|
+
if (values.any) {
|
|
610
|
+
arity(args, 0, 0, "next --any");
|
|
611
|
+
print(await nextQueueTurn(store, { buildOnly }));
|
|
612
|
+
} else {
|
|
613
|
+
arity(args, 1, 1, "next <id>");
|
|
614
|
+
const result = await nextTurn(store, args[0], { buildOnly });
|
|
615
|
+
print(result);
|
|
616
|
+
if (result.job.status === "blocked" || result.job.status === "failed") process.exitCode = 2;
|
|
617
|
+
}
|
|
598
618
|
} else if (command === "complete") {
|
|
599
619
|
arity(args, 2, 3, "complete <id> <turn-id> [result.json|-]");
|
|
600
620
|
outcome(await completeTurn(store, args[0], args[1], args[2] ? inputJSON(args[2]) : void 0, { buildOnly }));
|
|
@@ -620,6 +640,16 @@ async function main() {
|
|
|
620
640
|
arity(args, 2, 2, "reconcile-intake <id> <original-spec.json|->");
|
|
621
641
|
const { spec, baseJobId } = parseRequirement(inputJSON(args[1]));
|
|
622
642
|
print(view(store.reconcileIntake(args[0], spec, baseJobId)));
|
|
643
|
+
} else if (command === "notify") {
|
|
644
|
+
if (values.any) {
|
|
645
|
+
arity(args, 0, 0, "notify --any");
|
|
646
|
+
const outcomes = await notifyBuiltJobs(store, config);
|
|
647
|
+
print(outcomes);
|
|
648
|
+
if (outcomes.some((outcome) => outcome.error)) process.exitCode = 2;
|
|
649
|
+
} else {
|
|
650
|
+
arity(args, 1, 1, "notify <id>");
|
|
651
|
+
print(await notifyJob(store, config, args[0]));
|
|
652
|
+
}
|
|
623
653
|
} else if (command === "retry") {
|
|
624
654
|
arity(args, 1, 1, "retry <id>");
|
|
625
655
|
print(view(store.transition(args[0], (job) => {
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","names":[],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { existsSync, readFileSync, writeFileSync, mkdirSync, mkdtempSync, rmSync } from 'node:fs';\nimport { spawnSync } from 'node:child_process';\nimport { resolve, dirname, join } from 'node:path';\nimport { tmpdir } from 'node:os';\nimport { fileURLToPath } from 'node:url';\nimport { parseArgs } from 'node:util';\nimport { canonicalPath, loadConfig, loadJSON, expandArgv, normalizeIsolationPaths, validateProjectSource } from './config.js';\nimport { Store } from './store.js';\nimport { run, executionEnvironment } from './process.js';\n\nimport { runStep } from './scheduler.js';\nimport { nextTurn, completeTurn, abandonTurn } from './runner.js';\nimport { hosts, installIntegration, updateIntegration, inspectIntegration, uninstallIntegration } from './integrations.js';\nimport { submitRequirement, scanInbox } from './inbox.js';\nimport { MAX_INPUT_BYTES, parseRequirement, readInputFile } from './requirements.js';\nimport { dispatchRemote } from './remote.js';\nimport { FrameworkSchema, PlatformSchema, PackageTargetSchema, toError, validateJobConfig } from './schemas.js';\nimport type { Config, Framework, Job, Platform } from './schemas.js';\nimport { assertProject, doctorCommands } from './project-profiles.js';\nimport { closestOwnedGoWorkspace } from './go-dependencies.js';\nimport { validateMyGoCommand } from './mygo-build.js';\nimport { invalidateVerification, verificationConfigChanged } from './proof.js';\nimport { prepareIsolatedCommand, removeConfinedPath, type IsolatedCommand } from './isolation.js';\n\nconst packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');\nconst print = (value: unknown): void => console.log(JSON.stringify(value, null, 2));\nconst view = (job: Job) => ({ id: job.id, product: job.spec.id, framework: job.spec.framework, platform: job.spec.platform, channel: job.spec.channel, version: job.spec.version, stage: job.stage, status: job.status, hostTurns: job.hostTurns, attempts: job.attempts, workspace: job.workspace, artifact: job.artifact ?? null, error: job.error ?? null });\n\nfunction inputJSON(path: string): unknown {\n const bytes = path === '-' ? readFileSync(0) : readInputFile(path);\n if (bytes.length > MAX_INPUT_BYTES) throw new Error(`Input exceeds ${MAX_INPUT_BYTES} bytes`);\n return JSON.parse(bytes.toString('utf8')) as unknown;\n}\n\nfunction arity(args: string[], minimum: number, maximum: number, usage: string): void {\n if (args.length < minimum || args.length > maximum) throw new Error(`Usage: apphx ${usage}`);\n}\n\nfunction outcome(job: Job): void {\n print(view(job));\n if (job.status === 'blocked' || job.status === 'failed') process.exitCode = 2;\n}\n\nasync function probe(argv: string[], config: Config, context?: { cwd: string; env: NodeJS.ProcessEnv; sourceRoot?: string }) {\n let temporary: string | undefined;\n let isolated: IsolatedCommand | undefined;\n try {\n const env = context?.env ?? executionEnvironment(config);\n const expanded = expandArgv(argv, env);\n validateMyGoCommand(config, expanded);\n if (config.isolation) {\n if (!config.allowLocalExecution) return { available: false, detail: 'Owner must enable local execution before isolated probes run' };\n temporary = mkdtempSync(join(tmpdir(), 'apphx-doctor-'));\n const scoped: Config = { ...config, isolation: { ...config.isolation, readOnlyPaths: [...config.isolation.readOnlyPaths, ...(context?.sourceRoot ? [canonicalPath(context.sourceRoot)] : [])] } };\n normalizeIsolationPaths(scoped);\n isolated = prepareIsolatedCommand(expanded, { config: scoped, workspace: temporary, cwd: context?.cwd ?? temporary, env, scratchParent: temporary });\n }\n const result = await run(isolated?.argv ?? expanded, { cwd: context?.cwd ?? temporary, env: isolated?.env ?? env, timeoutMs: 30000 });\n return { available: result.code === 0, detail: (result.code === 0 ? result.stdout : result.stderr || result.stdout).trim() };\n } catch (error) { return { available: false, detail: toError(error).message }; }\n finally {\n isolated?.cleanup();\n if (temporary) removeConfinedPath(temporary, temporary);\n }\n}\n\nconst frameworks = FrameworkSchema.options;\nconst packageTargets = PackageTargetSchema.options;\n\nfunction initialConfig(framework: Framework, platform: Platform, target: Config['packageTarget']): Record<string, unknown> {\n if ((framework === 'mygo') !== (platform === 'macos')) throw new Error(`${framework} does not support ${platform}`);\n if ((framework === 'android-java' && platform !== 'android') || (framework === 'swift' && platform !== 'ios')) throw new Error(`${framework} does not support ${platform}`);\n const allowedTargets = platform === 'macos' ? ['app', 'dmg'] : platform === 'ios' ? ['simulator', 'ipa'] : ['apk', 'aab'];\n if (!allowedTargets.includes(target)) throw new Error(`${target} does not match platform ${platform}`);\n const template = JSON.parse(readFileSync(join(packageRoot, 'examples', `${framework}.factory.json`), 'utf8')) as Record<string, unknown>;\n template.packageTarget = target;\n if (framework === 'mygo') {\n template.packaging = {\n provider: 'local',\n commands: [['go', 'tool', 'mygo', 'build', '-platform', 'darwin/arm64', '-sign', '-', '-skip-notarize', ...(target === 'app' ? ['-skip-dmg'] : []), '-o', 'build']],\n artifactPath: target === 'app' ? 'build/darwin-arm64/MyGo App.app' : 'build/darwin-arm64/MyGo App 0.1.0.dmg',\n };\n } else if (framework === 'flutter') {\n template.executionEnv = platform === 'ios' ? ['IOS_DEVICE_ID'] : ['ANDROID_DEVICE_ID'];\n template.verification = {\n prerequisites: platform === 'ios' ? [['xcodebuild', '-version']] : [['java', '-version'], ['adb', 'version']],\n checks: [['flutter', 'analyze', '--fatal-infos'], ['flutter', 'test']],\n runtime: [['flutter', 'drive', '--driver', 'test_driver/integration_test.dart', '--target', 'integration_test/app_test.dart', '-d', platform === 'ios' ? '${IOS_DEVICE_ID}' : '${ANDROID_DEVICE_ID}', '--no-pub']],\n };\n } else if (framework === 'expo') {\n const device = platform === 'ios' ? 'IOS_DEVICE_ID' : 'ANDROID_DEVICE_ID';\n const profile = target === 'simulator' ? 'simulator' : target === 'apk' ? 'apk' : 'production';\n const output = target === 'simulator' ? 'build/simulator.tar.gz' : `build/app.${target}`;\n template.executionEnv = [device, ...(platform === 'android' ? ['ANDROID_HOME'] : [])];\n template.verification = {\n prerequisites: [['node', '--version'], ['eas', '--version']],\n checks: [['npm', 'run', 'lint'], ['npm', 'test', '--', '--runInBand']],\n runtime: [['npm', 'run', 'test:e2e', '--', '--platform', platform, '--device', '${' + device + '}']],\n };\n template.packaging = {\n provider: 'local',\n commands: [['eas', 'build', '--platform', platform, '--profile', profile, '--local', '--non-interactive', '--output', output], ...(target === 'simulator' ? [['tar', '-xzf', output, '-C', 'build']] : [])],\n artifactPath: target === 'simulator' ? 'build/App.app' : output,\n };\n } else if (platform === 'ios') {\n const native = framework === 'swift' ? '.' : framework === 'uni-app' ? 'native/ios' : 'ios';\n const project = framework === 'swift' ? ['-project', 'App.xcodeproj'] : ['-workspace', `${native}/App.xcworkspace`];\n const base = ['xcodebuild', ...project, '-scheme', 'App'];\n template.executionEnv = ['IOS_DEVICE_ID'];\n template.verification = {\n prerequisites: [['xcodebuild', '-version'], ...(framework === 'swift' ? [] : [['node', '--version'], ['npm', '--version']])],\n checks: framework === 'swift' ? [[...base, 'build-for-testing', '-destination', 'generic/platform=iOS Simulator', '-derivedDataPath', 'build/DerivedData']] : [['npm', 'run', 'lint'], ['npm', 'test', '--', '--runInBand']],\n runtime: framework === 'swift' ? [[...base, 'test', '-destination', 'id=${IOS_DEVICE_ID}', '-derivedDataPath', 'build/DerivedData']] : [['npm', 'run', 'test:e2e', '--', '--platform', 'ios', '--device', '${IOS_DEVICE_ID}']],\n };\n template.packaging = target === 'simulator' ? {\n commands: [[...base, 'build', '-configuration', 'Debug', '-destination', 'generic/platform=iOS Simulator', '-derivedDataPath', 'build/DerivedData']],\n artifactPath: 'build/DerivedData/Build/Products/Debug-iphonesimulator/App.app', provider: 'local',\n } : {\n commands: [[...base, 'archive', '-configuration', 'Release', '-destination', 'generic/platform=iOS', '-archivePath', 'build/App.xcarchive'], ['xcodebuild', '-exportArchive', '-archivePath', 'build/App.xcarchive', '-exportPath', 'build/export', '-exportOptionsPlist', 'ExportOptions.plist']],\n artifactPath: 'build/export/App.ipa', provider: 'local',\n };\n } else if (target === 'apk') {\n const packaging = template.packaging as { commands: string[][]; artifactPath: string };\n packaging.commands = packaging.commands.map(argv => argv.map(arg => arg === ':app:bundleRelease' ? ':app:assembleRelease' : arg));\n packaging.artifactPath = packaging.artifactPath.replace('bundle/release/app-release.aab', 'apk/release/app-release.apk');\n }\n return template;\n}\n\nconst help = `apphx <command> [--config factory.json] [--build-only]\n hosts List supported agent hosts and activation commands\n install <host> Install the workflow in the current project\n update <host> Update an existing, unmodified host workflow\n uninstall <host> Remove an unchanged installation owned by this package\n --project <directory> Select the project (default: current directory)\n --global Use the host's user-level skill directory instead\n doctor --host <host> Check installed workflow files; does not run the agent\n init [--allow-local-execution] Create owner-editable factory.json; default Flutter/iOS\n --framework <stack> flutter|android-java|swift|react-native|expo|uni-app|mygo\n --platform <platform> ios|android|macos (mygo defaults macos; android-java android)\n --package-target <target> simulator|ipa|apk|aab|app|dmg (MyGo app; Expo iOS ipa)\n doctor [spec.json] Check configured prerequisites and optional stack tools\n enqueue <spec.json|-> Persist requirements and return a task ID\n next <id> Resume a host turn or show the next deterministic action\n complete <id> <turn> [json|-] Record research/review, or finish the host's build turn\n abandon <id> <turn> Abandon a host turn without resetting its budget\n step <id> Execute one obfuscation, verification or packaging stage\n status [id] Read durable task state as JSON\n events <id> Read task transitions and evidence\n retry <id> Resume stopped work; preserve budgets and proofs\n submit <spec.json|-> Write requirements to the configured inbox\n scan [--observe] Validate or ingest inbox files; never start an agent\n inbox Read durable intake results\n reconcile-intake <id> <json|-> Restore a legacy request identity from original input\n remote <command> Call an installed Mac CLI over SSH (build-only)\n obfuscator <project> Run the bundled deterministic obfuscator on a project copy\n --config <file> Obfuscator options as JSON (required)\n --framework <stack> flutter|android-java|swift|react-native|expo|uni-app|mygo\n --seed <text> Determinism seed\n --version Print the installed package version\n\nYour agent supplies the model, session, tools and native delegation.\nNo coding-agent subprocess or autonomous daemon is started by this CLI.\nOnly verified local artifacts reach built. Store submission and review are manual human work outside this tool.`;\n\nasync function main(): Promise<void> {\n const { values, positionals, tokens } = parseArgs({\n allowPositionals: true,\n tokens: true,\n options: {\n config: { type: 'string', default: 'factory.json' },\n 'build-only': { type: 'boolean', default: false },\n project: { type: 'string' },\n global: { type: 'boolean' },\n host: { type: 'string' },\n 'allow-local-execution': { type: 'boolean' },\n framework: { type: 'string' },\n seed: { type: 'string' },\n platform: { type: 'string' },\n 'package-target': { type: 'string' },\n observe: { type: 'boolean' },\n version: { type: 'boolean', short: 'v' },\n help: { type: 'boolean', short: 'h' },\n },\n });\n const [command, ...args] = positionals;\n if (values.version) {\n const metadata = JSON.parse(readFileSync(join(packageRoot, 'package.json'), 'utf8')) as { version: string };\n console.log(metadata.version);\n return;\n }\n if (!command || command === 'help' || values.help) { console.log(help); return; }\n const flags: Record<string, string[]> = {\n hosts: [], install: ['project', 'global'], update: ['project', 'global'], uninstall: ['project', 'global'],\n init: ['config', 'allow-local-execution', 'framework', 'platform', 'package-target'], doctor: ['config', 'build-only', 'host', 'project', 'global'],\n enqueue: ['config', 'build-only'], next: ['config', 'build-only'], complete: ['config', 'build-only'], abandon: ['config', 'build-only'],\n step: ['config', 'build-only'], status: ['config', 'build-only'], events: ['config', 'build-only'], retry: ['config', 'build-only'],\n submit: ['config', 'build-only'], scan: ['config', 'build-only', 'observe'], inbox: ['config', 'build-only'],\n 'reconcile-intake': ['config', 'build-only'],\n remote: ['config', 'observe'],\n obfuscator: ['config', 'framework', 'seed'],\n };\n if (!(command in flags)) throw new Error(`Unknown command ${command}; run apphx --help`);\n for (const token of tokens) {\n if (token.kind === 'option' && !flags[command].includes(token.name)) throw new Error(`${command} does not accept --${token.name}`);\n }\n const configPath = values.config;\n const buildOnly = values['build-only'];\n if (values.global && values.project) throw new Error('Choose --project or --global, not both');\n const scope = { project: values.project, global: values.global };\n if (command === 'obfuscator') {\n arity(args, 1, 1, 'obfuscator <project> --config <file> [--framework <stack>] [--seed <text>]');\n const bundled = join(packageRoot, 'dist', 'vendor', 'obfuscator', 'dist', 'cli.js');\n if (!existsSync(bundled)) throw new Error(`Bundled obfuscator is missing at ${bundled}; reinstall the apphx package`);\n const forward = [bundled, '--project', resolve(args[0]!)];\n // Forward only flags that were actually given, so the bundled binary sees exactly what the user\n // typed; an explicit empty value must reach the child and be rejected there, not dropped here.\n const configGiven = tokens.some(token => token.kind === 'option' && token.name === 'config');\n if (configGiven) forward.push('--config', resolve(values.config));\n if (values.framework !== undefined) forward.push('--framework', values.framework);\n if (values.seed !== undefined) forward.push('--seed', values.seed);\n const result = spawnSync(process.execPath, forward, { stdio: 'inherit' });\n if (result.error) throw result.error;\n process.exitCode = result.status ?? 1;\n return;\n }\n if (command === 'hosts') { arity(args, 0, 0, 'hosts'); print(hosts); return; }\n if (command === 'install' || command === 'update' || command === 'uninstall') {\n arity(args, 1, 1, `${command} <host> [--project <directory> | --global]`);\n const operation = command === 'install' ? installIntegration : command === 'update' ? updateIntegration : uninstallIntegration;\n print(operation(args[0], scope));\n return;\n }\n if (command === 'doctor' && values.host) {\n arity(args, 0, 0, 'doctor --host <host> [--project <directory> | --global]');\n const result = inspectIntegration(values.host, scope);\n print(result);\n if (!result.installed) process.exitCode = 2;\n return;\n }\n if (command === 'doctor' && (values.project || values.global)) throw new Error('--project and --global require doctor --host <host>');\n if (command === 'init') {\n arity(args, 0, 0, 'init [--framework <stack>] [--platform ios|android|macos] [--package-target simulator|ipa|apk|aab|app|dmg] [--config <file>] [--allow-local-execution]');\n const framework = values.framework ?? 'flutter';\n if (!frameworks.includes(framework as Framework)) throw new Error(`Unknown framework ${framework}; choose ${frameworks.join(', ')}`);\n const platform = PlatformSchema.parse(values.platform ?? (framework === 'mygo' ? 'macos' : framework === 'android-java' ? 'android' : 'ios'));\n const target = values['package-target'] ?? (platform === 'macos' ? 'app' : platform === 'ios' ? framework === 'expo' ? 'ipa' : 'simulator' : 'apk');\n if (!packageTargets.includes(target as Config['packageTarget'])) throw new Error(`Unknown package target ${target}; choose ${packageTargets.join(', ')}`);\n const template = initialConfig(framework as Framework, platform, target as Config['packageTarget']);\n if (values['allow-local-execution']) template.allowLocalExecution = true;\n mkdirSync(dirname(resolve(configPath)), { recursive: true });\n writeFileSync(configPath, `${JSON.stringify(template, null, 2)}\\n`, { flag: 'wx', mode: 0o600 });\n print({ config: resolve(configPath), framework, platform, packageTarget: target, localExecution: template.allowLocalExecution, next: framework === 'mygo' ? 'Pin MyGo v0.3.0 in go.mod (Go 1.27.1), match app name/version/arch and artifact path, and implement real desktop UI acceptance in cmd/acceptance. Native UI needs no Bun. Local ad-hoc builds only; init creates configuration, not source.' : framework === 'expo' ? 'Configure your existing eas.json production (store IPA/AAB), apk (Android buildType apk), or simulator (ios.simulator true) profile, real device acceptance, and exact app product/output path; no prebuild/eject is requested. Run apphx doctor <spec.json> --build-only.' : 'Adapt module/scheme, real device acceptance, signing and artifact path to your project; then run apphx doctor <spec.json> --build-only. init creates configuration, not app source.' });\n return;\n }\n if (command === 'remote') {\n process.exitCode = await dispatchRemote(loadJSON(configPath), [...args, ...(values.observe ? ['--observe'] : [])]);\n return;\n }\n const config = loadConfig(configPath);\n if (command === 'submit') {\n arity(args, 1, 1, 'submit <spec.json|->');\n print(submitRequirement(config, inputJSON(args[0])));\n return;\n }\n if (command === 'doctor') {\n arity(args, 0, 1, 'doctor [spec.json] [--build-only]');\n const spec = args[0] ? parseRequirement(inputJSON(args[0])).spec : undefined;\n let prerequisiteContext: { cwd: string; env: NodeJS.ProcessEnv; sourceRoot?: string } | undefined;\n if (spec) {\n validateJobConfig(spec, config);\n let source: string | undefined;\n try { source = validateProjectSource(spec, config); }\n catch (error) {\n if (spec.framework !== 'mygo' || (error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n }\n const directory = spec.project?.directory ?? '.';\n const project = source ? resolve(source, directory) : undefined;\n if (source && project && (spec.framework !== 'mygo' || existsSync(project))) {\n assertProject(project, spec);\n if (spec.framework === 'mygo' || config.isolation) prerequisiteContext = {\n cwd: project, sourceRoot: source,\n env: { ...executionEnvironment(config), ...(spec.framework === 'mygo' ? { GOWORK: closestOwnedGoWorkspace(source, directory) ?? 'off', GOENV: 'off', GOTOOLCHAIN: 'local', GOFLAGS: '-mod=readonly' } : {}) },\n };\n }\n }\n const commands = spec && config.packaging?.provider !== 'cloud' ? doctorCommands(spec.framework, spec.platform) : [];\n const tools = await Promise.all(commands.map(async ({ name, argv }) => ({ name, ...await probe(argv[0] === 'flutter' && config.toolchain ? [join(config.toolchain.flutterSdk, 'bin', 'flutter'), ...argv.slice(1)] : argv, config) })));\n const prerequisites = await Promise.all(config.verification.prerequisites.map(async (argv, index) => ({\n name: `configured-prerequisite-${index + 1}`,\n ...(!config.allowLocalExecution\n ? { available: false, detail: 'Owner must enable allowLocalExecution before configured prerequisite commands run' }\n : spec?.framework === 'mygo' && !prerequisiteContext\n ? { available: false, detail: 'Project-scoped prerequisite cannot be checked yet: select an existing MyGo source app with project.sourceDir and project.directory; doctor does not create source or use the control module' }\n : await probe(argv, config, prerequisiteContext)),\n })));\n const environment = executionEnvironment(config);\n const configuredCommands = [...config.verification.prerequisites, ...config.verification.checks, ...config.verification.runtime, ...(config.packaging?.commands ?? [])];\n const neededEnv = [...new Set(configuredCommands.flat().flatMap(arg => [...arg.matchAll(/\\$\\{([A-Z][A-Z0-9_]*)\\}/g)].map(match => match[1])))];\n const checks = [\n { name: 'local-execution-permission', available: config.allowLocalExecution, detail: config.executionWarning ?? 'Trusted local commands permitted; host tools remain under the host permission policy' },\n ...(config.isolation ? [{ name: 'subprocess-isolation', ...await probe(['/usr/bin/true'], config), mode: config.isolation.mode, network: config.isolation.network }] : []),\n ...tools, ...prerequisites,\n ...neededEnv.map(name => ({ name, available: Boolean(environment[name]), detail: environment[name] ? 'Available in the configured execution environment; value not printed' : `Set ${name} and include its name in executionEnv` })),\n ];\n print({ framework: spec?.framework ?? null, platform: spec?.platform ?? null, checks, note: spec ? 'Tool availability is not runtime acceptance; configured checks run in the task workspace during verify' : 'No stack assumed; pass spec.json for profile-specific probes and compatibility checks', model: 'Provided by your agent host; no separate model authentication is configured here' });\n if (checks.some(check => !check.available)) process.exitCode = 2;\n return;\n }\n const queuedRequirement = command === 'enqueue' ? (() => {\n arity(args, 1, 1, 'enqueue <spec.json|->');\n const requirement = parseRequirement(inputJSON(args[0]));\n validateJobConfig(requirement.spec, config);\n validateProjectSource(requirement.spec, config);\n return requirement;\n })() : undefined;\n const store = new Store(config.stateDir);\n try {\n if (command === 'enqueue') {\n const { spec, baseJobId } = queuedRequirement!;\n print(view(store.enqueue(spec, config, baseJobId)));\n } else if (command === 'scan') {\n arity(args, 0, 0, 'scan [--observe]');\n const result = await scanInbox(store, config, { observe: values.observe });\n print(result);\n if (result.error || result.entries.some(entry => entry.status === 'error')) process.exitCode = 2;\n } else if (command === 'inbox') {\n arity(args, 0, 0, 'inbox');\n print(store.inboxEntries());\n } else if (command === 'status') {\n arity(args, 0, 1, 'status [id]');\n print(args[0] ? store.get(args[0]) : store.list().map(view));\n } else if (command === 'events') {\n arity(args, 1, 1, 'events <id>');\n print(store.events(args[0]));\n } else if (command === 'next') {\n arity(args, 1, 1, 'next <id>');\n const result = await nextTurn(store, args[0], { buildOnly });\n print(result);\n if (result.job.status === 'blocked' || result.job.status === 'failed') process.exitCode = 2;\n } else if (command === 'complete') {\n arity(args, 2, 3, 'complete <id> <turn-id> [result.json|-]');\n outcome(await completeTurn(store, args[0], args[1], args[2] ? inputJSON(args[2]) : undefined, { buildOnly }));\n } else if (command === 'abandon') {\n arity(args, 2, 2, 'abandon <id> <turn-id>');\n outcome(abandonTurn(store, args[0], args[1], { buildOnly }));\n } else if (command === 'step') {\n arity(args, 1, 1, 'step <id>');\n const controller = new AbortController();\n const stop = (): void => controller.abort();\n process.on('SIGINT', stop);\n process.on('SIGTERM', stop);\n try { outcome(await runStep(store, config, args[0], { signal: controller.signal, buildOnly })); }\n finally { process.removeListener('SIGINT', stop); process.removeListener('SIGTERM', stop); }\n } else if (command === 'reconcile-intake') {\n arity(args, 2, 2, 'reconcile-intake <id> <original-spec.json|->');\n const { spec, baseJobId } = parseRequirement(inputJSON(args[1]));\n print(view(store.reconcileIntake(args[0], spec, baseJobId)));\n } else if (command === 'retry') {\n arity(args, 1, 1, 'retry <id>');\n print(view(store.transition(args[0], job => {\n if (!['blocked', 'ready', 'built'].includes(job.status)) throw new Error(`Cannot retry ${job.status}; budgets and active work cannot be reset by retry`);\n if (job.turn) throw new Error('Abandon the active host turn before changing task configuration');\n if (job.cloudBuildPending) throw new Error('Cloud packaging outcome is uncertain; reconcile the existing provider run rather than replaying it with retry');\n const resumedConfig = { ...config, packageTarget: config.packageTarget };\n const proofChanged = verificationConfigChanged(job, resumedConfig);\n const patch: Partial<Job> = proofChanged ? { ...invalidateVerification(), stage: ['verify', 'review', 'package'].includes(job.stage) ? 'verify' : job.stage } : {};\n validateJobConfig(job.spec, resumedConfig);\n return { ...patch, config: resumedConfig, status: 'queued', manualRecovery: null, nextAt: Date.now(), error: null };\n })));\n } else throw new Error(`Unknown command ${command}; use --help`);\n } finally { store.close(); }\n}\n\nmain().catch(error => { console.error(JSON.stringify({ error: toError(error).message })); process.exitCode = 1; });\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.js","names":[],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { existsSync, readFileSync, writeFileSync, mkdirSync, mkdtempSync, rmSync } from 'node:fs';\nimport { spawnSync } from 'node:child_process';\nimport { resolve, dirname, join } from 'node:path';\nimport { tmpdir } from 'node:os';\nimport { fileURLToPath } from 'node:url';\nimport { parseArgs } from 'node:util';\nimport { canonicalPath, loadConfig, loadJSON, expandArgv, normalizeIsolationPaths, validateProjectSource } from './config.js';\nimport { Store } from './store.js';\nimport { run, executionEnvironment } from './process.js';\n\nimport { runStep } from './scheduler.js';\nimport { nextTurn, nextQueueTurn, completeTurn, abandonTurn } from './runner.js';\nimport { hosts, installIntegration, updateIntegration, inspectIntegration, uninstallIntegration } from './integrations.js';\nimport { submitRequirement, scanInbox } from './inbox.js';\nimport { MAX_INPUT_BYTES, parseRequirement, readInputFile } from './requirements.js';\nimport { dispatchRemote } from './remote.js';\nimport { FrameworkSchema, PlatformSchema, PackageTargetSchema, toError, validateJobConfig } from './schemas.js';\nimport type { Config, Framework, Job, Platform } from './schemas.js';\nimport { assertProject, doctorCommands } from './project-profiles.js';\nimport { closestOwnedGoWorkspace } from './go-dependencies.js';\nimport { validateMyGoCommand } from './mygo-build.js';\nimport { invalidateVerification, verificationConfigChanged } from './proof.js';\nimport { notifyJob, notifyBuiltJobs } from './notify.js';\nimport { prepareIsolatedCommand, removeConfinedPath, type IsolatedCommand } from './isolation.js';\n\nconst packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');\nconst print = (value: unknown): void => console.log(JSON.stringify(value, null, 2));\nconst view = (job: Job) => ({ id: job.id, product: job.spec.id, framework: job.spec.framework, platform: job.spec.platform, channel: job.spec.channel, version: job.spec.version, priority: job.spec.priority, stage: job.stage, status: job.status, hostTurns: job.hostTurns, attempts: job.attempts, workspace: job.workspace, artifact: job.artifact ?? null, error: job.error ?? null });\n\nfunction inputJSON(path: string): unknown {\n const bytes = path === '-' ? readFileSync(0) : readInputFile(path);\n if (bytes.length > MAX_INPUT_BYTES) throw new Error(`Input exceeds ${MAX_INPUT_BYTES} bytes`);\n return JSON.parse(bytes.toString('utf8')) as unknown;\n}\n\nfunction arity(args: string[], minimum: number, maximum: number, usage: string): void {\n if (args.length < minimum || args.length > maximum) throw new Error(`Usage: apphx ${usage}`);\n}\n\nfunction outcome(job: Job): void {\n print(view(job));\n if (job.status === 'blocked' || job.status === 'failed') process.exitCode = 2;\n}\n\nasync function probe(argv: string[], config: Config, context?: { cwd: string; env: NodeJS.ProcessEnv; sourceRoot?: string }) {\n let temporary: string | undefined;\n let isolated: IsolatedCommand | undefined;\n try {\n const env = context?.env ?? executionEnvironment(config);\n const expanded = expandArgv(argv, env);\n validateMyGoCommand(config, expanded);\n if (config.isolation) {\n if (!config.allowLocalExecution) return { available: false, detail: 'Owner must enable local execution before isolated probes run' };\n temporary = mkdtempSync(join(tmpdir(), 'apphx-doctor-'));\n const scoped: Config = { ...config, isolation: { ...config.isolation, readOnlyPaths: [...config.isolation.readOnlyPaths, ...(context?.sourceRoot ? [canonicalPath(context.sourceRoot)] : [])] } };\n normalizeIsolationPaths(scoped);\n isolated = prepareIsolatedCommand(expanded, { config: scoped, workspace: temporary, cwd: context?.cwd ?? temporary, env, scratchParent: temporary });\n }\n const result = await run(isolated?.argv ?? expanded, { cwd: context?.cwd ?? temporary, env: isolated?.env ?? env, timeoutMs: 30000 });\n return { available: result.code === 0, detail: (result.code === 0 ? result.stdout : result.stderr || result.stdout).trim() };\n } catch (error) { return { available: false, detail: toError(error).message }; }\n finally {\n isolated?.cleanup();\n if (temporary) removeConfinedPath(temporary, temporary);\n }\n}\n\nconst frameworks = FrameworkSchema.options;\nconst packageTargets = PackageTargetSchema.options;\n\nfunction initialConfig(framework: Framework, platform: Platform, target: Config['packageTarget']): Record<string, unknown> {\n if ((framework === 'mygo') !== (platform === 'macos')) throw new Error(`${framework} does not support ${platform}`);\n if ((framework === 'android-java' && platform !== 'android') || (framework === 'swift' && platform !== 'ios')) throw new Error(`${framework} does not support ${platform}`);\n const allowedTargets = platform === 'macos' ? ['app', 'dmg'] : platform === 'ios' ? ['simulator', 'ipa'] : ['apk', 'aab'];\n if (!allowedTargets.includes(target)) throw new Error(`${target} does not match platform ${platform}`);\n const template = JSON.parse(readFileSync(join(packageRoot, 'examples', `${framework}.factory.json`), 'utf8')) as Record<string, unknown>;\n template.packageTarget = target;\n if (framework === 'mygo') {\n template.packaging = {\n provider: 'local',\n commands: [['go', 'tool', 'mygo', 'build', '-platform', 'darwin/arm64', '-sign', '-', '-skip-notarize', ...(target === 'app' ? ['-skip-dmg'] : []), '-o', 'build']],\n artifactPath: target === 'app' ? 'build/darwin-arm64/MyGo App.app' : 'build/darwin-arm64/MyGo App 0.1.0.dmg',\n };\n } else if (framework === 'flutter') {\n template.executionEnv = platform === 'ios' ? ['IOS_DEVICE_ID'] : ['ANDROID_DEVICE_ID'];\n template.verification = {\n prerequisites: platform === 'ios' ? [['xcodebuild', '-version']] : [['java', '-version'], ['adb', 'version']],\n checks: [['flutter', 'analyze', '--fatal-infos'], ['flutter', 'test']],\n runtime: [['flutter', 'drive', '--driver', 'test_driver/integration_test.dart', '--target', 'integration_test/app_test.dart', '-d', platform === 'ios' ? '${IOS_DEVICE_ID}' : '${ANDROID_DEVICE_ID}', '--no-pub']],\n };\n } else if (framework === 'expo') {\n const device = platform === 'ios' ? 'IOS_DEVICE_ID' : 'ANDROID_DEVICE_ID';\n const profile = target === 'simulator' ? 'simulator' : target === 'apk' ? 'apk' : 'production';\n const output = target === 'simulator' ? 'build/simulator.tar.gz' : `build/app.${target}`;\n template.executionEnv = [device, ...(platform === 'android' ? ['ANDROID_HOME'] : [])];\n template.verification = {\n prerequisites: [['node', '--version'], ['eas', '--version']],\n checks: [['npm', 'run', 'lint'], ['npm', 'test', '--', '--runInBand']],\n runtime: [['npm', 'run', 'test:e2e', '--', '--platform', platform, '--device', '${' + device + '}']],\n };\n template.packaging = {\n provider: 'local',\n commands: [['eas', 'build', '--platform', platform, '--profile', profile, '--local', '--non-interactive', '--output', output], ...(target === 'simulator' ? [['tar', '-xzf', output, '-C', 'build']] : [])],\n artifactPath: target === 'simulator' ? 'build/App.app' : output,\n };\n } else if (platform === 'ios') {\n const native = framework === 'swift' ? '.' : framework === 'uni-app' ? 'native/ios' : 'ios';\n const project = framework === 'swift' ? ['-project', 'App.xcodeproj'] : ['-workspace', `${native}/App.xcworkspace`];\n const base = ['xcodebuild', ...project, '-scheme', 'App'];\n template.executionEnv = ['IOS_DEVICE_ID'];\n template.verification = {\n prerequisites: [['xcodebuild', '-version'], ...(framework === 'swift' ? [] : [['node', '--version'], ['npm', '--version']])],\n checks: framework === 'swift' ? [[...base, 'build-for-testing', '-destination', 'generic/platform=iOS Simulator', '-derivedDataPath', 'build/DerivedData']] : [['npm', 'run', 'lint'], ['npm', 'test', '--', '--runInBand']],\n runtime: framework === 'swift' ? [[...base, 'test', '-destination', 'id=${IOS_DEVICE_ID}', '-derivedDataPath', 'build/DerivedData']] : [['npm', 'run', 'test:e2e', '--', '--platform', 'ios', '--device', '${IOS_DEVICE_ID}']],\n };\n template.packaging = target === 'simulator' ? {\n commands: [[...base, 'build', '-configuration', 'Debug', '-destination', 'generic/platform=iOS Simulator', '-derivedDataPath', 'build/DerivedData']],\n artifactPath: 'build/DerivedData/Build/Products/Debug-iphonesimulator/App.app', provider: 'local',\n } : {\n commands: [[...base, 'archive', '-configuration', 'Release', '-destination', 'generic/platform=iOS', '-archivePath', 'build/App.xcarchive'], ['xcodebuild', '-exportArchive', '-archivePath', 'build/App.xcarchive', '-exportPath', 'build/export', '-exportOptionsPlist', 'ExportOptions.plist']],\n artifactPath: 'build/export/App.ipa', provider: 'local',\n };\n } else if (target === 'apk') {\n const packaging = template.packaging as { commands: string[][]; artifactPath: string };\n packaging.commands = packaging.commands.map(argv => argv.map(arg => arg === ':app:bundleRelease' ? ':app:assembleRelease' : arg));\n packaging.artifactPath = packaging.artifactPath.replace('bundle/release/app-release.aab', 'apk/release/app-release.apk');\n }\n return template;\n}\n\nconst help = `apphx <command> [--config factory.json] [--build-only]\n hosts List supported agent hosts and activation commands\n install <host> Install the workflow in the current project\n update <host> Update an existing, unmodified host workflow\n uninstall <host> Remove an unchanged installation owned by this package\n --project <directory> Select the project (default: current directory)\n --global Use the host's user-level skill directory instead\n doctor --host <host> Check installed workflow files; does not run the agent\n init [--allow-local-execution] Create owner-editable factory.json; default Flutter/iOS\n --framework <stack> flutter|android-java|swift|react-native|expo|uni-app|mygo\n --platform <platform> ios|android|macos (mygo defaults macos; android-java android)\n --package-target <target> simulator|ipa|apk|aab|app|dmg (MyGo app; Expo iOS ipa)\n doctor [spec.json] Check configured prerequisites and optional stack tools\n enqueue <spec.json|-> Persist requirements and return a task ID\n next [<id>|--any] Resume a host turn, show the next deterministic action, or pick the next actionable queued task (--any)\n complete <id> <turn> [json|-] Record research/review, or finish the host's build turn\n abandon <id> <turn> Abandon a host turn without resetting its budget\n step <id> Execute one obfuscation, verification or packaging stage\n status [id] Read durable task state as JSON\n events <id> Read task transitions and evidence\n retry <id> Resume stopped work; preserve budgets and proofs\n submit <spec.json|-> Write requirements to the configured inbox\n scan [--observe] Validate or ingest inbox files; never start an agent\n inbox Read durable intake results\n reconcile-intake <id> <json|-> Restore a legacy request identity from original input\n notify [<id>|--any] Email the author for built, gate-passed tasks (--any sweeps all unnotified)\n remote <command> Call an installed Mac CLI over SSH (build-only)\n obfuscator <project> Run the bundled deterministic obfuscator on a project copy\n --config <file> Obfuscator options as JSON (required)\n --framework <stack> flutter|android-java|swift|react-native|expo|uni-app|mygo\n --seed <text> Determinism seed\n --version Print the installed package version\n\nYour agent supplies the model, session, tools and native delegation.\nNo coding-agent subprocess or autonomous daemon is started by this CLI.\nOnly verified local artifacts reach built. Store submission and review are manual human work outside this tool.`;\n\nasync function main(): Promise<void> {\n const { values, positionals, tokens } = parseArgs({\n allowPositionals: true,\n tokens: true,\n options: {\n config: { type: 'string', default: 'factory.json' },\n 'build-only': { type: 'boolean', default: false },\n project: { type: 'string' },\n global: { type: 'boolean' },\n host: { type: 'string' },\n 'allow-local-execution': { type: 'boolean' },\n framework: { type: 'string' },\n seed: { type: 'string' },\n platform: { type: 'string' },\n 'package-target': { type: 'string' },\n observe: { type: 'boolean' },\n any: { type: 'boolean' },\n version: { type: 'boolean', short: 'v' },\n help: { type: 'boolean', short: 'h' },\n },\n });\n const [command, ...args] = positionals;\n if (values.version) {\n const metadata = JSON.parse(readFileSync(join(packageRoot, 'package.json'), 'utf8')) as { version: string };\n console.log(metadata.version);\n return;\n }\n if (!command || command === 'help' || values.help) { console.log(help); return; }\n const flags: Record<string, string[]> = {\n hosts: [], install: ['project', 'global'], update: ['project', 'global'], uninstall: ['project', 'global'],\n init: ['config', 'allow-local-execution', 'framework', 'platform', 'package-target'], doctor: ['config', 'build-only', 'host', 'project', 'global'],\n enqueue: ['config', 'build-only'], next: ['config', 'build-only', 'any'], complete: ['config', 'build-only'], abandon: ['config', 'build-only'],\n step: ['config', 'build-only'], status: ['config', 'build-only'], events: ['config', 'build-only'], retry: ['config', 'build-only'],\n notify: ['config', 'build-only', 'any'],\n submit: ['config', 'build-only'], scan: ['config', 'build-only', 'observe'], inbox: ['config', 'build-only'],\n 'reconcile-intake': ['config', 'build-only'],\n remote: ['config', 'observe'],\n obfuscator: ['config', 'framework', 'seed'],\n };\n if (!(command in flags)) throw new Error(`Unknown command ${command}; run apphx --help`);\n for (const token of tokens) {\n if (token.kind === 'option' && !flags[command].includes(token.name)) throw new Error(`${command} does not accept --${token.name}`);\n }\n const configPath = values.config;\n const buildOnly = values['build-only'];\n if (values.global && values.project) throw new Error('Choose --project or --global, not both');\n const scope = { project: values.project, global: values.global };\n if (command === 'obfuscator') {\n arity(args, 1, 1, 'obfuscator <project> --config <file> [--framework <stack>] [--seed <text>]');\n const bundled = join(packageRoot, 'dist', 'vendor', 'obfuscator', 'dist', 'cli.js');\n if (!existsSync(bundled)) throw new Error(`Bundled obfuscator is missing at ${bundled}; reinstall the apphx package`);\n const forward = [bundled, '--project', resolve(args[0]!)];\n // Forward only flags that were actually given, so the bundled binary sees exactly what the user\n // typed; an explicit empty value must reach the child and be rejected there, not dropped here.\n const configGiven = tokens.some(token => token.kind === 'option' && token.name === 'config');\n if (configGiven) forward.push('--config', resolve(values.config));\n if (values.framework !== undefined) forward.push('--framework', values.framework);\n if (values.seed !== undefined) forward.push('--seed', values.seed);\n const result = spawnSync(process.execPath, forward, { stdio: 'inherit' });\n if (result.error) throw result.error;\n process.exitCode = result.status ?? 1;\n return;\n }\n if (command === 'hosts') { arity(args, 0, 0, 'hosts'); print(hosts); return; }\n if (command === 'install' || command === 'update' || command === 'uninstall') {\n arity(args, 1, 1, `${command} <host> [--project <directory> | --global]`);\n const operation = command === 'install' ? installIntegration : command === 'update' ? updateIntegration : uninstallIntegration;\n operation(args[0], scope);\n print(['apphx', 'apphx-obfuscator'].map(skill => inspectIntegration(args[0], scope, skill as 'apphx' | 'apphx-obfuscator')));\n return;\n }\n if (command === 'doctor' && values.host) {\n arity(args, 0, 0, 'doctor --host <host> [--project <directory> | --global]');\n const host = values.host;\n const skills = ['apphx', 'apphx-obfuscator'] as const;\n const results = skills.map(skill => inspectIntegration(host, scope, skill));\n print(results);\n if (!results[0]!.installed) process.exitCode = 2;\n return;\n }\n if (command === 'doctor' && (values.project || values.global)) throw new Error('--project and --global require doctor --host <host>');\n if (command === 'init') {\n arity(args, 0, 0, 'init [--framework <stack>] [--platform ios|android|macos] [--package-target simulator|ipa|apk|aab|app|dmg] [--config <file>] [--allow-local-execution]');\n const framework = values.framework ?? 'flutter';\n if (!frameworks.includes(framework as Framework)) throw new Error(`Unknown framework ${framework}; choose ${frameworks.join(', ')}`);\n const platform = PlatformSchema.parse(values.platform ?? (framework === 'mygo' ? 'macos' : framework === 'android-java' ? 'android' : 'ios'));\n const target = values['package-target'] ?? (platform === 'macos' ? 'app' : platform === 'ios' ? framework === 'expo' ? 'ipa' : 'simulator' : 'apk');\n if (!packageTargets.includes(target as Config['packageTarget'])) throw new Error(`Unknown package target ${target}; choose ${packageTargets.join(', ')}`);\n const template = initialConfig(framework as Framework, platform, target as Config['packageTarget']);\n if (values['allow-local-execution']) template.allowLocalExecution = true;\n mkdirSync(dirname(resolve(configPath)), { recursive: true });\n writeFileSync(configPath, `${JSON.stringify(template, null, 2)}\\n`, { flag: 'wx', mode: 0o600 });\n print({ config: resolve(configPath), framework, platform, packageTarget: target, localExecution: template.allowLocalExecution, next: framework === 'mygo' ? 'Pin MyGo v0.3.0 in go.mod (Go 1.27.1), match app name/version/arch and artifact path, and implement real desktop UI acceptance in cmd/acceptance. Native UI needs no Bun. Local ad-hoc builds only; init creates configuration, not source.' : framework === 'expo' ? 'Configure your existing eas.json production (store IPA/AAB), apk (Android buildType apk), or simulator (ios.simulator true) profile, real device acceptance, and exact app product/output path; no prebuild/eject is requested. Run apphx doctor <spec.json> --build-only.' : 'Adapt module/scheme, real device acceptance, signing and artifact path to your project; then run apphx doctor <spec.json> --build-only. init creates configuration, not app source.' });\n return;\n }\n if (command === 'remote') {\n process.exitCode = await dispatchRemote(loadJSON(configPath), [...args, ...(values.observe ? ['--observe'] : [])]);\n return;\n }\n const config = loadConfig(configPath);\n if (command === 'submit') {\n arity(args, 1, 1, 'submit <spec.json|->');\n print(submitRequirement(config, inputJSON(args[0])));\n return;\n }\n if (command === 'doctor') {\n arity(args, 0, 1, 'doctor [spec.json] [--build-only]');\n const spec = args[0] ? parseRequirement(inputJSON(args[0])).spec : undefined;\n let prerequisiteContext: { cwd: string; env: NodeJS.ProcessEnv; sourceRoot?: string } | undefined;\n if (spec) {\n validateJobConfig(spec, config);\n let source: string | undefined;\n try { source = validateProjectSource(spec, config); }\n catch (error) {\n if (spec.framework !== 'mygo' || (error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n }\n const directory = spec.project?.directory ?? '.';\n const project = source ? resolve(source, directory) : undefined;\n if (source && project && (spec.framework !== 'mygo' || existsSync(project))) {\n assertProject(project, spec);\n if (spec.framework === 'mygo' || config.isolation) prerequisiteContext = {\n cwd: project, sourceRoot: source,\n env: { ...executionEnvironment(config), ...(spec.framework === 'mygo' ? { GOWORK: closestOwnedGoWorkspace(source, directory) ?? 'off', GOENV: 'off', GOTOOLCHAIN: 'local', GOFLAGS: '-mod=readonly' } : {}) },\n };\n }\n }\n const commands = spec && config.packaging?.provider !== 'cloud' ? doctorCommands(spec.framework, spec.platform) : [];\n const tools = await Promise.all(commands.map(async ({ name, argv }) => ({ name, ...await probe(argv[0] === 'flutter' && config.toolchain ? [join(config.toolchain.flutterSdk, 'bin', 'flutter'), ...argv.slice(1)] : argv, config) })));\n const prerequisites = await Promise.all(config.verification.prerequisites.map(async (argv, index) => ({\n name: `configured-prerequisite-${index + 1}`,\n ...(!config.allowLocalExecution\n ? { available: false, detail: 'Owner must enable allowLocalExecution before configured prerequisite commands run' }\n : spec?.framework === 'mygo' && !prerequisiteContext\n ? { available: false, detail: 'Project-scoped prerequisite cannot be checked yet: select an existing MyGo source app with project.sourceDir and project.directory; doctor does not create source or use the control module' }\n : await probe(argv, config, prerequisiteContext)),\n })));\n const environment = executionEnvironment(config);\n const configuredCommands = [...config.verification.prerequisites, ...config.verification.checks, ...config.verification.runtime, ...(config.packaging?.commands ?? [])];\n const neededEnv = [...new Set(configuredCommands.flat().flatMap(arg => [...arg.matchAll(/\\$\\{([A-Z][A-Z0-9_]*)\\}/g)].map(match => match[1])))];\n const checks = [\n { name: 'local-execution-permission', available: config.allowLocalExecution, detail: config.executionWarning ?? 'Trusted local commands permitted; host tools remain under the host permission policy' },\n ...(config.isolation ? [{ name: 'subprocess-isolation', ...await probe(['/usr/bin/true'], config), mode: config.isolation.mode, network: config.isolation.network }] : []),\n ...tools, ...prerequisites,\n ...neededEnv.map(name => ({ name, available: Boolean(environment[name]), detail: environment[name] ? 'Available in the configured execution environment; value not printed' : `Set ${name} and include its name in executionEnv` })),\n ];\n print({ framework: spec?.framework ?? null, platform: spec?.platform ?? null, checks, note: spec ? 'Tool availability is not runtime acceptance; configured checks run in the task workspace during verify' : 'No stack assumed; pass spec.json for profile-specific probes and compatibility checks', model: 'Provided by your agent host; no separate model authentication is configured here' });\n if (checks.some(check => !check.available)) process.exitCode = 2;\n return;\n }\n const queuedRequirement = command === 'enqueue' ? (() => {\n arity(args, 1, 1, 'enqueue <spec.json|->');\n const requirement = parseRequirement(inputJSON(args[0]));\n validateJobConfig(requirement.spec, config);\n validateProjectSource(requirement.spec, config);\n return requirement;\n })() : undefined;\n const store = new Store(config.stateDir);\n try {\n if (command === 'enqueue') {\n const { spec, baseJobId } = queuedRequirement!;\n print(view(store.enqueue(spec, config, baseJobId)));\n } else if (command === 'scan') {\n arity(args, 0, 0, 'scan [--observe]');\n const result = await scanInbox(store, config, { observe: values.observe });\n print(result);\n if (result.error || result.entries.some(entry => entry.status === 'error')) process.exitCode = 2;\n } else if (command === 'inbox') {\n arity(args, 0, 0, 'inbox');\n print(store.inboxEntries());\n } else if (command === 'status') {\n arity(args, 0, 1, 'status [id]');\n print(args[0] ? store.get(args[0]) : store.list().map(view));\n } else if (command === 'events') {\n arity(args, 1, 1, 'events <id>');\n print(store.events(args[0]));\n } else if (command === 'next') {\n if (values.any) {\n arity(args, 0, 0, 'next --any');\n print(await nextQueueTurn(store, { buildOnly }));\n } else {\n arity(args, 1, 1, 'next <id>');\n const result = await nextTurn(store, args[0], { buildOnly });\n print(result);\n if (result.job.status === 'blocked' || result.job.status === 'failed') process.exitCode = 2;\n }\n } else if (command === 'complete') {\n arity(args, 2, 3, 'complete <id> <turn-id> [result.json|-]');\n outcome(await completeTurn(store, args[0], args[1], args[2] ? inputJSON(args[2]) : undefined, { buildOnly }));\n } else if (command === 'abandon') {\n arity(args, 2, 2, 'abandon <id> <turn-id>');\n outcome(abandonTurn(store, args[0], args[1], { buildOnly }));\n } else if (command === 'step') {\n arity(args, 1, 1, 'step <id>');\n const controller = new AbortController();\n const stop = (): void => controller.abort();\n process.on('SIGINT', stop);\n process.on('SIGTERM', stop);\n try { outcome(await runStep(store, config, args[0], { signal: controller.signal, buildOnly })); }\n finally { process.removeListener('SIGINT', stop); process.removeListener('SIGTERM', stop); }\n } else if (command === 'reconcile-intake') {\n arity(args, 2, 2, 'reconcile-intake <id> <original-spec.json|->');\n const { spec, baseJobId } = parseRequirement(inputJSON(args[1]));\n print(view(store.reconcileIntake(args[0], spec, baseJobId)));\n } else if (command === 'notify') {\n if (values.any) {\n arity(args, 0, 0, 'notify --any');\n const outcomes = await notifyBuiltJobs(store, config);\n print(outcomes);\n if (outcomes.some(outcome => outcome.error)) process.exitCode = 2;\n } else {\n arity(args, 1, 1, 'notify <id>');\n print(await notifyJob(store, config, args[0]));\n }\n } else if (command === 'retry') {\n arity(args, 1, 1, 'retry <id>');\n print(view(store.transition(args[0], job => {\n if (!['blocked', 'ready', 'built'].includes(job.status)) throw new Error(`Cannot retry ${job.status}; budgets and active work cannot be reset by retry`);\n if (job.turn) throw new Error('Abandon the active host turn before changing task configuration');\n if (job.cloudBuildPending) throw new Error('Cloud packaging outcome is uncertain; reconcile the existing provider run rather than replaying it with retry');\n const resumedConfig = { ...config, packageTarget: config.packageTarget };\n const proofChanged = verificationConfigChanged(job, resumedConfig);\n const patch: Partial<Job> = proofChanged ? { ...invalidateVerification(), stage: ['verify', 'review', 'package'].includes(job.stage) ? 'verify' : job.stage } : {};\n validateJobConfig(job.spec, resumedConfig);\n return { ...patch, config: resumedConfig, status: 'queued', manualRecovery: null, nextAt: Date.now(), error: null };\n })));\n } else throw new Error(`Unknown command ${command}; use --help`);\n } finally { store.close(); }\n}\n\nmain().catch(error => { console.error(JSON.stringify({ error: toError(error).message })); process.exitCode = 1; });\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AA0BA,MAAM,cAAc,QAAQ,QAAQ,cAAc,YAAY,GAAG,CAAC,GAAG,IAAI;AACzE,MAAM,SAAS,UAAyB,QAAQ,IAAI,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AAClF,MAAM,QAAQ,SAAc;CAAE,IAAI,IAAI;CAAI,SAAS,IAAI,KAAK;CAAI,WAAW,IAAI,KAAK;CAAW,UAAU,IAAI,KAAK;CAAU,SAAS,IAAI,KAAK;CAAS,SAAS,IAAI,KAAK;CAAS,UAAU,IAAI,KAAK;CAAU,OAAO,IAAI;CAAO,QAAQ,IAAI;CAAQ,WAAW,IAAI;CAAW,UAAU,IAAI;CAAU,WAAW,IAAI;CAAW,UAAU,IAAI,YAAY;CAAM,OAAO,IAAI,SAAS;AAAK;AAE1X,SAAS,UAAU,MAAuB;CACxC,MAAM,QAAQ,SAAS,MAAM,aAAa,CAAC,IAAI,cAAc,IAAI;CACjE,IAAI,MAAM,SAAA,SAA0B,MAAM,IAAI,MAAM,iBAAiB,gBAAgB,OAAO;CAC5F,OAAO,KAAK,MAAM,MAAM,SAAS,MAAM,CAAC;AAC1C;AAEA,SAAS,MAAM,MAAgB,SAAiB,SAAiB,OAAqB;CACpF,IAAI,KAAK,SAAS,WAAW,KAAK,SAAS,SAAS,MAAM,IAAI,MAAM,gBAAgB,OAAO;AAC7F;AAEA,SAAS,QAAQ,KAAgB;CAC/B,MAAM,KAAK,GAAG,CAAC;CACf,IAAI,IAAI,WAAW,aAAa,IAAI,WAAW,UAAU,QAAQ,WAAW;AAC9E;AAEA,eAAe,MAAM,MAAgB,QAAgB,SAAwE;CAC3H,IAAI;CACJ,IAAI;CACJ,IAAI;EACF,MAAM,MAAM,SAAS,OAAO,qBAAqB,MAAM;EACvD,MAAM,WAAW,WAAW,MAAM,GAAG;EACrC,oBAAoB,QAAQ,QAAQ;EACpC,IAAI,OAAO,WAAW;GACpB,IAAI,CAAC,OAAO,qBAAqB,OAAO;IAAE,WAAW;IAAO,QAAQ;GAA+D;GACnI,YAAY,YAAY,KAAK,OAAO,GAAG,eAAe,CAAC;GACvD,MAAM,SAAiB;IAAE,GAAG;IAAQ,WAAW;KAAE,GAAG,OAAO;KAAW,eAAe,CAAC,GAAG,OAAO,UAAU,eAAe,GAAI,SAAS,aAAa,CAAC,cAAc,QAAQ,UAAU,CAAC,IAAI,CAAC,CAAE;IAAE;GAAE;GAChM,wBAAwB,MAAM;GAC9B,WAAW,uBAAuB,UAAU;IAAE,QAAQ;IAAQ,WAAW;IAAW,KAAK,SAAS,OAAO;IAAW;IAAK,eAAe;GAAU,CAAC;EACrJ;EACA,MAAM,SAAS,MAAM,IAAI,UAAU,QAAQ,UAAU;GAAE,KAAK,SAAS,OAAO;GAAW,KAAK,UAAU,OAAO;GAAK,WAAW;EAAM,CAAC;EACpI,OAAO;GAAE,WAAW,OAAO,SAAS;GAAG,SAAS,OAAO,SAAS,IAAI,OAAO,SAAS,OAAO,UAAU,OAAO,OAAA,CAAQ,KAAK;EAAE;CAC7H,SAAS,OAAO;EAAE,OAAO;GAAE,WAAW;GAAO,QAAQ,QAAQ,KAAK,CAAC,CAAC;EAAQ;CAAG,UACvE;EACN,UAAU,QAAQ;EAClB,IAAI,WAAW,mBAAmB,WAAW,SAAS;CACxD;AACF;AAEA,MAAM,aAAa,gBAAgB;AACnC,MAAM,iBAAiB,oBAAoB;AAE3C,SAAS,cAAc,WAAsB,UAAoB,QAA0D;CACzH,IAAK,cAAc,YAAa,aAAa,UAAU,MAAM,IAAI,MAAM,GAAG,UAAU,oBAAoB,UAAU;CAClH,IAAK,cAAc,kBAAkB,aAAa,aAAe,cAAc,WAAW,aAAa,OAAQ,MAAM,IAAI,MAAM,GAAG,UAAU,oBAAoB,UAAU;CAE1K,IAAI,EADmB,aAAa,UAAU,CAAC,OAAO,KAAK,IAAI,aAAa,QAAQ,CAAC,aAAa,KAAK,IAAI,CAAC,OAAO,KAAK,EAAA,CACpG,SAAS,MAAM,GAAG,MAAM,IAAI,MAAM,GAAG,OAAO,2BAA2B,UAAU;CACrG,MAAM,WAAW,KAAK,MAAM,aAAa,KAAK,aAAa,YAAY,GAAG,UAAU,cAAc,GAAG,MAAM,CAAC;CAC5G,SAAS,gBAAgB;CACzB,IAAI,cAAc,QAChB,SAAS,YAAY;EACnB,UAAU;EACV,UAAU,CAAC;GAAC;GAAM;GAAQ;GAAQ;GAAS;GAAa;GAAgB;GAAS;GAAK;GAAkB,GAAI,WAAW,QAAQ,CAAC,WAAW,IAAI,CAAC;GAAI;GAAM;EAAO,CAAC;EAClK,cAAc,WAAW,QAAQ,oCAAoC;CACvE;MACK,IAAI,cAAc,WAAW;EAClC,SAAS,eAAe,aAAa,QAAQ,CAAC,eAAe,IAAI,CAAC,mBAAmB;EACrF,SAAS,eAAe;GACtB,eAAe,aAAa,QAAQ,CAAC,CAAC,cAAc,UAAU,CAAC,IAAI,CAAC,CAAC,QAAQ,UAAU,GAAG,CAAC,OAAO,SAAS,CAAC;GAC5G,QAAQ,CAAC;IAAC;IAAW;IAAW;GAAe,GAAG,CAAC,WAAW,MAAM,CAAC;GACrE,SAAS,CAAC;IAAC;IAAW;IAAS;IAAY;IAAqC;IAAY;IAAkC;IAAM,aAAa,QAAQ,qBAAqB;IAAwB;GAAU,CAAC;EACnN;CACF,OAAO,IAAI,cAAc,QAAQ;EAC/B,MAAM,SAAS,aAAa,QAAQ,kBAAkB;EACtD,MAAM,UAAU,WAAW,cAAc,cAAc,WAAW,QAAQ,QAAQ;EAClF,MAAM,SAAS,WAAW,cAAc,2BAA2B,aAAa;EAChF,SAAS,eAAe,CAAC,QAAQ,GAAI,aAAa,YAAY,CAAC,cAAc,IAAI,CAAC,CAAE;EACpF,SAAS,eAAe;GACtB,eAAe,CAAC,CAAC,QAAQ,WAAW,GAAG,CAAC,OAAO,WAAW,CAAC;GAC3D,QAAQ,CAAC;IAAC;IAAO;IAAO;GAAM,GAAG;IAAC;IAAO;IAAQ;IAAM;GAAa,CAAC;GACrE,SAAS,CAAC;IAAC;IAAO;IAAO;IAAY;IAAM;IAAc;IAAU;IAAY,OAAO,SAAS;GAAG,CAAC;EACrG;EACA,SAAS,YAAY;GACnB,UAAU;GACV,UAAU,CAAC;IAAC;IAAO;IAAS;IAAc;IAAU;IAAa;IAAS;IAAW;IAAqB;IAAY;GAAM,GAAG,GAAI,WAAW,cAAc,CAAC;IAAC;IAAO;IAAQ;IAAQ;IAAM;GAAO,CAAC,IAAI,CAAC,CAAE;GAC1M,cAAc,WAAW,cAAc,kBAAkB;EAC3D;CACF,OAAO,IAAI,aAAa,OAAO;EAG7B,MAAM,OAAO;GAAC;GAAc,GADZ,cAAc,UAAU,CAAC,YAAY,eAAe,IAAI,CAAC,cAAc,GADxE,cAAc,UAAU,MAAM,cAAc,YAAY,eAAe,MACW,iBAAiB;GAC1E;GAAW;EAAK;EACxD,SAAS,eAAe,CAAC,eAAe;EACxC,SAAS,eAAe;GACtB,eAAe,CAAC,CAAC,cAAc,UAAU,GAAG,GAAI,cAAc,UAAU,CAAC,IAAI,CAAC,CAAC,QAAQ,WAAW,GAAG,CAAC,OAAO,WAAW,CAAC,CAAE;GAC3H,QAAQ,cAAc,UAAU,CAAC;IAAC,GAAG;IAAM;IAAqB;IAAgB;IAAkC;IAAoB;GAAmB,CAAC,IAAI,CAAC;IAAC;IAAO;IAAO;GAAM,GAAG;IAAC;IAAO;IAAQ;IAAM;GAAa,CAAC;GAC3N,SAAS,cAAc,UAAU,CAAC;IAAC,GAAG;IAAM;IAAQ;IAAgB;IAAuB;IAAoB;GAAmB,CAAC,IAAI,CAAC;IAAC;IAAO;IAAO;IAAY;IAAM;IAAc;IAAO;IAAY;GAAkB,CAAC;EAC/N;EACA,SAAS,YAAY,WAAW,cAAc;GAC5C,UAAU,CAAC;IAAC,GAAG;IAAM;IAAS;IAAkB;IAAS;IAAgB;IAAkC;IAAoB;GAAmB,CAAC;GACnJ,cAAc;GAAkE,UAAU;EAC5F,IAAI;GACF,UAAU,CAAC;IAAC,GAAG;IAAM;IAAW;IAAkB;IAAW;IAAgB;IAAwB;IAAgB;GAAqB,GAAG;IAAC;IAAc;IAAkB;IAAgB;IAAuB;IAAe;IAAgB;IAAuB;GAAqB,CAAC;GACjS,cAAc;GAAwB,UAAU;EAClD;CACF,OAAO,IAAI,WAAW,OAAO;EAC3B,MAAM,YAAY,SAAS;EAC3B,UAAU,WAAW,UAAU,SAAS,KAAI,SAAQ,KAAK,KAAI,QAAO,QAAQ,uBAAuB,yBAAyB,GAAG,CAAC;EAChI,UAAU,eAAe,UAAU,aAAa,QAAQ,kCAAkC,6BAA6B;CACzH;CACA,OAAO;AACT;AAEA,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCb,eAAe,OAAsB;CACnC,MAAM,EAAE,QAAQ,aAAa,WAAW,UAAU;EAChD,kBAAkB;EAClB,QAAQ;EACR,SAAS;GACP,QAAQ;IAAE,MAAM;IAAU,SAAS;GAAe;GAClD,cAAc;IAAE,MAAM;IAAW,SAAS;GAAM;GAChD,SAAS,EAAE,MAAM,SAAS;GAC1B,QAAQ,EAAE,MAAM,UAAU;GAC1B,MAAM,EAAE,MAAM,SAAS;GACvB,yBAAyB,EAAE,MAAM,UAAU;GAC3C,WAAW,EAAE,MAAM,SAAS;GAC5B,MAAM,EAAE,MAAM,SAAS;GACvB,UAAU,EAAE,MAAM,SAAS;GAC3B,kBAAkB,EAAE,MAAM,SAAS;GACnC,SAAS,EAAE,MAAM,UAAU;GAC3B,KAAK,EAAE,MAAM,UAAU;GACvB,SAAS;IAAE,MAAM;IAAW,OAAO;GAAI;GACvC,MAAM;IAAE,MAAM;IAAW,OAAO;GAAI;EACtC;CACF,CAAC;CACD,MAAM,CAAC,SAAS,GAAG,QAAQ;CAC3B,IAAI,OAAO,SAAS;EAClB,MAAM,WAAW,KAAK,MAAM,aAAa,KAAK,aAAa,cAAc,GAAG,MAAM,CAAC;EACnF,QAAQ,IAAI,SAAS,OAAO;EAC5B;CACF;CACA,IAAI,CAAC,WAAW,YAAY,UAAU,OAAO,MAAM;EAAE,QAAQ,IAAI,IAAI;EAAG;CAAQ;CAChF,MAAM,QAAkC;EACtC,OAAO,CAAC;EAAG,SAAS,CAAC,WAAW,QAAQ;EAAG,QAAQ,CAAC,WAAW,QAAQ;EAAG,WAAW,CAAC,WAAW,QAAQ;EACzG,MAAM;GAAC;GAAU;GAAyB;GAAa;GAAY;EAAgB;EAAG,QAAQ;GAAC;GAAU;GAAc;GAAQ;GAAW;EAAQ;EAClJ,SAAS,CAAC,UAAU,YAAY;EAAG,MAAM;GAAC;GAAU;GAAc;EAAK;EAAG,UAAU,CAAC,UAAU,YAAY;EAAG,SAAS,CAAC,UAAU,YAAY;EAC9I,MAAM,CAAC,UAAU,YAAY;EAAG,QAAQ,CAAC,UAAU,YAAY;EAAG,QAAQ,CAAC,UAAU,YAAY;EAAG,OAAO,CAAC,UAAU,YAAY;EAClI,QAAQ;GAAC;GAAU;GAAc;EAAK;EACtC,QAAQ,CAAC,UAAU,YAAY;EAAG,MAAM;GAAC;GAAU;GAAc;EAAS;EAAG,OAAO,CAAC,UAAU,YAAY;EAC3G,oBAAoB,CAAC,UAAU,YAAY;EAC3C,QAAQ,CAAC,UAAU,SAAS;EAC5B,YAAY;GAAC;GAAU;GAAa;EAAM;CAC5C;CACA,IAAI,EAAE,WAAW,QAAQ,MAAM,IAAI,MAAM,mBAAmB,QAAQ,mBAAmB;CACvF,KAAK,MAAM,SAAS,QAClB,IAAI,MAAM,SAAS,YAAY,CAAC,MAAM,QAAQ,CAAC,SAAS,MAAM,IAAI,GAAG,MAAM,IAAI,MAAM,GAAG,QAAQ,qBAAqB,MAAM,MAAM;CAEnI,MAAM,aAAa,OAAO;CAC1B,MAAM,YAAY,OAAO;CACzB,IAAI,OAAO,UAAU,OAAO,SAAS,MAAM,IAAI,MAAM,wCAAwC;CAC7F,MAAM,QAAQ;EAAE,SAAS,OAAO;EAAS,QAAQ,OAAO;CAAO;CAC/D,IAAI,YAAY,cAAc;EAC5B,MAAM,MAAM,GAAG,GAAG,4EAA4E;EAC9F,MAAM,UAAU,KAAK,aAAa,QAAQ,UAAU,cAAc,QAAQ,QAAQ;EAClF,IAAI,CAAC,WAAW,OAAO,GAAG,MAAM,IAAI,MAAM,oCAAoC,QAAQ,8BAA8B;EACpH,MAAM,UAAU;GAAC;GAAS;GAAa,QAAQ,KAAK,EAAG;EAAC;EAIxD,IADoB,OAAO,MAAK,UAAS,MAAM,SAAS,YAAY,MAAM,SAAS,QACrE,GAAG,QAAQ,KAAK,YAAY,QAAQ,OAAO,MAAM,CAAC;EAChE,IAAI,OAAO,cAAc,KAAA,GAAW,QAAQ,KAAK,eAAe,OAAO,SAAS;EAChF,IAAI,OAAO,SAAS,KAAA,GAAW,QAAQ,KAAK,UAAU,OAAO,IAAI;EACjE,MAAM,SAAS,UAAU,QAAQ,UAAU,SAAS,EAAE,OAAO,UAAU,CAAC;EACxE,IAAI,OAAO,OAAO,MAAM,OAAO;EAC/B,QAAQ,WAAW,OAAO,UAAU;EACpC;CACF;CACA,IAAI,YAAY,SAAS;EAAE,MAAM,MAAM,GAAG,GAAG,OAAO;EAAG,MAAM,KAAK;EAAG;CAAQ;CAC7E,IAAI,YAAY,aAAa,YAAY,YAAY,YAAY,aAAa;EAC5E,MAAM,MAAM,GAAG,GAAG,GAAG,QAAQ,2CAA2C;EAExE,CADkB,YAAY,YAAY,qBAAqB,YAAY,WAAW,oBAAoB,qBAAA,CAChG,KAAK,IAAI,KAAK;EACxB,MAAM,CAAC,SAAS,kBAAkB,CAAC,CAAC,KAAI,UAAS,mBAAmB,KAAK,IAAI,OAAO,KAAqC,CAAC,CAAC;EAC3H;CACF;CACA,IAAI,YAAY,YAAY,OAAO,MAAM;EACvC,MAAM,MAAM,GAAG,GAAG,yDAAyD;EAC3E,MAAM,OAAO,OAAO;EAEpB,MAAM,UAAU,CADA,SAAS,kBACJ,CAAC,CAAC,KAAI,UAAS,mBAAmB,MAAM,OAAO,KAAK,CAAC;EAC1E,MAAM,OAAO;EACb,IAAI,CAAC,QAAQ,EAAE,CAAE,WAAW,QAAQ,WAAW;EAC/C;CACF;CACA,IAAI,YAAY,aAAa,OAAO,WAAW,OAAO,SAAS,MAAM,IAAI,MAAM,qDAAqD;CACpI,IAAI,YAAY,QAAQ;EACtB,MAAM,MAAM,GAAG,GAAG,wJAAwJ;EAC1K,MAAM,YAAY,OAAO,aAAa;EACtC,IAAI,CAAC,WAAW,SAAS,SAAsB,GAAG,MAAM,IAAI,MAAM,qBAAqB,UAAU,WAAW,WAAW,KAAK,IAAI,GAAG;EACnI,MAAM,WAAW,eAAe,MAAM,OAAO,aAAa,cAAc,SAAS,UAAU,cAAc,iBAAiB,YAAY,MAAM;EAC5I,MAAM,SAAS,OAAO,sBAAsB,aAAa,UAAU,QAAQ,aAAa,QAAQ,cAAc,SAAS,QAAQ,cAAc;EAC7I,IAAI,CAAC,eAAe,SAAS,MAAiC,GAAG,MAAM,IAAI,MAAM,0BAA0B,OAAO,WAAW,eAAe,KAAK,IAAI,GAAG;EACxJ,MAAM,WAAW,cAAc,WAAwB,UAAU,MAAiC;EAClG,IAAI,OAAO,0BAA0B,SAAS,sBAAsB;EACpE,UAAU,QAAQ,QAAQ,UAAU,CAAC,GAAG,EAAE,WAAW,KAAK,CAAC;EAC3D,cAAc,YAAY,GAAG,KAAK,UAAU,UAAU,MAAM,CAAC,EAAE,KAAK;GAAE,MAAM;GAAM,MAAM;EAAM,CAAC;EAC/F,MAAM;GAAE,QAAQ,QAAQ,UAAU;GAAG;GAAW;GAAU,eAAe;GAAQ,gBAAgB,SAAS;GAAqB,MAAM,cAAc,SAAS,gPAAgP,cAAc,SAAS,+QAA+Q;EAAsL,CAAC;EACz2B;CACF;CACA,IAAI,YAAY,UAAU;EACxB,QAAQ,WAAW,MAAM,eAAe,SAAS,UAAU,GAAG,CAAC,GAAG,MAAM,GAAI,OAAO,UAAU,CAAC,WAAW,IAAI,CAAC,CAAE,CAAC;EACjH;CACF;CACA,MAAM,SAAS,WAAW,UAAU;CACpC,IAAI,YAAY,UAAU;EACxB,MAAM,MAAM,GAAG,GAAG,sBAAsB;EACxC,MAAM,kBAAkB,QAAQ,UAAU,KAAK,EAAE,CAAC,CAAC;EACnD;CACF;CACA,IAAI,YAAY,UAAU;EACxB,MAAM,MAAM,GAAG,GAAG,mCAAmC;EACrD,MAAM,OAAO,KAAK,KAAK,iBAAiB,UAAU,KAAK,EAAE,CAAC,CAAC,CAAC,OAAO,KAAA;EACnE,IAAI;EACJ,IAAI,MAAM;GACR,kBAAkB,MAAM,MAAM;GAC9B,IAAI;GACJ,IAAI;IAAE,SAAS,sBAAsB,MAAM,MAAM;GAAG,SAC7C,OAAO;IACZ,IAAI,KAAK,cAAc,UAAW,MAAgC,SAAS,UAAU,MAAM;GAC7F;GACA,MAAM,YAAY,KAAK,SAAS,aAAa;GAC7C,MAAM,UAAU,SAAS,QAAQ,QAAQ,SAAS,IAAI,KAAA;GACtD,IAAI,UAAU,YAAY,KAAK,cAAc,UAAU,WAAW,OAAO,IAAI;IAC3E,cAAc,SAAS,IAAI;IAC3B,IAAI,KAAK,cAAc,UAAU,OAAO,WAAW,sBAAsB;KACvE,KAAK;KAAS,YAAY;KAC1B,KAAK;MAAE,GAAG,qBAAqB,MAAM;MAAG,GAAI,KAAK,cAAc,SAAS;OAAE,QAAQ,wBAAwB,QAAQ,SAAS,KAAK;OAAO,OAAO;OAAO,aAAa;OAAS,SAAS;MAAgB,IAAI,CAAC;KAAG;IAC9M;GACF;EACF;EACA,MAAM,WAAW,QAAQ,OAAO,WAAW,aAAa,UAAU,eAAe,KAAK,WAAW,KAAK,QAAQ,IAAI,CAAC;EACnH,MAAM,QAAQ,MAAM,QAAQ,IAAI,SAAS,IAAI,OAAO,EAAE,MAAM,YAAY;GAAE;GAAM,GAAG,MAAM,MAAM,KAAK,OAAO,aAAa,OAAO,YAAY,CAAC,KAAK,OAAO,UAAU,YAAY,OAAO,SAAS,GAAG,GAAG,KAAK,MAAM,CAAC,CAAC,IAAI,MAAM,MAAM;EAAE,EAAE,CAAC;EACtO,MAAM,gBAAgB,MAAM,QAAQ,IAAI,OAAO,aAAa,cAAc,IAAI,OAAO,MAAM,WAAW;GACpG,MAAM,2BAA2B,QAAQ;GACzC,GAAI,CAAC,OAAO,sBACR;IAAE,WAAW;IAAO,QAAQ;GAAoF,IAChH,MAAM,cAAc,UAAU,CAAC,sBAC7B;IAAE,WAAW;IAAO,QAAQ;GAA8L,IAC1N,MAAM,MAAM,MAAM,QAAQ,mBAAmB;EACrD,EAAE,CAAC;EACH,MAAM,cAAc,qBAAqB,MAAM;EAC/C,MAAM,qBAAqB;GAAC,GAAG,OAAO,aAAa;GAAe,GAAG,OAAO,aAAa;GAAQ,GAAG,OAAO,aAAa;GAAS,GAAI,OAAO,WAAW,YAAY,CAAC;EAAE;EACtK,MAAM,YAAY,CAAC,GAAG,IAAI,IAAI,mBAAmB,KAAK,CAAC,CAAC,SAAQ,QAAO,CAAC,GAAG,IAAI,SAAS,0BAA0B,CAAC,CAAC,CAAC,KAAI,UAAS,MAAM,EAAE,CAAC,CAAC,CAAC;EAC7I,MAAM,SAAS;GACb;IAAE,MAAM;IAA8B,WAAW,OAAO;IAAqB,QAAQ,OAAO,oBAAoB;GAAuF;GACvM,GAAI,OAAO,YAAY,CAAC;IAAE,MAAM;IAAwB,GAAG,MAAM,MAAM,CAAC,eAAe,GAAG,MAAM;IAAG,MAAM,OAAO,UAAU;IAAM,SAAS,OAAO,UAAU;GAAQ,CAAC,IAAI,CAAC;GACxK,GAAG;GAAO,GAAG;GACb,GAAG,UAAU,KAAI,UAAS;IAAE;IAAM,WAAW,QAAQ,YAAY,KAAK;IAAG,QAAQ,YAAY,QAAQ,yEAAyE,OAAO,KAAK;GAAuC,EAAE;EACrO;EACA,MAAM;GAAE,WAAW,MAAM,aAAa;GAAM,UAAU,MAAM,YAAY;GAAM;GAAQ,MAAM,OAAO,2GAA2G;GAAyF,OAAO;EAAmF,CAAC;EAClY,IAAI,OAAO,MAAK,UAAS,CAAC,MAAM,SAAS,GAAG,QAAQ,WAAW;EAC/D;CACF;CACA,MAAM,oBAAoB,YAAY,mBAAmB;EACvD,MAAM,MAAM,GAAG,GAAG,uBAAuB;EACzC,MAAM,cAAc,iBAAiB,UAAU,KAAK,EAAE,CAAC;EACvD,kBAAkB,YAAY,MAAM,MAAM;EAC1C,sBAAsB,YAAY,MAAM,MAAM;EAC9C,OAAO;CACT,EAAA,CAAG,IAAI,KAAA;CACP,MAAM,QAAQ,IAAI,MAAM,OAAO,QAAQ;CACvC,IAAI;EACF,IAAI,YAAY,WAAW;GACzB,MAAM,EAAE,MAAM,cAAc;GAC5B,MAAM,KAAK,MAAM,QAAQ,MAAM,QAAQ,SAAS,CAAC,CAAC;EACpD,OAAO,IAAI,YAAY,QAAQ;GAC7B,MAAM,MAAM,GAAG,GAAG,kBAAkB;GACpC,MAAM,SAAS,MAAM,UAAU,OAAO,QAAQ,EAAE,SAAS,OAAO,QAAQ,CAAC;GACzE,MAAM,MAAM;GACZ,IAAI,OAAO,SAAS,OAAO,QAAQ,MAAK,UAAS,MAAM,WAAW,OAAO,GAAG,QAAQ,WAAW;EACjG,OAAO,IAAI,YAAY,SAAS;GAC9B,MAAM,MAAM,GAAG,GAAG,OAAO;GACzB,MAAM,MAAM,aAAa,CAAC;EAC5B,OAAO,IAAI,YAAY,UAAU;GAC/B,MAAM,MAAM,GAAG,GAAG,aAAa;GAC/B,MAAM,KAAK,KAAK,MAAM,IAAI,KAAK,EAAE,IAAI,MAAM,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC;EAC7D,OAAO,IAAI,YAAY,UAAU;GAC/B,MAAM,MAAM,GAAG,GAAG,aAAa;GAC/B,MAAM,MAAM,OAAO,KAAK,EAAE,CAAC;EAC7B,OAAO,IAAI,YAAY,QAAQ;GAC7B,IAAI,OAAO,KAAK;IACd,MAAM,MAAM,GAAG,GAAG,YAAY;IAC9B,MAAM,MAAM,cAAc,OAAO,EAAE,UAAU,CAAC,CAAC;GACjD,OAAO;IACL,MAAM,MAAM,GAAG,GAAG,WAAW;IAC7B,MAAM,SAAS,MAAM,SAAS,OAAO,KAAK,IAAI,EAAE,UAAU,CAAC;IAC3D,MAAM,MAAM;IACZ,IAAI,OAAO,IAAI,WAAW,aAAa,OAAO,IAAI,WAAW,UAAU,QAAQ,WAAW;GAC5F;EACF,OAAO,IAAI,YAAY,YAAY;GACjC,MAAM,MAAM,GAAG,GAAG,yCAAyC;GAC3D,QAAQ,MAAM,aAAa,OAAO,KAAK,IAAI,KAAK,IAAI,KAAK,KAAK,UAAU,KAAK,EAAE,IAAI,KAAA,GAAW,EAAE,UAAU,CAAC,CAAC;EAC9G,OAAO,IAAI,YAAY,WAAW;GAChC,MAAM,MAAM,GAAG,GAAG,wBAAwB;GAC1C,QAAQ,YAAY,OAAO,KAAK,IAAI,KAAK,IAAI,EAAE,UAAU,CAAC,CAAC;EAC7D,OAAO,IAAI,YAAY,QAAQ;GAC7B,MAAM,MAAM,GAAG,GAAG,WAAW;GAC7B,MAAM,aAAa,IAAI,gBAAgB;GACvC,MAAM,aAAmB,WAAW,MAAM;GAC1C,QAAQ,GAAG,UAAU,IAAI;GACzB,QAAQ,GAAG,WAAW,IAAI;GAC1B,IAAI;IAAE,QAAQ,MAAM,QAAQ,OAAO,QAAQ,KAAK,IAAI;KAAE,QAAQ,WAAW;KAAQ;IAAU,CAAC,CAAC;GAAG,UACxF;IAAE,QAAQ,eAAe,UAAU,IAAI;IAAG,QAAQ,eAAe,WAAW,IAAI;GAAG;EAC7F,OAAO,IAAI,YAAY,oBAAoB;GACzC,MAAM,MAAM,GAAG,GAAG,8CAA8C;GAChE,MAAM,EAAE,MAAM,cAAc,iBAAiB,UAAU,KAAK,EAAE,CAAC;GAC/D,MAAM,KAAK,MAAM,gBAAgB,KAAK,IAAI,MAAM,SAAS,CAAC,CAAC;EAC7D,OAAO,IAAI,YAAY,UAAU;GAC/B,IAAI,OAAO,KAAK;IACd,MAAM,MAAM,GAAG,GAAG,cAAc;IAChC,MAAM,WAAW,MAAM,gBAAgB,OAAO,MAAM;IACpD,MAAM,QAAQ;IACd,IAAI,SAAS,MAAK,YAAW,QAAQ,KAAK,GAAG,QAAQ,WAAW;GAClE,OAAO;IACL,MAAM,MAAM,GAAG,GAAG,aAAa;IAC/B,MAAM,MAAM,UAAU,OAAO,QAAQ,KAAK,EAAE,CAAC;GAC/C;EACF,OAAO,IAAI,YAAY,SAAS;GAC9B,MAAM,MAAM,GAAG,GAAG,YAAY;GAC9B,MAAM,KAAK,MAAM,WAAW,KAAK,KAAI,QAAO;IAC1C,IAAI,CAAC;KAAC;KAAW;KAAS;IAAO,CAAC,CAAC,SAAS,IAAI,MAAM,GAAG,MAAM,IAAI,MAAM,gBAAgB,IAAI,OAAO,mDAAmD;IACvJ,IAAI,IAAI,MAAM,MAAM,IAAI,MAAM,iEAAiE;IAC/F,IAAI,IAAI,mBAAmB,MAAM,IAAI,MAAM,+GAA+G;IAC1J,MAAM,gBAAgB;KAAE,GAAG;KAAQ,eAAe,OAAO;IAAc;IAEvE,MAAM,QADe,0BAA0B,KAAK,aACb,IAAI;KAAE,GAAG,uBAAuB;KAAG,OAAO;MAAC;MAAU;MAAU;KAAS,CAAC,CAAC,SAAS,IAAI,KAAK,IAAI,WAAW,IAAI;IAAM,IAAI,CAAC;IACjK,kBAAkB,IAAI,MAAM,aAAa;IACzC,OAAO;KAAE,GAAG;KAAO,QAAQ;KAAe,QAAQ;KAAU,gBAAgB;KAAM,QAAQ,KAAK,IAAI;KAAG,OAAO;IAAK;GACpH,CAAC,CAAC,CAAC;EACL,OAAO,MAAM,IAAI,MAAM,mBAAmB,QAAQ,aAAa;CACjE,UAAU;EAAE,MAAM,MAAM;CAAG;AAC7B;AAEA,KAAK,CAAC,CAAC,OAAM,UAAS;CAAE,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,QAAQ,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC;CAAG,QAAQ,WAAW;AAAG,CAAC"}
|
package/dist/config.js
CHANGED
|
@@ -67,8 +67,10 @@ function loadConfig(path = "factory.json") {
|
|
|
67
67
|
}
|
|
68
68
|
if (config.apple?.exportOptionsPlist) config.apple.exportOptionsPlist = resolve(root, config.apple.exportOptionsPlist);
|
|
69
69
|
if (config.obfuscation) {
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
if (config.obfuscation.configPath) {
|
|
71
|
+
config.obfuscation.configPath = resolve(root, config.obfuscation.configPath);
|
|
72
|
+
if (!existsSync(config.obfuscation.configPath) || !lstatSync(config.obfuscation.configPath).isFile()) throw new Error(`obfuscation.configPath must name an existing regular file: ${config.obfuscation.configPath}`);
|
|
73
|
+
}
|
|
72
74
|
}
|
|
73
75
|
if (config.inbox) {
|
|
74
76
|
config.inbox.directory = resolve(root, config.inbox.directory);
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","names":[],"sources":["../src/config.ts"],"sourcesContent":["import { readFileSync, existsSync, realpathSync, lstatSync } from 'node:fs';\nimport { basename, dirname, resolve, isAbsolute, relative, sep } from 'node:path';\nimport { z } from 'zod';\nimport { ConfigSchema, SpecSchema, toError } from './schemas.js';\nimport type { Config, Spec } from './schemas.js';\n\nexport function loadJSON(path: string): unknown {\n try { return JSON.parse(readFileSync(path, 'utf8')) as unknown; }\n catch (cause) { throw new Error(`Cannot read JSON at ${path}: ${toError(cause).message}`); }\n}\n\nexport function validateSpec(spec: unknown): Spec {\n return SpecSchema.parse(spec);\n}\n\nexport function canonicalPath(path: string): string {\n const absolute = resolve(path);\n if (existsSync(absolute)) return realpathSync(absolute);\n if (lstatSync(absolute, { throwIfNoEntry: false })?.isSymbolicLink()) throw new Error(`Cannot resolve dangling symlink at ${absolute}; point it to an existing directory before continuing`);\n return resolve(canonicalPath(dirname(absolute)), basename(absolute));\n}\n\nexport function normalizeIsolationPaths(config: Config): void {\n if (!config.isolation) return;\n const root = config.configPath ? dirname(resolve(config.configPath)) : process.cwd();\n const protectedPaths = [config.stateDir, config.workspaceRoot, ...(config.configPath ? [config.configPath] : [])].map(path => canonicalPath(resolve(root, path)));\n const contains = (parent: string, child: string): boolean => {\n const path = relative(parent, child);\n return path === '' || path !== '..' && !path.startsWith(`..${sep}`) && !isAbsolute(path);\n };\n config.isolation.readOnlyPaths = [...new Set(config.isolation.readOnlyPaths.map(path => {\n const absolute = canonicalPath(resolve(root, path));\n const info = lstatSync(absolute, { throwIfNoEntry: false });\n if (!info || !info.isDirectory() && !info.isFile()) throw new Error(`Isolation read-only path must exist as a regular file or directory: ${path}`);\n if (protectedPaths.some(protectedPath => contains(absolute, protectedPath) || contains(protectedPath, absolute))) throw new Error('Isolation read-only paths must not expose control state, configuration or other task workspaces');\n return absolute;\n }))];\n}\n\nexport function loadConfig(path = 'factory.json'): Config & { configPath: string } {\n const configPath = resolve(path);\n const source = z.record(z.string(), z.unknown()).parse(loadJSON(configPath));\n const legacyKeys = ['builder', 'reviewer', 'researcher', 'agentEnv', 'maxAgentCalls', 'maxConcurrentJobs'].filter(key => key in source);\n if (legacyKeys.length) throw new Error(`Legacy provider/daemon configuration is not supported (${legacyKeys.join(', ')}). Remove builder/reviewer/researcher/maxConcurrentJobs, rename agentEnv to executionEnv and maxAgentCalls to maxHostTurns. Models and authentication now belong to your host. Existing queue snapshots are migrated without deleting task history.`);\n const root = dirname(configPath);\n const config = ConfigSchema.parse({\n ...source, configPath,\n stateDir: resolve(root, z.string().min(1).default('.factory').parse(source.stateDir)),\n workspaceRoot: resolve(root, z.string().min(1).default('workspaces').parse(source.workspaceRoot)),\n });\n if (config.toolchain) {\n config.toolchain.flutterSdk = resolve(root, config.toolchain.flutterSdk);\n if (existsSync(config.toolchain.flutterSdk)) config.toolchain.flutterSdk = realpathSync(config.toolchain.flutterSdk);\n const workspace = existsSync(config.workspaceRoot) ? realpathSync(config.workspaceRoot) : config.workspaceRoot;\n const child = relative(workspace, config.toolchain.flutterSdk);\n if (!child || !(child === '..' || child.startsWith(`..${sep}`) || isAbsolute(child))) throw new Error('toolchain.flutterSdk must be outside workspaceRoot so verification does not trust an agent-writable SDK');\n }\n if (config.apple?.exportOptionsPlist) config.apple.exportOptionsPlist = resolve(root, config.apple.exportOptionsPlist);\n if (config.obfuscation) {\n config.obfuscation.configPath = resolve(root, config.obfuscation.configPath);\n if (!existsSync(config.obfuscation.configPath) || !lstatSync(config.obfuscation.configPath).isFile()) throw new Error(`obfuscation.configPath must name an existing regular file: ${config.obfuscation.configPath}`);\n }\n if (config.inbox) {\n config.inbox.directory = resolve(root, config.inbox.directory);\n const workspace = canonicalPath(config.workspaceRoot);\n const inbox = canonicalPath(config.inbox.directory);\n const child = relative(workspace, inbox);\n if (!child || !(child === '..' || child.startsWith(`..${sep}`) || isAbsolute(child))) throw new Error('inbox.directory must be outside workspaceRoot so agent output cannot become new requirements');\n }\n if (!config.allowLocalExecution) config.executionWarning = 'Local execution is disabled. Use a dedicated OS account or VM, then set allowLocalExecution=true; a workspace is not a security sandbox.';\n const state = canonicalPath(config.stateDir), workspace = canonicalPath(config.workspaceRoot);\n if ([relative(workspace, state), relative(state, workspace)].some(child => !child || !(child === '..' || child.startsWith(`..${sep}`) || isAbsolute(child)))) throw new Error('stateDir and workspaceRoot must not overlap in either direction so host tools do not own task state');\n normalizeIsolationPaths(config);\n return { ...config, configPath };\n}\n\nexport function validateProjectSource(spec: Spec, config: Config): string | undefined {\n if (!spec.project?.sourceDir) return undefined;\n const root = config.configPath ? dirname(resolve(config.configPath)) : process.cwd();\n const source = resolve(root, spec.project.sourceDir);\n const info = lstatSync(source);\n if (info.isSymbolicLink() || !info.isDirectory()) throw new Error('project.sourceDir must identify a real directory, not a symlink');\n const sourceDirectory = canonicalPath(source);\n for (const path of [config.stateDir, config.workspaceRoot]) {\n const reserved = canonicalPath(resolve(root, path));\n if ([relative(reserved, sourceDirectory), relative(sourceDirectory, reserved)].some(child => !child || !(child === '..' || child.startsWith(`..${sep}`) || isAbsolute(child)))) throw new Error('project.sourceDir must not overlap stateDir or workspaceRoot in either direction');\n }\n return sourceDirectory;\n}\n\nexport function inside(root: string, path: string): string {\n const resolved = resolve(root, path);\n const child = relative(root, resolved);\n if (!child || child === '..' || child.startsWith(`..${sep}`) || isAbsolute(child)) throw new Error(`Expected a path inside the workspace: ${path}`);\n const actual = relative(canonicalPath(root), canonicalPath(resolved));\n if (!actual || actual === '..' || actual.startsWith(`..${sep}`) || isAbsolute(actual)) throw new Error(`Workspace path escapes through a symlink: ${path}`);\n return resolved;\n}\n\nexport function expandArgv(argv: string[], env: NodeJS.ProcessEnv): string[] {\n return argv.map(arg => arg.replace(/\\$\\{([A-Z][A-Z0-9_]*)\\}/g, (_, key: string) => {\n if (/^(ASC_|APPLE_|FASTLANE_|MATCH_)/.test(key) || !env[key]) throw Object.assign(new Error(`Verification requires ${key} in the allowed worker environment; publisher secrets cannot be command arguments`), { code: 'SETUP_REQUIRED' });\n return env[key];\n }));\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"config.js","names":[],"sources":["../src/config.ts"],"sourcesContent":["import { readFileSync, existsSync, realpathSync, lstatSync } from 'node:fs';\nimport { basename, dirname, resolve, isAbsolute, relative, sep } from 'node:path';\nimport { z } from 'zod';\nimport { ConfigSchema, SpecSchema, toError } from './schemas.js';\nimport type { Config, Spec } from './schemas.js';\n\nexport function loadJSON(path: string): unknown {\n try { return JSON.parse(readFileSync(path, 'utf8')) as unknown; }\n catch (cause) { throw new Error(`Cannot read JSON at ${path}: ${toError(cause).message}`); }\n}\n\nexport function validateSpec(spec: unknown): Spec {\n return SpecSchema.parse(spec);\n}\n\nexport function canonicalPath(path: string): string {\n const absolute = resolve(path);\n if (existsSync(absolute)) return realpathSync(absolute);\n if (lstatSync(absolute, { throwIfNoEntry: false })?.isSymbolicLink()) throw new Error(`Cannot resolve dangling symlink at ${absolute}; point it to an existing directory before continuing`);\n return resolve(canonicalPath(dirname(absolute)), basename(absolute));\n}\n\nexport function normalizeIsolationPaths(config: Config): void {\n if (!config.isolation) return;\n const root = config.configPath ? dirname(resolve(config.configPath)) : process.cwd();\n const protectedPaths = [config.stateDir, config.workspaceRoot, ...(config.configPath ? [config.configPath] : [])].map(path => canonicalPath(resolve(root, path)));\n const contains = (parent: string, child: string): boolean => {\n const path = relative(parent, child);\n return path === '' || path !== '..' && !path.startsWith(`..${sep}`) && !isAbsolute(path);\n };\n config.isolation.readOnlyPaths = [...new Set(config.isolation.readOnlyPaths.map(path => {\n const absolute = canonicalPath(resolve(root, path));\n const info = lstatSync(absolute, { throwIfNoEntry: false });\n if (!info || !info.isDirectory() && !info.isFile()) throw new Error(`Isolation read-only path must exist as a regular file or directory: ${path}`);\n if (protectedPaths.some(protectedPath => contains(absolute, protectedPath) || contains(protectedPath, absolute))) throw new Error('Isolation read-only paths must not expose control state, configuration or other task workspaces');\n return absolute;\n }))];\n}\n\nexport function loadConfig(path = 'factory.json'): Config & { configPath: string } {\n const configPath = resolve(path);\n const source = z.record(z.string(), z.unknown()).parse(loadJSON(configPath));\n const legacyKeys = ['builder', 'reviewer', 'researcher', 'agentEnv', 'maxAgentCalls', 'maxConcurrentJobs'].filter(key => key in source);\n if (legacyKeys.length) throw new Error(`Legacy provider/daemon configuration is not supported (${legacyKeys.join(', ')}). Remove builder/reviewer/researcher/maxConcurrentJobs, rename agentEnv to executionEnv and maxAgentCalls to maxHostTurns. Models and authentication now belong to your host. Existing queue snapshots are migrated without deleting task history.`);\n const root = dirname(configPath);\n const config = ConfigSchema.parse({\n ...source, configPath,\n stateDir: resolve(root, z.string().min(1).default('.factory').parse(source.stateDir)),\n workspaceRoot: resolve(root, z.string().min(1).default('workspaces').parse(source.workspaceRoot)),\n });\n if (config.toolchain) {\n config.toolchain.flutterSdk = resolve(root, config.toolchain.flutterSdk);\n if (existsSync(config.toolchain.flutterSdk)) config.toolchain.flutterSdk = realpathSync(config.toolchain.flutterSdk);\n const workspace = existsSync(config.workspaceRoot) ? realpathSync(config.workspaceRoot) : config.workspaceRoot;\n const child = relative(workspace, config.toolchain.flutterSdk);\n if (!child || !(child === '..' || child.startsWith(`..${sep}`) || isAbsolute(child))) throw new Error('toolchain.flutterSdk must be outside workspaceRoot so verification does not trust an agent-writable SDK');\n }\n if (config.apple?.exportOptionsPlist) config.apple.exportOptionsPlist = resolve(root, config.apple.exportOptionsPlist);\n if (config.obfuscation) {\n if (config.obfuscation.configPath) {\n config.obfuscation.configPath = resolve(root, config.obfuscation.configPath);\n if (!existsSync(config.obfuscation.configPath) || !lstatSync(config.obfuscation.configPath).isFile()) throw new Error(`obfuscation.configPath must name an existing regular file: ${config.obfuscation.configPath}`);\n }\n }\n if (config.inbox) {\n config.inbox.directory = resolve(root, config.inbox.directory);\n const workspace = canonicalPath(config.workspaceRoot);\n const inbox = canonicalPath(config.inbox.directory);\n const child = relative(workspace, inbox);\n if (!child || !(child === '..' || child.startsWith(`..${sep}`) || isAbsolute(child))) throw new Error('inbox.directory must be outside workspaceRoot so agent output cannot become new requirements');\n }\n if (!config.allowLocalExecution) config.executionWarning = 'Local execution is disabled. Use a dedicated OS account or VM, then set allowLocalExecution=true; a workspace is not a security sandbox.';\n const state = canonicalPath(config.stateDir), workspace = canonicalPath(config.workspaceRoot);\n if ([relative(workspace, state), relative(state, workspace)].some(child => !child || !(child === '..' || child.startsWith(`..${sep}`) || isAbsolute(child)))) throw new Error('stateDir and workspaceRoot must not overlap in either direction so host tools do not own task state');\n normalizeIsolationPaths(config);\n return { ...config, configPath };\n}\n\nexport function validateProjectSource(spec: Spec, config: Config): string | undefined {\n if (!spec.project?.sourceDir) return undefined;\n const root = config.configPath ? dirname(resolve(config.configPath)) : process.cwd();\n const source = resolve(root, spec.project.sourceDir);\n const info = lstatSync(source);\n if (info.isSymbolicLink() || !info.isDirectory()) throw new Error('project.sourceDir must identify a real directory, not a symlink');\n const sourceDirectory = canonicalPath(source);\n for (const path of [config.stateDir, config.workspaceRoot]) {\n const reserved = canonicalPath(resolve(root, path));\n if ([relative(reserved, sourceDirectory), relative(sourceDirectory, reserved)].some(child => !child || !(child === '..' || child.startsWith(`..${sep}`) || isAbsolute(child)))) throw new Error('project.sourceDir must not overlap stateDir or workspaceRoot in either direction');\n }\n return sourceDirectory;\n}\n\nexport function inside(root: string, path: string): string {\n const resolved = resolve(root, path);\n const child = relative(root, resolved);\n if (!child || child === '..' || child.startsWith(`..${sep}`) || isAbsolute(child)) throw new Error(`Expected a path inside the workspace: ${path}`);\n const actual = relative(canonicalPath(root), canonicalPath(resolved));\n if (!actual || actual === '..' || actual.startsWith(`..${sep}`) || isAbsolute(actual)) throw new Error(`Workspace path escapes through a symlink: ${path}`);\n return resolved;\n}\n\nexport function expandArgv(argv: string[], env: NodeJS.ProcessEnv): string[] {\n return argv.map(arg => arg.replace(/\\$\\{([A-Z][A-Z0-9_]*)\\}/g, (_, key: string) => {\n if (/^(ASC_|APPLE_|FASTLANE_|MATCH_)/.test(key) || !env[key]) throw Object.assign(new Error(`Verification requires ${key} in the allowed worker environment; publisher secrets cannot be command arguments`), { code: 'SETUP_REQUIRED' });\n return env[key];\n }));\n}\n"],"mappings":"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"}
|