@hybridlabor-api/aos 4.13.2 → 4.14.1

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 (151) hide show
  1. package/.agents/AGENTS.md +8 -0
  2. package/.agents/nodes.json +5 -2
  3. package/.claude/hooks/conventional-commits.mjs +14 -15
  4. package/.claude/hooks/env-file-protection.mjs +14 -15
  5. package/.claude/hooks/go-gate.mjs +152 -10
  6. package/.claude/hooks/go-token.mjs +55 -0
  7. package/.claude/hooks/memb-inject.mjs +75 -62
  8. package/.claude/hooks/trail-autostart.mjs +27 -0
  9. package/.claude/hooks/trail-relay.mjs +1 -0
  10. package/.claude/settings.json +22 -4
  11. package/.claude/workflows/startcycle-dispatch.mjs +11 -4
  12. package/.opencode/plugins/bdb-aos.js +98 -121
  13. package/.opencode/plugins/lib/trail-autostart.js +38 -0
  14. package/CLAUDE.md +1 -1
  15. package/README.de.md +6 -6
  16. package/README.md +6 -6
  17. package/README.pt.md +6 -6
  18. package/THIRD_PARTY_NOTICES.md +19 -3
  19. package/assets/header-v5.png +0 -0
  20. package/bin/aos-acp.mjs +211 -0
  21. package/bin/aos-doctor.mjs +1 -1
  22. package/bin/aos-uninstall.mjs +2 -2
  23. package/docs/master-session-acp.md +51 -0
  24. package/installer.js +314 -42
  25. package/mcps/mcsc/packages/mcp/server.js +6 -7
  26. package/package.json +4 -3
  27. package/scripts/validate-skills.mjs +76 -0
  28. package/skills/basic/bdbmediastorm/SKILL.md +1 -1
  29. package/skills/basic/godmode-shipping/SKILL.md +3 -0
  30. package/skills/basic/master-session/SKILL.md +89 -0
  31. package/skills/basic/startcycle/SKILL.md +1 -1
  32. package/skills/basic/startcycle-graph/SKILL.md +2 -2
  33. package/skills/basic/startcycle-graph-user/SKILL.md +1 -1
  34. package/skills/basic/teamwork-preview/SKILL.md +1 -1
  35. package/skills/bdbrainstorm/SKILL.md +7 -1
  36. package/skills/global_config/agentic-harness-patterns/SKILL.md +257 -0
  37. package/skills/global_config/agentic-harness-patterns/metadata.json +10 -0
  38. package/skills/global_config/agentic-harness-patterns/references/agent-orchestration-pattern.md +97 -0
  39. package/skills/global_config/agentic-harness-patterns/references/bootstrap-sequence-pattern.md +106 -0
  40. package/skills/global_config/agentic-harness-patterns/references/context-engineering/compress-pattern.md +78 -0
  41. package/skills/global_config/agentic-harness-patterns/references/context-engineering/isolate-pattern.md +82 -0
  42. package/skills/global_config/agentic-harness-patterns/references/context-engineering/select-pattern.md +86 -0
  43. package/skills/global_config/agentic-harness-patterns/references/context-engineering-pattern.md +29 -0
  44. package/skills/global_config/agentic-harness-patterns/references/hook-lifecycle-pattern.md +111 -0
  45. package/skills/global_config/agentic-harness-patterns/references/memory-persistence-pattern.md +109 -0
  46. package/skills/global_config/agentic-harness-patterns/references/permission-gate-pattern.md +111 -0
  47. package/skills/global_config/agentic-harness-patterns/references/skill-runtime-pattern.md +104 -0
  48. package/skills/global_config/agentic-harness-patterns/references/task-decomposition-pattern.md +92 -0
  49. package/skills/global_config/agentic-harness-patterns/references/tool-registry-pattern.md +101 -0
  50. package/skills/global_config/agenttrail/SKILL.md +8 -0
  51. package/skills/global_config/agenttrail/bin/agenttrail.mjs +14 -0
  52. package/skills/global_config/agenttrail/bin/ensure.mjs +118 -0
  53. package/skills/global_config/aos-setup/scripts/aos-doctor.mjs +1 -1
  54. package/skills/global_config/bdb-visual-edit/SKILL.md +51 -0
  55. package/skills/global_config/bdb-visual-edit/references/vite-react-source-attr.md +59 -0
  56. package/skills/global_config/bdb-visual-edit/scripts/pick-snippet.js +27 -0
  57. package/skills/global_config/bdb-visual-edit/scripts/sanitize-element.mjs +123 -0
  58. package/skills/global_config/factory-collect/SKILL.md +74 -0
  59. package/skills/global_config/factory-human-digest/SKILL.md +92 -0
  60. package/skills/global_config/factory-lookback/SKILL.md +95 -0
  61. package/skills/global_config/factory-review-prs/SKILL.md +63 -0
  62. package/skills/global_config/git-pr-review/SKILL.md +3 -0
  63. package/skills/global_config/grilling/SKILL.md +2 -0
  64. package/skills/global_config/mcsc/SKILL.md +1 -1
  65. package/skills/global_config/plan-arbiter/SKILL.md +125 -0
  66. package/skills/global_config/plan-canvas/SKILL.md +62 -5
  67. package/skills/global_config/plan-canvas/scripts/lib/loopback-guard.js +19 -3
  68. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/README.md +285 -0
  69. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/agent-trail.js +129 -0
  70. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/board-client.js +124 -0
  71. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/examples/demo-plan/canvas.mdx +19 -0
  72. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/examples/demo-plan/plan.mdx +18 -0
  73. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/examples/recap-demo/plan.mdx +72 -0
  74. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/examples/showcase/README.md +29 -0
  75. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/examples/showcase/architecture.json +30 -0
  76. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/examples/showcase/builder/00_architecture.html +14950 -0
  77. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/examples/showcase/builder/canvas.mdx +511 -0
  78. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/examples/showcase/builder/plan.mdx +208 -0
  79. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/examples/showcase/recap/plan.mdx +102 -0
  80. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/examples/showcase/standard/plan.md +136 -0
  81. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/examples/signup-storyboard/canvas.mdx +124 -0
  82. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/examples/signup-storyboard/plan.mdx +37 -0
  83. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/index.js +188 -0
  84. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/kit.js +123 -0
  85. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/mdx.js +411 -0
  86. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/render.js +1291 -0
  87. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/templates/architecture/meta.json +1 -0
  88. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/templates/architecture/plan.mdx +195 -0
  89. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/templates/architecture/standard.md +95 -0
  90. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/templates/bugfix/meta.json +1 -0
  91. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/templates/bugfix/plan.mdx +105 -0
  92. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/templates/bugfix/standard.md +76 -0
  93. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/templates/feature/canvas.mdx +81 -0
  94. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/templates/feature/meta.json +1 -0
  95. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/templates/feature/plan.mdx +145 -0
  96. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/templates/feature/standard.md +76 -0
  97. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/templates/migration/meta.json +1 -0
  98. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/templates/migration/plan.mdx +172 -0
  99. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/templates/migration/standard.md +100 -0
  100. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/templates/recap/meta.json +1 -0
  101. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/templates/recap/plan.mdx +67 -0
  102. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/templates/recap/standard.md +49 -0
  103. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/templates/recap-board/canvas.mdx +63 -0
  104. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/templates/recap-board/meta.json +1 -0
  105. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/templates/recap-board/plan.mdx +49 -0
  106. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/templates/recap-board/standard.md +39 -0
  107. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/templates/recap-review/meta.json +1 -0
  108. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/templates/recap-review/plan.mdx +118 -0
  109. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/templates/recap-review/standard.md +57 -0
  110. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/templates/release/meta.json +1 -0
  111. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/templates/release/plan.mdx +173 -0
  112. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/templates/release/standard.md +96 -0
  113. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/templates/research/meta.json +1 -0
  114. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/templates/research/plan.mdx +91 -0
  115. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/templates/research/standard.md +54 -0
  116. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/templates/show-control/canvas.mdx +53 -0
  117. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/templates/show-control/meta.json +1 -0
  118. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/templates/show-control/plan.mdx +225 -0
  119. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/templates/show-control/standard.md +111 -0
  120. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/theme.css +472 -0
  121. package/skills/global_config/plan-canvas/scripts/lib/plan-builder/trail.js +216 -0
  122. package/skills/global_config/plan-canvas/scripts/lib/plan-canvas/markdown.js +1 -1
  123. package/skills/global_config/plan-canvas/scripts/lib/plan-canvas/server.js +37 -4
  124. package/skills/global_config/plan-canvas/scripts/lib/plan-canvas/ui.js +125 -29
  125. package/skills/global_config/plan-canvas/scripts/plan-canvas.js +196 -8
  126. package/skills/global_config/pr-recap/SKILL.md +47 -0
  127. package/skills/global_config/pr-recap/scripts/pr-recap.mjs +200 -0
  128. package/skills/global_config/quick-recap/SKILL.md +55 -0
  129. package/skills/global_config/stay-within-limits/SKILL.md +85 -0
  130. package/skills/global_config/triage/SKILL.md +3 -0
  131. package/skills/global_config/visual-edit/README.md +96 -0
  132. package/skills/global_config/visual-edit/SKILL.md +615 -0
  133. package/skills/global_config/visual-plan/README.md +93 -0
  134. package/skills/global_config/visual-plan/SKILL.md +544 -0
  135. package/skills/global_config/visual-plan/references/canvas.md +139 -0
  136. package/skills/global_config/visual-plan/references/connection.md +51 -0
  137. package/skills/global_config/visual-plan/references/document-quality.md +186 -0
  138. package/skills/global_config/visual-plan/references/exemplar.md +62 -0
  139. package/skills/global_config/visual-plan/references/local-files.md +99 -0
  140. package/skills/global_config/visual-plan/references/wireframe.md +319 -0
  141. package/skills/global_config/visual-recap/README.md +103 -0
  142. package/skills/global_config/visual-recap/SKILL.md +560 -0
  143. package/skills/global_config/visual-recap/references/connection.md +51 -0
  144. package/skills/global_config/visual-recap/references/local-files.md +99 -0
  145. package/skills/global_config/visual-recap/references/wireframe.md +319 -0
  146. package/skills/playbooks/pb-ci-fix/SKILL.md +49 -0
  147. package/skills/playbooks/pb-event-tracker/SKILL.md +45 -0
  148. package/skills/playbooks/pb-meeting-actions/SKILL.md +42 -0
  149. package/skills/playbooks/pb-project-new/SKILL.md +48 -0
  150. package/skills/playbooks/pb-week-plan/SKILL.md +45 -0
  151. package/assets/header-v4.jpg +0 -0
