@hybridlabor-api/aos 4.16.0 → 4.18.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/plugins/marketplace.json +20 -0
- package/.claude/hooks/aos-bus.mjs +8 -4
- package/.claude/hooks/env-file-protection.mjs +19 -1
- package/.claude/hooks/go-gate.mjs +788 -69
- package/.claude/hooks/go-grant.mjs +88 -0
- package/.claude/hooks/go-token.mjs +17 -2
- package/.claude/hooks/memb-inject.mjs +61 -37
- package/.claude/settings.json +8 -0
- package/.codex-plugin/plugin.json +36 -6
- package/.opencode/commands/bdb-aos-brainstorm.md +5 -0
- package/.opencode/commands/bdb-aos-doctor.md +5 -0
- package/.opencode/commands/bdb-aos-graph.md +5 -0
- package/.opencode/commands/bdb-aos-init.md +5 -0
- package/.opencode/commands/bdb-aos-loop.md +5 -0
- package/.opencode/commands/bdb-aos-mastersession.md +5 -0
- package/.opencode/commands/bdb-aos-memb.md +5 -0
- package/.opencode/commands/bdb-aos-orchestrator.md +5 -0
- package/.opencode/commands/bdb-aos-plan.md +5 -0
- package/.opencode/commands/bdb-aos-playbooks.md +5 -0
- package/.opencode/commands/bdb-aos-setup.md +5 -0
- package/.opencode/commands/bdb-aos-shipping.md +5 -0
- package/.opencode/commands/bdb-aos-startproject.md +5 -0
- package/.opencode/commands/bdb-aos-store.md +5 -0
- package/.opencode/plugins/bdb-aos.js +54 -10
- package/README.md +5 -4
- package/THIRD_PARTY_NOTICES.md +2 -2
- package/agy-commands/loop.md +5 -0
- package/bin/aos-acp.mjs +27 -1
- package/bin/aos-doctor.mjs +41 -4
- package/bin/aos-uninstall.mjs +41 -3
- package/bin/go-check.mjs +79 -0
- package/bin/guarded-patterns.json +106 -0
- package/commands/brainstorm.md +5 -0
- package/commands/doctor.md +5 -0
- package/commands/graph.md +5 -0
- package/commands/init.md +5 -0
- package/commands/loop.md +5 -0
- package/commands/mastersession.md +5 -0
- package/commands/memb.md +5 -0
- package/commands/orchestrator.md +5 -0
- package/commands/plan.md +5 -0
- package/commands/playbooks.md +5 -0
- package/commands/setup.md +5 -0
- package/commands/shipping.md +5 -0
- package/commands/startproject.md +5 -0
- package/commands/store.md +5 -0
- package/docs/codenotch.md +44 -0
- package/docs/codex-agy-setup.md +16 -0
- package/docs/codex-gate-smoke.md +43 -0
- package/docs/delegation-routing.md +32 -0
- package/docs/go-check.md +60 -0
- package/docs/master-session-acp.md +2 -0
- package/docs/opencode-setup.md +54 -0
- package/docs/plugin-migration.md +61 -0
- package/installer.js +351 -121
- package/lib/codenotch.js +389 -0
- package/lib/plugin-migration.js +462 -0
- package/lib/retired-skills.js +101 -0
- package/lib/store-ui/index.html +9 -1
- package/lib/store-ui/server.mjs +2 -0
- package/mcps/mcsc/README.md +1 -1
- package/mcps/mcsc/packages/core/src/adapters/agy.js +3 -1
- package/mcps/mcsc/packages/core/src/adapters/codex.js +2 -1
- package/mcps/mcsc/packages/core/src/adapters/opencode.js +2 -1
- package/mcps/mcsc/packages/core/src/depth.js +16 -0
- package/mcps/mcsc/packages/mcp/server.js +15 -2
- package/package.json +7 -2
- package/plugin-commands.json +143 -0
- package/plugin.json +299 -0
- package/plugins/bdb-aos-codex/.codex-plugin/plugin.json +38 -0
- package/plugins/bdb-aos-codex/skills/brainstorm/SKILL.md +6 -0
- package/plugins/bdb-aos-codex/skills/doctor/SKILL.md +6 -0
- package/plugins/bdb-aos-codex/skills/graph/SKILL.md +6 -0
- package/plugins/bdb-aos-codex/skills/init/SKILL.md +6 -0
- package/plugins/bdb-aos-codex/skills/loop/SKILL.md +6 -0
- package/plugins/bdb-aos-codex/skills/mastersession/SKILL.md +6 -0
- package/plugins/bdb-aos-codex/skills/memb/SKILL.md +6 -0
- package/plugins/bdb-aos-codex/skills/orchestrator/SKILL.md +6 -0
- package/plugins/bdb-aos-codex/skills/plan/SKILL.md +6 -0
- package/plugins/bdb-aos-codex/skills/playbooks/SKILL.md +6 -0
- package/plugins/bdb-aos-codex/skills/setup/SKILL.md +6 -0
- package/plugins/bdb-aos-codex/skills/shipping/SKILL.md +6 -0
- package/plugins/bdb-aos-codex/skills/startproject/SKILL.md +6 -0
- package/plugins/bdb-aos-codex/skills/store/SKILL.md +6 -0
- package/scripts/build-plugin-manifest.mjs +202 -3
- package/scripts/codex-gate-smoke.mjs +73 -0
- package/skills/basic/master-session/SKILL.md +11 -0
- package/skills/bdb-aos/scripts/list-playbooks.mjs +72 -0
- package/skills/global_config/agenttrail/SKILL.md +3 -1
- package/skills/global_config/agenttrail/bin/agenttrail.mjs +255 -117
- package/skills/global_config/agenttrail/bin/ensure.mjs +60 -40
- package/skills/global_config/agenttrail/bin/repoid.mjs +70 -0
- package/skills/global_config/agenttrail/public/index.html +9 -1
- package/skills/global_config/aos-setup/scripts/aos-doctor.mjs +1 -1
- package/skills/global_config/bdb-memb-mcp/SKILL.md +5 -4
- package/skills/global_config/bdb-visual-edit/SKILL.md +28 -32
- package/skills/global_config/bdb-visual-edit/references/vite-react-source-attr.md +2 -2
- package/skills/global_config/bdb-visual-edit/scripts/locate-source.mjs +135 -0
- package/skills/global_config/bdb-visual-edit/scripts/sanitize-element.mjs +30 -2
- package/skills/global_config/gogate/SKILL.md +123 -0
- package/skills/global_config/loop-templates/SKILL.md +27 -0
- package/skills/global_config/loop-templates/references/ci-until-green.md +27 -0
- package/skills/global_config/loop-templates/references/daily-summary.md +27 -0
- package/skills/global_config/loop-templates/references/pr-to-merge.md +27 -0
- package/skills/global_config/loop-templates/references/review-rounds.md +27 -0
- package/skills/global_config/mcsc/SKILL.md +9 -1
- package/skills/global_config/plan-arbiter/SKILL.md +1 -1
- package/skills/global_config/plan-canvas/SKILL.md +42 -4
- package/skills/global_config/plan-canvas/scripts/lib/plan-builder/README.md +1 -1
- package/skills/global_config/plan-canvas/scripts/lib/plan-builder/render.js +2 -2
- package/skills/global_config/plan-canvas/scripts/lib/plan-canvas/annotate-client/geometry.js +76 -0
- package/skills/global_config/plan-canvas/scripts/lib/plan-canvas/annotate-client/index.js +596 -0
- package/skills/global_config/plan-canvas/scripts/lib/plan-canvas/annotate-client/model.js +192 -0
- package/skills/global_config/plan-canvas/scripts/lib/plan-canvas/annotate-client/toolbar.js +99 -0
- package/skills/global_config/plan-canvas/scripts/lib/plan-canvas/annotate-server.js +282 -0
- package/skills/global_config/plan-canvas/scripts/lib/plan-canvas/annotation-schema.js +210 -0
- package/skills/global_config/plan-canvas/scripts/lib/plan-canvas/route.js +10 -0
- package/skills/global_config/plan-canvas/scripts/lib/plan-canvas/sdk.js +6 -230
- package/skills/global_config/plan-canvas/scripts/lib/plan-canvas/server.js +45 -4
- package/skills/global_config/plan-canvas/scripts/lib/plan-canvas/sessions.js +60 -21
- package/skills/global_config/plan-canvas/scripts/lib/plan-canvas/trail-on-approve.js +103 -0
- package/skills/global_config/plan-canvas/scripts/lib/plan-canvas/ui.js +19 -7
- package/skills/global_config/plan-canvas/scripts/plan-canvas.js +118 -20
- package/skills/global_config/subagent-setup/SKILL.md +6 -0
- package/skills/global_config/subagent-setup/scripts/setup-subagents.mjs +20 -1
- package/skills/playbooks/pb-idea-to-launch/SKILL.md +2 -2
- package/skills/playbooks/pb-redesign-app/SKILL.md +3 -3
- package/skills/playbooks/pb-release-aos/SKILL.md +2 -2
- package/skills/playbooks/pb-ship/SKILL.md +2 -2
- package/skills/playbooks/pb-worktrees-land/SKILL.md +2 -2
- package/.codex-plugin/marketplace.json +0 -11
- package/skills/global_config/bdb-visual-edit/scripts/pick-snippet.js +0 -27
- package/skills/global_config/visual-edit/README.md +0 -96
- package/skills/global_config/visual-edit/SKILL.md +0 -615
- package/skills/global_config/visual-plan/README.md +0 -93
- package/skills/global_config/visual-plan/SKILL.md +0 -544
- package/skills/global_config/visual-plan/references/canvas.md +0 -139
- package/skills/global_config/visual-plan/references/connection.md +0 -51
- package/skills/global_config/visual-plan/references/document-quality.md +0 -186
- package/skills/global_config/visual-plan/references/exemplar.md +0 -62
- package/skills/global_config/visual-plan/references/local-files.md +0 -99
- package/skills/global_config/visual-plan/references/wireframe.md +0 -319
- package/skills/global_config/visual-recap/README.md +0 -103
- package/skills/global_config/visual-recap/SKILL.md +0 -560
- package/skills/global_config/visual-recap/references/connection.md +0 -51
- package/skills/global_config/visual-recap/references/local-files.md +0 -99
- package/skills/global_config/visual-recap/references/wireframe.md +0 -319
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -309,7 +309,7 @@ dependency.
|
|
|
309
309
|
|
|
310
310
|
<https://github.com/BuilderIO/skills> — MIT. Copyright (c) 2026 Builder.io.
|
|
311
311
|
|
|
312
|
-
|
|
312
|
+
Eight skills are adapted under `skills/global_config/`: `read-the-damn-docs`, `stay-within-limits`, `quick-recap`, `plan-arbiter`, `factory-human-digest`, `factory-collect`, `factory-lookback`, and `factory-review-prs`. The four Factory skills and `plan-arbiter` have `installer-group` dropped and `category`/`source` added; in `factory-collect`, `factory-lookback` and `factory-review-prs` reply, close, approve, merge and publish actions are reduced to drafts or readiness reports that need the user's GO, and all of them carry an "AOS safety rules" section. `plan-arbiter` drops `agents/openai.yaml` and adds an AOS section on double plans. `stay-within-limits` and `quick-recap` are carried over with `category:` and `source:` added; `stay-within-limits` pins `ccusage` to 20.0.26 instead of `@latest`, and `quick-recap` no longer asks the installer to inject a managed `AGENTS.md` / `CLAUDE.md` block. `read-the-damn-docs` is described below:
|
|
313
313
|
the docs-first trigger list, the source hierarchy, the required workflow, the
|
|
314
314
|
must-trigger examples, and the "if docs are unavailable" rule. AOS additionally
|
|
315
315
|
adds a Verification section, a `category:` key (Builder's own validator forbids
|
|
@@ -318,7 +318,7 @@ guesswork* rule, and a pointer to the installed `firecrawl-search` /
|
|
|
318
318
|
`firecrawl-scrape` tools. Prose only — the upstream `agents/openai.yaml` and
|
|
319
319
|
README were not carried over, and no executable from the repo is referenced.
|
|
320
320
|
|
|
321
|
-
|
|
321
|
+
The other 13 skills in that repo (as of commit 0dba9ef) are **not** vendored. Three of them
|
|
322
322
|
(`an`, `turn-into-app`, `rewind`) plus three others
|
|
323
323
|
are build artefacts synced from a different upstream by
|
|
324
324
|
`scripts/sync-agent-native-skills.mjs`, and the repo's own documentation says
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Run a prompt repeatedly on an interval, using the harness built-in plus loop templates."
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Unverified, no loop mechanism confirmed for agy. Manual repeat: fill a `loop-templates` template, re-send it yourself at each interval, and stop at its limits or stop condition. Safety: a loop prompt never issues a GO, never types or runs `gogate`, never sets a mode or grant, and never merges, pushes or publishes unless a valid grant covers the action. Act on a guarded step only if the human's immediately preceding message is a literal GO or a valid grant covers it; a loop iteration never satisfies the first condition, so it must STOP and report instead of continuing a blocked guarded step. Templates (CI until green, follow a PR to merge, review rounds until no blockers, daily session summary) live in the `loop-templates` skill with run and duration limits and a stop condition each. Arguments: whatever the user wrote after the command name
|
package/bin/aos-acp.mjs
CHANGED
|
@@ -14,10 +14,11 @@
|
|
|
14
14
|
import { spawn } from "node:child_process";
|
|
15
15
|
import { appendFileSync, mkdirSync, readFileSync, realpathSync } from "node:fs";
|
|
16
16
|
import { homedir } from "node:os";
|
|
17
|
-
import { dirname, join } from "node:path";
|
|
17
|
+
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
18
18
|
import { fileURLToPath } from "node:url";
|
|
19
19
|
import { createInterface } from "node:readline";
|
|
20
20
|
import { GUARDED_PATTERNS, slug, tokenGrantsGo } from "../.claude/hooks/go-gate.mjs";
|
|
21
|
+
import { emitTrail } from "../mcps/mcsc/packages/core/src/trail.js";
|
|
21
22
|
|
|
22
23
|
export const ADAPTERS = {
|
|
23
24
|
claude: { cmd: ["npx", "-y", "@agentclientprotocol/claude-agent-acp"], consume: false },
|
|
@@ -113,6 +114,25 @@ export class AcpClient {
|
|
|
113
114
|
notify(method, params) { this.write({ jsonrpc: "2.0", method, params }); }
|
|
114
115
|
}
|
|
115
116
|
|
|
117
|
+
// Same agenttrail protocol as mcsc's adapters (SessionStart/SessionEnd, PreToolUse/PostToolUse),
|
|
118
|
+
// so the GO board reads ACP workers and mcsc runs from one source.
|
|
119
|
+
const cap = (t) => (t ? t.charAt(0).toUpperCase() + t.slice(1) : "Tool");
|
|
120
|
+
|
|
121
|
+
export function trailToolEvent(u, seen, cwd) {
|
|
122
|
+
const prev = seen.get(u.toolCallId) || {};
|
|
123
|
+
const info = { title: u.title ?? prev.title, kind: u.kind ?? prev.kind };
|
|
124
|
+
seen.set(u.toolCallId, info);
|
|
125
|
+
const done = u.status === "completed" || u.status === "failed";
|
|
126
|
+
if (u.sessionUpdate === "tool_call_update" && !done) return null;
|
|
127
|
+
const tool_input = {};
|
|
128
|
+
const file = u.locations?.[0]?.path ?? prev.file;
|
|
129
|
+
if (typeof file === "string" && file) tool_input.file_path = isAbsolute(file) ? file : resolve(cwd, file);
|
|
130
|
+
info.file = tool_input.file_path;
|
|
131
|
+
const command = commandOf(u);
|
|
132
|
+
if (command) tool_input.command = command;
|
|
133
|
+
return { hook_event_name: done ? "PostToolUse" : "PreToolUse", tool_name: cap(info.kind || info.title), tool_input };
|
|
134
|
+
}
|
|
135
|
+
|
|
116
136
|
function textOf(block) {
|
|
117
137
|
return block && block.type === "text" ? block.text : "";
|
|
118
138
|
}
|
|
@@ -134,6 +154,9 @@ export async function run(opts) {
|
|
|
134
154
|
const consume = opts.consume ?? adapter?.consume ?? true;
|
|
135
155
|
log("start", { adapter: opts.adapter, cmd: cmd.join(" "), cwd: opts.cwd, allow_default: opts.allowDefault, consume, model: opts.model || "adapter default" });
|
|
136
156
|
|
|
157
|
+
const trail = { session_id: `aos-acp-${process.pid}-${Date.now()}`, cwd: opts.cwd, agent: `${opts.adapter}:${opts.name}` };
|
|
158
|
+
const seenTools = new Map();
|
|
159
|
+
emitTrail({ ...trail, hook_event_name: "SessionStart" });
|
|
137
160
|
let sessionId;
|
|
138
161
|
const out = opts.stdout || process.stdout;
|
|
139
162
|
const client = new AcpClient(cmd, {
|
|
@@ -148,6 +171,8 @@ export async function run(opts) {
|
|
|
148
171
|
if (t) { out.write(t); log("text", { text: t }); }
|
|
149
172
|
} else if (u.sessionUpdate === "tool_call" || u.sessionUpdate === "tool_call_update") {
|
|
150
173
|
log(u.sessionUpdate, { id: u.toolCallId, title: u.title, kind: u.kind, status: u.status, command: commandOf(u) || undefined });
|
|
174
|
+
const ev = trailToolEvent(u, seenTools, opts.cwd);
|
|
175
|
+
if (ev) emitTrail({ ...trail, ...ev });
|
|
151
176
|
} else log("update", { kind: u.sessionUpdate });
|
|
152
177
|
},
|
|
153
178
|
onRequest: (method, p) => {
|
|
@@ -182,6 +207,7 @@ export async function run(opts) {
|
|
|
182
207
|
} finally {
|
|
183
208
|
if (timer) clearTimeout(timer);
|
|
184
209
|
client.child.kill();
|
|
210
|
+
await emitTrail({ ...trail, hook_event_name: "SessionEnd" });
|
|
185
211
|
}
|
|
186
212
|
}
|
|
187
213
|
|
package/bin/aos-doctor.mjs
CHANGED
|
@@ -12,6 +12,7 @@ import { createRequire } from 'node:module';
|
|
|
12
12
|
import os from 'node:os';
|
|
13
13
|
import path from 'node:path';
|
|
14
14
|
|
|
15
|
+
const pm = createRequire(import.meta.url)('../lib/plugin-migration.js');
|
|
15
16
|
const HOME = os.homedir();
|
|
16
17
|
const JSON_OUT = process.argv.includes('--json');
|
|
17
18
|
const NET = process.argv.includes('--net');
|
|
@@ -168,6 +169,40 @@ function checkAosCore() {
|
|
|
168
169
|
}
|
|
169
170
|
}
|
|
170
171
|
|
|
172
|
+
// JSONC to JSON: drops comments (not inside strings) and trailing commas.
|
|
173
|
+
function parseJsonc(text) {
|
|
174
|
+
let out = '';
|
|
175
|
+
for (let i = 0, str = false; i < text.length; i++) {
|
|
176
|
+
const c = text[i];
|
|
177
|
+
if (str) { out += c; if (c === '\\') out += text[++i] ?? ''; else if (c === '"') str = false; continue; }
|
|
178
|
+
if (c === '"') { str = true; out += c; continue; }
|
|
179
|
+
if (c === '/' && text[i + 1] === '/') { while (i < text.length && text[i] !== '\n') i++; out += '\n'; continue; }
|
|
180
|
+
if (c === '/' && text[i + 1] === '*') { i += 2; while (i < text.length && !(text[i] === '*' && text[i + 1] === '/')) i++; i++; continue; }
|
|
181
|
+
out += c;
|
|
182
|
+
}
|
|
183
|
+
try { return JSON.parse(out.replace(/,(\s*[}\]])/g, '$1')); } catch { return null; }
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Zen gateway limit: a tool name (OpenCode builds it from the MCP server name) is at most 64 characters.
|
|
187
|
+
// Names only, no network: the tool part of the name is not known here.
|
|
188
|
+
const ZEN_TOOL_NAME_MAX = 64;
|
|
189
|
+
|
|
190
|
+
function checkOpencodeMcpNames() {
|
|
191
|
+
const dirs = [process.platform === 'win32' ? path.join(process.env.APPDATA || HOME, 'opencode') : h('.config', 'opencode')];
|
|
192
|
+
const file = firstExisting(dirs.flatMap((d) => ['opencode.jsonc', 'opencode.json'].map((f) => path.join(d, f))));
|
|
193
|
+
if (!file) return;
|
|
194
|
+
const conf = parseJsonc(readFileSync(file, 'utf8'));
|
|
195
|
+
if (!conf) {
|
|
196
|
+
add('harnesses', 'OpenCode MCP names', false, `${tilde(file)} is not valid JSON(C); names not checked`, 'Fix the OpenCode config syntax.', true);
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
const names = Object.keys(conf.mcp && typeof conf.mcp === 'object' ? conf.mcp : {});
|
|
200
|
+
const tooLong = names.filter((n) => n.length > ZEN_TOOL_NAME_MAX);
|
|
201
|
+
add('harnesses', 'OpenCode MCP names', tooLong.length === 0,
|
|
202
|
+
tooLong.length ? `${tooLong.length} MCP name(s) over ${ZEN_TOOL_NAME_MAX} characters (Zen gateway limit): ${tooLong.join(', ')}` : `${names.length} MCP name(s) in ${tilde(file)}, none over ${ZEN_TOOL_NAME_MAX} characters`,
|
|
203
|
+
`Rename the MCP server(s) in ${tilde(file)} to a shorter name; tool names are built from them and a name over ${ZEN_TOOL_NAME_MAX} characters is rejected by the Zen gateway. Keeping the MCP set lean also helps.`, true);
|
|
204
|
+
}
|
|
205
|
+
|
|
171
206
|
// ---------------------------------------------------------------- 3. Harness Placement & Skills Sync
|
|
172
207
|
function checkHarnesses() {
|
|
173
208
|
const harnesses = [
|
|
@@ -183,10 +218,11 @@ function checkHarnesses() {
|
|
|
183
218
|
const exists = existsSync(hr.path);
|
|
184
219
|
const count = dirCount(hr.path);
|
|
185
220
|
const hasSentinel = existsSync(path.join(hr.path, SENTINEL, 'SKILL.md'));
|
|
186
|
-
const
|
|
221
|
+
const viaPlugin = hr.name === 'Claude Code' && !hasSentinel && pm.pluginInstalled(HOME, [SENTINEL]);
|
|
222
|
+
const ok = viaPlugin || (exists && count > 0 && hasSentinel);
|
|
187
223
|
add('harnesses', `${hr.name} Skills`, ok,
|
|
188
|
-
ok ? `${tilde(hr.path)} (${count} skills, sentinel verified)` : (exists ? `${tilde(hr.path)} (${count} skills, sentinel missing)` : `${tilde(hr.path)} not synced`),
|
|
189
|
-
`Run 'npx @hybridlabor-api/aos@latest' and select ${hr.name} to sync skills.`, !exists);
|
|
224
|
+
viaPlugin ? 'delivered by the bdb-aos Claude Code plugin (installed_plugins.json / plugin cache)' : ok ? `${tilde(hr.path)} (${count} skills, sentinel verified)` : (exists ? `${tilde(hr.path)} (${count} skills, sentinel missing)` : `${tilde(hr.path)} not synced`),
|
|
225
|
+
`Run 'npx @hybridlabor-api/aos@latest' and select ${hr.name} to sync skills.`, !exists && !viaPlugin);
|
|
190
226
|
}
|
|
191
227
|
|
|
192
228
|
// OpenCode Plugin check
|
|
@@ -197,12 +233,13 @@ function checkHarnesses() {
|
|
|
197
233
|
add('harnesses', 'OpenCode Plugin', !!opencodePlugin,
|
|
198
234
|
opencodePlugin ? tilde(opencodePlugin) : 'bdb-aos.js not installed in OpenCode plugins',
|
|
199
235
|
'Run the AOS installer to wire OpenCode telemetry plugin.', true);
|
|
236
|
+
checkOpencodeMcpNames();
|
|
200
237
|
}
|
|
201
238
|
|
|
202
239
|
// ---------------------------------------------------------------- 4. Hooks & Security Gates
|
|
203
240
|
function checkHooks() {
|
|
204
241
|
const claudeHooksDir = h('.claude', 'hooks');
|
|
205
|
-
const EXPECTED_VERSION = { 'memb-inject.mjs':
|
|
242
|
+
const EXPECTED_VERSION = { 'memb-inject.mjs': 8 };
|
|
206
243
|
const versionOf = (text) => {
|
|
207
244
|
const m = /^\/\/\s*aos-hook-version:\s*(\d+)/m.exec(text);
|
|
208
245
|
return m ? Number(m[1]) : null;
|
package/bin/aos-uninstall.mjs
CHANGED
|
@@ -5,6 +5,9 @@
|
|
|
5
5
|
// aos-uninstall --purge also the memory store, wikis and credentials
|
|
6
6
|
// aos-uninstall --dry-run list everything, delete nothing
|
|
7
7
|
// aos-uninstall --yes skip the confirmations (CI only)
|
|
8
|
+
// aos-uninstall --restore-plugin-backup
|
|
9
|
+
// put back the loose skill copies the installer removed when it
|
|
10
|
+
// registered the bdb-aos plugin (never overwrites an existing file)
|
|
8
11
|
//
|
|
9
12
|
// The file-level install manifest records every path AOS wrote together with
|
|
10
13
|
// the sha256 it wrote. That is what makes a precise uninstall possible: a file
|
|
@@ -19,6 +22,10 @@ import { createHash } from 'node:crypto';
|
|
|
19
22
|
import { createInterface } from 'node:readline/promises';
|
|
20
23
|
import os from 'node:os';
|
|
21
24
|
import path from 'node:path';
|
|
25
|
+
import { createRequire } from 'node:module';
|
|
26
|
+
|
|
27
|
+
const pm = createRequire(import.meta.url)('../lib/plugin-migration.js');
|
|
28
|
+
const cn = createRequire(import.meta.url)('../lib/codenotch.js');
|
|
22
29
|
|
|
23
30
|
const HOME = os.homedir();
|
|
24
31
|
const h = (...p) => path.join(HOME, ...p);
|
|
@@ -27,6 +34,7 @@ const tilde = (p) => p.replace(HOME, '~');
|
|
|
27
34
|
const PURGE = process.argv.includes('--purge');
|
|
28
35
|
const DRY = process.argv.includes('--dry-run');
|
|
29
36
|
const YES = process.argv.includes('--yes');
|
|
37
|
+
const RESTORE = process.argv.includes('--restore-plugin-backup');
|
|
30
38
|
|
|
31
39
|
const MANIFEST = h('.agents', '.bdb-install-manifest.json');
|
|
32
40
|
|
|
@@ -96,7 +104,9 @@ function plan() {
|
|
|
96
104
|
const legacy = LEGACY_MARKERS.filter(existsSync);
|
|
97
105
|
const data = PURGE ? DATA_PATHS.filter((d) => existsSync(d.path)) : [];
|
|
98
106
|
|
|
99
|
-
|
|
107
|
+
const codenotch = cn.planCodenotchUninstall({ stateFile: cn.stateFilePath(HOME) });
|
|
108
|
+
|
|
109
|
+
return { manifest, ours, edited, gone, agents, modules, legacy, data, codenotch };
|
|
100
110
|
}
|
|
101
111
|
|
|
102
112
|
function describe(p) {
|
|
@@ -133,6 +143,12 @@ function describe(p) {
|
|
|
133
143
|
for (const l of legacy) console.log(` ${tilde(l)}`);
|
|
134
144
|
}
|
|
135
145
|
|
|
146
|
+
if (p.codenotch) {
|
|
147
|
+
const c = p.codenotch;
|
|
148
|
+
const note = { remove: 'is removed (still the recorded build)', keep: 'is kept (replaced or modified since AOS installed it)', gone: 'is already gone' }[c.action];
|
|
149
|
+
console.log(`\nBDB AO Codenotch ${tilde(c.state.path || c.state.uninstallPath)} ${note}`);
|
|
150
|
+
}
|
|
151
|
+
|
|
136
152
|
console.log('\nBleibt erhalten:');
|
|
137
153
|
if (!PURGE) for (const d of DATA_PATHS.filter((d) => existsSync(d.path))) console.log(` ${tilde(d.path).padEnd(18)} ${d.what}`);
|
|
138
154
|
console.log(' jede Datei ohne Manifest-Eintrag — eigene Skills, fremde Hooks, alles Selbstgeschriebene');
|
|
@@ -162,7 +178,7 @@ function dirSize(p) {
|
|
|
162
178
|
|
|
163
179
|
// ------------------------------------------------------------------ execute
|
|
164
180
|
function execute(p) {
|
|
165
|
-
const { ours, edited, agents, modules, legacy, data } = p;
|
|
181
|
+
const { ours, edited, agents, modules, legacy, data, codenotch } = p;
|
|
166
182
|
const stamp = new Date().toISOString().replace(/[:.]/g, '').slice(0, 15);
|
|
167
183
|
let removed = 0, backed = 0;
|
|
168
184
|
|
|
@@ -235,16 +251,27 @@ function execute(p) {
|
|
|
235
251
|
} catch { console.log(` ${tilde(codexToml)} nicht lesbar — von Hand prüfen`); }
|
|
236
252
|
}
|
|
237
253
|
|
|
254
|
+
if (codenotch) {
|
|
255
|
+
const r = cn.uninstallCodenotch(codenotch, { stateFile: cn.stateFilePath(HOME) });
|
|
256
|
+
console.log(` Codenotch: ${r === 'remove' ? 'removed' : r === 'keep' ? 'kept, not the recorded build' : r === 'error' ? 'uninstaller failed, left in place' : 'already gone'}`);
|
|
257
|
+
}
|
|
258
|
+
|
|
238
259
|
for (const l of legacy) { try { rmSync(l); } catch { /* already gone */ } }
|
|
239
260
|
if (legacy.length) console.log(` ${legacy.length} Installations-Marker entfernt`);
|
|
240
261
|
|
|
262
|
+
const reg = pm.readState(HOME).registered.claudecode;
|
|
263
|
+
if (reg) {
|
|
264
|
+
const r = pm.deregisterClaude({ home: HOME, record: reg });
|
|
265
|
+
if (r.changed) console.log(` bdb-aos Plugin-Registrierung aus settings.json entfernt${reg.replaced ? ` (externer Marketplace ${reg.replaced.key} wiederhergestellt)` : ''}`);
|
|
266
|
+
}
|
|
267
|
+
|
|
241
268
|
// Only the BDB hook entries leave settings.json; everything else in it is
|
|
242
269
|
// the user's and must survive an uninstall exactly as it survives an install.
|
|
243
270
|
const settings = h('.claude', 'settings.json');
|
|
244
271
|
if (existsSync(settings)) {
|
|
245
272
|
try {
|
|
246
273
|
const s = JSON.parse(readFileSync(settings, 'utf8'));
|
|
247
|
-
const bdb = ['go-gate.mjs', 'graph-gate.mjs', 'memb-inject.mjs', 'trail-relay.mjs', 'trail-autostart.mjs', 'conventional-commits.mjs', 'env-file-protection.mjs'];
|
|
274
|
+
const bdb = ['go-gate.mjs', 'go-token.mjs', 'go-grant.mjs', 'graph-gate.mjs', 'memb-inject.mjs', 'trail-relay.mjs', 'trail-autostart.mjs', 'conventional-commits.mjs', 'env-file-protection.mjs'];
|
|
248
275
|
let touched = false;
|
|
249
276
|
for (const [event, entries] of Object.entries(s.hooks || {})) {
|
|
250
277
|
const kept = entries.filter((e) => !(e.hooks || []).some((x) => bdb.some((n) => String(x.command).includes(n))));
|
|
@@ -266,6 +293,7 @@ function execute(p) {
|
|
|
266
293
|
for (const f of [MANIFEST, h('.agents', '.bdb-manifest.json')]) {
|
|
267
294
|
try { rmSync(f); } catch { /* already gone */ }
|
|
268
295
|
}
|
|
296
|
+
pm.retireState(HOME);
|
|
269
297
|
}
|
|
270
298
|
|
|
271
299
|
// ---------------------------------------------------------------------- main
|
|
@@ -276,6 +304,16 @@ const ask = async (q) => {
|
|
|
276
304
|
return a;
|
|
277
305
|
};
|
|
278
306
|
|
|
307
|
+
if (RESTORE) {
|
|
308
|
+
const r = pm.restorePluginBackups({ home: HOME });
|
|
309
|
+
if (!r.dirs.length) { console.log('Keine Plugin-Migrations-Sicherung gefunden.'); process.exit(1); }
|
|
310
|
+
console.log(` ${r.files.length} Dateien aus ${r.dirs.length} Sicherung(en) wiederhergestellt, im Install-Manifest erfasst`);
|
|
311
|
+
console.log('Vorhandene Dateien wurden nicht überschrieben.');
|
|
312
|
+
if (r.deregistered) console.log(' bdb-aos Plugin-Registrierung entfernt, damit die Skills nicht doppelt geladen werden. Setze AOS_PLUGIN_MIGRATION=off, damit der Installer sie nicht erneut entfernt.');
|
|
313
|
+
else if (r.files.length && r.stillEnabled) console.log(' WARNUNG: das bdb-aos Plugin ist weiterhin aktiv, die Skills erscheinen doppelt. Plugin in Claude Code deaktivieren und AOS_PLUGIN_MIGRATION=off setzen.');
|
|
314
|
+
process.exit(0);
|
|
315
|
+
}
|
|
316
|
+
|
|
279
317
|
const p = plan();
|
|
280
318
|
console.log(PURGE ? '\x1b[31mAOS UNINSTALL — PURGE\x1b[0m' : 'AOS Uninstall');
|
|
281
319
|
if (!describe(p)) process.exit(1);
|
package/bin/go-check.mjs
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// go-check: one fixed answer to "may this worker run this guarded command?" for callers that
|
|
3
|
+
// are not a harness hook (AO). Installed at ~/.aos/bin/go-check.mjs.
|
|
4
|
+
//
|
|
5
|
+
// node go-check.mjs --session <Name> --command "<shell string>" [--consume]
|
|
6
|
+
// node go-check.mjs --write-patterns <file>
|
|
7
|
+
//
|
|
8
|
+
// stdout: {"guarded":bool,"ok":bool,"scope":[...]|null,"reason":"..."}
|
|
9
|
+
// exit 0 allowed (not guarded, or a valid GO token; --consume uses it up), 1 guarded without a
|
|
10
|
+
// valid GO, 2 error (the caller must treat 2 as denied). Only `GO <Name>` tokens count: mode
|
|
11
|
+
// soft grants and mode off belong to the human session and are never read here. Nothing in
|
|
12
|
+
// this file writes a token; the tool is synchronous, offline and reads no stdin.
|
|
13
|
+
|
|
14
|
+
import { existsSync, realpathSync, writeFileSync } from "node:fs";
|
|
15
|
+
import { dirname, join } from "node:path";
|
|
16
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
17
|
+
|
|
18
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
19
|
+
|
|
20
|
+
async function loadGate() {
|
|
21
|
+
for (const f of [join(here, "go-gate.mjs"), join(here, "..", ".claude", "hooks", "go-gate.mjs")]) {
|
|
22
|
+
if (existsSync(f)) return import(pathToFileURL(f).href);
|
|
23
|
+
}
|
|
24
|
+
throw new Error("go-gate.mjs not found next to go-check.mjs or in ../.claude/hooks");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const patternsJson = (gate) => ({
|
|
28
|
+
version: 1,
|
|
29
|
+
source: "go-gate.mjs GUARDED_PATTERNS (JavaScript RegExp syntax, lookaheads included; not RE2)",
|
|
30
|
+
scopes: gate.SCOPES,
|
|
31
|
+
patterns: gate.GUARDED_PATTERNS.map((r) => ({ source: r.source, flags: r.flags })),
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
export function check(gate, { session, command, consume = false }) {
|
|
35
|
+
if (typeof command !== "string" || !command.trim()) return { code: 2, out: { guarded: null, ok: false, scope: null, reason: "--command is empty" } };
|
|
36
|
+
const storeReason = gate.gateStoreReason(command);
|
|
37
|
+
if (storeReason) return { code: 1, out: { guarded: true, ok: false, scope: null, reason: storeReason } };
|
|
38
|
+
if (!gate.isGuardedCommand(command)) return { code: 0, out: { guarded: false, ok: true, scope: [], reason: "" } };
|
|
39
|
+
const scope = gate.commandScopes(command);
|
|
40
|
+
if (typeof session !== "string" || !gate.slug(session)) {
|
|
41
|
+
return { code: 2, out: { guarded: true, ok: false, scope, reason: "--session is missing or has no usable name" } };
|
|
42
|
+
}
|
|
43
|
+
const r = gate.tokenGrantsGo(session, { consume });
|
|
44
|
+
return r.ok
|
|
45
|
+
? { code: 0, out: { guarded: true, ok: true, scope, reason: consume ? "GO token consumed" : "GO token valid (not consumed)" } }
|
|
46
|
+
: { code: 1, out: { guarded: true, ok: false, scope, reason: r.reason } };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function parseArgs(argv) {
|
|
50
|
+
const o = {};
|
|
51
|
+
for (let i = 0; i < argv.length; i++) {
|
|
52
|
+
const a = argv[i];
|
|
53
|
+
if (a === "--session") o.session = argv[++i];
|
|
54
|
+
else if (a === "--command") o.command = argv[++i];
|
|
55
|
+
else if (a === "--write-patterns") o.writePatterns = argv[++i];
|
|
56
|
+
else if (a === "--consume") o.consume = true;
|
|
57
|
+
else throw new Error(`unknown argument ${a}`);
|
|
58
|
+
}
|
|
59
|
+
return o;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const done = (code, out) => process.stdout.write(JSON.stringify(out) + "\n", () => process.exit(code));
|
|
63
|
+
|
|
64
|
+
const invokedAs = (() => { try { return realpathSync(process.argv[1] || ""); } catch { return ""; } })();
|
|
65
|
+
if (invokedAs === fileURLToPath(import.meta.url)) {
|
|
66
|
+
try {
|
|
67
|
+
const o = parseArgs(process.argv.slice(2));
|
|
68
|
+
const gate = await loadGate();
|
|
69
|
+
if (o.writePatterns) {
|
|
70
|
+
writeFileSync(o.writePatterns, JSON.stringify(patternsJson(gate), null, 2) + "\n");
|
|
71
|
+
done(0, { ok: true, reason: `wrote ${o.writePatterns}` });
|
|
72
|
+
} else {
|
|
73
|
+
const { code, out } = check(gate, o);
|
|
74
|
+
done(code, out);
|
|
75
|
+
}
|
|
76
|
+
} catch (e) {
|
|
77
|
+
done(2, { guarded: null, ok: false, scope: null, reason: String(e?.message || e).slice(0, 300) });
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"source": "go-gate.mjs GUARDED_PATTERNS (JavaScript RegExp syntax, lookaheads included; not RE2)",
|
|
4
|
+
"scopes": [
|
|
5
|
+
"push-feature",
|
|
6
|
+
"push-main",
|
|
7
|
+
"merge",
|
|
8
|
+
"publish",
|
|
9
|
+
"destructive",
|
|
10
|
+
"github-write"
|
|
11
|
+
],
|
|
12
|
+
"patterns": [
|
|
13
|
+
{
|
|
14
|
+
"source": "(?:^|[;&|\\n({\\x60])\\s*(?:(?:sudo|env|command|builtin|exec|nohup|time|xargs|eval|then|do|else)(?:\\s+-{1,2}[\\w-]+(?:=\\S*)?(?:\\s+(?![-'\"])(?!(?:\\S*\\/)?(?:git|gh|npm|rm|opencode|curl|wget)\\b)[^\\s;&|'\"]+)?)*\\s+|(?:bash|sh|zsh|dash|ksh)(?:\\s+-\\w+)*\\s+-c\\s+|\\w+=\\S*\\s+)*['\"]?(?:[^\\s;&|()'\"]*\\/)?(?:git\\s+push|git(?:\\s+(?:-[cC]\\s*(?:\"[^\"]*\"|'[^']*'|\\S+)|--[\\w-]+(?:=(?:\"[^\"]*\"|'[^']*'|\\S+))?))+\\s+push)\\b",
|
|
15
|
+
"flags": "i"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"source": "(?:^|[;&|\\n({\\x60])\\s*(?:(?:sudo|env|command|builtin|exec|nohup|time|xargs|eval|then|do|else)(?:\\s+-{1,2}[\\w-]+(?:=\\S*)?(?:\\s+(?![-'\"])(?!(?:\\S*\\/)?(?:git|gh|npm|rm|opencode|curl|wget)\\b)[^\\s;&|'\"]+)?)*\\s+|(?:bash|sh|zsh|dash|ksh)(?:\\s+-\\w+)*\\s+-c\\s+|\\w+=\\S*\\s+)*['\"]?(?:[^\\s;&|()'\"]*\\/)?npm\\s+publish\\b",
|
|
19
|
+
"flags": "i"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"source": "(?:^|[;&|\\n({\\x60])\\s*(?:(?:sudo|env|command|builtin|exec|nohup|time|xargs|eval|then|do|else)(?:\\s+-{1,2}[\\w-]+(?:=\\S*)?(?:\\s+(?![-'\"])(?!(?:\\S*\\/)?(?:git|gh|npm|rm|opencode|curl|wget)\\b)[^\\s;&|'\"]+)?)*\\s+|(?:bash|sh|zsh|dash|ksh)(?:\\s+-\\w+)*\\s+-c\\s+|\\w+=\\S*\\s+)*['\"]?(?:[^\\s;&|()'\"]*\\/)?npm\\s+version\\b",
|
|
23
|
+
"flags": "i"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"source": "(?:^|[;&|\\n({\\x60])\\s*(?:(?:sudo|env|command|builtin|exec|nohup|time|xargs|eval|then|do|else)(?:\\s+-{1,2}[\\w-]+(?:=\\S*)?(?:\\s+(?![-'\"])(?!(?:\\S*\\/)?(?:git|gh|npm|rm|opencode|curl|wget)\\b)[^\\s;&|'\"]+)?)*\\s+|(?:bash|sh|zsh|dash|ksh)(?:\\s+-\\w+)*\\s+-c\\s+|\\w+=\\S*\\s+)*['\"]?(?:[^\\s;&|()'\"]*\\/)?(?:gh\\s+pr\\s+merge|gh(?:\\s+(?:-R|--repo)(?:\\s+|=)\\S+)+\\s+pr\\s+merge)\\b",
|
|
27
|
+
"flags": "i"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"source": "(?:^|[;&|\\n({\\x60])\\s*(?:(?:sudo|env|command|builtin|exec|nohup|time|xargs|eval|then|do|else)(?:\\s+-{1,2}[\\w-]+(?:=\\S*)?(?:\\s+(?![-'\"])(?!(?:\\S*\\/)?(?:git|gh|npm|rm|opencode|curl|wget)\\b)[^\\s;&|'\"]+)?)*\\s+|(?:bash|sh|zsh|dash|ksh)(?:\\s+-\\w+)*\\s+-c\\s+|\\w+=\\S*\\s+)*['\"]?(?:[^\\s;&|()'\"]*\\/)?(?:gh\\s+release\\s+create|gh(?:\\s+(?:-R|--repo)(?:\\s+|=)\\S+)+\\s+release\\s+create)\\b",
|
|
31
|
+
"flags": "i"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"source": "(?:^|[;&|\\n({\\x60])\\s*(?:(?:sudo|env|command|builtin|exec|nohup|time|xargs|eval|then|do|else)(?:\\s+-{1,2}[\\w-]+(?:=\\S*)?(?:\\s+(?![-'\"])(?!(?:\\S*\\/)?(?:git|gh|npm|rm|opencode|curl|wget)\\b)[^\\s;&|'\"]+)?)*\\s+|(?:bash|sh|zsh|dash|ksh)(?:\\s+-\\w+)*\\s+-c\\s+|\\w+=\\S*\\s+)*['\"]?(?:[^\\s;&|()'\"]*\\/)?(?:git\\s+reset\\s+--hard|(?:git\\s+|git(?:\\s+(?:-[cC]\\s*(?:\"[^\"]*\"|'[^']*'|\\S+)|--[\\w-]+(?:=(?:\"[^\"]*\"|'[^']*'|\\S+))?))+\\s+)reset\\b[^;&|\\n]*\\s--hard)\\b",
|
|
35
|
+
"flags": "i"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"source": "(?:^|[;&|\\n({\\x60])\\s*(?:(?:sudo|env|command|builtin|exec|nohup|time|xargs|eval|then|do|else)(?:\\s+-{1,2}[\\w-]+(?:=\\S*)?(?:\\s+(?![-'\"])(?!(?:\\S*\\/)?(?:git|gh|npm|rm|opencode|curl|wget)\\b)[^\\s;&|'\"]+)?)*\\s+|(?:bash|sh|zsh|dash|ksh)(?:\\s+-\\w+)*\\s+-c\\s+|\\w+=\\S*\\s+)*['\"]?(?:[^\\s;&|()'\"]*\\/)?(?:git\\s+clean|git(?:\\s+(?:-[cC]\\s*(?:\"[^\"]*\"|'[^']*'|\\S+)|--[\\w-]+(?:=(?:\"[^\"]*\"|'[^']*'|\\S+))?))+\\s+clean)\\b[^;&|\\n]*\\s(?:-[a-zA-Z]*f[a-zA-Z]*|--force)\\b",
|
|
39
|
+
"flags": "i"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"source": "(?:^|[;&|\\n({\\x60])\\s*(?:(?:sudo|env|command|builtin|exec|nohup|time|xargs|eval|then|do|else)(?:\\s+-{1,2}[\\w-]+(?:=\\S*)?(?:\\s+(?![-'\"])(?!(?:\\S*\\/)?(?:git|gh|npm|rm|opencode|curl|wget)\\b)[^\\s;&|'\"]+)?)*\\s+|(?:bash|sh|zsh|dash|ksh)(?:\\s+-\\w+)*\\s+-c\\s+|\\w+=\\S*\\s+)*['\"]?(?:[^\\s;&|()'\"]*\\/)?rm\\s+(?:[^;&|\\n]*\\s)?['\"]?(?:-[a-zA-Z]*[rR][a-zA-Z]*|--recursive)\\b",
|
|
43
|
+
"flags": "i"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"source": "(?:^|[;&|\\n({\\x60])\\s*(?:(?:sudo|env|command|builtin|exec|nohup|time|xargs|eval|then|do|else)(?:\\s+-{1,2}[\\w-]+(?:=\\S*)?(?:\\s+(?![-'\"])(?!(?:\\S*\\/)?(?:git|gh|npm|rm|opencode|curl|wget)\\b)[^\\s;&|'\"]+)?)*\\s+|(?:bash|sh|zsh|dash|ksh)(?:\\s+-\\w+)*\\s+-c\\s+|\\w+=\\S*\\s+)*['\"]?(?:[^\\s;&|()'\"]*\\/)?(?:git\\s+branch|git(?:\\s+(?:-[cC]\\s*(?:\"[^\"]*\"|'[^']*'|\\S+)|--[\\w-]+(?:=(?:\"[^\"]*\"|'[^']*'|\\S+))?))+\\s+branch)\\b[^;&|\\n]*\\s(?:-[a-zA-Z]*D[a-zA-Z]*|-[a-zA-Z]*(?:df|fd)[a-zA-Z]*)(?=\\s|$)",
|
|
47
|
+
"flags": ""
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"source": "(?:^|[;&|\\n({\\x60])\\s*(?:(?:sudo|env|command|builtin|exec|nohup|time|xargs|eval|then|do|else)(?:\\s+-{1,2}[\\w-]+(?:=\\S*)?(?:\\s+(?![-'\"])(?!(?:\\S*\\/)?(?:git|gh|npm|rm|opencode|curl|wget)\\b)[^\\s;&|'\"]+)?)*\\s+|(?:bash|sh|zsh|dash|ksh)(?:\\s+-\\w+)*\\s+-c\\s+|\\w+=\\S*\\s+)*['\"]?(?:[^\\s;&|()'\"]*\\/)?(?:git\\s+branch|git(?:\\s+(?:-[cC]\\s*(?:\"[^\"]*\"|'[^']*'|\\S+)|--[\\w-]+(?:=(?:\"[^\"]*\"|'[^']*'|\\S+))?))+\\s+branch)\\b(?=[^;&|\\n]*\\s(?:-d|--delete)\\b)(?=[^;&|\\n]*\\s(?:-f|--force)\\b)",
|
|
51
|
+
"flags": ""
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"source": "(?:^|[;&|\\n({\\x60])\\s*(?:(?:sudo|env|command|builtin|exec|nohup|time|xargs|eval|then|do|else)(?:\\s+-{1,2}[\\w-]+(?:=\\S*)?(?:\\s+(?![-'\"])(?!(?:\\S*\\/)?(?:git|gh|npm|rm|opencode|curl|wget)\\b)[^\\s;&|'\"]+)?)*\\s+|(?:bash|sh|zsh|dash|ksh)(?:\\s+-\\w+)*\\s+-c\\s+|\\w+=\\S*\\s+)*['\"]?(?:[^\\s;&|()'\"]*\\/)?(?:git\\s+worktree|git(?:\\s+(?:-[cC]\\s*(?:\"[^\"]*\"|'[^']*'|\\S+)|--[\\w-]+(?:=(?:\"[^\"]*\"|'[^']*'|\\S+))?))+\\s+worktree)\\s+remove\\b",
|
|
55
|
+
"flags": "i"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"source": "(?:^|[;&|\\n({\\x60])\\s*(?:(?:sudo|env|command|builtin|exec|nohup|time|xargs|eval|then|do|else)(?:\\s+-{1,2}[\\w-]+(?:=\\S*)?(?:\\s+(?![-'\"])(?!(?:\\S*\\/)?(?:git|gh|npm|rm|opencode|curl|wget)\\b)[^\\s;&|'\"]+)?)*\\s+|(?:bash|sh|zsh|dash|ksh)(?:\\s+-\\w+)*\\s+-c\\s+|\\w+=\\S*\\s+)*['\"]?(?:[^\\s;&|()'\"]*\\/)?(?:gh\\s+|gh(?:\\s+(?:-R|--repo)(?:\\s+|=)\\S+)+\\s+)pr\\s+(?:create|comment|edit|review|close)\\b",
|
|
59
|
+
"flags": "i"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"source": "(?:^|[;&|\\n({\\x60])\\s*(?:(?:sudo|env|command|builtin|exec|nohup|time|xargs|eval|then|do|else)(?:\\s+-{1,2}[\\w-]+(?:=\\S*)?(?:\\s+(?![-'\"])(?!(?:\\S*\\/)?(?:git|gh|npm|rm|opencode|curl|wget)\\b)[^\\s;&|'\"]+)?)*\\s+|(?:bash|sh|zsh|dash|ksh)(?:\\s+-\\w+)*\\s+-c\\s+|\\w+=\\S*\\s+)*['\"]?(?:[^\\s;&|()'\"]*\\/)?(?:gh\\s+|gh(?:\\s+(?:-R|--repo)(?:\\s+|=)\\S+)+\\s+)issue\\s+(?:create|comment)\\b",
|
|
63
|
+
"flags": "i"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"source": "(?:^|[;&|\\n({\\x60])\\s*(?:(?:sudo|env|command|builtin|exec|nohup|time|xargs|eval|then|do|else)(?:\\s+-{1,2}[\\w-]+(?:=\\S*)?(?:\\s+(?![-'\"])(?!(?:\\S*\\/)?(?:git|gh|npm|rm|opencode|curl|wget)\\b)[^\\s;&|'\"]+)?)*\\s+|(?:bash|sh|zsh|dash|ksh)(?:\\s+-\\w+)*\\s+-c\\s+|\\w+=\\S*\\s+)*['\"]?(?:[^\\s;&|()'\"]*\\/)?(?:gh\\s+|gh(?:\\s+(?:-R|--repo)(?:\\s+|=)\\S+)+\\s+)release\\s+(?:edit|delete)\\b",
|
|
67
|
+
"flags": "i"
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"source": "(?:^|[;&|\\n({\\x60])\\s*(?:(?:sudo|env|command|builtin|exec|nohup|time|xargs|eval|then|do|else)(?:\\s+-{1,2}[\\w-]+(?:=\\S*)?(?:\\s+(?![-'\"])(?!(?:\\S*\\/)?(?:git|gh|npm|rm|opencode|curl|wget)\\b)[^\\s;&|'\"]+)?)*\\s+|(?:bash|sh|zsh|dash|ksh)(?:\\s+-\\w+)*\\s+-c\\s+|\\w+=\\S*\\s+)*['\"]?(?:[^\\s;&|()'\"]*\\/)?(?:gh\\s+|gh(?:\\s+(?:-R|--repo)(?:\\s+|=)\\S+)+\\s+)repo\\s+(?:create|edit|delete)\\b",
|
|
71
|
+
"flags": "i"
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"source": "(?:^|[;&|\\n({\\x60])\\s*(?:(?:sudo|env|command|builtin|exec|nohup|time|xargs|eval|then|do|else)(?:\\s+-{1,2}[\\w-]+(?:=\\S*)?(?:\\s+(?![-'\"])(?!(?:\\S*\\/)?(?:git|gh|npm|rm|opencode|curl|wget)\\b)[^\\s;&|'\"]+)?)*\\s+|(?:bash|sh|zsh|dash|ksh)(?:\\s+-\\w+)*\\s+-c\\s+|\\w+=\\S*\\s+)*['\"]?(?:[^\\s;&|()'\"]*\\/)?(?:gh\\s+|gh(?:\\s+(?:-R|--repo)(?:\\s+|=)\\S+)+\\s+)api\\b[^;&|\\n]*\\s(?:-X\\s*|--method[\\s=]+)(?:POST|PATCH|PUT|DELETE)\\b",
|
|
75
|
+
"flags": "i"
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"source": "(?:^|[;&|\\n({\\x60])\\s*(?:(?:sudo|env|command|builtin|exec|nohup|time|xargs|eval|then|do|else)(?:\\s+-{1,2}[\\w-]+(?:=\\S*)?(?:\\s+(?![-'\"])(?!(?:\\S*\\/)?(?:git|gh|npm|rm|opencode|curl|wget)\\b)[^\\s;&|'\"]+)?)*\\s+|(?:bash|sh|zsh|dash|ksh)(?:\\s+-\\w+)*\\s+-c\\s+|\\w+=\\S*\\s+)*['\"]?(?:[^\\s;&|()'\"]*\\/)?(?:gh\\s+|gh(?:\\s+(?:-R|--repo)(?:\\s+|=)\\S+)+\\s+)api\\b[^;&|\\n]*\\s(?:-[fF]|--field|--raw-field|--input)",
|
|
79
|
+
"flags": ""
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"source": "(?:^|[;&|\\n({\\x60])\\s*(?:(?:sudo|env|command|builtin|exec|nohup|time|xargs|eval|then|do|else)(?:\\s+-{1,2}[\\w-]+(?:=\\S*)?(?:\\s+(?![-'\"])(?!(?:\\S*\\/)?(?:git|gh|npm|rm|opencode|curl|wget)\\b)[^\\s;&|'\"]+)?)*\\s+|(?:bash|sh|zsh|dash|ksh)(?:\\s+-\\w+)*\\s+-c\\s+|\\w+=\\S*\\s+)*['\"]?(?:[^\\s;&|()'\"]*\\/)?git\\s+(?:-[cC]\\s*\\S+\\s+)*-c\\s*['\"]?alias\\.",
|
|
83
|
+
"flags": "i"
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"source": "(?:^|[;&|\\n({\\x60])\\s*(?:(?:sudo|env|command|builtin|exec|nohup|time|xargs|eval|then|do|else)(?:\\s+-{1,2}[\\w-]+(?:=\\S*)?(?:\\s+(?![-'\"])(?!(?:\\S*\\/)?(?:git|gh|npm|rm|opencode|curl|wget)\\b)[^\\s;&|'\"]+)?)*\\s+|(?:bash|sh|zsh|dash|ksh)(?:\\s+-\\w+)*\\s+-c\\s+|\\w+=\\S*\\s+)*['\"]?(?:[^\\s;&|()'\"]*\\/)?opencode\\s+run\\b[^;&|\\n]*\\s(?:-[a-zA-Z]*[sc]\\S*|--session|--continue)(?=[\\s=]|$)",
|
|
87
|
+
"flags": ""
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"source": "(?:^|[;&|\\n({\\x60])\\s*(?:(?:sudo|env|command|builtin|exec|nohup|time|xargs|eval|then|do|else)(?:\\s+-{1,2}[\\w-]+(?:=\\S*)?(?:\\s+(?![-'\"])(?!(?:\\S*\\/)?(?:git|gh|npm|rm|opencode|curl|wget)\\b)[^\\s;&|'\"]+)?)*\\s+|(?:bash|sh|zsh|dash|ksh)(?:\\s+-\\w+)*\\s+-c\\s+|\\w+=\\S*\\s+)*['\"]?(?:[^\\s;&|()'\"]*\\/)?claude\\b[^;&|\\n]*\\s(?:-[a-zA-Z]*[cr]\\S*|--resume|--continue)(?=[\\s=]|$)",
|
|
91
|
+
"flags": ""
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"source": "(?:^|[;&|\\n({\\x60])\\s*(?:(?:sudo|env|command|builtin|exec|nohup|time|xargs|eval|then|do|else)(?:\\s+-{1,2}[\\w-]+(?:=\\S*)?(?:\\s+(?![-'\"])(?!(?:\\S*\\/)?(?:git|gh|npm|rm|opencode|curl|wget)\\b)[^\\s;&|'\"]+)?)*\\s+|(?:bash|sh|zsh|dash|ksh)(?:\\s+-\\w+)*\\s+-c\\s+|\\w+=\\S*\\s+)*['\"]?(?:[^\\s;&|()'\"]*\\/)?opencode\\s+attach\\b",
|
|
95
|
+
"flags": "i"
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"source": "\\/session\\/[^\\s/'\"]+\\/(?:message|prompt_async|command|shell)\\b",
|
|
99
|
+
"flags": "i"
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"source": "\\/\\/[^\\s'\"]*\\/tui\\/|\\/tui\\/(?:append|submit|clear|execute|open|show|publish|control)",
|
|
103
|
+
"flags": "i"
|
|
104
|
+
}
|
|
105
|
+
]
|
|
106
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Brainstorm a topic with the matching skill: bdbrainstorm, bdbmediastorm for event tech, grill-me for a stress test."
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Pick by topic: `bdbmediastorm` for live event technology and show control, `grill-me` when the human wants an existing idea stress-tested, `bdbrainstorm` otherwise. Say which one you chose. Topic: $ARGUMENTS
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Check the machine and the current project, and print suggested permissions.allow entries without writing any settings."
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Run `aos-doctor` (machine check) and report the result. If the current folder is an AOS project, also run the project check `node <aos-project-init skill dir>/scripts/aos-project-doctor.mjs` (it covers `.aos/project.json`, AGENTS.md and the wiki). Print suggested `permissions.allow` entries as text for the human to copy. Never write to settings.json or settings.local.json. Arguments: $ARGUMENTS
|
package/commands/init.md
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Set up the current project folder for AOS: slug, wiki, memory, Synapse map, AGENTS.md."
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Run the `aos-project-init` skill for the current project folder. This is project setup, not machine setup (that is `/bdb-aos:setup`). Arguments: $ARGUMENTS
|
package/commands/loop.md
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Run a prompt repeatedly on an interval, using the harness built-in plus loop templates."
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Use the built-in `/loop <interval> <prompt>` (omit the interval to self-pace). Offer a `loop-templates` template when the human has no prompt yet. Safety: a loop prompt never issues a GO, never types or runs `gogate`, never sets a mode or grant, and never merges, pushes or publishes unless a valid grant covers the action. Act on a guarded step only if the human's immediately preceding message is a literal GO or a valid grant covers it; a loop iteration never satisfies the first condition, so it must STOP and report instead of continuing a blocked guarded step. Templates (CI until green, follow a PR to merge, review rounds until no blockers, daily session summary) live in the `loop-templates` skill with run and duration limits and a stop condition each. Arguments: $ARGUMENTS
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Supervise other Claude Code sessions on this machine: roster, status requests, GO board, idle notices."
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Act as the master session with the `master-session` skill (ACP bridge: `bin/aos-acp.mjs`, see docs/master-session-acp.md). Keep the overview, relay the human's decisions, never decide for the human. Arguments: $ARGUMENTS
|
package/commands/memb.md
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Coordinate parallel coding agents across repositories through the AO daemon."
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Use the `ao-orchestrator` skill. It needs the AO daemon; check that it is running first and stop with a clear message if not. Do not confuse it with `agent-orchestrator`. Arguments: $ARGUMENTS
|
package/commands/plan.md
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Plan end to end: draft, render in plan-canvas or Plan Builder, annotate, await approval, then hand off."
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Run the full planning pipeline: 1) draft the plan with `concise-planning`; 2) always offer the choice between plan-canvas and Plan Builder (`aos-plan-canvas open <dir> --mode bdb-plan-builder`) for rendering; 3) collect annotations and wait for the human's approval; 4) only after approval continue with `writing-plans` or `/bdb-aos:graph`. Topic: $ARGUMENTS
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "List all pb-* playbooks with duration, difficulty and requirements, and start one."
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Run `node <bdb-aos skill dir>/scripts/list-playbooks.mjs` and show its output (name, est_time, difficulty, requires of every `pb-*` skill). If the human names a playbook in the arguments or picks one, start that `pb-*` skill; start nothing otherwise. Each playbook keeps its own go-gate points. Arguments: $ARGUMENTS
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Bring this machine to a complete, verified AOS installation (skills, MCP servers, gate hooks, memB, OpenWiki, Synapse)."
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Run the `aos-setup` skill for this machine. Report what is installed, what was repaired and what is still missing. Arguments: $ARGUMENTS
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Pre-ship framing and the technical release gate, with approvals under the go-gate rules."
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Use `bdb-shipping-skill` for the pre-flight and `godmode-shipping` for the gate. The playbook `pb-ship` can drive the whole flow. Push, merge and publish need the human's GO under the go-gate rules; never request one on the human's behalf. Arguments: $ARGUMENTS
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Start a new composition: project init, brainstorm, then ask whether graph or startcycle follows."
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Sequence: 1) `aos-project-init`; 2) `bdbrainstorm`; 3) stop and ask the human whether `/bdb-aos:graph` (startcycle-graph) or `startcycle` follows. Do not start a pipeline on your own. Idea: $ARGUMENTS
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# BDB AO Codenotch (macOS and Windows, default on)
|
|
2
|
+
|
|
3
|
+
The AOS installer installs the BDB AO Codenotch desktop app by default on **macOS and Windows**. On Linux the step is never offered and no code of it runs.
|
|
4
|
+
|
|
5
|
+
## Controlling it
|
|
6
|
+
|
|
7
|
+
| Mode | Behavior |
|
|
8
|
+
|---|---|
|
|
9
|
+
| Interactive | Prompt "Install BDB AO Codenotch?", default **yes** |
|
|
10
|
+
| Non-interactive (`-y`, no TTY) | Installs unless opted out |
|
|
11
|
+
| Opt out | `AOS_CODENOTCH=0` or `--no-codenotch` (wins over everything) |
|
|
12
|
+
| Force on | `AOS_CODENOTCH=1` or `--codenotch` (skips the question) |
|
|
13
|
+
|
|
14
|
+
A failure at any step (no release yet, 404, offline, rate limit, checksum mismatch, mount error) prints a warning and the AOS install continues; the exit code is never affected. The installer ends with one line saying whether Codenotch was installed, skipped or failed, and how to remove it.
|
|
15
|
+
|
|
16
|
+
## Windows
|
|
17
|
+
|
|
18
|
+
- Asset: `Codenotch-Setup-<version>.exe` plus `Codenotch-Setup-<version>.exe.sha256` from the same release. If the exact name is absent, the single `*Setup*.exe` that has a matching `.sha256` is used; anything ambiguous is refused.
|
|
19
|
+
- The SHA-256 is verified before the installer runs; a mismatch only warns.
|
|
20
|
+
- Runs the NSIS installer silently as `Setup.exe /S`, per-user, no admin, no elevation, with a 5 minute timeout, then checks the version in the per-user uninstall registry key (`HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall`, key `Codenotch`, fallback scan for a subkey whose DisplayName is Codenotch).
|
|
21
|
+
- Installed version same or newer: skipped. An older install AOS did not record is kept unless you confirm interactively.
|
|
22
|
+
- The path of the uninstaller and the version are recorded in `~/.agents/.bdb-codenotch.json` (`%USERPROFILE%` on Windows).
|
|
23
|
+
- `aos-uninstall` runs `<recorded uninstall.exe> /S` only if that file still exists and the registry version and uninstaller path still match the record; otherwise the install is left alone.
|
|
24
|
+
- Default install dir is `%LOCALAPPDATA%\Codenotch` (codenotch.exe, codenotch-hook.exe, uninstall.exe). The installer is unsigned, so Windows SmartScreen may warn.
|
|
25
|
+
- **Unverified:** the registry key (`Codenotch`), `DisplayVersion`, `UninstallString`, and the silent `/S` install and uninstall come from Tauri's stock NSIS template, not from a real build. They must be checked on Windows with the first CI-built installer.
|
|
26
|
+
|
|
27
|
+
## What it does (macOS)
|
|
28
|
+
|
|
29
|
+
1. Reads the release list of the public repo `hybridlabor-api/bdb-ao-codenotch` (`https://api.github.com/repos/hybridlabor-api/bdb-ao-codenotch/releases`, unauthenticated) and picks the newest release that is neither draft nor prerelease and carries this platform's asset plus a `.sha256`; other releases are ignored. A missing repo (404), no matching release, or a GitHub rate limit prints a friendly note and the install continues; nothing fails.
|
|
30
|
+
2. Downloads the `.dmg` and verifies its `.sha256` asset from the same release **before** mounting. A mismatch or a missing checksum refuses the install.
|
|
31
|
+
3. Mounts with `hdiutil attach -nobrowse -readonly -mountpoint <temp dir>` and always detaches again, even on failure.
|
|
32
|
+
4. Copies the single `.app` from the DMG to `/Applications`, or to `~/Applications` when `/Applications` is not writable. Never uses sudo.
|
|
33
|
+
5. Runs `xattr -dr com.apple.quarantine` on the copy. The app is **ad-hoc signed** until Apple developer certificates are in place, so Gatekeeper would otherwise block it.
|
|
34
|
+
6. Records path, version and bundle id in `~/.agents/.bdb-codenotch.json`.
|
|
35
|
+
|
|
36
|
+
## Idempotence and safety
|
|
37
|
+
|
|
38
|
+
- Installed version same or newer (`CFBundleShortVersionString`): skipped.
|
|
39
|
+
- Older and installed by AOS (recorded path, bundle id and version still match): asked in interactive mode, replaced automatically with `AOS_CODENOTCH=1`. The old copy is restored if the new copy fails.
|
|
40
|
+
- Older and not installed by AOS: kept with a note in non-interactive mode; in interactive mode replaced only after you confirm.
|
|
41
|
+
|
|
42
|
+
## Uninstall
|
|
43
|
+
|
|
44
|
+
`aos-uninstall` removes only the recorded `.app`, and only while its bundle id and version still match the record. A replaced or otherwise unknown app is kept. `--dry-run` lists the decision.
|