@mmerterden/multi-agent-pipeline 20.2.0 → 20.3.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 (621) hide show
  1. package/CHANGELOG.md +923 -1
  2. package/README.md +104 -81
  3. package/README.tr.md +103 -62
  4. package/docs/FIGMA_PIPELINE.md +35 -35
  5. package/docs/adr/0006-skills-core-external-split.md +1 -1
  6. package/docs/adr/0007-multi-tool-adapter-framework.md +6 -0
  7. package/docs/adr/0008-installer-modularization-and-secret-leak-defense.md +7 -0
  8. package/docs/architecture.md +50 -14
  9. package/docs/best-practices.md +1 -1
  10. package/docs/ecosystem.md +56 -32
  11. package/docs/facts.json +10 -10
  12. package/docs/features.md +97 -5
  13. package/docs/recovery-guide.md +7 -14
  14. package/docs/server-readiness.md +31 -24
  15. package/index.js +1 -1
  16. package/install/_common.mjs +3 -5
  17. package/install/_platform-filter.mjs +23 -1
  18. package/install/_unattended-profile.mjs +321 -75
  19. package/install/claude.mjs +51 -10
  20. package/install/codex.mjs +2 -0
  21. package/install/copilot.mjs +2 -0
  22. package/install/index.mjs +30 -17
  23. package/install/templates/claude-hooks.json +16 -5
  24. package/install/templates/copilot-instructions.md +1 -1
  25. package/install/templates/multi-agent-autopilot-awake.plist.template +48 -0
  26. package/install/templates/multi-agent-autopilot.plist.template +12 -5
  27. package/install/unattended-profile-legacy.json +80 -0
  28. package/manifest.json +616 -483
  29. package/package.json +8 -3
  30. package/pipeline/agents/code-reviewer.md +10 -0
  31. package/pipeline/agents/plan-critic.md +98 -0
  32. package/pipeline/agents/security-auditor.md +10 -0
  33. package/pipeline/agents/task-clarifier.md +10 -0
  34. package/pipeline/commands/multi-agent/SKILL.md +2 -2
  35. package/pipeline/commands/multi-agent/analysis/SKILL.md +6 -2
  36. package/pipeline/commands/multi-agent/analysis-jira/SKILL.md +12 -1
  37. package/pipeline/commands/multi-agent/analysis-resolve/SKILL.md +4 -0
  38. package/pipeline/commands/multi-agent/autopilot/SKILL.md +6 -2
  39. package/pipeline/commands/multi-agent/autopilot-off/SKILL.md +36 -6
  40. package/pipeline/commands/multi-agent/autopilot-on/SKILL.md +77 -12
  41. package/pipeline/commands/multi-agent/autopilot-status/SKILL.md +29 -8
  42. package/pipeline/commands/multi-agent/build-optimize/SKILL.md +4 -0
  43. package/pipeline/commands/multi-agent/channels/SKILL.md +9 -9
  44. package/pipeline/commands/multi-agent/complaint-analysis/SKILL.md +5 -1
  45. package/pipeline/commands/multi-agent/create-jira/SKILL.md +4 -0
  46. package/pipeline/commands/multi-agent/design-check/SKILL.md +16 -11
  47. package/pipeline/commands/multi-agent/diff-explain/SKILL.md +4 -0
  48. package/pipeline/commands/multi-agent/doctor/SKILL.md +4 -0
  49. package/pipeline/commands/multi-agent/feedback/SKILL.md +5 -1
  50. package/pipeline/commands/multi-agent/forget/SKILL.md +4 -0
  51. package/pipeline/commands/multi-agent/garbage-collect/SKILL.md +4 -0
  52. package/pipeline/commands/multi-agent/graph/SKILL.md +4 -0
  53. package/pipeline/commands/multi-agent/help/SKILL.md +37 -39
  54. package/pipeline/commands/multi-agent/ios-coding-standard/SKILL.md +4 -0
  55. package/pipeline/commands/multi-agent/issue/SKILL.md +7 -1
  56. package/pipeline/commands/multi-agent/jira/SKILL.md +7 -1
  57. package/pipeline/commands/multi-agent/kill/SKILL.md +9 -3
  58. package/pipeline/commands/multi-agent/language/SKILL.md +4 -0
  59. package/pipeline/commands/multi-agent/log/SKILL.md +4 -0
  60. package/pipeline/commands/multi-agent/manual-test/SKILL.md +5 -0
  61. package/pipeline/commands/multi-agent/model/SKILL.md +4 -0
  62. package/pipeline/commands/multi-agent/prune-logs/SKILL.md +4 -0
  63. package/pipeline/commands/multi-agent/prune-prompts/SKILL.md +4 -0
  64. package/pipeline/commands/multi-agent/purge/SKILL.md +4 -0
  65. package/pipeline/commands/multi-agent/refactor/SKILL.md +5 -0
  66. package/pipeline/commands/multi-agent/research/SKILL.md +49 -0
  67. package/pipeline/commands/multi-agent/resume/SKILL.md +29 -6
  68. package/pipeline/commands/multi-agent/review/SKILL.md +28 -9
  69. package/pipeline/commands/multi-agent/review-analysis/SKILL.md +5 -1
  70. package/pipeline/commands/multi-agent/review-issue/SKILL.md +4 -0
  71. package/pipeline/commands/multi-agent/review-jira/SKILL.md +4 -0
  72. package/pipeline/commands/multi-agent/route-off/SKILL.md +4 -0
  73. package/pipeline/commands/multi-agent/route-on/SKILL.md +4 -0
  74. package/pipeline/commands/multi-agent/route-status/SKILL.md +4 -0
  75. package/pipeline/commands/multi-agent/routines/SKILL.md +4 -0
  76. package/pipeline/commands/multi-agent/save/SKILL.md +6 -2
  77. package/pipeline/commands/multi-agent/scaffold/SKILL.md +47 -0
  78. package/pipeline/commands/multi-agent/scan/SKILL.md +4 -0
  79. package/pipeline/commands/multi-agent/search/SKILL.md +12 -8
  80. package/pipeline/commands/multi-agent/security-review/SKILL.md +4 -0
  81. package/pipeline/commands/multi-agent/serve/SKILL.md +62 -0
  82. package/pipeline/commands/multi-agent/setup/SKILL.md +27 -36
  83. package/pipeline/commands/multi-agent/stack/SKILL.md +4 -0
  84. package/pipeline/commands/multi-agent/status/SKILL.md +10 -9
  85. package/pipeline/commands/multi-agent/steer/SKILL.md +5 -1
  86. package/pipeline/commands/multi-agent/store-ready/SKILL.md +4 -0
  87. package/pipeline/commands/multi-agent/sync/SKILL.md +13 -13
  88. package/pipeline/commands/multi-agent/test/SKILL.md +4 -0
  89. package/pipeline/commands/multi-agent/test-accessibility/SKILL.md +4 -0
  90. package/pipeline/commands/multi-agent/test-dark-mode/SKILL.md +4 -0
  91. package/pipeline/commands/multi-agent/test-dynamic-type/SKILL.md +4 -0
  92. package/pipeline/commands/multi-agent/test-screenshots/SKILL.md +5 -1
  93. package/pipeline/commands/multi-agent/testflight-validation/SKILL.md +4 -0
  94. package/pipeline/commands/multi-agent/uninstall/SKILL.md +5 -1
  95. package/pipeline/commands/multi-agent/update/SKILL.md +4 -0
  96. package/pipeline/contract/CHANGELOG.md +74 -0
  97. package/pipeline/contract/README.md +126 -0
  98. package/pipeline/contract/build.mjs +427 -0
  99. package/pipeline/contract/fixtures/answer-result.json +11 -0
  100. package/pipeline/contract/fixtures/error-invalid-request.json +8 -0
  101. package/pipeline/contract/fixtures/error-unauthorized.json +5 -0
  102. package/pipeline/contract/fixtures/error-unsigned.json +5 -0
  103. package/pipeline/contract/fixtures/issues-empty.json +18 -0
  104. package/pipeline/contract/fixtures/launch-plan.json +31 -0
  105. package/pipeline/contract/fixtures/runs-awaiting-question.json +70 -0
  106. package/pipeline/contract/fixtures/runs-empty.json +6 -0
  107. package/pipeline/contract/fixtures/runs-failed.json +84 -0
  108. package/pipeline/contract/fixtures/runs-old-schema.json +70 -0
  109. package/pipeline/contract/fixtures/runs-pr-opened-redacted.json +101 -0
  110. package/pipeline/contract/fixtures/runs-pr-opened.json +106 -0
  111. package/pipeline/contract/fixtures/runs-running.json +84 -0
  112. package/pipeline/contract/fixtures/worktrees-empty.json +4 -0
  113. package/pipeline/contract/frozen/toolbox.json +107 -0
  114. package/pipeline/contract/manifest.json +263 -0
  115. package/pipeline/contract/types/index.d.ts +343 -0
  116. package/pipeline/lib/_jira-auth.sh +6 -2
  117. package/pipeline/lib/account-resolver.sh +1 -1
  118. package/pipeline/lib/autopilot-state.sh +19 -0
  119. package/pipeline/lib/context-link-extractor.sh +12 -5
  120. package/pipeline/lib/credential-inventory.sh +12 -5
  121. package/pipeline/lib/credential-store.sh +116 -185
  122. package/pipeline/lib/fetch-confluence.sh +44 -3
  123. package/pipeline/lib/fetch-document.sh +3 -4
  124. package/pipeline/lib/fetch-fortify.sh +1 -1
  125. package/pipeline/lib/figma-mcp-refresh.sh +2 -2
  126. package/pipeline/lib/figma-token.sh +5 -1
  127. package/pipeline/lib/issue-fetcher.sh +233 -16
  128. package/pipeline/lib/json-file-lock.mjs +172 -0
  129. package/pipeline/lib/model-dispatch.sh +21 -12
  130. package/pipeline/lib/model-rung.sh +6 -1
  131. package/pipeline/lib/multi-repo-pipeline.sh +1 -1
  132. package/pipeline/lib/outbound-gate.mjs +46 -16
  133. package/pipeline/lib/parse-complaints.sh +14 -7
  134. package/pipeline/lib/plan-todos.sh +3 -3
  135. package/pipeline/lib/post-pr-review.sh +9 -9
  136. package/pipeline/lib/pr-request-location.mjs +85 -0
  137. package/pipeline/lib/regular-file.mjs +153 -0
  138. package/pipeline/lib/repo-hygiene.sh +17 -0
  139. package/pipeline/lib/route-state.sh +5 -1
  140. package/pipeline/lib/run-paths.sh +3 -2
  141. package/pipeline/lib/stack-detect.sh +19 -1
  142. package/pipeline/lib/unattended-profile-check.mjs +178 -0
  143. package/pipeline/lib/unattended-settings-location.mjs +28 -0
  144. package/pipeline/lib/unattended.mjs +76 -0
  145. package/pipeline/lib/unattended.sh +32 -0
  146. package/pipeline/lib/untrusted.mjs +76 -0
  147. package/pipeline/lib/user-facing.mjs +82 -0
  148. package/pipeline/lib/user-facing.sh +58 -0
  149. package/pipeline/multi-agent-refs/_dev-context.md +1 -1
  150. package/pipeline/multi-agent-refs/analysis/evidence.md +4 -0
  151. package/pipeline/multi-agent-refs/analysis/locked.md +2 -2
  152. package/pipeline/multi-agent-refs/analysis/render.md +4 -3
  153. package/pipeline/multi-agent-refs/analysis/resolve.md +3 -1
  154. package/pipeline/multi-agent-refs/analysis/synthesis.md +4 -5
  155. package/pipeline/multi-agent-refs/analysis-template.md +10 -17
  156. package/pipeline/multi-agent-refs/channels/jira.md +1 -1
  157. package/pipeline/multi-agent-refs/component-dispatch.md +3 -3
  158. package/pipeline/multi-agent-refs/conventions-defaults.md +32 -32
  159. package/pipeline/multi-agent-refs/cross-cli-contract.md +10 -17
  160. package/pipeline/multi-agent-refs/features/autopilot-circuit-breaker.md +37 -9
  161. package/pipeline/multi-agent-refs/features/autopilot-operations.md +277 -0
  162. package/pipeline/multi-agent-refs/features/constitution.md +196 -0
  163. package/pipeline/multi-agent-refs/features/doctor.md +6 -3
  164. package/pipeline/multi-agent-refs/features/external-context-injection.md +6 -1
  165. package/pipeline/multi-agent-refs/features/jira-context.md +1 -1
  166. package/pipeline/multi-agent-refs/features/maturity-followup.md +43 -23
  167. package/pipeline/multi-agent-refs/features/model-fallback.md +9 -0
  168. package/pipeline/multi-agent-refs/features/phone-api.md +306 -0
  169. package/pipeline/multi-agent-refs/features/plan-critic.md +159 -0
  170. package/pipeline/multi-agent-refs/features/research.md +150 -0
  171. package/pipeline/multi-agent-refs/features/review-decision.md +185 -0
  172. package/pipeline/multi-agent-refs/features/scaffold.md +160 -0
  173. package/pipeline/multi-agent-refs/features/security-audit.md +6 -2
  174. package/pipeline/multi-agent-refs/features/skill-conformance.md +4 -1
  175. package/pipeline/multi-agent-refs/features/stack-adapters.md +116 -0
  176. package/pipeline/multi-agent-refs/features/unattended-gates.md +316 -0
  177. package/pipeline/multi-agent-refs/features/unattended-security.md +731 -0
  178. package/pipeline/multi-agent-refs/features/url-enrichment.md +2 -2
  179. package/pipeline/multi-agent-refs/features/usage-reporting.md +127 -31
  180. package/pipeline/multi-agent-refs/features/verify-by-test.md +1 -1
  181. package/pipeline/multi-agent-refs/features/visual-evidence.md +7 -7
  182. package/pipeline/multi-agent-refs/keychain.md +6 -11
  183. package/pipeline/multi-agent-refs/payload-contracts.md +2 -2
  184. package/pipeline/multi-agent-refs/phases/log-format.md +2 -3
  185. package/pipeline/multi-agent-refs/phases/modes.md +10 -12
  186. package/pipeline/multi-agent-refs/phases/operations.md +11 -5
  187. package/pipeline/multi-agent-refs/phases/phase-0-init.md +73 -81
  188. package/pipeline/multi-agent-refs/phases/phase-1-plan.md +22 -22
  189. package/pipeline/multi-agent-refs/phases/phase-2-dev.md +42 -66
  190. package/pipeline/multi-agent-refs/phases/phase-3-review.md +45 -79
  191. package/pipeline/multi-agent-refs/phases/phase-4-commit.md +28 -38
  192. package/pipeline/multi-agent-refs/phases/phase-5-report.md +27 -25
  193. package/pipeline/multi-agent-refs/phases.md +1 -1
  194. package/pipeline/multi-agent-refs/picker-contract.md +1 -1
  195. package/pipeline/multi-agent-refs/progress-contract.md +13 -16
  196. package/pipeline/multi-agent-refs/readiness-review.md +1 -1
  197. package/pipeline/multi-agent-refs/research/engine.md +91 -0
  198. package/pipeline/multi-agent-refs/rules.md +6 -4
  199. package/pipeline/multi-agent-refs/setup/repo-discovery.md +2 -2
  200. package/pipeline/multi-agent-refs/tracker-contract.md +2 -2
  201. package/pipeline/multi-agent-refs/unattended-contract.md +68 -16
  202. package/pipeline/rules/figma-pipeline.md +12 -12
  203. package/pipeline/schemas/agent-state.schema.json +480 -18
  204. package/pipeline/schemas/analysis-spec.schema.json +4 -4
  205. package/pipeline/schemas/answer-request.schema.json +24 -0
  206. package/pipeline/schemas/answer-result.schema.json +28 -0
  207. package/pipeline/schemas/autopilot-config.schema.json +111 -13
  208. package/pipeline/schemas/command-parameters.schema.json +99 -0
  209. package/pipeline/schemas/constitution.schema.json +56 -0
  210. package/pipeline/schemas/contract-error.schema.json +52 -0
  211. package/pipeline/schemas/design-check-config.schema.json +5 -1
  212. package/pipeline/schemas/issues.schema.json +61 -0
  213. package/pipeline/schemas/launch-plan.schema.json +46 -0
  214. package/pipeline/schemas/launch-request.schema.json +45 -0
  215. package/pipeline/schemas/launch.json +61 -0
  216. package/pipeline/schemas/launch.schema.json +84 -0
  217. package/pipeline/schemas/phases.json +2 -2
  218. package/pipeline/schemas/phases.schema.json +68 -0
  219. package/pipeline/schemas/phone-devices.schema.json +61 -0
  220. package/pipeline/schemas/phone-signed-request.schema.json +67 -0
  221. package/pipeline/schemas/plan-critique.schema.json +99 -0
  222. package/pipeline/schemas/plan-todos.schema.json +7 -7
  223. package/pipeline/schemas/planning-output.schema.json +5 -0
  224. package/pipeline/schemas/pr-request.schema.json +46 -0
  225. package/pipeline/schemas/prefs.schema.json +82 -7
  226. package/pipeline/schemas/research-output.schema.json +118 -0
  227. package/pipeline/schemas/review-file-exclusions.schema.json +25 -0
  228. package/pipeline/schemas/reviewer-output.schema.json +40 -4
  229. package/pipeline/schemas/run-questions.json +392 -0
  230. package/pipeline/schemas/run-questions.schema.json +118 -0
  231. package/pipeline/schemas/runs-index.schema.json +189 -0
  232. package/pipeline/schemas/scaffold-manifest.schema.json +43 -0
  233. package/pipeline/schemas/secret-patterns.schema.json +28 -0
  234. package/pipeline/schemas/stack-adapters.json +527 -0
  235. package/pipeline/schemas/stack-adapters.schema.json +184 -0
  236. package/pipeline/schemas/token-budget.json +1 -1
  237. package/pipeline/schemas/token-budget.schema.json +26 -0
  238. package/pipeline/schemas/triage-output.schema.json +64 -3
  239. package/pipeline/schemas/unattended-policy.json +139 -0
  240. package/pipeline/schemas/unattended-policy.schema.json +73 -0
  241. package/pipeline/schemas/unattended-profile.json +248 -0
  242. package/pipeline/schemas/unattended-profile.schema.json +198 -0
  243. package/pipeline/schemas/worktrees.schema.json +51 -0
  244. package/pipeline/scripts/README.md +1 -0
  245. package/pipeline/scripts/_autopilot-config.mjs +130 -0
  246. package/pipeline/scripts/_autopilot-ops.mjs +567 -0
  247. package/pipeline/scripts/_autopilot-outcomes.mjs +174 -0
  248. package/pipeline/scripts/_command-contract.mjs +384 -0
  249. package/pipeline/scripts/_cost.mjs +40 -0
  250. package/pipeline/scripts/_notices.mjs +160 -0
  251. package/pipeline/scripts/_phone-auth.mjs +485 -0
  252. package/pipeline/scripts/_pre-existing.mjs +294 -0
  253. package/pipeline/scripts/_redact.mjs +77 -0
  254. package/pipeline/scripts/_run-paths.mjs +4 -2
  255. package/pipeline/scripts/_stack-adapter.mjs +678 -0
  256. package/pipeline/scripts/_stack-routing.mjs +1 -1
  257. package/pipeline/scripts/agent-guard.py +348 -37
  258. package/pipeline/scripts/agent-guard.sh +41 -13
  259. package/pipeline/scripts/analysis-story-tree.mjs +79 -3
  260. package/pipeline/scripts/answer-question.mjs +181 -0
  261. package/pipeline/scripts/audit-log-rotate.sh +1 -4
  262. package/pipeline/scripts/audit-log.sh +4 -4
  263. package/pipeline/scripts/autopilot-arming.mjs +389 -21
  264. package/pipeline/scripts/autopilot-awake.mjs +255 -0
  265. package/pipeline/scripts/autopilot-intake.mjs +137 -36
  266. package/pipeline/scripts/autopilot-menubar.swift +156 -44
  267. package/pipeline/scripts/autopilot-publish.mjs +1625 -0
  268. package/pipeline/scripts/autopilot-runner.mjs +1678 -222
  269. package/pipeline/scripts/autopilot-status.sh +198 -33
  270. package/pipeline/scripts/build-lock.sh +120 -0
  271. package/pipeline/scripts/build-references.mjs +4 -1
  272. package/pipeline/scripts/build-stack-plugins.mjs +59 -22
  273. package/pipeline/scripts/capture-flush.sh +1 -1
  274. package/pipeline/scripts/capture-resume.sh +13 -9
  275. package/pipeline/scripts/check-derived-drift.mjs +52 -11
  276. package/pipeline/scripts/commands.mjs +88 -0
  277. package/pipeline/scripts/constitution.mjs +362 -0
  278. package/pipeline/scripts/contract-server.mjs +776 -0
  279. package/pipeline/scripts/cost-analyze.mjs +89 -39
  280. package/pipeline/scripts/diff-explain.mjs +12 -1
  281. package/pipeline/scripts/doctor.mjs +77 -28
  282. package/pipeline/scripts/evidence-gate.mjs +192 -12
  283. package/pipeline/scripts/feedback-send.mjs +4 -2
  284. package/pipeline/scripts/gate-ledger.mjs +449 -0
  285. package/pipeline/scripts/gc-abandoned.sh +132 -13
  286. package/pipeline/scripts/gen-facts.mjs +31 -15
  287. package/pipeline/scripts/gen-mode-dispatch.mjs +3 -3
  288. package/pipeline/scripts/github-ssh-setup.sh +140 -29
  289. package/pipeline/scripts/graph-mermaid.mjs +4 -1
  290. package/pipeline/scripts/issues.mjs +236 -0
  291. package/pipeline/scripts/jira-attach.sh +6 -2
  292. package/pipeline/scripts/jira-search.sh +4 -3
  293. package/pipeline/scripts/keychain-save.sh +125 -24
  294. package/pipeline/scripts/keychain.py +63 -93
  295. package/pipeline/scripts/launch-request.mjs +747 -0
  296. package/pipeline/scripts/localize-commands.mjs +4 -10
  297. package/pipeline/scripts/log-metric.sh +6 -5
  298. package/pipeline/scripts/maturity-followup.mjs +13 -4
  299. package/pipeline/scripts/memory-save.sh +25 -0
  300. package/pipeline/scripts/migrate-prefs.mjs +4 -3
  301. package/pipeline/scripts/open-questions-gate.mjs +276 -0
  302. package/pipeline/scripts/phase-tracker.sh +41 -27
  303. package/pipeline/scripts/phase0-exit-gate.mjs +22 -4
  304. package/pipeline/scripts/phone-devices.mjs +224 -0
  305. package/pipeline/scripts/plan-coverage-gate.mjs +200 -66
  306. package/pipeline/scripts/plan-critique-gate.mjs +591 -0
  307. package/pipeline/scripts/pr-request.mjs +188 -0
  308. package/pipeline/scripts/pre-commit-check.sh +115 -4
  309. package/pipeline/scripts/probe-evidence-capability.sh +44 -5
  310. package/pipeline/scripts/record-phase.mjs +71 -0
  311. package/pipeline/scripts/render-agent-log-cost.sh +17 -2
  312. package/pipeline/scripts/render-cost-summary.sh +1 -1
  313. package/pipeline/scripts/render-work-summary.sh +1 -1
  314. package/pipeline/scripts/require-supported-version.sh +4 -1
  315. package/pipeline/scripts/research-gate.mjs +704 -0
  316. package/pipeline/scripts/review-decision-gate.mjs +403 -0
  317. package/pipeline/scripts/routine-registry.mjs +5 -2
  318. package/pipeline/scripts/runs-index.mjs +135 -27
  319. package/pipeline/scripts/scaffold-gate.mjs +393 -0
  320. package/pipeline/scripts/skill-conformance.mjs +25 -8
  321. package/pipeline/scripts/skill-siblings.mjs +2 -1
  322. package/pipeline/scripts/smoke-cross-cli-behavior.sh +32 -6
  323. package/pipeline/scripts/smoke-schema-validation.sh +6 -2
  324. package/pipeline/scripts/spec-consistency-gate.mjs +469 -0
  325. package/pipeline/scripts/symbol-existence-gate.mjs +450 -0
  326. package/pipeline/scripts/test-gap-scan.mjs +40 -2
  327. package/pipeline/scripts/test-integrity-gate.mjs +20 -4
  328. package/pipeline/scripts/test-strength.mjs +484 -0
  329. package/pipeline/scripts/test-summary.mjs +651 -0
  330. package/pipeline/scripts/triage-memory.mjs +49 -9
  331. package/pipeline/scripts/unattended_policy.py +2786 -0
  332. package/pipeline/scripts/uninstall.mjs +10 -10
  333. package/pipeline/scripts/update-issue-progress.sh +1 -1
  334. package/pipeline/scripts/usage-identity.mjs +288 -0
  335. package/pipeline/scripts/usage-register.mjs +185 -63
  336. package/pipeline/scripts/usage-report.mjs +230 -66
  337. package/pipeline/scripts/validate-complaint-doc.mjs +28 -10
  338. package/pipeline/scripts/validate-planning.mjs +6 -0
  339. package/pipeline/scripts/verify-citations.mjs +151 -38
  340. package/pipeline/scripts/verify.mjs +58 -18
  341. package/pipeline/scripts/worktree-prepare.sh +126 -0
  342. package/pipeline/scripts/worktrees.mjs +124 -0
  343. package/pipeline/scripts/write-state.mjs +48 -17
  344. package/pipeline/skills/.skill-manifest.json +222 -226
  345. package/pipeline/skills/.skills-index.json +77 -88
  346. package/pipeline/skills/shared/README.md +44 -45
  347. package/pipeline/skills/shared/core/apple-archive-compliance/SKILL.md +3 -2
  348. package/pipeline/skills/shared/core/google-play-compliance/SKILL.md +3 -2
  349. package/pipeline/skills/shared/core/multi-agent/SKILL.md +10 -9
  350. package/pipeline/skills/shared/core/multi-agent-analysis/SKILL.md +6 -5
  351. package/pipeline/skills/shared/core/multi-agent-analysis-jira/SKILL.md +11 -3
  352. package/pipeline/skills/shared/core/multi-agent-analysis-resolve/SKILL.md +2 -1
  353. package/pipeline/skills/shared/core/multi-agent-autopilot/SKILL.md +4 -3
  354. package/pipeline/skills/shared/core/multi-agent-autopilot-off/SKILL.md +32 -6
  355. package/pipeline/skills/shared/core/multi-agent-autopilot-on/SKILL.md +66 -8
  356. package/pipeline/skills/shared/core/multi-agent-autopilot-status/SKILL.md +27 -9
  357. package/pipeline/skills/shared/core/multi-agent-build-optimize/SKILL.md +2 -1
  358. package/pipeline/skills/shared/core/multi-agent-channels/SKILL.md +7 -4
  359. package/pipeline/skills/shared/core/multi-agent-complaint-analysis/SKILL.md +3 -2
  360. package/pipeline/skills/shared/core/multi-agent-create-jira/SKILL.md +2 -1
  361. package/pipeline/skills/shared/core/multi-agent-design-check/SKILL.md +7 -5
  362. package/pipeline/skills/shared/core/multi-agent-diff-explain/SKILL.md +2 -1
  363. package/pipeline/skills/shared/core/multi-agent-doctor/SKILL.md +3 -2
  364. package/pipeline/skills/shared/core/multi-agent-feedback/SKILL.md +2 -1
  365. package/pipeline/skills/shared/core/multi-agent-forget/SKILL.md +2 -1
  366. package/pipeline/skills/shared/core/multi-agent-garbage-collect/SKILL.md +2 -1
  367. package/pipeline/skills/shared/core/multi-agent-graph/SKILL.md +2 -1
  368. package/pipeline/skills/shared/core/multi-agent-help/SKILL.md +2 -1
  369. package/pipeline/skills/shared/core/multi-agent-ios-coding-standard/SKILL.md +2 -1
  370. package/pipeline/skills/shared/core/multi-agent-issue/SKILL.md +3 -2
  371. package/pipeline/skills/shared/core/multi-agent-jira/SKILL.md +2 -1
  372. package/pipeline/skills/shared/core/multi-agent-kill/SKILL.md +7 -4
  373. package/pipeline/skills/shared/core/multi-agent-language/SKILL.md +2 -1
  374. package/pipeline/skills/shared/core/multi-agent-log/SKILL.md +2 -1
  375. package/pipeline/skills/shared/core/multi-agent-manual-test/SKILL.md +2 -1
  376. package/pipeline/skills/shared/core/multi-agent-model/SKILL.md +2 -1
  377. package/pipeline/skills/shared/core/multi-agent-prune-logs/SKILL.md +2 -1
  378. package/pipeline/skills/shared/core/multi-agent-prune-prompts/SKILL.md +2 -1
  379. package/pipeline/skills/shared/core/multi-agent-purge/SKILL.md +2 -1
  380. package/pipeline/skills/shared/core/multi-agent-refactor/SKILL.md +2 -1
  381. package/pipeline/skills/shared/core/multi-agent-research/SKILL.md +35 -0
  382. package/pipeline/skills/shared/core/multi-agent-resume/SKILL.md +7 -3
  383. package/pipeline/skills/shared/core/multi-agent-review/SKILL.md +7 -5
  384. package/pipeline/skills/shared/core/multi-agent-review-analysis/SKILL.md +2 -1
  385. package/pipeline/skills/shared/core/multi-agent-review-issue/SKILL.md +3 -2
  386. package/pipeline/skills/shared/core/multi-agent-review-jira/SKILL.md +2 -1
  387. package/pipeline/skills/shared/core/multi-agent-route-off/SKILL.md +2 -1
  388. package/pipeline/skills/shared/core/multi-agent-route-on/SKILL.md +2 -1
  389. package/pipeline/skills/shared/core/multi-agent-route-status/SKILL.md +2 -1
  390. package/pipeline/skills/shared/core/multi-agent-routines/SKILL.md +2 -1
  391. package/pipeline/skills/shared/core/multi-agent-save/SKILL.md +3 -2
  392. package/pipeline/skills/shared/core/multi-agent-scaffold/SKILL.md +30 -0
  393. package/pipeline/skills/shared/core/multi-agent-scan/SKILL.md +2 -1
  394. package/pipeline/skills/shared/core/multi-agent-search/SKILL.md +4 -3
  395. package/pipeline/skills/shared/core/multi-agent-security-review/SKILL.md +2 -1
  396. package/pipeline/skills/shared/core/multi-agent-serve/SKILL.md +60 -0
  397. package/pipeline/skills/shared/core/multi-agent-setup/SKILL.md +8 -8
  398. package/pipeline/skills/shared/core/multi-agent-stack/SKILL.md +2 -1
  399. package/pipeline/skills/shared/core/multi-agent-status/SKILL.md +7 -8
  400. package/pipeline/skills/shared/core/multi-agent-steer/SKILL.md +2 -1
  401. package/pipeline/skills/shared/core/multi-agent-store-ready/SKILL.md +2 -1
  402. package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +10 -10
  403. package/pipeline/skills/shared/core/multi-agent-test/SKILL.md +2 -1
  404. package/pipeline/skills/shared/core/multi-agent-test-accessibility/SKILL.md +2 -1
  405. package/pipeline/skills/shared/core/multi-agent-test-dark-mode/SKILL.md +2 -1
  406. package/pipeline/skills/shared/core/multi-agent-test-dynamic-type/SKILL.md +2 -1
  407. package/pipeline/skills/shared/core/multi-agent-test-screenshots/SKILL.md +2 -1
  408. package/pipeline/skills/shared/core/multi-agent-testflight-validation/SKILL.md +2 -1
  409. package/pipeline/skills/shared/core/multi-agent-uninstall/SKILL.md +3 -2
  410. package/pipeline/skills/shared/core/multi-agent-update/SKILL.md +2 -1
  411. package/pipeline/skills/shared/external/NOTICE-avdlee-swiftui-agent-skill.md +46 -0
  412. package/pipeline/skills/shared/external/NOTICE-dimillian-skills.md +9 -3
  413. package/pipeline/skills/shared/external/NOTICE-paul-hudson-skills.md +54 -0
  414. package/pipeline/skills/shared/external/NOTICE-swift-ios-skills.md +9 -11
  415. package/pipeline/skills/shared/external/NOTICE-vibeship-spawner-skills.md +203 -0
  416. package/pipeline/skills/shared/external/NOTICE-xcode-build-skills.md +10 -3
  417. package/pipeline/skills/shared/external/accessibility-compliance-accessibility-audit/SKILL.md +131 -25
  418. package/pipeline/skills/shared/external/agent-introspection-debugging/SKILL.md +4 -3
  419. package/pipeline/skills/shared/external/alarmkit/SKILL.md +2 -1
  420. package/pipeline/skills/shared/external/android-architecture/SKILL.md +85 -76
  421. package/pipeline/skills/shared/external/android-build-quality-gates/SKILL.md +51 -3
  422. package/pipeline/skills/shared/external/android-build-quality-gates/references/patterns.md +9 -0
  423. package/pipeline/skills/shared/external/android-datastore/SKILL.md +4 -3
  424. package/pipeline/skills/shared/external/android-design-tokens-codegen/SKILL.md +4 -3
  425. package/pipeline/skills/shared/external/android-jetpack-compose-expert/SKILL.md +106 -181
  426. package/pipeline/skills/shared/external/android-jetpack-compose-expert/references/patterns.md +147 -0
  427. package/pipeline/skills/shared/external/android-mvi-viewmodel/SKILL.md +45 -4
  428. package/pipeline/skills/shared/external/android-performance/SKILL.md +27 -2
  429. package/pipeline/skills/shared/external/android-performance/references/patterns.md +37 -37
  430. package/pipeline/skills/shared/external/api-patterns/SKILL.md +111 -67
  431. package/pipeline/skills/shared/external/api-patterns/references/contract-details.md +128 -0
  432. package/pipeline/skills/shared/external/api-security-best-practices/SKILL.md +136 -186
  433. package/pipeline/skills/shared/external/api-security-best-practices/references/abuse-controls.md +140 -0
  434. package/pipeline/skills/shared/external/api-security-best-practices/references/identity-and-access.md +207 -0
  435. package/pipeline/skills/shared/external/api-security-best-practices/references/operations.md +66 -0
  436. package/pipeline/skills/shared/external/api-security-best-practices/references/request-handling.md +175 -0
  437. package/pipeline/skills/shared/external/app-clips/SKILL.md +2 -0
  438. package/pipeline/skills/shared/external/app-intents/SKILL.md +2 -0
  439. package/pipeline/skills/shared/external/app-store-changelog/SKILL.md +4 -3
  440. package/pipeline/skills/shared/external/app-store-optimization/SKILL.md +2 -0
  441. package/pipeline/skills/shared/external/app-store-review/SKILL.md +2 -0
  442. package/pipeline/skills/shared/external/apple-on-device-ai/SKILL.md +2 -0
  443. package/pipeline/skills/shared/external/architecture/SKILL.md +106 -39
  444. package/pipeline/skills/shared/external/architecture/references/adr-and-review.md +76 -0
  445. package/pipeline/skills/shared/external/authentication/SKILL.md +2 -0
  446. package/pipeline/skills/shared/external/avkit/SKILL.md +2 -0
  447. package/pipeline/skills/shared/external/background-processing/SKILL.md +2 -1
  448. package/pipeline/skills/shared/external/backlog/SKILL.md +3 -2
  449. package/pipeline/skills/shared/external/callkit-voip/SKILL.md +2 -0
  450. package/pipeline/skills/shared/external/callkit-voip/evals/evals.json +1 -1
  451. package/pipeline/skills/shared/external/ci-cd-pipelines/SKILL.md +3 -2
  452. package/pipeline/skills/shared/external/clean-code/SKILL.md +192 -90
  453. package/pipeline/skills/shared/external/cloudkit-sync/SKILL.md +2 -1
  454. package/pipeline/skills/shared/external/cloudkit-sync/evals/evals.json +1 -1
  455. package/pipeline/skills/shared/external/compose-components/SKILL.md +4 -4
  456. package/pipeline/skills/shared/external/compose-navigation/SKILL.md +22 -22
  457. package/pipeline/skills/shared/external/compose-navigation/references/patterns.md +10 -10
  458. package/pipeline/skills/shared/external/compose-testing/SKILL.md +13 -6
  459. package/pipeline/skills/shared/external/compose-testing/references/patterns.md +59 -59
  460. package/pipeline/skills/shared/external/contacts-framework/SKILL.md +2 -0
  461. package/pipeline/skills/shared/external/context-compression/SKILL.md +118 -250
  462. package/pipeline/skills/shared/external/core-bluetooth/SKILL.md +2 -0
  463. package/pipeline/skills/shared/external/core-data/SKILL.md +2 -0
  464. package/pipeline/skills/shared/external/core-motion/SKILL.md +2 -0
  465. package/pipeline/skills/shared/external/core-nfc/SKILL.md +2 -0
  466. package/pipeline/skills/shared/external/coreml/SKILL.md +2 -1
  467. package/pipeline/skills/shared/external/council/SKILL.md +2 -1
  468. package/pipeline/skills/shared/external/cryptokit/SKILL.md +2 -0
  469. package/pipeline/skills/shared/external/css-modern/SKILL.md +3 -2
  470. package/pipeline/skills/shared/external/database-patterns/SKILL.md +3 -2
  471. package/pipeline/skills/shared/external/debugging-instruments/SKILL.md +2 -0
  472. package/pipeline/skills/shared/external/debugging-strategies/SKILL.md +130 -20
  473. package/pipeline/skills/shared/external/debugging-strategies/references/hard-cases.md +54 -0
  474. package/pipeline/skills/shared/external/device-integrity/SKILL.md +2 -0
  475. package/pipeline/skills/shared/external/docker-expert/SKILL.md +137 -381
  476. package/pipeline/skills/shared/external/docker-expert/references/patterns.md +98 -0
  477. package/pipeline/skills/shared/external/energykit/SKILL.md +2 -1
  478. package/pipeline/skills/shared/external/eventkit-calendar/SKILL.md +3 -1
  479. package/pipeline/skills/shared/external/eventkit-calendar/evals/evals.json +2 -2
  480. package/pipeline/skills/shared/external/fastapi-pro/SKILL.md +116 -185
  481. package/pipeline/skills/shared/external/fastapi-pro/references/app-structure.md +235 -0
  482. package/pipeline/skills/shared/external/fastapi-pro/references/testing-and-deployment.md +69 -0
  483. package/pipeline/skills/shared/external/firebase/SKILL.md +4 -3
  484. package/pipeline/skills/shared/external/github-actions-templates/SKILL.md +151 -293
  485. package/pipeline/skills/shared/external/github-actions-templates/references/patterns.md +96 -0
  486. package/pipeline/skills/shared/external/healthkit/SKILL.md +2 -0
  487. package/pipeline/skills/shared/external/hig-components-content/SKILL.md +69 -72
  488. package/pipeline/skills/shared/external/hig-components-content/references/content-views.md +111 -0
  489. package/pipeline/skills/shared/external/hig-components-layout/SKILL.md +77 -86
  490. package/pipeline/skills/shared/external/hig-components-layout/references/containers.md +98 -0
  491. package/pipeline/skills/shared/external/hig-components-status/SKILL.md +150 -78
  492. package/pipeline/skills/shared/external/hig-components-system/SKILL.md +76 -97
  493. package/pipeline/skills/shared/external/hig-components-system/references/surfaces.md +98 -0
  494. package/pipeline/skills/shared/external/hig-foundations/SKILL.md +48 -76
  495. package/pipeline/skills/shared/external/hig-foundations/references/foundations-detail.md +132 -0
  496. package/pipeline/skills/shared/external/hig-inputs/SKILL.md +147 -106
  497. package/pipeline/skills/shared/external/hig-patterns/SKILL.md +61 -77
  498. package/pipeline/skills/shared/external/hig-patterns/references/patterns.md +92 -0
  499. package/pipeline/skills/shared/external/hig-platforms/SKILL.md +147 -77
  500. package/pipeline/skills/shared/external/hig-technologies/SKILL.md +61 -121
  501. package/pipeline/skills/shared/external/hig-technologies/references/technologies.md +108 -0
  502. package/pipeline/skills/shared/external/homekit-matter/SKILL.md +2 -0
  503. package/pipeline/skills/shared/external/homekit-matter/evals/evals.json +1 -1
  504. package/pipeline/skills/shared/external/html-semantic/SKILL.md +3 -2
  505. package/pipeline/skills/shared/external/humanizer/SKILL.md +2 -1
  506. package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +2 -0
  507. package/pipeline/skills/shared/external/ios-coding-standard/SKILL.md +2 -1
  508. package/pipeline/skills/shared/external/ios-coding-standard/references/STANDARD.md +14 -2
  509. package/pipeline/skills/shared/external/ios-coding-standard/references/rules.yml +2 -2
  510. package/pipeline/skills/shared/external/ios-debugger-agent/SKILL.md +4 -3
  511. package/pipeline/skills/shared/external/ios-localization/SKILL.md +8 -6
  512. package/pipeline/skills/shared/external/ios-localization/evals/evals.json +2 -2
  513. package/pipeline/skills/shared/external/ios-localization/references/string-catalogs.md +11 -11
  514. package/pipeline/skills/shared/external/ios-module-structure/SKILL.md +2 -1
  515. package/pipeline/skills/shared/external/ios-networking/SKILL.md +2 -0
  516. package/pipeline/skills/shared/external/ios-simulator/SKILL.md +2 -0
  517. package/pipeline/skills/shared/external/kotlin-coroutines-expert/SKILL.md +102 -193
  518. package/pipeline/skills/shared/external/kotlin-coroutines-expert/references/patterns.md +103 -0
  519. package/pipeline/skills/shared/external/live-activities/SKILL.md +4 -2
  520. package/pipeline/skills/shared/external/live-activities/evals/evals.json +2 -2
  521. package/pipeline/skills/shared/external/localization-reuse-map/SKILL.md +7 -9
  522. package/pipeline/skills/shared/external/localization-reuse-map/reference/sources-and-recipes.md +3 -3
  523. package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-new-values.py +2 -2
  524. package/pipeline/skills/shared/external/macos-menubar-tuist-app/SKILL.md +4 -3
  525. package/pipeline/skills/shared/external/macos-spm-app-packaging/SKILL.md +5 -3
  526. package/pipeline/skills/shared/external/mapkit-location/SKILL.md +2 -0
  527. package/pipeline/skills/shared/external/mapkit-location/evals/evals.json +1 -1
  528. package/pipeline/skills/shared/external/metrickit-diagnostics/SKILL.md +2 -0
  529. package/pipeline/skills/shared/external/metrickit-diagnostics/evals/evals.json +1 -1
  530. package/pipeline/skills/shared/external/monorepo-architect/SKILL.md +149 -46
  531. package/pipeline/skills/shared/external/monorepo-architect/references/patterns.md +70 -0
  532. package/pipeline/skills/shared/external/musickit-audio/SKILL.md +2 -0
  533. package/pipeline/skills/shared/external/musickit-audio/evals/evals.json +1 -1
  534. package/pipeline/skills/shared/external/natural-language/SKILL.md +2 -0
  535. package/pipeline/skills/shared/external/nextjs-app-router/SKILL.md +3 -2
  536. package/pipeline/skills/shared/external/nodejs-backend-patterns/SKILL.md +91 -21
  537. package/pipeline/skills/shared/external/nodejs-backend-patterns/references/runtime-patterns.md +247 -0
  538. package/pipeline/skills/shared/external/nodejs-backend-patterns/references/testing-and-frameworks.md +57 -0
  539. package/pipeline/skills/shared/external/observability-engineer/SKILL.md +155 -232
  540. package/pipeline/skills/shared/external/observability-engineer/references/patterns.md +75 -0
  541. package/pipeline/skills/shared/external/passkit-wallet/SKILL.md +2 -0
  542. package/pipeline/skills/shared/external/passkit-wallet/evals/evals.json +2 -2
  543. package/pipeline/skills/shared/external/passkit-wallet/references/wallet-passes.md +18 -18
  544. package/pipeline/skills/shared/external/pdfkit/SKILL.md +2 -1
  545. package/pipeline/skills/shared/external/pencilkit-drawing/SKILL.md +2 -0
  546. package/pipeline/skills/shared/external/pencilkit-drawing/evals/evals.json +1 -1
  547. package/pipeline/skills/shared/external/permissionkit/SKILL.md +2 -0
  548. package/pipeline/skills/shared/external/photos-camera-media/SKILL.md +2 -1
  549. package/pipeline/skills/shared/external/push-notifications/SKILL.md +2 -0
  550. package/pipeline/skills/shared/external/python-patterns/SKILL.md +3 -2
  551. package/pipeline/skills/shared/external/react-best-practices/SKILL.md +3 -2
  552. package/pipeline/skills/shared/external/realitykit-ar/SKILL.md +2 -2
  553. package/pipeline/skills/shared/external/realitykit-ar/evals/evals.json +1 -1
  554. package/pipeline/skills/shared/external/rest-api-design/SKILL.md +3 -2
  555. package/pipeline/skills/shared/external/retrofit-networking/SKILL.md +7 -7
  556. package/pipeline/skills/shared/external/retrofit-networking/references/patterns.md +69 -69
  557. package/pipeline/skills/shared/external/room-database/references/patterns.md +126 -126
  558. package/pipeline/skills/shared/external/search-first/SKILL.md +2 -1
  559. package/pipeline/skills/shared/external/security-review/SKILL.md +4 -3
  560. package/pipeline/skills/shared/external/shareplay-activities/SKILL.md +2 -2
  561. package/pipeline/skills/shared/external/signal-community/SKILL.md +1 -1
  562. package/pipeline/skills/shared/external/skill-creator/SKILL.md +2 -1
  563. package/pipeline/skills/shared/external/speech-recognition/SKILL.md +2 -1
  564. package/pipeline/skills/shared/external/spm-build-analysis/SKILL.md +2 -0
  565. package/pipeline/skills/shared/external/storekit/SKILL.md +2 -0
  566. package/pipeline/skills/shared/external/swift-api-design-guidelines/SKILL.md +2 -0
  567. package/pipeline/skills/shared/external/swift-architecture/SKILL.md +2 -1
  568. package/pipeline/skills/shared/external/swift-charts/SKILL.md +2 -1
  569. package/pipeline/skills/shared/external/swift-codable/SKILL.md +2 -0
  570. package/pipeline/skills/shared/external/swift-concurrency/SKILL.md +3 -1
  571. package/pipeline/skills/shared/external/swift-concurrency-expert/SKILL.md +5 -4
  572. package/pipeline/skills/shared/external/swift-concurrency-pro/SKILL.md +2 -1
  573. package/pipeline/skills/shared/external/swift-formatstyle/SKILL.md +2 -0
  574. package/pipeline/skills/shared/external/swift-language/SKILL.md +3 -1
  575. package/pipeline/skills/shared/external/swift-security/SKILL.md +2 -1
  576. package/pipeline/skills/shared/external/swift-testing/SKILL.md +2 -0
  577. package/pipeline/skills/shared/external/swift-testing-pro/SKILL.md +2 -1
  578. package/pipeline/skills/shared/external/swift-testing-pro/references/new-features.md +10 -0
  579. package/pipeline/skills/shared/external/swiftdata/SKILL.md +2 -0
  580. package/pipeline/skills/shared/external/swiftdata-pro/SKILL.md +2 -1
  581. package/pipeline/skills/shared/external/swiftlint/SKILL.md +2 -0
  582. package/pipeline/skills/shared/external/swiftui-animation/SKILL.md +2 -0
  583. package/pipeline/skills/shared/external/swiftui-expert-skill/SKILL.md +3 -1
  584. package/pipeline/skills/shared/external/swiftui-gestures/SKILL.md +2 -0
  585. package/pipeline/skills/shared/external/swiftui-layout-components/SKILL.md +2 -0
  586. package/pipeline/skills/shared/external/swiftui-liquid-glass/SKILL.md +2 -0
  587. package/pipeline/skills/shared/external/swiftui-navigation/SKILL.md +2 -0
  588. package/pipeline/skills/shared/external/swiftui-patterns/SKILL.md +3 -1
  589. package/pipeline/skills/shared/external/swiftui-performance/SKILL.md +3 -1
  590. package/pipeline/skills/shared/external/swiftui-performance-audit/SKILL.md +5 -4
  591. package/pipeline/skills/shared/external/swiftui-pro/SKILL.md +2 -1
  592. package/pipeline/skills/shared/external/swiftui-ui-patterns/SKILL.md +5 -4
  593. package/pipeline/skills/shared/external/swiftui-uikit-interop/SKILL.md +2 -0
  594. package/pipeline/skills/shared/external/swiftui-view-refactor/SKILL.md +4 -3
  595. package/pipeline/skills/shared/external/swiftui-webkit/SKILL.md +2 -0
  596. package/pipeline/skills/shared/external/tailwind-css/SKILL.md +3 -2
  597. package/pipeline/skills/shared/external/testing-backend/SKILL.md +3 -2
  598. package/pipeline/skills/shared/external/tipkit/SKILL.md +2 -0
  599. package/pipeline/skills/shared/external/typescript-patterns/SKILL.md +3 -2
  600. package/pipeline/skills/shared/external/vision-framework/SKILL.md +2 -0
  601. package/pipeline/skills/shared/external/vue-composition/SKILL.md +3 -2
  602. package/pipeline/skills/shared/external/weatherkit/SKILL.md +2 -0
  603. package/pipeline/skills/shared/external/web-accessibility/SKILL.md +3 -2
  604. package/pipeline/skills/shared/external/web-performance/SKILL.md +3 -2
  605. package/pipeline/skills/shared/external/web-testing/SKILL.md +3 -2
  606. package/pipeline/skills/shared/external/widgetkit/SKILL.md +2 -0
  607. package/pipeline/skills/shared/external/widgetkit/references/widgetkit-advanced.md +1 -1
  608. package/pipeline/skills/shared/external/xcode-build-benchmark/SKILL.md +2 -0
  609. package/pipeline/skills/shared/external/xcode-build-fixer/SKILL.md +2 -0
  610. package/pipeline/skills/shared/external/xcode-build-orchestrator/SKILL.md +2 -0
  611. package/pipeline/skills/shared/external/xcode-compilation-analyzer/SKILL.md +2 -0
  612. package/pipeline/skills/shared/external/xcode-project-analyzer/SKILL.md +2 -0
  613. package/pipeline/skills/skills-index.md +40 -41
  614. package/docs/token-budget-history.md +0 -24
  615. package/pipeline/skills/shared/external/agentflow/SKILL.md +0 -199
  616. package/pipeline/skills/shared/external/android-ui-verification/SKILL.md +0 -66
  617. package/pipeline/skills/shared/external/api-security-best-practices/references/auth.md +0 -299
  618. package/pipeline/skills/shared/external/api-security-best-practices/references/input-validation.md +0 -255
  619. package/pipeline/skills/shared/external/api-security-best-practices/references/rate-limiting.md +0 -167
  620. package/pipeline/skills/shared/external/closed-loop-delivery/SKILL.md +0 -116
  621. package/pipeline/skills/shared/external/ios-developer/SKILL.md +0 -216
