@xgent-ai/skills 0.3.0 → 0.5.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 (631) hide show
  1. package/README.md +117 -11
  2. package/bin/xgent-skills.js +269 -9
  3. package/docs/claude-context-goal-guard.md +125 -0
  4. package/docs/codex-context-goal-guard.md +110 -0
  5. package/hooks/claude/context-goal-guard.js +139 -0
  6. package/hooks/claude/settings.example.json +26 -0
  7. package/hooks/codex/context-goal-guard.py +189 -0
  8. package/hooks/codex/hooks.example.json +26 -0
  9. package/package.json +7 -1
  10. package/skills/agi-mode/SKILL.md +225 -0
  11. package/skills/agi-mode/evals/baseline-coverage.md +96 -0
  12. package/skills/agi-mode/evals/scenarios.md +331 -0
  13. package/skills/agi-mode/evals/test_check_evidence.py +141 -0
  14. package/skills/agi-mode/playbooks/arena.md +47 -0
  15. package/skills/agi-mode/playbooks/authoring-a-skill.md +26 -0
  16. package/skills/agi-mode/playbooks/autonomous-run.md +39 -0
  17. package/skills/agi-mode/playbooks/bug-fix.md +27 -0
  18. package/skills/agi-mode/playbooks/design-prototype.md +41 -0
  19. package/skills/agi-mode/playbooks/eval.md +72 -0
  20. package/skills/agi-mode/playbooks/feature.md +26 -0
  21. package/skills/agi-mode/playbooks/forensics.md +31 -0
  22. package/skills/agi-mode/playbooks/hillclimb.md +73 -0
  23. package/skills/agi-mode/playbooks/investigation.md +29 -0
  24. package/skills/agi-mode/playbooks/migration-refactoring.md +27 -0
  25. package/skills/agi-mode/playbooks/optimization.md +27 -0
  26. package/skills/agi-mode/playbooks/pr-lifecycle.md +38 -0
  27. package/skills/agi-mode/playbooks/program.md +57 -0
  28. package/skills/agi-mode/playbooks/reflection.md +41 -0
  29. package/skills/agi-mode/playbooks/resource-cleanup.md +24 -0
  30. package/skills/agi-mode/playbooks/review.md +27 -0
  31. package/skills/agi-mode/playbooks/session-handoff.md +37 -0
  32. package/skills/agi-mode/playbooks/shipping.md +35 -0
  33. package/skills/agi-mode/playbooks/ui-delivery.md +34 -0
  34. package/skills/agi-mode/playbooks/unblock.md +54 -0
  35. package/skills/agi-mode/principles/autonomous-decisions.md +21 -0
  36. package/skills/agi-mode/principles/behavioral-tests.md +21 -0
  37. package/skills/agi-mode/principles/boundary-discipline.md +21 -0
  38. package/skills/agi-mode/principles/bounded-convergence.md +21 -0
  39. package/skills/agi-mode/principles/build-leverage.md +21 -0
  40. package/skills/agi-mode/principles/challenge-premises.md +21 -0
  41. package/skills/agi-mode/principles/complete-migrations.md +21 -0
  42. package/skills/agi-mode/principles/context-as-state.md +21 -0
  43. package/skills/agi-mode/principles/critical-path-throughput.md +21 -0
  44. package/skills/agi-mode/principles/domain-models-and-types.md +23 -0
  45. package/skills/agi-mode/principles/evidence-lifetime.md +21 -0
  46. package/skills/agi-mode/principles/experience-first.md +21 -0
  47. package/skills/agi-mode/principles/explore-alternatives.md +21 -0
  48. package/skills/agi-mode/principles/falsifiable-verification.md +21 -0
  49. package/skills/agi-mode/principles/foundations-first.md +21 -0
  50. package/skills/agi-mode/principles/idempotent-effects.md +21 -0
  51. package/skills/agi-mode/principles/information-first.md +21 -0
  52. package/skills/agi-mode/principles/minimize-complexity.md +21 -0
  53. package/skills/agi-mode/principles/outcome-ownership.md +21 -0
  54. package/skills/agi-mode/principles/prove-real-outcomes.md +21 -0
  55. package/skills/agi-mode/principles/redesign-from-constraints.md +21 -0
  56. package/skills/agi-mode/principles/root-cause.md +21 -0
  57. package/skills/agi-mode/principles/state-ownership.md +21 -0
  58. package/skills/agi-mode/principles/structural-learning.md +21 -0
  59. package/skills/agi-mode/principles/verifiable-units.md +21 -0
  60. package/skills/agi-mode/references/continuity.md +75 -0
  61. package/skills/agi-mode/references/eval-protocol.md +71 -0
  62. package/skills/agi-mode/references/evidence-contract.md +57 -0
  63. package/skills/agi-mode/references/evolution-evidence.md +71 -0
  64. package/skills/agi-mode/references/experiments.md +82 -0
  65. package/skills/agi-mode/references/reflection/divergent-reviewer.md +45 -0
  66. package/skills/agi-mode/references/reflection/judgment-reviewer.md +44 -0
  67. package/skills/agi-mode/references/reflection/synthesizer.md +39 -0
  68. package/skills/agi-mode/references/reflection/tooling-reviewer.md +57 -0
  69. package/skills/agi-mode/references/skill-evolution.md +50 -0
  70. package/skills/agi-mode/scripts/check_evidence.py +147 -0
  71. package/skills/apply-code-review/SKILL.md +53 -0
  72. package/skills/apply-code-review/agents/openai.yaml +4 -0
  73. package/skills/apply-code-review/references/record-contract.md +77 -0
  74. package/skills/apply-doc-review/SKILL.md +79 -0
  75. package/skills/apply-doc-review/agents/openai.yaml +4 -0
  76. package/skills/apply-doc-review/references/disposition-contract.md +57 -0
  77. package/skills/archify/LICENSE +22 -0
  78. package/skills/archify/SKILL.md +137 -0
  79. package/skills/archify/THIRD_PARTY_NOTICES.md +69 -0
  80. package/skills/archify/assets/JetBrainsMono-OFL.txt +93 -0
  81. package/skills/archify/assets/template.html +14937 -0
  82. package/skills/archify/bin/archify.mjs +2139 -0
  83. package/skills/archify/bin/open-artifact.mjs +86 -0
  84. package/skills/archify/bin/preview.mjs +653 -0
  85. package/skills/archify/bin/visual-check.mjs +829 -0
  86. package/skills/archify/brand-marks/README.md +31 -0
  87. package/skills/archify/brand-marks/catalog.json +131 -0
  88. package/skills/archify/delta/architecture-delta.mjs +1232 -0
  89. package/skills/archify/examples/agent-run.lifecycle.json +60 -0
  90. package/skills/archify/examples/agent-tool-call.workflow.json +94 -0
  91. package/skills/archify/examples/async-job-roundtrip.sequence.json +61 -0
  92. package/skills/archify/examples/brand-aware-delivery.architecture.json +47 -0
  93. package/skills/archify/examples/cache-miss-request.sequence.json +82 -0
  94. package/skills/archify/examples/checkout-platform.base.architecture.json +31 -0
  95. package/skills/archify/examples/checkout-platform.head.architecture.json +31 -0
  96. package/skills/archify/examples/dataflow-product-analytics.html +15048 -0
  97. package/skills/archify/examples/deployment-release.lifecycle.json +49 -0
  98. package/skills/archify/examples/event-stream.dataflow.json +57 -0
  99. package/skills/archify/examples/incident-response.workflow.json +64 -0
  100. package/skills/archify/examples/lifecycle-agent-run.html +14983 -0
  101. package/skills/archify/examples/product-analytics.dataflow.json +76 -0
  102. package/skills/archify/examples/production-deployment.architecture.json +71 -0
  103. package/skills/archify/examples/release-delivery.workflow.json +62 -0
  104. package/skills/archify/examples/sequence-cache-miss-request.html +15063 -0
  105. package/skills/archify/examples/web-app-rendered.html +15012 -0
  106. package/skills/archify/examples/web-app.architecture.json +46 -0
  107. package/skills/archify/examples/workflow-agent-tool-call-rendered.html +15054 -0
  108. package/skills/archify/migrations/workflow-v2.mjs +279 -0
  109. package/skills/archify/package-lock.json +149 -0
  110. package/skills/archify/package.json +39 -0
  111. package/skills/archify/recipes/scenarios.mjs +391 -0
  112. package/skills/archify/references/authoring-contract.md +247 -0
  113. package/skills/archify/references/brand-marks.md +65 -0
  114. package/skills/archify/references/delivery-contract.md +138 -0
  115. package/skills/archify/references/viewer-runtime.md +45 -0
  116. package/skills/archify/renderers/architecture/grid.mjs +62 -0
  117. package/skills/archify/renderers/architecture/render-architecture.mjs +1078 -0
  118. package/skills/archify/renderers/dataflow/README.md +104 -0
  119. package/skills/archify/renderers/dataflow/render-dataflow.mjs +483 -0
  120. package/skills/archify/renderers/lifecycle/README.md +115 -0
  121. package/skills/archify/renderers/lifecycle/render-lifecycle.mjs +561 -0
  122. package/skills/archify/renderers/sequence/README.md +114 -0
  123. package/skills/archify/renderers/sequence/render-sequence.mjs +464 -0
  124. package/skills/archify/renderers/shared/brand-marks.mjs +563 -0
  125. package/skills/archify/renderers/shared/cli.mjs +218 -0
  126. package/skills/archify/renderers/shared/desktop-readability.mjs +26 -0
  127. package/skills/archify/renderers/shared/diagnostics.mjs +160 -0
  128. package/skills/archify/renderers/shared/engineering-profiles.mjs +157 -0
  129. package/skills/archify/renderers/shared/generated-brand-marks.mjs +2003 -0
  130. package/skills/archify/renderers/shared/generated-validators.mjs +13 -0
  131. package/skills/archify/renderers/shared/geometry.mjs +1423 -0
  132. package/skills/archify/renderers/shared/i18n.mjs +595 -0
  133. package/skills/archify/renderers/shared/layout-report.mjs +40 -0
  134. package/skills/archify/renderers/shared/legend.mjs +217 -0
  135. package/skills/archify/renderers/shared/output-path.mjs +340 -0
  136. package/skills/archify/renderers/shared/repository-evidence.mjs +239 -0
  137. package/skills/archify/renderers/shared/repository-location.mjs +58 -0
  138. package/skills/archify/renderers/shared/text-fit.mjs +49 -0
  139. package/skills/archify/renderers/shared/utils.mjs +232 -0
  140. package/skills/archify/renderers/shared/validator.mjs +86 -0
  141. package/skills/archify/renderers/workflow/README.md +223 -0
  142. package/skills/archify/renderers/workflow/render-workflow.mjs +35 -0
  143. package/skills/archify/renderers/workflow/workflow-compiler.mjs +4400 -0
  144. package/skills/archify/renderers/workflow/workflow-migration-geometry.mjs +144 -0
  145. package/skills/archify/schemas/README.md +211 -0
  146. package/skills/archify/schemas/architecture.schema.json +178 -0
  147. package/skills/archify/schemas/common.schema.json +115 -0
  148. package/skills/archify/schemas/dataflow.schema.json +243 -0
  149. package/skills/archify/schemas/lifecycle.schema.json +266 -0
  150. package/skills/archify/schemas/sequence.schema.json +223 -0
  151. package/skills/archify/schemas/workflow.schema.json +428 -0
  152. package/skills/archify/scripts/check-render-output.mjs +916 -0
  153. package/skills/archify/scripts/check-update.mjs +1667 -0
  154. package/skills/archify/scripts/generate-brand-marks.mjs +141 -0
  155. package/skills/archify/scripts/generate-validators.mjs +66 -0
  156. package/skills/archify/scripts/render-examples.mjs +26 -0
  157. package/skills/archify/scripts/update-contract.mjs +182 -0
  158. package/skills/archify/skill-release.json +10 -0
  159. package/skills/archify/test/adaptive-reader-layout.test.mjs +86 -0
  160. package/skills/archify/test/animation.test.mjs +179 -0
  161. package/skills/archify/test/architecture-compare-recovery.test.mjs +157 -0
  162. package/skills/archify/test/architecture-delta-markers.test.mjs +137 -0
  163. package/skills/archify/test/architecture-delta.test.mjs +705 -0
  164. package/skills/archify/test/artifact-receipt-flush.test.mjs +126 -0
  165. package/skills/archify/test/authored-reachability.test.mjs +95 -0
  166. package/skills/archify/test/authoring-safety-contract.test.mjs +54 -0
  167. package/skills/archify/test/automatic-port-spread.test.mjs +376 -0
  168. package/skills/archify/test/base-input-compatibility.test.mjs +42 -0
  169. package/skills/archify/test/brand-marks.test.mjs +678 -0
  170. package/skills/archify/test/chapter-delta-preview.test.mjs +157 -0
  171. package/skills/archify/test/chapter-handoff.test.mjs +97 -0
  172. package/skills/archify/test/chapter-rail.test.mjs +86 -0
  173. package/skills/archify/test/checkout-line-endings.test.mjs +72 -0
  174. package/skills/archify/test/ci-scope.test.mjs +59 -0
  175. package/skills/archify/test/clean-skill-staging.test.mjs +440 -0
  176. package/skills/archify/test/cli-output-types.test.mjs +201 -0
  177. package/skills/archify/test/cli.test.mjs +986 -0
  178. package/skills/archify/test/community-proof-intake.test.mjs +125 -0
  179. package/skills/archify/test/cursor-onboarding.test.mjs +74 -0
  180. package/skills/archify/test/degraded.test.mjs +161 -0
  181. package/skills/archify/test/delivery-contract.test.mjs +52 -0
  182. package/skills/archify/test/desktop-reader-browser.test.mjs +80 -0
  183. package/skills/archify/test/diagram-guide.test.mjs +92 -0
  184. package/skills/archify/test/engineering-profile.test.mjs +209 -0
  185. package/skills/archify/test/export-browser.test.mjs +305 -0
  186. package/skills/archify/test/export-cleanup-browser.test.mjs +294 -0
  187. package/skills/archify/test/finder-browser.test.mjs +274 -0
  188. package/skills/archify/test/finder.test.mjs +104 -0
  189. package/skills/archify/test/fixtures/automatic-routing-node-border-clearance.workflow.json +40 -0
  190. package/skills/archify/test/fixtures/fail-migration-cleanup.mjs +17 -0
  191. package/skills/archify/test/fixtures/issue-126/custom-widths.workflow.json +18 -0
  192. package/skills/archify/test/fixtures/issue-126/explicit-route.workflow.json +28 -0
  193. package/skills/archify/test/fixtures/issue-126/explicit-viewbox.workflow.json +19 -0
  194. package/skills/archify/test/fixtures/issue-126/labels.workflow.json +18 -0
  195. package/skills/archify/test/fixtures/v1-baseline/agent-run.lifecycle.json +64 -0
  196. package/skills/archify/test/fixtures/v1-baseline/agent-tool-call.workflow.json +88 -0
  197. package/skills/archify/test/fixtures/v1-baseline/cache-miss-request.sequence.json +75 -0
  198. package/skills/archify/test/fixtures/v1-baseline/event-stream.dataflow.json +57 -0
  199. package/skills/archify/test/fixtures/v1-baseline/product-analytics.dataflow.json +70 -0
  200. package/skills/archify/test/fixtures/v1-baseline/production-deployment.architecture.json +71 -0
  201. package/skills/archify/test/fixtures/v1-baseline/web-app.architecture.json +41 -0
  202. package/skills/archify/test/fixtures/v1-workflow-700x400.workflow.json +22 -0
  203. package/skills/archify/test/fixtures/v1-workflow-explicit-coordinates.workflow.json +47 -0
  204. package/skills/archify/test/focus-browser.test.mjs +226 -0
  205. package/skills/archify/test/gallery.test.mjs +130 -0
  206. package/skills/archify/test/generate-validators.test.mjs +59 -0
  207. package/skills/archify/test/generate-viewer.test.mjs +165 -0
  208. package/skills/archify/test/generated-artifact-xml.test.mjs +88 -0
  209. package/skills/archify/test/geometry.test.mjs +739 -0
  210. package/skills/archify/test/golden.mjs +207 -0
  211. package/skills/archify/test/grid.test.mjs +47 -0
  212. package/skills/archify/test/guide-page.test.mjs +85 -0
  213. package/skills/archify/test/guide.test.mjs +81 -0
  214. package/skills/archify/test/guided-views-browser.test.mjs +460 -0
  215. package/skills/archify/test/guided-views.test.mjs +144 -0
  216. package/skills/archify/test/helpers/desktop-browser.mjs +48 -0
  217. package/skills/archify/test/helpers/offline-fonts.mjs +76 -0
  218. package/skills/archify/test/helpers/viewer-click.mjs +72 -0
  219. package/skills/archify/test/helpers/xml.mjs +37 -0
  220. package/skills/archify/test/i18n.test.mjs +422 -0
  221. package/skills/archify/test/intent-trace-browser.test.mjs +284 -0
  222. package/skills/archify/test/intent-trace.test.mjs +111 -0
  223. package/skills/archify/test/landing.test.mjs +97 -0
  224. package/skills/archify/test/layout-rules.test.mjs +1498 -0
  225. package/skills/archify/test/legend-contract.test.mjs +404 -0
  226. package/skills/archify/test/motion-governor-browser.test.mjs +342 -0
  227. package/skills/archify/test/motion-governor.test.mjs +111 -0
  228. package/skills/archify/test/offline-font-browser.test.mjs +210 -0
  229. package/skills/archify/test/offline-self-containment.test.mjs +80 -0
  230. package/skills/archify/test/open-artifact.test.mjs +118 -0
  231. package/skills/archify/test/ordinary-model-floor.test.mjs +1052 -0
  232. package/skills/archify/test/output-path.test.mjs +587 -0
  233. package/skills/archify/test/presentation.test.mjs +71 -0
  234. package/skills/archify/test/preset-tryon.test.mjs +113 -0
  235. package/skills/archify/test/preview-contract.test.mjs +40 -0
  236. package/skills/archify/test/preview.test.mjs +530 -0
  237. package/skills/archify/test/proof-aperture.test.mjs +78 -0
  238. package/skills/archify/test/reach-share-card.test.mjs +149 -0
  239. package/skills/archify/test/reader-layout-browser.test.mjs +320 -0
  240. package/skills/archify/test/readme-showcase.test.mjs +319 -0
  241. package/skills/archify/test/real-repository-proof.test.mjs +209 -0
  242. package/skills/archify/test/relationship-direct-explorer.test.mjs +115 -0
  243. package/skills/archify/test/relationship-lens.test.mjs +128 -0
  244. package/skills/archify/test/relationship-permalink.test.mjs +130 -0
  245. package/skills/archify/test/relationship-pulse.test.mjs +122 -0
  246. package/skills/archify/test/release-identity.test.mjs +476 -0
  247. package/skills/archify/test/release-package-gates.test.mjs +750 -0
  248. package/skills/archify/test/render-output-checks.test.mjs +588 -0
  249. package/skills/archify/test/renderer-diagnostic-boundary.test.mjs +107 -0
  250. package/skills/archify/test/repair-receipt.test.mjs +181 -0
  251. package/skills/archify/test/repository-evidence-replacement.test.mjs +136 -0
  252. package/skills/archify/test/repository-evidence.test.mjs +605 -0
  253. package/skills/archify/test/repository-language-metadata.test.mjs +67 -0
  254. package/skills/archify/test/route-journey.test.mjs +125 -0
  255. package/skills/archify/test/route-probe-browser.test.mjs +363 -0
  256. package/skills/archify/test/route-probe.test.mjs +114 -0
  257. package/skills/archify/test/route-share-card.test.mjs +163 -0
  258. package/skills/archify/test/semantic-camera.test.mjs +88 -0
  259. package/skills/archify/test/semantic-flow.test.mjs +90 -0
  260. package/skills/archify/test/semantic-legend-gateway.test.mjs +156 -0
  261. package/skills/archify/test/semantic-lens-browser.test.mjs +372 -0
  262. package/skills/archify/test/semantic-lens.test.mjs +103 -0
  263. package/skills/archify/test/semantic-passport.test.mjs +99 -0
  264. package/skills/archify/test/semantic-radar.test.mjs +735 -0
  265. package/skills/archify/test/semantic-zoom.test.mjs +86 -0
  266. package/skills/archify/test/sequence-column-fit.test.mjs +137 -0
  267. package/skills/archify/test/settled-flow.test.mjs +97 -0
  268. package/skills/archify/test/share-card-export.test.mjs +132 -0
  269. package/skills/archify/test/site-language-continuity.test.mjs +569 -0
  270. package/skills/archify/test/site-language-integration.mjs +9 -0
  271. package/skills/archify/test/skill-metadata.test.mjs +84 -0
  272. package/skills/archify/test/stable-update-manifest.test.mjs +167 -0
  273. package/skills/archify/test/start-page.test.mjs +312 -0
  274. package/skills/archify/test/story-beat-navigator.test.mjs +103 -0
  275. package/skills/archify/test/story-carrier.test.mjs +90 -0
  276. package/skills/archify/test/story-director-strip.test.mjs +91 -0
  277. package/skills/archify/test/story-follow-camera.test.mjs +103 -0
  278. package/skills/archify/test/story-horizon.test.mjs +91 -0
  279. package/skills/archify/test/story-moment-link.test.mjs +93 -0
  280. package/skills/archify/test/story-shelf.test.mjs +84 -0
  281. package/skills/archify/test/story-trail.test.mjs +81 -0
  282. package/skills/archify/test/toolbar-polish.test.mjs +57 -0
  283. package/skills/archify/test/update-contract.test.mjs +133 -0
  284. package/skills/archify/test/update-notifier.test.mjs +3317 -0
  285. package/skills/archify/test/v1-compatibility.test.mjs +329 -0
  286. package/skills/archify/test/vertical-edge.test.mjs +68 -0
  287. package/skills/archify/test/viewer-camera-browser.test.mjs +395 -0
  288. package/skills/archify/test/viewer-chrome-layout.test.mjs +1104 -0
  289. package/skills/archify/test/viewer-identifiers-browser.test.mjs +135 -0
  290. package/skills/archify/test/visual-check.test.mjs +400 -0
  291. package/skills/archify/test/webm-artifact.smoke.mjs +1855 -0
  292. package/skills/archify/test/workflow-compiler-hard-contract.test.mjs +2136 -0
  293. package/skills/archify/test/workflow-compiler.test.mjs +1163 -0
  294. package/skills/archify/test/workflow-migration.test.mjs +620 -0
  295. package/skills/archify/test/workflow-semantic-contract.test.mjs +131 -0
  296. package/skills/architect/SKILL.md +83 -0
  297. package/skills/architect/references/design-red-flags.md +33 -0
  298. package/skills/architect/references/rationale-template.md +35 -0
  299. package/skills/architect/references/runner-prompt.md +20 -0
  300. package/skills/arena/SKILL.md +13 -0
  301. package/skills/automate-me/SKILL.md +104 -0
  302. package/skills/autoresearch/SKILL.md +14 -0
  303. package/skills/debugging/SKILL.md +279 -0
  304. package/skills/dev-plan/SKILL.md +25 -18
  305. package/skills/dev-plan/references/execution-workflow.md +8 -61
  306. package/skills/dev-plan/references/plan-skeleton.md +43 -28
  307. package/skills/dev-plan/scripts/check_progress.sh +5 -1
  308. package/skills/documentation-writer/SKILL.md +204 -0
  309. package/skills/documentation-writer/assets/templates/ARCHITECTURE.md +49 -0
  310. package/skills/documentation-writer/assets/templates/CONCERNS.md +56 -0
  311. package/skills/documentation-writer/assets/templates/CONVENTIONS.md +52 -0
  312. package/skills/documentation-writer/assets/templates/FEATURES.md +43 -0
  313. package/skills/documentation-writer/assets/templates/INTEGRATIONS.md +48 -0
  314. package/skills/documentation-writer/assets/templates/STACK.md +56 -0
  315. package/skills/documentation-writer/assets/templates/STRUCTURE.md +44 -0
  316. package/skills/documentation-writer/assets/templates/TESTING.md +57 -0
  317. package/skills/documentation-writer/references/api-docs.md +185 -0
  318. package/skills/documentation-writer/references/architecture.md +134 -0
  319. package/skills/documentation-writer/references/codebase-map.md +113 -0
  320. package/skills/documentation-writer/references/inquiry-checkpoints.md +78 -0
  321. package/skills/documentation-writer/references/readme.md +89 -0
  322. package/skills/documentation-writer/references/stack-detection.md +134 -0
  323. package/skills/documentation-writer/references/user-manual.md +103 -0
  324. package/skills/documentation-writer/references/writing-style.md +220 -0
  325. package/skills/documentation-writer/scripts/check_doc.py +273 -0
  326. package/skills/documentation-writer/scripts/scan.py +712 -0
  327. package/skills/elintp/SKILL.md +27 -1
  328. package/skills/figure-it-out/SKILL.md +53 -0
  329. package/skills/gdpr-compliant/SKILL.md +283 -0
  330. package/skills/gdpr-compliant/references/Security.md +266 -0
  331. package/skills/gdpr-compliant/references/data-rights.md +177 -0
  332. package/skills/how/SKILL.md +58 -0
  333. package/skills/how/references/explainer-prompt.md +55 -0
  334. package/skills/how/references/explorer-prompt.md +52 -0
  335. package/skills/humanize-writing/SKILL.md +417 -0
  336. package/skills/humanize-writing/references/ai-tells.md +291 -0
  337. package/skills/kpi-dashboard-design/SKILL.md +103 -0
  338. package/skills/landing-page-conversion-audit/SKILL.md +122 -0
  339. package/skills/meeting-minutes/SKILL.md +235 -0
  340. package/skills/portal-app-exchange/SKILL.md +8 -17
  341. package/skills/portal-dev-setup/SKILL.md +137 -46
  342. package/skills/portal-dev-setup/puller.env.example +3 -2
  343. package/skills/portal-dev-setup/references/kafka.md +140 -0
  344. package/skills/portal-dev-setup/references/troubleshooting.md +22 -26
  345. package/skills/portal-dev-setup/scripts/onebox.sh +510 -56
  346. package/skills/portal-external-app/SKILL.md +57 -21
  347. package/skills/portal-external-app/references/contract-doc-template.md +1 -1
  348. package/skills/portal-external-app/references/integration-contract.md +4 -4
  349. package/skills/portal-external-app/references/public-entrypoints.md +100 -0
  350. package/skills/portal-external-app/references/quota-and-seats.md +12 -31
  351. package/skills/portal-external-app/references/registration-and-onebox.md +67 -11
  352. package/skills/portal-micro-app/SKILL.md +18 -28
  353. package/skills/portal-micro-app/references/manifest-and-acl.md +21 -3
  354. package/skills/portal-micro-app/references/open-api-and-extensions.md +1 -1
  355. package/skills/portal-micro-app/references/sdk-reference.md +1 -1
  356. package/skills/prd/SKILL.md +56 -38
  357. package/skills/prd/references/prd-skeleton.md +72 -34
  358. package/skills/prd/references/product-quality.md +89 -0
  359. package/skills/prd/references/spms-mapping.md +9 -7
  360. package/skills/react/SKILL.md +26 -4
  361. package/skills/react/references/actions.md +251 -0
  362. package/skills/react/references/data-fetching.md +25 -1
  363. package/skills/react/references/react19-migration.md +407 -0
  364. package/skills/reflect/SKILL.md +13 -0
  365. package/skills/review-code/SKILL.md +63 -0
  366. package/skills/review-code/agents/openai.yaml +4 -0
  367. package/skills/review-code/references/git-scopes.md +38 -0
  368. package/skills/review-code/references/report-contract.md +56 -0
  369. package/skills/review-code/references/review-lenses.md +33 -0
  370. package/skills/review-dev-plan/SKILL.md +88 -0
  371. package/skills/review-dev-plan/agents/openai.yaml +4 -0
  372. package/skills/review-dev-plan/references/report-contract.md +59 -0
  373. package/skills/review-dev-plan/references/review-lenses.md +82 -0
  374. package/skills/review-prd/SKILL.md +84 -0
  375. package/skills/review-prd/agents/openai.yaml +4 -0
  376. package/skills/review-prd/references/report-contract.md +64 -0
  377. package/skills/review-prd/references/review-lenses.md +82 -0
  378. package/skills/review-prd-dev-gaps/SKILL.md +84 -0
  379. package/skills/review-prd-dev-gaps/agents/openai.yaml +4 -0
  380. package/skills/review-prd-dev-gaps/references/report-contract.md +72 -0
  381. package/skills/security-audit/SKILL.md +191 -0
  382. package/skills/security-audit/references/language-patterns.md +221 -0
  383. package/skills/security-audit/references/report-format.md +194 -0
  384. package/skills/security-audit/references/secret-patterns.md +178 -0
  385. package/skills/security-audit/references/vuln-categories.md +288 -0
  386. package/skills/security-audit/references/vulnerable-packages.md +111 -0
  387. package/skills/sql-optimization/SKILL.md +296 -0
  388. package/skills/summarize/SKILL.md +1 -0
  389. package/skills/swarm/references/teams/product.md +2 -2
  390. package/skills/tdd/SKILL.md +42 -0
  391. package/skills/teach/SKILL.md +21 -0
  392. package/skills/test-plan/SKILL.md +12 -11
  393. package/skills/test-plan/references/case-taxonomy.md +3 -2
  394. package/skills/why/SKILL.md +158 -0
  395. package/skills/why/references/epistemics.md +144 -0
  396. package/skills/why/references/investigator-prompt.md +103 -0
  397. package/skills/why/references/source-playbook.md +17 -0
  398. package/skills/why/references/sources/code-archaeology.md +88 -0
  399. package/skills/why/references/sources/databricks.md +70 -0
  400. package/skills/why/references/sources/datadog.md +99 -0
  401. package/skills/why/references/sources/incident-postmortem.md +15 -0
  402. package/skills/why/references/sources/linear.md +48 -0
  403. package/skills/why/references/sources/notion.md +55 -0
  404. package/skills/why/references/sources/sentry.md +100 -0
  405. package/skills/why/references/sources/slack.md +54 -0
  406. package/skills/why/references/synthesizer-prompt.md +135 -0
  407. package/skills/xgent-app-release/SKILL.md +97 -28
  408. package/skills/xgent-app-release/references/build-and-package.md +8 -3
  409. package/skills/xgent-app-release/references/embed-csp.mjs +126 -0
  410. package/skills/xgent-app-release/references/frontend-archive.md +67 -0
  411. package/skills/xgent-app-release/references/public-delivery.md +75 -0
  412. package/skills/xgent-app-release/references/publish-api.md +62 -56
  413. package/skills/xgent-app-release/references/troubleshooting.md +18 -2
  414. package/skills/xgent-app-release/references/verify-preflight.mjs +50 -0
  415. package/skills/xgent-app-release/scripts/npm-token.mjs +8 -3
  416. package/skills/xgent-app-release/scripts/preflight.mjs +13 -2
  417. package/skills/xgent-init/SKILL.md +23 -82
  418. package/skills/xgent-init/references/external-app-AGENTS.template.md +149 -0
  419. package/skills/xgent-init/references/fill-guide.md +10 -22
  420. package/skills/xgent-init/scripts/check-docs.mjs +14 -86
  421. package/vendor/impeccable/VERSION.json +10 -16
  422. package/vendor/impeccable/bundle/blobs/{daa2a8ecd874f9f940dfd72aaa329318b06bb9be25515be85fea84c871b637a6 → 00c067253d37cd20a41dbe9c806d6a72cbff983ad1418b3c3e447998f577b9c2} +18 -11
  423. package/vendor/impeccable/bundle/blobs/{4ce929b8cafd37247ea4c148bbe39a9afe15908d1abf4a8248c5122275d16499 → 00d167d9183c8d0c6c0682055107382e6672bacf7a712de0abc8f157c2cb2210} +3 -2
  424. package/vendor/impeccable/bundle/blobs/{a9515f6f084d8f51c378eb3cdc6db1f12e06dba2d32fc61b7ee7950fa2586f2e → 016c082dcd2aa8f3c080a757c8ed335c6070a904bd2f39668bb9d3e6f95929c1} +1 -1
  425. package/vendor/impeccable/bundle/blobs/0221a193d111a9de33a785706a603e55dd974a115f549dbdf74e0f9ec72bde7d +101 -0
  426. package/vendor/impeccable/bundle/blobs/055c571f2960b8f929d6a8d3806a4d32dfcb9750b3ef8b60adc8930fff34b559 +101 -0
  427. package/vendor/impeccable/bundle/blobs/{3aa908c18db91d5f31d6bba6402eab6afc4e0b75137f841a86bd012386e0d8e2 → 0605c8729dc638a46798e90ab12486fe3ae3372a869757cfb387a08e23b3c84a} +18 -11
  428. package/vendor/impeccable/bundle/blobs/{ec58806f16fc7ba29bccef08f2e158cd00be077ce05d45e943a59bd26dc6dc55 → 0648e4e06d01cabc91fa7dc19256ceedeeeea213b9265e9d36b0918370e16fb2} +6 -0
  429. package/vendor/impeccable/bundle/blobs/06b20bd42e5682a42c5d6fbfaad4c55e66ff9b9d99a604bd31d3545af120fc2d +101 -0
  430. package/vendor/impeccable/bundle/blobs/{420e2fdee2b7f555d9a37ce348cf62610ddd98f96b1a0a511796ba600881588c → 08346755b13f1a3f7c6fb4e512387884b80467aaeff109fd41f5521d2a95635a} +3 -1
  431. package/vendor/impeccable/bundle/blobs/{8f651cb1f8cde0acc5cc511b77fddd98558a527f54974698a1650b0fd7e849a7 → 08398fa2d8e2b06b849f1c0f032e1e93b832e9294aed35c1c7f62b938d62ee80} +1 -1
  432. package/vendor/impeccable/bundle/blobs/087f6715114e901c2ce00b438e75b82fd48978c020a782f3dc361d39eb7198a6 +26 -0
  433. package/vendor/impeccable/bundle/blobs/{bc7a5128cfed46148396c08798b6b9429406fbe477e84e331a36ee2840b6b776 → 09310582ed23393b171eb99ad4a288cc422ac53c26d76311586ce54c6df77b22} +3 -1
  434. package/vendor/impeccable/bundle/blobs/{633903ba7cb38ed502448a66691fbf655805786a2f06be67043f12294ad08e86 → 0bc2bc36ca6e74f9f610392f1a4fb8f57b2676238ba1f9c65cd8714f5d27e8a2} +5 -0
  435. package/vendor/impeccable/bundle/blobs/0c064c9975f25f6eb5cf7911c2eeafd3e695d729f8c86a49a24ff2d76cb3cd94 +63 -0
  436. package/vendor/impeccable/bundle/blobs/{4a7d8695741e2cd354baada215b06798c050aa7a8e1ca6814f0e395e054d1ab1 → 0ccf57f758eb0d53bc32c5c77156f016e528d20fe2c2740662bf19964dfbb00b} +18 -11
  437. package/vendor/impeccable/bundle/blobs/0dd1e6ccf053cb80e057caf7bf2fef30fd0197a41d907a1a8d2d2d02f6978674 +63 -0
  438. package/vendor/impeccable/bundle/blobs/{943b0d7c9ce4f6802d8440a07b2ad3c61cbd1cc00ab63962bab7eea9ca584d20 → 0ed5986d1503399f48c11104df5e523a63be2d6558770ebfbbeb2323ca3f2ad3} +5 -5
  439. package/vendor/impeccable/bundle/blobs/14c9c9a7816026dd77494d06b8d1777c8d64785126b0c9ac8db5ebd996dfd6b6 +101 -0
  440. package/vendor/impeccable/bundle/blobs/{54cb270e8826380caefc8c40642a5d973f27df46bfdb762d822541a0c72a9877 → 14ef0ab84c10331f8af6b4124387a3f80b493175a04a3f89200719b4b5aea221} +18 -11
  441. package/vendor/impeccable/bundle/blobs/{6abbf5979db5cb1d7965bf5f91d589e984843069c587f4d1e63aab135bbace0f → 1547005438784032de3254cb35bff393e8187d7a459d0c20a693d9bfb0b5c1a4} +5 -0
  442. package/vendor/impeccable/bundle/blobs/162b814ddd1133923b9584bb95f85959e64844c94341d6bf10a81c06ab7cc02c +101 -0
  443. package/vendor/impeccable/bundle/blobs/16498466a97a5b19a593d5b3f245468c71784bea069d7fc8aa9690db5ac1d968 +29 -0
  444. package/vendor/impeccable/bundle/blobs/{b31ff29c7a1ea979c6d039f7e8d17007410697ab49536690dca109f0af3f20f8 → 16ba7fca1973c5faf53dd2ca523559129c0fe9e5f8d50b645f527afa78186cd2} +9 -0
  445. package/vendor/impeccable/bundle/blobs/1725ca4aa546a34770f29191b58bf8dc14957d4258fb9e7d02f7b1c59c412ea4 +63 -0
  446. package/vendor/impeccable/bundle/blobs/{598bfed550954471ba4d257d46b4d608cd82e4cdbf36d07bf93c5f4a563f7727 → 1898529e994bf0a31ee9ff3f87c343caea3d8a7e0986f404e129fbf89078ade0} +4 -3
  447. package/vendor/impeccable/bundle/blobs/{6e20041e209e8705d14aa9c4fb8cca3f0d743791de633785e5b46e2dd1ff1a6b → 19b439d7d16e139357459d3874f739ea94dbdffeb2a0e201df1620ed1e40574d} +1 -1
  448. package/vendor/impeccable/bundle/blobs/{04af9f2d6883fe76f9539d310d9c369052822a24886d2c330ab1e3fe5981c8a1 → 1b289c8c09de9d4442109ada91b1fa3a190e113a310cab7aa26a3633c5df0bb0} +1 -1
  449. package/vendor/impeccable/bundle/blobs/{eb3213b9c9f4d6b2f153e7b457f13aa131bcf633695229dad4eac39a920bdf38 → 1bb3bdce54386e96e21b5956713a80583e6b3b9d1170f3bb8dec3819fa341bc3} +5 -5
  450. package/vendor/impeccable/bundle/blobs/{e71d6b97680084a7ccec01844e658cbd2042aec00da0c91bec62a240ad7dcf6a → 1c11cb8ea42536c7a51e197f1aa32198960bb89262da2eaf32e0feb03c70792c} +18 -11
  451. package/vendor/impeccable/bundle/blobs/{f0c4d0615c7d520dfc2536c01cc7f1f3aab9b60ddc399ba01289fe62edb12370 → 1c6258015ed02c522948f8f1a3b6457395a8f7954497b87c1cd83f1791f9f819} +1 -1
  452. package/vendor/impeccable/bundle/blobs/{27c4b6c90ad12a186136f9ece9cb1830d4a6e36b11382ab334efc4543f8082de → 1d7145fd5bf65282b2e05cf42faf41766d68e83e2b75f460b3b62d81ada5e5d7} +18 -11
  453. package/vendor/impeccable/bundle/blobs/{1484a7ae206ab4f0e6262b21afe0f6307a629ed27d28fb7de69536a6800a4883 → 1e2f696760ee55fb154bdcc302c7d7b0fbb807e0308130594bd892dae14dc9ea} +5 -0
  454. package/vendor/impeccable/bundle/blobs/{6989120346e87907d59cc6d4708dd9dee29227ad583fbefee28935395b68ce34 → 1f6c3a1d7344f44eaa88b6f38334ad7d7b60201709589039a58cee73de486f5d} +1 -1
  455. package/vendor/impeccable/bundle/blobs/207d443cabe4e6fe1351f91785748957f757bf1e7aeca405433c0329dad46a15 +63 -0
  456. package/vendor/impeccable/bundle/blobs/{f7916d0113da7a19d4e03c113d5563d181457e44f1646ecab9191cfee5ae776d → 20e2111b3e065e8e8054f715ea3902e64b77886b30d2bddee723558f22942620} +4 -3
  457. package/vendor/impeccable/bundle/blobs/21e78c8a77badb3f83290cd4577ed3b24bd4dd3b57136d7da75733d4f3ee9ac0 +19 -0
  458. package/vendor/impeccable/bundle/blobs/{0f83648f6b425225290305bced51eacebacf9bf9bc05e21cdbad46863fbc89ce → 223f08673b267f81d7586f686afe05d7cd7529a8e11ac37d979f95c2ceaae8ce} +1 -1
  459. package/vendor/impeccable/bundle/blobs/2499b18f26639694344ca95682f47c65494f730cfff88aa9bd2aa83a22e5926d +101 -0
  460. package/vendor/impeccable/bundle/blobs/{074575671f24cf4298d06f0019f76e94f62e9a6ed205fce05b8e507341e64266 → 26cd88d10f8a14ed0ddb6e6b21e5e2c981f410eac93afa179202c354d7d1c0d5} +3 -1
  461. package/vendor/impeccable/bundle/blobs/{5f24c5a97b4ffcabc7c432b064cfdd04c7a2ad52f52e765be648dc0aadab8f38 → 275dd1b6e63bbd30d2713227c4f79b880a8bc4e01cc48d392068bb86939d3afa} +1 -1
  462. package/vendor/impeccable/bundle/blobs/{356cfa0ebf61589cf5d52691d101a69d69256062fe1d11d71d95d41a78289cbd → 28f65b42c1ce9aaea35dc37a51257d7c703bb7f6553ebe3b8ca238a1007251e0} +3 -1
  463. package/vendor/impeccable/bundle/blobs/{a1dbde501ffabb50f30f28f2de6755b5e91b3d4028292c5a3abd3358106eb457 → 2ac1624b1253f3b6fcf2da54d54293624176539b2e9609a49245e7e46c65ca5f} +5 -0
  464. package/vendor/impeccable/bundle/blobs/{3895765e9434400dfc1b30e364be002cf499c1718fb2431e65b907c14ae2cb27 → 2b9379cdb329890eebe2384fbaa23f771745f30d8cfc43e180ebd092e69bcd2f} +4 -3
  465. package/vendor/impeccable/bundle/blobs/{1a9180cec754f8afd354e7cb759750247e97c5bd26d3242ad4c45e315069e8c0 → 2bc5d62463cc83d6417df7b8f4a02b4135e2b1bb654aa7727890662496f86e3d} +5 -0
  466. package/vendor/impeccable/bundle/blobs/2ce1722bd1a9f366182d9357d629796b1448f7a0126a854df507eb044d891cab +26 -0
  467. package/vendor/impeccable/bundle/blobs/{e21af575fcc0f1df54ae422bea4dfa1e5211422606908919f6a86e19e0d5c20c → 3149a87bbed84bffe3558d5eaf1dc596b2e84d3c1be290fc7b1c13e481ae0803} +4 -3
  468. package/vendor/impeccable/bundle/blobs/3253eab02b62efa80abc74a5c85da08f3e2c6c20dff8dec38f4d236cbbfa0f3c +63 -0
  469. package/vendor/impeccable/bundle/blobs/{38c2e839e130008b6da814ab9c16f3fcbbedfdf721a9638eebd31a9e65341a7a → 37680abf9a8e446619fcd33862718f483d197bf2652f966adca8dc54d2909b9d} +3 -2
  470. package/vendor/impeccable/bundle/blobs/385a0efe833bd4afe4a257e7159590de0cf1b7fd8f7b213b732f1e537c62dab7 +21 -0
  471. package/vendor/impeccable/bundle/blobs/{8a1c872773996dfa1c1eb765ac7ed8e8d41f99d4f12f090b4725b694e85eaa62 → 3898bd9b56a042e860a0db4fb4dd81ac81126fa218b604702e2ac0c2287ae09b} +9 -0
  472. package/vendor/impeccable/bundle/blobs/3b2b60f23fa8ed9d73e721e17142c3933dc5318fa9a251742a76fee890ac81a8 +26 -0
  473. package/vendor/impeccable/bundle/blobs/3bd55b35c253f7841ca4e6e1a855a4b477d59aa2daf6e61e93fd685caaaff131 +63 -0
  474. package/vendor/impeccable/bundle/blobs/{dde1b74aeab3d90320e134f0ed0422bef99917dcab4c1749aa1720a2c94f725f → 3bed76a0d528e2d73da8acae4dc63702bdb5baca5ab11600d70e75fc9f2ba90b} +5 -0
  475. package/vendor/impeccable/bundle/blobs/{9b2fc50c5062073d097140cde85602bba181e325ec6b9eea1bd3da74582acb9d → 3ef9a43006bc68d83bc958fc8401e59f9beb6379048f5ced047747fdad05b895} +5 -5
  476. package/vendor/impeccable/bundle/blobs/{30e006fdee873bac23edaeadce0371161625e021e3cf442dff4b05bb82297ba1 → 400419aaa20f710e1a7e5ca1fce9e8bc995c4db84053f40cf778d987619e0210} +1 -1
  477. package/vendor/impeccable/bundle/blobs/40cd6024312a1339aa66801df533afa543e60c36e708f0f9659dd8d558f83dce +63 -0
  478. package/vendor/impeccable/bundle/blobs/{55e95137b3f9198c1d4dfc425366b82f1ef5f77d602682b2edf91f2ce9296289 → 412dd9a5238aee223397591fe49b3bd27b6b53d649a0e67ed8570f3e199cebb9} +1 -1
  479. package/vendor/impeccable/bundle/blobs/{181e814c1b9317098b2300c1b02ad0d137b6d82bd1e7e8cc64de4d00b4c50c25 → 41ef23c048ab739f48afdce26a2678d36ee40bcced34ef4b969d1d8ffafca64c} +3 -1
  480. package/vendor/impeccable/bundle/blobs/{edddeb3fad88adec9a055b1bf9d5c75418cbe97a13b1a7f6765e73249e482563 → 42831c3cd874346d8e7f120808d91e6ed3cda5c3eca6eefd76b126659536bc87} +5 -1
  481. package/vendor/impeccable/bundle/blobs/{e3c331cc21d9a216e25e08628610ea99c97e150893c3d26e5c0cecc532f26d7b → 43dbfcb7c2e54c9cca9fce66024f17c06a2f2be645547b718b75c8828a463de2} +1 -1
  482. package/vendor/impeccable/bundle/blobs/4435529820c3fc2eceae8b1ee35c906a34c7612fb860117e896152b45aee0770 +26 -0
  483. package/vendor/impeccable/bundle/blobs/44a60aedcc350c2d7d501d0f830a31a586a6511a9ff9b4e361cb328bb747339d +101 -0
  484. package/vendor/impeccable/bundle/blobs/{c6a0ec6c28ae55fe539f0f41a507b1638495afd285d6eb15c00245fc8cc7e7fe → 45dcea8da47cc21f447041daa942cf5d92cddde9a5a02c196cedbd159c829304} +5 -0
  485. package/vendor/impeccable/bundle/blobs/{015725eeca94f52bffd2132d4cb49bc3eb1ee76e6ac7378c065e629d59f56613 → 4700adf4542874f204c680ebad8317a97bf7169dbc04147082618ab59ce70c7d} +3 -2
  486. package/vendor/impeccable/bundle/blobs/4777bbeaff2efcd6a2a66b07aacaaf57cd32f3fab1c1da5a0513937fafb48bd1 +63 -0
  487. package/vendor/impeccable/bundle/blobs/{b6022a8c7200e96b0b55c2ff599a01d64123a2f5fe01557d4ca5192a6e0f0b0c → 484ea165f6d49ecc15b7a5c5623e377f2e203f4dad366df23eae99255ecf4572} +18 -11
  488. package/vendor/impeccable/bundle/blobs/485774d58dfd5796956024cdd9c12f05e692a3703f70b12a02ab43918885c3fd +101 -0
  489. package/vendor/impeccable/bundle/blobs/{3bf5d8661351831dbb2195e3b677fea1f128ca319c0589d538b66d9c9d7dddbc → 488da2e7406c6b4b5c92d7bc8cbd370cdaafc82a5f3ab5adbcffb21d1d1c4df4} +3 -1
  490. package/vendor/impeccable/bundle/blobs/{6f1d52863482fa0f6fff877f0cc8f6dd0b4230d28050b0d267e082776e61a332 → 492a8030d11e2f4908d934bd817bd6d16a3164056c74a7172f60e2cec5ff3055} +5 -0
  491. package/vendor/impeccable/bundle/blobs/{51e2f8963377f142ebdc9864e0ecc5aa1e5b7d344ed72d0e9d748d2d3d8c71b3 → 4972f28d96897c8dec891f0de7a0d9d51f36030ff780ed9d960241c75413da2b} +5 -5
  492. package/vendor/impeccable/bundle/blobs/4a6f0386bff78bb42efa285df2919e75209ec336672cf5fff91ba66ffb352eaa +63 -0
  493. package/vendor/impeccable/bundle/blobs/{12c1afcd15e86d840b89a78c6d17ce6d1b5609bac713d59271c6ab5932975dac → 4e3cc4d0e229ca96dd2e28fb2da0478a7f0bb64e447d07a652c425d8fbc57573} +3 -1
  494. package/vendor/impeccable/bundle/blobs/4ea8e05d0f88d24f182ad554da84317f90b9730e29fad262143ddf423a1f8645 +26 -0
  495. package/vendor/impeccable/bundle/blobs/{402656ca6df17bad1cd55ede0a966a7bb5b187cf4f89c517851f9efe7f14c0fd → 50d4b14134fc06daeac0aab6960800f171ef85250d3bcce6f246cf81e824463f} +3 -2
  496. package/vendor/impeccable/bundle/blobs/{43852ca5917de66704f73f9019d15482bb1efd92f2eefaeeeae23610b4c0c6a0 → 50f3b5714ca3e2c1bcf070003733407935ee050609d3123c2c065489fbc9950b} +5 -0
  497. package/vendor/impeccable/bundle/blobs/{f597742c8e5562263d3bce725cb55e920d8c2c60223f41a632d523ca30cdd12b → 51032bb883137007127d30189b44b516d0e6140271bf5881da7eca76f8bd282c} +3 -1
  498. package/vendor/impeccable/bundle/blobs/{13bd27aa8573e6d45d8bbf9f3fc991e4719d28a7e8f709009a4a5a49a227fff3 → 511ecde67e6bd976c9bdfa8d92f0dba359621344f8135c2a5ce5a66b385a4cb5} +5 -0
  499. package/vendor/impeccable/bundle/blobs/514a27fc9830455828d337cfc2fa95fa86be8e5464501bbabb9aca09a66b40ad +63 -0
  500. package/vendor/impeccable/bundle/blobs/{78ac93689928a580c2f90242cbaa96dda3fa4e55ff1f1d00e412b2a62ad85232 → 529cb2ace696ec11a86f4b010c9b137acf282072e483932181be1871df2aa690} +18 -11
  501. package/vendor/impeccable/bundle/blobs/53628d05b7eff0d4f48b95e48fad40266452fe1b42f398bd88dd9328353e0dd8 +101 -0
  502. package/vendor/impeccable/bundle/blobs/{00023f9e7f2e27604fde978b56510a8f837b76eeadd93221d11adcf4c98f1a10 → 53de37260c4f1c37e467557e9b038faa0f285b056bb2b95f435e0a7d1b69b0de} +3 -2
  503. package/vendor/impeccable/bundle/blobs/{0dbbef70048cc3ae44e6710ff09992ce14ad049ce8ed519b0ff8a1ddb4633f4e → 5415103ca4422ea1422e23bfe9f9bae181f5d6d6407442f7fba31856ada58d12} +3 -1
  504. package/vendor/impeccable/bundle/blobs/{af34b8af89edb10e228c0482754423f48238fce816eceb8703b8781c130da54e → 56285b28b0ffe471761c2ad062d3f933ed2346ca1b617f1323a30fed99a1a852} +1 -1
  505. package/vendor/impeccable/bundle/blobs/{12fefe52d80d25014e5f7e2f9b278275a675653d3d99ae8f0ecf344cdb9abbe6 → 56cc1bba51e6805de370160ce4a9399fef3740571204f13c3c751725870305e5} +3 -1
  506. package/vendor/impeccable/bundle/blobs/571f5c3bcf01c9b1bd02ab853a54db3f88375c4b8f39dd67d53e983a33e08bb7 +26 -0
  507. package/vendor/impeccable/bundle/blobs/{5ce02fc8f353d7f659535fb80e453963dc047a07c4396adf098fe010b479e7c0 → 5855d7595b0212bb8d521e0265378d437df8d2343d5f8a30408c3edde0a14d96} +3 -2
  508. package/vendor/impeccable/bundle/blobs/{2b21f0142ee88a11dbe2593362f5a910718a61062e3a64e7ff936ef1e74fd394 → 5a07d4769a741cd00fdf8c95b943ef072eb12cd0c9e2c2d2622d5fe0a4fa3894} +5 -5
  509. package/vendor/impeccable/bundle/blobs/{3dd45e1c32db3d3163a96ef198954905807b25cb9a1d206a7d77986f21d27652 → 5a9626fb8c1e9051155c68626fe7c765a55be325113245d44b4991fc3d3b014e} +5 -0
  510. package/vendor/impeccable/bundle/blobs/{d07e3131cdf3e392e59eaa3e2f59fcb0799d9494df4adfee12a21067fb8365ce → 5e354ae11913d5846faa3681a9ed98b68d1881fbbb1ecebf0769e3010bb0a426} +5 -0
  511. package/vendor/impeccable/bundle/blobs/{ad389ab12800738b0e5c97618278b7a824654b25990166ec9f389caa5c3386ca → 5e6eea05456108b8766cf354dda998e90b6a5ecca7f15d807e28659ee78c306f} +5 -0
  512. package/vendor/impeccable/bundle/blobs/{85b9c2d051de94ee9129c58be111946f73035ca62bbd2a3936f4fa48768fe5cf → 634257e766b1fecacd25e27dbfc7e21ef3b440b01e94e92b8b17711018d8a661} +18 -11
  513. package/vendor/impeccable/bundle/blobs/6428239079f98fd6500e9fd032dd289b52052da7a4364ff357b0a5341b6444db +63 -0
  514. package/vendor/impeccable/bundle/blobs/{f424dafa190533cd32c0bc3e4131d0c472d58e16bb191eab14f0ae73c2cea917 → 647bab2f5cf6279d58d808f4df05d1ac63c1c86c6df9d13406ae776458653995} +5 -0
  515. package/vendor/impeccable/bundle/blobs/{8e7bb79db7331b93f99de314dd5599de8587ec0b6c25e26cf1efab25c0777fcb → 6528f2aebe4a425b724de293c8f6dc8a42ca80c7f1ed3039b8b9a813b004956a} +4 -3
  516. package/vendor/impeccable/bundle/blobs/{89eb0206a0d9308c6c6a7cc01bc4fd8812d2bd34bb9a831988c5d86fac2c60de → 6575a657642ccdab42d0743ceaee06621c77811b4dc4f21c616e28aabf5e28ef} +1 -1
  517. package/vendor/impeccable/bundle/blobs/66d60356172ccafdd334fca9bf33243c8409216a733dcde0d66a24fd70ee8132 +1 -0
  518. package/vendor/impeccable/bundle/blobs/{759bab1d8adc071fdde2efcf6e2157aa4026f3c2b4f3c342a8070bf328011616 → 69cad1ae7355825ef320ac9638a1c9675ba9fda01c9a0fa12244cc4a1973e550} +2 -2
  519. package/vendor/impeccable/bundle/blobs/6d21d8e2729effaecc5b6239dadbcffb1ec8d51e8bdadeb47a39827266a61c5e +26 -0
  520. package/vendor/impeccable/bundle/blobs/{ff882c59c9aced92338aa194cc99a521ea2f083fd22eef3b1c1225e06bc72f66 → 6d9258a49c0b0583ec255eeb1092554298d5eea676fb9391f5a5a1377c3fd770} +4 -3
  521. package/vendor/impeccable/bundle/blobs/{68bc52a604731ca024610051fc763f4d78a53eb2a45d35b40a8c0383043baa63 → 6f4dfe968f47302ea64dca0e02f8c6d81497d93e4f436d09236e305456cbcc02} +4 -3
  522. package/vendor/impeccable/bundle/blobs/{f97a6891c80bbbc728edefcf4b638d1a823b38f3cb16ecd0fbb717734cc5c0c8 → 6f7f1639a933ed88e116aa8ab0cfb951096930d14f413349ae22ed04e28d2358} +5 -5
  523. package/vendor/impeccable/bundle/blobs/713a942482531ef8ef103adf48d9decd7327697450e444289aa0479458e4ee1f +101 -0
  524. package/vendor/impeccable/bundle/blobs/{6d47503587ad6da17ac529f44a96123bbb96a9c91a7a9350b7690fc467561a5d → 7212014fb2477d1d54aedaa79cdb861071a58afb2ae6d4dc5a495fa4810c6f8a} +5 -5
  525. package/vendor/impeccable/bundle/blobs/{21bc91f6e07691e82b7bba99f9e1d956f9d7a6810dcdc18d231fe73b53a13b23 → 73f8bdec7d9a97476fd7d7e0b4114b5c3e9c7b84c22cbb876cd18c3e64a9b8c5} +5 -0
  526. package/vendor/impeccable/bundle/blobs/{a8547c8565979894f0c07f92a96ac2a38e681a31fbf155ffeefc7566e185d9c2 → 754e9f0aa2101245a83cb17d8cc5bc49cf87997b29a83dedbfff283dbd0a8c4f} +5 -0
  527. package/vendor/impeccable/bundle/blobs/{84df879a0332a56ece4bff1922ecf4f50635951b3c67e67eb46f31bc5d30fa9a → 765d3e890cd7f58ca94b6834181052166e9c4f9ef06278dc241da4d64da2d595} +3 -1
  528. package/vendor/impeccable/bundle/blobs/778cedc9199b407d3e23fa1041e38d548b00b1101a33517aa2a2eb299f9d0edc +26 -0
  529. package/vendor/impeccable/bundle/blobs/{ef0b8eca20e1321cf7216fd0bda41ce54b0cca197cfd1b075eb51f3436f59059 → 77ae09542fbc10aa4e8b119d6fd19359908a47c13c30068d6a150bfdb50e3e10} +1 -1
  530. package/vendor/impeccable/bundle/blobs/{15b4837dccb27d7382e2f134ef050b244c4488b1906e0308f288112183cc09ac → 796bbd8231413fcbf22eb7e6f40c402842aa4b10b1894545a7b05d9201ca7c4a} +18 -11
  531. package/vendor/impeccable/bundle/blobs/{5e3616ac45568f239fda3a4764f7d3bf3473b8b5eefd91e402dd9208a4b851d1 → 7af7fcc09c6b14f26ba78734460a2f9dddd2dcd2e2fa0c47c682f539e2f4cad5} +1 -1
  532. package/vendor/impeccable/bundle/blobs/7b1a4cc5ce94837c8309962a204c47361927e442b7a1c3cc472f90276eca8b8c +63 -0
  533. package/vendor/impeccable/bundle/blobs/7c417abe75f0ce4341b6f5acbadcafbbeabcc32cdb13c930aecc5cabda9f9242 +26 -0
  534. package/vendor/impeccable/bundle/blobs/7e36403ed58e0e82c0e42bf2fbea1c066b8e63276978647a6f1e44bf1edb23fb +63 -0
  535. package/vendor/impeccable/bundle/blobs/80191b3580a996a2045105976f728e0f46de22c412fc7640741add9767b2d8f4 +101 -0
  536. package/vendor/impeccable/bundle/blobs/814610dee1081abc4213476ff0c4ae3e8f457909550d250ea0f89953687c85c6 +63 -0
  537. package/vendor/impeccable/bundle/blobs/8157b5a376e46980117f1ad6d08b24ee7be966f5de64b041bd213d486ea8c077 +26 -0
  538. package/vendor/impeccable/bundle/blobs/{bad9250670c18d89722563fd747bae4c4bec64d1db0ee09d12d4fea04fe271b8 → 8373668da1aa37c39888809ed9e834a7edfcb884af12f74934c270d004fba626} +3 -2
  539. package/vendor/impeccable/bundle/blobs/{46250caaec1bd69619a5b28a73cb3c845b319d029b0af9228aaa7001e7e0104a → 83d614fec61078175383012a088f49a9c0bb08b9ebd2b651c77cb94a323474ab} +5 -0
  540. package/vendor/impeccable/bundle/blobs/{a5371492582dbeb69b24a1a2947b256a2da8a4d55917af709bbab6e452d9d23c → 8449781319a33d4a10a7fab9bfa4812241c303b95f33703b300b097dba51089a} +18 -11
  541. package/vendor/impeccable/bundle/blobs/{12d2a8043ae8668ad29c32bfa92995849fc49cb016e6ebd4f7e59539d96e7b03 → 857c4a0db5859f1fa91152db684528299dfc552525f50f416d1625a270e12671} +5 -5
  542. package/vendor/impeccable/bundle/blobs/{bead87679caad7c537dd7c04c3bb78be56ac7eec279ad6aad7322f48ff2df2d9 → 871a8e4d749b807c693ebabd83defbd6c76e1bd2a0f53a28a460cb1308ba8634} +6 -0
  543. package/vendor/impeccable/bundle/blobs/{cf3ae16765e7b5bc333ef76e24ab37f080e3d62e931c4986158e3cbcda6b9f7a → 881a58aadf300bcc8f4947243e82192ae8dd7f14822a70fabc84fc74a5f9199c} +5 -5
  544. package/vendor/impeccable/bundle/blobs/{896da399bafcffb0623bdd81bb18709d6eab25c9d5917e739c8798f31ff0d076 → 88549c11ea55d5dfc9f551db9a9c270d7362a9d42aa83db7747c9a7f020e1255} +5 -5
  545. package/vendor/impeccable/bundle/blobs/9287af96048c58ed0e72493cf7eb90c3957d4ba8b19e70ecf5d1f54264e9e597 +101 -0
  546. package/vendor/impeccable/bundle/blobs/92b7ab84c828fa888f4882c417c3d7f8fde2e5445b40f96f4fc8181a3e058afc +101 -0
  547. package/vendor/impeccable/bundle/blobs/{e2f98c4136d0ab70ec32fcdef58edb20ed8ec4f6cc067e0dae952b22cfd6a471 → 93c53421c3376f695fe9dad5c82102f74bb5dd15e4ced81bb4ad50a71e5f1027} +1 -1
  548. package/vendor/impeccable/bundle/blobs/{a8f4056a85706c0c8f80ec48e9b437e198464100aa42786f9252051f4b931c19 → 95f0c7935a6d0375e09ae67ae0066c0ce7b583bf1d445d268cc4d2f4f900b1bb} +3 -1
  549. package/vendor/impeccable/bundle/blobs/98384b78af087855dbb526ec1e870a676ecd87f57237643dfea815317dad8a07 +26 -0
  550. package/vendor/impeccable/bundle/blobs/{948326fab89f0d5c07355a06b9b9c30d08bba2e3a673a0151ebbf5a39dff7b9a → 99e4a6facdb07986aa721bda8a4e35466b30091f32e38d7a71d9fcbe3591f65a} +5 -0
  551. package/vendor/impeccable/bundle/blobs/{44a91b3f0810f43829d8584e912812444d15614e4b57ca8070aee7ab899f7c1e → 9a4aa0d4903eabee987fdc92053466ff7f6eb0604797aee0efe67d67999b3eae} +5 -5
  552. package/vendor/impeccable/bundle/blobs/{9b85b85443aec09918befb83208c72f475457db8261a8fc5e83ef7eec474c869 → 9d45e5f6c082de6df4a2cfff11deb969715c49b5d9891d100dd1b2252c5bdcdd} +18 -11
  553. package/vendor/impeccable/bundle/blobs/9db3c0857f4c2c8877b1fe24a47a229fee0de76ec9057bd8ee95f0677fb58d74 +26 -0
  554. package/vendor/impeccable/bundle/blobs/{5738bcf9ac21dbb2113fd0c5cc7e4bbfc8174778916ab5843644332b3dbbc36e → 9e82126a2e08aa365f9c430d383cf6e1921e04d1e0a1b5777716ff97828cfad8} +5 -5
  555. package/vendor/impeccable/bundle/blobs/{b3782f2d9215eb0f5df4fe3c0e0bec07cef011e1836d4d0e45ef02bc48d3adde → 9f2993499adadfdef4065a9a7fb69c75f888d892d4ee6bdbe62619bc772f495c} +1 -1
  556. package/vendor/impeccable/bundle/blobs/{1c804990fd8ac23a4b19c42972b5ae591d17f620d0006f0f32927c8db5d5bf50 → a1af8b8a97665a3692eb39872c235796684a387a0b83785872f81aebd9dab046} +18 -11
  557. package/vendor/impeccable/bundle/blobs/{824b994782a1fe68a244bbdff7218a2e0854655d90cc0fb5ade7ef9259ba6305 → a27399e3056c77a28ddd310fb5b4dee6e8e440dfa1737f7e38815097bec4c3a9} +5 -5
  558. package/vendor/impeccable/bundle/blobs/a569989e6a3d6453b4c45e9474e162a15cc54e11732ac6baa7990a6e7cccc0b5 +21 -0
  559. package/vendor/impeccable/bundle/blobs/a75b892696469e3ccd2af33c9eef793e635efc3c5ac45336b0c1373d90c856b0 +63 -0
  560. package/vendor/impeccable/bundle/blobs/{3ba92d4aa840ec1b6c2fda224339489d6dd65eedf43bb45836af02584d1faa88 → a7e8e60df83c6f47590467094ab2a13f1fe28ce45959a4e69dd89575a4208646} +5 -0
  561. package/vendor/impeccable/bundle/blobs/{e49d2b0110c55751da3c965b4ae4d294aa676c961a09f8efbbbf22c1ec7c4fa0 → a892e337eee548d53252abb72ba5aa85cbcf556ffd8dc74e05534652c010d574} +1 -1
  562. package/vendor/impeccable/bundle/blobs/{8f0867db7c6f6a54348a0d951f198a1bd852cd12505d821e6e1ac6bd42e7fcea → a93397adc906e245c69b42d4b25931fc92dc75baa60ca9a3749ba23b52ba01a0} +3 -2
  563. package/vendor/impeccable/bundle/blobs/{424b2e75cb204e2dca7db4a40dfe5a81f78dc0fc58ac4790e8b7bbf2f330bba4 → a9e63b2df611805e845e0bb1cca1a0c27e83640a78185c9fd9de90d53a539cdc} +5 -0
  564. package/vendor/impeccable/bundle/blobs/ab80e6a971baa66342548a846ce3fb69824ef9ef4e0f26c6f02685f225d00bbd +26 -0
  565. package/vendor/impeccable/bundle/blobs/af35b5fb6e45acb6483a5fbb864c3eaa9c57bacc43857f48183c836041c670ae +101 -0
  566. package/vendor/impeccable/bundle/blobs/af5842c4844b692b817319d5375611d4211dc7f459fb12da358baefc3a6cd373 +63 -0
  567. package/vendor/impeccable/bundle/blobs/b2732083f8f1d1924d38f84f179491430aebda8e0fd1f1d0785e3f883bcf3a40 +63 -0
  568. package/vendor/impeccable/bundle/blobs/b3b1d5a4c80ce279d88896601deee9ccfeacdae0d0cd433600985a5f7ac93c72 +26 -0
  569. package/vendor/impeccable/bundle/blobs/{fd5579dbae1fc2495b7dddde48df9673acebd27953bbb56d506d3b470375c9e9 → b4be5499f404a926cdd2c55d8fb7409ba74a56b3d0c7d865594cc0254d3e499a} +5 -0
  570. package/vendor/impeccable/bundle/blobs/{2fd096823e4a93f19edd421a69e10f90ebb630a014c673d1802a927c6f47b7d2 → b626e0677288a1660e9ce80c4f0454b527010239681f6b8dcc0f36b4a4d6bcb2} +3 -1
  571. package/vendor/impeccable/bundle/blobs/{33b6b32c0c3c0c4a2b22bd2275176b1c88a006dd94592a854f629911a0b21cdc → b719be9c5d4ced5d649ec6c0c90630196e7ee513d0da482aef13c705fdc23ab6} +3 -1
  572. package/vendor/impeccable/bundle/blobs/{df0eb9e9a484fc7b8a0f3e50573a7d7f81e0f17598ac30d9f3fe5a6c6aa5fefa → b8938fea3399aa639b4c873248035c219658069eef7be62672254e2f72c056f4} +5 -0
  573. package/vendor/impeccable/bundle/blobs/{ee0a15fcfc244b76b896a2650a17b35e444d4311166b69a3cfa32d11f8f44851 → ba0d96d88ab40fad1cb522e60b11affc568cfe9d340110ac5e71f834ac3d0f4a} +12 -0
  574. package/vendor/impeccable/bundle/blobs/{426c7f5437dd3c23a4cfaef6964dc7f1e038480f92238499b85f3ce7e4472bf4 → bc48bca63dff44e1f0205bafb64e16b2d6fb294ace405dbc9ae06a3bc6107154} +3 -1
  575. package/vendor/impeccable/bundle/blobs/{c3ad2a5fa570876af6645c48d246c664859e19f253d2dc9e0ead34e785d5b40a → bdd676c8f29295addfdbceaab285bb1184ec3ef7ff60501908b97ea8269580c4} +3 -2
  576. package/vendor/impeccable/bundle/blobs/{38d4d404030c6ea935d3223db1eeb22c45d04a94f41f98e02a43cdc5af7ff2e3 → c06effcdc60859157208d3b7ee23d56160f2386f6a2dfa2514ba82fe21828ae0} +1 -1
  577. package/vendor/impeccable/bundle/blobs/c100b67a4ae248ad564182b181acb1ee2fe64c00049aeef62d4e7a3213726f37 +26 -0
  578. package/vendor/impeccable/bundle/blobs/c2dfc965319745c403b99e00e9e97de15f1300ea721bd3f708f0ac47aadc537b +101 -0
  579. package/vendor/impeccable/bundle/blobs/{e9da72a13eb3411d6bbb316953022f62abc4434f505e5345907b216eda9f793b → c6b3bc811eb23d90ff9add1e0e5b40999a0bbbab364f5e6d08061f36d30429a5} +1 -1
  580. package/vendor/impeccable/bundle/blobs/{82a5e564563333aabb7ab4d2f8c26c785dfe2c2416ac6e9f30cba31440676194 → cdf8a88b9865599c58fe285041d2d46eea7d9bd2d4075d82de358191742b20ad} +5 -5
  581. package/vendor/impeccable/bundle/blobs/cf3d3a296890ac1ee363fee930f252e20d0935cd575367ad017b3cdc2dc5a50d +26 -0
  582. package/vendor/impeccable/bundle/blobs/{a1e4febca3455787d7c753fe177a150dccde6e742957de400b0307247802d200 → d2e16da9bb6b33c931378d1bf57dcfff5dc426a71434bc352cec6aece715a66f} +18 -11
  583. package/vendor/impeccable/bundle/blobs/{c36f6aac0ddf52eabbb21df09fd3310540dca6b09e7a4017d18e94c06c469405 → d4a9e18a879bbb92aa0a56e16b45481090dffa4470efdecf52fb0da8c900be5d} +5 -5
  584. package/vendor/impeccable/bundle/blobs/{869fa5390b84bfd00d072f5280a9002ea3e3936edf5985241be641a87f03ff7b → d57c3e0453f601ad688911fca4471057c7b46b561fcd42a1e12a581101c5186c} +1 -1
  585. package/vendor/impeccable/bundle/blobs/{910461b1c1f8216155165955c860a884a1e2f557cb38f21ef512ea90ef6503c2 → d5f83912eda93d42f93522bb74aeff0ea04d9c559577ec52fcccc130dd03166d} +2 -1
  586. package/vendor/impeccable/bundle/blobs/{9deb14303b421b5a9232755b5b9f317716f33e1e211557a98a00a9c409775c4d → d6489d7f3e607ce3f8514a7a7d3a0eb5e8f1ac55859eaf7d5c31b53de8fab9f3} +18 -11
  587. package/vendor/impeccable/bundle/blobs/{37080ea5e5b381adb7eae7a427231b0ad0dee0f0916fc1d6b673b7101a5b425b → d6a51f4df6d76f16b95ab81268a689f4c5936d505c5bb25c80ad7423f927bbc6} +5 -0
  588. package/vendor/impeccable/bundle/blobs/{61c72fdde649bf7f2e0668e48f9d222666c81672100b5f2265940e7aa13c8767 → d7b99a57652cb8741d57a15ba7e06de4707fac02a97e5e001179da007272f2b8} +3 -1
  589. package/vendor/impeccable/bundle/blobs/{57402ef6fd9d0745f8c60d778f77da83a8b16edf751fa1013598a0f6e5f0f541 → d9963fd73bf6129fe0c8ec25c5148f50617ec85683b8eeae7e411c9a42e2db33} +2 -1
  590. package/vendor/impeccable/bundle/blobs/{581409ace104a81744b7d08f5398a2c207cf76d9e50751f807b4382eaf66454f → da3b2399814db89d67959268c646601957d3e8c641b09a5bdbce84217c1c2cfe} +5 -5
  591. package/vendor/impeccable/bundle/blobs/{249f0437a52ab3eb4bc4d4a9f38e085334c0fbb7795e88dd419e32b5f58c924d → dc3aeccbea3e997704ce8b170f56b0eaf343a14ad4fedb22a6dbee0f205aa37f} +5 -0
  592. package/vendor/impeccable/bundle/blobs/{433a79eee3ce4c99e79a7aebe3a6d8ec9ff70216772e0c2ff9dce3a01d672963 → dcc1572e739cdabcbf084f276b447cb686aa18459896e6d8fe29f4d7d807bd1d} +5 -5
  593. package/vendor/impeccable/bundle/blobs/{2d7086992c07df1fc734cdf9c420c4bd8ad409ab7909e07c8b486c303d420732 → dd66761b291c7dbca6e9efd22023e38f8c53ad310f3a6cdab5dc7ecd7ae8f31f} +3 -2
  594. package/vendor/impeccable/bundle/blobs/dd953992625c240fd1842aaf533a865aabd09487cbc16fa01fe8bb4b4365b843 +101 -0
  595. package/vendor/impeccable/bundle/blobs/{df4f14df1daaad1606b682995f649da19a85debf264092447b3b7ddb8b4bc1ce → de70398719140e4951aa111e9625de5ed916ad1ef0877e4ab6f6b4a7e3cc5f8f} +18 -11
  596. package/vendor/impeccable/bundle/blobs/{8b23562ccc3e41609ce6e67fdad6cc57b6c961964c329eff6975a1b4c5471c0d → deaaa533475b6a9f7dd52e01a1f1997aa3af146694334981650f8c846f939559} +3 -1
  597. package/vendor/impeccable/bundle/blobs/{041535231366047a0beeb5daa64ea9c23d5a566580f7dafdb8c0623cb4a7e76b → e07176229b8a330970ca3c9c5e3dd68c2aaeb726285e30f471e91053d7f8e798} +1 -1
  598. package/vendor/impeccable/bundle/blobs/{115e1c3f1b58b5129910ed925dbf65d61d5ac4c2036618847555ce40098aae97 → e1075ea5b34ac9c60f7c5bda97356eeaf1b683b599592d324fd3704f0852ad7a} +18 -11
  599. package/vendor/impeccable/bundle/blobs/e3af212117e0c552b0976687200fe8f95846a01725a482e8e4dbfd75e40dbfa6 +26 -0
  600. package/vendor/impeccable/bundle/blobs/e3c2031978cd670d7150ff3140f12cf8b6882ef638ea9a9985caffa9a80c8713 +63 -0
  601. package/vendor/impeccable/bundle/blobs/e6e18e7c23cfe82961d90b9714cb466c20bd83f222ac63e9339b6b2c304e1787 +26 -0
  602. package/vendor/impeccable/bundle/blobs/e7af7ad18b307a3171fcf49421df2a557f93289d27af2430f10ee74e2a2fc2d3 +101 -0
  603. package/vendor/impeccable/bundle/blobs/{b161198874e4e77599bc31691e78790be14bacc2eb03be168c8a7543ece9fbe1 → e85da3098368807689009184eca2bb09a91bdb6cb1be3e7a61f91f1ae31cd69b} +18 -11
  604. package/vendor/impeccable/bundle/blobs/{6bdbc3f745ceee15e10b050f109ce42bbeb53ab3c3b5239257de1d596654dee7 → e8720f3aa41135211cc58cc299a39eeda86c75651f4279cc1ede8db10dcc0584} +4 -0
  605. package/vendor/impeccable/bundle/blobs/e9861052457cc1ddc42c687bb8c33a877834ced94fed74af2a4f00f6bae50795 +101 -0
  606. package/vendor/impeccable/bundle/blobs/{d1faa55eb956033d28e9f27fd2bc2a9f62c5da0f0abd6534819cc0a04db54d9d → eb3e86876c20f1cfc443dcbe48d8f41fea6e815082a304610be432272429a06d} +5 -0
  607. package/vendor/impeccable/bundle/blobs/{0e1819750e5448311a051d35ab6d0be0830418f78ca872ef10469fafebb27d4f → eba472f6190541c28e2e647ed019f43564ba5b92d629963f34c899175b25b31e} +5 -5
  608. package/vendor/impeccable/bundle/blobs/{f173ff03f989f162cee815feb2d8ca72daf00019c48694d89db16d52171a79c0 → eba609589a5a051643a7bae60b7cceef7cfe44d0f8bd9229e61473ac75910fb3} +1 -1
  609. package/vendor/impeccable/bundle/blobs/{8eb466778023fccea641654d662157b123eeb360f4a0875bf6fbe3d93680851c → ec81b008d2641402e3352b09b1a90562ef7a24598d7c5aded475038cce63aca0} +1 -1
  610. package/vendor/impeccable/bundle/blobs/{4acfb9e38f6e09f7484e36fc19704d69eab159436ee9329168be74c493042f22 → ec86b8633fbeb14ef2272f220fdd98089972b03b99da83e49eeb6a8b73b00617} +3 -1
  611. package/vendor/impeccable/bundle/blobs/{d15a2914d93e07a4956acd5c8b8211af17380f527acd10d8acf4f4920badaaaf → ef2e97cd690baf6fe5c895dd2d8844aff9fcc4a8bc04973402678a739c81d712} +4 -3
  612. package/vendor/impeccable/bundle/blobs/f0fbe529f63961a027bada2e6a3cbe86f4af0dba4b8e1010da22b007f9002f66 +63 -0
  613. package/vendor/impeccable/bundle/blobs/{c02feba25a961a72647ad317aba2d65baeeed53c4cdcc072f25bb37f4d867d43 → f254d59ff973e907cacdc2c34b8b4de075437d292de31dac30e10a9d7035086c} +3 -2
  614. package/vendor/impeccable/bundle/blobs/f5efb1b1dd4cd18e1d4789d7c8e0188f4342b25fffd53af6088ba8b67774fb99 +26 -0
  615. package/vendor/impeccable/bundle/blobs/{7af0a8665057c83b39bca2c8c7427ef2343734f70d4128c377113a6726a1e3b1 → f68a3d68ac92606e91aa8878e003d9432ddd09aa97ca01c6b3ce46c937dca316} +524 -4
  616. package/vendor/impeccable/bundle/blobs/{381ff89aa76e82a0d98456ec31cb117555ae045539fba47c45056daa50f611ca → f84b653ede0804d21e6210c6d21fd5352023914fedceae6ff14e20f1e93b06e7} +5 -5
  617. package/vendor/impeccable/bundle/blobs/{5b30a06646ad5e453d6b5ed1b8d446f69fca3cd13b8aeda28f0d0b2cbe8f62d1 → fb32d99751c5fc24493ff4460be1767bd5236dc820fd337775067c0620d1a7a6} +3 -1
  618. package/vendor/impeccable/bundle/blobs/{733504a70ed20bcfca9c26c353f7b88f8491d24f3f2fe124dc1e73b28eefa296 → fb5fec24adafa48df43eece6907c1c986a4772cbdc64142c881f00c3b312e9ca} +18 -11
  619. package/vendor/impeccable/bundle/blobs/fc149b5bc7a8d0cc9b9bf86e5013793f3857c1c302212e9aaf101cb95427386b +101 -0
  620. package/vendor/impeccable/bundle/manifest.json +413 -298
  621. package/skills/grafton-view-dev/SKILL.md +0 -195
  622. package/skills/grafton-view-dev/references/bindings.md +0 -120
  623. package/skills/grafton-view-dev/references/components.md +0 -168
  624. package/skills/grafton-view-dev/references/recipes.md +0 -208
  625. package/skills/grafton-view-dev/references/schema.md +0 -86
  626. package/skills/grafton-view-dev/references/stores.md +0 -310
  627. package/skills/portal-backend-app/SKILL.md +0 -56
  628. package/skills/portal-backend-app/references/gate-and-tokens.md +0 -93
  629. package/skills/portal-backend-app/references/wiring-and-conventions.md +0 -71
  630. package/skills/xgent-init/references/external-app-CLAUDE.template.md +0 -249
  631. package/vendor/impeccable/bundle/blobs/800cf1c0392b24de7c0a1c6ea6778ecb433dec71c49a150bce96a98477527b2f +0 -1
