@hybridlabor-api/aos 4.6.5 → 4.7.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 (486) hide show
  1. package/.agents/agents.md +1 -0
  2. package/.agents/nodes.json +5 -1
  3. package/.agents/state.schema.json +2 -1
  4. package/.agents/vendor-manifest.json +50 -0
  5. package/.claude/agents/architect.md +4 -0
  6. package/.claude/agents/security-reviewer.md +1 -1
  7. package/.claude/hooks/memb-inject.mjs +257 -135
  8. package/.claude/hooks/trail-relay.mjs +18 -0
  9. package/.claude/settings.json +70 -0
  10. package/.claude/workflows/startcycle-dispatch.mjs +29 -1
  11. package/.opencode/agents/architect.md +4 -0
  12. package/.opencode/plugins/bdb-aos.js +75 -0
  13. package/THIRD_PARTY_NOTICES.md +48 -0
  14. package/bin/aos-config.mjs +3 -1
  15. package/bin/aos-uninstall.mjs +55 -1
  16. package/docs/handover/agenttrail-for-ao.md +58 -0
  17. package/docs/handover/deja-for-ao.md +51 -0
  18. package/installer.js +257 -56
  19. package/mcp_config.json +4 -0
  20. package/mcps/mcsc/README.md +24 -0
  21. package/mcps/mcsc/package-lock.json +1234 -0
  22. package/mcps/mcsc/package.json +14 -0
  23. package/mcps/mcsc/packages/core/bin/mcsc.js +162 -0
  24. package/mcps/mcsc/packages/core/rulebook.default.yaml +49 -0
  25. package/mcps/mcsc/packages/core/schema/rulebook.schema.json +56 -0
  26. package/mcps/mcsc/packages/core/src/adapters/agy.js +107 -0
  27. package/mcps/mcsc/packages/core/src/adapters/codex.js +56 -0
  28. package/mcps/mcsc/packages/core/src/adapters/native.js +14 -0
  29. package/mcps/mcsc/packages/core/src/adapters/opencode.js +183 -0
  30. package/mcps/mcsc/packages/core/src/adapters/types.js +21 -0
  31. package/mcps/mcsc/packages/core/src/capabilities/buildOfferTable.js +34 -0
  32. package/mcps/mcsc/packages/core/src/capabilities/registry.js +99 -0
  33. package/mcps/mcsc/packages/core/src/capabilities/types.js +24 -0
  34. package/mcps/mcsc/packages/core/src/detect/cache.js +47 -0
  35. package/mcps/mcsc/packages/core/src/detect/inventory.js +73 -0
  36. package/mcps/mcsc/packages/core/src/detect/probes.js +158 -0
  37. package/mcps/mcsc/packages/core/src/detect/types.js +26 -0
  38. package/mcps/mcsc/packages/core/src/rulebook/load.js +53 -0
  39. package/mcps/mcsc/packages/core/src/rulebook/resolve.js +227 -0
  40. package/mcps/mcsc/packages/core/src/rulebook/rulebook.types.js +89 -0
  41. package/mcps/mcsc/packages/core/src/trail.js +17 -0
  42. package/mcps/mcsc/packages/mcp/server.js +302 -0
  43. package/mcps/mcsc/server.js +2 -0
  44. package/package.json +3 -1
  45. package/skills/basic/bdbmediastorm/SKILL.md +1 -1
  46. package/skills/basic/godmode-ui-ux/SKILL.md +2 -2
  47. package/skills/basic/godmode-ui-ux/references/anti-slop-rules.md +44 -40
  48. package/skills/basic/godmode-ui-ux/references/taste-archetypes.md +49 -0
  49. package/skills/basic/startcycle/SKILL.md +7 -0
  50. package/skills/basic/startcycle-graph/SKILL.md +12 -0
  51. package/skills/basic/startcycle-graph-user/SKILL.md +3 -0
  52. package/skills/basic/teamwork-preview/SKILL.md +2 -0
  53. package/skills/bdbrainstorm/SKILL.md +1 -0
  54. package/skills/global_config/agenttrail/LICENSE +21 -0
  55. package/skills/global_config/agenttrail/SKILL.md +48 -0
  56. package/skills/global_config/agenttrail/bin/agenttrail.mjs +1002 -0
  57. package/skills/global_config/agenttrail/public/index.html +661 -0
  58. package/skills/global_config/aos-project-init/SKILL.md +25 -5
  59. package/skills/global_config/aos-project-init/scripts/aos-project-doctor.mjs +11 -0
  60. package/skills/global_config/aos-setup/SKILL.md +34 -1
  61. package/skills/global_config/aos-setup/scripts/aos-doctor.mjs +115 -1
  62. package/skills/global_config/archify/LICENSE +22 -0
  63. package/skills/global_config/archify/SKILL.md +140 -0
  64. package/skills/global_config/archify/THIRD_PARTY_NOTICES.md +69 -0
  65. package/skills/global_config/archify/assets/JetBrainsMono-OFL.txt +93 -0
  66. package/skills/global_config/archify/assets/template.html +14937 -0
  67. package/skills/global_config/archify/bin/archify.mjs +2139 -0
  68. package/skills/global_config/archify/bin/open-artifact.mjs +86 -0
  69. package/skills/global_config/archify/bin/preview.mjs +653 -0
  70. package/skills/global_config/archify/bin/visual-check.mjs +829 -0
  71. package/skills/global_config/archify/brand-marks/README.md +31 -0
  72. package/skills/global_config/archify/brand-marks/catalog.json +131 -0
  73. package/skills/global_config/archify/delta/architecture-delta.mjs +1232 -0
  74. package/skills/global_config/archify/examples/agent-run.lifecycle.json +60 -0
  75. package/skills/global_config/archify/examples/agent-tool-call.workflow.json +94 -0
  76. package/skills/global_config/archify/examples/async-job-roundtrip.sequence.json +61 -0
  77. package/skills/global_config/archify/examples/brand-aware-delivery.architecture.json +47 -0
  78. package/skills/global_config/archify/examples/cache-miss-request.sequence.json +82 -0
  79. package/skills/global_config/archify/examples/checkout-platform.base.architecture.json +31 -0
  80. package/skills/global_config/archify/examples/checkout-platform.head.architecture.json +31 -0
  81. package/skills/global_config/archify/examples/deployment-release.lifecycle.json +49 -0
  82. package/skills/global_config/archify/examples/event-stream.dataflow.json +57 -0
  83. package/skills/global_config/archify/examples/incident-response.workflow.json +64 -0
  84. package/skills/global_config/archify/examples/product-analytics.dataflow.json +76 -0
  85. package/skills/global_config/archify/examples/production-deployment.architecture.json +71 -0
  86. package/skills/global_config/archify/examples/release-delivery.workflow.json +62 -0
  87. package/skills/global_config/archify/examples/web-app.architecture.json +46 -0
  88. package/skills/global_config/archify/migrations/workflow-v2.mjs +279 -0
  89. package/skills/global_config/archify/package.json +39 -0
  90. package/skills/global_config/archify/recipes/scenarios.mjs +391 -0
  91. package/skills/global_config/archify/references/authoring-contract.md +247 -0
  92. package/skills/global_config/archify/references/brand-marks.md +65 -0
  93. package/skills/global_config/archify/references/delivery-contract.md +138 -0
  94. package/skills/global_config/archify/references/viewer-runtime.md +45 -0
  95. package/skills/global_config/archify/renderers/architecture/grid.mjs +62 -0
  96. package/skills/global_config/archify/renderers/architecture/render-architecture.mjs +1078 -0
  97. package/skills/global_config/archify/renderers/dataflow/README.md +104 -0
  98. package/skills/global_config/archify/renderers/dataflow/render-dataflow.mjs +483 -0
  99. package/skills/global_config/archify/renderers/lifecycle/README.md +115 -0
  100. package/skills/global_config/archify/renderers/lifecycle/render-lifecycle.mjs +561 -0
  101. package/skills/global_config/archify/renderers/sequence/README.md +114 -0
  102. package/skills/global_config/archify/renderers/sequence/render-sequence.mjs +464 -0
  103. package/skills/global_config/archify/renderers/shared/brand-marks.mjs +563 -0
  104. package/skills/global_config/archify/renderers/shared/cli.mjs +218 -0
  105. package/skills/global_config/archify/renderers/shared/desktop-readability.mjs +26 -0
  106. package/skills/global_config/archify/renderers/shared/diagnostics.mjs +160 -0
  107. package/skills/global_config/archify/renderers/shared/engineering-profiles.mjs +157 -0
  108. package/skills/global_config/archify/renderers/shared/generated-brand-marks.mjs +2003 -0
  109. package/skills/global_config/archify/renderers/shared/generated-validators.mjs +13 -0
  110. package/skills/global_config/archify/renderers/shared/geometry.mjs +1423 -0
  111. package/skills/global_config/archify/renderers/shared/i18n.mjs +595 -0
  112. package/skills/global_config/archify/renderers/shared/layout-report.mjs +40 -0
  113. package/skills/global_config/archify/renderers/shared/legend.mjs +217 -0
  114. package/skills/global_config/archify/renderers/shared/output-path.mjs +340 -0
  115. package/skills/global_config/archify/renderers/shared/repository-evidence.mjs +239 -0
  116. package/skills/global_config/archify/renderers/shared/repository-location.mjs +58 -0
  117. package/skills/global_config/archify/renderers/shared/text-fit.mjs +49 -0
  118. package/skills/global_config/archify/renderers/shared/utils.mjs +232 -0
  119. package/skills/global_config/archify/renderers/shared/validator.mjs +86 -0
  120. package/skills/global_config/archify/renderers/workflow/README.md +223 -0
  121. package/skills/global_config/archify/renderers/workflow/render-workflow.mjs +35 -0
  122. package/skills/global_config/archify/renderers/workflow/workflow-compiler.mjs +4400 -0
  123. package/skills/global_config/archify/renderers/workflow/workflow-migration-geometry.mjs +144 -0
  124. package/skills/global_config/archify/schemas/README.md +211 -0
  125. package/skills/global_config/archify/schemas/architecture.schema.json +178 -0
  126. package/skills/global_config/archify/schemas/common.schema.json +115 -0
  127. package/skills/global_config/archify/schemas/dataflow.schema.json +243 -0
  128. package/skills/global_config/archify/schemas/lifecycle.schema.json +266 -0
  129. package/skills/global_config/archify/schemas/sequence.schema.json +223 -0
  130. package/skills/global_config/archify/schemas/workflow.schema.json +428 -0
  131. package/skills/global_config/archify/scripts/check-render-output.mjs +916 -0
  132. package/skills/global_config/archify/scripts/generate-brand-marks.mjs +141 -0
  133. package/skills/global_config/archify/scripts/generate-validators.mjs +66 -0
  134. package/skills/global_config/archify/scripts/render-examples.mjs +26 -0
  135. package/skills/global_config/archify/skill-release.json +10 -0
  136. package/skills/global_config/bdb-security-audit/SKILL.md +109 -0
  137. package/skills/global_config/bdb-security-audit/references/audit-checklists.md +172 -0
  138. package/skills/global_config/bdb-security-audit/references/skylos-guide.md +139 -0
  139. package/skills/global_config/bdb-security-audit/references/xalgorix-bridge.md +110 -0
  140. package/skills/global_config/bdbdesignpro/SKILL.md +4 -4
  141. package/skills/global_config/bdbdesignpro/references/bdb-motion-tokens.md +52 -31
  142. package/skills/global_config/bdbresilience/SKILL.md +10 -0
  143. package/skills/global_config/brag/SKILL.md +179 -0
  144. package/skills/global_config/brag/assets/music/README.md +20 -0
  145. package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-1-by-ende-dot-app.music-cues.json +3846 -0
  146. package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-1-by-ende-dot-app.music-cues.md +35 -0
  147. package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-10-by-ende-dot-app.music-cues.json +1826 -0
  148. package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-10-by-ende-dot-app.music-cues.md +35 -0
  149. package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-11-by-ende-dot-app.music-cues.json +2266 -0
  150. package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-11-by-ende-dot-app.music-cues.md +35 -0
  151. package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-12-by-ende-dot-app.music-cues.json +2806 -0
  152. package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-12-by-ende-dot-app.music-cues.md +35 -0
  153. package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-9-by-ende-dot-app.music-cues.json +2796 -0
  154. package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-9-by-ende-dot-app.music-cues.md +35 -0
  155. package/skills/global_config/brag/assets/music/happy-beats-business-moves-vol-1-by-ende-dot-app.mp3 +0 -0
  156. package/skills/global_config/brag/assets/music/happy-beats-business-moves-vol-10-by-ende-dot-app.mp3 +0 -0
  157. package/skills/global_config/brag/assets/music/happy-beats-business-moves-vol-11-by-ende-dot-app.mp3 +0 -0
  158. package/skills/global_config/brag/assets/music/happy-beats-business-moves-vol-12-by-ende-dot-app.mp3 +0 -0
  159. package/skills/global_config/brag/assets/music/happy-beats-business-moves-vol-9-by-ende-dot-app.mp3 +0 -0
  160. package/skills/global_config/brag/assets/sfx/casino/card-fan-1.ogg +0 -0
  161. package/skills/global_config/brag/assets/sfx/casino/card-fan-2.ogg +0 -0
  162. package/skills/global_config/brag/assets/sfx/casino/card-place-1.ogg +0 -0
  163. package/skills/global_config/brag/assets/sfx/casino/card-place-2.ogg +0 -0
  164. package/skills/global_config/brag/assets/sfx/casino/card-place-3.ogg +0 -0
  165. package/skills/global_config/brag/assets/sfx/casino/card-place-4.ogg +0 -0
  166. package/skills/global_config/brag/assets/sfx/casino/card-shove-1.ogg +0 -0
  167. package/skills/global_config/brag/assets/sfx/casino/card-shove-2.ogg +0 -0
  168. package/skills/global_config/brag/assets/sfx/casino/card-shove-3.ogg +0 -0
  169. package/skills/global_config/brag/assets/sfx/casino/card-shove-4.ogg +0 -0
  170. package/skills/global_config/brag/assets/sfx/casino/card-shuffle.ogg +0 -0
  171. package/skills/global_config/brag/assets/sfx/casino/card-slide-1.ogg +0 -0
  172. package/skills/global_config/brag/assets/sfx/casino/card-slide-2.ogg +0 -0
  173. package/skills/global_config/brag/assets/sfx/casino/card-slide-3.ogg +0 -0
  174. package/skills/global_config/brag/assets/sfx/casino/card-slide-4.ogg +0 -0
  175. package/skills/global_config/brag/assets/sfx/casino/card-slide-5.ogg +0 -0
  176. package/skills/global_config/brag/assets/sfx/casino/card-slide-6.ogg +0 -0
  177. package/skills/global_config/brag/assets/sfx/casino/card-slide-7.ogg +0 -0
  178. package/skills/global_config/brag/assets/sfx/casino/card-slide-8.ogg +0 -0
  179. package/skills/global_config/brag/assets/sfx/casino/cards-pack-open-1.ogg +0 -0
  180. package/skills/global_config/brag/assets/sfx/casino/cards-pack-open-2.ogg +0 -0
  181. package/skills/global_config/brag/assets/sfx/casino/chip-lay-1.ogg +0 -0
  182. package/skills/global_config/brag/assets/sfx/casino/chip-lay-2.ogg +0 -0
  183. package/skills/global_config/brag/assets/sfx/casino/chip-lay-3.ogg +0 -0
  184. package/skills/global_config/brag/assets/sfx/casino/chips-collide-1.ogg +0 -0
  185. package/skills/global_config/brag/assets/sfx/casino/chips-collide-2.ogg +0 -0
  186. package/skills/global_config/brag/assets/sfx/casino/chips-collide-3.ogg +0 -0
  187. package/skills/global_config/brag/assets/sfx/casino/chips-collide-4.ogg +0 -0
  188. package/skills/global_config/brag/assets/sfx/casino/chips-handle-1.ogg +0 -0
  189. package/skills/global_config/brag/assets/sfx/casino/chips-handle-2.ogg +0 -0
  190. package/skills/global_config/brag/assets/sfx/casino/chips-handle-3.ogg +0 -0
  191. package/skills/global_config/brag/assets/sfx/casino/chips-handle-4.ogg +0 -0
  192. package/skills/global_config/brag/assets/sfx/casino/chips-handle-6.ogg +0 -0
  193. package/skills/global_config/brag/assets/sfx/casino/chips-stack-1.ogg +0 -0
  194. package/skills/global_config/brag/assets/sfx/casino/chips-stack-2.ogg +0 -0
  195. package/skills/global_config/brag/assets/sfx/casino/chips-stack-3.ogg +0 -0
  196. package/skills/global_config/brag/assets/sfx/casino/chips-stack-4.ogg +0 -0
  197. package/skills/global_config/brag/assets/sfx/casino/chips-stack-5.ogg +0 -0
  198. package/skills/global_config/brag/assets/sfx/casino/chips-stack-6.ogg +0 -0
  199. package/skills/global_config/brag/assets/sfx/casino/dice-grab-1.ogg +0 -0
  200. package/skills/global_config/brag/assets/sfx/casino/dice-grab-2.ogg +0 -0
  201. package/skills/global_config/brag/assets/sfx/casino/dice-shake-1.ogg +0 -0
  202. package/skills/global_config/brag/assets/sfx/casino/dice-shake-2.ogg +0 -0
  203. package/skills/global_config/brag/assets/sfx/casino/dice-shake-3.ogg +0 -0
  204. package/skills/global_config/brag/assets/sfx/casino/dice-throw-1.ogg +0 -0
  205. package/skills/global_config/brag/assets/sfx/casino/dice-throw-2.ogg +0 -0
  206. package/skills/global_config/brag/assets/sfx/casino/dice-throw-3.ogg +0 -0
  207. package/skills/global_config/brag/assets/sfx/casino/die-throw-1.ogg +0 -0
  208. package/skills/global_config/brag/assets/sfx/casino/die-throw-2.ogg +0 -0
  209. package/skills/global_config/brag/assets/sfx/casino/die-throw-3.ogg +0 -0
  210. package/skills/global_config/brag/assets/sfx/casino/die-throw-4.ogg +0 -0
  211. package/skills/global_config/brag/assets/sfx/impact/footstep_carpet_000.ogg +0 -0
  212. package/skills/global_config/brag/assets/sfx/impact/footstep_carpet_003.ogg +0 -0
  213. package/skills/global_config/brag/assets/sfx/impact/footstep_carpet_004.ogg +0 -0
  214. package/skills/global_config/brag/assets/sfx/impact/footstep_concrete_000.ogg +0 -0
  215. package/skills/global_config/brag/assets/sfx/impact/footstep_concrete_001.ogg +0 -0
  216. package/skills/global_config/brag/assets/sfx/impact/footstep_concrete_002.ogg +0 -0
  217. package/skills/global_config/brag/assets/sfx/impact/footstep_concrete_003.ogg +0 -0
  218. package/skills/global_config/brag/assets/sfx/impact/footstep_concrete_004.ogg +0 -0
  219. package/skills/global_config/brag/assets/sfx/impact/footstep_grass_000.ogg +0 -0
  220. package/skills/global_config/brag/assets/sfx/impact/footstep_grass_001.ogg +0 -0
  221. package/skills/global_config/brag/assets/sfx/impact/footstep_grass_002.ogg +0 -0
  222. package/skills/global_config/brag/assets/sfx/impact/footstep_grass_003.ogg +0 -0
  223. package/skills/global_config/brag/assets/sfx/impact/footstep_grass_004.ogg +0 -0
  224. package/skills/global_config/brag/assets/sfx/impact/footstep_snow_000.ogg +0 -0
  225. package/skills/global_config/brag/assets/sfx/impact/footstep_snow_001.ogg +0 -0
  226. package/skills/global_config/brag/assets/sfx/impact/footstep_snow_002.ogg +0 -0
  227. package/skills/global_config/brag/assets/sfx/impact/footstep_snow_003.ogg +0 -0
  228. package/skills/global_config/brag/assets/sfx/impact/footstep_snow_004.ogg +0 -0
  229. package/skills/global_config/brag/assets/sfx/impact/footstep_wood_000.ogg +0 -0
  230. package/skills/global_config/brag/assets/sfx/impact/footstep_wood_001.ogg +0 -0
  231. package/skills/global_config/brag/assets/sfx/impact/footstep_wood_002.ogg +0 -0
  232. package/skills/global_config/brag/assets/sfx/impact/footstep_wood_003.ogg +0 -0
  233. package/skills/global_config/brag/assets/sfx/impact/footstep_wood_004.ogg +0 -0
  234. package/skills/global_config/brag/assets/sfx/impact/impactBell_heavy_000.ogg +0 -0
  235. package/skills/global_config/brag/assets/sfx/impact/impactBell_heavy_003.ogg +0 -0
  236. package/skills/global_config/brag/assets/sfx/impact/impactBell_heavy_004.ogg +0 -0
  237. package/skills/global_config/brag/assets/sfx/impact/impactGeneric_light_000.ogg +0 -0
  238. package/skills/global_config/brag/assets/sfx/impact/impactGeneric_light_001.ogg +0 -0
  239. package/skills/global_config/brag/assets/sfx/impact/impactGeneric_light_002.ogg +0 -0
  240. package/skills/global_config/brag/assets/sfx/impact/impactGeneric_light_003.ogg +0 -0
  241. package/skills/global_config/brag/assets/sfx/impact/impactGeneric_light_004.ogg +0 -0
  242. package/skills/global_config/brag/assets/sfx/impact/impactGlass_heavy_002.ogg +0 -0
  243. package/skills/global_config/brag/assets/sfx/impact/impactGlass_light_001.ogg +0 -0
  244. package/skills/global_config/brag/assets/sfx/impact/impactGlass_light_002.ogg +0 -0
  245. package/skills/global_config/brag/assets/sfx/impact/impactGlass_light_003.ogg +0 -0
  246. package/skills/global_config/brag/assets/sfx/impact/impactGlass_medium_000.ogg +0 -0
  247. package/skills/global_config/brag/assets/sfx/impact/impactGlass_medium_002.ogg +0 -0
  248. package/skills/global_config/brag/assets/sfx/impact/impactGlass_medium_004.ogg +0 -0
  249. package/skills/global_config/brag/assets/sfx/impact/impactMetal_heavy_000.ogg +0 -0
  250. package/skills/global_config/brag/assets/sfx/impact/impactMetal_heavy_002.ogg +0 -0
  251. package/skills/global_config/brag/assets/sfx/impact/impactMetal_heavy_004.ogg +0 -0
  252. package/skills/global_config/brag/assets/sfx/impact/impactMetal_light_002.ogg +0 -0
  253. package/skills/global_config/brag/assets/sfx/impact/impactMetal_light_003.ogg +0 -0
  254. package/skills/global_config/brag/assets/sfx/impact/impactMetal_medium_000.ogg +0 -0
  255. package/skills/global_config/brag/assets/sfx/impact/impactMetal_medium_001.ogg +0 -0
  256. package/skills/global_config/brag/assets/sfx/impact/impactMetal_medium_002.ogg +0 -0
  257. package/skills/global_config/brag/assets/sfx/impact/impactMetal_medium_003.ogg +0 -0
  258. package/skills/global_config/brag/assets/sfx/impact/impactMetal_medium_004.ogg +0 -0
  259. package/skills/global_config/brag/assets/sfx/impact/impactMining_001.ogg +0 -0
  260. package/skills/global_config/brag/assets/sfx/impact/impactPlank_medium_000.ogg +0 -0
  261. package/skills/global_config/brag/assets/sfx/impact/impactPlank_medium_001.ogg +0 -0
  262. package/skills/global_config/brag/assets/sfx/impact/impactPlank_medium_002.ogg +0 -0
  263. package/skills/global_config/brag/assets/sfx/impact/impactPlank_medium_003.ogg +0 -0
  264. package/skills/global_config/brag/assets/sfx/impact/impactPlank_medium_004.ogg +0 -0
  265. package/skills/global_config/brag/assets/sfx/impact/impactPlate_heavy_000.ogg +0 -0
  266. package/skills/global_config/brag/assets/sfx/impact/impactPlate_heavy_001.ogg +0 -0
  267. package/skills/global_config/brag/assets/sfx/impact/impactPlate_heavy_002.ogg +0 -0
  268. package/skills/global_config/brag/assets/sfx/impact/impactPlate_heavy_003.ogg +0 -0
  269. package/skills/global_config/brag/assets/sfx/impact/impactPlate_heavy_004.ogg +0 -0
  270. package/skills/global_config/brag/assets/sfx/impact/impactPlate_light_000.ogg +0 -0
  271. package/skills/global_config/brag/assets/sfx/impact/impactPlate_light_001.ogg +0 -0
  272. package/skills/global_config/brag/assets/sfx/impact/impactPlate_light_002.ogg +0 -0
  273. package/skills/global_config/brag/assets/sfx/impact/impactPlate_light_003.ogg +0 -0
  274. package/skills/global_config/brag/assets/sfx/impact/impactPlate_light_004.ogg +0 -0
  275. package/skills/global_config/brag/assets/sfx/impact/impactPlate_medium_000.ogg +0 -0
  276. package/skills/global_config/brag/assets/sfx/impact/impactPlate_medium_001.ogg +0 -0
  277. package/skills/global_config/brag/assets/sfx/impact/impactPlate_medium_002.ogg +0 -0
  278. package/skills/global_config/brag/assets/sfx/impact/impactPlate_medium_003.ogg +0 -0
  279. package/skills/global_config/brag/assets/sfx/impact/impactPlate_medium_004.ogg +0 -0
  280. package/skills/global_config/brag/assets/sfx/impact/impactPunch_heavy_000.ogg +0 -0
  281. package/skills/global_config/brag/assets/sfx/impact/impactPunch_heavy_001.ogg +0 -0
  282. package/skills/global_config/brag/assets/sfx/impact/impactPunch_heavy_002.ogg +0 -0
  283. package/skills/global_config/brag/assets/sfx/impact/impactPunch_heavy_003.ogg +0 -0
  284. package/skills/global_config/brag/assets/sfx/impact/impactPunch_heavy_004.ogg +0 -0
  285. package/skills/global_config/brag/assets/sfx/impact/impactPunch_medium_000.ogg +0 -0
  286. package/skills/global_config/brag/assets/sfx/impact/impactPunch_medium_001.ogg +0 -0
  287. package/skills/global_config/brag/assets/sfx/impact/impactPunch_medium_002.ogg +0 -0
  288. package/skills/global_config/brag/assets/sfx/impact/impactPunch_medium_003.ogg +0 -0
  289. package/skills/global_config/brag/assets/sfx/impact/impactPunch_medium_004.ogg +0 -0
  290. package/skills/global_config/brag/assets/sfx/impact/impactSoft_heavy_000.ogg +0 -0
  291. package/skills/global_config/brag/assets/sfx/impact/impactSoft_heavy_001.ogg +0 -0
  292. package/skills/global_config/brag/assets/sfx/impact/impactSoft_heavy_002.ogg +0 -0
  293. package/skills/global_config/brag/assets/sfx/impact/impactSoft_heavy_003.ogg +0 -0
  294. package/skills/global_config/brag/assets/sfx/impact/impactSoft_heavy_004.ogg +0 -0
  295. package/skills/global_config/brag/assets/sfx/impact/impactSoft_medium_000.ogg +0 -0
  296. package/skills/global_config/brag/assets/sfx/impact/impactSoft_medium_001.ogg +0 -0
  297. package/skills/global_config/brag/assets/sfx/impact/impactSoft_medium_002.ogg +0 -0
  298. package/skills/global_config/brag/assets/sfx/impact/impactSoft_medium_003.ogg +0 -0
  299. package/skills/global_config/brag/assets/sfx/impact/impactSoft_medium_004.ogg +0 -0
  300. package/skills/global_config/brag/assets/sfx/impact/impactTin_medium_000.ogg +0 -0
  301. package/skills/global_config/brag/assets/sfx/impact/impactTin_medium_001.ogg +0 -0
  302. package/skills/global_config/brag/assets/sfx/impact/impactTin_medium_002.ogg +0 -0
  303. package/skills/global_config/brag/assets/sfx/impact/impactTin_medium_003.ogg +0 -0
  304. package/skills/global_config/brag/assets/sfx/impact/impactTin_medium_004.ogg +0 -0
  305. package/skills/global_config/brag/assets/sfx/impact/impactWood_heavy_000.ogg +0 -0
  306. package/skills/global_config/brag/assets/sfx/impact/impactWood_heavy_001.ogg +0 -0
  307. package/skills/global_config/brag/assets/sfx/impact/impactWood_heavy_002.ogg +0 -0
  308. package/skills/global_config/brag/assets/sfx/impact/impactWood_heavy_003.ogg +0 -0
  309. package/skills/global_config/brag/assets/sfx/impact/impactWood_heavy_004.ogg +0 -0
  310. package/skills/global_config/brag/assets/sfx/impact/impactWood_light_000.ogg +0 -0
  311. package/skills/global_config/brag/assets/sfx/impact/impactWood_light_001.ogg +0 -0
  312. package/skills/global_config/brag/assets/sfx/impact/impactWood_light_002.ogg +0 -0
  313. package/skills/global_config/brag/assets/sfx/impact/impactWood_light_003.ogg +0 -0
  314. package/skills/global_config/brag/assets/sfx/impact/impactWood_light_004.ogg +0 -0
  315. package/skills/global_config/brag/assets/sfx/impact/impactWood_medium_000.ogg +0 -0
  316. package/skills/global_config/brag/assets/sfx/impact/impactWood_medium_001.ogg +0 -0
  317. package/skills/global_config/brag/assets/sfx/impact/impactWood_medium_002.ogg +0 -0
  318. package/skills/global_config/brag/assets/sfx/impact/impactWood_medium_003.ogg +0 -0
  319. package/skills/global_config/brag/assets/sfx/impact/impactWood_medium_004.ogg +0 -0
  320. package/skills/global_config/brag/assets/sfx/interface/bong_001.ogg +0 -0
  321. package/skills/global_config/brag/assets/sfx/interface/click_001.ogg +0 -0
  322. package/skills/global_config/brag/assets/sfx/interface/click_002.ogg +0 -0
  323. package/skills/global_config/brag/assets/sfx/interface/click_003.ogg +0 -0
  324. package/skills/global_config/brag/assets/sfx/interface/click_004.ogg +0 -0
  325. package/skills/global_config/brag/assets/sfx/interface/click_005.ogg +0 -0
  326. package/skills/global_config/brag/assets/sfx/interface/drop_001.ogg +0 -0
  327. package/skills/global_config/brag/assets/sfx/interface/drop_002.ogg +0 -0
  328. package/skills/global_config/brag/assets/sfx/interface/drop_003.ogg +0 -0
  329. package/skills/global_config/brag/assets/sfx/interface/error_005.ogg +0 -0
  330. package/skills/global_config/brag/assets/sfx/interface/error_006.ogg +0 -0
  331. package/skills/global_config/brag/assets/sfx/interface/glitch_002.ogg +0 -0
  332. package/skills/global_config/brag/assets/sfx/interface/glitch_004.ogg +0 -0
  333. package/skills/global_config/brag/assets/sfx/interface/select_008.ogg +0 -0
  334. package/skills/global_config/brag/assets/sfx/interface/switch_001.ogg +0 -0
  335. package/skills/global_config/brag/assets/sfx/interface/switch_002.ogg +0 -0
  336. package/skills/global_config/brag/assets/sfx/interface/switch_004.ogg +0 -0
  337. package/skills/global_config/brag/assets/sfx/interface/switch_005.ogg +0 -0
  338. package/skills/global_config/brag/assets/sfx/interface/switch_006.ogg +0 -0
  339. package/skills/global_config/brag/assets/sfx/interface/switch_007.ogg +0 -0
  340. package/skills/global_config/brag/assets/sfx/keyboard/keypress-001.wav +0 -0
  341. package/skills/global_config/brag/assets/sfx/keyboard/keypress-002.wav +0 -0
  342. package/skills/global_config/brag/assets/sfx/keyboard/keypress-003.wav +0 -0
  343. package/skills/global_config/brag/assets/sfx/keyboard/keypress-004.wav +0 -0
  344. package/skills/global_config/brag/assets/sfx/keyboard/keypress-005.wav +0 -0
  345. package/skills/global_config/brag/assets/sfx/keyboard/keypress-006.wav +0 -0
  346. package/skills/global_config/brag/assets/sfx/keyboard/keypress-007.wav +0 -0
  347. package/skills/global_config/brag/assets/sfx/keyboard/keypress-008.wav +0 -0
  348. package/skills/global_config/brag/assets/sfx/keyboard/keypress-009.wav +0 -0
  349. package/skills/global_config/brag/assets/sfx/keyboard/keypress-010.wav +0 -0
  350. package/skills/global_config/brag/assets/sfx/keyboard/keypress-011.wav +0 -0
  351. package/skills/global_config/brag/assets/sfx/keyboard/keypress-012.wav +0 -0
  352. package/skills/global_config/brag/assets/sfx/keyboard/keypress-013.wav +0 -0
  353. package/skills/global_config/brag/assets/sfx/keyboard/keypress-014.wav +0 -0
  354. package/skills/global_config/brag/assets/sfx/keyboard/keypress-015.wav +0 -0
  355. package/skills/global_config/brag/assets/sfx/keyboard/keypress-016.wav +0 -0
  356. package/skills/global_config/brag/assets/sfx/keyboard/keypress-017.wav +0 -0
  357. package/skills/global_config/brag/assets/sfx/keyboard/keypress-018.wav +0 -0
  358. package/skills/global_config/brag/assets/sfx/keyboard/keypress-019.wav +0 -0
  359. package/skills/global_config/brag/assets/sfx/keyboard/keypress-020.wav +0 -0
  360. package/skills/global_config/brag/assets/sfx/keyboard/keypress-021.wav +0 -0
  361. package/skills/global_config/brag/assets/sfx/keyboard/keypress-022.wav +0 -0
  362. package/skills/global_config/brag/assets/sfx/keyboard/keypress-023.wav +0 -0
  363. package/skills/global_config/brag/assets/sfx/keyboard/keypress-024.wav +0 -0
  364. package/skills/global_config/brag/assets/sfx/keyboard/keypress-025.wav +0 -0
  365. package/skills/global_config/brag/assets/sfx/keyboard/keypress-026.wav +0 -0
  366. package/skills/global_config/brag/assets/sfx/keyboard/keypress-027.wav +0 -0
  367. package/skills/global_config/brag/assets/sfx/keyboard/keypress-028.wav +0 -0
  368. package/skills/global_config/brag/assets/sfx/keyboard/keypress-029.wav +0 -0
  369. package/skills/global_config/brag/assets/sfx/keyboard/keypress-030.wav +0 -0
  370. package/skills/global_config/brag/assets/sfx/keyboard/keypress-031.wav +0 -0
  371. package/skills/global_config/brag/assets/sfx/keyboard/keypress-032.wav +0 -0
  372. package/skills/global_config/brag/assets/sfx/sfx-analysis.json +15584 -0
  373. package/skills/global_config/brag/assets/sfx/sfx-analysis.md +75 -0
  374. package/skills/global_config/brag/assets/sfx/ui/click1.ogg +0 -0
  375. package/skills/global_config/brag/assets/sfx/ui/click2.ogg +0 -0
  376. package/skills/global_config/brag/assets/sfx/ui/click3.ogg +0 -0
  377. package/skills/global_config/brag/assets/sfx/ui/click4.ogg +0 -0
  378. package/skills/global_config/brag/assets/sfx/ui/click5.ogg +0 -0
  379. package/skills/global_config/brag/assets/sfx/ui/mouseclick1.ogg +0 -0
  380. package/skills/global_config/brag/assets/sfx/ui/rollover1.ogg +0 -0
  381. package/skills/global_config/brag/assets/sfx/ui/rollover2.ogg +0 -0
  382. package/skills/global_config/brag/assets/sfx/ui/rollover4.ogg +0 -0
  383. package/skills/global_config/brag/assets/sfx/ui/rollover5.ogg +0 -0
  384. package/skills/global_config/brag/assets/sfx/ui/switch1.ogg +0 -0
  385. package/skills/global_config/brag/assets/sfx/ui/switch10.ogg +0 -0
  386. package/skills/global_config/brag/assets/sfx/ui/switch11.ogg +0 -0
  387. package/skills/global_config/brag/assets/sfx/ui/switch12.ogg +0 -0
  388. package/skills/global_config/brag/assets/sfx/ui/switch13.ogg +0 -0
  389. package/skills/global_config/brag/assets/sfx/ui/switch14.ogg +0 -0
  390. package/skills/global_config/brag/assets/sfx/ui/switch15.ogg +0 -0
  391. package/skills/global_config/brag/assets/sfx/ui/switch16.ogg +0 -0
  392. package/skills/global_config/brag/assets/sfx/ui/switch17.ogg +0 -0
  393. package/skills/global_config/brag/assets/sfx/ui/switch18.ogg +0 -0
  394. package/skills/global_config/brag/assets/sfx/ui/switch19.ogg +0 -0
  395. package/skills/global_config/brag/assets/sfx/ui/switch2.ogg +0 -0
  396. package/skills/global_config/brag/assets/sfx/ui/switch20.ogg +0 -0
  397. package/skills/global_config/brag/assets/sfx/ui/switch21.ogg +0 -0
  398. package/skills/global_config/brag/assets/sfx/ui/switch22.ogg +0 -0
  399. package/skills/global_config/brag/assets/sfx/ui/switch23.ogg +0 -0
  400. package/skills/global_config/brag/assets/sfx/ui/switch24.ogg +0 -0
  401. package/skills/global_config/brag/assets/sfx/ui/switch25.ogg +0 -0
  402. package/skills/global_config/brag/assets/sfx/ui/switch26.ogg +0 -0
  403. package/skills/global_config/brag/assets/sfx/ui/switch27.ogg +0 -0
  404. package/skills/global_config/brag/assets/sfx/ui/switch28.ogg +0 -0
  405. package/skills/global_config/brag/assets/sfx/ui/switch29.ogg +0 -0
  406. package/skills/global_config/brag/assets/sfx/ui/switch3.ogg +0 -0
  407. package/skills/global_config/brag/assets/sfx/ui/switch30.ogg +0 -0
  408. package/skills/global_config/brag/assets/sfx/ui/switch31.ogg +0 -0
  409. package/skills/global_config/brag/assets/sfx/ui/switch32.ogg +0 -0
  410. package/skills/global_config/brag/assets/sfx/ui/switch33.ogg +0 -0
  411. package/skills/global_config/brag/assets/sfx/ui/switch34.ogg +0 -0
  412. package/skills/global_config/brag/assets/sfx/ui/switch35.ogg +0 -0
  413. package/skills/global_config/brag/assets/sfx/ui/switch36.ogg +0 -0
  414. package/skills/global_config/brag/assets/sfx/ui/switch37.ogg +0 -0
  415. package/skills/global_config/brag/assets/sfx/ui/switch38.ogg +0 -0
  416. package/skills/global_config/brag/assets/sfx/ui/switch4.ogg +0 -0
  417. package/skills/global_config/brag/assets/sfx/ui/switch5.ogg +0 -0
  418. package/skills/global_config/brag/assets/sfx/ui/switch6.ogg +0 -0
  419. package/skills/global_config/brag/assets/sfx/ui/switch7.ogg +0 -0
  420. package/skills/global_config/brag/assets/sfx/ui/switch8.ogg +0 -0
  421. package/skills/global_config/brag/assets/sfx/ui/switch9.ogg +0 -0
  422. package/skills/global_config/brag/references/audio.md +307 -0
  423. package/skills/global_config/brag/references/step-1-inspect.md +133 -0
  424. package/skills/global_config/brag/references/step-2-plan.md +234 -0
  425. package/skills/global_config/brag/references/step-3-compose.md +210 -0
  426. package/skills/global_config/brag/references/step-4-deliver.md +168 -0
  427. package/skills/global_config/brag/references/tones.md +231 -0
  428. package/skills/global_config/brag/scripts/analyze_music_cues.py +309 -0
  429. package/skills/global_config/brag/scripts/pyproject.toml +14 -0
  430. package/skills/global_config/brag/scripts/uv.lock +819 -0
  431. package/skills/global_config/deja-memory/SKILL.md +42 -0
  432. package/skills/global_config/editable-design/LICENSE +202 -0
  433. package/skills/global_config/editable-design/README.md +34 -0
  434. package/skills/global_config/editable-design/SKILL.md +630 -0
  435. package/skills/global_config/editable-design/THIRD_PARTY_NOTICES.md +10 -0
  436. package/skills/global_config/editable-design/agents/openai.yaml +4 -0
  437. package/skills/global_config/editable-design/assets/editor/layer-editor.css +262 -0
  438. package/skills/global_config/editable-design/assets/editor/layer-editor.js +1929 -0
  439. package/skills/global_config/editable-design/assets/poster-starter/README.md +92 -0
  440. package/skills/global_config/editable-design/assets/poster-starter/assets/.gitkeep +0 -0
  441. package/skills/global_config/editable-design/assets/poster-starter/index.html +91 -0
  442. package/skills/global_config/editable-design/assets/poster-starter/poster.json +6 -0
  443. package/skills/global_config/editable-design/assets/poster-starter/reference/.gitkeep +1 -0
  444. package/skills/global_config/editable-design/assets/replay/icons/assets.png +0 -0
  445. package/skills/global_config/editable-design/assets/replay/icons/html.png +0 -0
  446. package/skills/global_config/editable-design/assets/replay/icons/input.png +0 -0
  447. package/skills/global_config/editable-design/assets/replay/icons/layers.png +0 -0
  448. package/skills/global_config/editable-design/assets/replay/icons/plan.png +0 -0
  449. package/skills/global_config/editable-design/assets/replay/icons/reference.png +0 -0
  450. package/skills/global_config/editable-design/assets/replay/icons/review.png +0 -0
  451. package/skills/global_config/editable-design/assets/replay/index.html +59 -0
  452. package/skills/global_config/editable-design/assets/replay/replay-motion.js +410 -0
  453. package/skills/global_config/editable-design/assets/replay/replay.css +380 -0
  454. package/skills/global_config/editable-design/assets/replay/replay.js +374 -0
  455. package/skills/global_config/editable-design/font-kit/package-lock.json +115 -0
  456. package/skills/global_config/editable-design/font-kit/package.json +19 -0
  457. package/skills/global_config/editable-design/pack.sh +20 -0
  458. package/skills/global_config/editable-design/references/asset-architecture.md +72 -0
  459. package/skills/global_config/editable-design/references/editor-pitfalls.md +70 -0
  460. package/skills/global_config/editable-design/references/editor-runtime.md +131 -0
  461. package/skills/global_config/editable-design/references/font-system.md +89 -0
  462. package/skills/global_config/editable-design/references/imagery.md +145 -0
  463. package/skills/global_config/editable-design/references/layout-typography.md +116 -0
  464. package/skills/global_config/editable-design/references/replay-contract.md +169 -0
  465. package/skills/global_config/editable-design/scripts/_browser.mjs +247 -0
  466. package/skills/global_config/editable-design/scripts/bake.mjs +87 -0
  467. package/skills/global_config/editable-design/scripts/build-replay.mjs +316 -0
  468. package/skills/global_config/editable-design/scripts/check-contract.mjs +293 -0
  469. package/skills/global_config/editable-design/scripts/check-fonts.sh +252 -0
  470. package/skills/global_config/editable-design/scripts/check-poster.sh +70 -0
  471. package/skills/global_config/editable-design/scripts/doctor.sh +78 -0
  472. package/skills/global_config/editable-design/scripts/explode.mjs +115 -0
  473. package/skills/global_config/editable-design/scripts/font-kit.mjs +187 -0
  474. package/skills/global_config/editable-design/scripts/import-asset.sh +23 -0
  475. package/skills/global_config/editable-design/scripts/init-poster.sh +64 -0
  476. package/skills/global_config/editable-design/scripts/install-font-kit.sh +13 -0
  477. package/skills/global_config/editable-design/scripts/package-lock.json +334 -0
  478. package/skills/global_config/editable-design/scripts/package.json +14 -0
  479. package/skills/global_config/editable-design/scripts/remove-chroma-key.py +201 -0
  480. package/skills/global_config/editable-design/scripts/render-poster.sh +202 -0
  481. package/skills/global_config/editable-design/scripts/trace.sh +159 -0
  482. package/skills/global_config/editable-design/scripts/verify-replay.mjs +97 -0
  483. package/skills/global_config/editable-design/scripts/verify.mjs +782 -0
  484. package/skills/global_config/editable-design/scripts/wire-editor.mjs +104 -0
  485. package/skills/global_config/editable-design/tests/fixtures/small-explode/index.html +86 -0
  486. package/skills/global_config/plan-canvas/SKILL.md +8 -0