@@ -27,9 +27,20 @@
27
27
  # ma_ap_is_on # exit 0 when configured, 1 otherwise. NO side effects
28
28
  # ma_ap_write <file> <- # atomic write from stdin, 0600
29
29
  # ma_ap_asset <rel> # resolve a script/lib/template across the 3 host roots
30
+ # ma_ap_command <sub> # the subcommand, spelled the way this host spells it
30
31
 
31
32
  set -uo pipefail
32
33
 
34
+ # The spelling of a command, and the language a sentence renders in, are one
35
+ # table for the whole pipeline. Sourcing it here is what keeps this file from
36
+ # carrying a second copy of either.
37
+ # shellcheck source=pipeline/lib/user-facing.sh
38
+ if [ -f "$(dirname "${BASH_SOURCE[0]}")/user-facing.sh" ]; then
39
+ . "$(dirname "${BASH_SOURCE[0]}")/user-facing.sh"
40
+ elif [ -f "$HOME/.claude/lib/user-facing.sh" ]; then
41
+ . "$HOME/.claude/lib/user-facing.sh"
42
+ fi
43
+
33
44
  MA_AP_ROOT="${MA_AUTOPILOT_ROOT:-$HOME/.claude/autopilot}"
34
45
 
35
46
  ma_ap_root() { printf '%s\n' "$MA_AP_ROOT"; }
