@bakers-build/addon-claude 0.0.0-stage → 0.1.0-next.38

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.
@@ -0,0 +1,113 @@
1
+ /**
2
+ * claude-measure — launch wrapper for `@bakers-build/addon-claude` `with.measure`.
3
+ *
4
+ * node claude-measure.mjs claude <claude args…>
5
+ *
6
+ * Writes the state group's settings, with the project's own `enabledPlugins`
7
+ * on top, to `.bakers/claude-measure.settings.json` — or, where git does not
8
+ * ignore that path, to a temporary file whose path replaces the `--settings`
9
+ * argument, so a foreign repository gains no untracked file. It then
10
+ * starts agent-proxy on an ephemeral loopback port, runs the command with
11
+ * `ANTHROPIC_BASE_URL` pointing at it, and closes the proxy when the command
12
+ * exits. The proxy therefore lives exactly as long as the agent process: no
13
+ * conductor state, nothing to reap after a restart.
14
+ *
15
+ * Reads `BB_STATE`, `BB_TICKET_IDENTIFIER` and `BB_RUN_UUID` from the run
16
+ * env; logs go to `assets-ai/<identifier>/node/<run uuid>/`, exported to the
17
+ * command as `BB_PROXY_LOG_DIR`. When the
18
+ * proxy cannot start (no identifier, log directory not gitignored) the command
19
+ * still runs, unmeasured, with a warning on stderr.
20
+ */
21
+
22
+ import { spawn, spawnSync } from 'node:child_process';
23
+ import { randomUUID } from 'node:crypto';
24
+ import fs from 'node:fs';
25
+ import os from 'node:os';
26
+ import path from 'node:path';
27
+ import { fileURLToPath } from 'node:url';
28
+ import { startServer } from './agent-proxy.mjs';
29
+
30
+ const HERE = path.dirname(fileURLToPath(import.meta.url));
31
+ const SETTINGS_REL = path.join('.bakers', 'claude-measure.settings.json');
32
+
33
+ const GROUPS = {
34
+ qualification: 'plan',
35
+ spec: 'plan',
36
+ diagnose: 'plan',
37
+ coding: 'coding',
38
+ review: 'review',
39
+ };
40
+
41
+ const [command, ...args] = process.argv.slice(2);
42
+ if (!command) {
43
+ console.error('usage: node claude-measure.mjs <command> [args…]');
44
+ process.exit(2);
45
+ }
46
+
47
+ /** A project's own plugin choice, e.g. an opt-out of a stale plugin copy. */
48
+ function projectPlugins() {
49
+ const merged = {};
50
+ for (const file of ['settings.json', 'settings.local.json']) {
51
+ try {
52
+ Object.assign(
53
+ merged,
54
+ JSON.parse(fs.readFileSync(path.join('.claude', file), 'utf8'))
55
+ .enabledPlugins,
56
+ );
57
+ } catch {
58
+ /* absent or unreadable: nothing to honour */
59
+ }
60
+ }
61
+ return merged;
62
+ }
63
+
64
+ // `--settings` outranks project settings, so fold the project's enabledPlugins
65
+ // into the copy: the profile is a default, the project has the last word.
66
+ const group = GROUPS[process.env.BB_STATE] ?? 'ops';
67
+ const profile = JSON.parse(
68
+ fs.readFileSync(path.join(HERE, `keytec-${group}.json`), 'utf8'),
69
+ );
70
+ profile.enabledPlugins = { ...profile.enabledPlugins, ...projectPlugins() };
71
+ const ignored =
72
+ spawnSync('git', ['check-ignore', '-q', SETTINGS_REL]).status === 0;
73
+ const settingsFile = ignored
74
+ ? SETTINGS_REL
75
+ : path.join(os.tmpdir(), `claude-measure-${randomUUID()}.settings.json`);
76
+ // The last one: an alias's own `--settings` precedes the measure flags.
77
+ const settingsAt = args.lastIndexOf('--settings');
78
+ if (settingsAt !== -1) args[settingsAt + 1] = settingsFile;
79
+ fs.mkdirSync(path.dirname(settingsFile), { recursive: true });
80
+ fs.writeFileSync(settingsFile, `${JSON.stringify(profile, null, 2)}\n`);
81
+
82
+ const env = { ...process.env };
83
+ let proxy;
84
+ try {
85
+ // One subdirectory per run, so several runs of a ticket stay apart.
86
+ proxy = await startServer({
87
+ port: 0,
88
+ cwd: process.cwd(),
89
+ quiet: true,
90
+ logSubdir: process.env.BB_RUN_UUID || undefined,
91
+ });
92
+ env.ANTHROPIC_BASE_URL = `http://127.0.0.1:${proxy.address.port}`;
93
+ env.BB_PROXY_LOG_DIR = proxy.logDirectory;
94
+ } catch (err) {
95
+ console.error(`${err.message} — running unmeasured`);
96
+ }
97
+
98
+ const child = spawn(command, args, { stdio: 'inherit', env });
99
+ // The terminal sends SIGINT to the whole process group; the child decides.
100
+ process.on('SIGINT', () => {});
101
+ for (const signal of ['SIGTERM', 'SIGHUP']) {
102
+ process.on(signal, () => child.kill(signal));
103
+ }
104
+ child.on('error', (err) => {
105
+ console.error(`claude-measure: ${err.message}`);
106
+ if (!ignored) fs.rmSync(settingsFile, { force: true });
107
+ process.exit(127);
108
+ });
109
+ child.on('exit', async (code, signal) => {
110
+ await proxy?.close();
111
+ if (!ignored) fs.rmSync(settingsFile, { force: true });
112
+ process.exit(code ?? (signal ? 128 + os.constants.signals[signal] : 1));
113
+ });
@@ -0,0 +1,36 @@
1
+ {
2
+ "effortLevel": "high",
3
+ "autoMemoryEnabled": false,
4
+ "enabledPlugins": {
5
+ "bakers@bakers": true,
6
+ "superpowers@claude-plugins-official": true,
7
+ "mattpocock-skills@keytec-mattpocock": true,
8
+ "keytec-drupal@keytec": true,
9
+ "designbook@designbook": true,
10
+ "designbook-drupal@designbook": true,
11
+ "designbook-css-tailwind@designbook": true
12
+ },
13
+ "permissions": {
14
+ "deny": [
15
+ "CronCreate",
16
+ "CronDelete",
17
+ "CronList",
18
+ "ScheduleWakeup",
19
+ "RemoteTrigger",
20
+ "SendMessage",
21
+ "EnterWorktree",
22
+ "ExitWorktree",
23
+ "ReportFindings",
24
+ "Workflow",
25
+ "WebSearch",
26
+ "Artifact",
27
+ "ArtifactComments",
28
+ "ArtifactData",
29
+ "DesignSync",
30
+ "SendFeedback",
31
+ "ShareOnboardingGuide",
32
+ "PushNotification",
33
+ "mcp__claude-in-chrome"
34
+ ]
35
+ }
36
+ }
@@ -0,0 +1,30 @@
1
+ {
2
+ "effortLevel": "medium",
3
+ "autoMemoryEnabled": false,
4
+ "enabledPlugins": {
5
+ "bakers@bakers": true
6
+ },
7
+ "permissions": {
8
+ "deny": [
9
+ "CronCreate",
10
+ "CronDelete",
11
+ "CronList",
12
+ "ScheduleWakeup",
13
+ "RemoteTrigger",
14
+ "SendMessage",
15
+ "EnterWorktree",
16
+ "ExitWorktree",
17
+ "ReportFindings",
18
+ "Workflow",
19
+ "WebSearch",
20
+ "Artifact",
21
+ "ArtifactComments",
22
+ "ArtifactData",
23
+ "DesignSync",
24
+ "SendFeedback",
25
+ "ShareOnboardingGuide",
26
+ "PushNotification",
27
+ "mcp__claude-in-chrome"
28
+ ]
29
+ }
30
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "effortLevel": "high",
3
+ "autoMemoryEnabled": false,
4
+ "enabledPlugins": {
5
+ "bakers@bakers": true,
6
+ "superpowers@claude-plugins-official": true,
7
+ "mattpocock-skills@keytec-mattpocock": true,
8
+ "keytec-drupal@keytec": true
9
+ },
10
+ "permissions": {
11
+ "deny": [
12
+ "CronCreate",
13
+ "CronDelete",
14
+ "CronList",
15
+ "ScheduleWakeup",
16
+ "RemoteTrigger",
17
+ "SendMessage",
18
+ "EnterWorktree",
19
+ "ExitWorktree",
20
+ "ReportFindings",
21
+ "Workflow",
22
+ "Artifact",
23
+ "ArtifactComments",
24
+ "ArtifactData",
25
+ "DesignSync",
26
+ "SendFeedback",
27
+ "ShareOnboardingGuide",
28
+ "PushNotification",
29
+ "mcp__claude-in-chrome"
30
+ ]
31
+ }
32
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "effortLevel": "high",
3
+ "autoMemoryEnabled": false,
4
+ "enabledPlugins": {
5
+ "bakers@bakers": true,
6
+ "superpowers@claude-plugins-official": true,
7
+ "mattpocock-skills@keytec-mattpocock": true,
8
+ "keytec-drupal@keytec": true
9
+ },
10
+ "permissions": {
11
+ "deny": [
12
+ "CronCreate",
13
+ "CronDelete",
14
+ "CronList",
15
+ "ScheduleWakeup",
16
+ "RemoteTrigger",
17
+ "SendMessage",
18
+ "EnterWorktree",
19
+ "ExitWorktree",
20
+ "ReportFindings",
21
+ "Workflow",
22
+ "Artifact",
23
+ "ArtifactComments",
24
+ "ArtifactData",
25
+ "DesignSync",
26
+ "SendFeedback",
27
+ "ShareOnboardingGuide",
28
+ "PushNotification",
29
+ "mcp__claude-in-chrome"
30
+ ]
31
+ }
32
+ }
package/package.json CHANGED
@@ -1,6 +1,29 @@
1
1
  {
2
2
  "name": "@bakers-build/addon-claude",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0-next.38",
4
+ "description": "bakers.build agent plugin for the Claude CLI.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "exports": {
8
+ ".": "./dist/src/index.js",
9
+ "./preset": "./dist/src/preset.js"
10
+ },
11
+ "files": [
12
+ "dist/src",
13
+ "measure/*.json",
14
+ "measure/agent-proxy.mjs",
15
+ "measure/claude-measure.mjs"
16
+ ],
17
+ "publishConfig": {
18
+ "access": "public"
19
+ },
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://git.key-tec.de/bakers-build/bakers-build.git",
23
+ "directory": "bakers-cli/addons/claude"
24
+ },
25
+ "peerDependencies": {
26
+ "@bakers-build/conductor": "^0.1.0-next.38",
27
+ "@bakers-build/core": "^0.1.0-next.38"
28
+ }
29
+ }