@mmerterden/multi-agent-pipeline 20.34.0 → 20.36.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 (335) hide show
  1. package/CHANGELOG.md +69 -1
  2. package/README.md +7 -5
  3. package/README.tr.md +6 -5
  4. package/docs/architecture.md +3 -3
  5. package/docs/ecosystem.md +5 -5
  6. package/docs/facts.json +4 -4
  7. package/install/catalog-history.json +1 -1
  8. package/install/claude.mjs +16 -1
  9. package/install/templates/claude-hooks.json +23 -1
  10. package/manifest.json +338 -305
  11. package/package.json +5 -1
  12. package/pipeline/agents/bulk-reader.md +3 -0
  13. package/pipeline/commands/multi-agent/channels/SKILL.md +1 -1
  14. package/pipeline/commands/multi-agent/office-on/SKILL.md +7 -3
  15. package/pipeline/commands/multi-agent/office-pair/SKILL.md +66 -0
  16. package/pipeline/commands/multi-agent/office-status/SKILL.md +3 -2
  17. package/pipeline/commands/multi-agent/sync/SKILL.md +3 -3
  18. package/pipeline/contract/CHANGELOG.md +9 -0
  19. package/pipeline/contract/README.md +1 -0
  20. package/pipeline/contract/fixtures/error-invalid-request.json +1 -1
  21. package/pipeline/contract/fixtures/error-unauthorized.json +1 -1
  22. package/pipeline/contract/fixtures/error-unsigned.json +1 -1
  23. package/pipeline/contract/manifest.json +14 -1
  24. package/pipeline/contract/types/index.d.ts +24 -2
  25. package/pipeline/lib/json-file-lock.mjs +61 -15
  26. package/pipeline/lib/office-remote.mjs +228 -0
  27. package/pipeline/lib/qr-code.mjs +386 -0
  28. package/pipeline/lib/repo-hygiene.sh +1 -0
  29. package/pipeline/lib/run-completion.mjs +17 -0
  30. package/pipeline/multi-agent-refs/channels/issue-comment.md +1 -1
  31. package/pipeline/multi-agent-refs/cross-cli-contract.md +4 -4
  32. package/pipeline/multi-agent-refs/features/office-remote-protocol.md +166 -0
  33. package/pipeline/multi-agent-refs/features/office-threat-model.md +1 -1
  34. package/pipeline/multi-agent-refs/features/scope-check.md +16 -1
  35. package/pipeline/multi-agent-refs/features/verify-by-test.md +10 -0
  36. package/pipeline/multi-agent-refs/help/en.md +1 -0
  37. package/pipeline/multi-agent-refs/help/tr.md +1 -0
  38. package/pipeline/multi-agent-refs/keychain.md +7 -0
  39. package/pipeline/multi-agent-refs/phases/phase-0-init.md +6 -2
  40. package/pipeline/multi-agent-refs/phases/phase-1-plan.md +4 -6
  41. package/pipeline/multi-agent-refs/phases/phase-2-dev.md +9 -12
  42. package/pipeline/multi-agent-refs/phases/phase-3-review.md +9 -8
  43. package/pipeline/multi-agent-refs/phases/phase-4-commit.md +1 -4
  44. package/pipeline/multi-agent-refs/rules.md +3 -2
  45. package/pipeline/multi-agent-refs/tracker-contract.md +1 -1
  46. package/pipeline/office/NOTICE.md +4 -1
  47. package/pipeline/office/assets/char_12.png +0 -0
  48. package/pipeline/office/assets/char_13.png +0 -0
  49. package/pipeline/office/assets/char_14.png +0 -0
  50. package/pipeline/office/assets/char_15.png +0 -0
  51. package/pipeline/office/assets/char_16.png +0 -0
  52. package/pipeline/office/assets/char_17.png +0 -0
  53. package/pipeline/office/assets/char_18.png +0 -0
  54. package/pipeline/office/assets/char_19.png +0 -0
  55. package/pipeline/office/assets/char_20.png +0 -0
  56. package/pipeline/office/assets/char_21.png +0 -0
  57. package/pipeline/office/assets/char_22.png +0 -0
  58. package/pipeline/office/assets/char_23.png +0 -0
  59. package/pipeline/office/assets/char_24.png +0 -0
  60. package/pipeline/office/assets/char_25.png +0 -0
  61. package/pipeline/office/assets/char_26.png +0 -0
  62. package/pipeline/office/assets/char_27.png +0 -0
  63. package/pipeline/office/assets/char_28.png +0 -0
  64. package/pipeline/office/assets/char_29.png +0 -0
  65. package/pipeline/office/assets/char_30.png +0 -0
  66. package/pipeline/office/index.html +293 -49
  67. package/pipeline/schemas/agent-state.schema.json +18 -0
  68. package/pipeline/schemas/planning-output.schema.json +18 -0
  69. package/pipeline/schemas/pr-reach.schema.json +55 -0
  70. package/pipeline/schemas/prefs.schema.json +13 -7
  71. package/pipeline/schemas/triage-output.schema.json +12 -1
  72. package/pipeline/schemas/unattended-policy.json +2 -1
  73. package/pipeline/scripts/_guard_rules.py +449 -1
  74. package/pipeline/scripts/_test-gaming.mjs +36 -0
  75. package/pipeline/scripts/agent-guard.py +79 -19
  76. package/pipeline/scripts/anonymize-findings.mjs +99 -0
  77. package/pipeline/scripts/answer-check.mjs +113 -0
  78. package/pipeline/scripts/answer-check.sh +20 -0
  79. package/pipeline/scripts/autopilot-publish.mjs +9 -2
  80. package/pipeline/scripts/contract-server.mjs +35 -1
  81. package/pipeline/scripts/gate-ledger.mjs +144 -21
  82. package/pipeline/scripts/office-build.mjs +276 -5
  83. package/pipeline/scripts/office-control.mjs +70 -10
  84. package/pipeline/scripts/office-pair.mjs +438 -0
  85. package/pipeline/scripts/office-remote-client.mjs +463 -0
  86. package/pipeline/scripts/phase-tracker.sh +8 -0
  87. package/pipeline/scripts/phase0-exit-gate.mjs +40 -37
  88. package/pipeline/scripts/phone-devices.mjs +9 -1
  89. package/pipeline/scripts/pre-commit-check.sh +28 -2
  90. package/pipeline/scripts/pre-push-check.sh +6 -12
  91. package/pipeline/scripts/rework-base.mjs +87 -0
  92. package/pipeline/scripts/run-commit-check.mjs +104 -0
  93. package/pipeline/scripts/run-scope-guard.mjs +58 -3
  94. package/pipeline/scripts/run-scope-guard.sh +13 -1
  95. package/pipeline/scripts/scope-check-gate.mjs +70 -6
  96. package/pipeline/scripts/task-mirror.mjs +106 -15
  97. package/pipeline/scripts/task-mirror.sh +3 -2
  98. package/pipeline/scripts/test-stability-gate.mjs +112 -0
  99. package/pipeline/scripts/update-check.sh +7 -1
  100. package/pipeline/scripts/update-issue-progress.sh +73 -8
  101. package/pipeline/scripts/validate-planning.mjs +105 -1
  102. package/pipeline/scripts/validate-triage.mjs +42 -2
  103. package/pipeline/scripts/work-items.mjs +119 -1
  104. package/pipeline/scripts/worktree-prepare-all.mjs +200 -0
  105. package/pipeline/scripts/worktree-prepare.sh +40 -4
  106. package/pipeline/scripts/write-state.mjs +67 -24
  107. package/pipeline/skills/.skill-manifest.json +12 -8
  108. package/pipeline/skills/.skills-index.json +15 -4
  109. package/pipeline/skills/shared/README.md +4 -3
  110. package/pipeline/skills/shared/core/apple-archive-compliance/SKILL.md +1 -1
  111. package/pipeline/skills/shared/core/google-play-compliance/SKILL.md +6 -6
  112. package/pipeline/skills/shared/core/google-play-compliance/references/rules.yml +1 -1
  113. package/pipeline/skills/shared/core/multi-agent-channels/SKILL.md +1 -1
  114. package/pipeline/skills/shared/core/multi-agent-office-pair/SKILL.md +19 -0
  115. package/pipeline/skills/shared/core/multi-agent-office-status/SKILL.md +2 -2
  116. package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +3 -3
  117. package/pipeline/skills/shared/external/alarmkit/references/alarmkit-patterns.md +14 -0
  118. package/pipeline/skills/shared/external/android-architecture/references/patterns.md +6 -0
  119. package/pipeline/skills/shared/external/android-build-quality-gates/references/patterns.md +10 -0
  120. package/pipeline/skills/shared/external/android-datastore/references/patterns.md +11 -0
  121. package/pipeline/skills/shared/external/android-design-tokens-codegen/references/patterns.md +8 -0
  122. package/pipeline/skills/shared/external/android-jetpack-compose-expert/references/patterns.md +6 -0
  123. package/pipeline/skills/shared/external/android-mvi-viewmodel/references/patterns.md +10 -0
  124. package/pipeline/skills/shared/external/android-performance/references/patterns.md +13 -0
  125. package/pipeline/skills/shared/external/android-security/references/patterns.md +16 -0
  126. package/pipeline/skills/shared/external/api-patterns/references/contract-details.md +9 -0
  127. package/pipeline/skills/shared/external/api-security-best-practices/references/abuse-controls.md +12 -0
  128. package/pipeline/skills/shared/external/api-security-best-practices/references/identity-and-access.md +13 -0
  129. package/pipeline/skills/shared/external/api-security-best-practices/references/request-handling.md +12 -0
  130. package/pipeline/skills/shared/external/app-clips/references/data-handoff-notifications-location.md +9 -0
  131. package/pipeline/skills/shared/external/app-clips/references/routing-and-experiences.md +8 -0
  132. package/pipeline/skills/shared/external/app-clips/references/size-capabilities-and-promotion.md +10 -0
  133. package/pipeline/skills/shared/external/app-intents/references/appintents-advanced.md +21 -0
  134. package/pipeline/skills/shared/external/app-store-optimization/references/keyword-research-methodology.md +9 -0
  135. package/pipeline/skills/shared/external/app-store-optimization/references/product-page-variants.md +7 -0
  136. package/pipeline/skills/shared/external/app-store-review/SKILL.md +2 -2
  137. package/pipeline/skills/shared/external/app-store-review/references/privacy-manifest.md +10 -0
  138. package/pipeline/skills/shared/external/app-store-review/references/review-checklists.md +10 -1
  139. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-conversion.md +22 -0
  140. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-optimization.md +17 -0
  141. package/pipeline/skills/shared/external/apple-on-device-ai/references/foundation-models.md +22 -0
  142. package/pipeline/skills/shared/external/apple-on-device-ai/references/mlx-swift.md +17 -0
  143. package/pipeline/skills/shared/external/authentication/references/keychain-biometric.md +9 -0
  144. package/pipeline/skills/shared/external/authentication/references/passkeys.md +11 -0
  145. package/pipeline/skills/shared/external/avkit/references/avkit-patterns.md +13 -0
  146. package/pipeline/skills/shared/external/background-processing/references/background-task-patterns.md +9 -0
  147. package/pipeline/skills/shared/external/callkit-voip/references/callkit-patterns.md +10 -0
  148. package/pipeline/skills/shared/external/cloudkit-sync/references/cloudkit-patterns.md +15 -0
  149. package/pipeline/skills/shared/external/compose-components/references/patterns.md +7 -0
  150. package/pipeline/skills/shared/external/compose-navigation/references/patterns.md +7 -0
  151. package/pipeline/skills/shared/external/compose-testing/references/patterns.md +15 -0
  152. package/pipeline/skills/shared/external/contacts-framework/references/contacts-patterns.md +9 -0
  153. package/pipeline/skills/shared/external/core-bluetooth/references/ble-patterns.md +11 -0
  154. package/pipeline/skills/shared/external/core-motion/references/motion-patterns.md +10 -0
  155. package/pipeline/skills/shared/external/core-nfc/references/nfc-patterns.md +13 -0
  156. package/pipeline/skills/shared/external/coreml/references/coreml-swift-integration.md +20 -0
  157. package/pipeline/skills/shared/external/cryptokit/references/cryptokit-patterns.md +16 -0
  158. package/pipeline/skills/shared/external/debugging-instruments/references/instruments-guide.md +16 -0
  159. package/pipeline/skills/shared/external/debugging-instruments/references/lldb-patterns.md +14 -0
  160. package/pipeline/skills/shared/external/device-integrity/references/device-integrity-patterns.md +13 -0
  161. package/pipeline/skills/shared/external/energykit/references/energykit-patterns.md +10 -0
  162. package/pipeline/skills/shared/external/eventkit-calendar/references/eventkit-patterns.md +10 -0
  163. package/pipeline/skills/shared/external/fastapi-pro/references/app-structure.md +10 -0
  164. package/pipeline/skills/shared/external/gradle-kotlin-dsl/references/patterns.md +17 -0
  165. package/pipeline/skills/shared/external/healthkit/references/healthkit-patterns.md +12 -0
  166. package/pipeline/skills/shared/external/hig-app-icons/references/icon-workflow.md +10 -0
  167. package/pipeline/skills/shared/external/hig-components-content/references/content-views.md +10 -0
  168. package/pipeline/skills/shared/external/hig-components-layout/references/bars-and-tabs.md +11 -0
  169. package/pipeline/skills/shared/external/hig-foundations/references/foundations-detail.md +13 -0
  170. package/pipeline/skills/shared/external/hig-foundations/references/type-color-spacing.md +13 -0
  171. package/pipeline/skills/shared/external/hig-patterns/references/onboarding-and-states.md +11 -0
  172. package/pipeline/skills/shared/external/hig-platforms/references/ipad-layout.md +12 -0
  173. package/pipeline/skills/shared/external/hig-technologies/references/technologies.md +16 -0
  174. package/pipeline/skills/shared/external/homekit-matter/references/matter-commissioning.md +9 -0
  175. package/pipeline/skills/shared/external/ios-accessibility/references/a11y-patterns.md +18 -0
  176. package/pipeline/skills/shared/external/ios-accessibility/references/large-content-and-appearance.md +9 -0
  177. package/pipeline/skills/shared/external/ios-accessibility/references/media-accessibility.md +9 -0
  178. package/pipeline/skills/shared/external/ios-accessibility/references/nutrition-labels.md +7 -0
  179. package/pipeline/skills/shared/external/ios-coding-standard/references/STANDARD.md +13 -0
  180. package/pipeline/skills/shared/external/ios-design-review/references/appearance-matrix.md +9 -0
  181. package/pipeline/skills/shared/external/ios-design-review/references/checklist.md +15 -0
  182. package/pipeline/skills/shared/external/ios-haptics/references/core-haptics.md +11 -0
  183. package/pipeline/skills/shared/external/ios-iphone-duo/references/api-map.md +11 -0
  184. package/pipeline/skills/shared/external/ios-iphone-duo/references/fixed-assumptions.md +15 -0
  185. package/pipeline/skills/shared/external/ios-iphone-duo/references/poses-and-panes.md +11 -0
  186. package/pipeline/skills/shared/external/ios-localization/references/formatstyle-locale.md +18 -0
  187. package/pipeline/skills/shared/external/ios-localization/references/string-catalogs.md +19 -0
  188. package/pipeline/skills/shared/external/ios-networking/references/background-websocket.md +15 -0
  189. package/pipeline/skills/shared/external/ios-networking/references/file-storage-patterns.md +7 -0
  190. package/pipeline/skills/shared/external/ios-networking/references/lightweight-clients.md +8 -0
  191. package/pipeline/skills/shared/external/ios-networking/references/network-framework.md +12 -0
  192. package/pipeline/skills/shared/external/ios-networking/references/urlsession-patterns.md +17 -0
  193. package/pipeline/skills/shared/external/ios-security/references/app-review-guidelines.md +8 -0
  194. package/pipeline/skills/shared/external/ios-security/references/cryptokit-advanced.md +14 -0
  195. package/pipeline/skills/shared/external/ios-security/references/file-storage-patterns.md +8 -0
  196. package/pipeline/skills/shared/external/ios-security/references/privacy-manifest.md +9 -0
  197. package/pipeline/skills/shared/external/ios-sf-symbols/references/effects-and-custom-symbols.md +9 -0
  198. package/pipeline/skills/shared/external/ios-simulator/references/simctl-commands.md +13 -0
  199. package/pipeline/skills/shared/external/kotlin-coroutines-expert/references/patterns.md +8 -0
  200. package/pipeline/skills/shared/external/live-activities/references/activitykit-patterns.md +21 -0
  201. package/pipeline/skills/shared/external/localization-reuse-map/reference/format-and-output.md +9 -0
  202. package/pipeline/skills/shared/external/localization-reuse-map/reference/sources-and-recipes.md +12 -0
  203. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-corelocation-patterns.md +16 -0
  204. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-patterns.md +21 -0
  205. package/pipeline/skills/shared/external/metrickit-diagnostics/references/metrickit-patterns.md +10 -0
  206. package/pipeline/skills/shared/external/musickit-audio/references/musickit-patterns.md +9 -0
  207. package/pipeline/skills/shared/external/natural-language/references/translation-patterns.md +12 -0
  208. package/pipeline/skills/shared/external/nodejs-backend-patterns/references/runtime-patterns.md +11 -0
  209. package/pipeline/skills/shared/external/passkit-wallet/references/wallet-passes.md +11 -0
  210. package/pipeline/skills/shared/external/pdfkit/references/pdfkit-patterns.md +18 -0
  211. package/pipeline/skills/shared/external/pencilkit-drawing/references/pencilkit-patterns.md +11 -0
  212. package/pipeline/skills/shared/external/permissionkit/references/permissionkit-patterns.md +11 -0
  213. package/pipeline/skills/shared/external/photos-camera-media/references/av-playback.md +15 -0
  214. package/pipeline/skills/shared/external/photos-camera-media/references/camera-capture.md +14 -0
  215. package/pipeline/skills/shared/external/photos-camera-media/references/image-loading-caching.md +14 -0
  216. package/pipeline/skills/shared/external/photos-camera-media/references/photokit-patterns.md +14 -0
  217. package/pipeline/skills/shared/external/push-notifications/references/notification-patterns.md +14 -0
  218. package/pipeline/skills/shared/external/push-notifications/references/rich-notifications.md +10 -0
  219. package/pipeline/skills/shared/external/realitykit-ar/references/realitykit-patterns.md +12 -0
  220. package/pipeline/skills/shared/external/retrofit-networking/references/patterns.md +14 -0
  221. package/pipeline/skills/shared/external/room-database/references/patterns.md +16 -0
  222. package/pipeline/skills/shared/external/shareplay-activities/references/shareplay-patterns.md +10 -0
  223. package/pipeline/skills/shared/external/speech-recognition/references/speechanalyzer-patterns.md +10 -0
  224. package/pipeline/skills/shared/external/spm-build-analysis/references/build-optimization-sources.md +14 -0
  225. package/pipeline/skills/shared/external/spm-build-analysis/references/spm-analysis-checks.md +19 -0
  226. package/pipeline/skills/shared/external/storekit/references/core-patterns.md +13 -0
  227. package/pipeline/skills/shared/external/storekit/references/storekit-advanced.md +31 -0
  228. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/argument-labels-and-parameters.md +8 -0
  229. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/conventions-and-special-rules.md +9 -0
  230. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/naming-and-clarity.md +10 -0
  231. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/side-effects-and-mutating-pairs.md +8 -0
  232. package/pipeline/skills/shared/external/swift-charts/references/charts-patterns.md +24 -0
  233. package/pipeline/skills/shared/external/swift-concurrency/references/bridging-interop.md +8 -0
  234. package/pipeline/skills/shared/external/swift-concurrency/references/concurrency-patterns.md +14 -0
  235. package/pipeline/skills/shared/external/swift-concurrency/references/swiftui-concurrency.md +12 -0
  236. package/pipeline/skills/shared/external/swift-concurrency/references/synchronization-primitives.md +10 -0
  237. package/pipeline/skills/shared/external/swift-concurrency-expert/references/swift-6-2-concurrency.md +8 -0
  238. package/pipeline/skills/shared/external/swift-concurrency-pro/references/actors.md +10 -0
  239. package/pipeline/skills/shared/external/swift-concurrency-pro/references/cancellation.md +7 -0
  240. package/pipeline/skills/shared/external/swift-concurrency-pro/references/interop.md +10 -0
  241. package/pipeline/skills/shared/external/swift-concurrency-pro/references/new-features.md +11 -0
  242. package/pipeline/skills/shared/external/swift-concurrency-pro/references/structured.md +9 -0
  243. package/pipeline/skills/shared/external/swift-concurrency-pro/references/testing.md +13 -0
  244. package/pipeline/skills/shared/external/swift-language/references/swift-attributes-interop.md +7 -0
  245. package/pipeline/skills/shared/external/swift-language/references/swift-patterns-extended.md +14 -0
  246. package/pipeline/skills/shared/external/swift-security/references/biometric-authentication.md +16 -0
  247. package/pipeline/skills/shared/external/swift-security/references/certificate-trust.md +17 -0
  248. package/pipeline/skills/shared/external/swift-security/references/common-anti-patterns.md +19 -0
  249. package/pipeline/skills/shared/external/swift-security/references/compliance-owasp-mapping.md +16 -0
  250. package/pipeline/skills/shared/external/swift-security/references/credential-storage-patterns.md +19 -0
  251. package/pipeline/skills/shared/external/swift-security/references/cryptokit-public-key.md +18 -0
  252. package/pipeline/skills/shared/external/swift-security/references/cryptokit-symmetric.md +16 -0
  253. package/pipeline/skills/shared/external/swift-security/references/keychain-access-control.md +17 -0
  254. package/pipeline/skills/shared/external/swift-security/references/keychain-fundamentals.md +17 -0
  255. package/pipeline/skills/shared/external/swift-security/references/keychain-item-classes.md +17 -0
  256. package/pipeline/skills/shared/external/swift-security/references/keychain-sharing.md +18 -0
  257. package/pipeline/skills/shared/external/swift-security/references/migration-legacy-stores.md +21 -0
  258. package/pipeline/skills/shared/external/swift-security/references/secure-enclave.md +16 -0
  259. package/pipeline/skills/shared/external/swift-security/references/testing-security-code.md +16 -0
  260. package/pipeline/skills/shared/external/swift-testing/references/testing-advanced.md +9 -0
  261. package/pipeline/skills/shared/external/swift-testing/references/testing-patterns.md +24 -0
  262. package/pipeline/skills/shared/external/swift-testing-pro/references/async-tests.md +9 -0
  263. package/pipeline/skills/shared/external/swift-testing-pro/references/new-features.md +11 -0
  264. package/pipeline/skills/shared/external/swift-testing-pro/references/writing-better-tests.md +13 -0
  265. package/pipeline/skills/shared/external/swiftdata/references/core-data-coexistence.md +8 -0
  266. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-advanced.md +17 -0
  267. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-queries.md +12 -0
  268. package/pipeline/skills/shared/external/swiftlint/references/adoption-and-configuration.md +11 -0
  269. package/pipeline/skills/shared/external/swiftlint/references/custom-rules-and-analyze.md +7 -0
  270. package/pipeline/skills/shared/external/swiftlint/references/plugins-run-scripts-and-integrations.md +13 -0
  271. package/pipeline/skills/shared/external/swiftlint/references/rule-reference.md +24 -0
  272. package/pipeline/skills/shared/external/swiftlint/references/rules-suppressions-and-baselines.md +12 -0
  273. package/pipeline/skills/shared/external/swiftui-animation/references/animation-advanced.md +15 -0
  274. package/pipeline/skills/shared/external/swiftui-animation/references/core-animation-bridge.md +15 -0
  275. package/pipeline/skills/shared/external/swiftui-animation/references/scroll-effects.md +12 -0
  276. package/pipeline/skills/shared/external/swiftui-expert-skill/references/accessibility-patterns.md +11 -0
  277. package/pipeline/skills/shared/external/swiftui-expert-skill/references/animation-advanced.md +7 -0
  278. package/pipeline/skills/shared/external/swiftui-expert-skill/references/animation-basics.md +13 -0
  279. package/pipeline/skills/shared/external/swiftui-expert-skill/references/animation-transitions.md +9 -0
  280. package/pipeline/skills/shared/external/swiftui-expert-skill/references/charts-accessibility.md +9 -0
  281. package/pipeline/skills/shared/external/swiftui-expert-skill/references/charts.md +17 -0
  282. package/pipeline/skills/shared/external/swiftui-expert-skill/references/image-optimization.md +9 -0
  283. package/pipeline/skills/shared/external/swiftui-expert-skill/references/latest-apis.md +10 -0
  284. package/pipeline/skills/shared/external/swiftui-expert-skill/references/layout-best-practices.md +12 -0
  285. package/pipeline/skills/shared/external/swiftui-expert-skill/references/list-patterns.md +12 -0
  286. package/pipeline/skills/shared/external/swiftui-expert-skill/references/macos-scenes.md +13 -0
  287. package/pipeline/skills/shared/external/swiftui-expert-skill/references/macos-views.md +12 -0
  288. package/pipeline/skills/shared/external/swiftui-expert-skill/references/macos-window-styling.md +12 -0
  289. package/pipeline/skills/shared/external/swiftui-expert-skill/references/performance-patterns.md +7 -0
  290. package/pipeline/skills/shared/external/swiftui-expert-skill/references/scroll-patterns.md +9 -0
  291. package/pipeline/skills/shared/external/swiftui-expert-skill/references/sheet-navigation-patterns.md +10 -0
  292. package/pipeline/skills/shared/external/swiftui-expert-skill/references/state-management.md +18 -0
  293. package/pipeline/skills/shared/external/swiftui-expert-skill/references/view-structure.md +16 -0
  294. package/pipeline/skills/shared/external/swiftui-gestures/references/gesture-patterns.md +11 -0
  295. package/pipeline/skills/shared/external/swiftui-layout-components/references/form.md +8 -0
  296. package/pipeline/skills/shared/external/swiftui-layout-components/references/grids.md +14 -0
  297. package/pipeline/skills/shared/external/swiftui-layout-components/references/scrollview.md +9 -0
  298. package/pipeline/skills/shared/external/swiftui-liquid-glass/references/liquid-glass.md +22 -0
  299. package/pipeline/skills/shared/external/swiftui-liquid-glass/references/uikit-glass.md +14 -0
  300. package/pipeline/skills/shared/external/swiftui-navigation/references/deeplinks.md +10 -0
  301. package/pipeline/skills/shared/external/swiftui-navigation/references/navigationstack.md +10 -0
  302. package/pipeline/skills/shared/external/swiftui-navigation/references/sheets.md +13 -0
  303. package/pipeline/skills/shared/external/swiftui-navigation/references/tabview.md +10 -0
  304. package/pipeline/skills/shared/external/swiftui-patterns/references/architecture-patterns.md +14 -0
  305. package/pipeline/skills/shared/external/swiftui-patterns/references/deprecated-migration.md +30 -0
  306. package/pipeline/skills/shared/external/swiftui-patterns/references/platform-and-sharing.md +16 -0
  307. package/pipeline/skills/shared/external/swiftui-performance/references/demystify-swiftui-performance-wwdc23.md +11 -0
  308. package/pipeline/skills/shared/external/swiftui-performance/references/optimizing-swiftui-performance-instruments.md +11 -0
  309. package/pipeline/skills/shared/external/swiftui-performance/references/understanding-hangs-in-your-app.md +10 -0
  310. package/pipeline/skills/shared/external/swiftui-performance-audit/references/code-smells.md +8 -0
  311. package/pipeline/skills/shared/external/swiftui-ui-patterns/references/app-wiring.md +12 -0
  312. package/pipeline/skills/shared/external/swiftui-ui-patterns/references/menu-bar.md +10 -0
  313. package/pipeline/skills/shared/external/swiftui-ui-patterns/references/navigationstack.md +11 -0
  314. package/pipeline/skills/shared/external/swiftui-ui-patterns/references/scroll-reveal.md +12 -0
  315. package/pipeline/skills/shared/external/swiftui-ui-patterns/references/sheets.md +14 -0
  316. package/pipeline/skills/shared/external/swiftui-ui-patterns/references/tabview.md +10 -0
  317. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/hosting-migration.md +10 -0
  318. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/representable-recipes.md +13 -0
  319. package/pipeline/skills/shared/external/swiftui-view-refactor/references/mv-patterns.md +12 -0
  320. package/pipeline/skills/shared/external/swiftui-webkit/references/loading-and-observation.md +8 -0
  321. package/pipeline/skills/shared/external/swiftui-webkit/references/navigation-and-javascript.md +8 -0
  322. package/pipeline/skills/shared/external/tipkit/references/tipkit-patterns.md +14 -0
  323. package/pipeline/skills/shared/external/vision-framework/references/vision-requests.md +17 -0
  324. package/pipeline/skills/shared/external/vision-framework/references/visionkit-scanner.md +11 -0
  325. package/pipeline/skills/shared/external/weatherkit/references/weatherkit-patterns.md +11 -0
  326. package/pipeline/skills/shared/external/widgetkit/references/widgetkit-advanced.md +27 -0
  327. package/pipeline/skills/shared/external/xcode-build-fixer/references/build-settings-best-practices.md +9 -0
  328. package/pipeline/skills/shared/external/xcode-build-fixer/references/fix-patterns.md +7 -0
  329. package/pipeline/skills/shared/external/xcode-build-orchestrator/references/build-settings-best-practices.md +9 -0
  330. package/pipeline/skills/shared/external/xcode-compilation-analyzer/references/build-optimization-sources.md +14 -0
  331. package/pipeline/skills/shared/external/xcode-compilation-analyzer/references/code-compilation-checks.md +8 -0
  332. package/pipeline/skills/shared/external/xcode-project-analyzer/references/build-optimization-sources.md +14 -0
  333. package/pipeline/skills/shared/external/xcode-project-analyzer/references/build-settings-best-practices.md +9 -0
  334. package/pipeline/skills/shared/external/xcode-project-analyzer/references/project-audit-checks.md +13 -0
  335. package/pipeline/skills/skills-index.md +2 -1