@@ -67,6 +78,14 @@ ma_ap_asset() { # $1 = path relative to a host root, e.g. scripts/autopilot-runn
67
78
  return 1
68
79
  }
69
80
 
81
+ # The three CLIs spell the same command three ways, and the tree this file was
82
+ # sourced from is the one in front of the user. A status line that names a
83
+ # command names the one this machine can actually type. The table itself is
84
+ # `ma_command` in user-facing.sh - one place, so a fourth host is one edit.
85
+ ma_ap_command() { # $1 = subcommand, e.g. autopilot-off
86
+ ma_command "$1" "$MA_AP_HOST_ROOT"
87
+ }
88
+
70
89
  MA_AP_LABEL="${MA_AUTOPILOT_LABEL:-com.multi-agent.autopilot}"
71
90
  MA_AP_PLIST="${MA_AUTOPILOT_PLIST:-$HOME/Library/LaunchAgents/$MA_AP_LABEL.plist}"
72
91
 
@@ -34,7 +34,7 @@
34
34
  # [
35
35
  # { "type": "confluence", "url": "...", "metadata": { "host": "...", "pageId": "...|null", "spaceKey": "...|null" } },
36
36
  # { "type": "swagger", "url": "...", "metadata": { "format": "json|yaml|unknown" } },
