@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.
- package/.agents/{agents.md → AGENTS.md} +3 -1
- package/.agents/nodes.json +3 -1
- package/.agents/vendor-manifest.json +23 -1
- package/.claude/agents/godmode-media-eventtech.md +1 -1
- package/.claude/hooks/conventional-commits.mjs +125 -0
- package/.claude/hooks/env-file-protection.mjs +105 -0
- package/.claude/hooks/go-gate.mjs +101 -81
- package/.claude/hooks/memb-inject.mjs +29 -1
- package/.claude/settings.json +13 -0
- package/.claude/workflows/startcycle-dispatch.mjs +23 -1
- package/.opencode/agents/godmode-media-eventtech.md +1 -1
- package/.opencode/plugins/bdb-aos.js +31 -4
- package/CLAUDE.md +0 -571
- package/README.de.md +1 -1
- package/README.md +1 -1
- package/README.pt.md +1 -1
- package/THIRD_PARTY_NOTICES.md +126 -0
- package/bin/aos-doctor.mjs +1 -1
- package/docs/skills_table.md +1 -1
- package/installer.js +187 -55
- package/package.json +7 -3
- package/packages/aos-cli/README.md +80 -0
- package/packages/aos-cli/bin/aos-cli.mjs +134 -0
- package/packages/aos-cli/core-skills.json +12 -0
- package/packages/aos-cli/extensions/aos.ts +321 -0
- package/packages/aos-cli/package-lock.json +1923 -0
- package/packages/aos-cli/package.json +29 -0
- package/packages/aos-cli/scripts/check-theme.mjs +63 -0
- package/packages/aos-cli/themes/aos.json +97 -0
- package/scripts/build-plugin-manifest.mjs +131 -0
- package/scripts/validate-skills.mjs +81 -6
- package/skills/basic/ao-orchestrator/SKILL.md +116 -0
- package/skills/basic/bdb-eventagency-skill/SKILL.md +252 -0
- package/skills/basic/bdb-shipping-skill/SKILL.md +161 -0
- package/skills/basic/godmode-eventtech/SKILL.md +4 -1
- package/skills/global_config/agenttrail/SKILL.md +6 -1
- package/skills/global_config/aos-project-init/SKILL.md +2 -0
- package/skills/global_config/aos-project-init/assets/AGENTS.template.md +1 -1
- package/skills/global_config/aos-project-init/scripts/aos-project-doctor.mjs +1 -1
- package/skills/global_config/aos-setup/SKILL.md +1 -1
- package/skills/global_config/aos-setup/scripts/aos-doctor.mjs +1 -1
- package/skills/global_config/ask-tim/SKILL.md +7 -7
- package/skills/global_config/bash-script-generator/SKILL.md +201 -0
- package/skills/global_config/bash-script-generator/assets/templates/standard-template.sh +96 -0
- package/skills/global_config/bash-script-generator/docs/bash-scripting-guide.md +729 -0
- package/skills/global_config/bash-script-generator/docs/generation-best-practices.md +193 -0
- package/skills/global_config/bash-script-generator/docs/script-patterns.md +566 -0
- package/skills/global_config/bash-script-generator/docs/text-processing-guide.md +437 -0
- package/skills/global_config/bash-script-generator/examples/log-analyzer.sh +92 -0
- package/skills/global_config/bash-script-generator/scripts/generate_script_template.sh +123 -0
- package/skills/global_config/bash-script-generator/scripts/run_ci_checks.sh +172 -0
- package/skills/global_config/bash-script-generator/scripts/test_generator.sh +413 -0
- package/skills/global_config/bash-script-validator/SKILL.md +249 -0
- package/skills/global_config/bash-script-validator/docs/awk-reference.md +449 -0
- package/skills/global_config/bash-script-validator/docs/bash-reference.md +468 -0
- package/skills/global_config/bash-script-validator/docs/common-mistakes.md +623 -0
- package/skills/global_config/bash-script-validator/docs/grep-reference.md +395 -0
- package/skills/global_config/bash-script-validator/docs/regex-reference.md +391 -0
- package/skills/global_config/bash-script-validator/docs/sed-reference.md +454 -0
- package/skills/global_config/bash-script-validator/docs/shell-reference.md +463 -0
- package/skills/global_config/bash-script-validator/docs/shellcheck-reference.md +399 -0
- package/skills/global_config/bash-script-validator/examples/bad-bash.sh +55 -0
- package/skills/global_config/bash-script-validator/examples/bad-shell.sh +54 -0
- package/skills/global_config/bash-script-validator/examples/good-bash.sh +71 -0
- package/skills/global_config/bash-script-validator/examples/good-shell.sh +69 -0
- package/skills/global_config/bash-script-validator/scripts/run_ci_checks.sh +23 -0
- package/skills/global_config/bash-script-validator/scripts/shellcheck_wrapper.sh +174 -0
- package/skills/global_config/bash-script-validator/scripts/test_validate.sh +446 -0
- package/skills/global_config/bash-script-validator/scripts/validate.sh +512 -0
- package/skills/global_config/ci-pipeline/SKILL.md +135 -0
- package/skills/global_config/deja-memory/SKILL.md +3 -1
- package/skills/global_config/dispatching-parallel-agents/SKILL.md +170 -0
- package/skills/global_config/dockerfile-generator/SKILL.md +1038 -0
- package/skills/global_config/dockerfile-generator/examples/example.dockerignore +95 -0
- package/skills/global_config/dockerfile-generator/examples/golang-distroless.Dockerfile +34 -0
- package/skills/global_config/dockerfile-generator/examples/java-springboot.Dockerfile +45 -0
- package/skills/global_config/dockerfile-generator/examples/nextjs-production.Dockerfile +49 -0
- package/skills/global_config/dockerfile-generator/examples/nodejs-multistage.Dockerfile +55 -0
- package/skills/global_config/dockerfile-generator/examples/python-fastapi.Dockerfile +48 -0
- package/skills/global_config/dockerfile-generator/references/language_specific_guides.md +510 -0
- package/skills/global_config/dockerfile-generator/references/multistage_builds.md +570 -0
- package/skills/global_config/dockerfile-generator/references/optimization_patterns.md +492 -0
- package/skills/global_config/dockerfile-generator/references/security_best_practices.md +375 -0
- package/skills/global_config/dockerfile-generator/scripts/generate_dockerignore.sh +199 -0
- package/skills/global_config/dockerfile-generator/scripts/generate_golang.sh +172 -0
- package/skills/global_config/dockerfile-generator/scripts/generate_java.sh +185 -0
- package/skills/global_config/dockerfile-generator/scripts/generate_nodejs.sh +279 -0
- package/skills/global_config/dockerfile-generator/scripts/generate_python.sh +218 -0
- package/skills/global_config/dockerfile-generator/scripts/test_generator.sh +210 -0
- package/skills/global_config/dockerfile-validator/SKILL.md +300 -0
- package/skills/global_config/dockerfile-validator/examples/.dockerignore.example +34 -0
- package/skills/global_config/dockerfile-validator/examples/bad-example.Dockerfile +37 -0
- package/skills/global_config/dockerfile-validator/examples/golang-distroless.Dockerfile +50 -0
- package/skills/global_config/dockerfile-validator/examples/good-example.Dockerfile +52 -0
- package/skills/global_config/dockerfile-validator/examples/python-optimized.Dockerfile +53 -0
- package/skills/global_config/dockerfile-validator/examples/security-issues.Dockerfile +42 -0
- package/skills/global_config/dockerfile-validator/references/docker_best_practices.md +348 -0
- package/skills/global_config/dockerfile-validator/references/optimization_guide.md +473 -0
- package/skills/global_config/dockerfile-validator/references/security_checklist.md +208 -0
- package/skills/global_config/dockerfile-validator/scripts/dockerfile-validate.sh +699 -0
- package/skills/global_config/dockerfile-validator/scripts/test_validate.sh +35 -0
- package/skills/global_config/dockerfile-validator/tests/fixtures/copy-before-yarn-lock-read.Dockerfile +6 -0
- package/skills/global_config/dockerfile-validator/tests/fixtures/copy-before-yarn.Dockerfile +6 -0
- package/skills/global_config/dockerfile-validator/tests/fixtures/from-platform-nonroot.Dockerfile +7 -0
- package/skills/global_config/dockerfile-validator/tests/test_regression.sh +164 -0
- package/skills/global_config/finishing-a-development-branch/SKILL.md +228 -0
- package/skills/global_config/github-actions-generator/SKILL.md +353 -0
- package/skills/global_config/github-actions-generator/assets/templates/action/composite/action.yml +82 -0
- package/skills/global_config/github-actions-generator/assets/templates/action/docker/Dockerfile +25 -0
- package/skills/global_config/github-actions-generator/assets/templates/action/docker/action.yml +42 -0
- package/skills/global_config/github-actions-generator/assets/templates/action/docker/entrypoint.sh +27 -0
- package/skills/global_config/github-actions-generator/assets/templates/action/javascript/action.yml +33 -0
- package/skills/global_config/github-actions-generator/assets/templates/action/javascript/index.js +50 -0
- package/skills/global_config/github-actions-generator/assets/templates/action/javascript/package.json +27 -0
- package/skills/global_config/github-actions-generator/assets/templates/workflow/basic_workflow.yml +242 -0
- package/skills/global_config/github-actions-generator/assets/templates/workflow/reusable_workflow.yml +106 -0
- package/skills/global_config/github-actions-generator/examples/README.md +147 -0
- package/skills/global_config/github-actions-generator/examples/actions/setup-node-cached/action.yml +93 -0
- package/skills/global_config/github-actions-generator/examples/caching/docker-buildkit.yml +256 -0
- package/skills/global_config/github-actions-generator/examples/security/dependency-review.yml +62 -0
- package/skills/global_config/github-actions-generator/examples/security/sbom-attestation.yml +119 -0
- package/skills/global_config/github-actions-generator/examples/triggers/chatops-commands.yml +475 -0
- package/skills/global_config/github-actions-generator/examples/triggers/repository-dispatch.yml +418 -0
- package/skills/global_config/github-actions-generator/examples/triggers/workflow-orchestration.yml +404 -0
- package/skills/global_config/github-actions-generator/examples/workflows/docker-build-push.yml +68 -0
- package/skills/global_config/github-actions-generator/examples/workflows/go-ci.yml +161 -0
- package/skills/global_config/github-actions-generator/examples/workflows/monorepo-ci.yml +340 -0
- package/skills/global_config/github-actions-generator/examples/workflows/multi-environment-deploy.yml +406 -0
- package/skills/global_config/github-actions-generator/examples/workflows/nodejs-ci.yml +122 -0
- package/skills/global_config/github-actions-generator/examples/workflows/python-ci.yml +157 -0
- package/skills/global_config/github-actions-generator/examples/workflows/scheduled-tasks.yml +376 -0
- package/skills/global_config/github-actions-generator/references/advanced-triggers.md +917 -0
- package/skills/global_config/github-actions-generator/references/best-practices.md +755 -0
- package/skills/global_config/github-actions-generator/references/common-actions.md +715 -0
- package/skills/global_config/github-actions-generator/references/custom-actions.md +320 -0
- package/skills/global_config/github-actions-generator/references/expressions-and-contexts.md +688 -0
- package/skills/global_config/github-actions-generator/references/modern-features.md +421 -0
- package/skills/global_config/github-actions-generator/scripts/test_generator.sh +344 -0
- package/skills/global_config/github-actions-templates/SKILL.md +7 -0
- package/skills/global_config/github-actions-validator/SKILL.md +576 -0
- package/skills/global_config/github-actions-validator/examples/README.md +88 -0
- package/skills/global_config/github-actions-validator/examples/outdated-versions.yml +76 -0
- package/skills/global_config/github-actions-validator/examples/valid-ci.yml +79 -0
- package/skills/global_config/github-actions-validator/examples/with-errors.yml +47 -0
- package/skills/global_config/github-actions-validator/references/act_usage.md +233 -0
- package/skills/global_config/github-actions-validator/references/action_versions.md +122 -0
- package/skills/global_config/github-actions-validator/references/actionlint_usage.md +343 -0
- package/skills/global_config/github-actions-validator/references/common_errors.md +512 -0
- package/skills/global_config/github-actions-validator/references/modern_features.md +384 -0
- package/skills/global_config/github-actions-validator/references/runners.md +317 -0
- package/skills/global_config/github-actions-validator/scripts/install_tools.sh +113 -0
- package/skills/global_config/github-actions-validator/scripts/validate_workflow.sh +910 -0
- package/skills/global_config/github-actions-validator/tests/test_validate_workflow.sh +237 -0
- package/skills/global_config/makefile-generator/SKILL.md +614 -0
- package/skills/global_config/makefile-generator/assets/templates/.gitkeep +1 -0
- package/skills/global_config/makefile-generator/docs/makefile-structure.md +530 -0
- package/skills/global_config/makefile-generator/docs/optimization-guide.md +784 -0
- package/skills/global_config/makefile-generator/docs/patterns-guide.md +642 -0
- package/skills/global_config/makefile-generator/docs/security-guide.md +361 -0
- package/skills/global_config/makefile-generator/docs/targets-guide.md +642 -0
- package/skills/global_config/makefile-generator/docs/variables-guide.md +596 -0
- package/skills/global_config/makefile-generator/scripts/add_standard_targets.sh +539 -0
- package/skills/global_config/makefile-generator/scripts/generate_makefile_template.sh +690 -0
- package/skills/global_config/makefile-generator/test/test_helper_scripts.sh +190 -0
- package/skills/global_config/makefile-validator/SKILL.md +244 -0
- package/skills/global_config/makefile-validator/docs/bake-tool.md +1000 -0
- package/skills/global_config/makefile-validator/docs/best-practices.md +858 -0
- package/skills/global_config/makefile-validator/docs/common-mistakes.md +944 -0
- package/skills/global_config/makefile-validator/examples/bad-makefile.mk +77 -0
- package/skills/global_config/makefile-validator/examples/good-makefile.mk +103 -0
- package/skills/global_config/makefile-validator/scripts/test_validate.sh +382 -0
- package/skills/global_config/makefile-validator/scripts/validate_makefile.sh +712 -0
- package/skills/global_config/{MCP_Manage → mcp-manage}/SKILL.md +3 -3
- package/skills/global_config/plan-canvas/SKILL.md +9 -2
- package/skills/global_config/plan-canvas/scripts/lib/plan-canvas/ui.js +10 -2
- package/skills/global_config/plan-canvas/scripts/plan-canvas.js +1 -1
- package/skills/global_config/read-the-damn-docs/SKILL.md +175 -0
- package/skills/global_config/requesting-code-review/SKILL.md +98 -0
- package/skills/global_config/requesting-code-review/code-reviewer.md +198 -0
- package/skills/global_config/using-git-worktrees/SKILL.md +170 -0
- package/skills/global_config/verification-before-completion/SKILL.md +123 -0
- package/skills/global_config/writing-plans/SKILL.md +126 -46
- package/skills/global_config/writing-plans-legacy/SKILL.md +152 -0
- package/.claude/CLAUDE.md +0 -12
- package/mcps/RhinoMCP/docs/content/docs/getting-started/gemini.md +0 -61
- /package/{GEMINI.md → RULES.md} +0 -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 === '"'
|
|
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
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
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.
|