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