37
- # { "type": "crashlytics","url": "...", "metadata": { "projectId": "...", "platform": "ios|android", "issueId": "...", "sessionId": "...|null" } },
37
+ # { "type": "crashlytics","url": "...", "metadata": { "projectId": "...", "platform": "ios|android", "bundle": "...", "issueId": "...", "sessionId": "...|null" } },
38
38
  # { "type": "fortify", "url": "...|null", "metadata": { "host": "...|null", "versionId": "...|null", "instanceId": "...|null", "source": "url|label" } },
39
39
  # { "type": "document", "url": "...|null", "metadata": { "path": "...", "format": "docx|pdf|md|txt", "source": "path|url" } },
40
40
  # { "type": "graylog", "url": null, "metadata": { "idType": "trx|conversation", "id": "...", "label": "..." } },
@@ -71,6 +71,13 @@ for m in URL_RE.finditer(text):
71
71
  RAW_URLS.append(u)
72
72
 
73
73
 
74
+ def on_domain(netloc: str, *domains: str) -> bool:
75
+ """True when the URL's host is one of `domains` or a subdomain of one.
76
+ A bare suffix test would also accept look-alikes such as evil-figma.com."""
77
+ host = netloc.rsplit("@", 1)[-1].split(":", 1)[0]
78
+ return any(host == d or host.endswith("." + d) for d in domains)
79
+
80
+
74
81
  def classify(url: str):
