apphx 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/README.md +52 -138
  2. package/benchmarks/peer-context-worker.mjs +186 -0
  3. package/benchmarks/peer-context.mjs +150 -0
  4. package/dist/apple-types.js.map +1 -1
  5. package/dist/cli.js +373 -121
  6. package/dist/cli.js.map +1 -1
  7. package/dist/config.js +42 -4
  8. package/dist/config.js.map +1 -1
  9. package/dist/dependencies.js +455 -16
  10. package/dist/dependencies.js.map +1 -1
  11. package/dist/export-options.js +44 -2
  12. package/dist/export-options.js.map +1 -1
  13. package/dist/flutter.js +13 -25
  14. package/dist/flutter.js.map +1 -1
  15. package/dist/go-dependencies.js +389 -0
  16. package/dist/go-dependencies.js.map +1 -0
  17. package/dist/inbox.js +7 -8
  18. package/dist/inbox.js.map +1 -1
  19. package/dist/integrations.js +29 -29
  20. package/dist/integrations.js.map +1 -1
  21. package/dist/isolation.js +190 -0
  22. package/dist/isolation.js.map +1 -0
  23. package/dist/macos.js +57 -0
  24. package/dist/macos.js.map +1 -0
  25. package/dist/mygo-build.js +55 -0
  26. package/dist/mygo-build.js.map +1 -0
  27. package/dist/policy.js +35 -0
  28. package/dist/policy.js.map +1 -0
  29. package/dist/preflight.js +1 -1
  30. package/dist/process.js +3 -3
  31. package/dist/project-profiles.js +163 -0
  32. package/dist/project-profiles.js.map +1 -0
  33. package/dist/proof.js +33 -0
  34. package/dist/proof.js.map +1 -0
  35. package/dist/remote.js +1 -1
  36. package/dist/runner.js +269 -287
  37. package/dist/runner.js.map +1 -1
  38. package/dist/scheduler.js +0 -3
  39. package/dist/scheduler.js.map +1 -1
  40. package/dist/schemas.js +156 -44
  41. package/dist/schemas.js.map +1 -1
  42. package/dist/store.js +166 -44
  43. package/dist/store.js.map +1 -1
  44. package/dist/vendor/obfuscator/dist/cli.js +72 -0
  45. package/dist/vendor/obfuscator/dist/cli.js.map +1 -0
  46. package/dist/vendor/obfuscator/dist/code.js +585 -0
  47. package/dist/vendor/obfuscator/dist/code.js.map +1 -0
  48. package/dist/vendor/obfuscator/dist/common.js +262 -0
  49. package/dist/vendor/obfuscator/dist/common.js.map +1 -0
  50. package/dist/vendor/obfuscator/dist/config.js +123 -0
  51. package/dist/vendor/obfuscator/dist/config.js.map +1 -0
  52. package/dist/vendor/obfuscator/dist/content.js +89 -0
  53. package/dist/vendor/obfuscator/dist/content.js.map +1 -0
  54. package/dist/vendor/obfuscator/dist/obfuscate.js +93 -0
  55. package/dist/vendor/obfuscator/dist/obfuscate.js.map +1 -0
  56. package/dist/vendor/obfuscator/dist/png.js +283 -0
  57. package/dist/vendor/obfuscator/dist/png.js.map +1 -0
  58. package/dist/vendor/obfuscator/dist/project.js +159 -0
  59. package/dist/vendor/obfuscator/dist/project.js.map +1 -0
  60. package/dist/vendor/obfuscator/dist/resources.js +335 -0
  61. package/dist/vendor/obfuscator/dist/resources.js.map +1 -0
  62. package/dist/vendor/obfuscator/package.json +22 -0
  63. package/dist/workspace.js +113 -0
  64. package/dist/workspace.js.map +1 -0
  65. package/evals/control.mjs +73 -0
  66. package/evals/expectations.mjs +37 -0
  67. package/evals/host.mjs +51 -0
  68. package/evals/oracle.mjs +80 -0
  69. package/evals/policy.mjs +268 -0
  70. package/examples/android-java.factory.json +18 -0
  71. package/examples/android-java.json +16 -0
  72. package/examples/existing-project.factory.json +18 -0
  73. package/examples/existing-project.json +17 -0
  74. package/examples/expo.eas.json +17 -0
  75. package/examples/expo.factory.json +18 -0
  76. package/examples/expo.json +16 -0
  77. package/examples/factory.json +0 -2
  78. package/examples/flutter.factory.json +13 -0
  79. package/examples/flutter.json +16 -0
  80. package/examples/luggage.json +5 -3
  81. package/examples/mygo-web.factory.json +18 -0
  82. package/examples/mygo-web.json +16 -0
  83. package/examples/mygo.factory.json +18 -0
  84. package/examples/mygo.json +16 -0
  85. package/examples/react-native.factory.json +18 -0
  86. package/examples/react-native.json +16 -0
  87. package/examples/remote.json +1 -1
  88. package/examples/runtime/android-java/app/build.gradle +7 -0
  89. package/examples/runtime/android-java/app/src/main/AndroidManifest.xml +8 -0
  90. package/examples/runtime/android-java/app/src/main/java/dev/apphx/runtime/MainActivity.java +44 -0
  91. package/examples/runtime/android-java/sdk-build.mjs +29 -0
  92. package/examples/runtime/android-java/settings.gradle +2 -0
  93. package/examples/runtime/android-ui.mjs +70 -0
  94. package/examples/runtime/mygo-native/go.mod +13 -0
  95. package/examples/runtime/mygo-native/go.sum +10 -0
  96. package/examples/runtime/mygo-native/main.go +173 -0
  97. package/examples/runtime/mygo-native/main_test.go +14 -0
  98. package/examples/runtime/mygo-native/mygo.json +1 -0
  99. package/examples/runtime/mygo-web/bun.lock +15 -0
  100. package/examples/runtime/mygo-web/go.mod +9 -0
  101. package/examples/runtime/mygo-web/go.sum +8 -0
  102. package/examples/runtime/mygo-web/index.html +1 -0
  103. package/examples/runtime/mygo-web/main.go +60 -0
  104. package/examples/runtime/mygo-web/mygo.config.ts +10 -0
  105. package/examples/runtime/mygo-web/package.json +1 -0
  106. package/examples/runtime/mygo-web/src/main.ts +23 -0
  107. package/examples/runtime/mygo-web/src/mygo.ts +14 -0
  108. package/examples/swift.factory.json +18 -0
  109. package/examples/swift.json +16 -0
  110. package/examples/uni-app.factory.json +18 -0
  111. package/examples/uni-app.json +16 -0
  112. package/package.json +12 -5
  113. package/scripts/bundle-obfuscator.mjs +19 -0
  114. package/scripts/runtime-smoke.mjs +209 -0
  115. package/skills/apphx/SKILL.md +180 -0
  116. package/skills/apphx/resources/google-play-research-result.json +6 -0
  117. package/skills/apphx/resources/local-research-result.json +6 -0
  118. package/skills/{apple-app-factory → apphx}/resources/requirement.json +5 -8
  119. package/skills/apphx/resources/research-result.json +12 -0
  120. package/skills/apphx/resources/review-result.json +7 -0
  121. package/dist/apple.js +0 -900
  122. package/dist/apple.js.map +0 -1
  123. package/skills/apple-app-factory/SKILL.md +0 -103
  124. package/skills/apple-app-factory/resources/research-result.json +0 -21
  125. package/skills/apple-app-factory/resources/review-result.json +0 -7
  126. /package/skills/{apple-app-factory → apphx}/LICENSE +0 -0
