@hybridlabor-api/aos 4.8.0 โ†’ 4.10.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 (186) hide show
  1. package/.agents/{agents.md โ†’ AGENTS.md} +3 -1
  2. package/.agents/nodes.json +3 -1
  3. package/.agents/vendor-manifest.json +23 -1
  4. package/.claude/agents/godmode-media-eventtech.md +1 -1
  5. package/.claude/hooks/conventional-commits.mjs +125 -0
  6. package/.claude/hooks/env-file-protection.mjs +105 -0
  7. package/.claude/hooks/go-gate.mjs +101 -81
  8. package/.claude/hooks/memb-inject.mjs +29 -1
  9. package/.claude/settings.json +13 -0
  10. package/.claude/workflows/startcycle-dispatch.mjs +23 -1
  11. package/.opencode/agents/godmode-media-eventtech.md +1 -1
  12. package/.opencode/plugins/bdb-aos.js +31 -4
  13. package/CLAUDE.md +0 -571
  14. package/README.de.md +1 -1
  15. package/README.md +1 -1
  16. package/README.pt.md +1 -1
  17. package/THIRD_PARTY_NOTICES.md +126 -0
  18. package/bin/aos-doctor.mjs +1 -1
  19. package/docs/skills_table.md +1 -1
  20. package/installer.js +187 -55
  21. package/package.json +7 -3
  22. package/packages/aos-cli/README.md +80 -0
  23. package/packages/aos-cli/bin/aos-cli.mjs +134 -0
  24. package/packages/aos-cli/core-skills.json +12 -0
  25. package/packages/aos-cli/extensions/aos.ts +321 -0
  26. package/packages/aos-cli/package-lock.json +1923 -0
  27. package/packages/aos-cli/package.json +29 -0
  28. package/packages/aos-cli/scripts/check-theme.mjs +63 -0
  29. package/packages/aos-cli/themes/aos.json +97 -0
  30. package/scripts/build-plugin-manifest.mjs +131 -0
  31. package/scripts/validate-skills.mjs +81 -6
  32. package/skills/basic/ao-orchestrator/SKILL.md +116 -0
  33. package/skills/basic/bdb-eventagency-skill/SKILL.md +252 -0
  34. package/skills/basic/bdb-shipping-skill/SKILL.md +161 -0
  35. package/skills/basic/godmode-eventtech/SKILL.md +4 -1
  36. package/skills/global_config/agenttrail/SKILL.md +6 -1
  37. package/skills/global_config/aos-project-init/SKILL.md +2 -0
  38. package/skills/global_config/aos-project-init/assets/AGENTS.template.md +1 -1
  39. package/skills/global_config/aos-project-init/scripts/aos-project-doctor.mjs +1 -1
  40. package/skills/global_config/aos-setup/SKILL.md +1 -1
  41. package/skills/global_config/aos-setup/scripts/aos-doctor.mjs +1 -1
  42. package/skills/global_config/ask-tim/SKILL.md +7 -7
  43. package/skills/global_config/bash-script-generator/SKILL.md +201 -0
  44. package/skills/global_config/bash-script-generator/assets/templates/standard-template.sh +96 -0
  45. package/skills/global_config/bash-script-generator/docs/bash-scripting-guide.md +729 -0
  46. package/skills/global_config/bash-script-generator/docs/generation-best-practices.md +193 -0
  47. package/skills/global_config/bash-script-generator/docs/script-patterns.md +566 -0
  48. package/skills/global_config/bash-script-generator/docs/text-processing-guide.md +437 -0
  49. package/skills/global_config/bash-script-generator/examples/log-analyzer.sh +92 -0
  50. package/skills/global_config/bash-script-generator/scripts/generate_script_template.sh +123 -0
  51. package/skills/global_config/bash-script-generator/scripts/run_ci_checks.sh +172 -0
  52. package/skills/global_config/bash-script-generator/scripts/test_generator.sh +413 -0
  53. package/skills/global_config/bash-script-validator/SKILL.md +249 -0
  54. package/skills/global_config/bash-script-validator/docs/awk-reference.md +449 -0
  55. package/skills/global_config/bash-script-validator/docs/bash-reference.md +468 -0
  56. package/skills/global_config/bash-script-validator/docs/common-mistakes.md +623 -0
  57. package/skills/global_config/bash-script-validator/docs/grep-reference.md +395 -0
  58. package/skills/global_config/bash-script-validator/docs/regex-reference.md +391 -0
  59. package/skills/global_config/bash-script-validator/docs/sed-reference.md +454 -0
  60. package/skills/global_config/bash-script-validator/docs/shell-reference.md +463 -0
  61. package/skills/global_config/bash-script-validator/docs/shellcheck-reference.md +399 -0
  62. package/skills/global_config/bash-script-validator/examples/bad-bash.sh +55 -0
  63. package/skills/global_config/bash-script-validator/examples/bad-shell.sh +54 -0
  64. package/skills/global_config/bash-script-validator/examples/good-bash.sh +71 -0
  65. package/skills/global_config/bash-script-validator/examples/good-shell.sh +69 -0
  66. package/skills/global_config/bash-script-validator/scripts/run_ci_checks.sh +23 -0
  67. package/skills/global_config/bash-script-validator/scripts/shellcheck_wrapper.sh +174 -0
  68. package/skills/global_config/bash-script-validator/scripts/test_validate.sh +446 -0
  69. package/skills/global_config/bash-script-validator/scripts/validate.sh +512 -0
  70. package/skills/global_config/ci-pipeline/SKILL.md +135 -0
  71. package/skills/global_config/deja-memory/SKILL.md +3 -1
  72. package/skills/global_config/dispatching-parallel-agents/SKILL.md +170 -0
  73. package/skills/global_config/dockerfile-generator/SKILL.md +1038 -0
  74. package/skills/global_config/dockerfile-generator/examples/example.dockerignore +95 -0
  75. package/skills/global_config/dockerfile-generator/examples/golang-distroless.Dockerfile +34 -0
  76. package/skills/global_config/dockerfile-generator/examples/java-springboot.Dockerfile +45 -0
  77. package/skills/global_config/dockerfile-generator/examples/nextjs-production.Dockerfile +49 -0
  78. package/skills/global_config/dockerfile-generator/examples/nodejs-multistage.Dockerfile +55 -0
  79. package/skills/global_config/dockerfile-generator/examples/python-fastapi.Dockerfile +48 -0
  80. package/skills/global_config/dockerfile-generator/references/language_specific_guides.md +510 -0
  81. package/skills/global_config/dockerfile-generator/references/multistage_builds.md +570 -0
  82. package/skills/global_config/dockerfile-generator/references/optimization_patterns.md +492 -0
  83. package/skills/global_config/dockerfile-generator/references/security_best_practices.md +375 -0
  84. package/skills/global_config/dockerfile-generator/scripts/generate_dockerignore.sh +199 -0
  85. package/skills/global_config/dockerfile-generator/scripts/generate_golang.sh +172 -0
  86. package/skills/global_config/dockerfile-generator/scripts/generate_java.sh +185 -0
  87. package/skills/global_config/dockerfile-generator/scripts/generate_nodejs.sh +279 -0
  88. package/skills/global_config/dockerfile-generator/scripts/generate_python.sh +218 -0
  89. package/skills/global_config/dockerfile-generator/scripts/test_generator.sh +210 -0
  90. package/skills/global_config/dockerfile-validator/SKILL.md +300 -0
  91. package/skills/global_config/dockerfile-validator/examples/.dockerignore.example +34 -0
  92. package/skills/global_config/dockerfile-validator/examples/bad-example.Dockerfile +37 -0
  93. package/skills/global_config/dockerfile-validator/examples/golang-distroless.Dockerfile +50 -0
  94. package/skills/global_config/dockerfile-validator/examples/good-example.Dockerfile +52 -0
  95. package/skills/global_config/dockerfile-validator/examples/python-optimized.Dockerfile +53 -0
  96. package/skills/global_config/dockerfile-validator/examples/security-issues.Dockerfile +42 -0
  97. package/skills/global_config/dockerfile-validator/references/docker_best_practices.md +348 -0
  98. package/skills/global_config/dockerfile-validator/references/optimization_guide.md +473 -0
  99. package/skills/global_config/dockerfile-validator/references/security_checklist.md +208 -0
  100. package/skills/global_config/dockerfile-validator/scripts/dockerfile-validate.sh +699 -0
  101. package/skills/global_config/dockerfile-validator/scripts/test_validate.sh +35 -0
  102. package/skills/global_config/dockerfile-validator/tests/fixtures/copy-before-yarn-lock-read.Dockerfile +6 -0
  103. package/skills/global_config/dockerfile-validator/tests/fixtures/copy-before-yarn.Dockerfile +6 -0
  104. package/skills/global_config/dockerfile-validator/tests/fixtures/from-platform-nonroot.Dockerfile +7 -0
  105. package/skills/global_config/dockerfile-validator/tests/test_regression.sh +164 -0
  106. package/skills/global_config/finishing-a-development-branch/SKILL.md +228 -0
  107. package/skills/global_config/github-actions-generator/SKILL.md +353 -0
  108. package/skills/global_config/github-actions-generator/assets/templates/action/composite/action.yml +82 -0
  109. package/skills/global_config/github-actions-generator/assets/templates/action/docker/Dockerfile +25 -0
  110. package/skills/global_config/github-actions-generator/assets/templates/action/docker/action.yml +42 -0
  111. package/skills/global_config/github-actions-generator/assets/templates/action/docker/entrypoint.sh +27 -0
  112. package/skills/global_config/github-actions-generator/assets/templates/action/javascript/action.yml +33 -0
  113. package/skills/global_config/github-actions-generator/assets/templates/action/javascript/index.js +50 -0
  114. package/skills/global_config/github-actions-generator/assets/templates/action/javascript/package.json +27 -0
  115. package/skills/global_config/github-actions-generator/assets/templates/workflow/basic_workflow.yml +242 -0
  116. package/skills/global_config/github-actions-generator/assets/templates/workflow/reusable_workflow.yml +106 -0
  117. package/skills/global_config/github-actions-generator/examples/README.md +147 -0
  118. package/skills/global_config/github-actions-generator/examples/actions/setup-node-cached/action.yml +93 -0
  119. package/skills/global_config/github-actions-generator/examples/caching/docker-buildkit.yml +256 -0
  120. package/skills/global_config/github-actions-generator/examples/security/dependency-review.yml +62 -0
  121. package/skills/global_config/github-actions-generator/examples/security/sbom-attestation.yml +119 -0
  122. package/skills/global_config/github-actions-generator/examples/triggers/chatops-commands.yml +475 -0
  123. package/skills/global_config/github-actions-generator/examples/triggers/repository-dispatch.yml +418 -0
  124. package/skills/global_config/github-actions-generator/examples/triggers/workflow-orchestration.yml +404 -0
  125. package/skills/global_config/github-actions-generator/examples/workflows/docker-build-push.yml +68 -0
  126. package/skills/global_config/github-actions-generator/examples/workflows/go-ci.yml +161 -0
  127. package/skills/global_config/github-actions-generator/examples/workflows/monorepo-ci.yml +340 -0
  128. package/skills/global_config/github-actions-generator/examples/workflows/multi-environment-deploy.yml +406 -0
  129. package/skills/global_config/github-actions-generator/examples/workflows/nodejs-ci.yml +122 -0
  130. package/skills/global_config/github-actions-generator/examples/workflows/python-ci.yml +157 -0
  131. package/skills/global_config/github-actions-generator/examples/workflows/scheduled-tasks.yml +376 -0
  132. package/skills/global_config/github-actions-generator/references/advanced-triggers.md +917 -0
  133. package/skills/global_config/github-actions-generator/references/best-practices.md +755 -0
  134. package/skills/global_config/github-actions-generator/references/common-actions.md +715 -0
  135. package/skills/global_config/github-actions-generator/references/custom-actions.md +320 -0
  136. package/skills/global_config/github-actions-generator/references/expressions-and-contexts.md +688 -0
  137. package/skills/global_config/github-actions-generator/references/modern-features.md +421 -0
  138. package/skills/global_config/github-actions-generator/scripts/test_generator.sh +344 -0
  139. package/skills/global_config/github-actions-templates/SKILL.md +7 -0
  140. package/skills/global_config/github-actions-validator/SKILL.md +576 -0
  141. package/skills/global_config/github-actions-validator/examples/README.md +88 -0
  142. package/skills/global_config/github-actions-validator/examples/outdated-versions.yml +76 -0
  143. package/skills/global_config/github-actions-validator/examples/valid-ci.yml +79 -0
  144. package/skills/global_config/github-actions-validator/examples/with-errors.yml +47 -0
  145. package/skills/global_config/github-actions-validator/references/act_usage.md +233 -0
  146. package/skills/global_config/github-actions-validator/references/action_versions.md +122 -0
  147. package/skills/global_config/github-actions-validator/references/actionlint_usage.md +343 -0
  148. package/skills/global_config/github-actions-validator/references/common_errors.md +512 -0
  149. package/skills/global_config/github-actions-validator/references/modern_features.md +384 -0
  150. package/skills/global_config/github-actions-validator/references/runners.md +317 -0
  151. package/skills/global_config/github-actions-validator/scripts/install_tools.sh +113 -0
  152. package/skills/global_config/github-actions-validator/scripts/validate_workflow.sh +910 -0
  153. package/skills/global_config/github-actions-validator/tests/test_validate_workflow.sh +237 -0
  154. package/skills/global_config/makefile-generator/SKILL.md +614 -0
  155. package/skills/global_config/makefile-generator/assets/templates/.gitkeep +1 -0
  156. package/skills/global_config/makefile-generator/docs/makefile-structure.md +530 -0
  157. package/skills/global_config/makefile-generator/docs/optimization-guide.md +784 -0
  158. package/skills/global_config/makefile-generator/docs/patterns-guide.md +642 -0
  159. package/skills/global_config/makefile-generator/docs/security-guide.md +361 -0
  160. package/skills/global_config/makefile-generator/docs/targets-guide.md +642 -0
  161. package/skills/global_config/makefile-generator/docs/variables-guide.md +596 -0
  162. package/skills/global_config/makefile-generator/scripts/add_standard_targets.sh +539 -0
  163. package/skills/global_config/makefile-generator/scripts/generate_makefile_template.sh +690 -0
  164. package/skills/global_config/makefile-generator/test/test_helper_scripts.sh +190 -0
  165. package/skills/global_config/makefile-validator/SKILL.md +244 -0
  166. package/skills/global_config/makefile-validator/docs/bake-tool.md +1000 -0
  167. package/skills/global_config/makefile-validator/docs/best-practices.md +858 -0
  168. package/skills/global_config/makefile-validator/docs/common-mistakes.md +944 -0
  169. package/skills/global_config/makefile-validator/examples/bad-makefile.mk +77 -0
  170. package/skills/global_config/makefile-validator/examples/good-makefile.mk +103 -0
  171. package/skills/global_config/makefile-validator/scripts/test_validate.sh +382 -0
  172. package/skills/global_config/makefile-validator/scripts/validate_makefile.sh +712 -0
  173. package/skills/global_config/{MCP_Manage โ†’ mcp-manage}/SKILL.md +3 -3
  174. package/skills/global_config/plan-canvas/SKILL.md +9 -2
  175. package/skills/global_config/plan-canvas/scripts/lib/plan-canvas/ui.js +10 -2
  176. package/skills/global_config/plan-canvas/scripts/plan-canvas.js +1 -1
  177. package/skills/global_config/read-the-damn-docs/SKILL.md +175 -0
  178. package/skills/global_config/requesting-code-review/SKILL.md +98 -0
  179. package/skills/global_config/requesting-code-review/code-reviewer.md +198 -0
  180. package/skills/global_config/using-git-worktrees/SKILL.md +170 -0
  181. package/skills/global_config/verification-before-completion/SKILL.md +123 -0
  182. package/skills/global_config/writing-plans/SKILL.md +126 -46
  183. package/skills/global_config/writing-plans-legacy/SKILL.md +152 -0
  184. package/.claude/CLAUDE.md +0 -12
  185. package/mcps/RhinoMCP/docs/content/docs/getting-started/gemini.md +0 -61
  186. /package/{GEMINI.md โ†’ RULES.md} +0 -0