75
82
  """Return (type, metadata) when the URL matches a known channel; else None."""
76
83
  parsed = up.urlparse(url)
@@ -80,7 +87,7 @@ def classify(url: str):
80
87
 
81
88
  # --- Figma --------------------------------------------------------------
82
89
  # figma.com/{design|make|board|slides|file}/<fileKey>/...
83
- if host.endswith("figma.com"):
90
+ if on_domain(host, "figma.com"):
84
91
  parts = [p for p in path.split("/") if p]
85
92
  kind = parts[0] if parts else "design"
86
93
  # Normalise legacy /file/ to /design/
@@ -185,7 +192,7 @@ def classify(url: str):
185
192
  # advisory context - extractor flags them so the orchestrator can decide
186
193
  # whether to fetch (Block B work).
187
194
  if (
188
- host.endswith(("notion.so", "notion.site"))
195
+ on_domain(host, "notion.so", "notion.site")
189
196
  or host == "docs.google.com"
190
197
  or host == "drive.google.com"
191
198
  or host == "gist.github.com"
@@ -221,14 +228,14 @@ for url in RAW_URLS:
221
228
  # alternation so "trxid" is not shadowed by "trx". The id is alphanumeric plus
222
229
  # ._- and long enough (>= 6 chars) to avoid catching stray words.
223
230
  GRAYLOG_RE = re.compile(
224
- r"(?P<label>"
231
+ r"\b(?P<label>"
225
232
  r"x[\s_-]*conversation[\s_-]*id"
226
233
  r"|conversation[\s_-]*id"
227
234
  r"|conv[\s_-]*id"
228
235
  r"|transaction[\s_-]*id"
229
236
  r"|trx[\s_-]*id"
230
237
  r"|trx"
231
- r")"
238
+ r")(?![A-Za-z0-9])"
232
239
  r"\s*[:=#]?\s*"
233
240
  r"[\"']?(?P<id>[A-Za-z0-9][A-Za-z0-9._-]{5,})",
234
241
  re.IGNORECASE,
@@ -53,6 +53,10 @@ set -uo pipefail
53
53
 
54
54
  PREFS="${MULTI_AGENT_PREFS:-$HOME/.claude/multi-agent-preferences.json}"
55
55
 
56
+ _MA_CI_HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
57
+ # shellcheck source=/dev/null
58
+ if [ -f "$_MA_CI_HERE/user-facing.sh" ]; then . "$_MA_CI_HERE/user-facing.sh"; else . "$HOME/.claude/lib/user-facing.sh"; fi
59
+
56
60
  STORE=""
57
61
  for c in "$HOME/.claude/lib/credential-store.sh" "$HOME/.copilot/lib/credential-store.sh" \
58
62
  "$HOME/.codex/lib/credential-store.sh" "$(dirname "$0")/credential-store.sh"; do
@@ -354,7 +358,7 @@ capability_of() {
354
358
  fortify) echo "pull a static-analysis finding and its remediation guidance" ;;
355
359
  graylog) echo "pull request logs by transaction or conversation id (advisory)" ;;
356
360
  graylog_test) echo "pull the same logs from the test environment (falls back to the graylog token when unset)" ;;