@@ -0,0 +1,563 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { lookup } from 'node:dns/promises';
3
+ import http from 'node:http';
4
+ import https from 'node:https';
5
+ import net from 'node:net';
6
+ import { BRAND_MARKS } from './generated-brand-marks.mjs';
7
+ import { throwDiagnosticError } from './diagnostics.mjs';
8
+ import { esc, textUnits } from './utils.mjs';
9
+
10
+ const COLLECTIONS = Object.freeze({
11
+ architecture: 'components',
12
+ workflow: 'nodes',
13
+ sequence: 'participants',
14
+ dataflow: 'nodes',
15
+ lifecycle: 'states',
16
+ });
17
+ const MARK_BY_LOOKUP = new Map();
18
+ const MARK_BY_DOMAIN = new Map();
19
+ const RESOLVED_BY_NODE = new WeakMap();
20
+ const RESOLVED_MARK = Symbol('archify.brandMark');
21
+ const MAX_HTML_BYTES = 256 * 1024;
22
+ const MAX_IMAGE_BYTES = 1024 * 1024;
23
+ const MAX_CAPTURE_CONCURRENCY = 3;
24
+ const DEFAULT_CAPTURE_TIMEOUT_MS = 8000;
25
+ const USER_AGENT = 'Archify/2.15 brand-preview';
26
+
27
+ function lookupForms(value) {
28
+ const raw = String(value ?? '').trim().toLocaleLowerCase('en-US');
29
+ if (!raw) return [];
30
+ const dashed = raw.replace(/[\s_]+/g, '-');
31
+ const compact = raw.replace(/[\s_.-]+/g, '');
32
+ return [...new Set([raw, dashed, compact])];
33
+ }
34
+
35
+ for (const mark of BRAND_MARKS) {
36
+ for (const value of [mark.id, mark.title, ...mark.aliases]) {
37
+ for (const form of lookupForms(value)) {
38
+ if (!MARK_BY_LOOKUP.has(form)) MARK_BY_LOOKUP.set(form, mark);
39
+ }
40
+ }
41
+ for (const domain of mark.domains) MARK_BY_DOMAIN.set(domain, mark);
42
+ }
43
+
44
+ function asUrl(value) {
45
+ try {
46
+ const url = new URL(String(value));
47
+ return ['https:', 'http:'].includes(url.protocol) ? url : null;
48
+ } catch {
49
+ return null;
50
+ }
51
+ }
52
+
53
+ function domainMark(hostname) {
54
+ const host = hostname.toLocaleLowerCase('en-US').replace(/\.$/, '');
55
+ const candidates = [...MARK_BY_DOMAIN.entries()]
56
+ .filter(([domain]) => host === domain || host.endsWith(`.${domain}`))
57
+ .sort(([left], [right]) => right.length - left.length);
58
+ return candidates[0]?.[1] || null;
59
+ }
60
+
61
+ export function findBrandMark(value) {
62
+ const url = asUrl(value);
63
+ if (url) return domainMark(url.hostname);
64
+ for (const form of lookupForms(value)) {
65
+ const mark = MARK_BY_LOOKUP.get(form);
66
+ if (mark) return mark;
67
+ }
68
+ return null;
69
+ }
70
+
71
+ export function listBrandMarks(query = '') {
72
+ const needle = String(query).trim().toLocaleLowerCase('en-US');
73
+ return BRAND_MARKS.filter((mark) => {
74
+ if (!needle) return true;
75
+ return [mark.id, mark.title, mark.category, ...mark.aliases, ...mark.domains]
76
+ .some((value) => String(value).toLocaleLowerCase('en-US').includes(needle));
77
+ }).map(({ path, ...mark }) => mark);
78
+ }
79
+
80
+ function ipv4Private(address) {
81
+ const parts = address.split('.').map(Number);
82
+ if (parts.length !== 4 || parts.some((part) => !Number.isInteger(part) || part < 0 || part > 255)) return true;
83
+ const [a, b, c] = parts;
84
+ return a === 0 || a === 10 || a === 127 || a >= 224
85
+ || (a === 100 && b >= 64 && b <= 127)
86
+ || (a === 169 && b === 254)
87
+ || (a === 172 && b >= 16 && b <= 31)
88
+ || (a === 192 && b === 0 && (c === 0 || c === 2))
89
+ || (a === 192 && b === 88 && c === 99)
90
+ || (a === 192 && b === 168)
91
+ || (a === 198 && (b === 18 || b === 19))
92
+ || (a === 198 && b === 51 && c === 100)
93
+ || (a === 203 && b === 0 && c === 113);
94
+ }
95
+
96
+ function ipv6Private(address) {
97
+ const normalized = address.toLocaleLowerCase('en-US').split('%')[0];
98
+ if (normalized === '::' || normalized === '::1') return true;
99
+ if (normalized.startsWith('fc') || normalized.startsWith('fd') || normalized.startsWith('ff') || /^fe[89ab]/.test(normalized)) return true;
100
+ if (normalized.startsWith('64:ff9b:') || normalized.startsWith('100:')
101
+ || normalized.startsWith('2001:db8:') || normalized.startsWith('2002:')) return true;
102
+ const mappedDotted = normalized.match(/::ffff:(\d+\.\d+\.\d+\.\d+)$/);
103
+ if (mappedDotted) return ipv4Private(mappedDotted[1]);
104
+ const mappedHex = normalized.match(/::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/);
105
+ if (mappedHex) {
106
+ const high = Number.parseInt(mappedHex[1], 16);
107
+ const low = Number.parseInt(mappedHex[2], 16);
108
+ return ipv4Private(`${high >>> 8}.${high & 255}.${low >>> 8}.${low & 255}`);
109
+ }
110
+ const compatibleHex = normalized.match(/^::([0-9a-f]{1,4}):([0-9a-f]{1,4})$/);
111
+ if (compatibleHex) {
112
+ const high = Number.parseInt(compatibleHex[1], 16);
113
+ const low = Number.parseInt(compatibleHex[2], 16);
114
+ return ipv4Private(`${high >>> 8}.${high & 255}.${low >>> 8}.${low & 255}`);
115
+ }
116
+ return false;
117
+ }
118
+
119
+ export function isPrivateBrandAddress(address) {
120
+ const family = net.isIP(address);
121
+ return family === 4 ? ipv4Private(address) : (family === 6 ? ipv6Private(address) : true);
122
+ }
123
+
124
+ function validateUrlShape(url, allowPrivate = process.env.ARCHIFY_BRAND_ALLOW_PRIVATE === '1') {
125
+ if (!['https:', 'http:'].includes(url.protocol)) throw new Error('only HTTP(S) brand links are supported');
126
+ if (url.username || url.password) throw new Error('brand links cannot contain credentials');
127
+ const expectedPort = url.protocol === 'https:' ? '443' : '80';
128
+ if (!allowPrivate && url.port && url.port !== expectedPort) {
129
+ throw new Error('brand links must use a standard web port');
130
+ }
131
+ const host = url.hostname.toLocaleLowerCase('en-US').replace(/\.$/, '').replace(/^\[|\]$/g, '');
132
+ if (!allowPrivate && (host === 'localhost' || host.endsWith('.localhost') || host.endsWith('.local'))) {
133
+ throw new Error('private brand links are not fetched');
134
+ }
135
+ return host;
136
+ }
137
+
138
+ function beforeDeadline(promise, deadline) {
139
+ const remaining = deadline - Date.now();
140
+ if (remaining <= 0) return Promise.reject(new Error('brand capture timed out'));
141
+ return new Promise((resolve, reject) => {
142
+ const timer = setTimeout(() => reject(new Error('brand capture timed out')), remaining);
143
+ timer.unref?.();
144
+ promise.then(
145
+ (value) => { clearTimeout(timer); resolve(value); },
146
+ (error) => { clearTimeout(timer); reject(error); },
147
+ );
148
+ });
149
+ }
150
+
151
+ async function resolveRequestTarget(url, deadline) {
152
+ const allowPrivate = process.env.ARCHIFY_BRAND_ALLOW_PRIVATE === '1';
153
+ const host = validateUrlShape(url, allowPrivate);
154
+ const directFamily = net.isIP(host);
155
+ const addresses = directFamily
156
+ ? [{ address: host, family: directFamily }]
157
+ : await beforeDeadline(lookup(host, { all: true, verbatim: true }), deadline);
158
+ if (!addresses.length || (!allowPrivate && addresses.some(({ address }) => isPrivateBrandAddress(address)))) {
159
+ throw new Error('private brand links are not fetched');
160
+ }
161
+ return addresses[0];
162
+ }
163
+
164
+ function timeoutSignal(milliseconds) {
165
+ if (typeof AbortSignal.timeout === 'function') return AbortSignal.timeout(milliseconds);
166
+ const controller = new AbortController();
167
+ const timer = setTimeout(() => controller.abort(), milliseconds);
168
+ timer.unref?.();
169
+ return controller.signal;
170
+ }
171
+
172
+ function captureTimeoutMilliseconds() {
173
+ const configured = Number(process.env.ARCHIFY_BRAND_CAPTURE_TIMEOUT_MS);
174
+ if (!Number.isFinite(configured)) return DEFAULT_CAPTURE_TIMEOUT_MS;
175
+ return Math.max(100, Math.min(30000, Math.round(configured)));
176
+ }
177
+
178
+ function requestPinned(url, accept, target, deadline) {
179
+ return new Promise((resolve, reject) => {
180
+ const transport = url.protocol === 'https:' ? https : http;
181
+ const request = transport.request(url, {
182
+ method: 'GET',
183
+ signal: timeoutSignal(Math.max(1, Math.min(4500, deadline - Date.now()))),
184
+ headers: { accept, 'user-agent': USER_AGENT },
185
+ // Reuse the exact public address that passed validation. This closes the
186
+ // DNS-rebinding gap between checking a hostname and opening its socket.
187
+ lookup(_hostname, options, callback) {
188
+ if (options?.all) callback(null, [target]);
189
+ else callback(null, target.address, target.family);
190
+ },
191
+ }, (response) => {
192
+ const status = response.statusCode || 0;
193
+ resolve({
194
+ status,
195
+ ok: status >= 200 && status < 300,
196
+ headers: {
197
+ get(name) {
198
+ const value = response.headers[String(name).toLocaleLowerCase('en-US')];
199
+ return Array.isArray(value) ? value.join(', ') : (value ?? null);
200
+ },
201
+ },
202
+ body: response,
203
+ });
204
+ });
205
+ request.on('error', reject);
206
+ request.end();
207
+ });
208
+ }
209
+
210
+ async function checkedFetch(input, accept, deadline) {
211
+ let current = new URL(input);
212
+ for (let redirects = 0; redirects <= 3; redirects += 1) {
213
+ if (Date.now() >= deadline) throw new Error('brand capture timed out');
214
+ const target = await resolveRequestTarget(current, deadline);
215
+ const response = await requestPinned(current, accept, target, deadline);
216
+ if ([301, 302, 303, 307, 308].includes(response.status)) {
217
+ const location = response.headers.get('location');
218
+ response.body.resume();
219
+ if (!location || redirects === 3) throw new Error('brand link redirected too many times');
220
+ current = new URL(location, current);
221
+ continue;
222
+ }
223
+ if (!response.ok) {
224
+ response.body.resume();
225
+ throw new Error(`brand link returned HTTP ${response.status}`);
226
+ }
227
+ return { response, finalUrl: current };
228
+ }
229
+ throw new Error('brand link redirected too many times');
230
+ }
231
+
232
+ async function readLimited(response, maximum) {
233
+ const declared = Number(response.headers.get('content-length'));
234
+ if (Number.isFinite(declared) && declared > maximum) {
235
+ response.body?.destroy?.();
236
+ throw new Error('brand asset is too large');
237
+ }
238
+ if (response.body && typeof response.body[Symbol.asyncIterator] === 'function') {
239
+ const chunks = [];
240
+ let total = 0;
241
+ for await (const value of response.body) {
242
+ total += value.byteLength;
243
+ if (total > maximum) {
244
+ response.body.destroy?.();
245
+ throw new Error('brand asset is too large');
246
+ }
247
+ chunks.push(Buffer.from(value));
248
+ }
249
+ return Buffer.concat(chunks, total);
250
+ }
251
+ if (!response.body?.getReader) {
252
+ const buffer = Buffer.from(await response.arrayBuffer());
253
+ if (buffer.length > maximum) throw new Error('brand asset is too large');
254
+ return buffer;
255
+ }
256
+ const reader = response.body.getReader();
257
+ const chunks = [];
258
+ let total = 0;
259
+ while (true) {
260
+ const { done, value } = await reader.read();
261
+ if (done) break;
262
+ total += value.byteLength;
263
+ if (total > maximum) {
264
+ await reader.cancel();
265
+ throw new Error('brand asset is too large');
266
+ }
267
+ chunks.push(Buffer.from(value));
268
+ }
269
+ return Buffer.concat(chunks, total);
270
+ }
271
+
272
+ function attribute(tag, name) {
273
+ const match = tag.match(new RegExp(`\\b${name}\\s*=\\s*(?:"([^"]*)"|'([^']*)'|([^\\s>]+))`, 'i'));
274
+ return match ? (match[1] ?? match[2] ?? match[3] ?? '') : '';
275
+ }
276
+
277
+ function iconCandidates(html, pageUrl) {
278
+ const candidates = [];
279
+ for (const match of html.matchAll(/<link\b[^>]*>/gi)) {
280
+ const tag = match[0];
281
+ const rel = attribute(tag, 'rel').toLocaleLowerCase('en-US').split(/\s+/);
282
+ if (!rel.some((value) => value === 'icon' || value === 'apple-touch-icon' || value === 'mask-icon')) continue;
283
+ const href = attribute(tag, 'href');
284
+ if (!href) continue;
285
+ try {
286
+ const url = new URL(href, pageUrl);
287
+ if (!['https:', 'http:'].includes(url.protocol)) continue;
288
+ const type = attribute(tag, 'type').toLocaleLowerCase('en-US');
289
+ const sizes = attribute(tag, 'sizes');
290
+ const area = [...sizes.matchAll(/(\d+)x(\d+)/gi)]
291
+ .reduce((best, size) => Math.max(best, Number(size[1]) * Number(size[2])), 0);
292
+ const score = (type.includes('svg') || /\.svg(?:$|[?#])/i.test(url.href) ? 1000000 : 0)
293
+ + (rel.includes('apple-touch-icon') ? 500000 : 0)
294
+ + area;
295
+ candidates.push({ url, score });
296
+ } catch {
297
+ // A malformed icon candidate is ignored; the deterministic fallback remains available.
298
+ }
299
+ }
300
+ candidates.sort((left, right) => right.score - left.score);
301
+ const fallback = new URL('/favicon.ico', pageUrl);
302
+ const unique = new Map(candidates.map((candidate) => [candidate.url.href, candidate]));
303
+ unique.delete(fallback.href);
304
+ return [...unique.values()].slice(0, 5).concat({ url: fallback, score: -1 });
305
+ }
306
+
307
+ async function imageData(response) {
308
+ const contentType = (response.headers.get('content-type') || '').split(';')[0].trim().toLocaleLowerCase('en-US');
309
+ const allowed = new Set([
310
+ 'image/png',
311
+ 'image/jpeg',
312
+ 'image/webp',
313
+ 'image/x-icon',
314
+ 'image/vnd.microsoft.icon',
315
+ ]);
316
+ if (!allowed.has(contentType)) {
317
+ response.body?.destroy?.();
318
+ throw new Error(`unsupported brand image type ${contentType || 'unknown'}`);
319
+ }
320
+ const buffer = await readLimited(response, MAX_IMAGE_BYTES);
321
+ const signatureMatches = contentType === 'image/png'
322
+ ? buffer.length >= 45
323
+ && buffer.subarray(0, 8).equals(Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]))
324
+ && buffer.readUInt32BE(8) === 13
325
+ && buffer.toString('ascii', 12, 16) === 'IHDR'
326
+ && buffer.readUInt32BE(16) > 0
327
+ && buffer.readUInt32BE(20) > 0
328
+ && buffer.toString('ascii', buffer.length - 8, buffer.length - 4) === 'IEND'
329
+ : (contentType === 'image/jpeg'
330
+ ? buffer.length >= 20
331
+ && buffer[0] === 0xff && buffer[1] === 0xd8 && buffer[2] === 0xff
332
+ && buffer.at(-2) === 0xff && buffer.at(-1) === 0xd9
333
+ : (contentType === 'image/webp'
334
+ ? buffer.length >= 16
335
+ && buffer.toString('ascii', 0, 4) === 'RIFF'
336
+ && buffer.toString('ascii', 8, 12) === 'WEBP'
337
+ && buffer.readUInt32LE(4) + 8 <= buffer.length
338
+ : buffer.length >= 22
339
+ && buffer[0] === 0 && buffer[1] === 0 && buffer[2] === 1 && buffer[3] === 0
340
+ && buffer.readUInt16LE(4) > 0
341
+ && 6 + buffer.readUInt16LE(4) * 16 <= buffer.length));
342
+ if (!signatureMatches) throw new Error(`brand asset bytes do not match ${contentType}`);
343
+ return {
344
+ dataUrl: `data:${contentType};base64,${buffer.toString('base64')}`,
345
+ sha256: createHash('sha256').update(buffer).digest('hex'),
346
+ contentType,
347
+ };
348
+ }
349
+
350
+ async function captureRemoteBrand(value, deadline = Date.now() + captureTimeoutMilliseconds()) {
351
+ const sourceUrl = new URL(value);
352
+ const fallback = (reason) => ({
353
+ id: sourceUrl.hostname,
354
+ title: sourceUrl.hostname,
355
+ category: 'link',
356
+ kind: 'fallback',
357
+ status: 'unavailable',
358
+ sourceUrl: sourceUrl.href,
359
+ reason,
360
+ });
361
+ try {
362
+ const page = await checkedFetch(sourceUrl, 'text/html,application/xhtml+xml,image/*;q=0.8', deadline);
363
+ const pageType = (page.response.headers.get('content-type') || '').toLocaleLowerCase('en-US');
364
+ if (pageType.startsWith('image/')) {
365
+ const image = await imageData(page.response);
366
+ return {
367
+ id: sourceUrl.hostname,
368
+ title: sourceUrl.hostname,
369
+ category: 'link',
370
+ kind: 'remote',
371
+ status: 'captured',
372
+ sourceUrl: sourceUrl.href,
373
+ resolvedUrl: page.finalUrl.href,
374
+ ...image,
375
+ };
376
+ }
377
+ if (!pageType.includes('text/html') && !pageType.includes('application/xhtml+xml')) {
378
+ page.response.body?.destroy?.();
379
+ return fallback('linked page is not HTML');
380
+ }
381
+ const html = (await readLimited(page.response, MAX_HTML_BYTES)).toString('utf8');
382
+ const iconErrors = [];
383
+ for (const candidate of iconCandidates(html, page.finalUrl)) {
384
+ try {
385
+ const fetched = await checkedFetch(candidate.url, 'image/*', deadline);
386
+ const image = await imageData(fetched.response);
387
+ return {
388
+ id: sourceUrl.hostname,
389
+ title: sourceUrl.hostname,
390
+ category: 'link',
391
+ kind: 'remote',
392
+ status: 'captured',
393
+ sourceUrl: sourceUrl.href,
394
+ resolvedUrl: fetched.finalUrl.href,
395
+ ...image,
396
+ };
397
+ } catch (error) {
398
+ iconErrors.push(error);
399
+ // Try the next declared favicon before using the generic link mark.
400
+ }
401
+ }
402
+ const usefulError = iconErrors.find((error) => /unsupported brand image type/i.test(error?.message))
403
+ || iconErrors.at(-1);
404
+ return fallback(usefulError?.message || 'no usable site icon was found');
405
+ } catch (error) {
406
+ return fallback(error.message);
407
+ }
408
+ }
409
+
410
+ export async function captureBrandReference(value) {
411
+ const url = asUrl(value);
412
+ if (!url) throw new Error('brand capture requires one HTTP(S) URL');
413
+ validateUrlShape(url);
414
+ const preset = findBrandMark(url.href);
415
+ if (preset) return { brand: preset.id, resolved: { ...preset, kind: 'preset', status: 'preset' } };
416
+ const resolved = await captureRemoteBrand(url.href);
417
+ if (resolved.status !== 'captured' || !resolved.sha256) {
418
+ throw new Error(`brand capture failed: ${resolved.reason || 'no usable site icon was found'}`);
419
+ }
420
+ return {
421
+ brand: { url: url.href, sha256: resolved.sha256 },
422
+ resolved,
423
+ };
424
+ }
425
+
426
+ function remoteBrand(value, cache, deadline) {
427
+ const key = new URL(value).href;
428
+ if (!cache.has(key)) cache.set(key, captureRemoteBrand(key, deadline));
429
+ return cache.get(key);
430
+ }
431
+
432
+ function suggestions(value) {
433
+ const needle = lookupForms(value)[0] || '';
434
+ return BRAND_MARKS.map((mark) => ({
435
+ id: mark.id,
436
+ score: lookupForms(mark.id).some((form) => form.includes(needle) || needle.includes(form)) ? 0 : 1,
437
+ })).sort((left, right) => left.score - right.score || left.id.localeCompare(right.id))
438
+ .slice(0, 5)
439
+ .map((entry) => entry.id);
440
+ }
441
+
442
+ async function mapConcurrent(values, limit, visit) {
443
+ let cursor = 0;
444
+ const workers = Array.from({ length: Math.min(limit, values.length) }, async () => {
445
+ while (cursor < values.length) {
446
+ const index = cursor;
447
+ cursor += 1;
448
+ await visit(values[index], index);
449
+ }
450
+ });
451
+ await Promise.all(workers);
452
+ }
453
+
454
+ export async function prepareDiagramBrandMarks(diagramType, diagram) {
455
+ const collection = COLLECTIONS[diagramType];
456
+ const nodes = collection && Array.isArray(diagram[collection]) ? diagram[collection] : [];
457
+ const unknown = [];
458
+ const remoteByUrl = new Map();
459
+ const deadline = Date.now() + captureTimeoutMilliseconds();
460
+ await mapConcurrent(nodes, MAX_CAPTURE_CONCURRENCY, async (node, index) => {
461
+ if (!node.brand) return;
462
+ if (typeof node.brand === 'object') {
463
+ const url = asUrl(node.brand.url);
464
+ const resolved = url ? await remoteBrand(url.href, remoteByUrl, deadline) : null;
465
+ if (!resolved || resolved.status !== 'captured') {
466
+ unknown.push(`/${collection}/${index}/brand could not reproduce the pinned capture: ${resolved?.reason || 'invalid URL'}`);
467
+ return;
468
+ }
469
+ if (resolved.sha256 !== node.brand.sha256) {
470
+ unknown.push(`/${collection}/${index}/brand digest changed: expected ${node.brand.sha256}, received ${resolved.sha256}`);
471
+ return;
472
+ }
473
+ node[RESOLVED_MARK] = resolved;
474
+ RESOLVED_BY_NODE.set(node, resolved);
475
+ return;
476
+ }
477
+ const preset = findBrandMark(node.brand);
478
+ if (preset) {
479
+ const resolved = { ...preset, kind: 'preset', status: 'preset', sourceUrl: preset.provenance.source };
480
+ node[RESOLVED_MARK] = resolved;
481
+ RESOLVED_BY_NODE.set(node, resolved);
482
+ return;
483
+ }
484
+ const url = asUrl(node.brand);
485
+ if (url) {
486
+ unknown.push(`/${collection}/${index}/brand ${JSON.stringify(node.brand)} is an unpinned URL; capture it first with \`archify brands capture ${url.href} --json\``);
487
+ return;
488
+ }
489
+ unknown.push(`/${collection}/${index}/brand ${JSON.stringify(node.brand)} is not a built-in brand; closest IDs: ${suggestions(node.brand).join(', ')}`);
490
+ });
491
+ if (unknown.length) {
492
+ throwDiagnosticError(`Brand mark validation failed:\n- ${unknown.join('\n- ')}`, unknown.map((message) => ({
493
+ code: message.includes('is an unpinned URL') ? 'brand/unpinned-url'
494
+ : (message.includes('digest changed') ? 'brand/digest-mismatch'
495
+ : (message.includes('could not reproduce') ? 'brand/capture-unavailable' : 'brand/unknown')),
496
+ severity: 'error',
497
+ message,
498
+ subject: { diagramType, collection },
499
+ evidence: {},
500
+ supportedFixes: message.includes('is an unpinned URL')
501
+ ? ['run `archify brands capture <url> --json` and author the returned digest-pinned brand object']
502
+ : ['choose an ID from `archify brands`', 'run `archify brands capture <url> --json` for an unknown official site'],
503
+ })));
504
+ }
505
+ }
506
+
507
+ export function brandMarkFor(node) {
508
+ return node?.[RESOLVED_MARK] || RESOLVED_BY_NODE.get(node) || null;
509
+ }
510
+
511
+ export function brandMetadataFor(node) {
512
+ const mark = brandMarkFor(node);
513
+ return mark ? {
514
+ brand: mark.title,
515
+ brandId: mark.id,
516
+ brandStatus: mark.status,
517
+ brandSource: mark.sourceUrl,
518
+ } : {};
519
+ }
520
+
521
+ export function brandLabelFitWidth(node, width) {
522
+ return brandMarkFor(node) ? Math.max(1, width - 48) : width;
523
+ }
524
+
525
+ export function brandTopRailProblem(node, width, minimumFontSize, subject = 'Node') {
526
+ if (!brandMarkFor(node)) return null;
527
+ const available = width - 48;
528
+ const required = textUnits(node.label) * minimumFontSize * 0.6;
529
+ if (available >= required) return null;
530
+ return `${subject} "${node.id}" brand top rail leaves ${Math.max(0, available)}px for its label, but `
531
+ + `"${node.label}" needs ~${Math.ceil(required)}px at the ${minimumFontSize}px legible minimum — widen the node or shorten the label.`;
532
+ }
533
+
534
+ function markAttrs(mark) {
535
+ return [
536
+ `data-brand-mark="${esc(mark.id)}"`,
537
+ `data-brand-title="${esc(mark.title)}"`,
538
+ `data-brand-status="${esc(mark.status)}"`,
539
+ mark.sourceUrl ? `data-brand-source="${esc(mark.sourceUrl)}"` : '',
540
+ mark.sha256 ? `data-brand-sha256="${esc(mark.sha256)}"` : '',
541
+ ].filter(Boolean).join(' ');
542
+ }
543
+
544
+ export function renderBrandMark(node, { x, y, size = 16 } = {}) {
545
+ const mark = brandMarkFor(node);
546
+ if (!mark) return '';
547
+ const inset = 3;
548
+ let content;
549
+ if (mark.kind === 'preset') {
550
+ const scale = (size - inset * 2) / mark.viewBox;
551
+ content = `<path d="${esc(mark.path)}" transform="translate(${inset} ${inset}) scale(${scale})" fill="#${esc(mark.hex)}"/>`;
552
+ } else if (mark.kind === 'remote') {
553
+ content = `<image href="${esc(mark.dataUrl)}" x="${inset}" y="${inset}" width="${size - inset * 2}" height="${size - inset * 2}" preserveAspectRatio="xMidYMid meet"/>`;
554
+ } else {
555
+ const scale = size / 20;
556
+ content = `<g transform="scale(${scale})" class="brand-mark-fallback"><circle cx="10" cy="10" r="5.2"/><path d="M4.8 10h10.4M10 4.8c1.6 1.6 2.4 3.3 2.4 5.2s-.8 3.6-2.4 5.2M10 4.8C8.4 6.4 7.6 8.1 7.6 10s.8 3.6 2.4 5.2"/></g>`;
557
+ }
558
+ return `<g aria-hidden="true" ${markAttrs(mark)} class="brand-mark" transform="translate(${x} ${y})">
559
+ <rect width="${size}" height="${size}" rx="4" class="brand-mark-badge"/>
560
+ ${content}
561
+ <rect width="${size}" height="${size}" rx="4" class="brand-mark-frame"/>
562
+ </g>`;
563
+ }