@@ -287,6 +287,132 @@ the upstream offensive exploit content is stripped and not carried over.
287
287
 
288
288
  ---
289
289
 
290
+ ## talkvalue/event-agency-skills
291
+
292
+ <https://github.com/talkvalue/event-agency-skills> โ€” Apache-2.0.
293
+ Copyright talkvalue contributors. Upstream carries no explicit copyright line
294
+ in `README.md`, `CONTRIBUTING.md`, or the plugin manifests; the attribution
295
+ above is the repository's own `LICENSE` grant.
296
+
297
+ Prose techniques adapted into `skills/basic/bdb-eventagency-skill/SKILL.md`:
298
+ stakeholder-type inbox classification with temporal priority overrides,
299
+ vendor-type failure-impact tiers, phase-based escalation thresholds
300
+ (T-30 โ†’ show day), BLOCKED-means-ours item semantics, the speaker materials
301
+ deadline framework (D-30 / D-21 / D-14 / D-7 / D-1), and post-event
302
+ performance-tier reporting. Upstream scripts, Composio tool bindings, and all
303
+ Python were not carried over; the skill is self-contained prose with no
304
+ dependency.
305
+
306
+ ---
307
+
308
+ ## BuilderIO/skills
309
+
310
+ <https://github.com/BuilderIO/skills> โ€” MIT. Copyright (c) 2026 Builder.io.
311
+
312
+ One skill adapted into `skills/global_config/read-the-damn-docs/SKILL.md`:
313
+ the docs-first trigger list, the source hierarchy, the required workflow, the
314
+ must-trigger examples, and the "if docs are unavailable" rule. AOS additionally
315
+ adds a Verification section, a `category:` key (Builder's own validator forbids
316
+ one, AOS requires it), a division-of-labour note against the `AGENTS.md` *Zero
317
+ guesswork* rule, and a pointer to the installed `firecrawl-search` /
318
+ `firecrawl-scrape` tools. Prose only โ€” the upstream `agents/openai.yaml` and
319
+ README were not carried over, and no executable from the repo is referenced.
320
+
321
+ The other 22 skills in that repo are **not** vendored. Six of them
322
+ (`visual-plan`, `visual-recap`, `visual-edit`, `an`, `turn-into-app`, `rewind`)
323
+ are build artefacts synced from a different upstream by
324
+ `scripts/sync-agent-native-skills.mjs`, and the repo's own documentation says
325
+ not to treat them as standalone. Its `.mcp.json` and plugin manifests register
326
+ external HTTP MCP servers without a prompt, so the plugin surface must never be
327
+ installed.
328
+ ## obra/superpowers
329
+
330
+ <https://github.com/obra/superpowers> โ€” MIT. Copyright (c) 2025 Jesse Vincent.
331
+
332
+ Tracked in `.agents/vendor-manifest.json` at pinned commit
333
+ `8ca22dba9a94f28898bbce59f2537ff4d87c747d` (v6.4.2).
334
+
335
+ Five workflow skills are vendored under `skills/global_config/`, each carried
336
+ whole with its companion files: `verification-before-completion`,
337
+ `requesting-code-review` (plus `code-reviewer.md`),
338
+ `finishing-a-development-branch`, `using-git-worktrees`, and
339
+ `dispatching-parallel-agents`. A sixth, `writing-plans`, **replaces** the AOS
340
+ version of that skill; the superseded AOS original is kept alongside it as
341
+ `writing-plans-legacy` (`source: community`, marked `deprecated_by`) rather than
342
+ deleted.
343
+
344
+ AOS modifications: `category:`, `source:` and `date_added:` added to the
345
+ frontmatter; the `superpowers:` namespace prefix stripped from cross-skill
346
+ references so they resolve to AOS skill names. AOS adaptations to
347
+ `writing-plans`: the plan output path is kept at AOS's `docs/plans/` rather
348
+ than upstream's `docs/superpowers/plans/`, and the AOS `risk: critical` marker
349
+ is carried over.
350
+
351
+ AOS already vendored four other skills from this repository earlier
352
+ (`brainstorming`, `test-driven-development`, `executing-plans`,
353
+ `subagent-driven-development`) without recording it here. Those imports still
354
+ carry the `superpowers:` prefix in their cross-references.
355
+
356
+ ---
357
+
358
+ ## akin-ozer/cc-devops-skills
359
+
360
+ <https://github.com/akin-ozer/cc-devops-skills> โ€” Apache-2.0.
361
+ Copyright [yyyy] [name of copyright owner] (upstream ships the unfilled
362
+ Apache-2.0 notice).
363
+
364
+ Tracked in `.agents/vendor-manifest.json` at pinned commit
365
+ `276af751e659315aaf56d3ad13d7c26f4e72e28a`.
366
+
367
+ Four generator/validator pairs are vendored under `skills/global_config/`, each
368
+ carried whole including its `references/`, `scripts/`, `examples/`, `docs/` and
369
+ `test/` subtrees: `github-actions-generator` + `github-actions-validator`,
370
+ `dockerfile-generator` + `dockerfile-validator`, `bash-script-generator` +
371
+ `bash-script-validator`, `makefile-generator` + `makefile-validator`.
372
+
373
+ AOS modifications: `category:`, `source:` and `date_added:` added to the
374
+ frontmatter; the `devops-skills:` namespace prefix stripped from cross-skill
375
+ references so they resolve to AOS skill names; the Docker example user
376
+ `appuser` renamed to `app` throughout `dockerfile-generator` and
377
+ `dockerfile-validator` to satisfy the E-PATH01 username check.
378
+
379
+ ---
380
+
381
+ ## davila7/claude-code-templates
382
+
383
+ <https://github.com/davila7/claude-code-templates> โ€” MIT.
384
+ Copyright (c) 2025 Daniel (San) รvila.
385
+
386
+ `conventional-commits` (`.claude/hooks/conventional-commits.mjs`) and
387
+ `env-file-protection` (`.claude/hooks/env-file-protection.mjs`) are ported from
388
+ upstream's `conventional-commits.py` and `env-file-protection.json`, selected
389
+ from a set of 62 hooks. Tracked in `.agents/vendor-manifest.json`.
390
+
391
+ Both are ports, not verbatim copies, and the differences are behavioural:
392
+
393
+ - **Python to .mjs.** Upstream ships Python. Node is already a hard AOS install
394
+ dependency and every other AOS hook is `.mjs`; `python3` is absent on a stock
395
+ Windows install, where the installer also runs.
396
+ - **Both harnesses.** Upstream's `env-file-protection` is an inline `echo`
397
+ guarded by a matcher `if` field, which Antigravity and the Gemini CLI ignore โ€”
398
+ there it would fire on every write. The check lives in code instead, and both
399
+ hooks emit the Antigravity `{"decision":...}` stdout form as well as the
400
+ Claude Code stderr/exit-2 form.
401
+ - **`.env.example` and friends are allowed.** Upstream's matcher blocks
402
+ `.env*`, which contradicts its own advice to put new values in
403
+ `.env.example`. Templates (`example`, `sample`, `template`, `dist`) are
404
+ committed and hold no live secret, so they are exempt here.
405
+ - **Both hooks fail open.** An unreadable payload or an unextractable commit
406
+ message allows the call, unlike `go-gate`, which fails closed. A regex miss
407
+ must not wedge a commit.
408
+
409
+ Upstream's `secret-scanner`, `tdd-gate`, and `dangerous-command-blocker` were
410
+ reviewed and **not** shipped; they remain available on demand from the ECC
411
+ store. Reasons are in `docs/handover/` and the branch description for
412
+ `feat/cicd-skills-import`.
413
+
414
+ ---
415
+
290
416
  ## Note on `mcps/`