357
- usage_ingest) echo "report pipeline usage counters and send /multi-agent:feedback" ;;
361
+ usage_ingest) echo "report pipeline usage counters and send $(ma_command feedback)" ;;
358
362
  figma|figma_mcp) echo "fetch design context, screenshots and Code Connect mappings" ;;
359
363
  jenkins) echo "read build results" ;;
360
364
  npm) echo "publish to the npm registry" ;;
@@ -408,7 +412,7 @@ if [ -n "$QUERY" ]; then
408
412
  fi
409
413
  exit 0 ;;
410
414
  2) echo "$QUERY: no credential helper on this host - run the pipeline installer (credential-store.sh missing)" >&2; exit 2 ;;
411
- *) echo "$QUERY: NOT AVAILABLE - onboard it via /multi-agent:setup before relying on it" >&2; exit 1 ;;
415
+ *) echo "$QUERY: NOT AVAILABLE - onboard it via $(ma_command setup) before relying on it" >&2; exit 1 ;;
412
416
  esac
413
417
  fi
414
418
 
@@ -417,7 +421,7 @@ fi
417
421
  # tokens that are sitting in the store.
418
422
  if [ -z "$STORE" ]; then
419
423
  if [ "$MODE" = "json" ]; then
420
- echo '{"status":"no-backend","reason":"credential-store.sh not found on this host","credentials":[]}'
424
+ echo '{"status":"no-backend","probed":false,"reason":"credential-store.sh not found on this host","credentials":[]}'
421
425
  else
422
426
  echo "no credential helper on this host - run the pipeline installer (credential-store.sh missing)" >&2
423
427
  fi
@@ -443,10 +447,13 @@ while IFS=$'\t' read -r key mapped; do
443
447
  done < <(mapping_keys)
444
448
 
445
449
  if [ -z "$ROWS" ]; then
450
+ # status, probed and credentials are in every --json envelope, the short ones
451
+ # included: a decoder that requires them (pipeline/contract/frozen/toolbox.json)
452
+ # would otherwise fail on exactly the machine that has nothing mapped yet.
446
453
  if [ "$MODE" = "json" ]; then
447
- echo '{"status":"empty","reason":"no keychainMapping in preferences","credentials":[]}'
454
+ echo '{"status":"empty","probed":false,"reason":"no keychainMapping in preferences","credentials":[]}'
448
455
  else
449
- echo "no keychainMapping found in $PREFS - run /multi-agent:setup" >&2
456
+ echo "no keychainMapping found in $PREFS - run $(ma_command setup)" >&2
450
457
  fi
451
458
  exit 0
452
459
  fi
@@ -1,9 +1,9 @@
1
1
  #!/bin/bash
2
2
  #
3
3
  # credential-store.sh
4
- # Cross-platform secret storage wrapper. Used by every script that previously
5
- # called `security find-generic-password` directly so tokens can live in the
6
- # native credential store on macOS, Windows, and Linux.
4
+ # Secret storage wrapper over the macOS Keychain. Every script reads and writes
5
+ # tokens through here rather than calling `security` itself, so key mapping,
6
+ # argv hygiene and the audit trail live in one place.
7
7
  #
8
8
  # Subcommands:
9
9
  # get <key> Read secret value to stdout (empty + exit 1 if missing)
@@ -12,40 +12,51 @@
12
12
  # keeps the secret off this script's argv (visible to
13
13
  # ps). A literal "-" value cannot be stored this way.
14
14
  # delete <key> Remove secret
15
+ # probe <key> Is the secret readable right now, without a prompt?
16
+ # Prints one word - readable | missing | locked - and
17
+ # never the value: the backend's stdout goes to
18
+ # /dev/null and only its exit status and error text
19
+ # are read. Exit 0 readable, 1 missing, 5 locked.
15
20
  # list List all keys (one per line)
16
- # platform Print detected platform: macos | windows | linux | unknown
21
+ # platform Print detected platform: macos | unknown
17
22
  # doctor Check backend availability, print remediation if missing
18
23
  #
19
- # Backends:
20
- # macOS -> Keychain via `security`
21
- # Windows -> Credential Manager via PowerShell `CredentialManager` module
22
- # (Install-Module CredentialManager -Scope CurrentUser)
23
- # Linux -> libsecret via `secret-tool`
24
+ # Backend: the macOS Keychain via `security`. The pipeline is macOS only
25
+ # (ADR-0012); on any other host every subcommand except `platform` exits 2.
24
26
  #
25
- # Returns 0 on success, 1 on missing/empty value, 2 on backend missing,
26
- # 3 on usage error.
27
+ # Returns 0 on success, 1 on missing/empty value, 2 on backend missing or a
28
+ # non-macOS host, 3 on usage error, 5 when `probe` finds the store locked.
27
29
 
28
30
  set -euo pipefail
29
31
 
30
32
  detect_platform() {
31
33
  case "$(uname -s 2>/dev/null)" in
32
34
  Darwin) echo "macos" ;;
33
- Linux) echo "linux" ;;
34
- MINGW*|MSYS*|CYGWIN*) echo "windows" ;;
35
- *) [ -n "${WINDIR:-}${OS:-}" ] && echo "windows" || echo "unknown" ;;
35
+ *) echo "unknown" ;;
36
36
  esac
37
37
  }
38
38
 
39
- PLATFORM=$(detect_platform)
39
+ PLATFORM="${CREDENTIAL_STORE_PLATFORM:-$(detect_platform)}"
40
40
  CMD="${1:-}"
41
41
  shift || true
42
42
 
43
+ if [ "$PLATFORM" != "macos" ] && [ "$CMD" != "platform" ]; then
44
+ echo "ERR: macOS only, see ADR-0012 (detected: $PLATFORM)" >&2
45
+ exit 2
46
+ fi
47
+
43
48
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)"
49
+
50
+ # CREDENTIAL_STORE_KEYCHAIN scopes every backend call to one keychain file
51
+ # instead of the user's search list. Tests point it at a throwaway keychain so
52
+ # they never write to the login keychain. keychain.py reads the same variable.
53
+ KEYCHAIN_FILE=()
54
+ if [ -n "${CREDENTIAL_STORE_KEYCHAIN:-}" ]; then KEYCHAIN_FILE=("$CREDENTIAL_STORE_KEYCHAIN"); fi
44
55
  KEYCHAIN_PY="$SCRIPT_DIR/../scripts/keychain.py"
45
56
 
46
57
  # --- Python delegate --------------------------------------------------------
47
- # On macOS / Linux, prefer the Python helper for deterministic behaviour:
48
- # - It writes BOTH -l (label) and -s (service) attributes on macOS, so items
58
+ # Prefer the Python helper for deterministic behaviour:
59
+ # - It writes BOTH -l (label) and -s (service) attributes, so items
49
60
  # are findable by either convention (personal tokens use -l, this script
50
61
  # historically used -s).
51
62
  # - It returns clean exit codes (0 ok / 1 missing / 2 backend / 4 error).
@@ -54,39 +65,12 @@ delegate_to_python() {
54
65
  [ "${KEYCHAIN_DELEGATE:-1}" != "0" ] || return 1
55
66
  command -v python3 >/dev/null 2>&1 || return 1
56
67
  [ -f "$KEYCHAIN_PY" ] || return 1
57
- case "$PLATFORM" in
58
- macos|linux) return 0 ;;
59
- *) return 1 ;;
60
- esac
61
- }
62
-
63
- # --- Helpers ----------------------------------------------------------------
64
- ps_run() {
65
- # Execute a PowerShell command, suppressing profile load. Reads stdin if any.
66
- # Windows PowerShell (powershell.exe) is preferred over pwsh: the
67
- # CredentialManager binary module is built for .NET Framework and users
68
- # install it via `Install-Module CredentialManager` in Windows PowerShell,
69
- # so its module path is only guaranteed visible there.
70
- if command -v powershell.exe >/dev/null 2>&1; then
71
- powershell.exe -NoProfile -NonInteractive -Command "$1"
72
- elif command -v pwsh >/dev/null 2>&1; then
73
- pwsh -NoProfile -NonInteractive -Command "$1"
74
- else
75
- return 127
76
- fi
77
- }
78
-
79
- require_cmd() {
80
- local cmd="$1" hint="$2"
81
- if ! command -v "$cmd" >/dev/null 2>&1; then
82
- echo "ERR: $cmd not found. $hint" >&2
83
- exit 2
84
- fi
68
+ [ "$PLATFORM" = "macos" ]
85
69
  }
