@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.
- package/LICENSE +21 -0
- package/README.md +4 -2
- package/dist/src/footprint.d.ts +22 -0
- package/dist/src/footprint.js +152 -0
- package/dist/src/index.d.ts +44 -0
- package/dist/src/index.js +217 -0
- package/dist/src/preset.d.ts +4 -0
- package/dist/src/preset.js +33 -0
- package/measure/agent-proxy.mjs +686 -0
- package/measure/claude-measure.mjs +113 -0
- package/measure/keytec-coding.json +36 -0
- package/measure/keytec-ops.json +30 -0
- package/measure/keytec-plan.json +32 -0
- package/measure/keytec-review.json +32 -0
- package/package.json +27 -4
|
@@ -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.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
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
|
+
}
|