package/installer.js CHANGED
@@ -2609,10 +2609,7 @@ async function installOSAgentWorkspace() {
2609
2609
  if (daemonBin !== binTarget) {
2610
2610
  installStep('place the ao binary', () => {
2611
2611
  fs.mkdirSync(localBinDir, { recursive: true });
2612
- fs.copyFileSync(daemonBin, binTarget);
2613
- if (!isWin) {
2614
- fs.chmodSync(binTarget, 0o755);
2615
- }
2612
+ installBinaryAtomically(daemonBin, binTarget);
2616
2613
  log.step(`Installed ao to ${binTarget}`);
2617
2614
  }, 'AO cannot be started without its binary.');
2618
2615
  }
@@ -3320,7 +3317,16 @@ async function installMcpsForTarget(paths, ctx) {
3320
3317
  // spaces) rather than matching the first alphanumeric run anywhere in the
3321
3318
  // block, so it can't accidentally pick up a word from prose if the heading
3322
3319
  // format changes.
3323
- function parseAgentsMd(content) {
3320
+ function loadCommonSkills(dir = srcDir) {
3321
+ try {
3322
+ const reg = JSON.parse(fs.readFileSync(path.join(dir, '.agents', 'nodes.json'), 'utf8'));
3323
+ return Array.isArray(reg.common) ? reg.common.filter((s) => typeof s === 'string') : [];
3324
+ } catch {
3325
+ return [];
3326
+ }
3327
+ }
3328
+
3329
+ function parseAgentsMd(content, commonSkills = loadCommonSkills()) {
3324
3330
  const blocks = content.split(/\n## /).slice(1);
3325
3331
  const agents = [];
3326
3332
  for (const raw of blocks) {
@@ -3350,7 +3356,7 @@ function parseAgentsMd(content) {
3350
3356
  name,
3351
3357
  role: roleMatch[1].trim(),
3352
3358
  model: modelMatch ? modelMatch[1].trim() : null,
3353
- skills: extractListAfter('Primary Skills'),
3359
+ skills: [...new Set([...extractListAfter('Primary Skills'), ...commonSkills])],
3354
3360
  mcpServers: extractListAfter('MCP Servers'),
3355
3361
  output: outputMatch ? outputMatch[1].trim() : null,
3356
3362
  systemPrompt: raw.trim(),
@@ -3768,6 +3774,21 @@ function installOpencodePlugin({ targetHome = homeDir, configPath = null, data =
3768
3774
  }
3769
3775
  }
3770
3776
 
3777
+ // The plugin imports its decision logic from ./aos-hooks/ next to itself.
3778
+ const hooksSrc = path.join(srcDir, '.claude', 'hooks');
3779
+ if (fs.existsSync(hooksSrc)) {
3780
+ try {
3781
+ copyDirRecursiveSync(hooksSrc, path.join(opencodeDir, 'plugins', 'aos-hooks'));
3782
+ } catch (e) {
3783
+ log.error(`Could not install OpenCode plugin hooks (OpenCode gates inactive): ${e.message}`);
3784
+ }
3785
+ }
3786
+
3787
+ const trailLibSrc = path.join(srcDir, '.opencode', 'plugins', 'lib');
3788
+ if (fs.existsSync(trailLibSrc)) {
3789
+ try { copyDirRecursiveSync(trailLibSrc, path.join(opencodeDir, 'plugins', 'lib')); } catch (e) { log.warn(`Could not install OpenCode plugin lib: ${e.message}`); }
3790
+ }
3791
+
3771
3792
  // Slash-command payloads. Without these the /startcycle-graph command has no
3772
3793
  // native resolution and only survives as a raw-text match in the plugin.
3773
3794
  const commandsSrc = path.join(srcDir, '.opencode', 'commands');
@@ -3966,14 +3987,14 @@ function installGlobalBinaries() {
3966
3987
  // merged result goes to a .bdb-new.json sidecar -- the same recovery pattern
3967
3988
  // the MCP config merge in installMcpsForTarget uses.
3968
3989
  function mergeBdbSettingsHooks(settingsPath, { projectLocal = false } = {}) {
3969
- const bdbHookScripts = ['go-gate.mjs', 'graph-gate.mjs', 'memb-inject.mjs', 'trail-relay.mjs', 'conventional-commits.mjs', 'env-file-protection.mjs'];
3990
+ const bdbHookScripts = ['go-gate.mjs', 'go-token.mjs', 'graph-gate.mjs', 'memb-inject.mjs', 'trail-relay.mjs', 'trail-autostart.mjs', 'conventional-commits.mjs', 'env-file-protection.mjs'];
3970
3991
  // memb-inject reads the machine-global memB store under $HOME and is
3971
3992
  // installed once per machine, so it stays $HOME-anchored even inside a
3972
3993
  // project harness -- unlike the two gate hooks, which are per-checkout by
3973
3994
  // design. Pointing it at $CLAUDE_PROJECT_DIR would make it fail on every
3974
3995
  // prompt in any project the harness was never installed into. trail-relay
3975
3996
  // talks to machine-global live-map daemons, so it is anchored the same way.
3976
- const machineGlobalHooks = ['memb-inject.mjs', 'trail-relay.mjs'];
3997
+ const machineGlobalHooks = ['memb-inject.mjs', 'trail-relay.mjs', 'trail-autostart.mjs'];
3977
3998
  const isBdbEntry = (entry) => {
3978
3999
  const cmds = (entry && Array.isArray(entry.hooks) ? entry.hooks : [])
3979
4000
  .map((h) => (h && typeof h.command === 'string' ? h.command : ''))
@@ -3983,8 +4004,8 @@ function mergeBdbSettingsHooks(settingsPath, { projectLocal = false } = {}) {
3983
4004
  // Global installs must point at the copies installGlobalHooks put under
3984
4005
  // $HOME/.claude/hooks; $CLAUDE_PROJECT_DIR would not exist in other projects.
3985
4006
  const localize = (cmd) => (projectLocal
3986
- ? (machineGlobalHooks.some((n) => cmd.includes(n)) ? cmd : cmd.split('${HOME}').join('$CLAUDE_PROJECT_DIR'))
3987
- : cmd.split('$CLAUDE_PROJECT_DIR/.claude/hooks/').join('$HOME/.claude/hooks/'));
4007
+ ? (machineGlobalHooks.some((n) => cmd.includes(n)) ? cmd : cmd.split('${HOME}').join('${CLAUDE_PROJECT_DIR}').replace(/\$CLAUDE_PROJECT_DIR\b/g, '${CLAUDE_PROJECT_DIR}'))
4008
+ : cmd.replace(/\$\{?CLAUDE_PROJECT_DIR\}?\/\.claude\/hooks\//g, '$HOME/.claude/hooks/'));
3988
4009
  const cloneBdbEntries = (entries) =>
3989
4010
  JSON.parse(JSON.stringify(entries)).map((e) => ({
3990
4011
  ...e,
@@ -4046,64 +4067,111 @@ function mergeBdbSettingsHooks(settingsPath, { projectLocal = false } = {}) {
4046
4067
  }
4047
4068
  }
4048
4069
 
4070
+ // agy runs a hook command through `sh -c` / `cmd /c` with cwd = the hooks.json folder, and
4071
+ // cmd cannot parse the \" Go emits for quotes. So the command is relative and quote-free.
4072
+ function agyHookCommand(hooksJsonDir, scriptPath, args = '') {
4073
+ const rel = path.relative(hooksJsonDir, scriptPath).split(path.sep).join('/');
4074
+ if (!rel || rel.startsWith('..') || path.isAbsolute(rel) || /[\s"'&|<>^%]/.test(rel)) {
4075
+ throw new Error(`agy hook script must sit under ${hooksJsonDir} with a plain path, got ${scriptPath}`);
4076
+ }
4077
+ return `node ${rel}${args}`;
4078
+ }
4079
+
4080
+ // Runs every AOS command of a hooks.json once with `{}` on stdin, the way agy does.
4081
+ // Returns [{ command, reason }] for each failure; `spawn` is injectable for tests.
4082
+ function selfCheckAgyHooks(hooksPath, spawn = spawnSync) {
4083
+ const bdbScripts = ['go-gate.mjs', 'graph-gate.mjs', 'memb-inject.mjs', 'startcycle-dispatch.mjs', 'trail-relay.mjs', 'conventional-commits.mjs', 'env-file-protection.mjs'];
4084
+ const data = readJsonFile(hooksPath);
4085
+ const commands = [];
4086
+ const walk = (v) => {
4087
+ if (Array.isArray(v)) v.forEach(walk);
4088
+ else if (v && typeof v === 'object') {
4089
+ if (typeof v.command === 'string' && bdbScripts.some((n) => v.command.includes(n))) commands.push(v.command);
4090
+ Object.values(v).forEach(walk);
4091
+ }
4092
+ };
4093
+ walk(data && data.hooks);
4094
+ const [shell, flag] = process.platform === 'win32' ? ['cmd', '/c'] : ['sh', '-c'];
4095
+ const failures = [];
4096
+ for (const command of [...new Set(commands)]) {
4097
+ // AGENTTRAIL_PORT=1: the no-op payload must not show up on a live map.
4098
+ const r = spawn(shell, [flag, command], { cwd: path.dirname(hooksPath), input: '{}', encoding: 'utf8', timeout: 5000, windowsHide: true, env: { ...process.env, AGENTTRAIL_PORT: '1' } });
4099
+ const stderr = String((r && r.stderr) || '');
4100
+ let reason = null;
4101
+ if (!r || r.error) reason = `spawn failed: ${r && r.error ? r.error.message : 'no result'}`;
4102
+ else if (r.status !== 0) reason = `exit ${r.status}\n ${stderr.trim().slice(0, 500)}`;
4103
+ else if (/MODULE_NOT_FOUND|Cannot find module/.test(stderr)) reason = `module not found\n ${stderr.trim().slice(0, 500)}`;
4104
+ if (reason) failures.push({ command, reason });
4105
+ }
4106
+ return failures;
4107
+ }
4108
+
4049
4109
  // Merge the BDB hooks into Google Antigravity's hooks.json (.agents/hooks.json or
4050
4110
  // ~/.gemini/config/hooks.json), preserving user-defined foreign hooks.
4051
- function mergeAntigravityHooks(hooksPath, { projectLocal = false } = {}) {
4111
+ function mergeAntigravityHooks(hooksPath, { projectLocal = false, selfCheck = spawnSync } = {}) {
4052
4112
  const bdbHookScripts = ['go-gate.mjs', 'graph-gate.mjs', 'memb-inject.mjs', 'startcycle-dispatch.mjs', 'trail-relay.mjs', 'conventional-commits.mjs', 'env-file-protection.mjs'];
4053
- const isBdbEntry = (entry) => {
4054
- const cmds = (entry && Array.isArray(entry.hooks) ? entry.hooks : [entry])
4055
- .map((h) => (h && typeof h.command === 'string' ? h.command : (typeof h === 'string' ? h : '')))
4056
- .join(' ');
4057
- return bdbHookScripts.some((name) => cmds.includes(name));
4058
- };
4113
+ const isBdbHandler = (h) => typeof h?.command === 'string' && bdbHookScripts.some((name) => h.command.includes(name));
4059
4114
 
4060
4115
  const baseDir = path.dirname(hooksPath);
4061
- const hooksDir = projectLocal ? path.join(currentDir, '.agents', 'hooks') : path.join(baseDir, 'hooks');
4062
- const workflowsDir = projectLocal ? path.join(currentDir, '.agents', 'workflows') : path.join(baseDir, 'workflows');
4063
- const globalHooksDir = projectLocal ? path.join(homeDir, '.gemini', 'config', 'hooks') : hooksDir;
4064
-
4116
+ // Commands are relative to hooks.json's folder, so every script must live under it
4117
+ // (installProjectHarness copies the hooks into .agents/hooks for the project-local file).
4118
+ const hooksDir = path.join(baseDir, 'hooks');
4119
+ const workflowsDir = path.join(baseDir, 'workflows');
4120
+ const globalHooksDir = hooksDir;
4121
+
4122
+ const cmd = (dir, script, args = '') => agyHookCommand(baseDir, path.join(dir, script), args);
4123
+ // Observability hooks must never block a tool call when they cannot start.
4124
+ const obs = (dir, script, args = '') => cmd(dir, script, `${args} || exit 0`);
4065
4125
  const bdbHooks = {
4066
4126
  PreToolUse: [
4067
4127
  {
4068
4128
  matcher: "run_command|Bash",
4069
4129
  hooks: [
4070
- { type: "command", command: `node "${path.join(hooksDir, 'go-gate.mjs')}"`, timeout: 10000 },
4071
- { type: "command", command: `node "${path.join(hooksDir, 'conventional-commits.mjs')}"`, timeout: 10000 }
4130
+ { type: "command", command: cmd(hooksDir, 'go-gate.mjs'), timeout: 10 },
4131
+ { type: "command", command: cmd(hooksDir, 'conventional-commits.mjs'), timeout: 10 }
4072
4132
  ]
4073
4133
  },
4074
4134
  {
4075
4135
  matcher: "write_file|edit_file|replace|Write|Edit|MultiEdit",
4076
- hooks: [{ type: "command", command: `node "${path.join(hooksDir, 'env-file-protection.mjs')}"`, timeout: 10000 }]
4136
+ hooks: [{ type: "command", command: cmd(hooksDir, 'env-file-protection.mjs'), timeout: 10 }]
4077
4137
  },
4078
4138
  {
4079
- hooks: [{ type: "command", command: `node "${path.join(globalHooksDir, 'trail-relay.mjs')}" --agent agy --event PreToolUse`, timeout: 2000 }]
4139
+ matcher: "*",
4140
+ hooks: [{ type: "command", command: obs(globalHooksDir, 'trail-relay.mjs', ' --agent agy --event PreToolUse'), timeout: 2 }]
4080
4141
  }
4081
4142
  ],
4082
4143
  Stop: [
4083
- {
4084
- hooks: [{ type: "command", command: `node "${path.join(hooksDir, 'graph-gate.mjs')}"`, timeout: 10000 }]
4085
- },
4086
- {
4087
- hooks: [{ type: "command", command: `node "${path.join(globalHooksDir, 'trail-relay.mjs')}" --agent agy --event Stop`, timeout: 2000 }]
4088
- }
4144
+ { type: "command", command: cmd(hooksDir, 'graph-gate.mjs'), timeout: 10 },
4145
+ { type: "command", command: obs(globalHooksDir, 'trail-relay.mjs', ' --agent agy --event Stop'), timeout: 2 }
4089
4146
  ],
4090
4147
  PreInvocation: [
4091
- {
4092
- hooks: [
4093
- { type: "command", command: `node "${path.join(globalHooksDir, 'memb-inject.mjs')}"`, timeout: 8000 },
4094
- { type: "command", command: `node "${path.join(workflowsDir, 'startcycle-dispatch.mjs')}"`, timeout: 30000 }
4095
- ]
4096
- }
4148
+ { type: "command", command: obs(globalHooksDir, 'memb-inject.mjs'), timeout: 8 },
4149
+ { type: "command", command: cmd(workflowsDir, 'startcycle-dispatch.mjs'), timeout: 30 }
4097
4150
  ]
4098
4151
  };
4099
4152
 
4153
+ // Drops BDB handlers (old wrapped or current shape), keeps foreign ones, and
4154
+ // rewraps flat events so previously written `{ hooks: [...] }` entries migrate.
4155
+ const keepForeign = (event, entries) => {
4156
+ const out = [];
4157
+ for (const e of Array.isArray(entries) ? entries : []) {
4158
+ const nested = e && Array.isArray(e.hooks);
4159
+ if (bdbHooks[event][0].hooks) {
4160
+ if (!nested) { if (!isBdbHandler(e)) out.push(e); continue; }
4161
+ const kept = e.hooks.filter((h) => !isBdbHandler(h));
4162
+ if (kept.length) out.push({ ...e, hooks: kept });
4163
+ } else {
4164
+ out.push(...(nested ? e.hooks : [e]).filter((h) => !isBdbHandler(h)));
4165
+ }
4166
+ }
4167
+ return out;
4168
+ };
4169
+
4100
4170
  const buildMerged = (existing) => {
4101
4171
  const merged = existing && typeof existing === 'object' ? existing : {};
4102
4172
  merged.hooks = merged.hooks && typeof merged.hooks === 'object' ? merged.hooks : {};
4103
4173
  for (const [event, entries] of Object.entries(bdbHooks)) {
4104
- const foreignEntries = (Array.isArray(merged.hooks[event]) ? merged.hooks[event] : [])
4105
- .filter((e) => !isBdbEntry(e));
4106
- merged.hooks[event] = [...foreignEntries, ...entries];
4174
+ merged.hooks[event] = [...keepForeign(event, merged.hooks[event]), ...entries];
4107
4175
  }
4108
4176
  return merged;
4109
4177
  };
@@ -4135,7 +4203,19 @@ function mergeAntigravityHooks(hooksPath, { projectLocal = false } = {}) {
4135
4203
 
4136
4204
  try {
4137
4205
  fs.mkdirSync(path.dirname(hooksPath), { recursive: true });
4138
- fs.writeFileSync(hooksPath, JSON.stringify(buildMerged(existing), null, 2) + '\n');
4206
+ const previousRaw = existing ? fs.readFileSync(hooksPath, 'utf8') : null;
4207
+ const tmpPath = `${hooksPath}.${process.pid}.tmp`;
4208
+ fs.writeFileSync(tmpPath, JSON.stringify(buildMerged(existing), null, 2) + '\n');
4209
+ fs.renameSync(tmpPath, hooksPath);
4210
+ if (!DRY_RUN) {
4211
+ const failures = selfCheckAgyHooks(hooksPath, selfCheck);
4212
+ if (failures.length) {
4213
+ if (previousRaw === null) fs.unlinkSync(hooksPath);
4214
+ else fs.writeFileSync(hooksPath, previousRaw);
4215
+ log.warn(`Antigravity hook self-check FAILED for ${hooksPath}; the previous hooks.json was ${previousRaw === null ? 'removed (none existed)' : 'restored'}.`);
4216
+ for (const f of failures) log.warn(` command: ${f.command}\n ${f.reason}`);
4217
+ }
4218
+ }
4139
4219
  } catch (e) {
4140
4220
  log.warn(`Could not write ${hooksPath}: ${e.message}`);
4141
4221
  }
@@ -4510,6 +4590,107 @@ function shouldAutostartLaunchpad(overrides = {}) {
4510
4590
  return isDevEnvironment(overrides);
4511
4591
  }
4512
4592
 
4593
+ // Plan Canvas autostart is strictly opt-in (--autostart-plan-canvas): unlike
4594
+ // the launchpad opener it is NOT implied by a dev checkout. The server never
4595
+ // idle-exits there (AOS_PLAN_CANVAS_IDLE_MS=0 is honoured by server.js).
4596
+ const PLAN_CANVAS_LABEL = 'com.bdb.plan-canvas';
4597
+
4598
+ function shouldAutostartPlanCanvas(overrides = {}) {
4599
+ const argv = overrides.argv || process.argv;
4600
+ return argv.includes('--autostart-plan-canvas');
4601
+ }
4602
+
4603
+ function buildPlanCanvasPlist({ nodeBin, scriptPath, home, logDir }) {
4604
+ return `<?xml version="1.0" encoding="UTF-8"?>
4605
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
4606
+ <plist version="1.0">
4607
+ <dict>
4608
+ <key>Label</key>
4609
+ <string>${PLAN_CANVAS_LABEL}</string>
4610
+ <key>ProgramArguments</key>
4611
+ <array>
4612
+ <string>${nodeBin}</string>
4613
+ <string>${scriptPath}</string>
4614
+ <string>server</string>
4615
+ </array>
4616
+ <key>EnvironmentVariables</key>
4617
+ <dict>
4618
+ <key>AOS_PLAN_CANVAS_IDLE_MS</key>
4619
+ <string>0</string>
4620
+ </dict>
4621
+ <key>WorkingDirectory</key>
4622
+ <string>${home}</string>
4623
+ <key>RunAtLoad</key>
4624
+ <true/>
4625
+ <key>KeepAlive</key>
4626
+ <true/>
4627
+ <key>ThrottleInterval</key>
4628
+ <integer>30</integer>
4629
+ <key>StandardOutPath</key>
4630
+ <string>${path.join(logDir, 'plan-canvas.stdout.log')}</string>
4631
+ <key>StandardErrorPath</key>
4632
+ <string>${path.join(logDir, 'plan-canvas.stderr.log')}</string>
4633
+ </dict>
4634
+ </plist>`;
4635
+ }
4636
+
4637
+ // Same bat + hidden-vbs-in-Startup mechanism as the OpenWiki visualizer.
4638
+ function buildPlanCanvasWinFiles({ nodeBin, scriptPath, home, logDir, batPath }) {
4639
+ const out = path.join(logDir, 'plan-canvas.stdout.log');
4640
+ const err = path.join(logDir, 'plan-canvas.stderr.log');
4641
+ return {
4642
+ bat: `@echo off\r\ncd /d "${home}"\r\nset AOS_PLAN_CANVAS_IDLE_MS=0\r\n"${nodeBin}" "${scriptPath}" server >> "${out}" 2>> "${err}"\r\n`,
4643
+ vbs: `Set WshShell = CreateObject("WScript.Shell")\r\nWshShell.CurrentDirectory = "${home}"\r\nWshShell.Run """${batPath}""", 0, False\r\n`,
4644
+ };
4645
+ }
4646
+
4647
+ function installPlanCanvasAutostart(overrides = {}) {
4648
+ if (!shouldAutostartPlanCanvas(overrides)) return false;
4649
+ if ((overrides.dryRun ?? DRY_RUN)) {
4650
+ log.step('[dry-run] would register the Plan Canvas background server (Port 4519, no idle exit)');
4651
+ return false;
4652
+ }
4653
+ const home = overrides.homeDir || homeDir;
4654
+ const platform = overrides.platform || process.platform;
4655
+ const scriptPath = [
4656
+ path.join(home, '.agents', 'skills', 'plan-canvas', 'scripts', 'plan-canvas.js'),
4657
+ path.join(srcDir, 'skills', 'global_config', 'plan-canvas', 'scripts', 'plan-canvas.js'),
4658
+ ].find(p => fs.existsSync(p));
4659
+ if (!scriptPath) {
4660
+ log.warn('Plan Canvas autostart skipped: plan-canvas.js not found. Start it with: aos-plan-canvas server');
4661
+ return false;
4662
+ }
4663
+ const nodeBin = overrides.nodeBin || process.execPath;
4664
+ const logDir = path.join(home, '.agents', 'logs');
4665
+ try {
4666
+ fs.mkdirSync(logDir, { recursive: true });
4667
+ if (platform === 'darwin') {
4668
+ const plistPath = path.join(home, 'Library', 'LaunchAgents', `${PLAN_CANVAS_LABEL}.plist`);
4669
+ fs.mkdirSync(path.dirname(plistPath), { recursive: true });
4670
+ fs.writeFileSync(plistPath, buildPlanCanvasPlist({ nodeBin, scriptPath, home, logDir }));
4671
+ if (!overrides.skipLaunchctl) {
4672
+ execSync(`launchctl unload "${plistPath}" 2>/dev/null || true`, { stdio: 'ignore' });
4673
+ execSync(`launchctl load -w "${plistPath}" 2>/dev/null || true`, { stdio: 'ignore' });
4674
+ }
4675
+ log.success('Plan Canvas LaunchAgent registered (Port 4519)');
4676
+ } else if (platform === 'win32') {
4677
+ const startupDir = path.join(overrides.appData || process.env.APPDATA || path.join(home, 'AppData', 'Roaming'), 'Microsoft', 'Windows', 'Start Menu', 'Programs', 'Startup');
4678
+ fs.mkdirSync(startupDir, { recursive: true });
4679
+ const batPath = path.join(home, '.agents', 'run-plan-canvas.bat');
4680
+ const vbsPath = path.join(startupDir, `${PLAN_CANVAS_LABEL}.vbs`);
4681
+ const files = buildPlanCanvasWinFiles({ nodeBin, scriptPath, home, logDir, batPath });
4682
+ fs.writeFileSync(batPath, files.bat, 'utf-8');
4683
+ fs.writeFileSync(vbsPath, files.vbs, 'utf-8');
4684
+ if (!overrides.skipLaunchctl) spawn('wscript.exe', [vbsPath], { detached: true, stdio: 'ignore' }).unref();
4685
+ log.success('Plan Canvas Startup entry registered (Port 4519)');
4686
+ } else {
4687
+ log.step('Plan Canvas autostart is only wired for macOS and Windows. Start it with: aos-plan-canvas server');
4688
+ return false;
4689
+ }
4690
+ return true;
4691
+ } catch (e) { logDebug(e, 'plan canvas autostart'); return false; }
4692
+ }
4693
+
4513
4694
  function generateAndOpenLaunchpad(installedModules = []) {
4514
4695
  if (DRY_RUN) {
4515
4696
  log.step('[dry-run] would generate & open BDB Launchpad HTML');
@@ -4645,6 +4826,16 @@ function generateAndOpenLaunchpad(installedModules = []) {
4645
4826
  .card.offline .card-hint {
4646
4827
  display: block;
4647
4828
  }
4829
+ .card-hint code {
4830
+ font-family: var(--mono);
4831
+ font-style: normal;
4832
+ color: #ffffff;
4833
+ background: #0a0a0a;
4834
+ border: 1px solid var(--accent);
4835
+ border-radius: 4px;
4836
+ padding: 1px 6px;
4837
+ cursor: copy;
4838
+ }
4648
4839
  .footer {
4649
4840
  margin-top: 28px;
4650
4841
  text-align: center;
@@ -4835,6 +5026,25 @@ function generateAndOpenLaunchpad(installedModules = []) {
4835
5026
  <span class="status-dot" id="dot-store" title="Checking..."></span>
4836
5027
  </div>
4837
5028
  </a>
5029
+ <a class="card" href="http://127.0.0.1:4519/" target="_blank">
5030
+ <div class="card-content">
5031
+ <div class="card-icon"><svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
5032
+ <defs><linearGradient id="grad-plancanvas" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#FFFFFF"/><stop offset="100%" stop-color="#9b30c4"/></linearGradient></defs>
5033
+ <rect x="18" y="22" width="64" height="56" rx="4" fill="url(#grad-plancanvas)" opacity="0.85"/>
5034
+ <rect x="26" y="30" width="22" height="14" rx="1.5" fill="#0a0a0a" opacity="0.6"/><rect x="52" y="30" width="22" height="14" rx="1.5" fill="#0a0a0a" opacity="0.6"/>
5035
+ <line x1="26" y1="54" x2="74" y2="54" stroke="#0a0a0a" stroke-width="2.5" opacity="0.5"/><line x1="26" y1="64" x2="56" y2="64" stroke="#0a0a0a" stroke-width="2.5" opacity="0.5"/>
5036
+ </svg></div>
5037
+ <div class="card-info">
5038
+ <h2>Plan Canvas</h2>
5039
+ <p>Review plans in the browser: annotate, chat, approve</p>
5040
+ <div class="card-hint">offline — run: <code data-copy="aos-plan-canvas server" title="Click to copy">aos-plan-canvas server</code></div>
5041
+ </div>
5042
+ </div>
5043
+ <div class="card-meta">
5044
+ <span class="port-pill">:4519</span>
5045
+ <span class="status-dot" id="dot-plancanvas" title="Checking..."></span>
5046
+ </div>
5047
+ </a>
4838
5048
  </div>
4839
5049
  <div class="footer">
4840
5050
  <span>Autostart Daemons • 127.0.0.1</span>
@@ -4862,7 +5072,26 @@ function generateAndOpenLaunchpad(installedModules = []) {
4862
5072
  checkHealth('http://127.0.0.1:9080', 'dot-remote');
4863
5073
  checkHealth('http://127.0.0.1:4321', 'dot-openwiki');
4864
5074
  checkHealth('http://127.0.0.1:4322', 'dot-store');
4865
- }
5075
+ checkHealth('http://127.0.0.1:4519', 'dot-plancanvas');
5076
+ }
5077
+ document.addEventListener('click', (ev) => {
5078
+ const el = ev.target.closest && ev.target.closest('[data-copy]');
5079
+ if (!el) return;
5080
+ ev.preventDefault();
5081
+ ev.stopPropagation();
5082
+ const text = el.getAttribute('data-copy');
5083
+ const fallback = () => {
5084
+ const ta = document.createElement('textarea');
5085
+ ta.value = text;
5086
+ document.body.appendChild(ta);
5087
+ ta.select();
5088
+ try { document.execCommand('copy'); } catch (e) {}
5089
+ ta.remove();
5090
+ };
5091
+ if (navigator.clipboard && navigator.clipboard.writeText) navigator.clipboard.writeText(text).catch(fallback);
5092
+ else fallback();
5093
+ el.title = 'Copied';
5094
+ }, true);
4866
5095
  checkAllHealth();
4867
5096
  setInterval(checkAllHealth, 5000);
4868
5097
  </script>
@@ -5075,6 +5304,7 @@ async function universalHarnessSync(primaryMcpConfigPath, installedModules = [])
5075
5304
  }
5076
5305
  log.success('Universal Sync Complete!');
5077
5306
  generateAndOpenLaunchpad(installedModules);
5307
+ installPlanCanvasAutostart();
5078
5308
  }
5079
5309
 
5080
5310
  async function runQuickUpdate(installState) {
@@ -5241,7 +5471,41 @@ function installAosCli() {
5241
5471
  }
5242
5472
  }
5243
5473
 
5474
+ // A running daemon may execute dest; overwriting its inode keeps stale code-signature
5475
+ // state on macOS and every new exec dies with SIGKILL. Rename gives dest a fresh inode.
5476
+ function installBinaryAtomically(src, dest) {
5477
+ const tmp = path.join(path.dirname(dest), `.${path.basename(dest)}.${process.pid}.${Date.now()}.tmp`);
5478
+ try {
5479
+ fs.copyFileSync(src, tmp);
5480
+ if (process.platform !== 'win32') fs.chmodSync(tmp, 0o755);
5481
+ fs.renameSync(tmp, dest);
5482
+ } catch (e) {
5483
+ try { fs.unlinkSync(tmp); } catch (_) {}
5484
+ throw e;
5485
+ }
5486
+ }
5487
+
5244
5488
  async function main() {
5489
+ const args = process.argv.slice(2);
5490
+ if (args.includes('--version') || args.includes('-V')) {
5491
+ console.log(pkg.version);
5492
+ return;
5493
+ }
5494
+ if (args.includes('--help') || args.includes('-h')) {
5495
+ console.log(`Usage: aos [command] [options]
5496
+
5497
+ Commands:
5498
+ store Browse and install skills
5499
+ doctor|checkup Check the installation
5500
+
5501
+ Options:
5502
+ -y, --yes Non-interactive install (implied without a TTY)
5503
+ --dry-run Show what would change
5504
+ --verbose, -v Verbose output
5505
+ -V, --version Print the version and exit
5506
+ -h, --help Print this help and exit`);
5507
+ return;
5508
+ }
5245
5509
  if (process.argv[2] === 'store') {
5246
5510
  const storeScript = path.join(srcDir, 'bin', 'aos-store.mjs');
5247
5511
  const result = spawnSync(process.execPath, [storeScript, ...process.argv.slice(3)], { stdio: 'inherit' });
@@ -5695,6 +5959,7 @@ if (require.main === module) {
5695
5959
 
5696
5960
  // Exported for tests -- requiring installer.js must not launch the TUI.
5697
5961
  module.exports = {
5962
+ installBinaryAtomically,
5698
5963
  installOSAgentWorkspace,
5699
5964
  downloadOrUpdateModule,
5700
5965
  detectPlatforms,
@@ -5704,6 +5969,8 @@ module.exports = {
5704
5969
  keepExistingEnvValues,
5705
5970
  mergeBdbSettingsHooks,
5706
5971
  mergeAntigravityHooks,
5972
+ agyHookCommand,
5973
+ selfCheckAgyHooks,
5707
5974
  mergeCodexTomlHooks,
5708
5975
  mergeCodexHooks: mergeCodexTomlHooks,
5709
5976
  mergeCodexTomlMcpServers,
@@ -5726,6 +5993,7 @@ module.exports = {
5726
5993
  INSTALL_MANIFEST_PATH,
5727
5994
  // Agent compilers & pipeline helpers
5728
5995
  parseAgentsMd,
5996
+ loadCommonSkills,
5729
5997
  compileClaudeAgents,
5730
5998
  compileOpenCodeAgents,
5731
5999
  compileCodexAgents,
@@ -5736,6 +6004,10 @@ module.exports = {
5736
6004
  generateAndOpenLaunchpad,
5737
6005
  shouldOpenLaunchpad,
5738
6006
  shouldAutostartLaunchpad,
6007
+ shouldAutostartPlanCanvas,
6008
+ buildPlanCanvasPlist,
6009
+ buildPlanCanvasWinFiles,
6010
+ installPlanCanvasAutostart,
5739
6011
  isDevEnvironment,
5740
6012
  LAUNCHPAD_WEB_MODULES,
5741
6013
  LAUNCHPAD_OPEN_FLAGS,
@@ -64,16 +64,15 @@ async function init() {
64
64
 
65
65
  const customRulebook = path.resolve(process.cwd(), 'rulebook.yaml');
66
66
  const defaultRulebook = path.resolve(__dirname, '../core/rulebook.default.yaml');
67
- const rulebookPath = fs.existsSync(customRulebook) ? customRulebook : defaultRulebook;
68
67
 
69
68
  try {
70
- if (fs.existsSync(rulebookPath)) {
71
- rules = loadRulebook(rulebookPath);
72
- const now = Date.now();
73
- offerTable = await buildOfferTable(rules, inventory, now);
74
- }
69
+ rules = await loadRulebook({
70
+ defaultsPath: defaultRulebook,
71
+ overridePath: fs.existsSync(customRulebook) ? customRulebook : undefined,
72
+ });
73
+ offerTable = await buildOfferTable(rules, inventory, Date.now());
75
74
  } catch (e) {
76
- console.error(`[mcsc-mcp] Warning: could not load rulebook from ${rulebookPath}: ${e.message}`);
75
+ console.error(`[mcsc-mcp] Warning: could not load rulebook from ${defaultRulebook}: ${e.message}`);
77
76
  }
78
77
  }
79
78
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hybridlabor-api/aos",
3
- "version": "4.13.2",
3
+ "version": "4.14.1",
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": {
@@ -18,7 +18,8 @@
18
18
  "aos-config": "bin/aos-config.mjs",
19
19
  "aos-store": "bin/aos-store.mjs",
20
20
  "aos-doctor": "bin/aos-doctor.mjs",
21
- "aos-uninstall": "bin/aos-uninstall.mjs"
21
+ "aos-uninstall": "bin/aos-uninstall.mjs",
22
+ "aos-acp": "bin/aos-acp.mjs"
22
23
  },
23
24
  "scripts": {
24
25
  "validate": "node scripts/validate-skills.mjs",
@@ -27,7 +28,7 @@
27
28
  "plugin:build": "node scripts/build-plugin-manifest.mjs",
28
29
  "plugin:check": "node scripts/build-plugin-manifest.mjs --check",
29
30
  "doctor": "node bin/aos-doctor.mjs",
30
- "test": "node scripts/validate-skills.mjs --selftest && node scripts/validate-skills.mjs && node scripts/build-plugin-manifest.mjs --check && node --test tests/opencode-graph-gate.test.js && node --test tests/cross-harness-hooks.test.js && node tests/aos-store.test.mjs && node --test tests/aos-store-ui.test.mjs && node tests/aos-store-scenario.test.mjs && node tests/aos-doctor.test.mjs && node tests/build-plugin-manifest.test.mjs && node --test tests/agent-models.test.js && node --test tests/installer-p3.test.js"
31
+ "test": "node scripts/validate-skills.mjs --selftest && node scripts/validate-skills.mjs && node scripts/build-plugin-manifest.mjs --check && node --test tests/opencode-graph-gate.test.js && node --test tests/cross-harness-hooks.test.js && node --test tests/plan-canvas-security.test.mjs && node --test tests/plan-canvas-modes.test.mjs && node --test tests/swarm-wiring.test.js && node tests/aos-store.test.mjs && node --test tests/aos-store-ui.test.mjs && node tests/aos-store-scenario.test.mjs && node tests/aos-doctor.test.mjs && node tests/build-plugin-manifest.test.mjs && node --test tests/agent-models.test.js && node --test tests/installer-p3.test.js && node --test tests/installer-binary.test.js && node --test tests/installer-version.test.js && node --test tests/mcsc-server.test.js && node --test tests/antigravity-hooks.test.js && node --test tests/windows-hooks.test.js && node --test tests/plan-builder.test.mjs && node --test tests/plan-builder-trail.test.mjs && node --test tests/plan-builder-showcase.test.mjs && node --test tests/plan-builder-templates.test.mjs && node --test tests/plan-canvas-home.test.mjs && node --test tests/launchpad-installer.test.js && node --test tests/launchpad-plan-canvas.test.js && node --test tests/go-token.test.js && node --test tests/master-session-skill.test.js && node --test tests/aos-acp.test.js && node --test tests/opencode-go-token.test.js && node --test tests/opencode-adapter.test.js && node --test tests/pr-recap.test.mjs && node --test tests/bdb-visual-edit.test.mjs && node --test tests/opencode-trail-autostart.test.mjs && node --test tests/trail-autostart-hook.test.mjs && node --test tests/agenttrail-ensure.test.mjs"
31
32
  },
32
33
  "publishConfig": {
33
34
  "access": "public"