86
70
 
87
71
  # --- Logical key -> backend key --------------------------------------------
88
72
  # Callers pass a LOGICAL key ("github", "jira", "figma_pat"). The actual
89
- # Keychain / libsecret / Credential Manager entry is named by
73
+ # Keychain entry is named by
90
74
  # prefs.global.keychainMapping, so a lookup that uses the logical key verbatim
91
75
  # finds nothing whenever the two differ - silently, because a missing entry and
92
76
  # a missing mapping look identical from here. Resolve the mapping first and fall
@@ -94,13 +78,12 @@ require_cmd() {
94
78
  # entries whose name already equals the logical key).
95
79
  PREFS_FILE="${MULTI_AGENT_PREFS:-$HOME/.claude/multi-agent-preferences.json}"
96
80
 
97
- # Reader order is python3 then node, and both are here on purpose. python3 is present
98
- # on macOS and every mainstream Linux; node is guaranteed wherever this pipeline is
99
- # installed at all, because the installer IS a node program. Windows commonly has node
100
- # and no python3, and with a python3-only reader the mapping was skipped there in
101
- # silence: the lookup fell back to the LOGICAL key, searched Credential Manager for a
102
- # target that does not exist, and reported the token as missing while it sat under its
103
- # mapped name. A missing interpreter must not look like a missing token.
81
+ # Reader order is python3 then node, and both are here on purpose. python3 is not
82
+ # guaranteed on a mac (it arrives with the Command Line Tools or Homebrew); node is
83
+ # guaranteed wherever this pipeline is installed at all, because the installer IS a
84
+ # node program. With a python3-only reader a host without python3 would skip the
85
+ # mapping in silence, look up the LOGICAL key, and report a token as missing while it
86
+ # sits under its mapped name. A missing interpreter must not look like a missing token.
104
87
  resolve_key() {
105
88
  local logical="$1" mapped=""
106
89
  if [ -f "$PREFS_FILE" ]; then
@@ -171,26 +154,17 @@ do_get() {
171
154
  return 1
172
155
  fi
173
156
  local val=""
174
- case "$PLATFORM" in
175
- macos)
176
- val=$(security find-generic-password -s "$key" -w 2>/dev/null || true)
177
- ;;
178
- linux)
179
- require_cmd secret-tool "Install: sudo apt install libsecret-tools (Debian/Ubuntu) or sudo dnf install libsecret (Fedora)."
180
- val=$(secret-tool lookup service "$key" 2>/dev/null || true)
181
- ;;
182
- windows)
183
- # Escape single quotes for PowerShell single-quoted strings ('' = literal ').
184
- local key_esc="${key//\'/\'\'}"
185
- val=$(ps_run "
186
- \$ErrorActionPreference='SilentlyContinue'
187
- \$c = Get-StoredCredential -Target '$key_esc'
188
- if (\$c) { \$c.GetNetworkCredential().Password }
189
- " 2>/dev/null | tr -d '\r' || true)
190
- ;;
191
- *)
192
- echo "ERR: unsupported platform" >&2; exit 2 ;;
193
- esac
157
+ # `-w` prints a value it considers non-printable (a newline included) as
158
+ # bare hex with no marker. `-g` prints `password: 0x<HEX>` in that case,
159
+ # and the marker is what makes the decoding unambiguous.
160
+ local attrs hex
161
+ attrs=$(security find-generic-password -s "$key" -g ${KEYCHAIN_FILE[@]+"${KEYCHAIN_FILE[@]}"} 2>&1 >/dev/null || true)
162
+ hex=$(printf '%s\n' "$attrs" | sed -n 's/^password: 0x\([0-9A-Fa-f]*\).*/\1/p' | head -n 1)
163
+ if [ -n "$hex" ]; then
164
+ val=$(printf '%s' "$hex" | xxd -r -p; printf x); val=${val%x}
165
+ else
166
+ val=$(security find-generic-password -s "$key" -w ${KEYCHAIN_FILE[@]+"${KEYCHAIN_FILE[@]}"} 2>/dev/null || true)
167
+ fi
194
168
  if [ -z "$val" ]; then
195
169
  audit_lookup "$logical" false
196
170
  return 1
@@ -208,44 +182,26 @@ do_set() {
208
182
  if [ "$val" = "-" ]; then
209
183
  val=$(cat)
210
184
  fi
211
- # macOS writes go through `security -i` below: the secret travels on stdin
212
- # and never lands on any argv, which is the property the delegate cannot
213
- # promise from here.
214
- if [ "$PLATFORM" != "macos" ] && delegate_to_python; then
185
+ # The delegate receives the secret on stdin and hands it to `security -i` on
186
+ # stdin as well, so no argv ever carries it, and it writes both the -l and -s
187
+ # attributes that lookups by either convention expect.
188
+ if delegate_to_python; then
215
189
  printf '%s' "$val" | python3 "$KEYCHAIN_PY" set "$key" -
216
190
  return $?
217
191
  fi
218
- case "$PLATFORM" in
219
- macos)
220
- # `security -i` reads the add command from stdin, so the secret never
221
- # lands on the `security` argv (visible to ps). printf is a bash
222
- # builtin, so no argv exposure there either. Double quotes/backslashes
223
- # are escaped for security's interactive tokenizer.
224
- local key_sec val_sec
225
- key_sec=${key//\\/\\\\}; key_sec=${key_sec//\"/\\\"}
226
- val_sec=${val//\\/\\\\}; val_sec=${val_sec//\"/\\\"}
227
- printf 'add-generic-password -U -s "%s" -a "%s" -w "%s"\n' \
228
- "$key_sec" "${USER:-claude}" "$val_sec" | security -i >/dev/null 2>&1
229
- ;;
230
- linux)
231
- require_cmd secret-tool "Install libsecret-tools (see doctor)."
232
- printf '%s' "$val" | secret-tool store --label="$key" service "$key" >/dev/null
233
- ;;
234
- windows)
235
- # Escape single quotes for PowerShell single-quoted strings ('' = literal ').
236
- local key_esc="${key//\'/\'\'}"
237
- # The secret is piped via stdin ([Console]::In) so it never appears on
238
- # the PowerShell argv (visible to process listings).
239
- printf '%s' "$val" | ps_run "
240
- \$ErrorActionPreference='Stop'
241
- \$raw = [Console]::In.ReadToEnd()
242
- \$pwd = ConvertTo-SecureString \$raw -AsPlainText -Force
243
- New-StoredCredential -Target '$key_esc' -UserName '${USER:-${USERNAME:-claude}}' -SecurePassword \$pwd -Persist LocalMachine | Out-Null
244
- " >/dev/null
245
- ;;
246
- *)
247
- echo "ERR: unsupported platform" >&2; exit 2 ;;
248
- esac
192
+ # `security -i` reads the add command from stdin, so the secret never
193
+ # lands on the `security` argv (visible to ps). printf is a bash
194
+ # builtin, so no argv exposure there either. The value goes in as
195
+ # `-X <hex>`: the interactive tokenizer reads one command per line, so a
196
+ # newline inside a quoted `-w` value would end the command early.
197
+ local key_sec val_hex target=""
198
+ key_sec=${key//\\/\\\\}; key_sec=${key_sec//\"/\\\"}
199
+ val_hex=$(printf '%s' "$val" | od -An -v -tx1 | tr -d ' \n')
200
+ if [ -n "${CREDENTIAL_STORE_KEYCHAIN:-}" ]; then
201
+ target=${CREDENTIAL_STORE_KEYCHAIN//\\/\\\\}; target=" \"${target//\"/\\\"}\""
202
+ fi
203
+ printf 'add-generic-password -U -a "%s" -l "%s" -s "%s" -X %s%s\n' \
204
+ "${USER:-claude}" "$key_sec" "$key_sec" "$val_hex" "$target" | security -i >/dev/null 2>&1
249
205
  }
250
206
 
251
207
  do_delete() {
@@ -256,97 +212,72 @@ do_delete() {
256
212
  python3 "$KEYCHAIN_PY" delete "$key" >/dev/null 2>&1 || true
257
213
  return 0
258
214
  fi
259
- case "$PLATFORM" in
260
- macos) security delete-generic-password -s "$key" >/dev/null 2>&1 || true ;;
261
- linux) secret-tool clear service "$key" >/dev/null 2>&1 || true ;;
262
- windows) local key_esc="${key//\'/\'\'}"; ps_run "Remove-StoredCredential -Target '$key_esc' -ErrorAction SilentlyContinue" >/dev/null 2>&1 || true ;;
263
- esac
215
+ security delete-generic-password -s "$key" ${KEYCHAIN_FILE[@]+"${KEYCHAIN_FILE[@]}"} >/dev/null 2>&1 || true
216
+ }
217
+
218
+ # Readable without a prompt, answered without the value ever leaving the backend.
219
+ #
220
+ # The data is really read - an attribute-only lookup would say "present" for an
221
+ # item whose access control still asks before handing the value over, which is
222
+ # exactly the item a background tick cannot use. `-w` prints the value on
223
+ # stdout, and stdout goes to /dev/null; stderr carries only the backend's error
224
+ # text, and that is what separates a locked keychain (errSecInteractionNotAllowed,
225
+ # exit 36) from a missing item (errSecItemNotFound, exit 44). Both conventions are
226
+ # tried, label then service, as keychain.py reads them.
227
+ do_probe() {
228
+ local key="${1:-}"
229
+ [ -z "$key" ] && { echo "usage: $0 probe <key>" >&2; exit 3; }
230
+ key=$(resolve_key "$key")
231
+ local locked=0 rc err
232
+ local sec="${CREDENTIAL_STORE_SECURITY_BIN:-security}" attr
233
+ for attr in -l -s; do
234
+ rc=0
235
+ err=$("$sec" find-generic-password "$attr" "$key" -w ${KEYCHAIN_FILE[@]+"${KEYCHAIN_FILE[@]}"} 2>&1 >/dev/null) || rc=$?
236
+ if [ "$rc" -eq 0 ]; then echo "readable"; return 0; fi
237
+ case "$rc:$err" in
238
+ 36:* | *"nteraction is not allowed"*) locked=1 ;;
239
+ esac
240
+ done
241
+ if [ "$locked" -eq 1 ]; then echo "locked"; return 5; fi
242
+ echo "missing"
243
+ return 1
264
244
  }
265
245
 