@@ -10,6 +10,8 @@
10
10
  # onebox.sh up ★ 按顺序把整套铺起来(迁移→种子→各库→注册→起栈),幂等可重跑。
11
11
  # 顺序本身是契约(种子会 truncate、反代启动时才读 /svc map),
12
12
  # 这条命令就是为了不让人自己记它。
13
+ # onebox.sh upgrade [--image <ref>] [--proxy-image <ref>]
14
+ # 换部署资产并追加版本信息;保留现有配置、端口、密钥与数据,再跑 up。
13
15
  # onebox.sh doctor ★ 体检:把排查表里能自动判的都判一遍,每条给一行可直接粘的修法。
14
16
  # 跑不通先跑它,别翻文档。
15
17
  # onebox.sh add <key> ★ 把一个平台侧 App 拉进来陪调(如 omni-parser 多模态解析):
@@ -74,6 +76,8 @@ load_registry_config() {
74
76
  done < "$f"
75
77
  # base64 不是加密,同组可读就等于把口令摊在那儿
76
78
  if [ -n "${PULLER_AUTH:-}" ]; then
79
+ # Only the permission field is read; the filename is never parsed.
80
+ # shellcheck disable=SC2012
77
81
  case "$(ls -l "$f" | cut -c1-10)" in ??????---*) ;; *) warn "$f 含 PULLER_AUTH 且同组/其他人可读 —— chmod 600 $f";; esac
