@xgent-ai/skills 0.3.0 → 0.4.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 (625) hide show
  1. package/README.md +94 -10
  2. package/bin/xgent-skills.js +55 -9
  3. package/package.json +1 -1
  4. package/skills/agi-mode/SKILL.md +225 -0
  5. package/skills/agi-mode/evals/baseline-coverage.md +96 -0
  6. package/skills/agi-mode/evals/scenarios.md +331 -0
  7. package/skills/agi-mode/evals/test_check_evidence.py +141 -0
  8. package/skills/agi-mode/playbooks/arena.md +47 -0
  9. package/skills/agi-mode/playbooks/authoring-a-skill.md +26 -0
  10. package/skills/agi-mode/playbooks/autonomous-run.md +39 -0
  11. package/skills/agi-mode/playbooks/bug-fix.md +27 -0
  12. package/skills/agi-mode/playbooks/design-prototype.md +41 -0
  13. package/skills/agi-mode/playbooks/eval.md +72 -0
  14. package/skills/agi-mode/playbooks/feature.md +26 -0
  15. package/skills/agi-mode/playbooks/forensics.md +31 -0
  16. package/skills/agi-mode/playbooks/hillclimb.md +73 -0
  17. package/skills/agi-mode/playbooks/investigation.md +29 -0
  18. package/skills/agi-mode/playbooks/migration-refactoring.md +27 -0
  19. package/skills/agi-mode/playbooks/optimization.md +27 -0
  20. package/skills/agi-mode/playbooks/pr-lifecycle.md +38 -0
  21. package/skills/agi-mode/playbooks/program.md +57 -0
  22. package/skills/agi-mode/playbooks/reflection.md +41 -0
  23. package/skills/agi-mode/playbooks/resource-cleanup.md +24 -0
  24. package/skills/agi-mode/playbooks/review.md +27 -0
  25. package/skills/agi-mode/playbooks/session-handoff.md +37 -0
  26. package/skills/agi-mode/playbooks/shipping.md +35 -0
  27. package/skills/agi-mode/playbooks/ui-delivery.md +34 -0
  28. package/skills/agi-mode/playbooks/unblock.md +54 -0
  29. package/skills/agi-mode/principles/autonomous-decisions.md +21 -0
  30. package/skills/agi-mode/principles/behavioral-tests.md +21 -0
  31. package/skills/agi-mode/principles/boundary-discipline.md +21 -0
  32. package/skills/agi-mode/principles/bounded-convergence.md +21 -0
  33. package/skills/agi-mode/principles/build-leverage.md +21 -0
  34. package/skills/agi-mode/principles/challenge-premises.md +21 -0
  35. package/skills/agi-mode/principles/complete-migrations.md +21 -0
  36. package/skills/agi-mode/principles/context-as-state.md +21 -0
  37. package/skills/agi-mode/principles/critical-path-throughput.md +21 -0
  38. package/skills/agi-mode/principles/domain-models-and-types.md +23 -0
  39. package/skills/agi-mode/principles/evidence-lifetime.md +21 -0
  40. package/skills/agi-mode/principles/experience-first.md +21 -0
  41. package/skills/agi-mode/principles/explore-alternatives.md +21 -0
  42. package/skills/agi-mode/principles/falsifiable-verification.md +21 -0
  43. package/skills/agi-mode/principles/foundations-first.md +21 -0
  44. package/skills/agi-mode/principles/idempotent-effects.md +21 -0
  45. package/skills/agi-mode/principles/information-first.md +21 -0
  46. package/skills/agi-mode/principles/minimize-complexity.md +21 -0
  47. package/skills/agi-mode/principles/outcome-ownership.md +21 -0
  48. package/skills/agi-mode/principles/prove-real-outcomes.md +21 -0
  49. package/skills/agi-mode/principles/redesign-from-constraints.md +21 -0
  50. package/skills/agi-mode/principles/root-cause.md +21 -0
  51. package/skills/agi-mode/principles/state-ownership.md +21 -0
  52. package/skills/agi-mode/principles/structural-learning.md +21 -0
  53. package/skills/agi-mode/principles/verifiable-units.md +21 -0
  54. package/skills/agi-mode/references/continuity.md +75 -0
  55. package/skills/agi-mode/references/eval-protocol.md +71 -0
  56. package/skills/agi-mode/references/evidence-contract.md +57 -0
  57. package/skills/agi-mode/references/evolution-evidence.md +71 -0
  58. package/skills/agi-mode/references/experiments.md +82 -0
  59. package/skills/agi-mode/references/reflection/divergent-reviewer.md +45 -0
  60. package/skills/agi-mode/references/reflection/judgment-reviewer.md +44 -0
  61. package/skills/agi-mode/references/reflection/synthesizer.md +39 -0
  62. package/skills/agi-mode/references/reflection/tooling-reviewer.md +57 -0
  63. package/skills/agi-mode/references/skill-evolution.md +50 -0
  64. package/skills/agi-mode/scripts/check_evidence.py +147 -0
  65. package/skills/apply-code-review/SKILL.md +53 -0
  66. package/skills/apply-code-review/agents/openai.yaml +4 -0
  67. package/skills/apply-code-review/references/record-contract.md +77 -0
  68. package/skills/apply-doc-review/SKILL.md +79 -0
  69. package/skills/apply-doc-review/agents/openai.yaml +4 -0
  70. package/skills/apply-doc-review/references/disposition-contract.md +57 -0
  71. package/skills/archify/LICENSE +22 -0
  72. package/skills/archify/SKILL.md +137 -0
  73. package/skills/archify/THIRD_PARTY_NOTICES.md +69 -0
  74. package/skills/archify/assets/JetBrainsMono-OFL.txt +93 -0
  75. package/skills/archify/assets/template.html +14937 -0
  76. package/skills/archify/bin/archify.mjs +2139 -0
  77. package/skills/archify/bin/open-artifact.mjs +86 -0
  78. package/skills/archify/bin/preview.mjs +653 -0
  79. package/skills/archify/bin/visual-check.mjs +829 -0
  80. package/skills/archify/brand-marks/README.md +31 -0
  81. package/skills/archify/brand-marks/catalog.json +131 -0
  82. package/skills/archify/delta/architecture-delta.mjs +1232 -0
  83. package/skills/archify/examples/agent-run.lifecycle.json +60 -0
  84. package/skills/archify/examples/agent-tool-call.workflow.json +94 -0
  85. package/skills/archify/examples/async-job-roundtrip.sequence.json +61 -0
  86. package/skills/archify/examples/brand-aware-delivery.architecture.json +47 -0
  87. package/skills/archify/examples/cache-miss-request.sequence.json +82 -0
  88. package/skills/archify/examples/checkout-platform.base.architecture.json +31 -0
  89. package/skills/archify/examples/checkout-platform.head.architecture.json +31 -0
  90. package/skills/archify/examples/dataflow-product-analytics.html +15048 -0
  91. package/skills/archify/examples/deployment-release.lifecycle.json +49 -0
  92. package/skills/archify/examples/event-stream.dataflow.json +57 -0
  93. package/skills/archify/examples/incident-response.workflow.json +64 -0
  94. package/skills/archify/examples/lifecycle-agent-run.html +14983 -0
  95. package/skills/archify/examples/product-analytics.dataflow.json +76 -0
  96. package/skills/archify/examples/production-deployment.architecture.json +71 -0
  97. package/skills/archify/examples/release-delivery.workflow.json +62 -0
  98. package/skills/archify/examples/sequence-cache-miss-request.html +15063 -0
  99. package/skills/archify/examples/web-app-rendered.html +15012 -0
  100. package/skills/archify/examples/web-app.architecture.json +46 -0
  101. package/skills/archify/examples/workflow-agent-tool-call-rendered.html +15054 -0
  102. package/skills/archify/migrations/workflow-v2.mjs +279 -0
  103. package/skills/archify/package-lock.json +149 -0
  104. package/skills/archify/package.json +39 -0
  105. package/skills/archify/recipes/scenarios.mjs +391 -0
  106. package/skills/archify/references/authoring-contract.md +247 -0
  107. package/skills/archify/references/brand-marks.md +65 -0
  108. package/skills/archify/references/delivery-contract.md +138 -0
  109. package/skills/archify/references/viewer-runtime.md +45 -0
  110. package/skills/archify/renderers/architecture/grid.mjs +62 -0
  111. package/skills/archify/renderers/architecture/render-architecture.mjs +1078 -0
  112. package/skills/archify/renderers/dataflow/README.md +104 -0
  113. package/skills/archify/renderers/dataflow/render-dataflow.mjs +483 -0
  114. package/skills/archify/renderers/lifecycle/README.md +115 -0
  115. package/skills/archify/renderers/lifecycle/render-lifecycle.mjs +561 -0
  116. package/skills/archify/renderers/sequence/README.md +114 -0
  117. package/skills/archify/renderers/sequence/render-sequence.mjs +464 -0
  118. package/skills/archify/renderers/shared/brand-marks.mjs +563 -0
  119. package/skills/archify/renderers/shared/cli.mjs +218 -0
  120. package/skills/archify/renderers/shared/desktop-readability.mjs +26 -0
  121. package/skills/archify/renderers/shared/diagnostics.mjs +160 -0
  122. package/skills/archify/renderers/shared/engineering-profiles.mjs +157 -0
  123. package/skills/archify/renderers/shared/generated-brand-marks.mjs +2003 -0
  124. package/skills/archify/renderers/shared/generated-validators.mjs +13 -0
  125. package/skills/archify/renderers/shared/geometry.mjs +1423 -0
  126. package/skills/archify/renderers/shared/i18n.mjs +595 -0
  127. package/skills/archify/renderers/shared/layout-report.mjs +40 -0
  128. package/skills/archify/renderers/shared/legend.mjs +217 -0
  129. package/skills/archify/renderers/shared/output-path.mjs +340 -0
  130. package/skills/archify/renderers/shared/repository-evidence.mjs +239 -0
  131. package/skills/archify/renderers/shared/repository-location.mjs +58 -0
  132. package/skills/archify/renderers/shared/text-fit.mjs +49 -0
  133. package/skills/archify/renderers/shared/utils.mjs +232 -0
  134. package/skills/archify/renderers/shared/validator.mjs +86 -0
  135. package/skills/archify/renderers/workflow/README.md +223 -0
  136. package/skills/archify/renderers/workflow/render-workflow.mjs +35 -0
  137. package/skills/archify/renderers/workflow/workflow-compiler.mjs +4400 -0
  138. package/skills/archify/renderers/workflow/workflow-migration-geometry.mjs +144 -0
  139. package/skills/archify/schemas/README.md +211 -0
  140. package/skills/archify/schemas/architecture.schema.json +178 -0
  141. package/skills/archify/schemas/common.schema.json +115 -0
  142. package/skills/archify/schemas/dataflow.schema.json +243 -0
  143. package/skills/archify/schemas/lifecycle.schema.json +266 -0
  144. package/skills/archify/schemas/sequence.schema.json +223 -0
  145. package/skills/archify/schemas/workflow.schema.json +428 -0
  146. package/skills/archify/scripts/check-render-output.mjs +916 -0
  147. package/skills/archify/scripts/check-update.mjs +1667 -0
  148. package/skills/archify/scripts/generate-brand-marks.mjs +141 -0
  149. package/skills/archify/scripts/generate-validators.mjs +66 -0
  150. package/skills/archify/scripts/render-examples.mjs +26 -0
  151. package/skills/archify/scripts/update-contract.mjs +182 -0
  152. package/skills/archify/skill-release.json +10 -0
  153. package/skills/archify/test/adaptive-reader-layout.test.mjs +86 -0
  154. package/skills/archify/test/animation.test.mjs +179 -0
  155. package/skills/archify/test/architecture-compare-recovery.test.mjs +157 -0
  156. package/skills/archify/test/architecture-delta-markers.test.mjs +137 -0
  157. package/skills/archify/test/architecture-delta.test.mjs +705 -0
  158. package/skills/archify/test/artifact-receipt-flush.test.mjs +126 -0
  159. package/skills/archify/test/authored-reachability.test.mjs +95 -0
  160. package/skills/archify/test/authoring-safety-contract.test.mjs +54 -0
  161. package/skills/archify/test/automatic-port-spread.test.mjs +376 -0
  162. package/skills/archify/test/base-input-compatibility.test.mjs +42 -0
  163. package/skills/archify/test/brand-marks.test.mjs +678 -0
  164. package/skills/archify/test/chapter-delta-preview.test.mjs +157 -0
  165. package/skills/archify/test/chapter-handoff.test.mjs +97 -0
  166. package/skills/archify/test/chapter-rail.test.mjs +86 -0
  167. package/skills/archify/test/checkout-line-endings.test.mjs +72 -0
  168. package/skills/archify/test/ci-scope.test.mjs +59 -0
  169. package/skills/archify/test/clean-skill-staging.test.mjs +440 -0
  170. package/skills/archify/test/cli-output-types.test.mjs +201 -0
  171. package/skills/archify/test/cli.test.mjs +986 -0
  172. package/skills/archify/test/community-proof-intake.test.mjs +125 -0
  173. package/skills/archify/test/cursor-onboarding.test.mjs +74 -0
  174. package/skills/archify/test/degraded.test.mjs +161 -0
  175. package/skills/archify/test/delivery-contract.test.mjs +52 -0
  176. package/skills/archify/test/desktop-reader-browser.test.mjs +80 -0
  177. package/skills/archify/test/diagram-guide.test.mjs +92 -0
  178. package/skills/archify/test/engineering-profile.test.mjs +209 -0
  179. package/skills/archify/test/export-browser.test.mjs +305 -0
  180. package/skills/archify/test/export-cleanup-browser.test.mjs +294 -0
  181. package/skills/archify/test/finder-browser.test.mjs +274 -0
  182. package/skills/archify/test/finder.test.mjs +104 -0
  183. package/skills/archify/test/fixtures/automatic-routing-node-border-clearance.workflow.json +40 -0
  184. package/skills/archify/test/fixtures/fail-migration-cleanup.mjs +17 -0
  185. package/skills/archify/test/fixtures/issue-126/custom-widths.workflow.json +18 -0
  186. package/skills/archify/test/fixtures/issue-126/explicit-route.workflow.json +28 -0
  187. package/skills/archify/test/fixtures/issue-126/explicit-viewbox.workflow.json +19 -0
  188. package/skills/archify/test/fixtures/issue-126/labels.workflow.json +18 -0
  189. package/skills/archify/test/fixtures/v1-baseline/agent-run.lifecycle.json +64 -0
  190. package/skills/archify/test/fixtures/v1-baseline/agent-tool-call.workflow.json +88 -0
  191. package/skills/archify/test/fixtures/v1-baseline/cache-miss-request.sequence.json +75 -0
  192. package/skills/archify/test/fixtures/v1-baseline/event-stream.dataflow.json +57 -0
  193. package/skills/archify/test/fixtures/v1-baseline/product-analytics.dataflow.json +70 -0
  194. package/skills/archify/test/fixtures/v1-baseline/production-deployment.architecture.json +71 -0
  195. package/skills/archify/test/fixtures/v1-baseline/web-app.architecture.json +41 -0
  196. package/skills/archify/test/fixtures/v1-workflow-700x400.workflow.json +22 -0
  197. package/skills/archify/test/fixtures/v1-workflow-explicit-coordinates.workflow.json +47 -0
  198. package/skills/archify/test/focus-browser.test.mjs +226 -0
  199. package/skills/archify/test/gallery.test.mjs +130 -0
  200. package/skills/archify/test/generate-validators.test.mjs +59 -0
  201. package/skills/archify/test/generate-viewer.test.mjs +165 -0
  202. package/skills/archify/test/generated-artifact-xml.test.mjs +88 -0
  203. package/skills/archify/test/geometry.test.mjs +739 -0
  204. package/skills/archify/test/golden.mjs +207 -0
  205. package/skills/archify/test/grid.test.mjs +47 -0
  206. package/skills/archify/test/guide-page.test.mjs +85 -0
  207. package/skills/archify/test/guide.test.mjs +81 -0
  208. package/skills/archify/test/guided-views-browser.test.mjs +460 -0
  209. package/skills/archify/test/guided-views.test.mjs +144 -0
  210. package/skills/archify/test/helpers/desktop-browser.mjs +48 -0
  211. package/skills/archify/test/helpers/offline-fonts.mjs +76 -0
  212. package/skills/archify/test/helpers/viewer-click.mjs +72 -0
  213. package/skills/archify/test/helpers/xml.mjs +37 -0
  214. package/skills/archify/test/i18n.test.mjs +422 -0
  215. package/skills/archify/test/intent-trace-browser.test.mjs +284 -0
  216. package/skills/archify/test/intent-trace.test.mjs +111 -0
  217. package/skills/archify/test/landing.test.mjs +97 -0
  218. package/skills/archify/test/layout-rules.test.mjs +1498 -0
  219. package/skills/archify/test/legend-contract.test.mjs +404 -0
  220. package/skills/archify/test/motion-governor-browser.test.mjs +342 -0
  221. package/skills/archify/test/motion-governor.test.mjs +111 -0
  222. package/skills/archify/test/offline-font-browser.test.mjs +210 -0
  223. package/skills/archify/test/offline-self-containment.test.mjs +80 -0
  224. package/skills/archify/test/open-artifact.test.mjs +118 -0
  225. package/skills/archify/test/ordinary-model-floor.test.mjs +1052 -0
  226. package/skills/archify/test/output-path.test.mjs +587 -0
  227. package/skills/archify/test/presentation.test.mjs +71 -0
  228. package/skills/archify/test/preset-tryon.test.mjs +113 -0
  229. package/skills/archify/test/preview-contract.test.mjs +40 -0
  230. package/skills/archify/test/preview.test.mjs +530 -0
  231. package/skills/archify/test/proof-aperture.test.mjs +78 -0
  232. package/skills/archify/test/reach-share-card.test.mjs +149 -0
  233. package/skills/archify/test/reader-layout-browser.test.mjs +320 -0
  234. package/skills/archify/test/readme-showcase.test.mjs +319 -0
  235. package/skills/archify/test/real-repository-proof.test.mjs +209 -0
  236. package/skills/archify/test/relationship-direct-explorer.test.mjs +115 -0
  237. package/skills/archify/test/relationship-lens.test.mjs +128 -0
  238. package/skills/archify/test/relationship-permalink.test.mjs +130 -0
  239. package/skills/archify/test/relationship-pulse.test.mjs +122 -0
  240. package/skills/archify/test/release-identity.test.mjs +476 -0
  241. package/skills/archify/test/release-package-gates.test.mjs +750 -0
  242. package/skills/archify/test/render-output-checks.test.mjs +588 -0
  243. package/skills/archify/test/renderer-diagnostic-boundary.test.mjs +107 -0
  244. package/skills/archify/test/repair-receipt.test.mjs +181 -0
  245. package/skills/archify/test/repository-evidence-replacement.test.mjs +136 -0
  246. package/skills/archify/test/repository-evidence.test.mjs +605 -0
  247. package/skills/archify/test/repository-language-metadata.test.mjs +67 -0
  248. package/skills/archify/test/route-journey.test.mjs +125 -0
  249. package/skills/archify/test/route-probe-browser.test.mjs +363 -0
  250. package/skills/archify/test/route-probe.test.mjs +114 -0
  251. package/skills/archify/test/route-share-card.test.mjs +163 -0
  252. package/skills/archify/test/semantic-camera.test.mjs +88 -0
  253. package/skills/archify/test/semantic-flow.test.mjs +90 -0
  254. package/skills/archify/test/semantic-legend-gateway.test.mjs +156 -0
  255. package/skills/archify/test/semantic-lens-browser.test.mjs +372 -0
  256. package/skills/archify/test/semantic-lens.test.mjs +103 -0
  257. package/skills/archify/test/semantic-passport.test.mjs +99 -0
  258. package/skills/archify/test/semantic-radar.test.mjs +735 -0
  259. package/skills/archify/test/semantic-zoom.test.mjs +86 -0
  260. package/skills/archify/test/sequence-column-fit.test.mjs +137 -0
  261. package/skills/archify/test/settled-flow.test.mjs +97 -0
  262. package/skills/archify/test/share-card-export.test.mjs +132 -0
  263. package/skills/archify/test/site-language-continuity.test.mjs +569 -0
  264. package/skills/archify/test/site-language-integration.mjs +9 -0
  265. package/skills/archify/test/skill-metadata.test.mjs +84 -0
  266. package/skills/archify/test/stable-update-manifest.test.mjs +167 -0
  267. package/skills/archify/test/start-page.test.mjs +312 -0
  268. package/skills/archify/test/story-beat-navigator.test.mjs +103 -0
  269. package/skills/archify/test/story-carrier.test.mjs +90 -0
  270. package/skills/archify/test/story-director-strip.test.mjs +91 -0
  271. package/skills/archify/test/story-follow-camera.test.mjs +103 -0
  272. package/skills/archify/test/story-horizon.test.mjs +91 -0
  273. package/skills/archify/test/story-moment-link.test.mjs +93 -0
  274. package/skills/archify/test/story-shelf.test.mjs +84 -0
  275. package/skills/archify/test/story-trail.test.mjs +81 -0
  276. package/skills/archify/test/toolbar-polish.test.mjs +57 -0
  277. package/skills/archify/test/update-contract.test.mjs +133 -0
  278. package/skills/archify/test/update-notifier.test.mjs +3317 -0
  279. package/skills/archify/test/v1-compatibility.test.mjs +329 -0
  280. package/skills/archify/test/vertical-edge.test.mjs +68 -0
  281. package/skills/archify/test/viewer-camera-browser.test.mjs +395 -0
  282. package/skills/archify/test/viewer-chrome-layout.test.mjs +1104 -0
  283. package/skills/archify/test/viewer-identifiers-browser.test.mjs +135 -0
  284. package/skills/archify/test/visual-check.test.mjs +400 -0
  285. package/skills/archify/test/webm-artifact.smoke.mjs +1855 -0
  286. package/skills/archify/test/workflow-compiler-hard-contract.test.mjs +2136 -0
  287. package/skills/archify/test/workflow-compiler.test.mjs +1163 -0
  288. package/skills/archify/test/workflow-migration.test.mjs +620 -0
  289. package/skills/archify/test/workflow-semantic-contract.test.mjs +131 -0
  290. package/skills/architect/SKILL.md +83 -0
  291. package/skills/architect/references/design-red-flags.md +33 -0
  292. package/skills/architect/references/rationale-template.md +35 -0
  293. package/skills/architect/references/runner-prompt.md +20 -0
  294. package/skills/arena/SKILL.md +13 -0
  295. package/skills/automate-me/SKILL.md +104 -0
  296. package/skills/autoresearch/SKILL.md +14 -0
  297. package/skills/debugging/SKILL.md +279 -0
  298. package/skills/dev-plan/SKILL.md +24 -19
  299. package/skills/dev-plan/references/execution-workflow.md +8 -61
  300. package/skills/dev-plan/references/plan-skeleton.md +43 -28
  301. package/skills/dev-plan/scripts/check_progress.sh +4 -0
  302. package/skills/documentation-writer/SKILL.md +204 -0
  303. package/skills/documentation-writer/assets/templates/ARCHITECTURE.md +49 -0
  304. package/skills/documentation-writer/assets/templates/CONCERNS.md +56 -0
  305. package/skills/documentation-writer/assets/templates/CONVENTIONS.md +52 -0
  306. package/skills/documentation-writer/assets/templates/FEATURES.md +43 -0
  307. package/skills/documentation-writer/assets/templates/INTEGRATIONS.md +48 -0
  308. package/skills/documentation-writer/assets/templates/STACK.md +56 -0
  309. package/skills/documentation-writer/assets/templates/STRUCTURE.md +44 -0
  310. package/skills/documentation-writer/assets/templates/TESTING.md +57 -0
  311. package/skills/documentation-writer/references/api-docs.md +185 -0
  312. package/skills/documentation-writer/references/architecture.md +134 -0
  313. package/skills/documentation-writer/references/codebase-map.md +113 -0
  314. package/skills/documentation-writer/references/inquiry-checkpoints.md +78 -0
  315. package/skills/documentation-writer/references/readme.md +89 -0
  316. package/skills/documentation-writer/references/stack-detection.md +134 -0
  317. package/skills/documentation-writer/references/user-manual.md +103 -0
  318. package/skills/documentation-writer/references/writing-style.md +220 -0
  319. package/skills/documentation-writer/scripts/check_doc.py +273 -0
  320. package/skills/documentation-writer/scripts/scan.py +712 -0
  321. package/skills/elintp/SKILL.md +27 -1
  322. package/skills/figure-it-out/SKILL.md +53 -0
  323. package/skills/gdpr-compliant/SKILL.md +283 -0
  324. package/skills/gdpr-compliant/references/Security.md +266 -0
  325. package/skills/gdpr-compliant/references/data-rights.md +177 -0
  326. package/skills/how/SKILL.md +58 -0
  327. package/skills/how/references/explainer-prompt.md +55 -0
  328. package/skills/how/references/explorer-prompt.md +52 -0
  329. package/skills/humanize-writing/SKILL.md +417 -0
  330. package/skills/humanize-writing/references/ai-tells.md +291 -0
  331. package/skills/kpi-dashboard-design/SKILL.md +103 -0
  332. package/skills/landing-page-conversion-audit/SKILL.md +122 -0
  333. package/skills/meeting-minutes/SKILL.md +235 -0
  334. package/skills/portal-app-exchange/SKILL.md +8 -17
  335. package/skills/portal-dev-setup/SKILL.md +137 -46
  336. package/skills/portal-dev-setup/puller.env.example +3 -2
  337. package/skills/portal-dev-setup/references/kafka.md +140 -0
  338. package/skills/portal-dev-setup/references/troubleshooting.md +22 -26
  339. package/skills/portal-dev-setup/scripts/onebox.sh +510 -56
  340. package/skills/portal-external-app/SKILL.md +57 -21
  341. package/skills/portal-external-app/references/contract-doc-template.md +1 -1
  342. package/skills/portal-external-app/references/integration-contract.md +4 -4
  343. package/skills/portal-external-app/references/public-entrypoints.md +100 -0
  344. package/skills/portal-external-app/references/quota-and-seats.md +12 -31
  345. package/skills/portal-external-app/references/registration-and-onebox.md +67 -11
  346. package/skills/portal-micro-app/SKILL.md +18 -28
  347. package/skills/portal-micro-app/references/manifest-and-acl.md +21 -3
  348. package/skills/portal-micro-app/references/open-api-and-extensions.md +1 -1
  349. package/skills/portal-micro-app/references/sdk-reference.md +1 -1
  350. package/skills/prd/SKILL.md +56 -38
  351. package/skills/prd/references/prd-skeleton.md +72 -34
  352. package/skills/prd/references/product-quality.md +89 -0
  353. package/skills/prd/references/spms-mapping.md +9 -7
  354. package/skills/react/SKILL.md +26 -4
  355. package/skills/react/references/actions.md +251 -0
  356. package/skills/react/references/data-fetching.md +25 -1
  357. package/skills/react/references/react19-migration.md +407 -0
  358. package/skills/reflect/SKILL.md +13 -0
  359. package/skills/review-code/SKILL.md +63 -0
  360. package/skills/review-code/agents/openai.yaml +4 -0
  361. package/skills/review-code/references/git-scopes.md +38 -0
  362. package/skills/review-code/references/report-contract.md +56 -0
  363. package/skills/review-code/references/review-lenses.md +33 -0
  364. package/skills/review-dev-plan/SKILL.md +88 -0
  365. package/skills/review-dev-plan/agents/openai.yaml +4 -0
  366. package/skills/review-dev-plan/references/report-contract.md +59 -0
  367. package/skills/review-dev-plan/references/review-lenses.md +82 -0
  368. package/skills/review-prd/SKILL.md +84 -0
  369. package/skills/review-prd/agents/openai.yaml +4 -0
  370. package/skills/review-prd/references/report-contract.md +64 -0
  371. package/skills/review-prd/references/review-lenses.md +82 -0
  372. package/skills/review-prd-dev-gaps/SKILL.md +84 -0
  373. package/skills/review-prd-dev-gaps/agents/openai.yaml +4 -0
  374. package/skills/review-prd-dev-gaps/references/report-contract.md +72 -0
  375. package/skills/security-audit/SKILL.md +191 -0
  376. package/skills/security-audit/references/language-patterns.md +221 -0
  377. package/skills/security-audit/references/report-format.md +194 -0
  378. package/skills/security-audit/references/secret-patterns.md +178 -0
  379. package/skills/security-audit/references/vuln-categories.md +288 -0
  380. package/skills/security-audit/references/vulnerable-packages.md +111 -0
  381. package/skills/sql-optimization/SKILL.md +296 -0
  382. package/skills/summarize/SKILL.md +1 -0
  383. package/skills/swarm/references/teams/product.md +2 -2
  384. package/skills/tdd/SKILL.md +42 -0
  385. package/skills/teach/SKILL.md +21 -0
  386. package/skills/test-plan/SKILL.md +12 -11
  387. package/skills/test-plan/references/case-taxonomy.md +3 -2
  388. package/skills/why/SKILL.md +158 -0
  389. package/skills/why/references/epistemics.md +144 -0
  390. package/skills/why/references/investigator-prompt.md +103 -0
  391. package/skills/why/references/source-playbook.md +17 -0
  392. package/skills/why/references/sources/code-archaeology.md +88 -0
  393. package/skills/why/references/sources/databricks.md +70 -0
  394. package/skills/why/references/sources/datadog.md +99 -0
  395. package/skills/why/references/sources/incident-postmortem.md +15 -0
  396. package/skills/why/references/sources/linear.md +48 -0
  397. package/skills/why/references/sources/notion.md +55 -0
  398. package/skills/why/references/sources/sentry.md +100 -0
  399. package/skills/why/references/sources/slack.md +54 -0
  400. package/skills/why/references/synthesizer-prompt.md +135 -0
  401. package/skills/xgent-app-release/SKILL.md +97 -28
  402. package/skills/xgent-app-release/references/build-and-package.md +8 -3
  403. package/skills/xgent-app-release/references/embed-csp.mjs +126 -0
  404. package/skills/xgent-app-release/references/frontend-archive.md +67 -0
  405. package/skills/xgent-app-release/references/public-delivery.md +75 -0
  406. package/skills/xgent-app-release/references/publish-api.md +62 -56
  407. package/skills/xgent-app-release/references/troubleshooting.md +18 -2
  408. package/skills/xgent-app-release/references/verify-preflight.mjs +50 -0
  409. package/skills/xgent-app-release/scripts/npm-token.mjs +8 -3
  410. package/skills/xgent-app-release/scripts/preflight.mjs +13 -2
  411. package/skills/xgent-init/SKILL.md +23 -82
  412. package/skills/xgent-init/references/external-app-AGENTS.template.md +149 -0
  413. package/skills/xgent-init/references/fill-guide.md +10 -22
  414. package/skills/xgent-init/scripts/check-docs.mjs +14 -86
  415. package/vendor/impeccable/VERSION.json +10 -16
  416. package/vendor/impeccable/bundle/blobs/{daa2a8ecd874f9f940dfd72aaa329318b06bb9be25515be85fea84c871b637a6 → 00c067253d37cd20a41dbe9c806d6a72cbff983ad1418b3c3e447998f577b9c2} +18 -11
  417. package/vendor/impeccable/bundle/blobs/{4ce929b8cafd37247ea4c148bbe39a9afe15908d1abf4a8248c5122275d16499 → 00d167d9183c8d0c6c0682055107382e6672bacf7a712de0abc8f157c2cb2210} +3 -2
  418. package/vendor/impeccable/bundle/blobs/{a9515f6f084d8f51c378eb3cdc6db1f12e06dba2d32fc61b7ee7950fa2586f2e → 016c082dcd2aa8f3c080a757c8ed335c6070a904bd2f39668bb9d3e6f95929c1} +1 -1
  419. package/vendor/impeccable/bundle/blobs/0221a193d111a9de33a785706a603e55dd974a115f549dbdf74e0f9ec72bde7d +101 -0
  420. package/vendor/impeccable/bundle/blobs/055c571f2960b8f929d6a8d3806a4d32dfcb9750b3ef8b60adc8930fff34b559 +101 -0
  421. package/vendor/impeccable/bundle/blobs/{3aa908c18db91d5f31d6bba6402eab6afc4e0b75137f841a86bd012386e0d8e2 → 0605c8729dc638a46798e90ab12486fe3ae3372a869757cfb387a08e23b3c84a} +18 -11
  422. package/vendor/impeccable/bundle/blobs/{ec58806f16fc7ba29bccef08f2e158cd00be077ce05d45e943a59bd26dc6dc55 → 0648e4e06d01cabc91fa7dc19256ceedeeeea213b9265e9d36b0918370e16fb2} +6 -0
  423. package/vendor/impeccable/bundle/blobs/06b20bd42e5682a42c5d6fbfaad4c55e66ff9b9d99a604bd31d3545af120fc2d +101 -0
  424. package/vendor/impeccable/bundle/blobs/{420e2fdee2b7f555d9a37ce348cf62610ddd98f96b1a0a511796ba600881588c → 08346755b13f1a3f7c6fb4e512387884b80467aaeff109fd41f5521d2a95635a} +3 -1
  425. package/vendor/impeccable/bundle/blobs/{8f651cb1f8cde0acc5cc511b77fddd98558a527f54974698a1650b0fd7e849a7 → 08398fa2d8e2b06b849f1c0f032e1e93b832e9294aed35c1c7f62b938d62ee80} +1 -1
  426. package/vendor/impeccable/bundle/blobs/087f6715114e901c2ce00b438e75b82fd48978c020a782f3dc361d39eb7198a6 +26 -0
  427. package/vendor/impeccable/bundle/blobs/{bc7a5128cfed46148396c08798b6b9429406fbe477e84e331a36ee2840b6b776 → 09310582ed23393b171eb99ad4a288cc422ac53c26d76311586ce54c6df77b22} +3 -1
  428. package/vendor/impeccable/bundle/blobs/{633903ba7cb38ed502448a66691fbf655805786a2f06be67043f12294ad08e86 → 0bc2bc36ca6e74f9f610392f1a4fb8f57b2676238ba1f9c65cd8714f5d27e8a2} +5 -0
  429. package/vendor/impeccable/bundle/blobs/0c064c9975f25f6eb5cf7911c2eeafd3e695d729f8c86a49a24ff2d76cb3cd94 +63 -0
  430. package/vendor/impeccable/bundle/blobs/{4a7d8695741e2cd354baada215b06798c050aa7a8e1ca6814f0e395e054d1ab1 → 0ccf57f758eb0d53bc32c5c77156f016e528d20fe2c2740662bf19964dfbb00b} +18 -11
  431. package/vendor/impeccable/bundle/blobs/0dd1e6ccf053cb80e057caf7bf2fef30fd0197a41d907a1a8d2d2d02f6978674 +63 -0
  432. package/vendor/impeccable/bundle/blobs/{943b0d7c9ce4f6802d8440a07b2ad3c61cbd1cc00ab63962bab7eea9ca584d20 → 0ed5986d1503399f48c11104df5e523a63be2d6558770ebfbbeb2323ca3f2ad3} +5 -5
  433. package/vendor/impeccable/bundle/blobs/14c9c9a7816026dd77494d06b8d1777c8d64785126b0c9ac8db5ebd996dfd6b6 +101 -0
  434. package/vendor/impeccable/bundle/blobs/{54cb270e8826380caefc8c40642a5d973f27df46bfdb762d822541a0c72a9877 → 14ef0ab84c10331f8af6b4124387a3f80b493175a04a3f89200719b4b5aea221} +18 -11
  435. package/vendor/impeccable/bundle/blobs/{6abbf5979db5cb1d7965bf5f91d589e984843069c587f4d1e63aab135bbace0f → 1547005438784032de3254cb35bff393e8187d7a459d0c20a693d9bfb0b5c1a4} +5 -0
  436. package/vendor/impeccable/bundle/blobs/162b814ddd1133923b9584bb95f85959e64844c94341d6bf10a81c06ab7cc02c +101 -0
  437. package/vendor/impeccable/bundle/blobs/16498466a97a5b19a593d5b3f245468c71784bea069d7fc8aa9690db5ac1d968 +29 -0
  438. package/vendor/impeccable/bundle/blobs/{b31ff29c7a1ea979c6d039f7e8d17007410697ab49536690dca109f0af3f20f8 → 16ba7fca1973c5faf53dd2ca523559129c0fe9e5f8d50b645f527afa78186cd2} +9 -0
  439. package/vendor/impeccable/bundle/blobs/1725ca4aa546a34770f29191b58bf8dc14957d4258fb9e7d02f7b1c59c412ea4 +63 -0
  440. package/vendor/impeccable/bundle/blobs/{598bfed550954471ba4d257d46b4d608cd82e4cdbf36d07bf93c5f4a563f7727 → 1898529e994bf0a31ee9ff3f87c343caea3d8a7e0986f404e129fbf89078ade0} +4 -3
  441. package/vendor/impeccable/bundle/blobs/{6e20041e209e8705d14aa9c4fb8cca3f0d743791de633785e5b46e2dd1ff1a6b → 19b439d7d16e139357459d3874f739ea94dbdffeb2a0e201df1620ed1e40574d} +1 -1
  442. package/vendor/impeccable/bundle/blobs/{04af9f2d6883fe76f9539d310d9c369052822a24886d2c330ab1e3fe5981c8a1 → 1b289c8c09de9d4442109ada91b1fa3a190e113a310cab7aa26a3633c5df0bb0} +1 -1
  443. package/vendor/impeccable/bundle/blobs/{eb3213b9c9f4d6b2f153e7b457f13aa131bcf633695229dad4eac39a920bdf38 → 1bb3bdce54386e96e21b5956713a80583e6b3b9d1170f3bb8dec3819fa341bc3} +5 -5
  444. package/vendor/impeccable/bundle/blobs/{e71d6b97680084a7ccec01844e658cbd2042aec00da0c91bec62a240ad7dcf6a → 1c11cb8ea42536c7a51e197f1aa32198960bb89262da2eaf32e0feb03c70792c} +18 -11
  445. package/vendor/impeccable/bundle/blobs/{f0c4d0615c7d520dfc2536c01cc7f1f3aab9b60ddc399ba01289fe62edb12370 → 1c6258015ed02c522948f8f1a3b6457395a8f7954497b87c1cd83f1791f9f819} +1 -1
  446. package/vendor/impeccable/bundle/blobs/{27c4b6c90ad12a186136f9ece9cb1830d4a6e36b11382ab334efc4543f8082de → 1d7145fd5bf65282b2e05cf42faf41766d68e83e2b75f460b3b62d81ada5e5d7} +18 -11
  447. package/vendor/impeccable/bundle/blobs/{1484a7ae206ab4f0e6262b21afe0f6307a629ed27d28fb7de69536a6800a4883 → 1e2f696760ee55fb154bdcc302c7d7b0fbb807e0308130594bd892dae14dc9ea} +5 -0
  448. package/vendor/impeccable/bundle/blobs/{6989120346e87907d59cc6d4708dd9dee29227ad583fbefee28935395b68ce34 → 1f6c3a1d7344f44eaa88b6f38334ad7d7b60201709589039a58cee73de486f5d} +1 -1
  449. package/vendor/impeccable/bundle/blobs/207d443cabe4e6fe1351f91785748957f757bf1e7aeca405433c0329dad46a15 +63 -0
  450. package/vendor/impeccable/bundle/blobs/{f7916d0113da7a19d4e03c113d5563d181457e44f1646ecab9191cfee5ae776d → 20e2111b3e065e8e8054f715ea3902e64b77886b30d2bddee723558f22942620} +4 -3
  451. package/vendor/impeccable/bundle/blobs/21e78c8a77badb3f83290cd4577ed3b24bd4dd3b57136d7da75733d4f3ee9ac0 +19 -0
  452. package/vendor/impeccable/bundle/blobs/{0f83648f6b425225290305bced51eacebacf9bf9bc05e21cdbad46863fbc89ce → 223f08673b267f81d7586f686afe05d7cd7529a8e11ac37d979f95c2ceaae8ce} +1 -1
  453. package/vendor/impeccable/bundle/blobs/2499b18f26639694344ca95682f47c65494f730cfff88aa9bd2aa83a22e5926d +101 -0
  454. package/vendor/impeccable/bundle/blobs/{074575671f24cf4298d06f0019f76e94f62e9a6ed205fce05b8e507341e64266 → 26cd88d10f8a14ed0ddb6e6b21e5e2c981f410eac93afa179202c354d7d1c0d5} +3 -1
  455. package/vendor/impeccable/bundle/blobs/{5f24c5a97b4ffcabc7c432b064cfdd04c7a2ad52f52e765be648dc0aadab8f38 → 275dd1b6e63bbd30d2713227c4f79b880a8bc4e01cc48d392068bb86939d3afa} +1 -1
  456. package/vendor/impeccable/bundle/blobs/{356cfa0ebf61589cf5d52691d101a69d69256062fe1d11d71d95d41a78289cbd → 28f65b42c1ce9aaea35dc37a51257d7c703bb7f6553ebe3b8ca238a1007251e0} +3 -1
  457. package/vendor/impeccable/bundle/blobs/{a1dbde501ffabb50f30f28f2de6755b5e91b3d4028292c5a3abd3358106eb457 → 2ac1624b1253f3b6fcf2da54d54293624176539b2e9609a49245e7e46c65ca5f} +5 -0
  458. package/vendor/impeccable/bundle/blobs/{3895765e9434400dfc1b30e364be002cf499c1718fb2431e65b907c14ae2cb27 → 2b9379cdb329890eebe2384fbaa23f771745f30d8cfc43e180ebd092e69bcd2f} +4 -3
  459. package/vendor/impeccable/bundle/blobs/{1a9180cec754f8afd354e7cb759750247e97c5bd26d3242ad4c45e315069e8c0 → 2bc5d62463cc83d6417df7b8f4a02b4135e2b1bb654aa7727890662496f86e3d} +5 -0
  460. package/vendor/impeccable/bundle/blobs/2ce1722bd1a9f366182d9357d629796b1448f7a0126a854df507eb044d891cab +26 -0
  461. package/vendor/impeccable/bundle/blobs/{e21af575fcc0f1df54ae422bea4dfa1e5211422606908919f6a86e19e0d5c20c → 3149a87bbed84bffe3558d5eaf1dc596b2e84d3c1be290fc7b1c13e481ae0803} +4 -3
  462. package/vendor/impeccable/bundle/blobs/3253eab02b62efa80abc74a5c85da08f3e2c6c20dff8dec38f4d236cbbfa0f3c +63 -0
  463. package/vendor/impeccable/bundle/blobs/{38c2e839e130008b6da814ab9c16f3fcbbedfdf721a9638eebd31a9e65341a7a → 37680abf9a8e446619fcd33862718f483d197bf2652f966adca8dc54d2909b9d} +3 -2
  464. package/vendor/impeccable/bundle/blobs/385a0efe833bd4afe4a257e7159590de0cf1b7fd8f7b213b732f1e537c62dab7 +21 -0
  465. package/vendor/impeccable/bundle/blobs/{8a1c872773996dfa1c1eb765ac7ed8e8d41f99d4f12f090b4725b694e85eaa62 → 3898bd9b56a042e860a0db4fb4dd81ac81126fa218b604702e2ac0c2287ae09b} +9 -0
  466. package/vendor/impeccable/bundle/blobs/3b2b60f23fa8ed9d73e721e17142c3933dc5318fa9a251742a76fee890ac81a8 +26 -0
  467. package/vendor/impeccable/bundle/blobs/3bd55b35c253f7841ca4e6e1a855a4b477d59aa2daf6e61e93fd685caaaff131 +63 -0
  468. package/vendor/impeccable/bundle/blobs/{dde1b74aeab3d90320e134f0ed0422bef99917dcab4c1749aa1720a2c94f725f → 3bed76a0d528e2d73da8acae4dc63702bdb5baca5ab11600d70e75fc9f2ba90b} +5 -0
  469. package/vendor/impeccable/bundle/blobs/{9b2fc50c5062073d097140cde85602bba181e325ec6b9eea1bd3da74582acb9d → 3ef9a43006bc68d83bc958fc8401e59f9beb6379048f5ced047747fdad05b895} +5 -5
  470. package/vendor/impeccable/bundle/blobs/{30e006fdee873bac23edaeadce0371161625e021e3cf442dff4b05bb82297ba1 → 400419aaa20f710e1a7e5ca1fce9e8bc995c4db84053f40cf778d987619e0210} +1 -1
  471. package/vendor/impeccable/bundle/blobs/40cd6024312a1339aa66801df533afa543e60c36e708f0f9659dd8d558f83dce +63 -0
  472. package/vendor/impeccable/bundle/blobs/{55e95137b3f9198c1d4dfc425366b82f1ef5f77d602682b2edf91f2ce9296289 → 412dd9a5238aee223397591fe49b3bd27b6b53d649a0e67ed8570f3e199cebb9} +1 -1
  473. package/vendor/impeccable/bundle/blobs/{181e814c1b9317098b2300c1b02ad0d137b6d82bd1e7e8cc64de4d00b4c50c25 → 41ef23c048ab739f48afdce26a2678d36ee40bcced34ef4b969d1d8ffafca64c} +3 -1
  474. package/vendor/impeccable/bundle/blobs/{edddeb3fad88adec9a055b1bf9d5c75418cbe97a13b1a7f6765e73249e482563 → 42831c3cd874346d8e7f120808d91e6ed3cda5c3eca6eefd76b126659536bc87} +5 -1
  475. package/vendor/impeccable/bundle/blobs/{e3c331cc21d9a216e25e08628610ea99c97e150893c3d26e5c0cecc532f26d7b → 43dbfcb7c2e54c9cca9fce66024f17c06a2f2be645547b718b75c8828a463de2} +1 -1
  476. package/vendor/impeccable/bundle/blobs/4435529820c3fc2eceae8b1ee35c906a34c7612fb860117e896152b45aee0770 +26 -0
  477. package/vendor/impeccable/bundle/blobs/44a60aedcc350c2d7d501d0f830a31a586a6511a9ff9b4e361cb328bb747339d +101 -0
  478. package/vendor/impeccable/bundle/blobs/{c6a0ec6c28ae55fe539f0f41a507b1638495afd285d6eb15c00245fc8cc7e7fe → 45dcea8da47cc21f447041daa942cf5d92cddde9a5a02c196cedbd159c829304} +5 -0
  479. package/vendor/impeccable/bundle/blobs/{015725eeca94f52bffd2132d4cb49bc3eb1ee76e6ac7378c065e629d59f56613 → 4700adf4542874f204c680ebad8317a97bf7169dbc04147082618ab59ce70c7d} +3 -2
  480. package/vendor/impeccable/bundle/blobs/4777bbeaff2efcd6a2a66b07aacaaf57cd32f3fab1c1da5a0513937fafb48bd1 +63 -0
  481. package/vendor/impeccable/bundle/blobs/{b6022a8c7200e96b0b55c2ff599a01d64123a2f5fe01557d4ca5192a6e0f0b0c → 484ea165f6d49ecc15b7a5c5623e377f2e203f4dad366df23eae99255ecf4572} +18 -11
  482. package/vendor/impeccable/bundle/blobs/485774d58dfd5796956024cdd9c12f05e692a3703f70b12a02ab43918885c3fd +101 -0
  483. package/vendor/impeccable/bundle/blobs/{3bf5d8661351831dbb2195e3b677fea1f128ca319c0589d538b66d9c9d7dddbc → 488da2e7406c6b4b5c92d7bc8cbd370cdaafc82a5f3ab5adbcffb21d1d1c4df4} +3 -1
  484. package/vendor/impeccable/bundle/blobs/{6f1d52863482fa0f6fff877f0cc8f6dd0b4230d28050b0d267e082776e61a332 → 492a8030d11e2f4908d934bd817bd6d16a3164056c74a7172f60e2cec5ff3055} +5 -0
  485. package/vendor/impeccable/bundle/blobs/{51e2f8963377f142ebdc9864e0ecc5aa1e5b7d344ed72d0e9d748d2d3d8c71b3 → 4972f28d96897c8dec891f0de7a0d9d51f36030ff780ed9d960241c75413da2b} +5 -5
  486. package/vendor/impeccable/bundle/blobs/4a6f0386bff78bb42efa285df2919e75209ec336672cf5fff91ba66ffb352eaa +63 -0
  487. package/vendor/impeccable/bundle/blobs/{12c1afcd15e86d840b89a78c6d17ce6d1b5609bac713d59271c6ab5932975dac → 4e3cc4d0e229ca96dd2e28fb2da0478a7f0bb64e447d07a652c425d8fbc57573} +3 -1
  488. package/vendor/impeccable/bundle/blobs/4ea8e05d0f88d24f182ad554da84317f90b9730e29fad262143ddf423a1f8645 +26 -0
  489. package/vendor/impeccable/bundle/blobs/{402656ca6df17bad1cd55ede0a966a7bb5b187cf4f89c517851f9efe7f14c0fd → 50d4b14134fc06daeac0aab6960800f171ef85250d3bcce6f246cf81e824463f} +3 -2
  490. package/vendor/impeccable/bundle/blobs/{43852ca5917de66704f73f9019d15482bb1efd92f2eefaeeeae23610b4c0c6a0 → 50f3b5714ca3e2c1bcf070003733407935ee050609d3123c2c065489fbc9950b} +5 -0
  491. package/vendor/impeccable/bundle/blobs/{f597742c8e5562263d3bce725cb55e920d8c2c60223f41a632d523ca30cdd12b → 51032bb883137007127d30189b44b516d0e6140271bf5881da7eca76f8bd282c} +3 -1
  492. package/vendor/impeccable/bundle/blobs/{13bd27aa8573e6d45d8bbf9f3fc991e4719d28a7e8f709009a4a5a49a227fff3 → 511ecde67e6bd976c9bdfa8d92f0dba359621344f8135c2a5ce5a66b385a4cb5} +5 -0
  493. package/vendor/impeccable/bundle/blobs/514a27fc9830455828d337cfc2fa95fa86be8e5464501bbabb9aca09a66b40ad +63 -0
  494. package/vendor/impeccable/bundle/blobs/{78ac93689928a580c2f90242cbaa96dda3fa4e55ff1f1d00e412b2a62ad85232 → 529cb2ace696ec11a86f4b010c9b137acf282072e483932181be1871df2aa690} +18 -11
  495. package/vendor/impeccable/bundle/blobs/53628d05b7eff0d4f48b95e48fad40266452fe1b42f398bd88dd9328353e0dd8 +101 -0
  496. package/vendor/impeccable/bundle/blobs/{00023f9e7f2e27604fde978b56510a8f837b76eeadd93221d11adcf4c98f1a10 → 53de37260c4f1c37e467557e9b038faa0f285b056bb2b95f435e0a7d1b69b0de} +3 -2
  497. package/vendor/impeccable/bundle/blobs/{0dbbef70048cc3ae44e6710ff09992ce14ad049ce8ed519b0ff8a1ddb4633f4e → 5415103ca4422ea1422e23bfe9f9bae181f5d6d6407442f7fba31856ada58d12} +3 -1
  498. package/vendor/impeccable/bundle/blobs/{af34b8af89edb10e228c0482754423f48238fce816eceb8703b8781c130da54e → 56285b28b0ffe471761c2ad062d3f933ed2346ca1b617f1323a30fed99a1a852} +1 -1
  499. package/vendor/impeccable/bundle/blobs/{12fefe52d80d25014e5f7e2f9b278275a675653d3d99ae8f0ecf344cdb9abbe6 → 56cc1bba51e6805de370160ce4a9399fef3740571204f13c3c751725870305e5} +3 -1
  500. package/vendor/impeccable/bundle/blobs/571f5c3bcf01c9b1bd02ab853a54db3f88375c4b8f39dd67d53e983a33e08bb7 +26 -0
  501. package/vendor/impeccable/bundle/blobs/{5ce02fc8f353d7f659535fb80e453963dc047a07c4396adf098fe010b479e7c0 → 5855d7595b0212bb8d521e0265378d437df8d2343d5f8a30408c3edde0a14d96} +3 -2
  502. package/vendor/impeccable/bundle/blobs/{2b21f0142ee88a11dbe2593362f5a910718a61062e3a64e7ff936ef1e74fd394 → 5a07d4769a741cd00fdf8c95b943ef072eb12cd0c9e2c2d2622d5fe0a4fa3894} +5 -5
  503. package/vendor/impeccable/bundle/blobs/{3dd45e1c32db3d3163a96ef198954905807b25cb9a1d206a7d77986f21d27652 → 5a9626fb8c1e9051155c68626fe7c765a55be325113245d44b4991fc3d3b014e} +5 -0
  504. package/vendor/impeccable/bundle/blobs/{d07e3131cdf3e392e59eaa3e2f59fcb0799d9494df4adfee12a21067fb8365ce → 5e354ae11913d5846faa3681a9ed98b68d1881fbbb1ecebf0769e3010bb0a426} +5 -0
  505. package/vendor/impeccable/bundle/blobs/{ad389ab12800738b0e5c97618278b7a824654b25990166ec9f389caa5c3386ca → 5e6eea05456108b8766cf354dda998e90b6a5ecca7f15d807e28659ee78c306f} +5 -0
  506. package/vendor/impeccable/bundle/blobs/{85b9c2d051de94ee9129c58be111946f73035ca62bbd2a3936f4fa48768fe5cf → 634257e766b1fecacd25e27dbfc7e21ef3b440b01e94e92b8b17711018d8a661} +18 -11
  507. package/vendor/impeccable/bundle/blobs/6428239079f98fd6500e9fd032dd289b52052da7a4364ff357b0a5341b6444db +63 -0
  508. package/vendor/impeccable/bundle/blobs/{f424dafa190533cd32c0bc3e4131d0c472d58e16bb191eab14f0ae73c2cea917 → 647bab2f5cf6279d58d808f4df05d1ac63c1c86c6df9d13406ae776458653995} +5 -0
  509. package/vendor/impeccable/bundle/blobs/{8e7bb79db7331b93f99de314dd5599de8587ec0b6c25e26cf1efab25c0777fcb → 6528f2aebe4a425b724de293c8f6dc8a42ca80c7f1ed3039b8b9a813b004956a} +4 -3
  510. package/vendor/impeccable/bundle/blobs/{89eb0206a0d9308c6c6a7cc01bc4fd8812d2bd34bb9a831988c5d86fac2c60de → 6575a657642ccdab42d0743ceaee06621c77811b4dc4f21c616e28aabf5e28ef} +1 -1
  511. package/vendor/impeccable/bundle/blobs/66d60356172ccafdd334fca9bf33243c8409216a733dcde0d66a24fd70ee8132 +1 -0
  512. package/vendor/impeccable/bundle/blobs/{759bab1d8adc071fdde2efcf6e2157aa4026f3c2b4f3c342a8070bf328011616 → 69cad1ae7355825ef320ac9638a1c9675ba9fda01c9a0fa12244cc4a1973e550} +2 -2
  513. package/vendor/impeccable/bundle/blobs/6d21d8e2729effaecc5b6239dadbcffb1ec8d51e8bdadeb47a39827266a61c5e +26 -0
  514. package/vendor/impeccable/bundle/blobs/{ff882c59c9aced92338aa194cc99a521ea2f083fd22eef3b1c1225e06bc72f66 → 6d9258a49c0b0583ec255eeb1092554298d5eea676fb9391f5a5a1377c3fd770} +4 -3
  515. package/vendor/impeccable/bundle/blobs/{68bc52a604731ca024610051fc763f4d78a53eb2a45d35b40a8c0383043baa63 → 6f4dfe968f47302ea64dca0e02f8c6d81497d93e4f436d09236e305456cbcc02} +4 -3
  516. package/vendor/impeccable/bundle/blobs/{f97a6891c80bbbc728edefcf4b638d1a823b38f3cb16ecd0fbb717734cc5c0c8 → 6f7f1639a933ed88e116aa8ab0cfb951096930d14f413349ae22ed04e28d2358} +5 -5
  517. package/vendor/impeccable/bundle/blobs/713a942482531ef8ef103adf48d9decd7327697450e444289aa0479458e4ee1f +101 -0
  518. package/vendor/impeccable/bundle/blobs/{6d47503587ad6da17ac529f44a96123bbb96a9c91a7a9350b7690fc467561a5d → 7212014fb2477d1d54aedaa79cdb861071a58afb2ae6d4dc5a495fa4810c6f8a} +5 -5
  519. package/vendor/impeccable/bundle/blobs/{21bc91f6e07691e82b7bba99f9e1d956f9d7a6810dcdc18d231fe73b53a13b23 → 73f8bdec7d9a97476fd7d7e0b4114b5c3e9c7b84c22cbb876cd18c3e64a9b8c5} +5 -0
  520. package/vendor/impeccable/bundle/blobs/{a8547c8565979894f0c07f92a96ac2a38e681a31fbf155ffeefc7566e185d9c2 → 754e9f0aa2101245a83cb17d8cc5bc49cf87997b29a83dedbfff283dbd0a8c4f} +5 -0
  521. package/vendor/impeccable/bundle/blobs/{84df879a0332a56ece4bff1922ecf4f50635951b3c67e67eb46f31bc5d30fa9a → 765d3e890cd7f58ca94b6834181052166e9c4f9ef06278dc241da4d64da2d595} +3 -1
  522. package/vendor/impeccable/bundle/blobs/778cedc9199b407d3e23fa1041e38d548b00b1101a33517aa2a2eb299f9d0edc +26 -0
  523. package/vendor/impeccable/bundle/blobs/{ef0b8eca20e1321cf7216fd0bda41ce54b0cca197cfd1b075eb51f3436f59059 → 77ae09542fbc10aa4e8b119d6fd19359908a47c13c30068d6a150bfdb50e3e10} +1 -1
  524. package/vendor/impeccable/bundle/blobs/{15b4837dccb27d7382e2f134ef050b244c4488b1906e0308f288112183cc09ac → 796bbd8231413fcbf22eb7e6f40c402842aa4b10b1894545a7b05d9201ca7c4a} +18 -11
  525. package/vendor/impeccable/bundle/blobs/{5e3616ac45568f239fda3a4764f7d3bf3473b8b5eefd91e402dd9208a4b851d1 → 7af7fcc09c6b14f26ba78734460a2f9dddd2dcd2e2fa0c47c682f539e2f4cad5} +1 -1
  526. package/vendor/impeccable/bundle/blobs/7b1a4cc5ce94837c8309962a204c47361927e442b7a1c3cc472f90276eca8b8c +63 -0
  527. package/vendor/impeccable/bundle/blobs/7c417abe75f0ce4341b6f5acbadcafbbeabcc32cdb13c930aecc5cabda9f9242 +26 -0
  528. package/vendor/impeccable/bundle/blobs/7e36403ed58e0e82c0e42bf2fbea1c066b8e63276978647a6f1e44bf1edb23fb +63 -0
  529. package/vendor/impeccable/bundle/blobs/80191b3580a996a2045105976f728e0f46de22c412fc7640741add9767b2d8f4 +101 -0
  530. package/vendor/impeccable/bundle/blobs/814610dee1081abc4213476ff0c4ae3e8f457909550d250ea0f89953687c85c6 +63 -0
  531. package/vendor/impeccable/bundle/blobs/8157b5a376e46980117f1ad6d08b24ee7be966f5de64b041bd213d486ea8c077 +26 -0
  532. package/vendor/impeccable/bundle/blobs/{bad9250670c18d89722563fd747bae4c4bec64d1db0ee09d12d4fea04fe271b8 → 8373668da1aa37c39888809ed9e834a7edfcb884af12f74934c270d004fba626} +3 -2
  533. package/vendor/impeccable/bundle/blobs/{46250caaec1bd69619a5b28a73cb3c845b319d029b0af9228aaa7001e7e0104a → 83d614fec61078175383012a088f49a9c0bb08b9ebd2b651c77cb94a323474ab} +5 -0
  534. package/vendor/impeccable/bundle/blobs/{a5371492582dbeb69b24a1a2947b256a2da8a4d55917af709bbab6e452d9d23c → 8449781319a33d4a10a7fab9bfa4812241c303b95f33703b300b097dba51089a} +18 -11
  535. package/vendor/impeccable/bundle/blobs/{12d2a8043ae8668ad29c32bfa92995849fc49cb016e6ebd4f7e59539d96e7b03 → 857c4a0db5859f1fa91152db684528299dfc552525f50f416d1625a270e12671} +5 -5
  536. package/vendor/impeccable/bundle/blobs/{bead87679caad7c537dd7c04c3bb78be56ac7eec279ad6aad7322f48ff2df2d9 → 871a8e4d749b807c693ebabd83defbd6c76e1bd2a0f53a28a460cb1308ba8634} +6 -0
  537. package/vendor/impeccable/bundle/blobs/{cf3ae16765e7b5bc333ef76e24ab37f080e3d62e931c4986158e3cbcda6b9f7a → 881a58aadf300bcc8f4947243e82192ae8dd7f14822a70fabc84fc74a5f9199c} +5 -5
  538. package/vendor/impeccable/bundle/blobs/{896da399bafcffb0623bdd81bb18709d6eab25c9d5917e739c8798f31ff0d076 → 88549c11ea55d5dfc9f551db9a9c270d7362a9d42aa83db7747c9a7f020e1255} +5 -5
  539. package/vendor/impeccable/bundle/blobs/9287af96048c58ed0e72493cf7eb90c3957d4ba8b19e70ecf5d1f54264e9e597 +101 -0
  540. package/vendor/impeccable/bundle/blobs/92b7ab84c828fa888f4882c417c3d7f8fde2e5445b40f96f4fc8181a3e058afc +101 -0
  541. package/vendor/impeccable/bundle/blobs/{e2f98c4136d0ab70ec32fcdef58edb20ed8ec4f6cc067e0dae952b22cfd6a471 → 93c53421c3376f695fe9dad5c82102f74bb5dd15e4ced81bb4ad50a71e5f1027} +1 -1
  542. package/vendor/impeccable/bundle/blobs/{a8f4056a85706c0c8f80ec48e9b437e198464100aa42786f9252051f4b931c19 → 95f0c7935a6d0375e09ae67ae0066c0ce7b583bf1d445d268cc4d2f4f900b1bb} +3 -1
  543. package/vendor/impeccable/bundle/blobs/98384b78af087855dbb526ec1e870a676ecd87f57237643dfea815317dad8a07 +26 -0
  544. package/vendor/impeccable/bundle/blobs/{948326fab89f0d5c07355a06b9b9c30d08bba2e3a673a0151ebbf5a39dff7b9a → 99e4a6facdb07986aa721bda8a4e35466b30091f32e38d7a71d9fcbe3591f65a} +5 -0
  545. package/vendor/impeccable/bundle/blobs/{44a91b3f0810f43829d8584e912812444d15614e4b57ca8070aee7ab899f7c1e → 9a4aa0d4903eabee987fdc92053466ff7f6eb0604797aee0efe67d67999b3eae} +5 -5
  546. package/vendor/impeccable/bundle/blobs/{9b85b85443aec09918befb83208c72f475457db8261a8fc5e83ef7eec474c869 → 9d45e5f6c082de6df4a2cfff11deb969715c49b5d9891d100dd1b2252c5bdcdd} +18 -11
  547. package/vendor/impeccable/bundle/blobs/9db3c0857f4c2c8877b1fe24a47a229fee0de76ec9057bd8ee95f0677fb58d74 +26 -0
  548. package/vendor/impeccable/bundle/blobs/{5738bcf9ac21dbb2113fd0c5cc7e4bbfc8174778916ab5843644332b3dbbc36e → 9e82126a2e08aa365f9c430d383cf6e1921e04d1e0a1b5777716ff97828cfad8} +5 -5
  549. package/vendor/impeccable/bundle/blobs/{b3782f2d9215eb0f5df4fe3c0e0bec07cef011e1836d4d0e45ef02bc48d3adde → 9f2993499adadfdef4065a9a7fb69c75f888d892d4ee6bdbe62619bc772f495c} +1 -1
  550. package/vendor/impeccable/bundle/blobs/{1c804990fd8ac23a4b19c42972b5ae591d17f620d0006f0f32927c8db5d5bf50 → a1af8b8a97665a3692eb39872c235796684a387a0b83785872f81aebd9dab046} +18 -11
  551. package/vendor/impeccable/bundle/blobs/{824b994782a1fe68a244bbdff7218a2e0854655d90cc0fb5ade7ef9259ba6305 → a27399e3056c77a28ddd310fb5b4dee6e8e440dfa1737f7e38815097bec4c3a9} +5 -5
  552. package/vendor/impeccable/bundle/blobs/a569989e6a3d6453b4c45e9474e162a15cc54e11732ac6baa7990a6e7cccc0b5 +21 -0
  553. package/vendor/impeccable/bundle/blobs/a75b892696469e3ccd2af33c9eef793e635efc3c5ac45336b0c1373d90c856b0 +63 -0
  554. package/vendor/impeccable/bundle/blobs/{3ba92d4aa840ec1b6c2fda224339489d6dd65eedf43bb45836af02584d1faa88 → a7e8e60df83c6f47590467094ab2a13f1fe28ce45959a4e69dd89575a4208646} +5 -0
  555. package/vendor/impeccable/bundle/blobs/{e49d2b0110c55751da3c965b4ae4d294aa676c961a09f8efbbbf22c1ec7c4fa0 → a892e337eee548d53252abb72ba5aa85cbcf556ffd8dc74e05534652c010d574} +1 -1
  556. package/vendor/impeccable/bundle/blobs/{8f0867db7c6f6a54348a0d951f198a1bd852cd12505d821e6e1ac6bd42e7fcea → a93397adc906e245c69b42d4b25931fc92dc75baa60ca9a3749ba23b52ba01a0} +3 -2
  557. package/vendor/impeccable/bundle/blobs/{424b2e75cb204e2dca7db4a40dfe5a81f78dc0fc58ac4790e8b7bbf2f330bba4 → a9e63b2df611805e845e0bb1cca1a0c27e83640a78185c9fd9de90d53a539cdc} +5 -0
  558. package/vendor/impeccable/bundle/blobs/ab80e6a971baa66342548a846ce3fb69824ef9ef4e0f26c6f02685f225d00bbd +26 -0
  559. package/vendor/impeccable/bundle/blobs/af35b5fb6e45acb6483a5fbb864c3eaa9c57bacc43857f48183c836041c670ae +101 -0
  560. package/vendor/impeccable/bundle/blobs/af5842c4844b692b817319d5375611d4211dc7f459fb12da358baefc3a6cd373 +63 -0
  561. package/vendor/impeccable/bundle/blobs/b2732083f8f1d1924d38f84f179491430aebda8e0fd1f1d0785e3f883bcf3a40 +63 -0
  562. package/vendor/impeccable/bundle/blobs/b3b1d5a4c80ce279d88896601deee9ccfeacdae0d0cd433600985a5f7ac93c72 +26 -0
  563. package/vendor/impeccable/bundle/blobs/{fd5579dbae1fc2495b7dddde48df9673acebd27953bbb56d506d3b470375c9e9 → b4be5499f404a926cdd2c55d8fb7409ba74a56b3d0c7d865594cc0254d3e499a} +5 -0
  564. package/vendor/impeccable/bundle/blobs/{2fd096823e4a93f19edd421a69e10f90ebb630a014c673d1802a927c6f47b7d2 → b626e0677288a1660e9ce80c4f0454b527010239681f6b8dcc0f36b4a4d6bcb2} +3 -1
  565. package/vendor/impeccable/bundle/blobs/{33b6b32c0c3c0c4a2b22bd2275176b1c88a006dd94592a854f629911a0b21cdc → b719be9c5d4ced5d649ec6c0c90630196e7ee513d0da482aef13c705fdc23ab6} +3 -1
  566. package/vendor/impeccable/bundle/blobs/{df0eb9e9a484fc7b8a0f3e50573a7d7f81e0f17598ac30d9f3fe5a6c6aa5fefa → b8938fea3399aa639b4c873248035c219658069eef7be62672254e2f72c056f4} +5 -0
  567. package/vendor/impeccable/bundle/blobs/{ee0a15fcfc244b76b896a2650a17b35e444d4311166b69a3cfa32d11f8f44851 → ba0d96d88ab40fad1cb522e60b11affc568cfe9d340110ac5e71f834ac3d0f4a} +12 -0
  568. package/vendor/impeccable/bundle/blobs/{426c7f5437dd3c23a4cfaef6964dc7f1e038480f92238499b85f3ce7e4472bf4 → bc48bca63dff44e1f0205bafb64e16b2d6fb294ace405dbc9ae06a3bc6107154} +3 -1
  569. package/vendor/impeccable/bundle/blobs/{c3ad2a5fa570876af6645c48d246c664859e19f253d2dc9e0ead34e785d5b40a → bdd676c8f29295addfdbceaab285bb1184ec3ef7ff60501908b97ea8269580c4} +3 -2
  570. package/vendor/impeccable/bundle/blobs/{38d4d404030c6ea935d3223db1eeb22c45d04a94f41f98e02a43cdc5af7ff2e3 → c06effcdc60859157208d3b7ee23d56160f2386f6a2dfa2514ba82fe21828ae0} +1 -1
  571. package/vendor/impeccable/bundle/blobs/c100b67a4ae248ad564182b181acb1ee2fe64c00049aeef62d4e7a3213726f37 +26 -0
  572. package/vendor/impeccable/bundle/blobs/c2dfc965319745c403b99e00e9e97de15f1300ea721bd3f708f0ac47aadc537b +101 -0
  573. package/vendor/impeccable/bundle/blobs/{e9da72a13eb3411d6bbb316953022f62abc4434f505e5345907b216eda9f793b → c6b3bc811eb23d90ff9add1e0e5b40999a0bbbab364f5e6d08061f36d30429a5} +1 -1
  574. package/vendor/impeccable/bundle/blobs/{82a5e564563333aabb7ab4d2f8c26c785dfe2c2416ac6e9f30cba31440676194 → cdf8a88b9865599c58fe285041d2d46eea7d9bd2d4075d82de358191742b20ad} +5 -5
  575. package/vendor/impeccable/bundle/blobs/cf3d3a296890ac1ee363fee930f252e20d0935cd575367ad017b3cdc2dc5a50d +26 -0
  576. package/vendor/impeccable/bundle/blobs/{a1e4febca3455787d7c753fe177a150dccde6e742957de400b0307247802d200 → d2e16da9bb6b33c931378d1bf57dcfff5dc426a71434bc352cec6aece715a66f} +18 -11
  577. package/vendor/impeccable/bundle/blobs/{c36f6aac0ddf52eabbb21df09fd3310540dca6b09e7a4017d18e94c06c469405 → d4a9e18a879bbb92aa0a56e16b45481090dffa4470efdecf52fb0da8c900be5d} +5 -5
  578. package/vendor/impeccable/bundle/blobs/{869fa5390b84bfd00d072f5280a9002ea3e3936edf5985241be641a87f03ff7b → d57c3e0453f601ad688911fca4471057c7b46b561fcd42a1e12a581101c5186c} +1 -1
  579. package/vendor/impeccable/bundle/blobs/{910461b1c1f8216155165955c860a884a1e2f557cb38f21ef512ea90ef6503c2 → d5f83912eda93d42f93522bb74aeff0ea04d9c559577ec52fcccc130dd03166d} +2 -1
  580. package/vendor/impeccable/bundle/blobs/{9deb14303b421b5a9232755b5b9f317716f33e1e211557a98a00a9c409775c4d → d6489d7f3e607ce3f8514a7a7d3a0eb5e8f1ac55859eaf7d5c31b53de8fab9f3} +18 -11
  581. package/vendor/impeccable/bundle/blobs/{37080ea5e5b381adb7eae7a427231b0ad0dee0f0916fc1d6b673b7101a5b425b → d6a51f4df6d76f16b95ab81268a689f4c5936d505c5bb25c80ad7423f927bbc6} +5 -0
  582. package/vendor/impeccable/bundle/blobs/{61c72fdde649bf7f2e0668e48f9d222666c81672100b5f2265940e7aa13c8767 → d7b99a57652cb8741d57a15ba7e06de4707fac02a97e5e001179da007272f2b8} +3 -1
  583. package/vendor/impeccable/bundle/blobs/{57402ef6fd9d0745f8c60d778f77da83a8b16edf751fa1013598a0f6e5f0f541 → d9963fd73bf6129fe0c8ec25c5148f50617ec85683b8eeae7e411c9a42e2db33} +2 -1
  584. package/vendor/impeccable/bundle/blobs/{581409ace104a81744b7d08f5398a2c207cf76d9e50751f807b4382eaf66454f → da3b2399814db89d67959268c646601957d3e8c641b09a5bdbce84217c1c2cfe} +5 -5
  585. package/vendor/impeccable/bundle/blobs/{249f0437a52ab3eb4bc4d4a9f38e085334c0fbb7795e88dd419e32b5f58c924d → dc3aeccbea3e997704ce8b170f56b0eaf343a14ad4fedb22a6dbee0f205aa37f} +5 -0
  586. package/vendor/impeccable/bundle/blobs/{433a79eee3ce4c99e79a7aebe3a6d8ec9ff70216772e0c2ff9dce3a01d672963 → dcc1572e739cdabcbf084f276b447cb686aa18459896e6d8fe29f4d7d807bd1d} +5 -5
  587. package/vendor/impeccable/bundle/blobs/{2d7086992c07df1fc734cdf9c420c4bd8ad409ab7909e07c8b486c303d420732 → dd66761b291c7dbca6e9efd22023e38f8c53ad310f3a6cdab5dc7ecd7ae8f31f} +3 -2
  588. package/vendor/impeccable/bundle/blobs/dd953992625c240fd1842aaf533a865aabd09487cbc16fa01fe8bb4b4365b843 +101 -0
  589. package/vendor/impeccable/bundle/blobs/{df4f14df1daaad1606b682995f649da19a85debf264092447b3b7ddb8b4bc1ce → de70398719140e4951aa111e9625de5ed916ad1ef0877e4ab6f6b4a7e3cc5f8f} +18 -11
  590. package/vendor/impeccable/bundle/blobs/{8b23562ccc3e41609ce6e67fdad6cc57b6c961964c329eff6975a1b4c5471c0d → deaaa533475b6a9f7dd52e01a1f1997aa3af146694334981650f8c846f939559} +3 -1
  591. package/vendor/impeccable/bundle/blobs/{041535231366047a0beeb5daa64ea9c23d5a566580f7dafdb8c0623cb4a7e76b → e07176229b8a330970ca3c9c5e3dd68c2aaeb726285e30f471e91053d7f8e798} +1 -1
  592. package/vendor/impeccable/bundle/blobs/{115e1c3f1b58b5129910ed925dbf65d61d5ac4c2036618847555ce40098aae97 → e1075ea5b34ac9c60f7c5bda97356eeaf1b683b599592d324fd3704f0852ad7a} +18 -11
  593. package/vendor/impeccable/bundle/blobs/e3af212117e0c552b0976687200fe8f95846a01725a482e8e4dbfd75e40dbfa6 +26 -0
  594. package/vendor/impeccable/bundle/blobs/e3c2031978cd670d7150ff3140f12cf8b6882ef638ea9a9985caffa9a80c8713 +63 -0
  595. package/vendor/impeccable/bundle/blobs/e6e18e7c23cfe82961d90b9714cb466c20bd83f222ac63e9339b6b2c304e1787 +26 -0
  596. package/vendor/impeccable/bundle/blobs/e7af7ad18b307a3171fcf49421df2a557f93289d27af2430f10ee74e2a2fc2d3 +101 -0
  597. package/vendor/impeccable/bundle/blobs/{b161198874e4e77599bc31691e78790be14bacc2eb03be168c8a7543ece9fbe1 → e85da3098368807689009184eca2bb09a91bdb6cb1be3e7a61f91f1ae31cd69b} +18 -11
  598. package/vendor/impeccable/bundle/blobs/{6bdbc3f745ceee15e10b050f109ce42bbeb53ab3c3b5239257de1d596654dee7 → e8720f3aa41135211cc58cc299a39eeda86c75651f4279cc1ede8db10dcc0584} +4 -0
  599. package/vendor/impeccable/bundle/blobs/e9861052457cc1ddc42c687bb8c33a877834ced94fed74af2a4f00f6bae50795 +101 -0
  600. package/vendor/impeccable/bundle/blobs/{d1faa55eb956033d28e9f27fd2bc2a9f62c5da0f0abd6534819cc0a04db54d9d → eb3e86876c20f1cfc443dcbe48d8f41fea6e815082a304610be432272429a06d} +5 -0
  601. package/vendor/impeccable/bundle/blobs/{0e1819750e5448311a051d35ab6d0be0830418f78ca872ef10469fafebb27d4f → eba472f6190541c28e2e647ed019f43564ba5b92d629963f34c899175b25b31e} +5 -5
  602. package/vendor/impeccable/bundle/blobs/{f173ff03f989f162cee815feb2d8ca72daf00019c48694d89db16d52171a79c0 → eba609589a5a051643a7bae60b7cceef7cfe44d0f8bd9229e61473ac75910fb3} +1 -1
  603. package/vendor/impeccable/bundle/blobs/{8eb466778023fccea641654d662157b123eeb360f4a0875bf6fbe3d93680851c → ec81b008d2641402e3352b09b1a90562ef7a24598d7c5aded475038cce63aca0} +1 -1
  604. package/vendor/impeccable/bundle/blobs/{4acfb9e38f6e09f7484e36fc19704d69eab159436ee9329168be74c493042f22 → ec86b8633fbeb14ef2272f220fdd98089972b03b99da83e49eeb6a8b73b00617} +3 -1
  605. package/vendor/impeccable/bundle/blobs/{d15a2914d93e07a4956acd5c8b8211af17380f527acd10d8acf4f4920badaaaf → ef2e97cd690baf6fe5c895dd2d8844aff9fcc4a8bc04973402678a739c81d712} +4 -3
  606. package/vendor/impeccable/bundle/blobs/f0fbe529f63961a027bada2e6a3cbe86f4af0dba4b8e1010da22b007f9002f66 +63 -0
  607. package/vendor/impeccable/bundle/blobs/{c02feba25a961a72647ad317aba2d65baeeed53c4cdcc072f25bb37f4d867d43 → f254d59ff973e907cacdc2c34b8b4de075437d292de31dac30e10a9d7035086c} +3 -2
  608. package/vendor/impeccable/bundle/blobs/f5efb1b1dd4cd18e1d4789d7c8e0188f4342b25fffd53af6088ba8b67774fb99 +26 -0
  609. package/vendor/impeccable/bundle/blobs/{7af0a8665057c83b39bca2c8c7427ef2343734f70d4128c377113a6726a1e3b1 → f68a3d68ac92606e91aa8878e003d9432ddd09aa97ca01c6b3ce46c937dca316} +524 -4
  610. package/vendor/impeccable/bundle/blobs/{381ff89aa76e82a0d98456ec31cb117555ae045539fba47c45056daa50f611ca → f84b653ede0804d21e6210c6d21fd5352023914fedceae6ff14e20f1e93b06e7} +5 -5
  611. package/vendor/impeccable/bundle/blobs/{5b30a06646ad5e453d6b5ed1b8d446f69fca3cd13b8aeda28f0d0b2cbe8f62d1 → fb32d99751c5fc24493ff4460be1767bd5236dc820fd337775067c0620d1a7a6} +3 -1
  612. package/vendor/impeccable/bundle/blobs/{733504a70ed20bcfca9c26c353f7b88f8491d24f3f2fe124dc1e73b28eefa296 → fb5fec24adafa48df43eece6907c1c986a4772cbdc64142c881f00c3b312e9ca} +18 -11
  613. package/vendor/impeccable/bundle/blobs/fc149b5bc7a8d0cc9b9bf86e5013793f3857c1c302212e9aaf101cb95427386b +101 -0
  614. package/vendor/impeccable/bundle/manifest.json +413 -298
  615. package/skills/grafton-view-dev/SKILL.md +0 -195
  616. package/skills/grafton-view-dev/references/bindings.md +0 -120
  617. package/skills/grafton-view-dev/references/components.md +0 -168
  618. package/skills/grafton-view-dev/references/recipes.md +0 -208
  619. package/skills/grafton-view-dev/references/schema.md +0 -86
  620. package/skills/grafton-view-dev/references/stores.md +0 -310
  621. package/skills/portal-backend-app/SKILL.md +0 -56
  622. package/skills/portal-backend-app/references/gate-and-tokens.md +0 -93
  623. package/skills/portal-backend-app/references/wiring-and-conventions.md +0 -71
  624. package/skills/xgent-init/references/external-app-CLAUDE.template.md +0 -249
  625. package/vendor/impeccable/bundle/blobs/800cf1c0392b24de7c0a1c6ea6778ecb433dec71c49a150bce96a98477527b2f +0 -1
