@hybridlabor-api/aos 4.7.2 β†’ 4.9.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 (166) hide show
  1. package/.agents/agents.md +1 -1
  2. package/.agents/nodes.json +1 -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/settings.json +13 -0
  9. package/.opencode/agents/godmode-media-eventtech.md +1 -1
  10. package/.opencode/plugins/bdb-aos.js +31 -4
  11. package/README.de.md +1 -1
  12. package/README.md +1 -1
  13. package/README.pt.md +1 -1
  14. package/THIRD_PARTY_NOTICES.md +88 -0
  15. package/docs/skills_table.md +1 -1
  16. package/installer.js +309 -101
  17. package/package.json +6 -2
  18. package/packages/aos-cli/README.md +80 -0
  19. package/packages/aos-cli/bin/aos-cli.mjs +134 -0
  20. package/packages/aos-cli/core-skills.json +12 -0
  21. package/packages/aos-cli/extensions/aos.ts +321 -0
  22. package/packages/aos-cli/package-lock.json +1923 -0
  23. package/packages/aos-cli/package.json +29 -0
  24. package/packages/aos-cli/scripts/check-theme.mjs +63 -0
  25. package/packages/aos-cli/themes/aos.json +97 -0
  26. package/scripts/build-plugin-manifest.mjs +131 -0
  27. package/scripts/validate-skills.mjs +81 -6
  28. package/skills/basic/ao-orchestrator/SKILL.md +116 -0
  29. package/skills/global_config/agenttrail/SKILL.md +6 -1
  30. package/skills/global_config/ask-tim/SKILL.md +4 -4
  31. package/skills/global_config/bash-script-generator/SKILL.md +201 -0
  32. package/skills/global_config/bash-script-generator/assets/templates/standard-template.sh +96 -0
  33. package/skills/global_config/bash-script-generator/docs/bash-scripting-guide.md +729 -0
  34. package/skills/global_config/bash-script-generator/docs/generation-best-practices.md +193 -0
  35. package/skills/global_config/bash-script-generator/docs/script-patterns.md +566 -0
  36. package/skills/global_config/bash-script-generator/docs/text-processing-guide.md +437 -0
  37. package/skills/global_config/bash-script-generator/examples/log-analyzer.sh +92 -0
  38. package/skills/global_config/bash-script-generator/scripts/generate_script_template.sh +123 -0
  39. package/skills/global_config/bash-script-generator/scripts/run_ci_checks.sh +172 -0
  40. package/skills/global_config/bash-script-generator/scripts/test_generator.sh +413 -0
  41. package/skills/global_config/bash-script-validator/SKILL.md +249 -0
  42. package/skills/global_config/bash-script-validator/docs/awk-reference.md +449 -0
  43. package/skills/global_config/bash-script-validator/docs/bash-reference.md +468 -0
  44. package/skills/global_config/bash-script-validator/docs/common-mistakes.md +623 -0
  45. package/skills/global_config/bash-script-validator/docs/grep-reference.md +395 -0
  46. package/skills/global_config/bash-script-validator/docs/regex-reference.md +391 -0
  47. package/skills/global_config/bash-script-validator/docs/sed-reference.md +454 -0
  48. package/skills/global_config/bash-script-validator/docs/shell-reference.md +463 -0
  49. package/skills/global_config/bash-script-validator/docs/shellcheck-reference.md +399 -0
  50. package/skills/global_config/bash-script-validator/examples/bad-bash.sh +55 -0
  51. package/skills/global_config/bash-script-validator/examples/bad-shell.sh +54 -0
  52. package/skills/global_config/bash-script-validator/examples/good-bash.sh +71 -0
  53. package/skills/global_config/bash-script-validator/examples/good-shell.sh +69 -0
  54. package/skills/global_config/bash-script-validator/scripts/run_ci_checks.sh +23 -0
  55. package/skills/global_config/bash-script-validator/scripts/shellcheck_wrapper.sh +174 -0
  56. package/skills/global_config/bash-script-validator/scripts/test_validate.sh +446 -0
  57. package/skills/global_config/bash-script-validator/scripts/validate.sh +512 -0
  58. package/skills/global_config/ci-pipeline/SKILL.md +135 -0
  59. package/skills/global_config/dispatching-parallel-agents/SKILL.md +170 -0
  60. package/skills/global_config/dockerfile-generator/SKILL.md +1038 -0
  61. package/skills/global_config/dockerfile-generator/examples/example.dockerignore +95 -0
  62. package/skills/global_config/dockerfile-generator/examples/golang-distroless.Dockerfile +34 -0
  63. package/skills/global_config/dockerfile-generator/examples/java-springboot.Dockerfile +45 -0
  64. package/skills/global_config/dockerfile-generator/examples/nextjs-production.Dockerfile +49 -0
  65. package/skills/global_config/dockerfile-generator/examples/nodejs-multistage.Dockerfile +55 -0
  66. package/skills/global_config/dockerfile-generator/examples/python-fastapi.Dockerfile +48 -0
  67. package/skills/global_config/dockerfile-generator/references/language_specific_guides.md +510 -0
  68. package/skills/global_config/dockerfile-generator/references/multistage_builds.md +570 -0
  69. package/skills/global_config/dockerfile-generator/references/optimization_patterns.md +492 -0
  70. package/skills/global_config/dockerfile-generator/references/security_best_practices.md +375 -0
  71. package/skills/global_config/dockerfile-generator/scripts/generate_dockerignore.sh +199 -0
  72. package/skills/global_config/dockerfile-generator/scripts/generate_golang.sh +172 -0
  73. package/skills/global_config/dockerfile-generator/scripts/generate_java.sh +185 -0
  74. package/skills/global_config/dockerfile-generator/scripts/generate_nodejs.sh +279 -0
  75. package/skills/global_config/dockerfile-generator/scripts/generate_python.sh +218 -0
  76. package/skills/global_config/dockerfile-generator/scripts/test_generator.sh +210 -0
  77. package/skills/global_config/dockerfile-validator/SKILL.md +300 -0
  78. package/skills/global_config/dockerfile-validator/examples/.dockerignore.example +34 -0
  79. package/skills/global_config/dockerfile-validator/examples/bad-example.Dockerfile +37 -0
  80. package/skills/global_config/dockerfile-validator/examples/golang-distroless.Dockerfile +50 -0
  81. package/skills/global_config/dockerfile-validator/examples/good-example.Dockerfile +52 -0
  82. package/skills/global_config/dockerfile-validator/examples/python-optimized.Dockerfile +53 -0
  83. package/skills/global_config/dockerfile-validator/examples/security-issues.Dockerfile +42 -0
  84. package/skills/global_config/dockerfile-validator/references/docker_best_practices.md +348 -0
  85. package/skills/global_config/dockerfile-validator/references/optimization_guide.md +473 -0
  86. package/skills/global_config/dockerfile-validator/references/security_checklist.md +208 -0
  87. package/skills/global_config/dockerfile-validator/scripts/dockerfile-validate.sh +699 -0
  88. package/skills/global_config/dockerfile-validator/scripts/test_validate.sh +35 -0
  89. package/skills/global_config/dockerfile-validator/tests/fixtures/copy-before-yarn-lock-read.Dockerfile +6 -0
  90. package/skills/global_config/dockerfile-validator/tests/fixtures/copy-before-yarn.Dockerfile +6 -0
  91. package/skills/global_config/dockerfile-validator/tests/fixtures/from-platform-nonroot.Dockerfile +7 -0
  92. package/skills/global_config/dockerfile-validator/tests/test_regression.sh +164 -0
  93. package/skills/global_config/finishing-a-development-branch/SKILL.md +228 -0
  94. package/skills/global_config/github-actions-generator/SKILL.md +353 -0
  95. package/skills/global_config/github-actions-generator/assets/templates/action/composite/action.yml +82 -0
  96. package/skills/global_config/github-actions-generator/assets/templates/action/docker/Dockerfile +25 -0
  97. package/skills/global_config/github-actions-generator/assets/templates/action/docker/action.yml +42 -0
  98. package/skills/global_config/github-actions-generator/assets/templates/action/docker/entrypoint.sh +27 -0
  99. package/skills/global_config/github-actions-generator/assets/templates/action/javascript/action.yml +33 -0
  100. package/skills/global_config/github-actions-generator/assets/templates/action/javascript/index.js +50 -0
  101. package/skills/global_config/github-actions-generator/assets/templates/action/javascript/package.json +27 -0
  102. package/skills/global_config/github-actions-generator/assets/templates/workflow/basic_workflow.yml +242 -0
  103. package/skills/global_config/github-actions-generator/assets/templates/workflow/reusable_workflow.yml +106 -0
  104. package/skills/global_config/github-actions-generator/examples/README.md +147 -0
  105. package/skills/global_config/github-actions-generator/examples/actions/setup-node-cached/action.yml +93 -0
  106. package/skills/global_config/github-actions-generator/examples/caching/docker-buildkit.yml +256 -0
  107. package/skills/global_config/github-actions-generator/examples/security/dependency-review.yml +62 -0
  108. package/skills/global_config/github-actions-generator/examples/security/sbom-attestation.yml +119 -0
  109. package/skills/global_config/github-actions-generator/examples/triggers/chatops-commands.yml +475 -0
  110. package/skills/global_config/github-actions-generator/examples/triggers/repository-dispatch.yml +418 -0
  111. package/skills/global_config/github-actions-generator/examples/triggers/workflow-orchestration.yml +404 -0
  112. package/skills/global_config/github-actions-generator/examples/workflows/docker-build-push.yml +68 -0
  113. package/skills/global_config/github-actions-generator/examples/workflows/go-ci.yml +161 -0
  114. package/skills/global_config/github-actions-generator/examples/workflows/monorepo-ci.yml +340 -0
  115. package/skills/global_config/github-actions-generator/examples/workflows/multi-environment-deploy.yml +406 -0
  116. package/skills/global_config/github-actions-generator/examples/workflows/nodejs-ci.yml +122 -0
  117. package/skills/global_config/github-actions-generator/examples/workflows/python-ci.yml +157 -0
  118. package/skills/global_config/github-actions-generator/examples/workflows/scheduled-tasks.yml +376 -0
  119. package/skills/global_config/github-actions-generator/references/advanced-triggers.md +917 -0
  120. package/skills/global_config/github-actions-generator/references/best-practices.md +755 -0
  121. package/skills/global_config/github-actions-generator/references/common-actions.md +715 -0
  122. package/skills/global_config/github-actions-generator/references/custom-actions.md +320 -0
  123. package/skills/global_config/github-actions-generator/references/expressions-and-contexts.md +688 -0
  124. package/skills/global_config/github-actions-generator/references/modern-features.md +421 -0
  125. package/skills/global_config/github-actions-generator/scripts/test_generator.sh +344 -0
  126. package/skills/global_config/github-actions-templates/SKILL.md +7 -0
  127. package/skills/global_config/github-actions-validator/SKILL.md +576 -0
  128. package/skills/global_config/github-actions-validator/examples/README.md +88 -0
  129. package/skills/global_config/github-actions-validator/examples/outdated-versions.yml +76 -0
  130. package/skills/global_config/github-actions-validator/examples/valid-ci.yml +79 -0
  131. package/skills/global_config/github-actions-validator/examples/with-errors.yml +47 -0
  132. package/skills/global_config/github-actions-validator/references/act_usage.md +233 -0
  133. package/skills/global_config/github-actions-validator/references/action_versions.md +122 -0
  134. package/skills/global_config/github-actions-validator/references/actionlint_usage.md +343 -0
  135. package/skills/global_config/github-actions-validator/references/common_errors.md +512 -0
  136. package/skills/global_config/github-actions-validator/references/modern_features.md +384 -0
  137. package/skills/global_config/github-actions-validator/references/runners.md +317 -0
  138. package/skills/global_config/github-actions-validator/scripts/install_tools.sh +113 -0
  139. package/skills/global_config/github-actions-validator/scripts/validate_workflow.sh +910 -0
  140. package/skills/global_config/github-actions-validator/tests/test_validate_workflow.sh +237 -0
  141. package/skills/global_config/makefile-generator/SKILL.md +614 -0
  142. package/skills/global_config/makefile-generator/assets/templates/.gitkeep +1 -0
  143. package/skills/global_config/makefile-generator/docs/makefile-structure.md +530 -0
  144. package/skills/global_config/makefile-generator/docs/optimization-guide.md +784 -0
  145. package/skills/global_config/makefile-generator/docs/patterns-guide.md +642 -0
  146. package/skills/global_config/makefile-generator/docs/security-guide.md +361 -0
  147. package/skills/global_config/makefile-generator/docs/targets-guide.md +642 -0
  148. package/skills/global_config/makefile-generator/docs/variables-guide.md +596 -0
  149. package/skills/global_config/makefile-generator/scripts/add_standard_targets.sh +539 -0
  150. package/skills/global_config/makefile-generator/scripts/generate_makefile_template.sh +690 -0
  151. package/skills/global_config/makefile-generator/test/test_helper_scripts.sh +190 -0
  152. package/skills/global_config/makefile-validator/SKILL.md +244 -0
  153. package/skills/global_config/makefile-validator/docs/bake-tool.md +1000 -0
  154. package/skills/global_config/makefile-validator/docs/best-practices.md +858 -0
  155. package/skills/global_config/makefile-validator/docs/common-mistakes.md +944 -0
  156. package/skills/global_config/makefile-validator/examples/bad-makefile.mk +77 -0
  157. package/skills/global_config/makefile-validator/examples/good-makefile.mk +103 -0
  158. package/skills/global_config/makefile-validator/scripts/test_validate.sh +382 -0
  159. package/skills/global_config/makefile-validator/scripts/validate_makefile.sh +712 -0
  160. package/skills/global_config/{MCP_Manage β†’ mcp-manage}/SKILL.md +3 -3
  161. package/skills/global_config/requesting-code-review/SKILL.md +98 -0
  162. package/skills/global_config/requesting-code-review/code-reviewer.md +198 -0
  163. package/skills/global_config/using-git-worktrees/SKILL.md +170 -0
  164. package/skills/global_config/verification-before-completion/SKILL.md +123 -0
  165. package/skills/global_config/writing-plans/SKILL.md +126 -46
  166. package/skills/global_config/writing-plans-legacy/SKILL.md +139 -0
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "@hybridlabor-api/aos-cli",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "description": "AOS CLI -- the AOS dispatcher contract and skills on the pi coding agent",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "bin": {
9
+ "aos-cli": "bin/aos-cli.mjs"
10
+ },
11
+ "files": [
12
+ "bin/",
13
+ "themes/",
14
+ "scripts/",
15
+ "extensions/",
16
+ "core-skills.json",
17
+ "!packages/aos-cli/node_modules",
18
+ "README.md"
19
+ ],
20
+ "scripts": {
21
+ "test": "node scripts/check-theme.mjs"
22
+ },
23
+ "engines": {
24
+ "node": ">=22.19.0"
25
+ },
26
+ "dependencies": {
27
+ "@earendil-works/pi-coding-agent": "^0.87.1"
28
+ }
29
+ }
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env node
2
+ // Validate themes/aos.json against pi's theme schema contract.
3
+ //
4
+ // Two things go wrong when you re-skin a pi theme, and neither is obvious:
5
+ // a missing required role makes pi reject the whole theme, and a role pointing
6
+ // at a var that does not exist looks fine in the file but resolves to nothing
7
+ // at render time. This is a theme-tuning loop guard, not a schema validator --
8
+ // it checks the contract pi actually enforces, so it stays small.
9
+ //
10
+ // node scripts/check-theme.mjs
11
+
12
+ import { readFileSync } from 'node:fs';
13
+ import { fileURLToPath } from 'node:url';
14
+ import path from 'node:path';
15
+
16
+ const themePath = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', 'themes', 'aos.json');
17
+
18
+ // pi's published theme-schema.json, trimmed to the enforced part: the required
19
+ // colour roles and the five value forms pi accepts (hex, rgb()/oklsl(),
20
+ // 256-colour index, var reference, terminal default).
21
+ const REQUIRED = [
22
+ 'accent', 'border', 'borderAccent', 'borderMuted', 'success', 'error', 'warning',
23
+ 'muted', 'dim', 'text', 'thinkingText', 'selectedBg', 'userMessageBg',
24
+ 'userMessageText', 'customMessageBg', 'customMessageText', 'customMessageLabel',
25
+ 'toolPendingBg', 'toolSuccessBg', 'toolErrorBg', 'toolTitle', 'toolOutput',
26
+ 'mdHeading', 'mdLink', 'mdLinkUrl', 'mdCode', 'mdCodeBlock', 'mdCodeBlockBorder',
27
+ 'mdQuote', 'mdQuoteBorder', 'mdHr', 'mdListBullet', 'toolDiffAdded',
28
+ 'toolDiffRemoved', 'toolDiffContext', 'syntaxComment', 'syntaxKeyword',
29
+ 'syntaxFunction', 'syntaxVariable', 'syntaxString', 'syntaxNumber', 'syntaxType',
30
+ 'syntaxOperator', 'syntaxPunctuation', 'thinkingOff', 'thinkingMinimal',
31
+ 'thinkingLow', 'thinkingMedium', 'thinkingHigh', 'thinkingXhigh', 'bashMode',
32
+ ];
33
+ const isLiteral = (v) =>
34
+ v === '' || typeof v === 'number' ||
35
+ /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(v) ||
36
+ /^(rgb|oklsl)\(/.test(v);
37
+
38
+ const theme = JSON.parse(readFileSync(themePath, 'utf8'));
39
+ const colors = theme.colors ?? {};
40
+ const vars = theme.vars ?? {};
41
+
42
+ const problems = [];
43
+ if (theme.name !== 'aos') problems.push(`name is "${theme.name}", expected "aos"`);
44
+ for (const role of REQUIRED) {
45
+ if (!(role in colors)) problems.push(`missing required color role: ${role}`);
46
+ }
47
+ for (const [role, value] of Object.entries(colors)) {
48
+ if (typeof value !== 'string') problems.push(`${role}: expected a string, got ${typeof value}`);
49
+ else if (!isLiteral(value) && !(value in vars)) problems.push(`${role}: references undefined var "${value}"`);
50
+ }
51
+ for (const [name, value] of Object.entries(vars)) {
52
+ if (typeof value === 'string' && value.startsWith('#') && !isLiteral(value)) problems.push(`var ${name}: malformed hex "${value}"`);
53
+ if (typeof value === 'string' && !value.startsWith('#') && !isLiteral(value) && !(value in vars)) {
54
+ problems.push(`var ${name}: references undefined var "${value}"`);
55
+ }
56
+ }
57
+
58
+ if (problems.length) {
59
+ for (const p of problems) console.error(` ${p}`);
60
+ console.error(`\ntheme invalid (${problems.length} problem${problems.length > 1 ? 's' : ''})`);
61
+ process.exit(1);
62
+ }
63
+ console.log(`theme "${theme.name}" valid -- ${Object.keys(colors).length} roles, ${Object.keys(vars).length} vars, ${REQUIRED.length} required present`);
@@ -0,0 +1,97 @@
1
+ {
2
+ "$schema": "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
3
+ "name": "aos",
4
+ "appearance": "dark",
5
+ "vars": {
6
+ "purple": "#9D4EDD",
7
+ "amethyst": "#9B59B6",
8
+ "beige": "#DECAA8",
9
+ "gold": "#D4AF37",
10
+ "forge": "#FF6321",
11
+ "emerald": "#2ECC71",
12
+
13
+ "cyan": "#00d7ff",
14
+ "blue": "#5f87ff",
15
+ "red": "#cc6666",
16
+ "text": "#d4d4d4",
17
+ "gray": "#808080",
18
+ "dimGray": "#666666",
19
+ "darkGray": "#505050",
20
+ "accent": "purple",
21
+ "selectedBg": "#3a3a4a",
22
+ "userMsgBg": "#343541",
23
+ "toolPendingBg": "#282832",
24
+ "toolSuccessBg": "#283228",
25
+ "toolErrorBg": "#3c2828",
26
+ "customMsgBg": "#2d2838"
27
+ },
28
+ "colors": {
29
+ "accent": "accent",
30
+ "border": "amethyst",
31
+ "borderAccent": "gold",
32
+ "borderMuted": "darkGray",
33
+ "success": "emerald",
34
+ "error": "red",
35
+ "warning": "forge",
36
+ "muted": "gray",
37
+ "dim": "dimGray",
38
+ "text": "text",
39
+ "thinkingText": "gray",
40
+
41
+ "selectedBg": "selectedBg",
42
+ "scrollbarTrack": "darkGray",
43
+ "scrollbarThumb": "text",
44
+ "searchMatchBg": "selectedBg",
45
+ "searchMatchText": "text",
46
+ "userMessageBg": "userMsgBg",
47
+ "userMessageText": "text",
48
+ "customMessageBg": "customMsgBg",
49
+ "customMessageText": "text",
50
+ "customMessageLabel": "amethyst",
51
+ "toolPendingBg": "toolPendingBg",
52
+ "toolSuccessBg": "toolSuccessBg",
53
+ "toolErrorBg": "toolErrorBg",
54
+ "toolTitle": "text",
55
+ "toolOutput": "gray",
56
+
57
+ "mdHeading": "beige",
58
+ "mdLink": "cyan",
59
+ "mdLinkUrl": "dimGray",
60
+ "mdCode": "accent",
61
+ "mdCodeBlock": "emerald",
62
+ "mdCodeBlockBorder": "gray",
63
+ "mdQuote": "gray",
64
+ "mdQuoteBorder": "amethyst",
65
+ "mdHr": "gray",
66
+ "mdListBullet": "accent",
67
+
68
+ "toolDiffAdded": "emerald",
69
+ "toolDiffRemoved": "red",
70
+ "toolDiffContext": "gray",
71
+
72
+ "syntaxComment": "#6A9955",
73
+ "syntaxKeyword": "#569CD6",
74
+ "syntaxFunction": "#DCDCAA",
75
+ "syntaxVariable": "#9CDCFE",
76
+ "syntaxString": "#CE9178",
77
+ "syntaxNumber": "#B5CEA8",
78
+ "syntaxType": "#4EC9B0",
79
+ "syntaxOperator": "#D4D4D4",
80
+ "syntaxPunctuation": "#D4D4D4",
81
+
82
+ "thinkingOff": "darkGray",
83
+ "thinkingMinimal": "#6e6e6e",
84
+ "thinkingLow": "#5f87af",
85
+ "thinkingMedium": "#81a2be",
86
+ "thinkingHigh": "amethyst",
87
+ "thinkingXhigh": "purple",
88
+ "thinkingMax": "#ff5fff",
89
+
90
+ "bashMode": "emerald"
91
+ },
92
+ "export": {
93
+ "pageBg": "#18181e",
94
+ "cardBg": "#1e1e24",
95
+ "infoBg": "#3c3728"
96
+ }
97
+ }
@@ -0,0 +1,131 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Generates .claude-plugin/plugin.json and the plugin-root agents/ directory.
4
+ //
5
+ // Claude Code resolves plugin components two different ways, and only one of
6
+ // them is obvious:
7
+ //
8
+ // skills -> the manifest's "skills" array, one entry per skill DIRECTORY.
9
+ // No globs ("skills/*/*/" is rejected as "Path not found") and no
10
+ // recursion (a category dir like ./skills/global_config resolves to
11
+ // nothing, because it holds no SKILL.md of its own). Every skill
12
+ // must therefore be named explicitly, or it silently ships nothing.
13
+ // agents -> convention only, <plugin-root>/agents/*.md. The manifest's
14
+ // "agents" key is accepted by the schema and then ignored, so a
15
+ // correct-looking path list there yields 0 agents and no warning.
16
+ //
17
+ // The AOS skills live at skills/<category>/<name>/SKILL.md, two levels deep, and
18
+ // the agent personas live at .claude/agents/ (referenced by .agents/nodes.json
19
+ // personaFile paths and regenerated by installer.js, so they cannot move). Both
20
+ // facts mean the plugin needs a generated layout, which is what this script is.
21
+ //
22
+ // Usage: node scripts/build-plugin-manifest.mjs [--check]
23
+
24
+ import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'node:fs';
25
+ import { dirname, join, relative, resolve } from 'node:path';
26
+ import { fileURLToPath } from 'node:url';
27
+
28
+ const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..');
29
+ const CHECK = process.argv.includes('--check');
30
+
31
+ const pkg = JSON.parse(readFileSync(join(ROOT, 'package.json'), 'utf8'));
32
+ const repoUrl = pkg.repository?.url?.replace(/^git\+/, '').replace(/\.git$/, '') ??
33
+ 'https://github.com/hybridlabor-api/aos';
34
+
35
+ function walkSkills(dir, output = []) {
36
+ if (!existsSync(dir)) return output;
37
+ for (const item of readdirSync(dir, { withFileTypes: true })) {
38
+ const full = join(dir, item.name);
39
+ if (item.isDirectory()) walkSkills(full, output);
40
+ else if (item.name === 'SKILL.md') output.push(dirname(full));
41
+ }
42
+ return output;
43
+ }
44
+
45
+ const skillDirs = walkSkills(join(ROOT, 'skills')).sort();
46
+ if (skillDirs.length === 0) throw new Error('No skills found under skills/ β€” refusing to write an empty manifest');
47
+
48
+ const skills = skillDirs.map((dir) => `./${relative(ROOT, dir).split(/[\\/]/).join('/')}`);
49
+
50
+ const agentSrc = join(ROOT, '.claude', 'agents');
51
+ const agentDst = join(ROOT, 'agents');
52
+ const agentNames = existsSync(agentSrc)
53
+ ? readdirSync(agentSrc).filter((name) => name.endsWith('.md')).sort()
54
+ : [];
55
+
56
+ // The personas are the same 13 files the repo loads via .claude/agents/. They are
57
+ // copied rather than symlinked because validate --strict (the release gate)
58
+ // refuses a symlinked component directory, and a symlink is fragile once the
59
+ // plugin is cloned or downloaded on a platform that does not create them.
60
+ const drift = [];
61
+ if (!CHECK) mkdirSync(agentDst, { recursive: true });
62
+ for (const name of agentNames) {
63
+ const want = readFileSync(join(agentSrc, name));
64
+ const path = join(agentDst, name);
65
+ if (!existsSync(path) || !readFileSync(path).equals(want)) {
66
+ if (CHECK) drift.push(name);
67
+ else {
68
+ writeFileSync(path, want);
69
+ console.log(`synced agents/${name}`);
70
+ }
71
+ }
72
+ }
73
+ if (!CHECK) {
74
+ for (const name of readdirSync(agentDst)) {
75
+ if (!agentNames.includes(name)) {
76
+ rmSync(join(agentDst, name));
77
+ console.log(`removed stale agents/${name}`);
78
+ }
79
+ }
80
+ }
81
+
82
+ const manifest = {
83
+ $schema: 'https://anthropic.com/claude-code/plugin.schema.json',
84
+ name: 'bdb-aos',
85
+ version: pkg.version,
86
+ description:
87
+ 'Full BDB Agent OS suite: 200+ curated skills, subagents, the startcycle pipeline, ' +
88
+ 'CI/CD workflows and security hooks for Claude Code.',
89
+ author: { name: 'Tim Rennings / Hybridlabor Global LLC', email: 'hybridlabor@gmail.com' },
90
+ homepage: repoUrl,
91
+ repository: repoUrl,
92
+ license: 'proprietary',
93
+ keywords: ['skills', 'agent-os', 'cicd', 'multiagent', 'startcycle', 'bdb'],
94
+ skills,
95
+ };
96
+
97
+ const target = join(ROOT, '.claude-plugin', 'plugin.json');
98
+ const serialized = `${JSON.stringify(manifest, null, 2)}\n`;
99
+ const current = existsSync(target) ? readFileSync(target, 'utf8') : '';
100
+
101
+ // `claude plugin tag` refuses to cut a release unless plugin.json and the
102
+ // enclosing marketplace entry agree on the version, so the marketplace copy of
103
+ // the number is generated here too rather than hand-maintained.
104
+ const marketPath = join(ROOT, '.claude-plugin', 'marketplace.json');
105
+ const market = JSON.parse(readFileSync(marketPath, 'utf8'));
106
+ const entry = market.plugins?.find((plugin) => plugin.name === manifest.name);
107
+ if (!entry) throw new Error(`marketplace.json has no entry named ${manifest.name}`);
108
+ entry.version = pkg.version;
109
+ const marketSerialized = `${JSON.stringify(market, null, 2)}\n`;
110
+ const marketCurrent = readFileSync(marketPath, 'utf8');
111
+
112
+ if (CHECK) {
113
+ if (current !== serialized) {
114
+ console.error('plugin.json is out of date β€” run: node scripts/build-plugin-manifest.mjs');
115
+ process.exit(1);
116
+ }
117
+ if (marketCurrent !== marketSerialized) {
118
+ console.error('marketplace.json version is out of date β€” run: node scripts/build-plugin-manifest.mjs');
119
+ process.exit(1);
120
+ }
121
+ if (drift.length > 0) {
122
+ console.error(`agents/ is out of date (${drift.join(', ')}) β€” run: node scripts/build-plugin-manifest.mjs`);
123
+ process.exit(1);
124
+ }
125
+ console.log(`plugin manifest up to date: ${skills.length} skills, ${agentNames.length} agents`);
126
+ } else {
127
+ mkdirSync(dirname(target), { recursive: true });
128
+ writeFileSync(target, serialized);
129
+ writeFileSync(marketPath, marketSerialized);
130
+ console.log(`Wrote .claude-plugin/plugin.json with ${skills.length} skills and ${agentNames.length} agents`);
131
+ }
@@ -17,6 +17,19 @@ const CATEGORIES = new Set([
17
17
  ]);
18
18
  const REQUIRED = ['name', 'description', 'category'];
19
19
 
20
+ // The Agent Skills specification constrains `name` to lowercase letters,
21
+ // numbers, and single hyphens, max 64 chars. A harness that enforces the spec
22
+ // drops such a skill silently, so a self-consistent name==directory pair is
23
+ // not enough: `MCP_Manage` matched its own directory perfectly and was still
24
+ // unloadable by pi. Tolerant harnesses hide this; strict ones lose the skill.
25
+ const NAME_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
26
+ const NAME_MAX = 64;
27
+
28
+ // Charset and length are one rule. Keeping them as two expressions meant the
29
+ // selftest could assert the charset and pass while the length limit lived only
30
+ // in validate() -- the two can drift, and then the test proves nothing.
31
+ const isValidSkillName = (v) => v.length <= NAME_MAX && NAME_RE.test(v);
32
+
20
33
  // Names that are stand-ins or service accounts rather than a person. The rule
21
34
  // is about leaking a human's username; `/home/agent` on the SaaS fleet is a
22
35
  // role account and is meant to be written down.
@@ -36,7 +49,7 @@ function findClosingQuote(s, from, q) {
36
49
  for (let i = from; i < s.length; i++) {
37
50
  if (s[i] !== q) continue;
38
51
  if (q === "'" && s[i + 1] === "'") { i++; continue; } // '' escapes a quote
39
- if (q === '"' && s[i - 1] === '\\') continue;
52
+ if (q === '"') { let b = 0, j = i - 1; while (j >= from && s[j] === '\\') { b++; j--; } if (b % 2 !== 0) continue; }
40
53
  return i;
41
54
  }
42
55
  return -1;
@@ -108,6 +121,18 @@ export function scanFrontmatter(text) {
108
121
  }
109
122
  } else {
110
123
  eatIndented(false); // plain scalar
124
+ // A plain (unquoted) scalar containing ": " is a nested mapping as far as
125
+ // YAML is concerned. The scanner above takes the rest of the line as the
126
+ // value and sees nothing wrong, and so does every lenient harness β€” but
127
+ // a spec-conformant reader parses it as a map, drops the frontmatter, and
128
+ // the skill never loads. `description: live map: of a build` is the shape.
129
+ if (/:(\s|$)/.test(restT)) {
130
+ issues.push({
131
+ code: 'E-YAML04', key,
132
+ msg: `plain value of \`${key}\` contains ":" β€” YAML reads the rest as a nested mapping, not text. ` +
133
+ 'Quote the value or fold it (>-); as written the frontmatter does not parse.',
134
+ });
135
+ }
111
136
  }
112
137
 
113
138
  if (swallowed.length) {
@@ -247,11 +272,21 @@ function validate() {
247
272
  }
248
273
 
249
274
  const name = byKey.get('name');
250
- if (name && unquote(name.value) !== dirName) {
251
- findings.push({
252
- level: 'error', code: 'E-FM04', file: rel, line: name.line,
253
- msg: `\`name: ${unquote(name.value)}\` does not match its directory \`${dirName}\``,
254
- });
275
+ if (name) {
276
+ const value = unquote(name.value);
277
+ if (!isValidSkillName(value)) {
278
+ findings.push({
279
+ level: 'error', code: 'E-NAME01', file: rel, line: name.line,
280
+ msg: `\`name: ${value}\` is not spec-valid β€” lowercase a-z, 0-9 and single hyphens only, max ${NAME_MAX} chars. ` +
281
+ 'A harness that enforces the Agent Skills spec will not load this skill at all.',
282
+ });
283
+ }
284
+ if (value !== dirName) {
285
+ findings.push({
286
+ level: 'error', code: 'E-FM04', file: rel, line: name.line,
287
+ msg: `\`name: ${value}\` does not match its directory \`${dirName}\``,
288
+ });
289
+ }
255
290
  }
256
291
 
257
292
  const desc = byKey.get('description');
@@ -383,9 +418,49 @@ function selftest() {
383
418
  assert.equal(quoted.issues.length, 0);
384
419
  assert.equal(quoted.keys.find((k) => k.key === 'category').value, 'library');
385
420
 
421
+ // A plain scalar holding ": " is a nested mapping to a real YAML reader, so
422
+ // the frontmatter does not parse and the skill never loads. Every lenient
423
+ // harness accepts it, which is how agenttrail shipped: the shape passed this
424
+ // validator, Claude Code and Antigravity, and only pi rejected it.
425
+ const colon = scanFrontmatter([
426
+ '---', 'name: agenttrail', 'description: Live map of a build: which component',
427
+ 'category: bdb-core', '---',
428
+ ].join('\n'));
429
+ assert.ok(
430
+ colon.issues.some((i) => i.code === 'E-YAML04'),
431
+ 'a plain scalar containing ": " must be reported',
432
+ );
433
+ assert.equal(colon.keys.find((k) => k.key === 'description').value, 'Live map of a build: which component');
434
+
435
+ // A colon that is not followed by whitespace is not a mapping boundary --
436
+ // URLs and times are the common false positive.
437
+ const url = scanFrontmatter([
438
+ '---', 'name: firecrawl', 'description: See https://example.com/a:b for the API',
439
+ 'category: library', '---',
440
+ ].join('\n'));
441
+ assert.ok(!url.issues.some((i) => i.code === 'E-YAML04'), 'a colon inside a URL is not a mapping');
442
+
443
+ // The quoted form of the same text is fine -- that is the fix.
444
+ const quotedColon = scanFrontmatter([
445
+ '---', 'name: agenttrail', 'description: "Live map of a build: which component"',
446
+ 'category: bdb-core', '---',
447
+ ].join('\n'));
448
+ assert.equal(quotedColon.issues.length, 0, 'quoting the value resolves E-YAML04');
449
+
386
450
  assert.equal(scanFrontmatter('# no frontmatter').ok, false);
387
451
  assert.equal(scanFrontmatter('---\nname: x\n').reason, 'unterminated');
388
452
 
453
+ // The spec's name charset, and the case that shipped: MCP_Manage matched its
454
+ // own directory perfectly and was still unloadable by a strict reader.
455
+ for (const bad of ['MCP_Manage', 'MCP-manage', 'mcp_manage', '-mcp', 'mcp-', 'mcp--manage', 'mcp manage']) {
456
+ assert.ok(!isValidSkillName(bad), `\`${bad}\` must not be a valid skill name`);
457
+ }
458
+ for (const good of ['mcp-manage', 'ask-tim', 'a', 'skill2', 'a-b-c-1']) {
459
+ assert.ok(isValidSkillName(good), `\`${good}\` must be a valid skill name`);
460
+ }
461
+ assert.ok(isValidSkillName('a'.repeat(NAME_MAX)), 'a 64-char name is at the limit and valid');
462
+ assert.ok(!isValidSkillName('a'.repeat(NAME_MAX + 1)), 'a 65-char name is over the limit');
463
+
389
464
  console.log('βœ“ selftest passed');
390
465
  }
391
466
 
@@ -0,0 +1,116 @@
1
+ ---
2
+ name: ao-orchestrator
3
+ description: Use when acting as the multi-project orchestrator and lead coordinator across repositories using the Agent Orchestrator (AO) daemon. Spawns, inspects, coordinates, and reviews parallel coding agents in isolated Git worktrees.
4
+ category: bdb-core
5
+ risk: safe
6
+ tools:
7
+ - claude-code
8
+ - antigravity
9
+ - opencode
10
+ - cursor
11
+ - codex-cli
12
+ ---
13
+
14
+ # πŸ‘‘ AO Multi-Project Orchestrator (`/ao-orchestrator`)
15
+
16
+ ## Overview
17
+
18
+ This skill equips any AI coding agent across all supported harnesses (**Claude Code**, **Google Antigravity**, **OpenCode**, **Cursor**, **Codex**) to act as a **Multi-Project Orchestrator** supervising tasks across independent code repositories via the **Agent Orchestrator (AO)** background daemon (`~/.local/bin/ao`).
19
+
20
+ Instead of making changes directly across multiple repositories within a single context window, the Orchestrator breaks down high-level business goals into scoped work items, delegates them to specialized worker agents running in isolated Git worktrees, monitors their progress, and reviews/integrates their Pull Requests.
21
+
22
+ ---
23
+
24
+ ## 🧭 Orchestrator Responsibilities
25
+
26
+ 1. **Project Discovery & Mapping**: Identify which repositories and workspaces are involved in the user's goal.
27
+ 2. **Task Decomposition**: Split cross-repo features into clear, atomic specifications for individual worker sessions.
28
+ 3. **Session Lifecycle Management**: Spawn worker agents with explicit roles (`architect`, `techlead`, `ui_ux`, `engineering`, `reviewer`, `shipping`), appropriate harnesses (`claude-code`, `opencode`, `agy`), and specific prompts.
29
+ 4. **Coordination & Supervision**: Track running sessions via `ao session ls`, inspect agent logs, and inject steering instructions or clarifications via `ao send`.
30
+ 5. **Quality Gate & PR Review**: Run `ao review` once a worker completes its task, verify tests, and coordinate cross-project integration.
31
+
32
+ ---
33
+
34
+ ## πŸ› οΈ AO CLI Core Command Suite
35
+
36
+ The Orchestrator interacts with the local daemon (listening on loopback port `3101`) strictly through the `ao` CLI:
37
+
38
+ ### 1. Discovery & Status
39
+ ```bash
40
+ # Check AO daemon health and version
41
+ ao status
42
+
43
+ # List all registered repositories and workspaces
44
+ ao project ls
45
+
46
+ # List active and recent agent sessions across all projects
47
+ ao session ls
48
+ ```
49
+
50
+ ### 2. Spawning Multi-Project Workers
51
+ Run worker agents in fresh, isolated Git worktrees (`ao/<session-id>/root`) so they never conflict with uncommitted working trees:
52
+
53
+ ```bash
54
+ # Spawn a Backend Engineer in Project A
55
+ ao spawn \
56
+ --project <project-id-or-path> \
57
+ --name "Backend-API" \
58
+ --role engineering \
59
+ --harness claude-code \
60
+ --prompt "Implement the OAuth2 callback handler per specification in issue #42. Ensure all tests pass."
61
+
62
+ # Spawn a Frontend Designer/Engineer in Project B
63
+ ao spawn \
64
+ --project <project-id-or-path> \
65
+ --name "Frontend-UI" \
66
+ --role ui_ux \
67
+ --harness claude-code \
68
+ --prompt "Build the settings page OAuth connection cards with Tailwind and React."
69
+
70
+ # Spawn an Adversarial Reviewer for an existing worker branch
71
+ ao spawn \
72
+ --project <project-id-or-path> \
73
+ --name "Audit-Worker" \
74
+ --role reviewer \
75
+ --prompt "Review branch ao/<session-id>/root for security gaps, unhandled errors, and contract compliance."
76
+ ```
77
+
78
+ ### 3. Monitoring & Steering Sessions
79
+ ```bash
80
+ # Inspect detailed state of a specific session
81
+ ao session get <session-id>
82
+
83
+ # Send instructions, feedback, or corrections to a running worker
84
+ ao send <session-id> "The database migration must support SQLite and Postgres. Please update the schema."
85
+
86
+ # Switch agent harness if needed (e.g. switch to opencode or agy)
87
+ ao session switch-agent <session-id> --to opencode
88
+ ```
89
+
90
+ ### 4. Review & Completion
91
+ ```bash
92
+ # Trigger an AO code review of the worker's changes
93
+ ao review <session-id>
94
+
95
+ # Clean up or terminate completed sessions
96
+ ao session kill <session-id>
97
+ ao session cleanup
98
+ ```
99
+
100
+ ---
101
+
102
+ ## πŸ“‹ Multi-Project Orchestration Protocol
103
+
104
+ When the user asks you to coordinate work across multiple projects:
105
+
106
+ 1. **Step 1: Check Registered Projects**
107
+ Run `ao project ls` to verify the repositories exist in AO. If a project is not registered, instruct the user to register it or navigate to the directory and run `ao project add .`.
108
+ 2. **Step 2: Propose the Architecture & Work Breakdown**
109
+ Present a clear plan to the user:
110
+ - Which repo needs what changes.
111
+ - What workers will be spawned and with which AOS roles.
112
+ - The dependency order (e.g. Backend API first, then Frontend integration).
113
+ 3. **Step 3: Spawn Workers Orderly**
114
+ Spawn the prerequisite workers. Avoid spawning dependent workers before the contract/API they depend on is established.
115
+ 4. **Step 4: Report Progress to User**
116
+ Provide regular, concise summaries in your response showing the status of each spawned session and next actions.
@@ -1,6 +1,11 @@
1
1
  ---
2
2
  name: agenttrail
3
- description: Live map of a multi-agent build in the browser: which plan component is being worked on, by which agent or harness, what is done and what is stuck. Use when a multi-agent pipeline starts (/startcycle, /startcycle-graph, /teamwork-preview) or after a plan-canvas approve, or when the user asks to see what the agents are doing.
3
+ description: >-
4
+ Live map of a multi-agent build in the browser: which plan component is being
5
+ worked on, by which agent or harness, what is done and what is stuck. Use when
6
+ a multi-agent pipeline starts (/startcycle, /startcycle-graph,
7
+ /teamwork-preview) or after a plan-canvas approve, or when the user asks to
8
+ see what the agents are doing.
4
9
  category: bdb-core
5
10
  metadata:
6
11
  version: "0.2.0"
@@ -294,9 +294,9 @@ Use these for 3D, motion, video and live show control.
294
294
  * **Top Picks:** `godmode-media-creation` (video and montage), `godmode-eventtech` (live shows), `godmode-3d-creation` (meshes and scenes)
295
295
 
296
296
  * **Godmodes**: Determine the overarching flow (3D, Media, EventTech).
297
- * **Implementations**: `MCP_Manage` drives the creative applications over MCP, `spline-3d-integration` (web 3D), `threejs-skills` (WebGL), `remotion` (React β†’ MP4, deterministic frame counts).
297
+ * **Implementations**: `mcp-manage` drives the creative applications over MCP, `spline-3d-integration` (web 3D), `threejs-skills` (WebGL), `remotion` (React β†’ MP4, deterministic frame counts).
298
298
 
299
- * **Per-application MCP guides**: once `MCP_Manage` has told you *which* server to use, these document the tool surface of one application each β€” `bdb-touchdesigner-mcp`, `bdb-resolume-mcp`, `bdb-grandma3-mcp`, `bdb-davinci-mcp`, `bdb-adobe-suite-mcp`, `bdb-after-effects-mcp`, `bdb-blender-mcp`, `bdb-unreal-mcp`, `bdb-rhino-mcp`, `bdb-vectorworks-mcp`. Reach for one only when you already know the application; `MCP_Manage` is the way in.
299
+ * **Per-application MCP guides**: once `mcp-manage` has told you *which* server to use, these document the tool surface of one application each β€” `bdb-touchdesigner-mcp`, `bdb-resolume-mcp`, `bdb-grandma3-mcp`, `bdb-davinci-mcp`, `bdb-adobe-suite-mcp`, `bdb-after-effects-mcp`, `bdb-blender-mcp`, `bdb-unreal-mcp`, `bdb-rhino-mcp`, `bdb-vectorworks-mcp`. Reach for one only when you already know the application; `mcp-manage` is the way in.
300
300
 
301
301
  ### Which video route?
302
302
 
@@ -305,8 +305,8 @@ The choice is driven by where the pixels come from, not by the output format β€”
305
305
  | Source material | Route |
306
306
  |---|---|
307
307
  | Code-generated motion graphics, text, brand animation | `remotion` β€” React components rendered to MP4, deterministic and exactly frame-accurate |
308
- | Existing footage: cutting, colour, beat-sync | `godmode-media-creation` + `MCP_Manage` β†’ **DaVinci Resolve** (`davinci-resolve-mcp`) or **Adobe Premiere** (`adobe_uxp_mcp`) |
309
- | Compositing, motion design over footage | `MCP_Manage` β†’ **After Effects** (`ae-mcp`, `after-effects-mcp`), or **Photoshop** for stills (`adobe_uxp_mcp`) |
308
+ | Existing footage: cutting, colour, beat-sync | `godmode-media-creation` + `mcp-manage` β†’ **DaVinci Resolve** (`davinci-resolve-mcp`) or **Adobe Premiere** (`adobe_uxp_mcp`) |
309
+ | Compositing, motion design over footage | `mcp-manage` β†’ **After Effects** (`ae-mcp`, `after-effects-mcp`), or **Photoshop** for stills (`adobe_uxp_mcp`) |
310
310
  | Generative visuals: audio-reactive, shaders, real-time | `godmode-eventtech` β†’ TouchDesigner MCP, then `record_movie` |
311
311
  | Generative *assets*: textβ†’3D, imageβ†’3D, AI video | The **Creator Extension** engines β€” TRELLIS and TripoSR (3D), Text-to-CAD, OpenMontage (multimodal montage), Video-Shotcraft (shot direction), Palmier-Pro (timeline and grading), driven through `comfyui-mcp`. Installed as a separate power-up module, not a skill in this catalogue. |
312
312
  | Concept not settled yet | `bdbmediastorm` first β€” it runs the grilling interview for show-control and media work |