@@ -0,0 +1,55 @@
1
+ import { basename, posix } from "node:path";
2
+ // src/mygo-build.ts
3
+ /** Accept a direct, local MyGo build, never a wrapper that can add publishing flags. */
4
+ function validateMyGoPackaging(config, screenshotsDir) {
5
+ const profile = config.packaging;
6
+ if (!profile || profile.provider !== "local" || profile.commands.length !== 1) throw Object.assign(/* @__PURE__ */ new Error("MyGo requires one direct local build command"), { code: "SETUP_REQUIRED" });
7
+ const argv = profile.commands[0];
8
+ let start;
9
+ if (basename(argv[0]) === "mygo" && argv[1] === "build") start = 2;
10
+ else if (basename(argv[0]) === "go" && argv[1] === "tool" && argv[2] === "mygo" && argv[3] === "build") start = 4;
11
+ else if (basename(argv[0]) === "go" && argv[1] === "run" && /^github\.com\/egoist\/mygo\/cmd\/mygo@v\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(argv[2] ?? "") && argv[3] === "build") start = 4;
12
+ else throw Object.assign(/* @__PURE__ */ new Error("MyGo packaging must use a pinned go tool mygo build, installed mygo build, or version-pinned go run command"), { code: "SETUP_REQUIRED" });
13
+ const flags = /* @__PURE__ */ new Map();
14
+ for (let index = start; index < argv.length; index++) {
15
+ const flag = argv[index];
16
+ if (flags.has(flag)) throw Object.assign(/* @__PURE__ */ new Error(`Duplicate MyGo build flag: ${flag}`), { code: "SETUP_REQUIRED" });
17
+ if (flag === "-sign" || flag === "-platform" || flag === "-o") {
18
+ const value = argv[++index];
19
+ if (!value) throw Object.assign(/* @__PURE__ */ new Error(`Missing MyGo flag value: ${flag}`), { code: "SETUP_REQUIRED" });
20
+ flags.set(flag, value);
21
+ } else if (flag === "-skip-notarize" || flag === "-skip-dmg" || flag === "-skip-build-command") flags.set(flag, "true");
22
+ else throw Object.assign(/* @__PURE__ */ new Error(`MyGo local packaging does not permit ${flag}; upload, notarization and custom wrapper commands are out of scope`), { code: "SETUP_REQUIRED" });
23
+ }
24
+ if (flags.get("-sign") !== "-" || !flags.has("-skip-notarize")) throw Object.assign(/* @__PURE__ */ new Error("MyGo local builds require -sign - and -skip-notarize, even when project configuration enables signing/notarization"), { code: "SETUP_REQUIRED" });
25
+ const platform = flags.get("-platform");
26
+ if (!platform || !/^darwin\/(?:arm64|amd64|universal)$/.test(platform)) throw Object.assign(/* @__PURE__ */ new Error("MyGo packaging requires one explicit darwin/arm64, darwin/amd64 or darwin/universal target"), { code: "SETUP_REQUIRED" });
27
+ if (flags.get("-o") !== "build") throw Object.assign(/* @__PURE__ */ new Error("MyGo packaging requires -o build so output cannot replace project source"), { code: "SETUP_REQUIRED" });
28
+ const prefix = `build/${platform.replace("/", "-")}/`;
29
+ if (!profile.artifactPath.startsWith(prefix)) throw Object.assign(/* @__PURE__ */ new Error(`MyGo artifactPath must be inside ${prefix}`), { code: "SETUP_REQUIRED" });
30
+ if (screenshotsDir !== void 0) {
31
+ const screenshot = posix.normalize(screenshotsDir);
32
+ if (posix.isAbsolute(screenshot) || screenshot === ".." || screenshot.startsWith("../") || screenshot.includes("\\")) throw Object.assign(/* @__PURE__ */ new Error("MyGo screenshotsDir must stay within the selected project"), { code: "SETUP_REQUIRED" });
33
+ const outputDirectory = prefix.slice(0, -1);
34
+ if ([posix.relative(outputDirectory, screenshot), posix.relative(screenshot, outputDirectory)].some((path) => path === "" || path !== ".." && !path.startsWith("../") && !posix.isAbsolute(path))) throw Object.assign(/* @__PURE__ */ new Error("MyGo screenshotsDir must not overlap the platform output directory replaced during packaging"), { code: "SETUP_REQUIRED" });
35
+ }
36
+ if (config.packageTarget === "app" ? !flags.has("-skip-dmg") : flags.has("-skip-dmg")) throw Object.assign(/* @__PURE__ */ new Error("MyGo app builds require -skip-dmg; dmg builds must create the disk image"), { code: "SETUP_REQUIRED" });
37
+ }
38
+ /** Doctor and tracked execution share the same gate for every recognizable direct build. */
39
+ function validateMyGoCommand(config, argv) {
40
+ const tool = basename(argv[0] ?? "");
41
+ const buildIndex = argv.indexOf("build");
42
+ if (buildIndex <= 0) return;
43
+ if (!(tool === "mygo" || tool === "go" && argv.slice(1, buildIndex).some((value) => value === "mygo" || value === "github.com/egoist/mygo/cmd/mygo" || value.startsWith("github.com/egoist/mygo/cmd/mygo@")))) return;
44
+ validateMyGoPackaging({
45
+ ...config,
46
+ packageTarget: argv.includes("-skip-dmg") ? "app" : "dmg",
47
+ packaging: config.packaging ? {
48
+ ...config.packaging,
49
+ commands: [argv]
50
+ } : void 0
51
+ });
52
+ }
53
+ export { validateMyGoCommand, validateMyGoPackaging };
54
+
55
+ //# sourceMappingURL=mygo-build.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mygo-build.js","names":[],"sources":["../src/mygo-build.ts"],"sourcesContent":["import { basename, posix } from 'node:path';\nimport type { Config } from './schemas.js';\n\n/** Accept a direct, local MyGo build, never a wrapper that can add publishing flags. */\nexport function validateMyGoPackaging(config: Config, screenshotsDir?: string): void {\n const profile = config.packaging;\n if (!profile || profile.provider !== 'local' || profile.commands.length !== 1) throw Object.assign(new Error('MyGo requires one direct local build command'), { code: 'SETUP_REQUIRED' });\n const argv = profile.commands[0]!;\n let start: number;\n if (basename(argv[0]!) === 'mygo' && argv[1] === 'build') start = 2;\n else if (basename(argv[0]!) === 'go' && argv[1] === 'tool' && argv[2] === 'mygo' && argv[3] === 'build') start = 4;\n else if (basename(argv[0]!) === 'go' && argv[1] === 'run' && /^github\\.com\\/egoist\\/mygo\\/cmd\\/mygo@v\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?$/.test(argv[2] ?? '') && argv[3] === 'build') start = 4;\n else throw Object.assign(new Error('MyGo packaging must use a pinned go tool mygo build, installed mygo build, or version-pinned go run command'), { code: 'SETUP_REQUIRED' });\n const flags = new Map<string, string>();\n for (let index = start; index < argv.length; index++) {\n const flag = argv[index]!;\n if (flags.has(flag)) throw Object.assign(new Error(`Duplicate MyGo build flag: ${flag}`), { code: 'SETUP_REQUIRED' });\n if (flag === '-sign' || flag === '-platform' || flag === '-o') {\n const value = argv[++index];\n if (!value) throw Object.assign(new Error(`Missing MyGo flag value: ${flag}`), { code: 'SETUP_REQUIRED' });\n flags.set(flag, value);\n } else if (flag === '-skip-notarize' || flag === '-skip-dmg' || flag === '-skip-build-command') flags.set(flag, 'true');\n else throw Object.assign(new Error(`MyGo local packaging does not permit ${flag}; upload, notarization and custom wrapper commands are out of scope`), { code: 'SETUP_REQUIRED' });\n }\n if (flags.get('-sign') !== '-' || !flags.has('-skip-notarize')) throw Object.assign(new Error('MyGo local builds require -sign - and -skip-notarize, even when project configuration enables signing/notarization'), { code: 'SETUP_REQUIRED' });\n const platform = flags.get('-platform');\n if (!platform || !/^darwin\\/(?:arm64|amd64|universal)$/.test(platform)) throw Object.assign(new Error('MyGo packaging requires one explicit darwin/arm64, darwin/amd64 or darwin/universal target'), { code: 'SETUP_REQUIRED' });\n if (flags.get('-o') !== 'build') throw Object.assign(new Error('MyGo packaging requires -o build so output cannot replace project source'), { code: 'SETUP_REQUIRED' });\n const prefix = `build/${platform.replace('/', '-')}/`;\n if (!profile.artifactPath.startsWith(prefix)) throw Object.assign(new Error(`MyGo artifactPath must be inside ${prefix}`), { code: 'SETUP_REQUIRED' });\n if (screenshotsDir !== undefined) {\n const screenshot = posix.normalize(screenshotsDir);\n if (posix.isAbsolute(screenshot) || screenshot === '..' || screenshot.startsWith('../') || screenshot.includes('\\\\')) throw Object.assign(new Error('MyGo screenshotsDir must stay within the selected project'), { code: 'SETUP_REQUIRED' });\n const outputDirectory = prefix.slice(0, -1);\n if ([posix.relative(outputDirectory, screenshot), posix.relative(screenshot, outputDirectory)].some(path => path === '' || path !== '..' && !path.startsWith('../') && !posix.isAbsolute(path))) throw Object.assign(new Error('MyGo screenshotsDir must not overlap the platform output directory replaced during packaging'), { code: 'SETUP_REQUIRED' });\n }\n if (config.packageTarget === 'app' ? !flags.has('-skip-dmg') : flags.has('-skip-dmg')) throw Object.assign(new Error('MyGo app builds require -skip-dmg; dmg builds must create the disk image'), { code: 'SETUP_REQUIRED' });\n}\n\n/** Doctor and tracked execution share the same gate for every recognizable direct build. */\nexport function validateMyGoCommand(config: Config, argv: string[]): void {\n const tool = basename(argv[0] ?? '');\n const buildIndex = argv.indexOf('build');\n if (buildIndex <= 0) return;\n const direct = tool === 'mygo' || tool === 'go' && argv.slice(1, buildIndex).some(value => value === 'mygo' || value === 'github.com/egoist/mygo/cmd/mygo' || value.startsWith('github.com/egoist/mygo/cmd/mygo@'));\n if (!direct) return;\n validateMyGoPackaging({ ...config, packageTarget: argv.includes('-skip-dmg') ? 'app' : 'dmg', packaging: config.packaging ? { ...config.packaging, commands: [argv] } : undefined });\n}\n"],"mappings":"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"}
package/dist/policy.js ADDED
@@ -0,0 +1,35 @@
1
+ import { ResearchSchema } from "./schemas.js";
2
+ // src/policy.ts
3
+ function parseResearch(text, channel) {
4
+ const content = text.trim().replace(/^```(?:json)?\s*\n?/, "").replace(/\n?```$/, "");
5
+ let value;
6
+ try {
7
+ value = JSON.parse(content);
8
+ } catch {
9
+ throw new Error("Host did not return a JSON verdict; no approval was inferred from text or an exit code");
10
+ }
11
+ return ResearchSchema.parse(value);
12
+ }
13
+ /** Honest pre-delivery differentiation and quality checklist. Store submission and review stay manual. */
14
+ function internalQaChecklist() {
15
+ return [
16
+ "Internal QA checklist for a normal, honest local package handoff. Store submission, account setup and platform review are manual human work outside this tool; nothing here bypasses, influences or pre-approves a store reviewer.",
17
+ "Real value: each package has its own genuine purpose, audience and functional behavior. Identical functionality with only renamed labels is not meaningful differentiation.",
18
+ "Visual identity: themes, layouts, colors and interaction flows are real product choices for this app, not templated reskins produced to look different.",
19
+ "Developer and identity metadata: app name, title, icon, bundle/package id, keywords and description truthfully describe this app and its actual developer. Never forge identities, accounts, locations or submission sources.",
20
+ "Functionality: every advertised feature works and is exercised by the frozen runtime acceptance; no hidden functionality for any audience and no fabricated screenshots or evidence.",
21
+ "Metadata: price, region, category and description reflect the actual product. Design rationale notes, if any, are the owner's honest answers, not scripted reply templates.",
22
+ "Code identity: project, folder, class, function and resource names follow this project's real conventions. Do not mutate hashes, names or resource bytes solely to defeat similarity checks; that would be deceptive.",
23
+ "Quality gate: source, dependency and runtime proofs must be current; independent review must cover every frozen acceptance requirement with observed evidence. Only then may the artifact be handed off to a human for store submission."
24
+ ].join("\n");
25
+ }
26
+ function researchPrompt(job, portfolio) {
27
+ const siblings = `Other same-channel products ${JSON.stringify(portfolio)}; earlier versions of this same app are its source baseline, not competing products.`;
28
+ return `Research only with your own host tools. Preserve the requested ${job.spec.framework} ${job.spec.platform} project and its existing architecture. ${internalQaChecklist()} ${siblings} Assess technical feasibility, dependencies, licensing, privacy and real acceptance for this local package. Return typed JSON {"viable":boolean,"distinctness":"specific honest differentiation","risks":["..."],"plan":["concrete implementation and device acceptance step"]}. Do not promise store approval and do not add unrequested features.`;
29
+ }
30
+ function reviewInstructions(job) {
31
+ return `Use an independent reviewer with fresh context when supported; otherwise disclose the limitation. Review actual source and acceptance read-only. Verified source: ${job.verifiedDigest}; dependency resolution: ${job.verifiedDependencyDigest}; actual checks: ${JSON.stringify(job.config.verification)}. ${internalQaChecklist()} Reject incomplete requirements, data loss, fake screenshots, accessibility failures, placeholders, weak tests and hidden features. Return typed JSON {"approved":boolean,"findings":["blocking issue"],"acceptanceEvidence":[{"requirement":"exact acceptance string","evidence":"file/symbol + observed command or device scenario"}]}. Cover every acceptance requirement. Reviewer identity is advisory; the Harness gates typed results and unchanged execution evidence.`;
32
+ }
33
+ export { internalQaChecklist, parseResearch, researchPrompt, reviewInstructions };
34
+
35
+ //# sourceMappingURL=policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.js","names":[],"sources":["../src/policy.ts"],"sourcesContent":["import { ResearchSchema } from './schemas.js';\nimport type { Job, Spec } from './schemas.js';\n\nexport function parseResearch(text: string, channel: Spec['channel']) {\n const content = text.trim().replace(/^```(?:json)?\\s*\\n?/, '').replace(/\\n?```$/, '');\n let value: unknown;\n try { value = JSON.parse(content); }\n catch { throw new Error('Host did not return a JSON verdict; no approval was inferred from text or an exit code'); }\n return ResearchSchema.parse(value);\n}\n\n/** Honest pre-delivery differentiation and quality checklist. Store submission and review stay manual. */\nexport function internalQaChecklist(): string {\n return [\n 'Internal QA checklist for a normal, honest local package handoff. Store submission, account setup and platform review are manual human work outside this tool; nothing here bypasses, influences or pre-approves a store reviewer.',\n 'Real value: each package has its own genuine purpose, audience and functional behavior. Identical functionality with only renamed labels is not meaningful differentiation.',\n 'Visual identity: themes, layouts, colors and interaction flows are real product choices for this app, not templated reskins produced to look different.',\n 'Developer and identity metadata: app name, title, icon, bundle/package id, keywords and description truthfully describe this app and its actual developer. Never forge identities, accounts, locations or submission sources.',\n 'Functionality: every advertised feature works and is exercised by the frozen runtime acceptance; no hidden functionality for any audience and no fabricated screenshots or evidence.',\n 'Metadata: price, region, category and description reflect the actual product. Design rationale notes, if any, are the owner\\'s honest answers, not scripted reply templates.',\n 'Code identity: project, folder, class, function and resource names follow this project\\'s real conventions. Do not mutate hashes, names or resource bytes solely to defeat similarity checks; that would be deceptive.',\n 'Quality gate: source, dependency and runtime proofs must be current; independent review must cover every frozen acceptance requirement with observed evidence. Only then may the artifact be handed off to a human for store submission.',\n ].join('\\n');\n}\n\nexport function researchPrompt(job: Job, portfolio: Array<Pick<Spec, 'id' | 'purpose' | 'audience' | 'differentiators'>>): string {\n const siblings = `Other same-channel products ${JSON.stringify(portfolio)}; earlier versions of this same app are its source baseline, not competing products.`;\n return `Research only with your own host tools. Preserve the requested ${job.spec.framework} ${job.spec.platform} project and its existing architecture. ${internalQaChecklist()} ${siblings} Assess technical feasibility, dependencies, licensing, privacy and real acceptance for this local package. Return typed JSON {\"viable\":boolean,\"distinctness\":\"specific honest differentiation\",\"risks\":[\"...\"],\"plan\":[\"concrete implementation and device acceptance step\"]}. Do not promise store approval and do not add unrequested features.`;\n}\n\nexport function reviewInstructions(job: Job): string {\n return `Use an independent reviewer with fresh context when supported; otherwise disclose the limitation. Review actual source and acceptance read-only. Verified source: ${job.verifiedDigest}; dependency resolution: ${job.verifiedDependencyDigest}; actual checks: ${JSON.stringify(job.config.verification)}. ${internalQaChecklist()} Reject incomplete requirements, data loss, fake screenshots, accessibility failures, placeholders, weak tests and hidden features. Return typed JSON {\"approved\":boolean,\"findings\":[\"blocking issue\"],\"acceptanceEvidence\":[{\"requirement\":\"exact acceptance string\",\"evidence\":\"file/symbol + observed command or device scenario\"}]}. Cover every acceptance requirement. Reviewer identity is advisory; the Harness gates typed results and unchanged execution evidence.`;\n}\n"],"mappings":";;AAGA,SAAgB,cAAc,MAAc,SAA0B;CACpE,MAAM,UAAU,KAAK,KAAK,CAAC,CAAC,QAAQ,uBAAuB,EAAE,CAAC,CAAC,QAAQ,WAAW,EAAE;CACpF,IAAI;CACJ,IAAI;EAAE,QAAQ,KAAK,MAAM,OAAO;CAAG,QAC7B;EAAE,MAAM,IAAI,MAAM,wFAAwF;CAAG;CACnH,OAAO,eAAe,MAAM,KAAK;AACnC;;AAGA,SAAgB,sBAA8B;CAC5C,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,IAAI;AACb;AAEA,SAAgB,eAAe,KAAU,WAAyF;CAChI,MAAM,WAAW,+BAA+B,KAAK,UAAU,SAAS,EAAE;CAC1E,OAAO,kEAAkE,IAAI,KAAK,UAAU,GAAG,IAAI,KAAK,SAAS,0CAA0C,oBAAoB,EAAE,GAAG,SAAS;AAC/L;AAEA,SAAgB,mBAAmB,KAAkB;CACnD,OAAO,qKAAqK,IAAI,eAAe,2BAA2B,IAAI,yBAAyB,mBAAmB,KAAK,UAAU,IAAI,OAAO,YAAY,EAAE,IAAI,oBAAoB,EAAE;AAC9U"}
package/dist/preflight.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { toError } from "./schemas.js";
2
- import { run } from "./process.js";
3
2
  import { expandArgv } from "./config.js";