291
417
 
292
418
  Sub-repositories vendored under `mcps/` carry their own `LICENSE` files in
@@ -201,7 +201,7 @@ function checkHarnesses() {
201
201
  // ---------------------------------------------------------------- 4. Hooks & Security Gates
202
202
  function checkHooks() {
203
203
  const claudeHooksDir = h('.claude', 'hooks');
204
- const EXPECTED_VERSION = { 'memb-inject.mjs': 5 };
204
+ const EXPECTED_VERSION = { 'memb-inject.mjs': 6 };
205
205
  const versionOf = (text) => {
206
206
  const m = /^\/\/\s*aos-hook-version:\s*(\d+)/m.exec(text);
207
207
  return m ? Number(m[1]) : null;
@@ -52,7 +52,7 @@
52
52
  #### ๐ŸŽจ Frontend & UI/UX
53
53
  | Skill Name | Description |
54
54
  |------------|-------------|
55
- | `MCP_Manage` | Manages the BDB specialized MCP servers including Unreal Engine, Rhino 7/8, DaVinci Resolve, grandMA3, Resolume, GitHub, Chrome DevTools, and TouchDesigner. |
55
+ | `mcp-manage` | Manages the BDB specialized MCP servers including Unreal Engine, Rhino 7/8, DaVinci Resolve, grandMA3, Resolume, GitHub, Chrome DevTools, and TouchDesigner. |
56
56
  | `api-design-principles` | Master REST and GraphQL API design principles to build intuitive, scalable, and maintainable APIs that delight developers and stand the test of time. |
57
57
  | `api-patterns` | API design principles and decision-making. REST vs GraphQL vs tRPC selection, response formats, versioning, pagination. |
58
58
  | `bdbdesignpro` | Use when choosing an animation engine, defining motion tokens, adding scroll effects or micro-interactions, or auditing motion for accessibility and performance in BDB projects. Covers engine selection (GSAP, Motion.dev, Anime.js, React-Spring, Three.js, CSS Native), BDB brand-locked motion tokens, and the anti-slop/a11y quality gate. |
package/installer.js CHANGED
@@ -115,8 +115,8 @@ if (mcpsArgRaw && mcpsArg === null) {
115
115
  // not express that in a script or CI, and got Antigravity as their primary
116
116
  // target instead. Values match the menu: 0 universal, 1 Antigravity,
117
117
  // 2 Claude Desktop/Code, 3 Cursor, 4 custom, 5 Codex, 6 Windsurf, 7 Roo/Cline,
118
- // 8 Aider (9 = project harness has its own --project-harness flag).
119
- const VALID_PLATFORMS = ['0', '1', '2', '3', '4', '5', '6', '7', '8'];
118
+ // 8 Aider, 10 AOS CLI (9 = project harness has its own --project-harness flag).
119
+ const VALID_PLATFORMS = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '10'];
120
120
  const platformsArgRaw = process.argv.find(a => a === '--platforms' || a.startsWith('--platforms='));
121
121
  let PLATFORMS_ARG = null;
122
122
  if (platformsArgRaw) {
@@ -1257,6 +1257,7 @@ function syncSkillsToGlobalHarnesses(excludeSkills = []) {
1257
1257
  { dir: path.join(homeDir, '.codex', 'skills'), key: 'codex' },
1258
1258
  { dir: path.join(homeDir, '.cursor', 'skills'), key: 'cursor' },
1259
1259
  { dir: path.join(homeDir, '.roo', 'skills'), key: 'vscode' },
1260
+ { dir: process.platform === 'win32' ? path.join(process.env.APPDATA || homeDir, 'opencode', 'skills') : path.join(homeDir, '.config', 'opencode', 'skills'), key: 'opencode' },
1260
1261
  ].filter((d) => d.key === null || detectedKeys.has(d.key));
1261
1262
 
1262
1263
  for (const { dir: dest } of extraSkillDestinations) {
@@ -1709,8 +1710,12 @@ function checkModuleUpdate(pkgName, targetDir) {
1709
1710
  let remoteVer = null;
1710
1711
  let checkFailed = false;
1711
1712
  try {
1712
- const npmBin = process.platform === 'win32' ? 'npm.cmd' : 'npm';
1713
- remoteVer = execFileSync(npmBin, ['view', pkgName, 'version'], { stdio: ['ignore', 'pipe', 'ignore'], encoding: 'utf8', timeout: 4000, shell: process.platform === 'win32' }).trim();
1713
+ const npmCmd = process.platform === 'win32' ? 'npm.cmd' : 'npm';
1714
+ if (process.platform === 'win32') {
1715
+ remoteVer = execSync(`"${npmCmd}" view ${pkgName} version`, { stdio: ['ignore', 'pipe', 'ignore'], encoding: 'utf8', timeout: 4000 }).trim();
1716
+ } else {
1717
+ remoteVer = execFileSync(npmCmd, ['view', pkgName, 'version'], { stdio: ['ignore', 'pipe', 'ignore'], encoding: 'utf8', timeout: 4000 }).trim();
1718
+ }
1714
1719
  } catch (e) {
1715
1720
  // Offline, a proxy, or a misconfigured registry. Swallowing this
1716
1721
  // made every module report "up to date" forever on such a machine,
@@ -1805,15 +1810,40 @@ function downloadOrUpdateModule(pkgName, targetDir, displayName) {
1805
1810
  }
1806
1811
  }
1807
1812
 
1813
+ // Phase 1: retire the live tree. On Windows a running daemon holds open
1814
+ // file handles into targetDir โ€” retry with brief backoff before failing.
1815
+ // ponytail: 3 retries ร— 600ms; escalate to process kill if this ceiling matters
1816
+ let phase1Done = false;
1817
+ for (let attempt = 0; attempt < 3 && !phase1Done; attempt++) {
1818
+ try {
1819
+ fs.renameSync(targetDir, retiredDir);
1820
+ phase1Done = true;
1821
+ } catch (retireError) {
1822
+ const retriable = retireError.code === 'EPERM' || retireError.code === 'EBUSY';
1823
+ if (retriable && attempt < 2) {
1824
+ const delayMs = 600 * (attempt + 1);
1825
+ try {
1826
+ if (process.platform === 'win32') {
1827
+ execSync(`powershell -NoProfile -Command "Start-Sleep -Milliseconds ${delayMs}"`, { stdio: 'ignore' });
1828
+ } else {
1829
+ execSync(`sleep ${delayMs / 1000}`, { stdio: 'ignore' });
1830
+ }
1831
+ } catch (_) {}
1832
+ continue;
1833
+ }
1834
+ safeRmDirSync(stagingDir);
1835
+ throw retireError;
1836
+ }
1837
+ }
1838
+
1839
+ // Phase 2: promote the staging tree. stagingDir was just unpacked and
1840
+ // has no open handles, so a single attempt is sufficient.
1808
1841
  try {
1809
- fs.renameSync(targetDir, retiredDir);
1810
1842
  fs.renameSync(stagingDir, targetDir);
1811
- } catch (swapError) {
1812
- if (fs.existsSync(retiredDir) && !fs.existsSync(targetDir)) {
1813
- try { fs.renameSync(retiredDir, targetDir); } catch (_) {}
1814
- }
1843
+ } catch (promoteError) {
1844
+ try { fs.renameSync(retiredDir, targetDir); } catch (_) {}
1815
1845
  safeRmDirSync(stagingDir);
1816
- throw swapError;
1846
+ throw promoteError;
1817
1847
  }
1818
1848
 
1819
1849
  // On Windows especially, deleting a directory that was just renamed or contains
@@ -1886,6 +1916,21 @@ async function installMemB(interactive) {
1886
1916
  }));
1887
1917
  }
1888
1918
  const membDir = path.join(moduleBasePath(), 'memB');
1919
+ // On Windows the memB WebUI process holds open file handles inside membDir.
1920
+ // The atomic rename inside downloadOrUpdateModule fails with EPERM as long as
1921
+ // those handles are live โ€” retry backoff cannot help. Kill the process on
1922
+ // port 8088 before attempting the download so the rename succeeds.
1923
+ if (process.platform === 'win32') {
1924
+ try {
1925
+ execSync(
1926
+ 'powershell -NoProfile -Command "' +
1927
+ 'Get-NetTCPConnection -LocalPort 8088 -ErrorAction SilentlyContinue |' +
1928
+ ' Select-Object -ExpandProperty OwningProcess |' +
1929
+ ' ForEach-Object { Stop-Process -Id $_ -Force -ErrorAction SilentlyContinue }"',
1930
+ { stdio: 'ignore' }
1931
+ );
1932
+ } catch (_) {}
1933
+ }
1889
1934
  // A failed download used to fall through into venv setup and daemon
1890
1935
  // registration, each of which then failed on its own terms or, worse,
1891
1936
  // "succeeded" against a stale tree -- and the run still ended in a success
@@ -2561,10 +2606,15 @@ async function installOSAgentWorkspace() {
2561
2606
  execFileSync(binTarget, ['service', 'install'], { stdio: 'ignore' });
2562
2607
  }, 'Start it by hand with: ao service install');
2563
2608
 
2564
- if (await verifyDaemonListening(3101, 'AO Orchestrator', 8000)) {
2609
+ // Windows startup entries fire asynchronously โ€” give the service more time
2610
+ const aoTimeout = process.platform === 'win32' ? 20000 : 8000;
2611
+ if (await verifyDaemonListening(3101, 'AO Orchestrator', aoTimeout)) {
2565
2612
  log.success('AO Orchestrator running on http://localhost:3101');
2566
2613
  } else {
2567
- log.warn('AO did not answer on :3101 โ€” check `ao service status` and `ao service logs`.');
2614
+ const hint = process.platform === 'win32'
2615
+ ? 'Run `ao service install` again or log out and back in, then check `ao service status`.'
2616
+ : 'Check `ao service status` and `ao service logs`.';
2617
+ log.warn(`AO did not answer on :3101 โ€” ${hint}`);
2568
2618
  }
2569
2619
  }
2570
2620
  async function promptMemBIngestion(mcpCodeTarget) {
@@ -2638,8 +2688,10 @@ function verifyEcosystemInstallation() {
2638
2688
  let newerVersion = null;
2639
2689
  let newerTag = null;
2640
2690
  try {
2641
- const npmBin = process.platform === 'win32' ? 'npm.cmd' : 'npm';
2642
- const distTagsJson = execFileSync(npmBin, ['view', mod.pkg, 'dist-tags', '--json'], { stdio: ['ignore', 'pipe', 'ignore'], encoding: 'utf8', timeout: 4000, shell: process.platform === 'win32' }).trim();
2691
+ const npmCmd = process.platform === 'win32' ? 'npm.cmd' : 'npm';
2692
+ const distTagsJson = process.platform === 'win32'
2693
+ ? execSync(`"${npmCmd}" view ${mod.pkg} dist-tags --json`, { stdio: ['ignore', 'pipe', 'ignore'], encoding: 'utf8', timeout: 4000 }).trim()
2694
+ : execFileSync(npmCmd, ['view', mod.pkg, 'dist-tags', '--json'], { stdio: ['ignore', 'pipe', 'ignore'], encoding: 'utf8', timeout: 4000 }).trim();
2643
2695
  const distTags = JSON.parse(distTagsJson);
2644
2696
  for (const [tag, ver] of Object.entries(distTags)) {
2645
2697
  if (isNewerVersion(localVer, ver)) {
@@ -2685,7 +2737,7 @@ function verifyEcosystemInstallation() {
2685
2737
 
2686
2738
  console.log('');
2687
2739
  console.log(` ${colors.bold}โ”โ”โ” BDB Agent OS Dashboard โ”โ”โ”${colors.reset}`);
2688
- console.log(` Interactive Control Center: npx aos-dashboard`);
2740
+ console.log(` Interactive Control Center: aos-dashboard`);
2689
2741
  console.log(` ${colors.dim}(Live status & service control at http://127.0.0.1:7900)${colors.reset}`);
2690
2742
  }
2691
2743
 
@@ -2869,7 +2921,7 @@ async function installMcpsForTarget(paths, ctx) {
2869
2921
  }
2870
2922
  log.step(`Installed selected MCP servers to ${mcpCodeTarget}`);
2871
2923
 
2872
- const nodeMcps = ['adobe_uxp_mcp', 'unreal_mcp', 'tdmcp', 'touchdesigner-mcp', 'davinci-resolve-mcp', 'after-effects-mcp', 'computer-use-mcp'];
2924
+ const nodeMcps = ['adobe_uxp_mcp', 'unreal_mcp', 'tdmcp', 'touchdesigner-mcp', 'davinci-resolve-mcp', 'after-effects-mcp', 'computer-use-mcp', 'mcsc'];
2873
2925
  for (const mcpFolder of nodeMcps.filter(m => selectedMcps.includes(m))) {
2874
2926
  const targetFolder = path.join(mcpCodeTarget, mcpFolder);
2875
2927
  if (fs.existsSync(path.join(targetFolder, 'package.json'))) {
@@ -3417,13 +3469,17 @@ function compileCodexAgents(agents, targetDir, pipelineConfig = null) {
3417
3469
 
3418
3470
 
3419
3471
  function injectHarnessRules() {
3420
- const geminiMdSrc = path.join(srcDir, 'GEMINI.md');
3472
+ const rulesMdSrc = path.join(srcDir, 'RULES.md');
3421
3473
  const agentsMdSrc = path.join(srcDir, '.agents', 'agents.md');
3422
3474
 
3423
- if (fs.existsSync(geminiMdSrc)) {
3424
- installStep(`install GEMINI.md to ${path.join(geminiDir, 'GEMINI.md')}`, () => {
3425
- copyDirRecursiveSync(geminiMdSrc, path.join(geminiDir, 'GEMINI.md'));
3426
- log.step(`Installed GEMINI.md to ${path.join(geminiDir, 'GEMINI.md')}`);
3475
+ if (fs.existsSync(rulesMdSrc)) {
3476
+ installStep(`install RULES.md to ${path.join(geminiDir, 'RULES.md')}`, () => {
3477
+ copyDirRecursiveSync(rulesMdSrc, path.join(geminiDir, 'RULES.md'));
3478
+ // Keep GEMINI.md in sync for backwards compatibility with Antigravity CLI harnesses
3479
+ try {
3480
+ fs.copyFileSync(rulesMdSrc, path.join(geminiDir, 'GEMINI.md'));
3481
+ } catch (e) { logDebug(e, 'sync GEMINI.md fallback'); }
3482
+ log.step(`Installed RULES.md to ${path.join(geminiDir, 'RULES.md')}`);
3427
3483
  }, 'The harness injection below still runs.');
3428
3484
 
3429
3485
  // Dispatcher scripts must land in ~/.claude/workflows/, because that is
@@ -3443,7 +3499,7 @@ function injectHarnessRules() {
3443
3499
 
3444
3500
  const startcycleWorkflowSrc = path.join(srcDir, '.agents', 'workflows', 'startcycle.md');
3445
3501
  const sources = installStep('read the global rule sources', () => ({
3446
- globalRules: fs.readFileSync(geminiMdSrc, 'utf8'),
3502
+ globalRules: fs.readFileSync(rulesMdSrc, 'utf8'),
3447
3503
  startcycleContent: fs.existsSync(startcycleWorkflowSrc) ? fs.readFileSync(startcycleWorkflowSrc, 'utf8') : '',
3448
3504
  agentsMdContent: fs.existsSync(agentsMdSrc) ? fs.readFileSync(agentsMdSrc, 'utf8') : ''
3449
3505
  }), 'Cursor, Claude, Copilot and Codex keep their current instruction files.');
@@ -3625,23 +3681,23 @@ function injectHarnessRules() {
3625
3681
  // that adds or changes a hook silently never received it -- which is exactly
3626
3682
  // what happened to memb-inject.mjs in v4.4.0, on the machines that needed it
3627
3683
  // most (a fresh install got it; every machine that already had AOS did not).
3628
- function installGlobalHooks() {
3684
+ function installGlobalHooks({ targetHome = homeDir, targetGemini = geminiDir } = {}) {
3629
3685
  const hooksSrc = path.join(srcDir, '.claude', 'hooks');
3630
3686
  const workflowsSrc = path.join(srcDir, '.claude', 'workflows');
3631
3687
 
3632
3688
  // 1. Claude Code
3633
3689
  if (fs.existsSync(hooksSrc)) {
3634
- copyDirRecursiveSync(hooksSrc, path.join(homeDir, '.claude', 'hooks'));
3635
- log.step(`Installed hooks to ${path.join(homeDir, '.claude', 'hooks')}`);
3690
+ copyDirRecursiveSync(hooksSrc, path.join(targetHome, '.claude', 'hooks'));
3691
+ log.step(`Installed hooks to ${path.join(targetHome, '.claude', 'hooks')}`);
3636
3692
  }
3637
3693
  if (fs.existsSync(workflowsSrc)) {
3638
- copyDirRecursiveSync(workflowsSrc, path.join(homeDir, '.claude', 'workflows'));
3694
+ copyDirRecursiveSync(workflowsSrc, path.join(targetHome, '.claude', 'workflows'));
3639
3695
  }
3640
- mergeBdbSettingsHooks(path.join(homeDir, '.claude', 'settings.json'));
3696
+ mergeBdbSettingsHooks(path.join(targetHome, '.claude', 'settings.json'));
3641
3697
 
3642
3698
  // 2. Google Antigravity
3643
- const agyHooksDir = path.join(geminiDir, 'config', 'hooks');
3644
- const agyWorkflowsDir = path.join(geminiDir, 'config', 'workflows');
3699
+ const agyHooksDir = path.join(targetGemini, 'config', 'hooks');
3700
+ const agyWorkflowsDir = path.join(targetGemini, 'config', 'workflows');
3645
3701
  if (fs.existsSync(hooksSrc)) {
3646
3702
  copyDirRecursiveSync(hooksSrc, agyHooksDir);
3647
3703
  log.step(`Installed hooks to ${agyHooksDir}`);
@@ -3649,14 +3705,24 @@ function installGlobalHooks() {
3649
3705
  if (fs.existsSync(workflowsSrc)) {
3650
3706
  copyDirRecursiveSync(workflowsSrc, agyWorkflowsDir);
3651
3707
  }
3652
- mergeAntigravityHooks(path.join(geminiDir, 'config', 'hooks.json'));
3653
- if (fs.existsSync(path.join(geminiDir, 'antigravity-cli'))) {
3654
- mergeAntigravityHooks(path.join(geminiDir, 'antigravity-cli', 'hooks.json'));
3708
+ mergeAntigravityHooks(path.join(targetGemini, 'config', 'hooks.json'));
3709
+ const agyCliDir = path.join(targetGemini, 'antigravity-cli');
3710
+ if (fs.existsSync(agyCliDir)) {
3711
+ const agyCliHooksDir = path.join(agyCliDir, 'hooks');
3712
+ const agyCliWorkflowsDir = path.join(agyCliDir, 'workflows');
3713
+ if (fs.existsSync(hooksSrc)) {
3714
+ copyDirRecursiveSync(hooksSrc, agyCliHooksDir);
3715
+ log.step(`Installed hooks to ${agyCliHooksDir}`);
3716
+ }
3717
+ if (fs.existsSync(workflowsSrc)) {
3718
+ copyDirRecursiveSync(workflowsSrc, agyCliWorkflowsDir);
3719
+ }
3720
+ mergeAntigravityHooks(path.join(agyCliDir, 'hooks.json'));
3655
3721
  }
3656
3722
 
3657
3723
  // 3. OpenAI Codex CLI
3658
- const codexHooksDir = path.join(homeDir, '.codex', 'hooks');
3659
- const codexWorkflowsDir = path.join(homeDir, '.codex', 'workflows');
3724
+ const codexHooksDir = path.join(targetHome, '.codex', 'hooks');
3725
+ const codexWorkflowsDir = path.join(targetHome, '.codex', 'workflows');
3660
3726
  if (fs.existsSync(hooksSrc)) {
3661
3727
  copyDirRecursiveSync(hooksSrc, codexHooksDir);
3662
3728
  log.step(`Installed hooks to ${codexHooksDir}`);
@@ -3664,12 +3730,12 @@ function installGlobalHooks() {
3664
3730
  if (fs.existsSync(workflowsSrc)) {
3665
3731
  copyDirRecursiveSync(workflowsSrc, codexWorkflowsDir);
3666
3732
  }
3667
- mergeCodexTomlHooks(path.join(homeDir, '.codex', 'config.toml'));
3733
+ mergeCodexTomlHooks(path.join(targetHome, '.codex', 'config.toml'));
3668
3734
 
3669
3735
  // 4. OpenCode CLI
3670
3736
  const opencodeDir = process.platform === 'win32'
3671
- ? path.join(process.env.APPDATA || homeDir, 'opencode')
3672
- : path.join(homeDir, '.config', 'opencode');
3737
+ ? path.join(process.env.APPDATA || targetHome, 'opencode')
3738
+ : path.join(targetHome, '.config', 'opencode');
3673
3739
  const opencodePluginSrc = path.join(srcDir, '.opencode', 'plugins', 'bdb-aos.js');
3674
3740
  if (fs.existsSync(opencodePluginSrc)) {
3675
3741
  const opencodePluginsDir = path.join(opencodeDir, 'plugins');
@@ -3745,7 +3811,7 @@ function installGlobalBinaries() {
3745
3811
  // merged result goes to a .bdb-new.json sidecar -- the same recovery pattern
3746
3812
  // the MCP config merge in installMcpsForTarget uses.
3747
3813
  function mergeBdbSettingsHooks(settingsPath, { projectLocal = false } = {}) {
3748
- const bdbHookScripts = ['go-gate.mjs', 'graph-gate.mjs', 'memb-inject.mjs', 'trail-relay.mjs'];
3814
+ const bdbHookScripts = ['go-gate.mjs', 'graph-gate.mjs', 'memb-inject.mjs', 'trail-relay.mjs', 'conventional-commits.mjs', 'env-file-protection.mjs'];
3749
3815
  // memb-inject reads the machine-global memB store under $HOME and is
3750
3816
  // installed once per machine, so it stays $HOME-anchored even inside a
3751
3817
  // project harness -- unlike the two gate hooks, which are per-checkout by
@@ -3817,7 +3883,7 @@ function mergeBdbSettingsHooks(settingsPath, { projectLocal = false } = {}) {
3817
3883
  // Merge the BDB hooks into Google Antigravity's hooks.json (.agents/hooks.json or
3818
3884
  // ~/.gemini/config/hooks.json), preserving user-defined foreign hooks.
3819
3885
  function mergeAntigravityHooks(hooksPath, { projectLocal = false } = {}) {
3820
- const bdbHookScripts = ['go-gate.mjs', 'graph-gate.mjs', 'memb-inject.mjs', 'startcycle-dispatch.mjs', 'trail-relay.mjs'];
3886
+ const bdbHookScripts = ['go-gate.mjs', 'graph-gate.mjs', 'memb-inject.mjs', 'startcycle-dispatch.mjs', 'trail-relay.mjs', 'conventional-commits.mjs', 'env-file-protection.mjs'];
3821
3887
  const isBdbEntry = (entry) => {
3822
3888
  const cmds = (entry && Array.isArray(entry.hooks) ? entry.hooks : [entry])
3823
3889
  .map((h) => (h && typeof h.command === 'string' ? h.command : (typeof h === 'string' ? h : '')))
@@ -3834,7 +3900,14 @@ function mergeAntigravityHooks(hooksPath, { projectLocal = false } = {}) {
3834
3900
  PreToolUse: [
3835
3901
  {
3836
3902
  matcher: "run_command|Bash",
3837
- hooks: [{ type: "command", command: `node "${path.join(hooksDir, 'go-gate.mjs')}"`, timeout: 10000 }]
3903
+ hooks: [
3904
+ { type: "command", command: `node "${path.join(hooksDir, 'go-gate.mjs')}"`, timeout: 10000 },
3905
+ { type: "command", command: `node "${path.join(hooksDir, 'conventional-commits.mjs')}"`, timeout: 10000 }
3906
+ ]
3907
+ },
3908
+ {
3909
+ matcher: "write_file|edit_file|replace|Write|Edit|MultiEdit",
3910
+ hooks: [{ type: "command", command: `node "${path.join(hooksDir, 'env-file-protection.mjs')}"`, timeout: 10000 }]
3838
3911
  },
3839
3912
  {
3840
3913
  hooks: [{ type: "command", command: `node "${path.join(globalHooksDir, 'trail-relay.mjs')}" --agent agy --event PreToolUse`, timeout: 2000 }]
@@ -4845,7 +4918,7 @@ async function runQuickUpdate(installState) {
4845
4918
  pruneRemovedSkills(_sessionManifest);
4846
4919
  s.stop('Skills refreshed');
4847
4920
 
4848
- // Everything injectHarnessRules() delivers -- GEMINI.md, the dispatcher
4921
+ // Everything injectHarnessRules() delivers -- RULES.md, the dispatcher
4849
4922
  // workflows the skills point at, the compiled subagent definitions, the
4850
4923
  // harness rule files and the gate + memory hooks -- used to be
4851
4924
  // fresh-install-only. v4.4.1 split just the hooks out of it for Quick
@@ -4856,18 +4929,24 @@ async function runQuickUpdate(installState) {
4856
4929
  injectHarnessRules();
4857
4930
  }, 'Harness files keep whatever version this machine already had.');
4858
4931
 
4859
- // OpenWiki setup only ever ran on a brand-new install (main()'s fresh-install
4860
- // branch below) -- an existing install running Quick Update never got offered
4861
- // it and never had its daemon schedule refreshed. promptCredentials() already
4862
- // detects an existing key and collapses to a single "keep existing" prompt in
4863
- // that case, so this is a no-op confirm for anyone already configured and a
4864
- // real one-time offer for anyone who isn't (including installs from before
4865
- // this feature existed).
4932
+ // OpenWiki: if already configured, refresh the daemon silently (no prompt).
4933
+ // Only ask when there is no key yet โ€” i.e. a first-time offer or a machine
4934
+ // that predates this feature. This avoids the "keep existing?" confirmation
4935
+ // on every Quick Update for users who have already set up OpenWiki.
4866
4936
  if (!isAutoYes) {
4867
- const creds = await promptCredentials(paths.targetMcpDir);
4868
- if (creds !== BACK) {
4869
- await installOpenWikiDaemon(creds.gemini, paths.targetSkillDir, { provider: creds.openwikiProvider, model: creds.openwikiModel, baseUrl: creds.openwikiBaseUrl });
4937
+ const _owEnv = loadExistingEnv(paths.targetMcpDir);
4938
+ const _owProvider = _owEnv['OPENWIKI_PROVIDER'] || 'google';
4939
+ const _owKeyName = PROVIDER_KEY_ENV_NAMES[_owProvider] || 'GEMINI_API_KEY';
4940
+ const _owKey = _owEnv[_owKeyName] || _owEnv['GEMINI_API_KEY'] || _owEnv['GOOGLE_API_KEY'] || _owEnv['OPENWIKI_API_KEY'] || '';
4941
+ if (_owKey || _owProvider === 'ollama') {
4942
+ await installOpenWikiDaemon(_owKey, paths.targetSkillDir, { provider: _owProvider, model: _owEnv['OPENWIKI_MODEL'] || '', baseUrl: _owEnv['OPENWIKI_BASE_URL'] || '' });
4870
4943
  await installOpenWikiVisualizer();
4944
+ } else {
4945
+ const creds = await promptCredentials(paths.targetMcpDir);
4946
+ if (creds !== BACK) {
4947
+ await installOpenWikiDaemon(creds.gemini, paths.targetSkillDir, { provider: creds.openwikiProvider, model: creds.openwikiModel, baseUrl: creds.openwikiBaseUrl });
4948
+ await installOpenWikiVisualizer();
4949
+ }
4871
4950
  }
4872
4951
  }
4873
4952
 
@@ -4920,6 +4999,40 @@ function buildAoAnnouncementBanner() {
4920
4999
  ].join('\n');
4921
5000
  }
4922
5001
 
5002
+ // AOS CLI ships as a separate npm package under packages/ for one reason: pi
5003
+ // updates on its own cadence, and folding it into this release cycle would turn
5004
+ // every pi bump into a full AOS reinstall. So it installs as an ordinary global
5005
+ // package and pulls pi in as its own dependency -- and it writes nothing to
5006
+ // ~/.agents, because it reads that directory rather than owning it.
5007
+ function installAosCli() {
5008
+ const pkgDir = path.join(srcDir, 'packages', 'aos-cli');
5009
+ const manual = 'cd packages/aos-cli && npm install -g .';
5010
+
5011
+ if (!fs.existsSync(path.join(pkgDir, 'package.json'))) {
5012
+ log.warn(`AOS CLI package missing at ${pkgDir} -- skipped. Install it later: ${manual}`);
5013
+ return;
5014
+ }
5015
+ if (hasExecutable('aos-cli')) {
5016
+ log.step('aos-cli is already on PATH.');
5017
+ return;
5018
+ }
5019
+ if (DRY_RUN) {
5020
+ log.step('[dry-run] would run: npm install -g <packages/aos-cli>');
5021
+ return;
5022
+ }
5023
+
5024
+ const res = installStep('install AOS CLI', () => {
5025
+ log.step('Installing AOS CLI globally (pi is installed as its dependency)...');
5026
+ execSync(`npm install -g ${JSON.stringify(pkgDir)}`, { stdio: 'ignore' });
5027
+ }, `The rest of AOS is installed. Install AOS CLI later: ${manual}`);
5028
+
5029
+ if (res.ok && hasExecutable('aos-cli')) {
5030
+ log.success('AOS CLI installed -- run `aos-cli`.');
5031
+ } else if (res.ok) {
5032
+ log.warn('AOS CLI is installed but `aos-cli` is not on PATH. launchd and some Windows shells start with a PATH that omits npm\'s global bin.');
5033
+ }
5034
+ }
5035
+
4923
5036
  async function main() {
4924
5037
  if (process.argv[2] === 'store') {
4925
5038
  const storeScript = path.join(srcDir, 'bin', 'aos-store.mjs');
@@ -4978,7 +5091,7 @@ async function main() {
4978
5091
  path.join(srcDir, '.cursor'),
4979
5092
  path.join(srcDir, '.github'),
4980
5093
  path.join(srcDir, '.codex-plugin'),
4981
- path.join(srcDir, 'GEMINI.md'),
5094
+ path.join(srcDir, 'RULES.md'),
4982
5095
  path.join(srcDir, 'AGENTS.md'),
4983
5096
  path.join(srcDir, 'CLAUDE.md'),
4984
5097
  path.join(srcDir, 'CODEX.md'),
@@ -5061,6 +5174,7 @@ async function main() {
5061
5174
  { value: '7', label: 'Roo Code / Cline / VS Code', hint: '~/.roo' },
5062
5175
  { value: '8', label: 'Aider CLI', hint: '~/.aider' },
5063
5176
  { value: '9', label: '๐Ÿ“ Local Project Harness', hint: 'copy dispatcher contract to current project' },
5177
+ { value: '10', label: '๐Ÿ–ฅ๏ธ AOS CLI', hint: 'pi harness -- reads ~/.agents, no own skill copy' },
5064
5178
  { value: '4', label: 'โš™๏ธ Custom Installation', hint: 'specify paths manually' }
5065
5179
  ];
5066
5180
 
@@ -5090,7 +5204,7 @@ async function main() {
5090
5204
  selectedMcps = await promptMcpSelection(tier);
5091
5205
  } else {
5092
5206
  const ctx = { tier: '1', selectedPlatforms: ['0'], mode: 'merge', customPaths: null, creds: null, selectedMcps: null };
5093
- const platformNames = { '0': '๐ŸŒ Universal Harness', '1': 'Google Antigravity', '2': 'Claude Desktop/Code', '3': 'Cursor/Generic IDE', '4': 'Custom Paths', '5': 'ChatGPT Codex CLI', '6': 'Windsurf', '7': 'Roo Code / Cline / VS Code', '8': 'Aider CLI', '9': 'Local Project Harness' };
5207
+ const platformNames = { '0': '๐ŸŒ Universal Harness', '1': 'Google Antigravity', '2': 'Claude Desktop/Code', '3': 'Cursor/Generic IDE', '4': 'Custom Paths', '5': 'ChatGPT Codex CLI', '6': 'Windsurf', '7': 'Roo Code / Cline / VS Code', '8': 'Aider CLI', '9': 'Local Project Harness', '10': 'AOS CLI' };
5094
5208
 
5095
5209
  const stepTier = async () => {
5096
5210
  const t = await selectWithBack({
@@ -5256,7 +5370,22 @@ async function main() {
5256
5370
  fs.mkdirSync(backupDir, { recursive: true, mode: 0o700 });
5257
5371
  }, 'The installation continues, but existing files are not backed up.');
5258
5372
 
5259
- const targets = specificPlatforms.map(p => ({
5373
+ // '10' is an action, not a directory target. AOS CLI reads
5374
+ // ~/.agents/skills, which syncSkillsToGlobalHarnesses() already writes --
5375
+ // left in this list it would fall through resolveTargetPaths()'s universal
5376
+ // defaults and install a second full copy of every skill somewhere nobody
5377
+ // reads them from.
5378
+ const aosCliRequested = specificPlatforms.includes('10');
5379
+ const dirPlatforms = specificPlatforms.filter(p => p !== '10');
5380
+
5381
+ if (aosCliRequested && dirPlatforms.length === 0) {
5382
+ // AOS CLI alone would have no skills to load, and an empty target list
5383
+ // leaves primaryTarget undefined for everything downstream of it.
5384
+ log.warn('AOS CLI was the only target -- adding the universal skill target so it has something to load.');
5385
+ dirPlatforms.push('1');
5386
+ }
5387
+
5388
+ const targets = dirPlatforms.map(p => ({
5260
5389
  value: p,
5261
5390
  ...resolveTargetPaths(p, customPaths)
5262
5391
  }));
@@ -5343,10 +5472,13 @@ async function main() {
5343
5472
  // Flush file-level install manifest after all writes are done.
5344
5473
  flushSessionManifest();
5345
5474
 
5475
+ // After the skill sync, because AOS CLI is useless without ~/.agents.
5476
+ if (aosCliRequested) installAosCli();
5477
+
5346
5478
  console.log('');
5347
5479
  verifyEcosystemInstallation();
5348
5480
 
5349
- outro(`๐ŸŽ‰ Installation complete! Targets: ${targets.map(t => t.value).join(', ')} ยท Tier: ${tier === '1' ? 'Pro MEDIA' : 'Basic'}${DRY_RUN ? ' ยท DRY-RUN (nothing was modified)' : ''}`);
5481
+ outro(`๐ŸŽ‰ Installation complete! Targets: ${targets.map(t => t.value).join(', ')}${aosCliRequested ? ' + AOS CLI' : ''} ยท Tier: ${tier === '1' ? 'Pro MEDIA' : 'Basic'}${DRY_RUN ? ' ยท DRY-RUN (nothing was modified)' : ''}`);
5350
5482
  }
5351
5483
 
5352
5484
  if (require.main === module) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hybridlabor-api/aos",
3
- "version": "4.8.0",
3
+ "version": "4.10.0",
4
4
  "description": "AOS โ€” A Curated AI AGENT OS. Optimized agent skills and add-ons like memB, OpenWiki, Heimdall Token Saver, and Godmode architectures.",
5
5
  "main": "installer.js",
6
6
  "engines": {
@@ -24,8 +24,10 @@
24
24
  "validate": "node scripts/validate-skills.mjs",
25
25
  "validate:strict": "node scripts/validate-skills.mjs --strict",
26
26
  "store:index": "node scripts/build-ecc-store-index.mjs",
27
+ "plugin:build": "node scripts/build-plugin-manifest.mjs",
28
+ "plugin:check": "node scripts/build-plugin-manifest.mjs --check",
27
29
  "doctor": "node bin/aos-doctor.mjs",
28
- "test": "node scripts/validate-skills.mjs --selftest && node scripts/validate-skills.mjs && node tests/aos-store.test.mjs && node tests/aos-doctor.test.mjs"
30
+ "test": "node scripts/validate-skills.mjs --selftest && node scripts/validate-skills.mjs && node scripts/build-plugin-manifest.mjs --check && node tests/aos-store.test.mjs && node tests/aos-doctor.test.mjs && node tests/build-plugin-manifest.test.mjs"
29
31
  },
30
32
  "publishConfig": {
31
33
  "access": "public"
@@ -43,7 +45,7 @@
43
45
  "bin/",
44
46
  "lib/",
45
47
  "mcp_config.json",
46
- "GEMINI.md",
48
+ "RULES.md",
47
49
  "CODEX.md",
48
50
  "CLAUDE.md",
49
51
  "THIRD_PARTY_NOTICES.md",
@@ -58,6 +60,8 @@
58
60
  "mcps/",
59
61
  "scripts/",
60
62
  "vendor/",
63
+ "packages/aos-cli/",
64
+ "!packages/aos-cli/node_modules",
61
65
  "!mcps/**/*.png",
62
66
  "!mcps/**/*.jpg",
63
67
  "!mcps/**/*.jpeg",