@@ -0,0 +1,438 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @file office-pair.mjs - pair a phone with this machine for the office
4
+ * remote layer (features/office-remote-protocol.md, Pairing).
5
+ *
6
+ * start [--relay <url>] [--terminal] register a pairing with the relay and
7
+ * show its QR (on this terminal when it is one)
8
+ * code on this machine's screen
9
+ * wait wait for the phone's pairing message, open it and
10
+ * print the comparison code
11
+ * confirm <code> enrol the device once the code the phone shows is
12
+ * typed back here, and send the phone its device id
13
+ * in the first sealed machine-to-phone frame
14
+ * cancel drop the pending pairing
15
+ *
16
+ * What stays on this machine: the machine private key and the relay token
17
+ * live in <phone dir>/remote.json (0600); the relay only gets the SHA-256 of
18
+ * the token. The one-time secret and the machine public key travel in the QR
19
+ * link's fragment, which a browser never sends to a server, so the relay can
20
+ * neither open the phone's pairing message nor swap the machine key. The QR
21
+ * page is a 0600 file in a 0700 directory opened in the local browser; the
22
+ * secret is never printed. Enrolment goes through `phone-devices.mjs add`
23
+ * with scopes read,answer, so `launch` stays a separate local switch.
24
+ *
25
+ * Every subcommand refuses an unattended run (unattended-policy.json).
26
+ * Exit: 0 done, 1 refused or failed, 2 usage, 3 unattended.
27
+ *
28
+ * @module pipeline/scripts/office-pair
29
+ */
30
+
31
+ import { spawnSync } from "node:child_process";
32
+ import { createHash, randomBytes, timingSafeEqual } from "node:crypto";
33
+ import { chmodSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
34
+ import { homedir } from "node:os";
35
+ import { dirname, join } from "node:path";
36
+ import { fileURLToPath } from "node:url";
37
+
38
+ import {
39
+ comparisonCode,
40
+ createMachineKeys,
41
+ directionKeys,
42
+ openPairing,
43
+ sealFrame,
44
+ } from "../lib/office-remote.mjs";
45
+ import { invokedDirectly } from "../lib/invoked-directly.mjs";
46
+ import { encodeQr, qrSvg, qrText } from "../lib/qr-code.mjs";
47
+ import { isUnattended } from "../lib/unattended.mjs";
48
+ import { phoneDir } from "./_phone-auth.mjs";
49
+ import { readConfig, writeConfig } from "./office-remote-client.mjs";
50
+
51
+ const HERE = dirname(fileURLToPath(import.meta.url));
52
+ export const PAIRING_TTL_MS = 10 * 60_000;
53
+ const NAME = /^[\p{L}\p{N} ._'-]{1,64}$/u;
54
+ const B64U = /^[A-Za-z0-9_-]+$/;
55
+
56
+ const home = (env) => env.HOME || homedir();
57
+ export const pendingPath = (env = process.env) => join(phoneDir(env), "pair-pending.json");
58
+ const pageDir = (env) => join(home(env), ".claude", "logs", "multi-agent", "office");
59
+ const pagePath = (env) => join(pageDir(env), "pair.html");
60
+ const b64u = (b) => Buffer.from(b).toString("base64url");
61
+ const sha256hex = (s) => createHash("sha256").update(s).digest("hex");
62
+
63
+ /** First 16 hex digits of SHA-256 over a public key, in groups of four (the phone shows the same). */
64
+ export const keyFingerprint = (publicKey) =>
65
+ createHash("sha256")
66
+ .update(Buffer.from(publicKey, "base64url"))
67
+ .digest("hex")
68
+ .slice(0, 16)
69
+ .replace(/(.{4})(?=.)/g, "$1 ");
70
+
71
+ class Refusal extends Error {}
72
+
73
+ function readJson(p) {
74
+ try {
75
+ return JSON.parse(readFileSync(p, "utf8"));
76
+ } catch {
77
+ return null;
78
+ }
79
+ }
80
+
81
+ function writePrivate(file, text) {
82
+ mkdirSync(dirname(file), { recursive: true, mode: 0o700 });
83
+ chmodSync(dirname(file), 0o700);
84
+ writeFileSync(file, text, { mode: 0o600 });
85
+ chmodSync(file, 0o600);
86
+ }
87
+
88
+ /** A relay URL: https, or http on the loopback; no credentials, query or fragment. */
89
+ export function relayOrigin(raw) {
90
+ let u;
91
+ try {
92
+ u = new URL(String(raw));
93
+ } catch {
94
+ throw new Refusal("the relay URL is not a URL");
95
+ }
96
+ const loopback = ["127.0.0.1", "localhost", "[::1]"].includes(u.hostname);
97
+ if (u.protocol !== "https:" && !(u.protocol === "http:" && loopback)) {
98
+ throw new Refusal("the relay URL must be https");
99
+ }
100
+ if (u.username || u.password || u.search || u.hash || (u.pathname && u.pathname !== "/")) {
101
+ throw new Refusal("the relay URL is an origin only (scheme, host, port)");
102
+ }
103
+ return u.origin;
104
+ }
105
+
106
+ function relayFromPrefs(env) {
107
+ const prefs = readJson(join(home(env), ".claude", "multi-agent-preferences.json"));
108
+ return prefs?.global?.office?.remote?.relayUrl ?? null;
109
+ }
110
+
111
+ /** The link the QR code carries; everything after `#` stays on the phone. */
112
+ export function pairingLink({ relayUrl, pairingId, secret, machinePublic }) {
113
+ return `${relayUrl}/office/pair#p=${pairingId}&s=${secret}&k=${machinePublic}`;
114
+ }
115
+
116
+ function pageHtml(svg) {
117
+ return (
118
+ "<!doctype html><html><head><meta charset=utf-8>" +
119
+ `<meta http-equiv="Content-Security-Policy" content="default-src 'none'">` +
120
+ "<title>Office pairing</title></head><body>" +
121
+ "<p>Scan with the phone, signed in to your site. The code expires in 10 minutes.</p>" +
122
+ `${svg}</body></html>`
123
+ );
124
+ }
125
+
126
+ function openPage(file, env) {
127
+ const bin = env.MA_OFFICE_OPENER || "open";
128
+ const r = spawnSync(bin, [`file://${file}`], { stdio: "ignore", timeout: 15000 });
129
+ return r.status === 0;
130
+ }
131
+
132
+ async function relayCall(fetchImpl, url, init) {
133
+ const res = await fetchImpl(url, { ...init, signal: AbortSignal.timeout(30_000) });
134
+ const text = await res.text();
135
+ let body;
136
+ try {
137
+ body = text ? JSON.parse(text) : null;
138
+ } catch {
139
+ body = null;
140
+ }
141
+ return { status: res.status, ok: res.ok, body };
142
+ }
143
+
144
+ /**
145
+ * Register a pairing with the relay and show its QR code.
146
+ *
147
+ * With `terminal`, the QR is also drawn on that stream, but only when it is a
148
+ * TTY: captured output (an agent's tool call, a pipe, a log) would keep the
149
+ * one-time secret the code carries.
150
+ *
151
+ * @returns {Promise<{pairingId: string, expiresAt: string, page: string, opened: boolean,
152
+ * terminal?: boolean, terminalRefused?: string}>}
153
+ */
154
+ export async function start({
155
+ relay,
156
+ env = process.env,
157
+ fetchImpl = fetch,
158
+ now = Date.now(),
159
+ terminal = null,
160
+ }) {
161
+ const configured = relay ?? relayFromPrefs(env);
162
+ if (!configured) {
163
+ throw new Refusal(
164
+ "no relay is set; add prefs global.office.remote.relayUrl or pass --relay <url>",
165
+ );
166
+ }
167
+ const relayUrl = relayOrigin(configured);
168
+ const existing = readConfig(env);
169
+ const machine =
170
+ existing?.machinePrivatePem && existing?.machinePublic
171
+ ? { privatePem: existing.machinePrivatePem, publicKey: existing.machinePublic }
172
+ : createMachineKeys();
173
+ const relayToken =
174
+ existing?.relayToken && existing.relayUrl === relayUrl
175
+ ? existing.relayToken
176
+ : b64u(randomBytes(32));
177
+ const pairingId = b64u(randomBytes(16));
178
+ const secret = b64u(randomBytes(16));
179
+ const expiresAt = new Date(now + PAIRING_TTL_MS).toISOString();
180
+ const r = await relayCall(fetchImpl, `${relayUrl}/api/office/relay/pairings`, {
181
+ method: "POST",
182
+ headers: { "content-type": "application/json" },
183
+ body: JSON.stringify({
184
+ pairingId,
185
+ machinePublic: machine.publicKey,
186
+ tokenHash: sha256hex(relayToken),
187
+ expiresAt,
188
+ }),
189
+ });
190
+ if (!r.ok) throw new Refusal(`the relay refused the pairing (${r.status})`);
191
+ writeConfig(
192
+ {
193
+ ...(existing ?? {}),
194
+ relayUrl,
195
+ relayToken,
196
+ pairingId: existing?.pairingId ?? null,
197
+ machinePrivatePem: machine.privatePem,
198
+ machinePublic: machine.publicKey,
199
+ devices: existing?.devices ?? {},
200
+ },
201
+ env,
202
+ );
203
+ writePrivate(
204
+ pendingPath(env),
205
+ JSON.stringify({ relayUrl, pairingId, secret, expiresAt, relayToken }) + "\n",
206
+ );
207
+ const link = pairingLink({ relayUrl, pairingId, secret, machinePublic: machine.publicKey });
208
+ const qr = encodeQr(link, { ecc: "M" });
209
+ writePrivate(pagePath(env), pageHtml(qrSvg(qr)));
210
+ const out = { pairingId, expiresAt, page: pagePath(env) };
211
+ if (terminal) {
212
+ if (terminal.isTTY) {
213
+ terminal.write(`${qrText(qr)}\n\nScan with the phone; the code expires in 10 minutes.\n`);
214
+ return { ...out, opened: false, terminal: true };
215
+ }
216
+ out.terminal = false;
217
+ out.terminalRefused = "stdout is not a terminal, so the QR stays in the page";
218
+ }
219
+ return { ...out, opened: openPage(pagePath(env), env) };
220
+ }
221
+
222
+ function pending(env, now) {
223
+ const p = readJson(pendingPath(env));
224
+ if (!p?.pairingId) throw new Refusal("no pairing is pending; run office-pair start");
225
+ if (Date.parse(p.expiresAt) <= now) {
226
+ dropPending(env);
227
+ throw new Refusal("the pairing expired; run office-pair start again");
228
+ }
229
+ return p;
230
+ }
231
+
232
+ function dropPending(env) {
233
+ rmSync(pendingPath(env), { force: true });
234
+ rmSync(pagePath(env), { force: true });
235
+ }
236
+
237
+ /** Check what the phone sent before anything of it is kept. */
238
+ export function checkPairingMessage(value, relayUrl) {
239
+ const v = value ?? {};
240
+ if (typeof v.deviceName !== "string" || !NAME.test(v.deviceName))
241
+ throw new Refusal("the device name is not 1 to 64 letters, digits, spaces or ._'-");
242
+ if (typeof v.devicePublicKey !== "string" || !/^[A-Za-z0-9_-]{43}$/.test(v.devicePublicKey))
243
+ throw new Refusal("the device key is not a base64url Ed25519 public key");
244
+ const pk = v.passkey ?? {};
245
+ if (typeof pk.credential !== "string" || !B64U.test(pk.credential) || pk.credential.length > 400)
246
+ throw new Refusal("the passkey public key is missing");
247
+ if (typeof pk.credentialId !== "string" || !B64U.test(pk.credentialId))
248
+ throw new Refusal("the passkey credential id is missing");
249
+ if (pk.origin !== relayUrl) throw new Refusal("the passkey origin is not the relay's");
250
+ if (pk.rpId !== new URL(relayUrl).hostname)
251
+ throw new Refusal("the passkey rp id is not the relay's host");
252
+ return {
253
+ deviceName: v.deviceName,
254
+ devicePublicKey: v.devicePublicKey,
255
+ passkey: {
256
+ credential: pk.credential,
257
+ credentialId: pk.credentialId,
258
+ rpId: pk.rpId,
259
+ origin: pk.origin,
260
+ },
261
+ };
262
+ }
263
+
264
+ /**
265
+ * Wait for the phone's pairing message, open it and keep it with the pending
266
+ * pairing. Prints the comparison code, never a key.
267
+ */
268
+ export async function wait({
269
+ env = process.env,
270
+ fetchImpl = fetch,
271
+ now = Date.now,
272
+ pollMs = 2000,
273
+ }) {
274
+ const p = pending(env, now());
275
+ const config = readConfig(env);
276
+ while (now() < Date.parse(p.expiresAt)) {
277
+ const r = await relayCall(
278
+ fetchImpl,
279
+ `${p.relayUrl}/api/office/relay/pairings/${encodeURIComponent(p.pairingId)}`,
280
+ { headers: { Authorization: `Bearer ${p.relayToken}` } },
281
+ );
282
+ if (r.ok && r.body?.envelope) {
283
+ const { sessionPublic, sealed } = r.body.envelope;
284
+ if (typeof sessionPublic !== "string" || !B64U.test(sessionPublic))
285
+ throw new Refusal("the phone sent no session key");
286
+ const opened = openPairing({
287
+ privatePem: config.machinePrivatePem,
288
+ peerPublic: sessionPublic,
289
+ secret: p.secret,
290
+ pairingId: p.pairingId,
291
+ sealed,
292
+ });
293
+ if (!opened.ok) throw new Refusal("the pairing message did not open with this pairing");
294
+ const message = checkPairingMessage(opened.value, p.relayUrl);
295
+ writePrivate(pendingPath(env), JSON.stringify({ ...p, sessionPublic, message }) + "\n");
296
+ return {
297
+ deviceName: message.deviceName,
298
+ code: comparisonCode(config.machinePublic, sessionPublic),
299
+ machineKey: keyFingerprint(config.machinePublic),
300
+ };
301
+ }
302
+ if (!r.ok && r.status !== 404) throw new Refusal(`the relay answered ${r.status}`);
303
+ await new Promise((res) => setTimeout(res, pollMs));
304
+ }
305
+ dropPending(env);
306
+ throw new Refusal("the pairing expired before the phone answered");
307
+ }
308
+
309
+ function enrol(message, env) {
310
+ const r = spawnSync(
311
+ process.execPath,
312
+ [
313
+ join(HERE, "phone-devices.mjs"),
314
+ "add",
315
+ "--name",
316
+ message.deviceName,
317
+ "--public-key",
318
+ message.devicePublicKey,
319
+ "--scopes",
320
+ "read,answer",
321
+ ],
322
+ { env, encoding: "utf8", timeout: 30_000 },
323
+ );
324
+ if (r.status !== 0) {
325
+ throw new Refusal(`phone-devices refused the device: ${(r.stderr || "").trim()}`);
326
+ }
327
+ return JSON.parse(r.stdout);
328
+ }
329
+
330
+ /**
331
+ * Enrol the device once the user typed the code the phone shows.
332
+ *
333
+ * @returns {Promise<{id: string, name: string, scopes: string[]}>}
334
+ */
335
+ export async function confirm({ code, env = process.env, fetchImpl = fetch, now = Date.now() }) {
336
+ const p = pending(env, now);
337
+ if (!p.message || !p.sessionPublic) throw new Refusal("run office-pair wait first");
338
+ const config = readConfig(env);
339
+ const want = Buffer.from(comparisonCode(config.machinePublic, p.sessionPublic));
340
+ const got = Buffer.from(String(code ?? "").trim());
341
+ if (got.length !== want.length || !timingSafeEqual(got, want)) {
342
+ dropPending(env);
343
+ throw new Refusal("the code does not match; the pairing was dropped, start again");
344
+ }
345
+ const device = enrol(p.message, env);
346
+ const keys = directionKeys({
347
+ privatePem: config.machinePrivatePem,
348
+ peerPublic: p.sessionPublic,
349
+ pairingId: p.pairingId,
350
+ role: "machine",
351
+ });
352
+ const welcome = sealFrame(keys.send, 1, "machine-to-phone", {
353
+ deviceId: device.id,
354
+ scopes: device.scopes,
355
+ });
356
+ const r = await relayCall(
357
+ fetchImpl,
358
+ `${p.relayUrl}/api/office/relay/pairings/${encodeURIComponent(p.pairingId)}/confirm`,
359
+ {
360
+ method: "POST",
361
+ headers: { Authorization: `Bearer ${p.relayToken}`, "content-type": "application/json" },
362
+ body: JSON.stringify({ welcome }),
363
+ },
364
+ );
365
+ if (!r.ok) {
366
+ spawnSync(process.execPath, [join(HERE, "phone-devices.mjs"), "revoke", device.id], {
367
+ env,
368
+ stdio: "ignore",
369
+ timeout: 30_000,
370
+ });
371
+ dropPending(env);
372
+ throw new Refusal(
373
+ `the relay refused the confirmation (${r.status}); the device was revoked again, start over`,
374
+ );
375
+ }
376
+ writeConfig(
377
+ {
378
+ ...config,
379
+ pairingId: p.pairingId,
380
+ devices: {
381
+ [device.id]: {
382
+ id: device.id,
383
+ sessionPublic: p.sessionPublic,
384
+ passkey: { ...p.message.passkey, signCount: 0 },
385
+ recvCounter: 0,
386
+ sendCounter: 1,
387
+ },
388
+ },
389
+ },
390
+ env,
391
+ );
392
+ dropPending(env);
393
+ return { id: device.id, name: device.name, scopes: device.scopes };
394
+ }
395
+
396
+ /** Drop the pending pairing and its QR page. */
397
+ export function cancel({ env = process.env } = {}) {
398
+ const had = existsSync(pendingPath(env));
399
+ dropPending(env);
400
+ return { cancelled: had };
401
+ }
402
+
403
+ async function main(argv) {
404
+ const [cmd, ...rest] = argv;
405
+ if (!["start", "wait", "confirm", "cancel"].includes(cmd)) {
406
+ process.stderr.write(
407
+ "usage: office-pair.mjs start [--relay <url>] [--terminal] | wait | confirm <code> | cancel\n",
408
+ );
409
+ return 2;
410
+ }
411
+ if (isUnattended()) {
412
+ process.stderr.write("office-pair: an unattended run may not pair a device\n");
413
+ return 3;
414
+ }
415
+ try {
416
+ let out;
417
+ if (cmd === "start") {
418
+ const i = rest.indexOf("--relay");
419
+ out = await start({
420
+ relay: i === -1 ? undefined : rest[i + 1],
421
+ terminal: rest.includes("--terminal") ? process.stdout : null,
422
+ });
423
+ } else if (cmd === "wait") out = await wait({});
424
+ else if (cmd === "confirm") out = await confirm({ code: rest[0] });
425
+ else out = cancel();
426
+ process.stdout.write(JSON.stringify(out) + "\n");
427
+ return 0;
428
+ } catch (err) {
429
+ process.stderr.write(`office-pair: ${err.message}\n`);
430
+ return 1;
431
+ }
432
+ }
433
+
434
+ if (invokedDirectly(import.meta.url)) {
435
+ main(process.argv.slice(2)).then((code) => {
436
+ process.exitCode = code;
437
+ });
438
+ }