78
82
  fi
79
83
  }
@@ -123,12 +127,13 @@ registry_login() {
123
127
  || die "docker login $REGISTRY 失败。口令可能已被轮换 —— 先 docker logout $REGISTRY 再让开发团队补一份新的 PULLER_AUTH。(陈旧凭证不会提示你去登录,只会一直 401。)"
124
128
  }
125
129
 
126
- # do_pull REF HINT —— docker pull 的 "What's Next" 提示走 stderr,>/dev/null 挡不住;
130
+ # do_pull REF HINT [PLATFORM] —— docker pull 的 "What's Next" 提示走 stderr,>/dev/null 挡不住;
127
131
  # 但 2>&1 会把真错误一起吞掉,所以收进临时文件、只在失败时回显。
128
132
  do_pull() {
129
133
  local ref="$1" hint="$2" errf; errf="$(mktemp)"
130
- info "拉 ${ref} …"
131
- if ! docker pull "$ref" >/dev/null 2>"$errf"; then
134
+ local -a pf=(); [ -n "${3:-}" ] && pf=(--platform "$3")
135
+ info "拉 ${ref}${3:+(${3})} …"
136
+ if ! docker pull ${pf[@]+"${pf[@]}"} "$ref" >/dev/null 2>"$errf"; then
132
137
  local msg; msg="$(tail -3 "$errf")"; rm -f "$errf"
133
138
  die "docker pull $ref 失败。${hint:+$hint
134
139
  }$msg"