@@ -0,0 +1,1104 @@
1
+ import { test } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { execFileSync } from 'node:child_process';
4
+ import fs from 'node:fs';
5
+ import os from 'node:os';
6
+ import path from 'node:path';
7
+ import { fileURLToPath, pathToFileURL } from 'node:url';
8
+
9
+ import { ChromeVisualBrowser, findChrome } from '../bin/visual-check.mjs';
10
+ import { MIN_PROJECTED_NODE_TEXT_PX } from '../renderers/shared/desktop-readability.mjs';
11
+
12
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
13
+ const skillRoot = path.resolve(__dirname, '..');
14
+ const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'archify-viewer-chrome-layout-'));
15
+ const chromePath = process.env.ARCHIFY_CHROME ? findChrome() : null;
16
+
17
+ const CASES = {
18
+ architecture: 'web-app.architecture.json',
19
+ workflow: 'agent-tool-call.workflow.json',
20
+ sequence: 'cache-miss-request.sequence.json',
21
+ dataflow: 'product-analytics.dataflow.json',
22
+ lifecycle: 'agent-run.lifecycle.json',
23
+ };
24
+
25
+ function render(mode, example) {
26
+ const output = path.join(tmp, `${mode}.html`);
27
+ execFileSync(process.execPath, [
28
+ path.join(skillRoot, 'bin', 'archify.mjs'),
29
+ 'render',
30
+ mode,
31
+ path.join(skillRoot, 'examples', example),
32
+ output,
33
+ ]);
34
+ return output;
35
+ }
36
+
37
+ function renderWithoutLegend() {
38
+ const source = JSON.parse(fs.readFileSync(
39
+ path.join(skillRoot, 'examples', CASES.architecture),
40
+ 'utf8',
41
+ ));
42
+ source.meta = { ...source.meta, legend: { mode: 'hidden' } };
43
+ const input = path.join(tmp, 'architecture-no-legend.json');
44
+ const output = path.join(tmp, 'architecture-no-legend.html');
45
+ fs.writeFileSync(input, `${JSON.stringify(source, null, 2)}\n`);
46
+ execFileSync(process.execPath, [
47
+ path.join(skillRoot, 'bin', 'archify.mjs'),
48
+ 'render',
49
+ 'architecture',
50
+ input,
51
+ output,
52
+ ]);
53
+ return output;
54
+ }
55
+
56
+ function canonicalSvg(html) {
57
+ return html.match(/<svg\b[\s\S]*?<\/svg>/)?.[0] || '';
58
+ }
59
+
60
+ async function evaluate(browser, sessionId, expression, awaitPromise = false) {
61
+ const response = await browser.cdp.send('Runtime.evaluate', {
62
+ expression,
63
+ awaitPromise,
64
+ returnByValue: true,
65
+ }, sessionId);
66
+ if (response.exceptionDetails) {
67
+ throw new Error(response.exceptionDetails.exception?.description
68
+ || response.exceptionDetails.text
69
+ || 'Runtime.evaluate failed');
70
+ }
71
+ return response.result?.value;
72
+ }
73
+
74
+ async function waitForLayout(browser, sessionId) {
75
+ return evaluate(browser, sessionId, `(function () {
76
+ var fontsReady = document.fonts && document.fonts.ready
77
+ ? document.fonts.ready.catch(function () {})
78
+ : Promise.resolve();
79
+ return fontsReady.then(function () {
80
+ return new Promise(function (resolve, reject) {
81
+ var previous = '';
82
+ var stableFrames = 0;
83
+ var sampledFrames = 0;
84
+ function rect(element) {
85
+ if (!element) return 'missing';
86
+ var value = element.getBoundingClientRect();
87
+ return [value.left, value.top, value.right, value.bottom].map(function (entry) {
88
+ return Math.round(entry * 100) / 100;
89
+ }).join(',');
90
+ }
91
+ function sample() {
92
+ sampledFrames += 1;
93
+ var container = document.querySelector('.diagram-container');
94
+ var current = [
95
+ rect(container),
96
+ rect(container && container.querySelector(':scope > svg')),
97
+ rect(document.querySelector('.diagram-nav')),
98
+ rect(document.querySelector('[data-legend]')),
99
+ rect(document.getElementById('semantic-lens')),
100
+ rect(document.getElementById('overview-map')),
101
+ container ? getComputedStyle(container).getPropertyValue('--archify-nav-reserve') : ''
102
+ ].join('|');
103
+ if (current === previous) stableFrames += 1;
104
+ else {
105
+ previous = current;
106
+ stableFrames = 0;
107
+ }
108
+ /* Final-artifact tests cannot inspect private scheduler flags. Eight
109
+ equal frames cover the public three-frame contract plus any
110
+ reader/viewer handoff queued after a ResizeObserver callback. */
111
+ if (stableFrames >= 8) {
112
+ resolve({ stable: true, snapshot: current, sampledFrames: sampledFrames });
113
+ return;
114
+ }
115
+ if (sampledFrames >= 240) {
116
+ reject(new Error('Final Viewer geometry did not stabilize.'));
117
+ return;
118
+ }
119
+ requestAnimationFrame(sample);
120
+ }
121
+ requestAnimationFrame(sample);
122
+ });
123
+ });
124
+ })()`, true);
125
+ }
126
+
127
+ async function finalGeometry(browser, sessionId) {
128
+ return evaluate(browser, sessionId, `(function () {
129
+ function area(a, b) {
130
+ if (!a || !b || !a.width || !a.height || !b.width || !b.height) return 0;
131
+ return Math.max(0, Math.min(a.right, b.right) - Math.max(a.left, b.left)) *
132
+ Math.max(0, Math.min(a.bottom, b.bottom) - Math.max(a.top, b.top));
133
+ }
134
+ var container = document.querySelector('.diagram-container');
135
+ var legend = document.querySelector('[data-legend]');
136
+ var nav = document.querySelector('.diagram-nav');
137
+ var svg = container && container.querySelector(':scope > svg');
138
+ var lens = document.getElementById('semantic-lens');
139
+ var radar = document.getElementById('overview-map');
140
+ var passport = document.getElementById('focus-chip');
141
+ var chromeReceipt = window.Archify && Archify.viewerChromeLayout
142
+ && typeof Archify.viewerChromeLayout.receipt === 'function'
143
+ ? Archify.viewerChromeLayout.receipt()
144
+ : null;
145
+ var viewBox = svg && svg.viewBox && svg.viewBox.baseVal;
146
+ var projectedScale = svg && viewBox && viewBox.width > 0
147
+ ? Math.min(1, svg.getBoundingClientRect().width / viewBox.width)
148
+ : 0;
149
+ var minimumProjectedNodeTextPx = null;
150
+ if (svg && projectedScale > 0) {
151
+ Array.from(svg.querySelectorAll('text[data-node-label], text[data-boundary-label], text[data-detail="context"]')).forEach(function (text) {
152
+ if (text.hasAttribute('data-detail') && !text.closest('[data-node-id]')) return;
153
+ var sourceFontPx = parseFloat(text.getAttribute('font-size') || '');
154
+ if (!Number.isFinite(sourceFontPx)) return;
155
+ var projectedFontPx = sourceFontPx * projectedScale;
156
+ if (minimumProjectedNodeTextPx == null || projectedFontPx < minimumProjectedNodeTextPx) {
157
+ minimumProjectedNodeTextPx = projectedFontPx;
158
+ }
159
+ });
160
+ }
161
+ var legendRect = legend && getComputedStyle(legend).display !== 'none' ? legend.getBoundingClientRect() : null;
162
+ var navRect = nav && getComputedStyle(nav).display !== 'none' ? nav.getBoundingClientRect() : null;
163
+ var stageRect = window.Archify && Archify.viewerChromeLayout
164
+ && typeof Archify.viewerChromeLayout.stageRect === 'function'
165
+ ? Archify.viewerChromeLayout.stageRect()
166
+ : null;
167
+ var lensRect = lens && !lens.hidden && getComputedStyle(lens).display !== 'none' ? lens.getBoundingClientRect() : null;
168
+ var radarRect = radar && !radar.hidden && getComputedStyle(radar).display !== 'none' ? radar.getBoundingClientRect() : null;
169
+ var passportRect = passport && !passport.hidden && getComputedStyle(passport).display !== 'none' ? passport.getBoundingClientRect() : null;
170
+ var stageDockIntersectionArea = area(stageRect, navRect);
171
+ var semanticDockIntersectionArea = stageDockIntersectionArea > 0 && navRect && svg
172
+ ? Array.from(svg.querySelectorAll('[data-node-id]')).reduce(function (maximum, node) {
173
+ return Math.max(maximum, area(node.getBoundingClientRect(), navRect));
174
+ }, 0)
175
+ : 0;
176
+ return {
177
+ reserve: parseFloat(getComputedStyle(container).getPropertyValue('--archify-nav-reserve')) || 0,
178
+ receiptReserve: chromeReceipt ? chromeReceipt.reserve : null,
179
+ receiptEligible: chromeReceipt ? chromeReceipt.eligible : null,
180
+ receiptStageIntersectionArea: chromeReceipt ? chromeReceipt.stageIntersectionArea : null,
181
+ minimumProjectedNodeTextPx: minimumProjectedNodeTextPx,
182
+ stageGap: navRect && stageRect ? navRect.top - stageRect.bottom : null,
183
+ dockStageIntersectionArea: stageDockIntersectionArea,
184
+ legendDockIntersectionArea: stageDockIntersectionArea > 0 ? area(legendRect, navRect) : 0,
185
+ semanticDockIntersectionArea: semanticDockIntersectionArea,
186
+ legendLensIntersectionArea: area(legendRect, lensRect),
187
+ navLensIntersectionArea: area(navRect, lensRect),
188
+ legendRadarIntersectionArea: area(legendRect, radarRect),
189
+ navRadarIntersectionArea: area(navRect, radarRect),
190
+ legendPassportIntersectionArea: area(legendRect, passportRect),
191
+ navPassportIntersectionArea: area(navRect, passportRect),
192
+ radarPassportIntersectionArea: area(radarRect, passportRect),
193
+ legendRect: legendRect ? { left: legendRect.left, right: legendRect.right, top: legendRect.top, bottom: legendRect.bottom } : null,
194
+ navRect: navRect ? { left: navRect.left, right: navRect.right, top: navRect.top, bottom: navRect.bottom } : null,
195
+ passportRect: passportRect ? { left: passportRect.left, right: passportRect.right, top: passportRect.top, bottom: passportRect.bottom } : null,
196
+ radarRect: radarRect ? { left: radarRect.left, right: radarRect.right, top: radarRect.top, bottom: radarRect.bottom } : null,
197
+ hasLegend: Boolean(legendRect && legendRect.width && legendRect.height),
198
+ scrollWidth: document.documentElement.scrollWidth,
199
+ scrollHeight: document.documentElement.scrollHeight,
200
+ innerWidth: window.innerWidth,
201
+ innerHeight: window.innerHeight,
202
+ containerBottom: container ? container.getBoundingClientRect().bottom : null,
203
+ containerHeight: container ? container.clientHeight : null,
204
+ receiptGap: chromeReceipt ? chromeReceipt.gap : null,
205
+ navBottom: navRect ? navRect.bottom : null
206
+ };
207
+ })()`);
208
+ }
209
+
210
+ async function edgePaintHitsUnderDock(browser, sessionId, selector) {
211
+ return evaluate(browser, sessionId, `(function () {
212
+ var edge = document.querySelector(${JSON.stringify(selector)});
213
+ var nav = document.querySelector('.diagram-nav');
214
+ if (!edge || !nav || typeof edge.getTotalLength !== 'function') return null;
215
+ var navRect = nav.getBoundingClientRect();
216
+ var matrix = edge.getScreenCTM();
217
+ var length = edge.getTotalLength();
218
+ var hits = [];
219
+ for (var offset = 0; offset <= length; offset += 0.25) {
220
+ var point = edge.getPointAtLength(offset).matrixTransform(matrix);
221
+ if (point.x < navRect.left || point.x > navRect.right || point.y < navRect.top || point.y > navRect.bottom) continue;
222
+ if (document.elementsFromPoint(point.x, point.y).includes(edge)) {
223
+ hits.push({ x: point.x, y: point.y });
224
+ if (hits.length >= 5) break;
225
+ }
226
+ }
227
+ return hits;
228
+ })()`);
229
+ }
230
+
231
+ async function load(browser, artifactPath, { width = 1440, height = 900, query = '' } = {}) {
232
+ const sessionId = await browser.sessionPromise;
233
+ await browser.cdp.send('Emulation.setDeviceMetricsOverride', {
234
+ width,
235
+ height,
236
+ deviceScaleFactor: 1,
237
+ mobile: false,
238
+ }, sessionId);
239
+ const loaded = browser.cdp.waitFor('Page.loadEventFired', sessionId);
240
+ const navigation = await browser.cdp.send('Page.navigate', {
241
+ url: pathToFileURL(artifactPath).href + query,
242
+ }, sessionId);
243
+ if (navigation.errorText) throw new Error(`Chrome navigation failed: ${navigation.errorText}`);
244
+ await loaded;
245
+ await evaluate(browser, sessionId, `document.documentElement.setAttribute('data-motion', 'still')`);
246
+ await waitForLayout(browser, sessionId);
247
+ return sessionId;
248
+ }
249
+
250
+ test('the public CLI gives all typed renderers one final Viewer contract', () => {
251
+ const directChildSvg = /<div class="diagram-container"[^>]*>\s*<svg\b/;
252
+ assert.doesNotMatch(
253
+ '<div class="diagram-container"><section></section><svg>',
254
+ directChildSvg,
255
+ 'the direct-child assertion must not cross an intervening wrapper',
256
+ );
257
+ for (const [mode, example] of Object.entries(CASES)) {
258
+ const output = render(mode, example);
259
+ const html = fs.readFileSync(output, 'utf8');
260
+ assert.match(html, /class="[^"]*\bdiagram-nav\b[^"]*"/, mode);
261
+ assert.match(html, /data-legend/, mode);
262
+ assert.match(html, directChildSvg, `${mode} keeps the SVG as a direct child`);
263
+ assert.doesNotMatch(html, /class="diagram-stage"/, `${mode} does not re-nest the exported SVG`);
264
+ assert.doesNotMatch(canonicalSvg(html), /nav-safe-rail|archify-nav-reserve|viewerChromeLayout/, mode);
265
+ execFileSync(process.execPath, [path.join(skillRoot, 'bin', 'archify.mjs'), 'check', output]);
266
+ }
267
+ });
268
+
269
+ test('Viewer chrome remains outside the canonical SVG export boundary', () => {
270
+ const html = fs.readFileSync(render('architecture', CASES.architecture), 'utf8');
271
+ const svg = canonicalSvg(html);
272
+ assert.match(svg, /data-legend/);
273
+ assert.doesNotMatch(svg, /diagram-nav|data-nav-stage-rail|viewerChromeLayout/);
274
+ });
275
+
276
+ test('Dock Safe Rail keeps typed renderers clear across themes, Presentation, and low-height desktops', {
277
+ skip: chromePath ? false : 'Set ARCHIFY_CHROME to run the real browser regression.',
278
+ }, async () => {
279
+ const browser = new ChromeVisualBrowser(chromePath);
280
+ const matrix = Object.keys(CASES).flatMap((mode) => [
281
+ { mode, theme: 'light', width: 1440, height: 820, present: false },
282
+ { mode, theme: 'dark', width: 1440, height: 900, present: true },
283
+ ]);
284
+ try {
285
+ for (const entry of matrix) {
286
+ const query = `?theme=${entry.theme}${entry.present ? '&present=1' : ''}`;
287
+ const sessionId = await load(browser, render(entry.mode, CASES[entry.mode]), {
288
+ width: entry.width,
289
+ height: entry.height,
290
+ query,
291
+ });
292
+ const receipt = await finalGeometry(browser, sessionId);
293
+ const message = `${entry.mode}: ${JSON.stringify({ entry, receipt })}`;
294
+ assert.ok(receipt.reserve > 0, message);
295
+ assert.ok(receipt.stageGap >= 9, message);
296
+ assert.equal(receipt.dockStageIntersectionArea, 0, message);
297
+ assert.ok(receipt.scrollWidth <= receipt.innerWidth, message);
298
+ assert.ok(receipt.navBottom <= receipt.containerBottom + 0.5, message);
299
+ /* Normal artifacts intentionally keep supporting cards in document
300
+ flow on low-height pages. Presentation removes that document scroll
301
+ while every mode keeps the Viewer itself vertically contained. */
302
+ if (entry.present) {
303
+ assert.ok(receipt.scrollHeight <= receipt.innerHeight, message);
304
+ }
305
+ assert.ok(receipt.minimumProjectedNodeTextPx >= MIN_PROJECTED_NODE_TEXT_PX, message);
306
+ }
307
+ } finally {
308
+ await browser.close();
309
+ }
310
+ });
311
+
312
+ test('an artifact with no Legend still receives the desktop stage rail', {
313
+ skip: chromePath ? false : 'Set ARCHIFY_CHROME to run the real browser regression.',
314
+ }, async () => {
315
+ const browser = new ChromeVisualBrowser(chromePath);
316
+ try {
317
+ const sessionId = await load(browser, renderWithoutLegend());
318
+ const receipt = await finalGeometry(browser, sessionId);
319
+
320
+ assert.equal(receipt.hasLegend, false, JSON.stringify(receipt));
321
+ assert.ok(receipt.reserve > 0, JSON.stringify(receipt));
322
+ assert.ok(receipt.stageGap >= 9, JSON.stringify(receipt));
323
+ assert.ok(receipt.navBottom <= receipt.containerBottom + 0.5, JSON.stringify(receipt));
324
+ } finally {
325
+ await browser.close();
326
+ }
327
+ });
328
+
329
+ test('Dock Safe Rail resolves a forced Legend collision across the shared diagram viewer', {
330
+ skip: chromePath ? false : 'Set ARCHIFY_CHROME to run the real browser regression.',
331
+ }, async () => {
332
+ const browser = new ChromeVisualBrowser(chromePath);
333
+ try {
334
+ for (const [mode, example] of Object.entries(CASES)) {
335
+ const sessionId = await load(browser, render(mode, example));
336
+ const setup = await evaluate(browser, sessionId, `(function () {
337
+ var nav = document.querySelector('.diagram-nav');
338
+ var legendElement = document.querySelector('[data-legend]');
339
+ if (!legendElement) {
340
+ return { noLegend: true };
341
+ }
342
+ var initialLegend = legendElement.getBoundingClientRect();
343
+ var containerRect = document.querySelector('.diagram-container').getBoundingClientRect();
344
+ nav.style.right = 'auto';
345
+ nav.style.left = Math.max(0, initialLegend.left - containerRect.left) + 'px';
346
+ nav.style.bottom = Math.max(0, containerRect.bottom - initialLegend.bottom) + 'px';
347
+ nav.style.width = Math.max(240, initialLegend.width) + 'px';
348
+ window.dispatchEvent(new Event('resize'));
349
+ return { noLegend: false };
350
+ })()`);
351
+
352
+ if (setup.noLegend) {
353
+ const receipt = await finalGeometry(browser, sessionId);
354
+ assert.ok(receipt.reserve > 0, mode);
355
+ assert.ok(receipt.stageGap >= 9, mode);
356
+ continue;
357
+ }
358
+ await waitForLayout(browser, sessionId);
359
+ const receipt = await finalGeometry(browser, sessionId);
360
+ assert.ok(receipt.reserve > 0, `${mode}: ${JSON.stringify(receipt)}`);
361
+ assert.equal(receipt.legendDockIntersectionArea, 0, `${mode}: ${JSON.stringify(receipt)}`);
362
+ assert.ok(receipt.stageGap >= 9, `${mode}: ${JSON.stringify(receipt)}`);
363
+ }
364
+ } finally {
365
+ await browser.close();
366
+ }
367
+ });
368
+
369
+ test('Maka remains collision-free at the reported Retina-equivalent viewport', {
370
+ skip: chromePath ? false : 'Set ARCHIFY_CHROME to run the real browser regression.',
371
+ }, async () => {
372
+ const output = path.join(tmp, 'maka-architecture.html');
373
+ execFileSync(process.execPath, [
374
+ path.join(skillRoot, 'bin', 'archify.mjs'),
375
+ 'render',
376
+ 'architecture',
377
+ path.resolve(skillRoot, '..', 'examples', 'maka-architecture.architecture.json'),
378
+ output,
379
+ ]);
380
+ const browser = new ChromeVisualBrowser(chromePath);
381
+ try {
382
+ const sessionId = await load(browser, output, { width: 1484, height: 724 });
383
+ const receipt = await evaluate(browser, sessionId, `(function () {
384
+ var legend = document.querySelector('[data-legend]').getBoundingClientRect();
385
+ var dock = document.querySelector('.diagram-nav').getBoundingClientRect();
386
+ var width = Math.max(0, Math.min(legend.right, dock.right) - Math.max(legend.left, dock.left));
387
+ var height = Math.max(0, Math.min(legend.bottom, dock.bottom) - Math.max(legend.top, dock.top));
388
+ return {
389
+ intersectionArea: width * height,
390
+ scrollWidth: document.documentElement.scrollWidth,
391
+ innerWidth: window.innerWidth
392
+ };
393
+ })()`);
394
+
395
+ assert.equal(receipt.intersectionArea, 0, JSON.stringify(receipt));
396
+ assert.ok(receipt.scrollWidth <= receipt.innerWidth, JSON.stringify(receipt));
397
+ } finally {
398
+ await browser.close();
399
+ }
400
+ });
401
+
402
+ test('a real 5px Legend gap keeps the stage rail and Legend clear', {
403
+ skip: chromePath ? false : 'Set ARCHIFY_CHROME to run the real browser regression.',
404
+ }, async () => {
405
+ const browser = new ChromeVisualBrowser(chromePath);
406
+ try {
407
+ const sessionId = await load(browser, render('architecture', CASES.architecture));
408
+ await evaluate(browser, sessionId, `(function () {
409
+ var container = document.querySelector('.diagram-container');
410
+ var legend = document.querySelector('[data-legend]');
411
+ var nav = document.querySelector('.diagram-nav');
412
+ var legendRect = legend.getBoundingClientRect();
413
+ var containerRect = container.getBoundingClientRect();
414
+ nav.style.right = 'auto';
415
+ nav.style.left = (legendRect.right - containerRect.left + 5) + 'px';
416
+ nav.style.bottom = Math.max(0, containerRect.bottom - legendRect.bottom) + 'px';
417
+ window.dispatchEvent(new Event('resize'));
418
+ })()`);
419
+ await waitForLayout(browser, sessionId);
420
+ const receipt = await finalGeometry(browser, sessionId);
421
+
422
+ assert.equal(receipt.legendDockIntersectionArea, 0, JSON.stringify(receipt));
423
+ assert.ok(receipt.reserve > 0, JSON.stringify(receipt));
424
+ assert.ok(receipt.stageGap >= 9, JSON.stringify(receipt));
425
+ } finally {
426
+ await browser.close();
427
+ }
428
+ });
429
+
430
+ test('Presentation keeps its visible Dock clear of a colliding Legend', {
431
+ skip: chromePath ? false : 'Set ARCHIFY_CHROME to run the real browser regression.',
432
+ }, async () => {
433
+ const browser = new ChromeVisualBrowser(chromePath);
434
+ try {
435
+ const sessionId = await load(browser, render('architecture', CASES.architecture), { query: '?present=1' });
436
+ await evaluate(browser, sessionId, `(function () {
437
+ var container = document.querySelector('.diagram-container');
438
+ var legend = document.querySelector('[data-legend]');
439
+ var nav = document.querySelector('.diagram-nav');
440
+ var legendRect = legend.getBoundingClientRect();
441
+ var containerRect = container.getBoundingClientRect();
442
+ nav.style.right = 'auto';
443
+ nav.style.left = Math.max(0, legendRect.left - containerRect.left) + 'px';
444
+ nav.style.bottom = Math.max(0, containerRect.bottom - legendRect.bottom) + 'px';
445
+ nav.style.width = Math.max(240, legendRect.width) + 'px';
446
+ window.dispatchEvent(new Event('resize'));
447
+ })()`);
448
+ await waitForLayout(browser, sessionId);
449
+ const receipt = await finalGeometry(browser, sessionId);
450
+
451
+ assert.equal(receipt.legendDockIntersectionArea, 0, JSON.stringify(receipt));
452
+ assert.ok(receipt.reserve > 0, JSON.stringify(receipt));
453
+ } finally {
454
+ await browser.close();
455
+ }
456
+ });
457
+
458
+ test('manual zoom and pan reschedules Legend and Dock collision measurement', {
459
+ skip: chromePath ? false : 'Set ARCHIFY_CHROME to run the real browser regression.',
460
+ }, async () => {
461
+ const browser = new ChromeVisualBrowser(chromePath);
462
+ try {
463
+ const sessionId = await load(browser, render('architecture', CASES.architecture));
464
+ await evaluate(browser, sessionId, `(function () {
465
+ var container = document.querySelector('.diagram-container');
466
+ var zoomIn = document.querySelector('[data-view="in"]');
467
+ for (var index = 0; index < 8; index += 1) zoomIn.click();
468
+ var svg = container.querySelector(':scope > svg');
469
+ var rect = svg.getBoundingClientRect();
470
+ var pointer = { bubbles: true, pointerId: 7, button: 0 };
471
+ var startX = rect.left + rect.width / 2;
472
+ var startY = rect.top + rect.height / 2;
473
+ container.dispatchEvent(new PointerEvent('pointerdown', Object.assign({ clientX: startX, clientY: startY }, pointer)));
474
+ container.dispatchEvent(new PointerEvent('pointermove', Object.assign({ clientX: startX + 210, clientY: startY - 500 }, pointer)));
475
+ container.dispatchEvent(new PointerEvent('pointerup', Object.assign({ clientX: startX + 210, clientY: startY - 500 }, pointer)));
476
+ })()`);
477
+ await waitForLayout(browser, sessionId);
478
+ const receipt = await finalGeometry(browser, sessionId);
479
+
480
+ assert.equal(receipt.legendDockIntersectionArea, 0, JSON.stringify(receipt));
481
+ assert.equal(receipt.semanticDockIntersectionArea, 0, JSON.stringify(receipt));
482
+ assert.ok(receipt.reserve > 0, JSON.stringify(receipt));
483
+ } finally {
484
+ await browser.close();
485
+ }
486
+ });
487
+
488
+ test('camera pan clips authored relationship paint at the protected stage boundary', {
489
+ skip: chromePath ? false : 'Set ARCHIFY_CHROME to run the real browser regression.',
490
+ }, async () => {
491
+ const browser = new ChromeVisualBrowser(chromePath);
492
+ try {
493
+ const sessionId = await load(browser, render('architecture', CASES.architecture));
494
+ await evaluate(browser, sessionId, `(function () {
495
+ var container = document.querySelector('.diagram-container');
496
+ var zoomIn = document.querySelector('[data-view="in"]');
497
+ for (var index = 0; index < 8; index += 1) zoomIn.click();
498
+ var svg = container.querySelector(':scope > svg');
499
+ var rect = svg.getBoundingClientRect();
500
+ var pointer = { bubbles: true, pointerId: 11, button: 0 };
501
+ var startX = rect.left + rect.width / 2;
502
+ var startY = rect.top + rect.height / 2;
503
+ container.dispatchEvent(new PointerEvent('pointerdown', Object.assign({ clientX: startX, clientY: startY }, pointer)));
504
+ container.dispatchEvent(new PointerEvent('pointermove', Object.assign({ clientX: startX, clientY: startY + 500 }, pointer)));
505
+ container.dispatchEvent(new PointerEvent('pointerup', Object.assign({ clientX: startX, clientY: startY + 500 }, pointer)));
506
+ })()`);
507
+ await waitForLayout(browser, sessionId);
508
+ const hits = await edgePaintHitsUnderDock(
509
+ browser,
510
+ sessionId,
511
+ 'path[data-edge-id="jwt-verification"][data-edge-from="auth"][data-edge-to="api"]',
512
+ );
513
+
514
+ assert.deepEqual(hits, [], JSON.stringify(hits));
515
+ } finally {
516
+ await browser.close();
517
+ }
518
+ });
519
+
520
+ test('live camera transitions keep authored relationship paint outside the Dock on every frame', {
521
+ skip: chromePath ? false : 'Set ARCHIFY_CHROME to run the real browser regression.',
522
+ }, async () => {
523
+ const browser = new ChromeVisualBrowser(chromePath);
524
+ const artifact = render('architecture', CASES.architecture);
525
+ const scenarios = [
526
+ { name: 'zoom-in', setupZoomClicks: 7, action: 'in', duration: 260, clearsClip: false },
527
+ { name: 'zoom-out', setupZoomClicks: 8, action: 'out', duration: 260, clearsClip: false },
528
+ { name: 'reset', setupZoomClicks: 8, action: 'reset', duration: 420, clearsClip: true },
529
+ { name: 'interrupted zoom', setupZoomClicks: 8, action: 'interrupt', duration: 420, clearsClip: false },
530
+ ];
531
+ try {
532
+ for (const scenario of scenarios) {
533
+ const sessionId = await load(browser, artifact);
534
+ const result = await evaluate(browser, sessionId, `(function () {
535
+ var scenario = ${JSON.stringify(scenario)};
536
+ var container = document.querySelector('.diagram-container');
537
+ var svg = container.querySelector(':scope > svg');
538
+ var zoomIn = document.querySelector('[data-view="in"]');
539
+ var zoomOut = document.querySelector('[data-view="out"]');
540
+ for (var index = 0; index < scenario.setupZoomClicks; index += 1) zoomIn.click();
541
+
542
+ var rect = svg.getBoundingClientRect();
543
+ var pointer = { bubbles: true, pointerId: 17, button: 0 };
544
+ var x = rect.left + rect.width / 2;
545
+ var y = rect.top + rect.height / 2;
546
+ container.dispatchEvent(new PointerEvent('pointerdown', Object.assign({ clientX: x, clientY: y }, pointer)));
547
+ container.dispatchEvent(new PointerEvent('pointermove', Object.assign({ clientX: x, clientY: y + 500 }, pointer)));
548
+ container.dispatchEvent(new PointerEvent('pointerup', Object.assign({ clientX: x, clientY: y + 500 }, pointer)));
549
+
550
+ document.documentElement.removeAttribute('data-motion');
551
+ return new Promise(function (resolve) {
552
+ requestAnimationFrame(function () {
553
+ if (scenario.action === 'in') zoomIn.click();
554
+ else if (scenario.action === 'out') zoomOut.click();
555
+ else if (scenario.action === 'reset') document.querySelector('[data-view="reset"]').click();
556
+ else {
557
+ zoomOut.click();
558
+ requestAnimationFrame(function () { zoomIn.click(); });
559
+ }
560
+ var edge = document.querySelector(
561
+ 'path[data-edge-id="jwt-verification"][data-edge-from="auth"][data-edge-to="api"]'
562
+ );
563
+ var hits = [];
564
+ var started = performance.now();
565
+ function sample(now) {
566
+ var dock = document.querySelector('.diagram-nav').getBoundingClientRect();
567
+ var matrix = edge.getScreenCTM();
568
+ var length = edge.getTotalLength();
569
+ for (var offset = 0; offset <= length; offset += 0.25) {
570
+ var point = edge.getPointAtLength(offset).matrixTransform(matrix);
571
+ if (
572
+ point.x >= dock.left && point.x <= dock.right &&
573
+ point.y >= dock.top && point.y <= dock.bottom &&
574
+ document.elementsFromPoint(point.x, point.y).includes(edge)
575
+ ) {
576
+ hits.push({ ms: now - started, x: point.x, y: point.y });
577
+ break;
578
+ }
579
+ }
580
+ if (now - started < scenario.duration) requestAnimationFrame(sample);
581
+ else resolve({ hits: hits, clipPath: svg.style.getPropertyValue('clip-path') });
582
+ }
583
+ requestAnimationFrame(sample);
584
+ });
585
+ });
586
+ })()`, true);
587
+
588
+ assert.deepEqual(result.hits, [], `${scenario.name}: ${JSON.stringify(result.hits)}`);
589
+ if (scenario.clearsClip) {
590
+ assert.equal(result.clipPath, '', `${scenario.name} retains runtime clip-path`);
591
+ }
592
+ }
593
+ } finally {
594
+ await browser.close();
595
+ }
596
+ });
597
+
598
+ test('zoom keeps the desktop rail stable and reports protected stage geometry', {
599
+ skip: chromePath ? false : 'Set ARCHIFY_CHROME to run the real browser regression.',
600
+ }, async () => {
601
+ const browser = new ChromeVisualBrowser(chromePath);
602
+ try {
603
+ const sessionId = await load(browser, render('architecture', CASES.architecture));
604
+ const baseline = await finalGeometry(browser, sessionId);
605
+ await evaluate(browser, sessionId, `(function () {
606
+ var container = document.querySelector('.diagram-container');
607
+ var zoomIn = document.querySelector('[data-view="in"]');
608
+ for (var index = 0; index < 8; index += 1) zoomIn.click();
609
+ var svg = container.querySelector(':scope > svg');
610
+ var rect = svg.getBoundingClientRect();
611
+ var pointer = { bubbles: true, pointerId: 13, button: 0 };
612
+ var startX = rect.left + rect.width / 2;
613
+ var startY = rect.top + rect.height / 2;
614
+ container.dispatchEvent(new PointerEvent('pointerdown', Object.assign({ clientX: startX, clientY: startY }, pointer)));
615
+ container.dispatchEvent(new PointerEvent('pointermove', Object.assign({ clientX: startX + 210, clientY: startY - 500 }, pointer)));
616
+ container.dispatchEvent(new PointerEvent('pointerup', Object.assign({ clientX: startX + 210, clientY: startY - 500 }, pointer)));
617
+ })()`);
618
+ await waitForLayout(browser, sessionId);
619
+ const zoomed = await finalGeometry(browser, sessionId);
620
+
621
+ assert.ok(Math.abs(zoomed.reserve - baseline.reserve) <= 1, JSON.stringify({ baseline, zoomed }));
622
+ assert.equal(zoomed.dockStageIntersectionArea, 0, JSON.stringify({ baseline, zoomed }));
623
+ assert.equal(zoomed.receiptStageIntersectionArea, 0, JSON.stringify({ baseline, zoomed }));
624
+ } finally {
625
+ await browser.close();
626
+ }
627
+ });
628
+
629
+ test('Reset followed immediately by zoom and pan retains a collision-free desktop rail', {
630
+ skip: chromePath ? false : 'Set ARCHIFY_CHROME to run the real browser regression.',
631
+ }, async () => {
632
+ const browser = new ChromeVisualBrowser(chromePath);
633
+ try {
634
+ const sessionId = await load(browser, render('architecture', CASES.architecture));
635
+ const baseline = await finalGeometry(browser, sessionId);
636
+ await evaluate(browser, sessionId, `(function () {
637
+ var container = document.querySelector('.diagram-container');
638
+ document.querySelector('[data-view="reset"]').click();
639
+ var zoomIn = document.querySelector('[data-view="in"]');
640
+ for (var index = 0; index < 8; index += 1) zoomIn.click();
641
+ var svg = container.querySelector(':scope > svg');
642
+ var rect = svg.getBoundingClientRect();
643
+ var pointer = { bubbles: true, pointerId: 11, button: 0 };
644
+ var startX = rect.left + rect.width / 2;
645
+ var startY = rect.top + rect.height / 2;
646
+ container.dispatchEvent(new PointerEvent('pointerdown', Object.assign({ clientX: startX, clientY: startY }, pointer)));
647
+ container.dispatchEvent(new PointerEvent('pointermove', Object.assign({ clientX: startX, clientY: startY + 500 }, pointer)));
648
+ container.dispatchEvent(new PointerEvent('pointerup', Object.assign({ clientX: startX, clientY: startY + 500 }, pointer)));
649
+ })()`);
650
+ await waitForLayout(browser, sessionId);
651
+ const receipt = await finalGeometry(browser, sessionId);
652
+
653
+ assert.ok(receipt.reserve > 0, JSON.stringify({ baseline, receipt }));
654
+ assert.ok(receipt.reserve <= baseline.reserve + 1, JSON.stringify({ baseline, receipt }));
655
+ assert.equal(receipt.semanticDockIntersectionArea, 0, JSON.stringify({ baseline, receipt }));
656
+ } finally {
657
+ await browser.close();
658
+ }
659
+ });
660
+
661
+ test('zoomed camera restores its bounded desktop rail after crossing the mobile breakpoint', {
662
+ skip: chromePath ? false : 'Set ARCHIFY_CHROME to run the real browser regression.',
663
+ }, async () => {
664
+ const browser = new ChromeVisualBrowser(chromePath);
665
+ try {
666
+ const sessionId = await load(browser, render('architecture', CASES.architecture));
667
+ const baseline = await finalGeometry(browser, sessionId);
668
+ await evaluate(browser, sessionId, `(function () {
669
+ var zoomIn = document.querySelector('[data-view="in"]');
670
+ for (var index = 0; index < 8; index += 1) zoomIn.click();
671
+ })()`);
672
+ await waitForLayout(browser, sessionId);
673
+ const zoomed = await finalGeometry(browser, sessionId);
674
+
675
+ await browser.cdp.send('Emulation.setDeviceMetricsOverride', {
676
+ width: 720,
677
+ height: 900,
678
+ deviceScaleFactor: 1,
679
+ mobile: false,
680
+ }, sessionId);
681
+ await waitForLayout(browser, sessionId);
682
+ const mobile = await finalGeometry(browser, sessionId);
683
+ assert.equal(mobile.reserve, 0, JSON.stringify(mobile));
684
+
685
+ await browser.cdp.send('Emulation.setDeviceMetricsOverride', {
686
+ width: 1440,
687
+ height: 900,
688
+ deviceScaleFactor: 1,
689
+ mobile: false,
690
+ }, sessionId);
691
+ await waitForLayout(browser, sessionId);
692
+ const restored = await finalGeometry(browser, sessionId);
693
+
694
+ assert.ok(Math.abs(restored.reserve - baseline.reserve) <= 1, JSON.stringify({ baseline, zoomed, restored }));
695
+ assert.equal(restored.receiptReserve, restored.reserve, JSON.stringify(restored));
696
+ assert.equal(restored.receiptEligible, true, JSON.stringify(restored));
697
+ assert.ok(restored.scrollHeight <= restored.innerHeight, JSON.stringify(restored));
698
+ } finally {
699
+ await browser.close();
700
+ }
701
+ });
702
+
703
+ test('localized multiline Legends remain clear across required viewports, themes, and presets', {
704
+ skip: chromePath ? false : 'Set ARCHIFY_CHROME to run the real browser regression.',
705
+ }, async () => {
706
+ const browser = new ChromeVisualBrowser(chromePath);
707
+ const viewports = [[1440, 900], [1600, 1000], [1920, 1080], [2048, 1320]];
708
+ const cases = viewports.flatMap(([width, height]) => (
709
+ ['light', 'dark'].flatMap((theme) => (
710
+ ['classic', 'signal-flow', 'blueprint', 'editorial'].map((preset) => ({
711
+ width,
712
+ height,
713
+ theme,
714
+ preset,
715
+ }))
716
+ ))
717
+ ));
718
+ try {
719
+ const sessionId = await load(browser, render('architecture', CASES.architecture), { width: 1920, height: 1080 });
720
+ await evaluate(browser, sessionId, `(function () {
721
+ var text = document.querySelector('[data-legend] text');
722
+ var x = text.getAttribute('x') || '0';
723
+ var namespace = 'http://www.w3.org/2000/svg';
724
+ text.textContent = '';
725
+ var first = document.createElementNS(namespace, 'tspan');
726
+ first.setAttribute('x', x);
727
+ first.textContent = '应用与运行时编排服务(本地化长标签)';
728
+ var second = document.createElementNS(namespace, 'tspan');
729
+ second.setAttribute('x', x);
730
+ second.setAttribute('dy', '14');
731
+ second.textContent = '第二行语义说明';
732
+ text.appendChild(first);
733
+ text.appendChild(second);
734
+ })()`);
735
+
736
+ for (const entry of cases) {
737
+ await browser.cdp.send('Emulation.setDeviceMetricsOverride', {
738
+ width: entry.width,
739
+ height: entry.height,
740
+ deviceScaleFactor: 1,
741
+ mobile: false,
742
+ }, sessionId);
743
+ await evaluate(browser, sessionId, `(function () {
744
+ var html = document.documentElement;
745
+ var nav = document.querySelector('.diagram-nav');
746
+ html.setAttribute('data-preset', ${JSON.stringify(entry.preset)});
747
+ html.setAttribute('data-theme', ${JSON.stringify(entry.theme)});
748
+ document.querySelector('[data-view="reset"]').click();
749
+ nav.removeAttribute('style');
750
+ window.dispatchEvent(new Event('resize'));
751
+ })()`);
752
+ await waitForLayout(browser, sessionId);
753
+ let receipt = null;
754
+ for (let attempt = 0; attempt < 3; attempt += 1) {
755
+ await evaluate(browser, sessionId, `(function () {
756
+ var container = document.querySelector('.diagram-container');
757
+ var legend = document.querySelector('[data-legend]').getBoundingClientRect();
758
+ var nav = document.querySelector('.diagram-nav');
759
+ var containerRect = container.getBoundingClientRect();
760
+ nav.style.right = '0';
761
+ nav.style.left = '0';
762
+ nav.style.bottom = Math.max(0, containerRect.bottom - legend.bottom) + 'px';
763
+ nav.style.width = 'auto';
764
+ window.dispatchEvent(new Event('resize'));
765
+ })()`);
766
+ await waitForLayout(browser, sessionId);
767
+ receipt = await finalGeometry(browser, sessionId);
768
+ if (receipt.reserve > 0) break;
769
+ }
770
+ assert.equal(receipt.legendDockIntersectionArea, 0, JSON.stringify({ ...entry, receipt }));
771
+ assert.ok(receipt.reserve > 0, JSON.stringify({ ...entry, receipt }));
772
+ assert.equal(receipt.dockStageIntersectionArea, 0, JSON.stringify({ ...entry, receipt }));
773
+ assert.ok(receipt.stageGap >= 9, JSON.stringify({ ...entry, receipt }));
774
+ }
775
+ } finally {
776
+ await browser.close();
777
+ }
778
+ });
779
+
780
+ test('Semantic Lens and Radar protect the final Legend and Dock rectangles', {
781
+ skip: chromePath ? false : 'Set ARCHIFY_CHROME to run the real browser regression.',
782
+ }, async () => {
783
+ const browser = new ChromeVisualBrowser(chromePath);
784
+ try {
785
+ const sessionId = await load(browser, render('architecture', CASES.architecture), { width: 1440, height: 900 });
786
+ await evaluate(browser, sessionId, `document.getElementById('btn-semantic-lens').click()`);
787
+ await waitForLayout(browser, sessionId);
788
+ let receipt = await finalGeometry(browser, sessionId);
789
+ assert.equal(receipt.legendLensIntersectionArea, 0, JSON.stringify(receipt));
790
+ assert.equal(receipt.navLensIntersectionArea, 0, JSON.stringify(receipt));
791
+
792
+ await evaluate(browser, sessionId, `(function () {
793
+ document.getElementById('btn-semantic-lens').click();
794
+ document.getElementById('btn-overview-map').click();
795
+ })()`);
796
+ await waitForLayout(browser, sessionId);
797
+ receipt = await finalGeometry(browser, sessionId);
798
+ assert.equal(receipt.legendRadarIntersectionArea, 0, JSON.stringify(receipt));
799
+ assert.equal(receipt.navRadarIntersectionArea, 0, JSON.stringify(receipt));
800
+ } finally {
801
+ await browser.close();
802
+ }
803
+ });
804
+
805
+ test('Radar, Passport, Legend, and Dock remain mutually clear on desktop and narrow viewports', {
806
+ skip: chromePath ? false : 'Set ARCHIFY_CHROME to run the real browser regression.',
807
+ }, async () => {
808
+ const browser = new ChromeVisualBrowser(chromePath);
809
+ try {
810
+ const artifact = render('architecture', CASES.architecture);
811
+ for (const viewport of [
812
+ { width: 1440, height: 900, label: 'desktop' },
813
+ { width: 390, height: 600, label: 'narrow' },
814
+ ]) {
815
+ const sessionId = await load(browser, artifact, viewport);
816
+ await evaluate(browser, sessionId, `(function () {
817
+ var container = document.querySelector('.diagram-container');
818
+ window.scrollTo(0, Math.max(0, container.offsetTop));
819
+ Archify.focus.set('lb', { toggle: false });
820
+ Archify.radar.open();
821
+ window.dispatchEvent(new Event('resize'));
822
+ })()`);
823
+ await waitForLayout(browser, sessionId);
824
+ const receipt = await finalGeometry(browser, sessionId);
825
+ const message = viewport.label + ': ' + JSON.stringify(receipt);
826
+
827
+ assert.equal(receipt.legendDockIntersectionArea, 0, message);
828
+ assert.equal(receipt.legendPassportIntersectionArea, 0, message);
829
+ assert.equal(receipt.navPassportIntersectionArea, 0, message);
830
+ assert.equal(receipt.legendRadarIntersectionArea, 0, message);
831
+ assert.equal(receipt.navRadarIntersectionArea, 0, message);
832
+ assert.equal(receipt.radarPassportIntersectionArea, 0, message);
833
+ }
834
+ } finally {
835
+ await browser.close();
836
+ }
837
+ });
838
+
839
+ test('mobile, embed, and print keep zero reserve while hidden Legends retain the stage rail', {
840
+ skip: chromePath ? false : 'Set ARCHIFY_CHROME to run the real browser regression.',
841
+ }, async () => {
842
+ const browser = new ChromeVisualBrowser(chromePath);
843
+ try {
844
+ let sessionId = await load(browser, render('architecture', CASES.architecture), { width: 720, height: 900 });
845
+ let receipt = await finalGeometry(browser, sessionId);
846
+ assert.equal(receipt.reserve, 0, `mobile: ${JSON.stringify(receipt)}`);
847
+ assert.equal(receipt.legendDockIntersectionArea, 0, `mobile: ${JSON.stringify(receipt)}`);
848
+
849
+ sessionId = await load(browser, render('architecture', CASES.architecture), { query: '?embed=1' });
850
+ receipt = await finalGeometry(browser, sessionId);
851
+ assert.equal(receipt.reserve, 0, `embed: ${JSON.stringify(receipt)}`);
852
+
853
+ sessionId = await load(browser, render('architecture', CASES.architecture));
854
+ await evaluate(browser, sessionId, `(function () {
855
+ document.querySelector('[data-legend]').hidden = true;
856
+ window.dispatchEvent(new Event('resize'));
857
+ })()`);
858
+ await waitForLayout(browser, sessionId);
859
+ receipt = await finalGeometry(browser, sessionId);
860
+ assert.ok(receipt.reserve > 0, `hidden: ${JSON.stringify(receipt)}`);
861
+ assert.ok(receipt.stageGap >= 9, `hidden: ${JSON.stringify(receipt)}`);
862
+
863
+ await browser.cdp.send('Emulation.setEmulatedMedia', { media: 'print' }, sessionId);
864
+ await waitForLayout(browser, sessionId);
865
+ receipt = await finalGeometry(browser, sessionId);
866
+ assert.equal(receipt.reserve, 0, `print: ${JSON.stringify(receipt)}`);
867
+ } finally {
868
+ await browser.close();
869
+ }
870
+ });
871
+
872
+
873
+ test('Chrome Layout preserves scheduling, mode restoration and Reader handoffs', {
874
+ skip: chromePath ? false : 'Set ARCHIFY_CHROME to run the real browser regression.',
875
+ }, async (t) => {
876
+ const browser = new ChromeVisualBrowser(chromePath);
877
+ t.after(() => browser.close());
878
+ const evidence = process.env.ARCHIFY_CHROME_LAYOUT_EVIDENCE;
879
+ if (evidence) fs.mkdirSync(evidence, { recursive: true });
880
+ const observations = [];
881
+ const file = render('architecture', CASES.architecture);
882
+ const session = await browser.sessionPromise;
883
+ const send = (method, params = {}) => browser.cdp.send(method, params, session);
884
+ const run = (expression, awaitPromise = false) => evaluate(browser, session, expression, awaitPromise);
885
+ await send('Page.addScriptToEvaluateOnNewDocument', {
886
+ source: `window.chromeLayoutErrors = [];
887
+ addEventListener('error', e => chromeLayoutErrors.push(e.message));
888
+ addEventListener('unhandledrejection', e => chromeLayoutErrors.push(String(e.reason)));`,
889
+ });
890
+ async function resize(width, height = 900) {
891
+ await send('Emulation.setDeviceMetricsOverride', { width, height, deviceScaleFactor: 1, mobile: false });
892
+ await waitForLayout(browser, session);
893
+ }
894
+ async function state(label) {
895
+ // Read DOM first, without receipt(), measure() or public stability methods.
896
+ // This ensures those methods cannot make a missed automatic event pass.
897
+ const raw = await run(`(() => {
898
+ const html = document.documentElement;
899
+ const container = document.querySelector('.diagram-container');
900
+ const svg = container.querySelector(':scope > svg');
901
+ return {
902
+ reserve: parseFloat(container.style.getPropertyValue('--archify-nav-reserve')) || 0,
903
+ rootRail: html.getAttribute('data-nav-stage-rail'), rail: container.getAttribute('data-nav-stage-rail'),
904
+ reader: html.getAttribute('data-reader-layout'), width: innerWidth,
905
+ viewBox: svg.getAttribute('viewBox'),
906
+ errors: chromeLayoutErrors,
907
+ external: performance.getEntriesByType('resource').map(e => e.name).filter(n => /^https?:/.test(n))
908
+ };
909
+ })()`);
910
+ assert.deepEqual(raw.errors, [], label);
911
+ assert.deepEqual(raw.external, [], label);
912
+ const geometry = await finalGeometry(browser, session);
913
+ assert.equal(raw.reserve, geometry.receiptReserve, `${label}: observation must not repair stale state`);
914
+ assert.equal(raw.rootRail, raw.reserve ? 'true' : null, label);
915
+ assert.equal(raw.rail, raw.rootRail, label);
916
+ observations.push({ label, ...raw, geometry });
917
+ return { ...raw, geometry };
918
+ }
919
+ function zero(value) {
920
+ assert.equal(value.reserve, 0);
921
+ assert.equal(value.rail, null);
922
+ assert.equal(value.rootRail, null);
923
+ }
924
+ function clearStage(value) {
925
+ assert.equal(value.geometry.dockStageIntersectionArea, 0, JSON.stringify(value));
926
+ assert.ok(value.geometry.stageGap >= 9, JSON.stringify(value));
927
+ }
928
+ function variant(name, source) {
929
+ const original = fs.readFileSync(file, 'utf8');
930
+ const html = original.replace(' <script>\n var Archify = {};',
931
+ () => ` <script>${source}</script>\n <script>\n var Archify = {};`);
932
+ assert.notEqual(html, original);
933
+ const output = path.join(tmp, `chrome-${name}.html`);
934
+ fs.writeFileSync(output, html);
935
+ return output;
936
+ }
937
+ try {
938
+ await t.test('automatic resize crosses Chrome and Reader thresholds without reserve accumulation', async () => {
939
+ await load(browser, file);
940
+ const initial = await state('threshold-initial');
941
+ for (const width of [719, 720, 721, 1023, 1024, 1025, 720, 1440]) {
942
+ await resize(width);
943
+ const current = await state(`threshold-${width}-${observations.length}`);
944
+ assert.equal(current.geometry.receiptEligible, width > 720);
945
+ assert.equal(current.reader, width >= 1024 ? 'adaptive' : null);
946
+ assert.equal(current.viewBox, initial.viewBox);
947
+ if (width <= 720) zero(current);
948
+ else clearStage(current);
949
+ if (width === 1440) assert.equal(current.reserve, initial.reserve);
950
+ }
951
+ });
952
+
953
+ await t.test('automatic observer callbacks handle navigation size, visibility and content changes', async () => {
954
+ await load(browser, file);
955
+ const initial = await state('observer-initial');
956
+ await run(`document.querySelector('.diagram-nav').style.display = 'none'`);
957
+ await waitForLayout(browser, session);
958
+ zero(await state('observer-nav-hidden'));
959
+ await run(`document.querySelector('.diagram-nav').style.display = ''`);
960
+ await waitForLayout(browser, session);
961
+ const restored = await state('observer-nav-restored');
962
+ assert.equal(restored.reserve, initial.reserve);
963
+ await run(`document.querySelector('.diagram-nav').style.height = '120px'`);
964
+ await waitForLayout(browser, session);
965
+ const taller = await state('observer-nav-taller');
966
+ assert.ok(taller.reserve > initial.reserve);
967
+ clearStage(taller);
968
+ // A legend mutation drives the existing MutationObserver. Font/preset
969
+ // rules remain the production rules; no public layout method is invoked.
970
+ await run(`document.querySelector('[data-legend]').setAttribute('transform', 'translate(0,-20)')`);
971
+ await waitForLayout(browser, session);
972
+ clearStage(await state('observer-legend-changed'));
973
+ await run(`document.querySelector('.diagram-nav').style.height = ''; window.dispatchEvent(new Event('resize'))`);
974
+ await waitForLayout(browser, session);
975
+ assert.equal((await state('observer-returned')).reserve, initial.reserve);
976
+ await run(`document.querySelector('.diagram-nav').style.bottom = '-200px'; window.dispatchEvent(new Event('resize'))`);
977
+ await waitForLayout(browser, session);
978
+ zero(await state('no-reserve-needed'));
979
+ });
980
+
981
+ await t.test('embed and print restore a zoomed rail, while Presentation remains eligible', async () => {
982
+ for (const mode of ['embed', 'print']) {
983
+ if (mode === 'print') await send('Emulation.setEmulatedMedia', { media: 'print' });
984
+ await load(browser, file, { query: mode === 'embed' ? '?embed=1' : '' });
985
+ zero(await state(`${mode}-initial`));
986
+ await send('Emulation.setEmulatedMedia', { media: '' });
987
+ await load(browser, file);
988
+ const initial = await state(`${mode}-ordinary`);
989
+ await run('Archify.view.zoomIn()');
990
+ await waitForLayout(browser, session);
991
+ for (let cycle = 0; cycle < 2; cycle += 1) {
992
+ if (mode === 'embed') await run(`document.documentElement.setAttribute('data-embed', 'true')`);
993
+ else {
994
+ await send('Emulation.setEmulatedMedia', { media: 'print' });
995
+ await run(`window.dispatchEvent(new Event('beforeprint'))`);
996
+ }
997
+ await waitForLayout(browser, session);
998
+ zero(await state(`${mode}-enter-${cycle}`));
999
+ if (mode === 'embed') await run(`document.documentElement.removeAttribute('data-embed')`);
1000
+ else {
1001
+ await send('Emulation.setEmulatedMedia', { media: '' });
1002
+ await run(`window.dispatchEvent(new Event('afterprint'))`);
1003
+ }
1004
+ await waitForLayout(browser, session);
1005
+ const restored = await state(`${mode}-return-${cycle}`);
1006
+ assert.equal(restored.reserve, initial.reserve);
1007
+ clearStage(restored);
1008
+ }
1009
+ }
1010
+ for (const theme of ['dark', 'light']) {
1011
+ await send('Emulation.setEmulatedMedia', { media: '', features: [
1012
+ { name: 'prefers-reduced-motion', value: theme === 'light' ? 'reduce' : 'no-preference' },
1013
+ ] });
1014
+ await load(browser, file, { query: `?theme=${theme}&present=1` });
1015
+ const present = await state(`presentation-${theme}`);
1016
+ assert.equal(present.geometry.receiptEligible, true);
1017
+ clearStage(present);
1018
+ if (evidence) {
1019
+ const shot = await send('Page.captureScreenshot', { format: 'png' });
1020
+ fs.writeFileSync(path.join(evidence, `presentation-${theme}.png`), Buffer.from(shot.data, 'base64'));
1021
+ }
1022
+ await run('Archify.presentation.exit()');
1023
+ await waitForLayout(browser, session);
1024
+ clearStage(await state(`presentation-return-${theme}`));
1025
+ }
1026
+ await send('Emulation.setEmulatedMedia', { features: [] });
1027
+ });
1028
+
1029
+ await t.test('pending Reader probes coalesce and retain the rail when the camera changes', async () => {
1030
+ for (const reject of [false, true]) {
1031
+ await load(browser, file);
1032
+ const initial = await state(`probe-initial-${reject}`);
1033
+ assert.ok(initial.reserve > 0);
1034
+ const pending = await run(`(() => {
1035
+ const reader = Archify.readerLayout;
1036
+ const original = reader.whenStable;
1037
+ let release;
1038
+ const gate = new Promise((resolve, reject) => { release = ${reject} ? () => reject(new Error('test reader rejection')) : resolve; });
1039
+ reader.whenStable = () => gate;
1040
+ const first = Archify.viewerChromeLayout.reprobe();
1041
+ const second = Archify.viewerChromeLayout.reprobe();
1042
+ const measuring = Archify.viewerChromeLayout.measure();
1043
+ const reserve = document.querySelector('.diagram-container').style.getPropertyValue('--archify-nav-reserve');
1044
+ Archify.view.zoomIn();
1045
+ window.dispatchEvent(new Event('resize'));
1046
+ window.finishChromeProbe = async () => {
1047
+ reader.whenStable = original;
1048
+ release();
1049
+ const result = await first;
1050
+ delete window.finishChromeProbe;
1051
+ return result;
1052
+ };
1053
+ return { same: first === second, measuring, reserve };
1054
+ })()`);
1055
+ assert.deepEqual(pending, { same: true, measuring: null, reserve: '' });
1056
+ assert.equal(await run('finishChromeProbe()', true), true);
1057
+ await waitForLayout(browser, session);
1058
+ const restored = await state(`probe-restored-${reject}`);
1059
+ assert.equal(restored.reserve, initial.reserve);
1060
+ clearStage(restored);
1061
+ await run(`for (let i = 0; i < 20; i++) { Archify.viewerChromeLayout.schedule(); Archify.viewerChromeLayout.reprobe(); window.dispatchEvent(new Event('resize')); }`);
1062
+ await waitForLayout(browser, session);
1063
+ const repeated = await state(`probe-burst-${reject}`);
1064
+ assert.equal(repeated.reserve, initial.reserve);
1065
+ assert.deepEqual(repeated.geometry, restored.geometry);
1066
+ }
1067
+ });
1068
+
1069
+ await t.test('font readiness and optional observers preserve their existing fallbacks', async () => {
1070
+ const noObservers = variant('no-observers', 'window.ResizeObserver = undefined; window.MutationObserver = undefined;');
1071
+ await load(browser, noObservers);
1072
+ const initial = await state('fallback-initial');
1073
+ await resize(720);
1074
+ zero(await state('fallback-mobile'));
1075
+ await resize(1440);
1076
+ assert.equal((await state('fallback-return')).reserve, initial.reserve);
1077
+
1078
+ const delayedFonts = variant('fonts', `window.originalChromeFonts = document.fonts;
1079
+ Object.defineProperty(document, 'fonts', { configurable: true, value: { ready: new Promise(resolve => { window.releaseChromeFonts = resolve; }) } });`);
1080
+ // Bypass load's font/stability wait to observe the deliberately pending gate.
1081
+ const loaded = browser.cdp.waitFor('Page.loadEventFired', session);
1082
+ await send('Page.navigate', { url: pathToFileURL(delayedFonts).href });
1083
+ await loaded;
1084
+ const result = await run(`(async () => {
1085
+ let resolved = false;
1086
+ const stable = Archify.viewerChromeLayout.whenStable().then(() => { resolved = true; });
1087
+ document.querySelector('.diagram-nav').style.height = '100px';
1088
+ await new Promise(resolve => requestAnimationFrame(() => requestAnimationFrame(resolve)));
1089
+ const beforeReady = resolved;
1090
+ releaseChromeFonts();
1091
+ await stable;
1092
+ Object.defineProperty(document, 'fonts', { configurable: true, value: originalChromeFonts });
1093
+ return { beforeReady, resolved };
1094
+ })()`, true);
1095
+ assert.deepEqual(result, { beforeReady: false, resolved: true });
1096
+ await waitForLayout(browser, session);
1097
+ clearStage(await state('font-ready'));
1098
+ });
1099
+ } finally {
1100
+ if (evidence) fs.writeFileSync(path.join(evidence, 'observations.json'), JSON.stringify(observations, null, 2) + '\n');
1101
+ }
1102
+ });
1103
+
1104
+ process.on('exit', () => fs.rmSync(tmp, { recursive: true, force: true }));