266
246
  do_list() {
267
- case "$PLATFORM" in
268
- macos)
269
- # Read `svce` - the SERVICE attribute, which is what `set` writes with -s and
270
- # `get` looks up with -s. This used to read `0x00000007`, which is the LABEL:
271
- # it happens to match for items written by keychain.py (which stamps both -l and
272
- # -s), but it is the wrong key in principle and diverges on any item whose label
273
- # was set independently, listing a name `get` cannot resolve.
274
- #
275
- # `dump-keychain` prints the first few attributes under numeric tags and the rest
276
- # under named ones, and `svce` is in the named group - so the tag to match is
277
- # `"svce"`, not `0x00000008`.
278
- #
279
- # Without `-d` this reads attributes only and does not prompt for access; only
280
- # the data-dumping form does.
281
- #
282
- # A trailing `\000` appears when security prints the value in its hex+C-string
283
- # form; it is not part of the service name.
284
- security dump-keychain 2>/dev/null \
285
- | awk -F'"' '/"svce"<blob>=/ && NF >= 5 { v = $4; sub(/\\000$/, "", v); if (v != "") print v }' \
286
- | sort -u
287
- ;;
288
- linux)
289
- secret-tool search --all 2>/dev/null \
290
- | awk -F'= ' '/^attribute\.service/{print $2}' \
291
- | sort -u
292
- ;;
293
- windows)
294
- ps_run "Get-StoredCredential | ForEach-Object { \$_.TargetName }" 2>/dev/null | tr -d '\r'
295
- ;;
296
- esac
247
+ # Read `svce` - the SERVICE attribute, which is what `set` writes with -s and
248
+ # `get` looks up with -s. This used to read `0x00000007`, which is the LABEL:
249
+ # it happens to match for items written by keychain.py (which stamps both -l and
250
+ # -s), but it is the wrong key in principle and diverges on any item whose label
251
+ # was set independently, listing a name `get` cannot resolve.
252
+ #
253
+ # `dump-keychain` prints the first few attributes under numeric tags and the rest
254
+ # under named ones, and `svce` is in the named group - so the tag to match is
255
+ # `"svce"`, not `0x00000008`.
256
+ #
257
+ # Without `-d` this reads attributes only and does not prompt for access; only
258
+ # the data-dumping form does.
259
+ #
260
+ # A trailing `\000` appears when security prints the value in its hex+C-string
261
+ # form; it is not part of the service name.
262
+ security dump-keychain ${KEYCHAIN_FILE[@]+"${KEYCHAIN_FILE[@]}"} 2>/dev/null \
263
+ | awk -F'"' '/"svce"<blob>=/ && NF >= 5 { v = $4; sub(/\\000$/, "", v); if (v != "") print v }' \
264
+ | sort -u
297
265
  }
298
266
 
299
267
  do_doctor() {
300
268
  echo "Platform: $PLATFORM"
301
- case "$PLATFORM" in
302
- macos)
303
- command -v security >/dev/null 2>&1 \
304
- && echo "Backend: security ✓ (built-in)" \
305
- || echo "Backend: security ✗ MISSING (impossible on macOS)"
306
- ;;
307
- linux)
308
- if command -v secret-tool >/dev/null 2>&1; then
309
- echo "Backend: secret-tool ✓"
310
- else
311
- echo "Backend: secret-tool ✗ MISSING"
312
- echo "Install: sudo apt install libsecret-tools # Debian/Ubuntu"
313
- echo " sudo dnf install libsecret # Fedora/RHEL"
314
- fi
315
- ;;
316
- windows)
317
- if command -v pwsh >/dev/null 2>&1 || command -v powershell.exe >/dev/null 2>&1; then
318
- echo "Backend: PowerShell ✓"
319
- local has_mod
320
- has_mod=$(ps_run "if (Get-Module -ListAvailable -Name CredentialManager) {'yes'} else {'no'}" 2>/dev/null | tr -d '\r' || echo "no")
321
- if [ "$has_mod" = "yes" ]; then
322
- echo "Module: CredentialManager ✓"
323
- else
324
- echo "Module: CredentialManager ✗ MISSING"
325
- echo "Install: Install-Module CredentialManager -Scope CurrentUser -Force"
326
- fi
327
- else
328
- echo "Backend: PowerShell ✗ MISSING"
329
- fi
330
- ;;
331
- *)
332
- # This used to advertise an env-var fallback. There isn't one here: `get` on an
333
- # unrecognised platform exits 2. Individual callers have their own env escape
334
- # hatches (figma-token.sh honours $FIGMA_PAT, for instance), but this helper
335
- # does not, and claiming otherwise sent people looking for a mechanism that
336
- # does not exist.
337
- echo "Backend: none - unrecognised platform, \`get\` exits 2"
338
- echo "Workaround: set the credential in the caller's own env var where one"
339
- echo " exists (e.g. FIGMA_PAT), or run on macOS / Linux / Windows"
340
- ;;
341
- esac
269
+ command -v security >/dev/null 2>&1 \
270
+ && echo "Backend: security ✓ (built-in)" \
271
+ || echo "Backend: security ✗ MISSING (impossible on macOS)"
342
272
  }
343
273
 
344
274
  case "$CMD" in
345
275
  get) do_get "$@" ;;
346
276
  set) do_set "$@" ;;
347
277
  delete) do_delete "$@" ;;
278
+ probe) do_probe "$@" ;;
348
279
  list) do_list ;;
349
280
  platform) echo "$PLATFORM" ;;
350
281
  doctor) do_doctor ;;
351
- *) echo "usage: $0 {get|set|delete|list|platform|doctor} [args]" >&2; exit 3 ;;
282
+ *) echo "usage: $0 {get|set|delete|probe|list|platform|doctor} [args]" >&2; exit 3 ;;
352
283
  esac
@@ -16,6 +16,8 @@
16
16
  # CONFLUENCE_AUTH_TOKEN_KEY default prefs.global.keychainMapping.confluence
17
17
  # fallback "${USER}_Confluence_Access_Token"
18
18
  # CONFLUENCE_HOST_OVERRIDE forces the host (overrides URL host extraction)
19
+ # and is the one host trusted without a match
20
+ # against prefs.global.hosts.confluence
19
21
  #
20
22
  # Output (stdout, single JSON object):
21
23
  # {
@@ -34,6 +36,10 @@
34
36
  # 2 missing token or auth failure (after Save Flow trigger)
35
37
  # 3 network / HTTP error
36
38
  # 4 bad usage
39
+ # 6 host refused: the page is not on prefs.global.hosts.confluence
40
+ # (host-not-allowed), or no Confluence host is configured and the page is
41
+ # not on Atlassian Cloud (host-not-configured). Checked before the token
42
+ # is read, so the token never travels to a host the user did not name.
37
43
  #
38
44
  # Notes on auth:
39
45
  # The script reads the Confluence token via credential-store.sh. If the
@@ -44,7 +50,8 @@
44
50
  set -euo pipefail
45
51
 
46
52
  URL=""
47
- HOST_OVERRIDE="${CONFLUENCE_HOST_OVERRIDE:-}"
53
+ ENV_HOST_OVERRIDE="${CONFLUENCE_HOST_OVERRIDE:-}"
54
+ HOST_OVERRIDE="$ENV_HOST_OVERRIDE"
48
55
  PAGE_ID=""
49
56
  TIMEOUT="${CONFLUENCE_TIMEOUT_SECONDS:-20}"
50
57
 
@@ -87,7 +94,7 @@ space_key = ""
87
94
 
88
95
  if url:
89
96
  p = up.urlparse(url)
90
- host = host_override or p.netloc
97
+ host = host_override or p.netloc.rsplit("@", 1)[-1]
91
98
  query = up.parse_qs(p.query)
92
99
  if not page_id:
93
100
  page_id = (query.get("pageId") or [""])[0]
@@ -113,8 +120,42 @@ if [ -z "$HOST" ]; then
113
120
  exit 4
114
121
  fi
115
122
 
116
- # Resolve token via keychainMapping with sane fallback.
123
+ # HOST is the exact string curl receives in https://$HOST/..., so it has to be a
124
+ # bare host[:port]. A '/', '#', '?', '@' or '\' would let a value end with the
125
+ # allowed suffix while curl reads the part before it as the host.
126
+ if ! [[ "$HOST" =~ ^[A-Za-z0-9.-]+(:[0-9]{1,5})?$ ]] || { [[ "$HOST" == *:* ]] && [ "${HOST##*:}" -gt 65535 ]; }; then
127
+ printf '%s\n' '{"status":"blocked","reason":"host-malformed","service":"confluence","expected_pref":"global.hosts.confluence"}' >&2
128
+ exit 6
129
+ fi
130
+
131
+ # The link usually comes from ticket text, so its host is attacker-choosable.
132
+ # The token goes only to the configured host (or a subdomain of it); without a
133
+ # configured host, only to Atlassian Cloud, where the host is the tenant.
117
134
  PREFS="$HOME/.claude/multi-agent-preferences.json"
135
+ if [ -z "$ENV_HOST_OVERRIDE" ]; then
136
+ HOST_VERDICT=$(python3 - "$HOST" "$PREFS" <<'PY'
137
+ import json, sys
138
+ host = sys.argv[1].lower().split(":", 1)[0].rstrip(".")
139
+ try:
140
+ with open(sys.argv[2]) as f:
141
+ allowed = (json.load(f).get("global", {}).get("hosts", {}).get("confluence") or "")
142
+ except Exception:
143
+ allowed = ""
144
+ allowed = allowed.lower().strip().rstrip("/").split("://")[-1].split("/")[0].split(":")[0]
145
+ if allowed:
146
+ ok = host == allowed or host.endswith("." + allowed)
147
+ print("ok" if ok else "host-not-allowed")
148
+ else:
149
+ print("ok" if host.endswith(".atlassian.net") else "host-not-configured")
150
+ PY
151
+ )
152
+ if [ "$HOST_VERDICT" != "ok" ]; then
153
+ printf '%s\n' '{"status":"blocked","reason":"'"$HOST_VERDICT"'","service":"confluence","expected_pref":"global.hosts.confluence"}' >&2
154
+ exit 6
155
+ fi
156
+ fi
157
+
158
+ # Resolve token via keychainMapping with sane fallback.
118
159
  TOKEN_KEY="${CONFLUENCE_AUTH_TOKEN_KEY:-}"
119
160
  if [ -z "$TOKEN_KEY" ] && [ -f "$PREFS" ]; then
120
161
  TOKEN_KEY=$(python3 -c "
@@ -39,10 +39,9 @@
39
39
  #
40
40
  # .docx needs no external tool: the file is a zip and `word/document.xml` is
41
41
  # read with the python3 standard library, which the lib layer already depends
42
- # on. Requiring pandoc or libreoffice would be the wrong dependency for a tool
43
- # that must work on macOS, Linux and Windows alike. PDF has no stdlib path, so
44
- # `pdftotext` is used when present and its absence is a soft skip rather than
45
- # an error - on Windows that absence is the normal case.
42
+ # on. Requiring pandoc or libreoffice would be the wrong dependency for a small
43
+ # reader. PDF has no stdlib path, so `pdftotext` is used when present and its
44
+ # absence is a soft skip rather than an error.
46
45
 
47
46
  set -uo pipefail
48
47