@@ -254,6 +259,85 @@ port_free() { ! (exec 3<>"/dev/tcp/127.0.0.1/$1") >/dev/null 2>&1; }
254
259
  pick_port() { local p; for p in "$@"; do port_free "$p" && { printf '%s' "$p"; return; }; done; printf '%s' "$1"; }
255
260
  rand_hex() { openssl rand -hex 32 2>/dev/null || head -c32 /dev/urandom | od -An -tx1 | tr -d ' \n'; }
256
261
 
262
+ _image_version() {
263
+ local image="$1" id created
264
+ id="$(docker image inspect "$image" --format '{{.Id}}' 2>/dev/null | cut -c8-14 || true)"
265
+ created="$(docker image inspect "$image" --format '{{.Created}}' 2>/dev/null | cut -c1-10 || true)"
266
+ [ -z "$id" ] || printf 'onebox %s %s%s' "${image##*:}" "$id" "${created:+ built ${created}}"
267
+ }
268
+
269
+ # Shared by init and upgrade. Machine-owned state must never come from an image.
270
+ _extract_assets() {
271
+ local image="$1" home="$2" postgres_volume="${3:-}" tmp cid
272
+ info "从 ${image} 取出 compose 资产…"
273
+ tmp="$(mktemp -d)"
274
+ cid="$(docker create "$image")" || { rm -rf "$tmp"; die "docker create 失败,请确认镜像已就位。"; }
275
+ if ! docker cp "$cid:/app/deploy" "$tmp/deploy" >/dev/null; then
276
+ docker rm -f "$cid" >/dev/null; rm -rf "$tmp"
277
+ die "镜像里没有 /app/deploy,请使用门户一盒镜像。"
278
+ fi
279
+ docker rm -f "$cid" >/dev/null
280
+ if ! grep -qE '^ rustfs:' "$tmp/deploy/docker-compose.yml" \
281
+ || [ ! -f "$tmp/deploy/scripts/objectstore-cutover.sh" ] \
282
+ || [ ! -f "$tmp/deploy/scripts/objectstore-manifest.ts" ]; then
283
+ rm -rf "$tmp"; die "镜像里的对象存储资产还是旧版,请 upgrade --image <新版一盒镜像>。"
284
+ fi
285
+ ( cd "$tmp/deploy" && rm -rf .DS_Store k8s oauth pm2 caddy knowledge-devkit onebox/Dockerfile \
286
+ compose.env generated backup scripts/tests \
287
+ app-devkit/manifests/pagebuilder.manifest.json app-devkit/manifests/task-gateway.manifest.json )
288
+ # Persist volume identity in staging before replacing assets. If a later version
289
+ # check refuses an unknown layout, the next run must still find the same data.
290
+ if [ -n "$postgres_volume" ]; then
291
+ if ! awk -v volume="$postgres_volume" '
292
+ /^volumes:/{volumes=1}
293
+ volumes && /^ pg-data:/{print " pg-data:"; print " name: " volume; pg=1; count++; next}
294
+ volumes && /^ [A-Za-z0-9_-]+:/{pg=0}
295
+ pg && /^ name:/{next}
296
+ {print}
297
+ END{if(count!=1)exit 1}
298
+ ' "$tmp/deploy/docker-compose.yml" > "$tmp/compose-pinned.yml"; then
299
+ rm -rf "$tmp"; die "新版资产缺少唯一 pg-data 卷定义,未替换现有资产。"
300
+ fi
301
+ mv "$tmp/compose-pinned.yml" "$tmp/deploy/docker-compose.yml" \
302
+ || { rm -rf "$tmp"; die "无法保留 PostgreSQL 卷名,未替换现有资产。"; }
303
+ fi
304
+ # This retired overlay otherwise survives extraction and duplicates logging mounts.
305
+ [ -f "$tmp/deploy/onebox/docker-compose.portal-logs.yml" ] \
306
+ || rm -f "$home/onebox/docker-compose.portal-logs.yml"
307
+ ( cd "$tmp/deploy" && tar -cf - . ) | ( cd "$home" && tar -xf - )
308
+ rm -rf "$tmp"
309
+ }
310
+
311
+ cmd_upgrade() {
312
+ local image="" proxy=""
313
+ while [ $# -gt 0 ]; do
314
+ case "$1" in
315
+ --image) image="${2:?}"; shift 2 ;;
316
+ --proxy-image) proxy="${2:?}"; shift 2 ;;
317
+ *) die "upgrade: 不认识的参数 '$1'" ;;
318
+ esac
319
+ done
320
+ if [ -z "$image" ]; then
321
+ image="$(_eff XGENT_IMAGE)"
322
+ [ -n "$proxy" ] || proxy="$(_eff XGENT_PROXY_IMAGE)"
323
+ fi
324
+ [ -n "$image" ] || die "compose.env 缺 XGENT_IMAGE,请 upgrade --image <新版一盒镜像>。"
325
+ [ -n "$proxy" ] || proxy="${image%/*}/proxy:${image##*:}"
326
+ pull_images "$image" "$proxy"
327
+ # Retain the old volume identity even after down and with a custom volume name.
328
+ local postgres_volume; postgres_volume="$(_postgres_volume)" || die "无法确认升级前的 PostgreSQL 数据卷。"
329
+ _extract_assets "$image" "$HOME_DIR" "$postgres_volume"
330
+ _env_set XGENT_IMAGE "$image"
331
+ _env_set XGENT_PROXY_IMAGE "$proxy"
332
+ local version; version="$(_image_version "$image")"
333
+ [ -z "$version" ] || _env_set APP_VERSION "$version"
334
+ _objectstore_image
335
+ _pin_postgres "$postgres_volume"
336
+ _kafka_defaults
337
+ info "部署资产已升级;现有配置、generated/、backup/、端口与数据卷保留。"
338
+ info "下一步:$0 up(仍会重种门户库;App 自己的库不重置)。"
339
+ }
340
+
257
341
  cmd_init() {
258
342
  local image="${XGENT_IMAGE:-}" proxy="" key="" home="./portal-onebox" force=0
259
343
  while [ $# -gt 0 ]; do
@@ -288,11 +372,11 @@ cmd_init() {
288
372
  --format '{{.Label "com.docker.compose.project"}}\t{{.Label "com.docker.compose.project.config_files"}}' 2>/dev/null \
289
373
  | awk -F'\t' -v h="$home/" '($1=="xgent-onebox" || $1 ~ /^onebox-/) && index($2, h)!=1 { print $1; exit }' || true)"
290
374
  if [ -n "$other" ]; then
291
- [ "$force" = 1 ] || die "本机已有一套一盒(compose 项目 $other)—— 一台机器只共用一套,别再铺第二套。
375
+ [ "$force" = 1 ] || die "本机已有一套一盒(compose 项目 ${other})—— 一台机器只共用一套,别再铺第二套。
292
376
  要调你的 App:XGENT_ONEBOX_HOME=<那套 portal-onebox/ 的路径> 复用它的栈跑 register-app / dc;
293
377
  宿主上的 dev 后端直连它的 pg/redis/minio(SKILL.md §5)。那套的路径查看:docker compose ls。
294
378
  确需整份重来(--force 会连 compose.env 一起重建):$0 init --force …"
295
- warn "本机已有另一套一盒($other)—— --force 放行,但请确认那套已 down 掉,别长期并存。"
379
+ warn "本机已有另一套一盒(${other})—— --force 放行,但请确认那套已 down 掉,别长期并存。"
296
380
  fi
297
381
 
298
382
  # 1) 备齐镜像 —— 没有 puller 凭证就在这里停下,而不是让人跑到一半才发现
@@ -304,29 +388,19 @@ cmd_init() {
304
388
  # (CR-4:自动授予租户那段代码比某一版镜像新一天,症状是市场里没有卡片且零报错)。
305
389
  # 这里把 tag + 镜像 ID + 构建日期钉进 compose.env,`/health` 与 `status` 立刻能回答
306
390
  # 「我跑的是哪一版」。取不到就留空,不编。
307
- local img_id img_created ver=""
308
- img_id="$(docker image inspect "$image" --format '{{.Id}}' 2>/dev/null | cut -c8-14 || true)"
309
- img_created="$(docker image inspect "$image" --format '{{.Created}}' 2>/dev/null | cut -c1-10 || true)"
310
- # 取不到镜像元信息(离线 load 的、docker 不认的)就留空 —— 宁可不自报,也不编一个版本号。
311
- if [ -n "$img_id" ]; then ver="onebox ${image##*:} ${img_id}${img_created:+ built ${img_created}}"; fi
391
+ local ver; ver="$(_image_version "$image")"
312
392
 
313
393
  # 2) 从镜像里取 compose 资产 —— 版本天然与镜像对齐,不需要门户仓
314
- info "从 $image 取出 compose 资产…"
315
- local tmp cid; tmp="$(mktemp -d)"
316
- cid="$(docker create "$image")" || die "docker create 失败。先 docker login 到镜像仓库,并确认 tag 写对了。"
317
- docker cp "$cid:/app/deploy" "$tmp/deploy" >/dev/null || { docker rm -f "$cid" >/dev/null; die "镜像里没有 /app/deploy —— 这多半不是门户一盒镜像。"; }
318
- docker rm -f "$cid" >/dev/null
319
- # 只留联调用得上的:compose + 一盒增量 + devkit + postgres 建库脚本 + 两个 manifest 样例
320
- ( cd "$tmp/deploy" && rm -rf .DS_Store k8s oauth pm2 caddy knowledge-devkit onebox/Dockerfile \
321
- app-devkit/manifests/pagebuilder.manifest.json app-devkit/manifests/task-gateway.manifest.json 2>/dev/null || true )
322
- ( cd "$tmp/deploy" && tar -cf - . ) | ( cd "$home" && tar -xf - )
323
- rm -rf "$tmp"
394
+ _extract_assets "$image" "$home"
324
395
 
325
396
  # 3) 挑空闲端口 —— 首次用最常见的翻车就是 80/5432/6379/9000 已被别的东西占着
326
- local hp hsp pgp rdp mnp mncp base
397
+ local hp hsp pgp rdp mnp mncp kfp base kafka_cluster_id kafka_password
327
398
  hp="$(pick_port 80 8080 8090 18080)"; hsp="$(pick_port 443 8443 18443)"
328
399
  pgp="$(pick_port 5432 15432 25432)"; rdp="$(pick_port 6379 16379 26379)"
329
400
  mnp="$(pick_port 9000 19000 29000)"; mncp="$(pick_port 9001 19001 29001)"
401
+ kfp="$(pick_port 9092 19092 29092)"
402
+ kafka_cluster_id="$(_kafka_cluster_id)" || die "无法生成 Kafka 集群 ID,初始化中止。"
403
+ kafka_password="$(_kafka_admin_password)" || die "无法生成 Kafka 管理密码,初始化中止。"
330
404
  base="http://localhost"; [ "$hp" = "80" ] || base="http://localhost:$hp"
331
405
 
332
406
  # 4) 三段模板 + 本机覆盖块(覆盖块必须在最末尾)
@@ -355,6 +429,9 @@ POSTGRES_PORT=$pgp
355
429
  REDIS_PORT=$rdp
356
430
  MINIO_PORT=$mnp
357
431
  MINIO_CONSOLE_PORT=$mncp
432
+ KAFKA_PORT=$kfp
433
+ KAFKA_CLUSTER_ID=$kafka_cluster_id
434
+ KAFKA_ADMIN_PASSWORD=$kafka_password
358
435
  PORTAL_BASE_URL=$base
359
436
  FILES_APP_URL=$base
360
437
 
@@ -379,6 +456,7 @@ APP_IMAGE=
379
456
  # micro(有前端、iframe 嵌入)才要,且必须是【绝对路径】、目录里有 index.html:
380
457
  #APP_FRONTEND_DIST=/abs/path/to/your/frontend/dist
381
458
  EOF
459
+ chmod 600 "$envf" || die "无法保护 compose.env 权限,初始化中止。"
382
460
 
383
461
  # 5) 别让它进版本库:里面是密钥,且随时能从镜像重新生成
384
462
  local root; root="$(git rev-parse --show-toplevel 2>/dev/null || true)"
@@ -390,18 +468,15 @@ EOF
390
468
  echo
391
469
  printf '%s一盒资产就位:%s%s\n' "$c_grn" "$home" "$c_off"
392
470
  printf ' 门户地址 %s\n' "$base"
393
- printf ' 端口 http=%s pg=%s redis=%s minio=%s/%s\n' "$hp" "$pgp" "$rdp" "$mnp" "$mncp"
471
+ printf ' 端口 http=%s pg=%s redis=%s minio=%s/%s kafka=%s\n' "$hp" "$pgp" "$rdp" "$mnp" "$mncp" "$kfp"
394
472
  printf ' 项目名 xgent-onebox(全机一套共用,别改名)\n'
395
473
  echo
396
474
  echo "下一步(顺序本身是契约,见 SKILL.md §3)。先记一个短名:"
397
475
  echo " S=$0"
398
476
  echo
399
477
  echo " 1. 编辑 $envf 末尾:填 APP_IMAGE(micro 再加 APP_FRONTEND_DIST)"
400
- echo " 2. \$S dc up -d postgres redis minio"
401
- echo " 3. \$S dc run --rm portal-api bun run db:migrate"
402
- echo " 4. \$S dc run --rm portal-api bun run db:seed:onebox"
403
- echo " 5. \$S dc run --rm -v \"\$PWD/<放 manifest 的目录>:/devkit:ro\" portal-api bun run register-app /devkit/app.manifest.json"
404
- echo " 6. \$S dc up -d 然后 \$S smoke"
478
+ echo " 2. \$S up"
479
+ echo " 3. \$S doctor"
405
480
  }
406
481
 
407
482
  cmd_pull() {
@@ -424,7 +499,7 @@ cmd_pull() {
424
499
  do_pull "$image" "tag 写错了?一盒只有两种::latest(可变指针,跟着最新一版走)和 :v<版本>-<7位sha>(钉住某一版)。"
425
500
  do_pull "$proxy" "代理镜像名是从 runtime 镜像推出来的,有的部署不叫 proxy —— 用 --proxy-image 指定。"
426
501
  printf '%s两个镜像就位%s\n' "$c_grn" "$c_off"
427
- echo "换版本的话,记得同步 compose.env 末尾的 XGENT_IMAGE / XGENT_PROXY_IMAGE,再 dc up -d"
502
+ echo "镜像就位后跑 $0 upgrade --image ${image} --proxy-image ${proxy},再跑 $0 up。"
428
503
  }
429
504
 
430
505
  # --- 其余子命令 ---------------------------------------------------------------
@@ -434,7 +509,7 @@ cmd_env() {
434
509
  echo
435
510
  local k v n
436
511
  for k in COMPOSE_PROJECT_NAME XGENT_IMAGE XGENT_PROXY_IMAGE XGENT_APP_CATALOG NODE_ENV DEV_MOCK_OAUTH \
437
- HTTP_PORT HTTPS_PORT POSTGRES_PORT REDIS_PORT MINIO_PORT MINIO_CONSOLE_PORT PORTAL_BASE_URL \
512
+ HTTP_PORT HTTPS_PORT POSTGRES_PORT REDIS_PORT MINIO_PORT MINIO_CONSOLE_PORT KAFKA_PORT PORTAL_BASE_URL \
438
513
  APP_KEY APP_IMAGE APP_FRONTEND_DIST PREVIEW_MEDIA_CONVERTER_URL; do
439
514
  v="$(_eff "$k")"
440
515
  n="$(_assignments | awk -F'\t' -v k="$k" '$2==k{seen[$3]=1} END{print length(seen)}')"
@@ -511,14 +586,14 @@ cmd_status() {
511
586
  for cid in $(dc ps -q 2>/dev/null || true); do
512
587
  tst="$(docker inspect "$cid" --format '{{json .Config.Healthcheck.Test}}' 2>/dev/null || true)"
513
588
  case "$tst" in
514
- *"curl -fsS http"*|*"wget -q -O /dev/null http://127.0.0.1:80/"*)
589
+ *"curl -fsS http://127.0.0.1:8080/health"*|*"wget -q -O /dev/null http://127.0.0.1:80/"*)
515
590
  nm="$(docker inspect "$cid" --format '{{.Name}}' 2>/dev/null | sed 's#^/##')"
516
591
  stale="$stale ${nm:-$cid}" ;;
517
592
  esac
518
593
  done
519
594
  if [ -n "$stale" ]; then
520
595
  warn "这些容器的 healthcheck 还是旧镜像里那条永远失败的探针,它们的 unhealthy 是假红(判活只看下面的探测):$stale"
521
- _note "新镜像已换成 bun / 不跟随重定向的 curl。$0 pull 换新镜像 + $0 init --force 重铺 compose 之后,unhealthy 就是真红。"
596
+ _note "新镜像已换成 bun / 不跟随重定向的 curl。$0 pull 后跑 $0 upgrade,再跑 $0 up;upgrade 保留配置与数据。"
522
597
  else
523
598
  _note "healthcheck 都是新探针 —— 这里的 unhealthy 就是真红,别当假红放过去(先看 $0 dc logs <服务>)。"
524
599
  fi
@@ -530,19 +605,305 @@ cmd_status() {
530
605
  _env_set() { # _env_set KEY VALUE —— 追加到 compose.env 末尾(后定义者胜),已是同值则跳过
531
606
  local k="$1" v="$2"
532
607
  [ "$(_eff "$k")" = "$v" ] && return 0
533
- printf '%s=%s\n' "$k" "$v" >> "$ENV_FILE"
608
+ printf '%s=%s\n' "$k" "$v" >> "$ENV_FILE" || die "无法写入 compose.env,操作中止。"
534
609
  info "compose.env += ${k}=${v}"
535
610
  }
611
+ _env_append_secret() {
612
+ printf '%s=%s\n' "$1" "$2" >> "$ENV_FILE" || die "无法写入 compose.env,操作中止。"
613
+ info "compose.env += ${1}=***"
614
+ }
615
+ _kafka_cluster_id() {
616
+ local value
617
+ value="$(openssl rand -base64 16 | tr '+/' '-_' | tr -d '=')" || return 1
618
+ [ "${#value}" = 22 ] || return 1
619
+ printf '%s' "$value"
620
+ }
621
+ _kafka_admin_password() {
622
+ local value
623
+ value="$(openssl rand -hex 24)" || return 1
624
+ [ "${#value}" = 48 ] || return 1
625
+ printf '%s' "$value"
626
+ }
627
+ _kafka_defaults() {
628
+ # Only absent keys are filled. An existing cluster ID/password must never rotate.
629
+ local value
630
+ if ! grep -q '^KAFKA_CLUSTER_ID=' "$ENV_FILE"; then
631
+ value="$(_kafka_cluster_id)" || die "无法生成 Kafka 集群 ID,升级中止。"
632
+ _env_set KAFKA_CLUSTER_ID "$value"
633
+ fi
634
+ if ! grep -q '^KAFKA_ADMIN_PASSWORD=' "$ENV_FILE"; then
635
+ value="$(_kafka_admin_password)" || die "无法生成 Kafka 管理密码,升级中止。"
636
+ _env_append_secret KAFKA_ADMIN_PASSWORD "$value"
637
+ fi
638
+ if ! grep -q '^KAFKA_PORT=' "$ENV_FILE"; then _env_set KAFKA_PORT "$(pick_port 9092 19092 29092)"; fi
639
+ chmod 600 "$ENV_FILE" || die "无法保护 compose.env 权限,升级中止。"
640
+ }
641
+ _kafka_assets_current() {
642
+ grep -qE '^ kafka:' "$HOME_DIR/docker-compose.yml" \
643
+ && grep -q '^KAFKA_CLUSTER_ID=' "$ENV_FILE" \
644
+ && grep -q '^KAFKA_ADMIN_PASSWORD=' "$ENV_FILE" \
645
+ && grep -q '^KAFKA_PORT=' "$ENV_FILE"
646
+ }
647
+ _require_kafka_assets() {
648
+ _kafka_assets_current || die "一盒 Kafka 资产或配置是旧版,先跑 $0 upgrade --image <新版一盒镜像>,再跑 $0 up。"
649
+ }
650
+ _kafka_up() {
651
+ local deadline cid state
652
+ if ! dc up -d kafka </dev/null; then
653
+ warn "Kafka 启动失败,门户继续;查看下方日志。"
654
+ dc logs --tail 50 kafka </dev/null || true
655
+ return 0
656
+ fi
657
+ deadline=$((SECONDS+60))
658
+ while [ "$SECONDS" -lt "$deadline" ]; do
659
+ cid="$(dc ps -q kafka </dev/null 2>/dev/null || true)"; state=''
660
+ [ -z "$cid" ] || state="$(docker inspect --format '{{if .State.Health}}{{.State.Health.Status}}{{end}}' "$cid" </dev/null 2>/dev/null || true)"
661
+ if [ "$state" = healthy ]; then info "Kafka: healthy"; return 0; fi
662
+ [ "$SECONDS" -ge "$deadline" ] || sleep 1
663
+ done
664
+ warn "Kafka 60s 内未健康,门户继续;依赖 Kafka 的应用需等服务恢复。"
665
+ dc logs --tail 50 kafka </dev/null || true
666
+ return 0
667
+ }
668
+ _ensure_kafka() { # _ensure_kafka LISTING_KEY ENV_PREFIX
669
+ local key="$1" prefix="$2" username password admin deadline
670
+ [[ "$key" =~ ^[a-z0-9][a-z0-9-]*$ ]] || return 1
671
+ _kafka_assets_current || return 1
672
+ dc up -d kafka </dev/null >/dev/null 2>&1 || return 1
673
+ deadline=$((SECONDS+60))
674
+ until dc exec -T kafka nc -z 127.0.0.1 9092 </dev/null >/dev/null 2>&1; do
675
+ [ "$SECONDS" -lt "$deadline" ] || return 1
676
+ sleep 1
677
+ done
678
+ username="app_${key//-/_}"
679
+ password="$(_eff "${prefix}_KAFKA_PASSWORD")"
680
+ if [ -z "$password" ]; then
681
+ password="$(_kafka_admin_password)" || return 1
682
+ # Persist before contacting the broker: a partial ACL failure must reuse this password.
683
+ _env_append_secret "${prefix}_KAFKA_PASSWORD" "$password"
684
+ fi
685
+ admin="$(_eff KAFKA_ADMIN_PASSWORD)"
686
+ [ -n "$admin" ] || return 1
687
+ case "$admin" in *$'\n'*|*$'\r'*) return 1 ;; esac
688
+ # Generated passwords are hex; preserve existing safe base64/url-safe passwords too.
689
+ [[ "$password" =~ ^[A-Za-z0-9_+/=-]+$ ]] || return 1
690
+ chmod 600 "$ENV_FILE" || return 1
691
+ # Secrets enter through stdin, never command arguments or raw CLI output. The temporary
692
+ # properties live only inside the broker and are removed on success, failure or signal.
693
+ # shellcheck disable=SC2016
694
+ if ! printf '%s\n%s\n' "$admin" "$password" | dc exec -T kafka bash -ec '
695
+ umask 077
696
+ IFS= read -r admin
697
+ IFS= read -r password
698
+ dir=$(mktemp -d /tmp/xgent-kafka-admin.XXXXXX)
699
+ trap '\''rm -rf "$dir"'\'' EXIT
700
+ trap '\''exit 1'\'' HUP INT TERM
701
+ escaped=${admin//\\/\\\\}; escaped=${escaped//\"/\\\"}
702
+ jaas="org.apache.kafka.common.security.plain.PlainLoginModule required username=\"admin\" password=\"$escaped\";"
703
+ printf "security.protocol=SASL_PLAINTEXT\nsasl.mechanism=PLAIN\nsasl.jaas.config=%s\nrequest.timeout.ms=10000\ndefault.api.timeout.ms=15000\n" "${jaas//\\/\\\\}" > "$dir/admin.properties"
704
+ printf "SCRAM-SHA-512=iterations=8192,password=%s\n" "$password" > "$dir/scram.properties"
705
+ /opt/kafka/bin/kafka-configs.sh --bootstrap-server kafka:9092 --command-config "$dir/admin.properties" --alter --add-config-file "$dir/scram.properties" --entity-type users --entity-name "$1"
706
+ acl=(--bootstrap-server kafka:9092 --command-config "$dir/admin.properties" --add --allow-principal "User:$1" --allow-host "*" --resource-pattern-type prefixed)
707
+ /opt/kafka/bin/kafka-acls.sh "${acl[@]}" --topic "$2" --operation Create --operation Delete --operation Describe --operation DescribeConfigs --operation Read --operation Write
708
+ /opt/kafka/bin/kafka-acls.sh "${acl[@]}" --group "$2" --operation Read --operation Describe --operation Delete
709
+ /opt/kafka/bin/kafka-acls.sh "${acl[@]}" --transactional-id "$2" --operation Write --operation Describe
710
+ ' bash "$username" "app.${key}." >/dev/null 2>&1; then return 1; fi
711
+ _env_set "${prefix}_KAFKA_BROKERS" kafka:9092
712
+ _env_set "${prefix}_KAFKA_USERNAME" "$username"
713
+ _env_set "${prefix}_KAFKA_SASL_MECHANISM" SCRAM-SHA-512
714
+ _env_set "${prefix}_KAFKA_TOPIC_PREFIX" "app.${key}."
715
+ info "Kafka 用户 ${username} 与前缀 app.${key}. 就绪"
716
+ }
717
+ _kafka_add_warning() {
718
+ warn "Kafka 供给失败;门户与应用初始化继续。已保存的密码保持不变,检查 Kafka 日志后重试:"
719
+ printf ' XGENT_ONEBOX_HOME=%q bash %q add %q' "$HOME_DIR" "$0" "$1"
720
+ [ -z "${ADD_MANIFEST:-}" ] || printf ' --manifest %q' "$ADD_MANIFEST"
721
+ [ -z "${ADD_FROM:-}" ] || printf ' --from %q' "$ADD_FROM"
722
+ printf '\n'
723
+ _note "手工修复命令见《平台 Kafka 接入指引》的一盒故障恢复;不要把管理员密码填进 App requiredEnv。"
724
+ }
725
+ _portal_services_up() {
726
+ # Kafka has its own non-blocking startup; do not retry it in the hard-fail group.
727
+ local enabled svc services=()
728
+ enabled="$(dc config --services)" || die "无法读取一盒服务清单。"
729
+ while IFS= read -r svc; do
730
+ [ -z "$svc" ] || [ "$svc" = kafka ] || services+=("$svc")
731
+ done <<< "$enabled"
732
+ [ "${#services[@]}" -gt 0 ] || die "一盒服务清单为空。"
733
+ dc up -d "${services[@]}"
734
+ }
536
735
  _svc_running() { [ -n "$(dc ps -q "$1" 2>/dev/null || true)" ]; }
736
+ # v1 的放行表只在 Caddy load 时读取;v2 由唯一发布器生成、验证并应用整代配置。
737
+ # 必须先询问镜像的受管 selector;模式损坏时不能按旧镜像降级,更不能重读兼容模板。
738
+ _reload_proxy() {
739
+ _svc_running reverse-proxy || return 0
740
+ local selected out
741
+ if ! selected="$(dc exec -T reverse-proxy sh -c '
742
+ selector=/usr/local/libexec/xgent-gateway-config
743
+ if [ -e "$selector" ] || [ -L "$selector" ]; then
744
+ [ -f "$selector" ] && [ -x "$selector" ] || exit 1
745
+ exec "$selector"
746
+ fi
747
+ # 旧镜像只有完全没有受管状态时才允许兼容 reload。
748
+ for path in /etc/caddy/sites/gateway-v2.enabled /etc/caddy/sites/current /etc/caddy/gateway-operation.conf; do
749
+ if [ -e "$path" ] || [ -L "$path" ]; then exit 1; fi
750
+ done
751
+ printf "/etc/caddy/Caddyfile\n"
752
+ ' 2>/dev/null)"; then
753
+ die "无法确认反代模式;已停止 reload。请检查受管模式与 current 快照,再按网关维护文档恢复。"
754
+ fi
755
+ case "$selected" in
756
+ /etc/caddy/Caddyfile) ;;
757
+ /*/current/Caddyfile)
758
+ info " 反代为 v2,路由变更由唯一发布器应用;请查看发布状态确认结果"
759
+ return 0 ;;
760
+ *) die "反代模式返回无效;已停止 reload,不会回退到兼容模板。" ;;
761
+ esac
762
+ if out="$(dc exec -T reverse-proxy caddy reload --config /etc/caddy/Caddyfile --adapter caddyfile 2>&1)"; then
763
+ info " 反代已重读 /svc 放行表"
764
+ else
765
+ warn "反代重读失败,/svc 仍是改动前那份:$(printf '%s' "$out" | tail -2 | tr '\n' ' ')"
766
+ fi
767
+ }
537
768
  _ok() { printf ' %s✓%s %s\n' "$c_grn" "$c_off" "$*"; }
538
769
  _bad() { printf ' %s✗%s %s\n' "$c_red" "$c_off" "$1"; shift; [ $# -gt 0 ] && printf ' %s↳ %s%s\n' "$c_dim" "$*" "$c_off"; DOCTOR_BAD=$((DOCTOR_BAD+1)); return 0; }
539
770
  _note() { printf ' %s↳ %s%s\n' "$c_dim" "$*" "$c_off"; }
540
771
 
541
772
  # --- up:按顺序铺一遍(幂等)---------------------------------------------------
773
+ _objectstore_assets_current() {
774
+ grep -qE '^ rustfs:' "$HOME_DIR/docker-compose.yml" \
775
+ && [ -f "$HOME_DIR/scripts/objectstore-cutover.sh" ] \
776
+ && [ -f "$HOME_DIR/scripts/objectstore-manifest.ts" ]
777
+ }
778
+ _require_objectstore_assets() {
779
+ _objectstore_assets_current || die "一盒资产是旧版,先跑 $0 upgrade --image <新版一盒镜像>,再跑 $0 up。"
780
+ }
781
+ _objectstore_image() {
782
+ local image
783
+ image="$(dc config --images rustfs)" || die "无法读取 RustFS 镜像配置;旧对象存储未切换。"
784
+ [ -n "$image" ] || die "Compose 配置里没有 RustFS 镜像;旧对象存储未切换。"
785
+ docker image inspect "$image" >/dev/null 2>&1 && return 0
786
+ dc pull rustfs </dev/null || die "RustFS 镜像尚未就位;拉取失败,旧对象存储未切换。修复镜像拉取后重跑。"
787
+ }
788
+
789
+ # An asset upgrade must not upgrade/downgrade an existing PostgreSQL data directory.
790
+ # Inspect only this project's real mount, then read it through a read-only container.
791
+ _postgres_volume() {
792
+ local project ids cid volume volumes configured
793
+ project="$(_eff COMPOSE_PROJECT_NAME xgent-onebox)"
794
+ ids="$(docker ps -aq --filter "label=com.docker.compose.project=$project" --filter label=com.docker.compose.service=postgres)" \
795
+ || die "无法检查本项目 PostgreSQL 容器;未启动服务。"
796
+ if [ -n "$ids" ]; then
797
+ [ "$(printf '%s\n' "$ids" | wc -l | tr -d ' ')" = 1 ] || die "本项目有多个 PostgreSQL 容器,无法确定权威数据卷;请人工确认,勿删卷。"
798
+ cid="$ids"
799
+ volume="$(docker inspect "$cid" --format '{{range .Mounts}}{{if eq .Type "volume"}}{{if or (eq .Destination "/var/lib/postgresql") (eq .Destination "/var/lib/postgresql/data")}}{{println .Name}}{{end}}{{end}}{{end}}')" \
800
+ || die "无法读取 PostgreSQL 挂载,勿删卷。"
801
+ [ -n "$volume" ] && [ "$(printf '%s\n' "$volume" | wc -l | tr -d ' ')" = 1 ] \
802
+ || die "PostgreSQL 挂载不是唯一命名卷;请人工确认,勿删卷。"
803
+ else
804
+ volume="$(docker volume ls --filter "label=com.docker.compose.project=$project" --filter label=com.docker.compose.volume=pg-data --format '{{.Name}}')" \
805
+ || die "无法查询 PostgreSQL 数据卷;未启动服务。"
806
+ if [ -n "$volume" ]; then
807
+ [ "$(printf '%s\n' "$volume" | wc -l | tr -d ' ')" = 1 ] || die "本项目有多个 pg-data 卷,拒绝自动选择。"
808
+ else
809
+ configured="$(awk '
810
+ /^volumes:/{volumes=1; next}
811
+ volumes && /^ pg-data:/{pg=1; next}
812
+ volumes && /^ [A-Za-z0-9_-]+:/{pg=0}
813
+ pg && /^ name:/{sub(/^ name:[[:space:]]*/, ""); print}
814
+ ' "$HOME_DIR/docker-compose.yml" | sed "s/^[\"']//; s/[\"']$//")"
815
+ volume="${configured:-${project}_pg-data}"
816
+ [[ "$volume" =~ ^[A-Za-z0-9][A-Za-z0-9_.-]*$ ]] || die "pg-data 自定义卷名无法确定;请人工确认,勿删卷。"
817
+ volumes="$(docker volume ls --format '{{.Name}}')" || die "无法查询 Docker 数据卷;未启动服务。"
818
+ printf '%s\n' "$volumes" | grep -qxF "$volume" || return 0
819
+ fi
820
+ fi
821
+ printf '%s' "$volume"
822
+ }
823
+ _pin_postgres() {
824
+ local volume state major layout file next
825
+ if [ $# -gt 0 ]; then volume="$1"
826
+ else volume="$(_postgres_volume)" || die "无法确认 PostgreSQL 数据卷;未启动服务。"; fi
827
+ [ -n "$volume" ] || return 0
828
+ state="$(docker run --rm --network none -u 0 --entrypoint sh -v "$volume:/probe:ro" rustfs/rustfs:1.0.0 -c '
829
+ set -eu
830
+ count=0
831
+ for f in /probe/PG_VERSION /probe/[0-9]*/docker/PG_VERSION; do
832
+ [ -f "$f" ] || continue
833
+ count=$((count+1)); major=$(cat "$f")
834
+ if [ "$f" = /probe/PG_VERSION ]; then layout=legacy
835
+ elif [ "$f" = "/probe/$major/docker/PG_VERSION" ]; then layout=parent
836
+ else echo unknown; exit 1; fi
837
+ printf "%s %s\n" "$major" "$layout"
838
+ done
839
+ if [ "$count" = 0 ]; then
840
+ if [ -z "$(ls -A /probe)" ]; then echo empty; else echo unknown; fi
841
+ fi
842
+ ' </dev/null)" || die "PostgreSQL 只读卷检查失败;未启动服务,勿删卷。"
843
+ [ "$state" = empty ] && return 0
844
+ [ "$(printf '%s\n' "$state" | wc -l | tr -d ' ')" = 1 ] \
845
+ || die "PostgreSQL 卷内有多个版本目录,拒绝自动选择;勿删卷。"
846
+ major="${state%% *}"; layout="${state#* }"
847
+ [[ "$major" =~ ^[1-9][0-9]$ ]] || die "PostgreSQL 卷布局或版本未知;拒绝启动,勿删卷。"
848
+ if [ "$layout" = legacy ] && [ "$major" -lt 18 ]; then
849
+ layout=/var/lib/postgresql/data
850
+ elif [ "$layout" = parent ] && [ "$major" -ge 18 ]; then
851
+ layout=/var/lib/postgresql
852
+ else
853
+ die "PostgreSQL 版本与目录布局不一致;拒绝启动,勿删卷。"
854
+ fi
855
+ file="$HOME_DIR/docker-compose.yml"; next="$(mktemp "$HOME_DIR/.postgres-compose.XXXXXX")"
856
+ if ! awk -v major="$major" -v mount="$layout" -v volume="$volume" '
857
+ /^ postgres:/{svc=1; print; next}
858
+ svc && /^ [A-Za-z0-9_-]+:/{svc=0}
859
+ /^volumes:/{svc=0; volumes=1}
860
+ svc && /^ image:/{print " image: postgres:" major "-alpine"; images++; next}
861
+ svc && /^[[:space:]]*- pg-data:\/var\/lib\/postgresql(\/data)?[[:space:]]*$/{print " - pg-data:" mount; mounts++; next}
862
+ volumes && /^ pg-data:/{print " pg-data:"; print " name: " volume; named=1; names++; next}
863
+ volumes && /^ [A-Za-z0-9_-]+:/{named=0}
864
+ named && /^ name:/{next}
865
+ {print}
866
+ END{if(images!=1 || mounts!=1 || names!=1)exit 1}
867
+ ' "$file" > "$next"; then
868
+ rm -f "$next"; die "PostgreSQL compose 布局不符合预期,未覆盖文件;请人工确认,勿删卷。"
869
+ fi
870
+ # 运行中的 portal-api / controller 按 inode 单文件挂载它;内容没变就不换文件,免得它们读到已删除的旧文件。
871
+ if cmp -s "$next" "$file"; then rm -f "$next"
872
+ else mv "$next" "$file" || { rm -f "$next"; die "无法保存 PostgreSQL 版本保护;未启动服务。"; }; fi
873
+ info "PostgreSQL 存量卷保持 PG${major} 与 ${layout} 挂载;大版本迁移需另行安排。"
874
+ }
875
+
876
+ _objectstore_up() {
877
+ _require_objectstore_assets
878
+ _objectstore_image
879
+ local code deadline
880
+ if "$HOME_DIR/scripts/objectstore-cutover.sh" \
881
+ --project "$(_eff COMPOSE_PROJECT_NAME xgent-onebox)" --env-file "$ENV_FILE" \
882
+ --backup-dir "$HOME_DIR/backup" </dev/null; then
883
+ :
884
+ else
885
+ code=$?
886
+ die "对象存储切换中止(退出 ${code});按上方提示处理,未启动正式 RustFS。"
887
+ fi
888
+ dc up -d rustfs </dev/null || die "RustFS 启动失败;已过提交点,rustfs-data 是权威,勿删。看 $0 dc logs rustfs;回退只执行 $HOME_DIR/backup/rollback-minio.sh。"
889
+ deadline=$((SECONDS+60))
890
+ while [ "$SECONDS" -lt "$deadline" ]; do
891
+ if dc exec -T rustfs curl -fsS --max-time 1 http://127.0.0.1:9000/health </dev/null >/dev/null 2>&1; then return 0; fi
892
+ [ "$SECONDS" -ge "$deadline" ] || sleep 1
893
+ done
894
+ die "RustFS 60s 未就绪;已过提交点,rustfs-data 是权威,勿删。看 $0 dc logs rustfs;回退只执行 $HOME_DIR/backup/rollback-minio.sh。"
895
+ }
896
+
542
897
  cmd_up() {
898
+ _require_objectstore_assets
899
+ _require_kafka_assets
543
900
  [ -n "$APP_KEY" ] || die "compose.env 里还没有 APP_KEY —— 先跑 $0 init --key <你的listingKey>。"
544
- info "① 基础设施(postgres / redis / minio)"
545
- dc up -d postgres redis minio
901
+ info "① 基础设施(postgres / redis / RustFS / Kafka)"
902
+ _objectstore_image
903
+ _pin_postgres
904
+ _objectstore_up
905
+ dc up -d postgres redis
906
+ _kafka_up
546
907
  info " 等 postgres 就绪…"
547
908
  # 首次初始化时 initdb 会先起一个临时实例再重启,单次 pg_isready 会在那个窗口里误判就绪,
548
909
  # 紧接着的 db:migrate 就撞 ECONNREFUSED(实测)。要求连续 3 秒都就绪才算。
@@ -557,8 +918,7 @@ cmd_up() {
557
918
  # 逐租户基线(org 的预置档案字段就是这么来的),表还没建就只能眼看着它失败。
558
919
  local k
559
920
  for k in ${CATALOG//,/ }; do
560
- # qbank/lms 是 QBANK-WORKFLOW-ACTIONS §5.9 的变体成员;基础集不含它们时这段零执行。
561
- case "$k" in files|llm-gateway|git|org|qbank|lms) dc run --rm portal-api bun run "db:$k:migrate" || warn "db:$k:migrate 失败,继续";; esac
921
+ case "$k" in files|llm-gateway|git|org) dc run --rm portal-api bun run "db:$k:migrate" || warn "db:$k:migrate 失败,继续";; esac
562
922
  done
563
923
  info "②b 你自己的库 xgent-${APP_KEY}"
564
924
  _ensure_db "xgent-${APP_KEY}"
@@ -580,7 +940,8 @@ cmd_up() {
580
940
  info "④b 目录里的清单型 App:${mk}"
581
941
  ADD_QUIET=1 cmd_add "$mk" || warn "add ${mk} 失败 —— 看上面的报错;修完重跑 $0 up(幂等)"
582
942
  done
583
- info "⑤ 起门户三件套 + 基础服务" ; dc up -d
943
+ info "⑤ 起门户三件套 + 基础服务" ; _portal_services_up
944
+ _reload_proxy
584
945
  _has_catalog observability && _portal_logs_up
585
946
  echo; info "跑一次体检:"; cmd_doctor
586
947
  }
@@ -597,7 +958,7 @@ _portal_logs_up() {
597
958
  # 容器的 workdir 是 /app(monorepo 根),脚本在 apps/api 下;不走 package script 是因为它带 --env-file=../../.env,镜像里没有那份文件。
598
959
  sec="$(dc run --rm --no-deps -T -w /app/apps/api portal-api bun run scripts/portal-logs-key.ts 2>"$err")" || rc=$?
599
960
  if [ "$rc" -eq 0 ] && [ -n "$sec" ]; then
600
- _env_set OBS_ACCESS_KEY "$sec"
961
+ _env_append_secret OBS_ACCESS_KEY "$sec"
601
962
  else
602
963
  warn "采集密钥没签成(rc=${rc}):$(grep -v xsak_ "$err" | tail -3 | tr '\n' ' ')"; rm -f "$err"; return 0
603
964
  fi
@@ -607,13 +968,18 @@ _portal_logs_up() {
607
968
  _ok "portal-logs 已起;portal-api 的 stdout/stderr 经 fluentd 驱动进 app_portal_console(观测:$0 dc logs portal-logs)"
608
969
  }
609
970
 
610
- # 在一盒 minio 上建桶(幂等)。minio 镜像自带 mc;凭证就是 compose.env 里的 MINIO_ROOT_USER/PASSWORD。
971
+ # 使用 RustFS 自带 curl 与容器内凭据建桶;不依赖已停止分发的 mc。
611
972
  _ensure_bucket() { # _ensure_bucket <bucket>
612
- local u p; u="$(_eff MINIO_ROOT_USER minioadmin)"; p="$(_eff MINIO_ROOT_PASSWORD minioadmin)"
613
- dc up -d minio >/dev/null 2>&1 || true
614
- local i=0; until dc exec -T minio mc ready local >/dev/null 2>&1; do i=$((i+1)); [ "$i" -gt 30 ] && { warn "minio 30s 没就绪,桶 $1 没建"; return 0; }; sleep 1; done
615
- dc exec -T minio sh -c "mc alias set local http://127.0.0.1:9000 '$u' '$p' >/dev/null 2>&1 && mc mb --ignore-existing local/$1" >/dev/null 2>&1 \
616
- && info "桶 $1 就绪" || warn "桶 $1 没建成($0 dc exec minio mc mb local/$1 手工补)"
973
+ local bucket="$1"
974
+ [[ "$bucket" =~ ^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$ ]] || die "对象存储桶名不合法。"
975
+ _objectstore_up
976
+ # Credentials and bucket positional argument expand in the container shell.
977
+ # shellcheck disable=SC2016
978
+ if dc exec -T rustfs sh -c 'exec curl -fsS --max-time 10 --retry 10 --retry-delay 1 --retry-all-errors \
979
+ --aws-sigv4 "aws:amz:us-east-1:s3" --user "$RUSTFS_ACCESS_KEY:$RUSTFS_SECRET_KEY" \
980
+ -X PUT "http://127.0.0.1:9000/$1"' sh "$bucket" </dev/null >/dev/null; then
981
+ info "桶 ${bucket} 就绪"
982
+ else die "桶 ${bucket} 没建成;检查 $0 dc logs rustfs,修复后重跑原命令。"; fi
617
983
  }
618
984
  _ensure_db() { # _ensure_db <dbname>
619
985
  if dc exec -T postgres psql -U postgres -lqt 2>/dev/null | cut -d'|' -f1 | grep -qw "$1"; then
@@ -679,6 +1045,9 @@ _manifest_json() { # _manifest_json KEY → 把 manifest JSON 打到 stdout
679
1045
  }
680
1046
 
681
1047
  cmd_add() {
1048
+ _require_objectstore_assets
1049
+ _objectstore_image
1050
+ _pin_postgres
682
1051
  local key="" want_image=""
683
1052
  ADD_MANIFEST=""; ADD_FROM=""
684
1053
  while [ $# -gt 0 ]; do
@@ -702,6 +1071,8 @@ cmd_add() {
702
1071
 
703
1072
  # 用 portal-api 里的 bun 解析(不对宿主机的 python/jq 做任何假设)
704
1073
  local fields
1074
+ # JavaScript template expressions must reach Bun without shell expansion.
1075
+ # shellcheck disable=SC2016
705
1076
  fields="$(printf '%s' "$mj" | dc run --rm --no-deps -T portal-api bun -e '
706
1077
  let raw=""; for await (const c of Bun.stdin.stream()) raw += new TextDecoder().decode(c);
707
1078
  const m = JSON.parse(raw); const d = m.deployDescriptor ?? {};
@@ -713,20 +1084,43 @@ cmd_add() {
713
1084
  console.log(`M_HEALTH=${q(d.healthPath ?? "/health")}`);
714
1085
  console.log(`M_SA=${q((m.serviceAccount ?? {}).clientId)}`);
715
1086
  console.log(`M_ENV=${(m.requiredEnv ?? []).map((e) => (typeof e === "string" ? e : e.key)).join(" ")}`);
1087
+ console.log(`M_KAFKA=${(m.requiredServices ?? []).some((s) => s.kind === "kafka") ? "1" : "0"}`);
716
1088
  // 非空 ⇒ 它是跨应用交换的【发起方】,需要一把 App Secret(下面与 SA 密钥同源生成注入)。
717
1089
  console.log(`M_XTARGETS=${(m.exchangeTargets ?? []).join(" ")}`);
718
1090
  console.log(`M_MIGRATE=${(d.migrateArgs ?? []).join(" ")}`);
1091
+ console.log(`M_DEPS=${(m.dependencies ?? []).join(" ")}`);
719
1092
  ' 2>/dev/null)" || die "解析清单失败 —— 它可能不是一份合法的 app.manifest.json。"
720
- local M_KEY="" M_TYPE="" M_IMAGE="" M_PORT="" M_HEALTH="" M_SA="" M_ENV="" M_XTARGETS="" M_MIGRATE=""
1093
+ local M_KEY="" M_TYPE="" M_IMAGE="" M_PORT="" M_HEALTH="" M_SA="" M_ENV="" M_KAFKA="" M_XTARGETS="" M_MIGRATE="" M_DEPS=""
721
1094
  eval "$(printf '%s' "$fields" | sed 's/^\([A-Z_]*\)=\(.*\)$/\1="\2"/')"
722
1095
  [ "$M_KEY" = "$key" ] || die "清单里的 listingKey 是「${M_KEY}」,与你要加的「${key}」对不上。"
723
1096
  info " ${M_KEY} type=${M_TYPE} port=${M_PORT} sa=${M_SA}"
724
1097
 
1098
+ # 依赖预检:register-app 要求 dependencies 里每个 key 在【这台门户】已有清单,否则
1099
+ # DEPENDENCY_UNAVAILABLE —— 而且只报第一个、带一屏堆栈。拉镜像之前一次点名全部缺的。
1100
+ # 只卡「有没有清单」:装不装由「应用管理 → 应用市场」安装时按依赖一并装上,不归这里。
1101
+ if [ -n "$M_DEPS" ]; then
1102
+ dc up -d postgres >/dev/null 2>&1 || true
1103
+ local rows dep dmiss=""
1104
+ if rows="$(dc exec -T postgres psql -U postgres -d "$(_eff POSTGRES_DB xgent-portal)" -tAc 'select listing_key from marketplace_listings' 2>/dev/null)"; then
1105
+ rows=" $(printf '%s' "$rows" | tr -d '\r' | tr '\n' ' ') "
1106
+ for dep in $M_DEPS; do
1107
+ _is_portal_hosted "$dep" && continue
1108
+ case "$rows" in *" $dep "*) ;; *) dmiss="${dmiss:+$dmiss }$dep" ;; esac
1109
+ done
1110
+ else
1111
+ warn "读不到本地门户的清单表(postgres 还没就绪或还没 migrate),跳过依赖预检,交给 register-app 判。"
1112
+ fi
1113
+ [ -z "$dmiss" ] || die "「${key}」依赖 ${dmiss},这台一盒里还没有它们的清单 —— 直接注册会被拒(DEPENDENCY_UNAVAILABLE)。
1114
+ 先逐个 ${0} add <依赖>(配了 MANIFEST_STORE 就从目录取清单;镜像在 <REGISTRY>/<ONEBOX_PROJECT>/ 下,清单没写 deployDescriptor.image 时加 --image <全引用>),再重跑 ${0} add ${key}。
1115
+ 之后在「应用管理 → 应用市场」里安装 ${key},依赖会被一并装上、自动授予。"
1116
+ fi
1117
+
725
1118
  # ② 镜像:清单里的相对名按 <REGISTRY>/<ONEBOX_PROJECT>/ 补全(版本由清单钉住,可复现)
726
1119
  local ivar ref; ivar="$(printf '%s' "$key" | tr 'a-z-' 'A-Z_')_IMAGE"
727
1120
  ref="${want_image:-$(_eff "$ivar")}"
728
1121
  if [ -z "$ref" ]; then
729
- [ -n "$M_IMAGE" ] || die "清单里没有 deployDescriptor.image,也没给 --image。"
1122
+ [ -n "$M_IMAGE" ] || die "清单里没有 deployDescriptor.image,也没给 --image。
1123
+ 陪调用的平台侧 App 镜像在 ${REGISTRY:-<REGISTRY>}/${ONEBOX_PROJECT:-${PROJECT:-<ONEBOX_PROJECT>}}/${key}:<tag> 下 —— 用 --image 给全引用(tag 找门户团队确认),并请该 App 在清单里补上 deployDescriptor.image。"
730
1124
  case "$M_IMAGE" in
731
1125
  */*) ref="$M_IMAGE" ;; # 已经带项目/域名,原样用
732
1126
  *) load_registry_config || true
@@ -738,20 +1132,32 @@ cmd_add() {
738
1132
  if docker image inspect "$ref" >/dev/null 2>&1; then info " 本地已有,跳过拉取"
739
1133
  else
740
1134
  require_puller; registry_login
741
- do_pull "$ref" "配合调试用的 App 都发在一盒同一个项目(ONEBOX_PROJECT=${ONEBOX_PROJECT:-未配})下;确实不在就用 --image 给全引用。"
1135
+ # 只发了 amd64 的镜像(buildx 默认带 attestation,推上去是个 index)在 Apple Silicon 上裸 pull
1136
+ # 报 no matching manifest。本机没指定平台、裸 pull 又失败时,看它有没有 amd64 那一份:有就按
1137
+ # amd64 拉(走仿真),并把 <PREFIX>_PLATFORM 记进 compose.env —— 生成片段的 platform: 读它。
1138
+ # 其它失败原因(项目 / tag 不对、没权限)由 do_pull 原样报。
1139
+ local pvar plat; pvar="${ivar%_IMAGE}_PLATFORM"; plat="$(_eff "$pvar" "$(_eff APP_PLATFORM)")"
1140
+ [ -n "$plat" ] || info "拉 ${ref} …"
1141
+ if [ -n "$plat" ] || ! docker pull "$ref" >/dev/null 2>&1; then
1142
+ if [ -z "$plat" ] && docker manifest inspect "$ref" 2>/dev/null | grep -Eq '"architecture": *"amd64"'; then
1143
+ plat="linux/amd64"; warn "${ref} 没有本机架构的版本,改按 ${plat} 拉(仿真运行,冷启动慢)"
1144
+ _env_set "$pvar" "$plat"
1145
+ fi
1146
+ do_pull "$ref" "配合调试用的 App 都发在一盒同一个项目(ONEBOX_PROJECT=${ONEBOX_PROJECT:-未配})下;确实不在就用 --image 给全引用。" "$plat"
1147
+ fi
742
1148
  fi
743
1149
  _env_set "$ivar" "$ref"
744
1150
 
745
1151
  # ③ 密钥:一盒现生成,两侧同源(清单里有没有明文都不影响)
746
1152
  local svar sec; svar="$(printf '%s' "$key" | tr 'a-z-' 'A-Z_')_SA_SECRET"
747
- sec="$(_eff "$svar")"; [ -n "$sec" ] || { sec="$(rand_hex | cut -c1-32)"; _env_set "$svar" "$sec"; }
1153
+ sec="$(_eff "$svar")"; [ -n "$sec" ] || { sec="$(rand_hex | cut -c1-32)"; _env_append_secret "$svar" "$sec"; }
748
1154
  # 声明了 exchangeTargets 的 App 是跨应用交换的【发起方】,它在 /oauth/token 上用
749
1155
  # `sk_<key>` + App Secret 换对方的令牌。目录里的清单按红线剥掉了 exchangeInitiatorSecret,
750
1156
  # 而 register-app 的 dev 模式只在【清单里有这个字段】时才 wireInitiatorSecret ——
751
1157
  # 不补这一把,该 App 的跨应用交换会稳定 401,且症状出现在「发起方」而不是这里。
752
1158
  local avar asec=""; avar="$(printf '%s' "$key" | tr 'a-z-' 'A-Z_')_APP_SECRET"
753
1159
  if [ -n "$M_XTARGETS" ]; then
754
- asec="$(_eff "$avar")"; [ -n "$asec" ] || { asec="$(rand_hex | cut -c1-32)"; _env_set "$avar" "$asec"; }
1160
+ asec="$(_eff "$avar")"; [ -n "$asec" ] || { asec="$(rand_hex | cut -c1-32)"; _env_append_secret "$avar" "$asec"; }
755
1161
  fi
756
1162
 
757
1163
  info "④ 注册清单(非破坏性、幂等)"
@@ -774,6 +1180,7 @@ cmd_add() {
774
1180
  dc run --rm --no-deps -v "$HOME_DIR:/devkit:ro" portal-api bun run register-app "/devkit/.add-$key.manifest.json" \
775
1181
  || { rm -f "$HOME_DIR/.add-$key.manifest.json"; die "注册失败 —— 看上面的报错。"; }
776
1182
  rm -f "$HOME_DIR/.add-$key.manifest.json"
1183
+ _reload_proxy
777
1184
 
778
1185
  info "⑤ 建库 xgent-${key}"
779
1186
  dc up -d postgres >/dev/null 2>&1 || true
@@ -782,6 +1189,10 @@ cmd_add() {
782
1189
  # ⑥ 从 manifest 生成 compose 片段
783
1190
  local gen="$HOME_DIR/generated"; mkdir -p "$gen"
784
1191
  local out="$gen/${key}.yml" PREFIX; PREFIX="$(printf '%s' "$key" | tr 'a-z-' 'A-Z_')"
1192
+ case " $M_ENV " in *" ${PREFIX}_KAFKA_USERNAME "*) M_KAFKA=1 ;; esac
1193
+ if [ "$M_KAFKA" = 1 ]; then
1194
+ if ! _ensure_kafka "$key" "$PREFIX"; then _kafka_add_warning "$key"; fi
1195
+ fi
785
1196
  {
786
1197
  echo "# 由 onebox.sh add ${key} 从 manifest 生成 —— 不要手改,重跑 add 会覆盖。"
787
1198
  echo "services:"
@@ -803,20 +1214,42 @@ cmd_add() {
803
1214
  # 发起方才有:门户库里那把(register-app 从清单读)与容器里这把必须同源,否则
804
1215
  # 跨应用交换在【发起方】上 401,而错看起来像是被调方的问题。
805
1216
  [ -n "$M_XTARGETS" ] && echo " ${PREFIX}_APP_SECRET: \${${avar}}"
1217
+ # 库连接串:<PREFIX>_DATABASE_URL 是生产的约定名(批准时按它建库并注入,发版 preflight 也要求它);
1218
+ # 后两个是旧名,留给还没改名的镜像。三个都指向同一个库。
1219
+ echo " ${PREFIX}_DATABASE_URL: postgres://postgres:postgres@postgres:5432/xgent-${key}"
806
1220
  echo " ${PREFIX}_PG_DSN: postgres://postgres:postgres@postgres:5432/xgent-${key}"
807
1221
  echo " DATABASE_URL: postgres://postgres:postgres@postgres:5432/xgent-${key}"
808
1222
  echo " expose: [\"\${${PREFIX}_PORT:-${M_PORT}}\"]"
809
1223
  echo " networks: { default: { aliases: [${key}-server] } }"
810
1224
  } > "$out"
811
- info "⑥ 生成 ${out#$HOME_DIR/}"
812
- [ -n "$M_ENV" ] && _note "清单声明了 requiredEnv:${M_ENV} —— 值归平台,按需补进 compose.env 末尾。"
1225
+ info "⑥ 生成 ${out#"$HOME_DIR"/}"
1226
+ # requiredEnv 里【既不在上面生成的片段、也不在 compose.env】的键 —— 一盒版的 REQUIRED_ENV_MISSING
1227
+ # (生产还会把平台代为供给的键算作已提供,一盒只有这两处来源)。在这里点名,而不是等容器缺变量退出。
1228
+ if [ -n "$M_ENV" ]; then
1229
+ local gen_keys="PORT PORTAL_INTROSPECT_URL ${PREFIX}_SA_CLIENT_ID ${PREFIX}_SA_CLIENT_SECRET ${PREFIX}_DATABASE_URL ${PREFIX}_PG_DSN DATABASE_URL"
1230
+ [ -n "$M_XTARGETS" ] && gen_keys="$gen_keys ${PREFIX}_APP_SECRET"
1231
+ local ek missing=""
1232
+ for ek in $M_ENV; do
1233
+ case " $gen_keys " in *" $ek "*) continue ;; esac
1234
+ [ -n "$(_eff "$ek")" ] && continue
1235
+ missing="${missing:+$missing }$ek"
1236
+ done
1237
+ if [ -n "$missing" ]; then
1238
+ warn "requiredEnv 里这些键既不在生成的片段里、也不在 compose.env 里:${missing}"
1239
+ _note "值归平台(生产由审批屏填),这里补进 compose.env 末尾,再重跑 ${0} add ${key}。"
1240
+ else
1241
+ _note "requiredEnv 的键都已到位(生成的片段 + compose.env)。"
1242
+ fi
1243
+ fi
813
1244
 
814
1245
  # 例外:manifest 描述不了的自带 infra(如 knowledge 的 Chroma)
815
1246
  local extra_args=() extra="$SKILL_DIR/services/${key}.extra.yml"
816
1247
  [ -f "$extra" ] && { extra_args=(-f "$extra"); info " 叠加自带依赖 services/${key}.extra.yml"; }
817
1248
 
818
- # 对象存储桶:清单 requiredEnv 里带 *_S3_BUCKET_NAME / ZO_S3_BUCKET_NAME 的,按 compose.env 里的值在一盒 minio 上建桶
1249
+ # 对象存储桶:清单 requiredEnv 里带 *_S3_BUCKET_NAME / ZO_S3_BUCKET_NAME 的,按 compose.env 在 RustFS 建桶
819
1250
  local bvar bname
1251
+ # M_ENV is a validated whitespace-delimited list of environment key names.
1252
+ # shellcheck disable=SC2086
820
1253
  for bvar in $(printf '%s\n' $M_ENV | grep -E '_S3_BUCKET(_NAME)?$' || true); do
821
1254
  bname="$(_eff "$bvar")"; [ -n "$bname" ] && _ensure_bucket "$bname"
822
1255
  done
@@ -824,7 +1257,8 @@ cmd_add() {
824
1257
  # 清单声明了 deployDescriptor.migrateArgs(生产由 deploy-controller 在换容器前跑):起容器前先跑一次
825
1258
  if [ -n "$M_MIGRATE" ]; then
826
1259
  info "⑥b 迁移:${key}-server ${M_MIGRATE}"
827
- dc up -d postgres minio >/dev/null 2>&1 || true
1260
+ _objectstore_up
1261
+ dc up -d postgres >/dev/null
828
1262
  # shellcheck disable=SC2086
829
1263
  XGENT_ONEBOX_HOME="$HOME_DIR" dc -f "$out" ${extra_args[@]+"${extra_args[@]}"} run --rm --no-deps "${key}-server" $M_MIGRATE \
830
1264
  || warn "${key}-server ${M_MIGRATE} 失败 —— 看上面的报错(多半是 env 值没到位)"
@@ -862,6 +1296,24 @@ cmd_doctor() {
862
1296
  echo "一盒体检(${BASE_URL})"
863
1297
  echo
864
1298
 
1299
+ echo "对象存储"
1300
+ if ! _objectstore_assets_current; then
1301
+ _bad "对象存储部署资产是旧版" "$0 upgrade --image <新版一盒镜像> && $0 up"
1302
+ elif dc exec -T rustfs curl -fsS --max-time 5 http://127.0.0.1:9000/health </dev/null >/dev/null 2>&1; then
1303
+ _ok "RustFS /health 正常"
1304
+ else
1305
+ _bad "RustFS 未就绪" "$0 up;失败时保留 rustfs-data,查看 $0 dc logs rustfs。"
1306
+ fi
1307
+
1308
+ echo "Kafka"
1309
+ if ! _kafka_assets_current; then
1310
+ _bad "Kafka 部署资产或配置是旧版" "$0 upgrade --image <新版一盒镜像> && $0 up"
1311
+ elif dc exec -T kafka nc -z 127.0.0.1 9092 </dev/null >/dev/null 2>&1; then
1312
+ _ok "Kafka INTERNAL 监听正常(SASL 认证由服务探测验证)"
1313
+ else
1314
+ _bad "Kafka 未就绪;门户与现有应用可继续运行" "$0 dc logs --tail 50 kafka;修复后重跑 $0 up。"
1315
+ fi
1316
+
865
1317
  echo "① 镜像版本"
866
1318
  local iv; iv="$(_eff XGENT_IMAGE)"
867
1319
  if docker image inspect "$iv" >/dev/null 2>&1; then
@@ -930,13 +1382,14 @@ cmd_doctor() {
930
1382
  local keys="$CATALOG"; [ -n "$APP_KEY" ] && keys="$CATALOG,$APP_KEY"
931
1383
  local code
932
1384
  code="$(curl -s -m 8 -o /dev/null -w '%{http_code}' "$BASE_URL/health" || true)"
933
- [ "$code" = "200" ] && _ok "门户 /health 200" || _bad "门户 /health HTTP ${code:-000}" "000=反代没起或端口不对($0 dc ps);其它看 $0 dc logs portal-api"
1385
+ if [ "$code" = "200" ]; then _ok "门户 /health 200"
1386
+ else _bad "门户 /health HTTP ${code:-000}" "000=反代没起或端口不对($0 dc ps);其它看 $0 dc logs portal-api"; fi
934
1387
  for k in ${keys//,/ }; do
935
1388
  _is_portal_hosted "$k" && continue
936
1389
  code="$(curl -s -m 8 -o /dev/null -w '%{http_code}' "$BASE_URL/svc/$k/health" || true)"
937
1390
  case "$code" in
938
1391
  200) _ok "/svc/$k 200";;
939
- 404) _bad "/svc/$k 404" "放行没写成或反代在写之前就起了:$0 dc exec reverse-proxy caddy reload";;
1392
+ 404) _bad "/svc/$k 404" "放行尚未应用:检查发布状态及 $0 dc logs portal-api,勿手工 reload 兼容模板";;
940
1393
  502) _bad "/svc/$k 502" "后端不在/没听 8080/别名没命中:$0 dc logs ${k}-server";;
941
1394
  *) _bad "/svc/$k HTTP ${code:-000}" "$0 dc ps";;
942
1395
  esac
@@ -951,6 +1404,7 @@ cmd_doctor() {
951
1404
 
952
1405
  case "${1-status}" in
953
1406
  init) shift; cmd_init "$@" ;;
1407
+ upgrade) require_home; load_env; shift; cmd_upgrade "$@" ;;
954
1408
  pull) shift; cmd_pull "$@" ;;
955
1409
  env) require_home; load_env; cmd_env ;;
956
1410
  smoke) require_home; load_env; cmd_smoke ;;
@@ -962,5 +1416,5 @@ case "${1-status}" in
962
1416
  dc) require_home; load_env; shift; dc "$@" ;;
963
1417
  # 打印开头那段注释直到第一条非注释行 —— 别写死行号,加一条子命令就会截断(踩过)。
964
1418
  -h|--help|help) awk 'NR>1 && /^#/ {sub(/^# ?/,""); print; next} NR>1 {exit}' "${BASH_SOURCE[0]}" ;;
965
- *) die "未知子命令 '$1'。用 init | up | doctor | add <key> | pull | env | status | smoke | chain | dc <args...>" ;;
1419
+ *) die "未知子命令 '$1'。用 init | upgrade | up | doctor | add <key> | pull | env | status | smoke | chain | dc <args...>" ;;
966
1420
  esac