3
+ import { run } from "./process.js";
4
4
  // src/preflight.ts
5
5
  function prerequisiteFailure(argv, reason, detail, cause) {
6
6
  return Object.assign(new Error(`Prerequisite ${JSON.stringify(argv)} ${detail}. Restore the configured worker environment before retrying.`, { cause }), {
package/dist/process.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { toError } from "./schemas.js";
2
- import { randomUUID } from "node:crypto";
3
- import { dirname } from "node:path";
4
- import { spawn, spawnSync } from "node:child_process";
5
2
  import { closeSync, mkdirSync, openSync, readFileSync, writeSync } from "node:fs";
3
+ import { spawn, spawnSync } from "node:child_process";
4
+ import { dirname } from "node:path";
5
+ import { randomUUID } from "node:crypto";
6
6
  import { setTimeout as setTimeout$1 } from "node:timers/promises";
7
7
  // src/process.ts
8
8
  const COMMAND_TOKEN = "APPLE_APP_FACTORY_COMMAND_TOKEN";
@@ -0,0 +1,163 @@
1
+ import { inside } from "./config.js";
2
+ import { parseGoManifest } from "./go-dependencies.js";
3
+ import { generatedModulePaths, isGeneratedPath } from "./dependencies.js";
4
+ import { lstatSync, readFileSync, readdirSync } from "node:fs";
5
+ import { join } from "node:path";
6
+ import { parseDocument } from "yaml";
7
+ // src/project-profiles.ts
8
+ function file(root, path) {
9
+ const absolute = inside(root, path);
10
+ const stat = lstatSync(absolute, { throwIfNoEntry: false });
11
+ if (!stat) return void 0;
12
+ if (!stat.isFile() || stat.isSymbolicLink()) throw new Error(`Project manifest must be a regular source file: ${path}`);
13
+ return readFileSync(absolute, "utf8");
14
+ }
15
+ function json(root, path, comments = false) {
16
+ let text = file(root, path);
17
+ if (text === void 0) return void 0;
18
+ if (comments) text = text.replace(/"(?:\\.|[^"\\])*"|\/\*[\s\S]*?\*\/|\/\/[^\r\n]*/g, (token) => token.startsWith("/") ? "" : token);
19
+ const value = JSON.parse(text);
20
+ if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error(`Expected a project manifest object: ${path}`);
21
+ return value;
22
+ }
23
+ function directories(root, framework, current = "", moduleOutputs = [...generatedModulePaths(root, framework)]) {
24
+ const result = [current];
25
+ for (const entry of readdirSync(join(root, current), { withFileTypes: true })) {
26
+ const path = current ? `${current}/${entry.name}` : entry.name;
27
+ if (isGeneratedPath(path, framework) || moduleOutputs.some((output) => path === output || path.startsWith(`${output}/`))) continue;
28
+ const stat = lstatSync(join(root, path));
29
+ if (stat.isSymbolicLink()) throw new Error(`Project source symlinks are not trusted: ${path}`);
30
+ if (stat.isDirectory()) result.push(...directories(root, framework, path, moduleOutputs));
31
+ }
32
+ return result;
33
+ }
34
+ /** The caller resolves project.directory; this function never generates or ejects a project. */
35
+ function assertProject(root, spec) {
36
+ const fail = (manifest) => {
37
+ throw new Error(`${spec.framework} build completion requires ${manifest} in the project directory`);
38
+ };
39
+ if (spec.platform === "macos" && spec.framework !== "mygo") fail("an existing supported iOS or Android platform; macOS is supported only for MyGo");
40
+ if (spec.framework === "mygo") {
41
+ if (spec.platform !== "macos") fail("the macOS platform");
42
+ const mod = file(root, "go.mod");
43
+ if (mod === void 0 || !parseGoManifest(mod).requires.has("github.com/egoist/mygo")) fail("a go.mod requiring github.com/egoist/mygo");
44
+ const native = json(root, "mygo.json");
45
+ const web = file(root, "mygo.config.ts");
46
+ if (native === void 0 === (web === void 0)) fail("exactly one mygo.json or mygo.config.ts");
47
+ if (web !== void 0 && !json(root, "package.json") && !json(root, "frontend/package.json")) fail("the original package.json or frontend/package.json for mygo.config.ts");
48
+ return;
49
+ }
50
+ if (spec.framework === "flutter") {
51
+ const text = file(root, "pubspec.yaml");
52
+ if (!text) fail("a Flutter pubspec.yaml");
53
+ const document = parseDocument(text);
54
+ if (document.errors.length) throw new Error(`Invalid pubspec.yaml: ${document.errors.map((error) => error.message).join("; ")}`);
55
+ const value = document.toJS();
56
+ if (!value || typeof value.name !== "string" || value.dependencies?.flutter?.sdk !== "flutter") fail("a named pubspec.yaml with dependencies.flutter.sdk: flutter");
57
+ return;
58
+ }
59
+ if (spec.framework === "android-java") {
60
+ if (spec.platform !== "android") fail("the Android platform");
61
+ const settings = file(root, "settings.gradle") ?? file(root, "settings.gradle.kts");
62
+ const application = directories(root, spec.framework).some((directory) => {
63
+ const prefix = directory ? `${directory}/` : "";
64
+ if ((file(root, `${prefix}build.gradle`) ?? file(root, `${prefix}build.gradle.kts`)) === void 0) return false;
65
+ const manifest = file(root, `${prefix}src/main/AndroidManifest.xml`)?.replace(/<!--[\s\S]*?-->/g, "");
66
+ return !!manifest && /<manifest\b/.test(manifest) && /<application\b/.test(manifest) && /<\/manifest\s*>/.test(manifest);
67
+ });
68
+ if (settings === void 0 || !application) fail("Gradle settings/build files and an application module src/main/AndroidManifest.xml");
69
+ return;
70
+ }
71
+ if (spec.framework === "swift") {
72
+ if (spec.platform !== "ios") fail("the iOS platform");
73
+ const swift = file(root, "Package.swift");
74
+ if (swift && /swift-tools-version\s*:/.test(swift) && /\bPackage\s*\(/.test(swift)) return;
75
+ for (const directory of directories(root, spec.framework)) if (directory.endsWith(".xcodeproj")) {
76
+ const project = file(root, `${directory}/project.pbxproj`);
77
+ if (project && /\bPBXProject\b/.test(project)) return;
78
+ }
79
+ fail("a Swift Package.swift or an Xcode .xcodeproj/project.pbxproj");
80
+ }
81
+ const pkg = json(root, "package.json");
82
+ const dependencies = {
83
+ ...pkg?.dependencies,
84
+ ...pkg?.devDependencies
85
+ };
86
+ if (spec.framework === "uni-app") {
87
+ const source = json(root, "src/manifest.json", true) ? "src/" : "";
88
+ const manifest = json(root, `${source}manifest.json`, true);
89
+ const pages = json(root, `${source}pages.json`, true);
90
+ if (!manifest || !Array.isArray(pages?.pages) || !pages.pages.length) fail("manifest.json and nonempty pages.json at the root or under src/");
91
+ const cli = typeof dependencies["@dcloudio/uni-app"] === "string" && !!dependencies["@dcloudio/uni-app"];
92
+ const classic = !!file(root, `${source}App.vue`) && !!(file(root, `${source}main.js`) ?? file(root, `${source}main.ts`));
93
+ if (!cli && !classic) fail("a uni-app CLI package.json or HBuilderX App.vue and main.js/main.ts");
94
+ return;
95
+ }
96
+ const required = spec.framework === "react-native" ? "react-native" : "expo";
97
+ if (!pkg || typeof dependencies[required] !== "string" || !dependencies[required]) fail(`package.json declaring ${required}`);
98
+ }
99
+ function buildInstructions(spec) {
100
+ return `${`Build the ${spec.platform} application using the ${spec.framework} stack. ${spec.project?.sourceDir ? "Preserve the imported project and its existing native structure." : "Preserve any existing project, including a prepared predecessor; generate a real runnable project only when none exists in the designated project directory."}`}\n${{
101
+ flutter: "Use a Flutter pubspec.yaml, Dart sources and the selected platform runner. Resolve dependencies with flutter pub get; keep pubspec.lock. Do not modify the Flutter SDK.",
102
+ "android-java": "Use a Java Android application with Gradle settings/build files and AndroidManifest.xml. Keep the Gradle wrapper and dependency locks; use the existing application module rather than rewriting it.",
103
+ swift: "Use the existing Xcode project or Swift package, Swift sources and iOS application configuration. Keep Package.resolved and Podfile.lock when used. Do not replace an existing Xcode project with a package.",
104
+ "react-native": "Use package.json with react-native and the existing iOS/Android native projects. Keep the package-manager lockfile and native dependency locks. Do not migrate to Expo or regenerate native projects.",
105
+ expo: "Use package.json with expo and the existing Expo application configuration. Preserve managed or prebuilt structure; do not force expo prebuild or eject. Cloud builds require the owner-configured permission and packaging commands.",
106
+ "uni-app": "Preserve either the existing CLI package.json with @dcloudio/uni-app or the classic HBuilderX App.vue/main.js/main.ts project without requiring npm. Keep manifest.json/pages.json (root or src) and existing native structure; use the owner-configured HBuilderX/CLI Android/iOS packager, not a fabricated artifact.",
107
+ mygo: "Preserve native-UI Go-only projects with go.mod and mygo.json, or existing web projects with go.mod, mygo.config.ts and their original package.json (at the root or under frontend/) and package manager; keep exactly one MyGo config and require github.com/egoist/mygo in go.mod. Native projects need neither package.json nor Bun nor Xcode. Do not rewrite a web project or require Bun solely because its config is TypeScript; preserve its existing runtime and frontend scripts. Preserve the pinned MyGo tool/module version in go.mod; do not use @latest or install tools automatically. Prepare go.sum, any go.work/go.work.sum, frontend dependency locks and generated frontend bindings before proof, preserving the original frontend build process. Use Go vet/tests plus an owner-implemented real macOS desktop acceptance harness that launches and drives the actual app; go test or a headless view test alone is not desktop acceptance, and no iOS simulator is involved. Never generate a stub acceptance command. Packaging stays local-only through the frozen direct go tool mygo build command (or owner-configured pinned direct MyGo invocation), with -sign - and -skip-notarize; never upload, notarize or access signing keychains. Use the frozen output path, architecture and app/dmg target; do not replace the owner packaging profile."
108
+ }[spec.framework]}\nImplement the acceptance criteria, run the configured checks and runtime evidence commands, and leave packaging to the frozen owner command profile. Never replace checks with no-ops or claim unobserved SDK/build results.`;
109
+ }
110
+ function doctorCommands(framework, platform) {
111
+ const commands = [];
112
+ if (framework === "mygo") {
113
+ if (platform !== "macos") throw new Error("MyGo doctor supports only macOS");
114
+ return [
115
+ {
116
+ name: "Go",
117
+ argv: ["go", "version"]
118
+ },
119
+ {
120
+ name: "macOS code signing",
121
+ argv: ["/usr/bin/which", "codesign"]
122
+ },
123
+ {
124
+ name: "macOS disk images",
125
+ argv: ["hdiutil", "help"]
126
+ }
127
+ ];
128
+ }
129
+ if (platform === "macos") throw new Error("macOS doctor supports only MyGo");
130
+ if (framework === "flutter") commands.push({
131
+ name: "Flutter",
132
+ argv: ["flutter", "--version"]
133
+ });
134
+ else if (framework === "swift") commands.push({
135
+ name: "Swift",
136
+ argv: ["swift", "--version"]
137
+ });
138
+ else if (framework === "react-native" || framework === "expo") commands.push({
139
+ name: "Node.js",
140
+ argv: ["node", "--version"]
141
+ }, {
142
+ name: "npm",
143
+ argv: ["npm", "--version"]
144
+ });
145
+ if (platform === "ios") commands.push({
146
+ name: "Xcode",
147
+ argv: ["xcodebuild", "-version"]
148
+ }, {
149
+ name: "Xcode tools",
150
+ argv: ["xcrun", "--version"]
151
+ });
152
+ else commands.push({
153
+ name: "Java",
154
+ argv: ["java", "-version"]
155
+ }, {
156
+ name: "Android platform tools",
157
+ argv: ["adb", "version"]
158
+ });
159
+ return commands;
160
+ }
161
+ export { assertProject, buildInstructions, doctorCommands };
162
+
163
+ //# sourceMappingURL=project-profiles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-profiles.js","names":[],"sources":["../src/project-profiles.ts"],"sourcesContent":["import { lstatSync, readFileSync, readdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { parseDocument } from 'yaml';\nimport { inside } from './config.js';\nimport { generatedModulePaths, isGeneratedPath } from './dependencies.js';\nimport { parseGoManifest } from './go-dependencies.js';\nimport type { Framework, Platform, Spec } from './schemas.js';\n\nfunction file(root: string, path: string): string | undefined {\n const absolute = inside(root, path);\n const stat = lstatSync(absolute, { throwIfNoEntry: false });\n if (!stat) return undefined;\n if (!stat.isFile() || stat.isSymbolicLink()) throw new Error(`Project manifest must be a regular source file: ${path}`);\n return readFileSync(absolute, 'utf8');\n}\n\nfunction json(root: string, path: string, comments = false): Record<string, unknown> | undefined {\n let text = file(root, path);\n if (text === undefined) return undefined;\n if (comments) text = text.replace(/\"(?:\\\\.|[^\"\\\\])*\"|\\/\\*[\\s\\S]*?\\*\\/|\\/\\/[^\\r\\n]*/g, token => token.startsWith('/') ? '' : token);\n const value: unknown = JSON.parse(text);\n if (!value || typeof value !== 'object' || Array.isArray(value)) throw new Error(`Expected a project manifest object: ${path}`);\n return value as Record<string, unknown>;\n}\n\nfunction directories(root: string, framework: Framework, current = '', moduleOutputs = [...generatedModulePaths(root, framework)]): string[] {\n const result = [current];\n for (const entry of readdirSync(join(root, current), { withFileTypes: true })) {\n const path = current ? `${current}/${entry.name}` : entry.name;\n if (isGeneratedPath(path, framework) || moduleOutputs.some(output => path === output || path.startsWith(`${output}/`))) continue;\n const stat = lstatSync(join(root, path));\n if (stat.isSymbolicLink()) throw new Error(`Project source symlinks are not trusted: ${path}`);\n if (stat.isDirectory()) result.push(...directories(root, framework, path, moduleOutputs));\n }\n return result;\n}\n\n/** The caller resolves project.directory; this function never generates or ejects a project. */\nexport function assertProject(root: string, spec: Spec): void {\n const fail = (manifest: string): never => { throw new Error(`${spec.framework} build completion requires ${manifest} in the project directory`); };\n if (spec.platform === 'macos' && spec.framework !== 'mygo') fail('an existing supported iOS or Android platform; macOS is supported only for MyGo');\n if (spec.framework === 'mygo') {\n if (spec.platform !== 'macos') fail('the macOS platform');\n const mod = file(root, 'go.mod');\n if (mod === undefined || !parseGoManifest(mod).requires.has('github.com/egoist/mygo')) fail('a go.mod requiring github.com/egoist/mygo');\n const native = json(root, 'mygo.json');\n const web = file(root, 'mygo.config.ts');\n if ((native === undefined) === (web === undefined)) fail('exactly one mygo.json or mygo.config.ts');\n if (web !== undefined && !json(root, 'package.json') && !json(root, 'frontend/package.json')) fail('the original package.json or frontend/package.json for mygo.config.ts');\n return;\n }\n if (spec.framework === 'flutter') {\n const text = file(root, 'pubspec.yaml');\n if (!text) fail('a Flutter pubspec.yaml');\n const document = parseDocument(text!);\n if (document.errors.length) throw new Error(`Invalid pubspec.yaml: ${document.errors.map(error => error.message).join('; ')}`);\n const value = document.toJS();\n if (!value || typeof value.name !== 'string' || value.dependencies?.flutter?.sdk !== 'flutter') fail('a named pubspec.yaml with dependencies.flutter.sdk: flutter');\n return;\n }\n if (spec.framework === 'android-java') {\n if (spec.platform !== 'android') fail('the Android platform');\n const settings = file(root, 'settings.gradle') ?? file(root, 'settings.gradle.kts');\n const application = directories(root, spec.framework).some(directory => {\n const prefix = directory ? `${directory}/` : '';\n const build = file(root, `${prefix}build.gradle`) ?? file(root, `${prefix}build.gradle.kts`);\n if (build === undefined) return false;\n const manifest = file(root, `${prefix}src/main/AndroidManifest.xml`)?.replace(/<!--[\\s\\S]*?-->/g, '');\n return !!manifest && /<manifest\\b/.test(manifest) && /<application\\b/.test(manifest) && /<\\/manifest\\s*>/.test(manifest);\n });\n if (settings === undefined || !application) fail('Gradle settings/build files and an application module src/main/AndroidManifest.xml');\n return;\n }\n if (spec.framework === 'swift') {\n if (spec.platform !== 'ios') fail('the iOS platform');\n const swift = file(root, 'Package.swift');\n if (swift && /swift-tools-version\\s*:/.test(swift) && /\\bPackage\\s*\\(/.test(swift)) return;\n for (const directory of directories(root, spec.framework)) {\n if (directory.endsWith('.xcodeproj')) {\n const project = file(root, `${directory}/project.pbxproj`);\n if (project && /\\bPBXProject\\b/.test(project)) return;\n }\n }\n fail('a Swift Package.swift or an Xcode .xcodeproj/project.pbxproj');\n }\n const pkg = json(root, 'package.json');\n const dependencies = { ...(pkg?.dependencies as Record<string, unknown> | undefined), ...(pkg?.devDependencies as Record<string, unknown> | undefined) };\n if (spec.framework === 'uni-app') {\n const source = json(root, 'src/manifest.json', true) ? 'src/' : '';\n const manifest = json(root, `${source}manifest.json`, true);\n const pages = json(root, `${source}pages.json`, true);\n if (!manifest || !Array.isArray(pages?.pages) || !pages.pages.length) fail('manifest.json and nonempty pages.json at the root or under src/');\n const cli = typeof dependencies['@dcloudio/uni-app'] === 'string' && !!dependencies['@dcloudio/uni-app'];\n const classic = !!file(root, `${source}App.vue`) && !!(file(root, `${source}main.js`) ?? file(root, `${source}main.ts`));\n if (!cli && !classic) fail('a uni-app CLI package.json or HBuilderX App.vue and main.js/main.ts');\n return;\n }\n const required = spec.framework === 'react-native' ? 'react-native' : 'expo';\n if (!pkg || typeof dependencies[required] !== 'string' || !dependencies[required]) fail(`package.json declaring ${required}`);\n}\n\nexport function buildInstructions(spec: Spec): string {\n const context = `Build the ${spec.platform} application using the ${spec.framework} stack. ${spec.project?.sourceDir ? 'Preserve the imported project and its existing native structure.' : 'Preserve any existing project, including a prepared predecessor; generate a real runnable project only when none exists in the designated project directory.'}`;\n const guidance: Record<Framework, string> = {\n flutter: 'Use a Flutter pubspec.yaml, Dart sources and the selected platform runner. Resolve dependencies with flutter pub get; keep pubspec.lock. Do not modify the Flutter SDK.',\n 'android-java': 'Use a Java Android application with Gradle settings/build files and AndroidManifest.xml. Keep the Gradle wrapper and dependency locks; use the existing application module rather than rewriting it.',\n swift: 'Use the existing Xcode project or Swift package, Swift sources and iOS application configuration. Keep Package.resolved and Podfile.lock when used. Do not replace an existing Xcode project with a package.',\n 'react-native': 'Use package.json with react-native and the existing iOS/Android native projects. Keep the package-manager lockfile and native dependency locks. Do not migrate to Expo or regenerate native projects.',\n expo: 'Use package.json with expo and the existing Expo application configuration. Preserve managed or prebuilt structure; do not force expo prebuild or eject. Cloud builds require the owner-configured permission and packaging commands.',\n 'uni-app': 'Preserve either the existing CLI package.json with @dcloudio/uni-app or the classic HBuilderX App.vue/main.js/main.ts project without requiring npm. Keep manifest.json/pages.json (root or src) and existing native structure; use the owner-configured HBuilderX/CLI Android/iOS packager, not a fabricated artifact.',\n mygo: 'Preserve native-UI Go-only projects with go.mod and mygo.json, or existing web projects with go.mod, mygo.config.ts and their original package.json (at the root or under frontend/) and package manager; keep exactly one MyGo config and require github.com/egoist/mygo in go.mod. Native projects need neither package.json nor Bun nor Xcode. Do not rewrite a web project or require Bun solely because its config is TypeScript; preserve its existing runtime and frontend scripts. Preserve the pinned MyGo tool/module version in go.mod; do not use @latest or install tools automatically. Prepare go.sum, any go.work/go.work.sum, frontend dependency locks and generated frontend bindings before proof, preserving the original frontend build process. Use Go vet/tests plus an owner-implemented real macOS desktop acceptance harness that launches and drives the actual app; go test or a headless view test alone is not desktop acceptance, and no iOS simulator is involved. Never generate a stub acceptance command. Packaging stays local-only through the frozen direct go tool mygo build command (or owner-configured pinned direct MyGo invocation), with -sign - and -skip-notarize; never upload, notarize or access signing keychains. Use the frozen output path, architecture and app/dmg target; do not replace the owner packaging profile.',\n };\n return `${context}\\n${guidance[spec.framework]}\\nImplement the acceptance criteria, run the configured checks and runtime evidence commands, and leave packaging to the frozen owner command profile. Never replace checks with no-ops or claim unobserved SDK/build results.`;\n}\n\nexport function doctorCommands(framework: Framework, platform: Platform): Array<{ name: string; argv: string[] }> {\n const commands: Array<{ name: string; argv: string[] }> = [];\n if (framework === 'mygo') {\n if (platform !== 'macos') throw new Error('MyGo doctor supports only macOS');\n return [\n { name: 'Go', argv: ['go', 'version'] },\n { name: 'macOS code signing', argv: ['/usr/bin/which', 'codesign'] },\n { name: 'macOS disk images', argv: ['hdiutil', 'help'] },\n ];\n }\n if (platform === 'macos') throw new Error('macOS doctor supports only MyGo');\n if (framework === 'flutter') commands.push({ name: 'Flutter', argv: ['flutter', '--version'] });\n else if (framework === 'swift') commands.push({ name: 'Swift', argv: ['swift', '--version'] });\n else if (framework === 'react-native' || framework === 'expo') commands.push({ name: 'Node.js', argv: ['node', '--version'] }, { name: 'npm', argv: ['npm', '--version'] });\n if (platform === 'ios') commands.push({ name: 'Xcode', argv: ['xcodebuild', '-version'] }, { name: 'Xcode tools', argv: ['xcrun', '--version'] });\n else commands.push({ name: 'Java', argv: ['java', '-version'] }, { name: 'Android platform tools', argv: ['adb', 'version'] });\n return commands;\n}\n"],"mappings":"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"}
package/dist/proof.js ADDED
@@ -0,0 +1,33 @@
1
+ // src/proof.ts
2
+ function verificationContract(config) {
3
+ return {
4
+ verification: config.verification,
5
+ executionEnv: config.executionEnv,
6
+ toolchain: config.toolchain,
7
+ packaging: config.packaging,
8
+ apple: config.apple,
9
+ packageTarget: config.packageTarget,
10
+ allowCloudBuild: config.allowCloudBuild,
11
+ isolation: config.isolation,
12
+ obfuscation: config.obfuscation
13
+ };
14
+ }
15
+ function verificationConfigChanged(job, config) {
16
+ return JSON.stringify(verificationContract(job.config)) !== JSON.stringify(verificationContract(config)) || job.verifiedDigest != null && !job.verifiedDependencyDigest;
17
+ }
18
+ function invalidateVerification() {
19
+ return {
20
+ verifiedDigest: null,
21
+ verifiedDependencyDigest: null,
22
+ screenshotDigest: null,
23
+ verifiedAt: void 0,
24
+ review: null,
25
+ reviewPolicyContextDigest: null,
26
+ artifact: null,
27
+ ipaPath: null,
28
+ archiveDigest: null
29
+ };
30
+ }
31
+ export { invalidateVerification, verificationConfigChanged };
32
+
33
+ //# sourceMappingURL=proof.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proof.js","names":[],"sources":["../src/proof.ts"],"sourcesContent":["import type { Config, Job } from './schemas.js';\n\nfunction verificationContract(config: Config) {\n return {\n verification: config.verification, executionEnv: config.executionEnv, toolchain: config.toolchain,\n packaging: config.packaging, apple: config.apple, packageTarget: config.packageTarget, allowCloudBuild: config.allowCloudBuild,\n isolation: config.isolation, obfuscation: config.obfuscation,\n };\n}\n\nexport function verificationConfigChanged(job: Job, config: Config): boolean {\n return JSON.stringify(verificationContract(job.config)) !== JSON.stringify(verificationContract(config))\n || (job.verifiedDigest != null && !job.verifiedDependencyDigest);\n}\n\nexport function invalidateVerification(): Partial<Job> {\n return {\n verifiedDigest: null, verifiedDependencyDigest: null, screenshotDigest: null, verifiedAt: undefined,\n review: null, reviewPolicyContextDigest: null, artifact: null, ipaPath: null, archiveDigest: null,\n };\n}\n"],"mappings":";AAEA,SAAS,qBAAqB,QAAgB;CAC5C,OAAO;EACL,cAAc,OAAO;EAAc,cAAc,OAAO;EAAc,WAAW,OAAO;EACxF,WAAW,OAAO;EAAW,OAAO,OAAO;EAAO,eAAe,OAAO;EAAe,iBAAiB,OAAO;EAC/G,WAAW,OAAO;EAAW,aAAa,OAAO;CACnD;AACF;AAEA,SAAgB,0BAA0B,KAAU,QAAyB;CAC3E,OAAO,KAAK,UAAU,qBAAqB,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,qBAAqB,MAAM,CAAC,KACjG,IAAI,kBAAkB,QAAQ,CAAC,IAAI;AAC3C;AAEA,SAAgB,yBAAuC;CACrD,OAAO;EACL,gBAAgB;EAAM,0BAA0B;EAAM,kBAAkB;EAAM,YAAY,KAAA;EAC1F,QAAQ;EAAM,2BAA2B;EAAM,UAAU;EAAM,SAAS;EAAM,eAAe;CAC/F;AACF"}
package/dist/remote.js CHANGED
@@ -2,8 +2,8 @@ import { toError } from "./schemas.js";
2
2
  import { loadJSON } from "./config.js";
3
3
  import { parseRequirement } from "./requirements.js";
4
4
  import { z } from "zod";
5
- import { posix } from "node:path";
6
5
  import { spawn } from "node:child_process";
6
+ import { posix } from "node:path";
7
7
  // src/remote.ts
8
8
  const remotePath = z.string().min(1).refine((value) => posix.isAbsolute(value) && !value.includes("\0") && !/[\r\n]/.test(value), "Use an absolute path on the Mac worker");
9
9
  const RemoteSchema = z.strictObject({