borgmcp 0.9.0 → 0.9.2

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,83 @@
1
+ import type { Role } from './role-resolver.js';
2
+ export interface AssimilateFlags {
3
+ worktree?: string;
4
+ template?: string;
5
+ noTemplate?: boolean;
6
+ cubeName?: string;
7
+ here?: boolean;
8
+ yes?: boolean;
9
+ }
10
+ export interface AssimilateArgs {
11
+ role: string | undefined;
12
+ flags: AssimilateFlags;
13
+ }
14
+ export interface CubeSummary {
15
+ id: string;
16
+ name: string;
17
+ }
18
+ export interface CubeDetail {
19
+ id: string;
20
+ name: string;
21
+ roles: Role[];
22
+ }
23
+ export interface AssimilateResult {
24
+ cube_id: string;
25
+ drone_id: string;
26
+ drone_label: string;
27
+ session_token: string;
28
+ role_id: string;
29
+ }
30
+ export interface ActiveCube {
31
+ cubeId: string;
32
+ droneId: string;
33
+ name: string;
34
+ sessionToken: string;
35
+ droneLabel: string;
36
+ apiUrl: string;
37
+ }
38
+ export interface AssimilateDeps {
39
+ runSync: (cmd: string, args: string[], cwd?: string) => {
40
+ status: number | null;
41
+ stdout: string;
42
+ stderr: string;
43
+ };
44
+ pathExists: (p: string) => boolean;
45
+ cwd: () => string;
46
+ chdir: (p: string) => void;
47
+ exec: (cmd: string, args: string[], cwd: string) => Promise<number>;
48
+ stderr: (line: string) => void;
49
+ stdout: (line: string) => void;
50
+ prompt: (message: string) => Promise<string>;
51
+ isTTY: () => boolean;
52
+ getHostname: () => string;
53
+ setTerminalTitle: (label: string, cubeName: string) => void;
54
+ getActiveCube: () => Promise<ActiveCube | null>;
55
+ setActiveCube: (a: ActiveCube) => Promise<void>;
56
+ findProjectRoot: (cwd: string) => string;
57
+ getCachedAuth: () => Promise<{
58
+ token: string;
59
+ apiUrl: string;
60
+ } | null>;
61
+ runSetup: () => Promise<{
62
+ token: string;
63
+ apiUrl: string;
64
+ }>;
65
+ listCubes: (apiUrl: string, token: string) => Promise<CubeSummary[]>;
66
+ getCube: (apiUrl: string, token: string, cubeId: string) => Promise<CubeDetail>;
67
+ createCube: (apiUrl: string, token: string, params: {
68
+ name: string;
69
+ template?: string;
70
+ }) => Promise<CubeDetail>;
71
+ assimilate: (apiUrl: string, token: string, params: {
72
+ cube_id: string;
73
+ role_id: string;
74
+ hostname?: string | null;
75
+ }) => Promise<AssimilateResult>;
76
+ listTemplates: (apiUrl: string, token: string) => Promise<Array<{
77
+ name: string;
78
+ description: string;
79
+ }>>;
80
+ getInboxPath: (cubeId: string, droneId: string) => string;
81
+ }
82
+ export declare function runAssimilate(args: AssimilateArgs, deps: AssimilateDeps): Promise<number>;
83
+ //# sourceMappingURL=assimilate-cmd.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assimilate-cmd.d.ts","sourceRoot":"","sources":["../src/assimilate-cmd.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,232 @@
1
+ import { dirname, basename, join } from 'node:path';
2
+ import { roleSlug, matchRoleByName, pickDefaultRole } from './role-resolver.js';
3
+ import { deriveCubeName, parseGitRemote, sanitizeRemoteUrl } from './cube-name.js';
4
+ import { validateName } from './name-validator.js';
5
+ export async function runAssimilate(args, deps) {
6
+ // ----- Input validation (before any subprocess work) -----
7
+ if (args.role !== undefined) {
8
+ const v = validateName(args.role);
9
+ if (!v.ok) {
10
+ deps.stderr(v.error + '\n');
11
+ return 1;
12
+ }
13
+ }
14
+ if (args.flags.worktree !== undefined) {
15
+ const v = validateName(args.flags.worktree);
16
+ if (!v.ok) {
17
+ deps.stderr(v.error + '\n');
18
+ return 1;
19
+ }
20
+ }
21
+ // ----- Step 1: Auth check -----
22
+ let auth = await deps.getCachedAuth();
23
+ if (!auth) {
24
+ if (!deps.isTTY() && !args.flags.yes) {
25
+ deps.stderr('borg setup required and stdin is non-interactive. Run `borg setup` first in an interactive terminal.\n');
26
+ return 1;
27
+ }
28
+ auth = await deps.runSetup();
29
+ }
30
+ // ----- Step 2: Cube-name derivation -----
31
+ const projectRoot = deps.findProjectRoot(deps.cwd());
32
+ let cubeName;
33
+ if (args.flags.cubeName) {
34
+ cubeName = args.flags.cubeName;
35
+ }
36
+ else {
37
+ const remoteResult = deps.runSync('git', ['remote', 'get-url', 'origin'], projectRoot);
38
+ const remoteUrl = remoteResult.status === 0 ? remoteResult.stdout : null;
39
+ cubeName = deriveCubeName(projectRoot, remoteUrl);
40
+ // UX-F4 (drone-7 Phase E review): emit a stderr nudge when the
41
+ // remote was readable but didn't parse, so the user has a signal
42
+ // that auto-derivation diverged from their git remote.
43
+ //
44
+ // BUG-1 fix (v0.9.2): the prior implementation used
45
+ // `cubeName === deriveCubeName(projectRoot, null)` as a proxy for
46
+ // "parse failed and we fell through to basename." False positive
47
+ // when the repo dir name matches the parsed remote name (which is
48
+ // the common case). Now we test parse success/failure directly by
49
+ // calling sanitizeRemoteUrl + parseGitRemote and emit the nudge
50
+ // only when the remote was readable, sanitization succeeded, but
51
+ // parsing returned null — the genuine "fell through to basename"
52
+ // case.
53
+ if (remoteUrl) {
54
+ const sanitized = sanitizeRemoteUrl(remoteUrl);
55
+ const parsedRepo = sanitized ? parseGitRemote(sanitized) : null;
56
+ if (sanitized && !parsedRepo && cubeName) {
57
+ deps.stderr(`couldn't parse git remote '${sanitized}' — using directory name '${cubeName}' as cube name\n`);
58
+ }
59
+ }
60
+ }
61
+ if (!cubeName) {
62
+ deps.stderr('could not derive cube name — pass --cube-name <name>\n');
63
+ return 1;
64
+ }
65
+ // ----- Step 3: Worktree decision -----
66
+ const roleArgSlug = args.role ? roleSlug(args.role) : null;
67
+ const existing = await deps.getActiveCube();
68
+ const wantSibling = args.flags.worktree !== undefined || existing !== null;
69
+ if (wantSibling) {
70
+ if (existing && args.flags.here) {
71
+ deps.stderr(`this directory already hosts an active drone; remove --here or run from a fresh worktree\n`);
72
+ return 1;
73
+ }
74
+ const parent = dirname(projectRoot);
75
+ const repoBase = basename(projectRoot);
76
+ const suffix = args.flags.worktree ?? roleArgSlug ?? 'drone';
77
+ let candidate = join(parent, `${repoBase}-${suffix}`);
78
+ let n = 2;
79
+ while (deps.pathExists(candidate) || worktreeRegistered(deps, projectRoot, candidate)) {
80
+ candidate = join(parent, `${repoBase}-${suffix}-${n}`);
81
+ n++;
82
+ }
83
+ const wt = deps.runSync('git', ['worktree', 'add', '--detach', candidate], projectRoot);
84
+ if (wt.status !== 0) {
85
+ deps.stderr(`git worktree add failed: ${wt.stderr}\n`);
86
+ return 1;
87
+ }
88
+ deps.stderr(`spawned sibling worktree at ${candidate}; ` +
89
+ `original dir is registered as active (edit ~/.config/borgmcp/cubes.json if stale).\n`);
90
+ deps.chdir(candidate);
91
+ }
92
+ const spawnedWorktreePath = wantSibling ? deps.cwd() : null;
93
+ // ----- Step 4: Cube existence check -----
94
+ const allCubes = await deps.listCubes(auth.apiUrl, auth.token);
95
+ const existingCube = allCubes.find((c) => c.name === cubeName);
96
+ // ----- Step 4.5: Fetch detail OR step 5: create -----
97
+ let cubeDetail;
98
+ let isFirstDrone;
99
+ if (existingCube) {
100
+ cubeDetail = await deps.getCube(auth.apiUrl, auth.token, existingCube.id);
101
+ isFirstDrone = false;
102
+ }
103
+ else {
104
+ // ----- Step 5: First-drone bootstrap -----
105
+ let chosenTemplate;
106
+ if (args.flags.template) {
107
+ chosenTemplate = args.flags.template;
108
+ }
109
+ else if (args.flags.noTemplate) {
110
+ chosenTemplate = undefined;
111
+ }
112
+ else if (!deps.isTTY()) {
113
+ if (!args.flags.yes) {
114
+ deps.stderr('cube creation needs a template choice but stdin is non-interactive.\n' +
115
+ 'Pass --template <name>, --no-template, or --yes (defaults to software-dev).\n');
116
+ return 1;
117
+ }
118
+ chosenTemplate = 'software-dev';
119
+ }
120
+ else if (args.flags.yes) {
121
+ chosenTemplate = 'software-dev';
122
+ }
123
+ else {
124
+ const templates = await deps.listTemplates(auth.apiUrl, auth.token);
125
+ const lines = ['First drone joining a new cube. Apply a template?'];
126
+ templates.forEach((t, i) => {
127
+ const tag = i === 0 ? ' (default)' : '';
128
+ lines.push(` ${i + 1}) ${t.name}${tag} — ${t.description}`);
129
+ });
130
+ lines.push(` ${templates.length + 1}) skip — no template`);
131
+ const answer = (await deps.prompt(lines.join('\n') + '\n[1]: ')).trim();
132
+ const choice = answer === '' ? 1 : parseInt(answer, 10);
133
+ if (Number.isNaN(choice) || choice < 1 || choice > templates.length + 1) {
134
+ deps.stderr(`invalid choice "${answer}"\n`);
135
+ return 1;
136
+ }
137
+ chosenTemplate = choice <= templates.length ? templates[choice - 1].name : undefined;
138
+ }
139
+ cubeDetail = await deps.createCube(auth.apiUrl, auth.token, chosenTemplate ? { name: cubeName, template: chosenTemplate } : { name: cubeName });
140
+ isFirstDrone = true;
141
+ }
142
+ // ----- Step 6: Role resolution -----
143
+ let resolvedRole;
144
+ if (args.role !== undefined) {
145
+ resolvedRole = matchRoleByName(cubeDetail.roles, args.role);
146
+ if (!resolvedRole) {
147
+ const available = cubeDetail.roles.map((r) => r.name).join(', ');
148
+ deps.stderr(`no role matching "${args.role}" in cube "${cubeDetail.name}". Available: ${available}\n` +
149
+ `(Use --template <name> on first-drone setup or run \`borg:create-role\` from inside Claude.)\n`);
150
+ return 1;
151
+ }
152
+ }
153
+ else {
154
+ resolvedRole = pickDefaultRole(cubeDetail.roles, { isFirstDrone });
155
+ if (!resolvedRole) {
156
+ deps.stderr(`cube "${cubeDetail.name}" has no default or human-seat role; cannot infer a role. ` +
157
+ `Either pass a role argument explicitly (e.g. \`borg assimilate builder\`) or ` +
158
+ `run \`borg:create-role\` from inside Claude to set up roles.\n`);
159
+ return 1;
160
+ }
161
+ }
162
+ // ----- Step 7: Assimilate + persist -----
163
+ // CR-PE-F2 (drone-2 Phase E review): wrap in try/catch and roll
164
+ // back the step-3 worktree on failure so partial state doesn't
165
+ // orphan a directory + git-registry entry. Best-effort rollback;
166
+ // if `git worktree remove` itself fails, surface a friendly
167
+ // manual-cleanup hint.
168
+ let result;
169
+ try {
170
+ result = await deps.assimilate(auth.apiUrl, auth.token, {
171
+ cube_id: cubeDetail.id,
172
+ role_id: resolvedRole.id,
173
+ hostname: deps.getHostname(),
174
+ });
175
+ await deps.setActiveCube({
176
+ cubeId: result.cube_id,
177
+ droneId: result.drone_id,
178
+ name: cubeDetail.name,
179
+ sessionToken: result.session_token,
180
+ droneLabel: result.drone_label,
181
+ apiUrl: auth.apiUrl,
182
+ });
183
+ }
184
+ catch (err) {
185
+ const message = err instanceof Error ? err.message : String(err);
186
+ deps.stderr(`assimilate failed: ${message}\n`);
187
+ if (spawnedWorktreePath) {
188
+ const rm = deps.runSync('git', ['worktree', 'remove', '--force', spawnedWorktreePath], projectRoot);
189
+ if (rm.status === 0) {
190
+ deps.stderr(`rolled back spawned worktree at ${spawnedWorktreePath}\n`);
191
+ }
192
+ else {
193
+ deps.stderr(`manual cleanup needed: \`git worktree remove --force ${spawnedWorktreePath}\` ` +
194
+ `(rollback attempt failed: ${rm.stderr.trim() || 'unknown'})\n`);
195
+ }
196
+ }
197
+ return 1;
198
+ }
199
+ // ----- Step 8: Launch Claude Code -----
200
+ // Mirrors the kickoff invocation from claude.ts (no-args path): Claude
201
+ // picks up the newly-persisted ActiveCube via the MCP stdio server on
202
+ // startup. The kickoff prompt re-enters /loop borg:regen so the new
203
+ // drone bootstraps into the cube cleanly. The monitor clause (CR-PE-F1)
204
+ // arms the inbox tail so the new drone wakes on peer log entries in
205
+ // real time — without this, drones miss real-time wake events during
206
+ // the bootstrap window and only self-heal at the /loop heartbeat.
207
+ deps.setTerminalTitle(result.drone_label, cubeDetail.name);
208
+ const claudeCwd = deps.cwd(); // post-chdir if step 3 spawned a worktree
209
+ const inboxPath = deps.getInboxPath(result.cube_id, result.drone_id);
210
+ const monitorClause = `If you haven't yet, arm a persistent Monitor running the command ` +
211
+ `\`borg-inbox-monitor ${inboxPath}\` ` +
212
+ `so each event's task-notification title summarizes the new cube log entry ` +
213
+ `(drone label, role, and first ~80 chars of the message body) — letting you ` +
214
+ `triage events without reading the full body. `;
215
+ const kickoff = `/loop Call borg:regen and follow the playbook in its response. ` +
216
+ `Note: at session start the borg MCP server is still spinning up in ` +
217
+ `parallel — if a system reminder claims "MCP server disconnected" or ` +
218
+ `the borg: tools are not yet registered, do NOT bail. Load them via ` +
219
+ `ToolSearch and attempt the call; the server typically becomes ` +
220
+ `available within a few seconds. ` +
221
+ monitorClause +
222
+ `Use a 30-minute (1800s) fallback heartbeat for ScheduleWakeup.`;
223
+ const exitCode = await deps.exec('claude', [kickoff], claudeCwd);
224
+ return exitCode;
225
+ }
226
+ function worktreeRegistered(deps, projectRoot, candidate) {
227
+ const res = deps.runSync('git', ['worktree', 'list', '--porcelain'], projectRoot);
228
+ if (res.status !== 0)
229
+ return false;
230
+ return res.stdout.split('\n').some((line) => line === `worktree ${candidate}`);
231
+ }
232
+ //# sourceMappingURL=assimilate-cmd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assimilate-cmd.js","sourceRoot":"","sources":["../src/assimilate-cmd.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Real-IO factory for the `borg assimilate` orchestrator. Produces a
3
+ * fully-wired `AssimilateDeps` whose seams call into the existing
4
+ * client modules (remote-client HTTP, cubes.ts persistence, auth.ts
5
+ * setup wizard, terminal-title helper).
6
+ *
7
+ * Test code never calls this — tests construct stub deps directly
8
+ * (see `client/__tests__/assimilate-cmd.test.ts:makeStubDeps`).
9
+ */
10
+ import type { AssimilateDeps } from './assimilate-cmd.js';
11
+ export declare function buildDefaultAssimilateDeps(): AssimilateDeps;
12
+ //# sourceMappingURL=assimilate-deps.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assimilate-deps.d.ts","sourceRoot":"","sources":["../src/assimilate-deps.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAmB1D,wBAAgB,0BAA0B,IAAI,cAAc,CAkG3D"}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Real-IO factory for the `borg assimilate` orchestrator. Produces a
3
+ * fully-wired `AssimilateDeps` whose seams call into the existing
4
+ * client modules (remote-client HTTP, cubes.ts persistence, auth.ts
5
+ * setup wizard, terminal-title helper).
6
+ *
7
+ * Test code never calls this — tests construct stub deps directly
8
+ * (see `client/__tests__/assimilate-cmd.test.ts:makeStubDeps`).
9
+ */
10
+ import { spawnSync, spawn as spawnChild } from 'node:child_process';
11
+ import { existsSync } from 'node:fs';
12
+ import { hostname as osHostname } from 'node:os';
13
+ import { createInterface } from 'node:readline/promises';
14
+ import { API_URL, getValidToken, listCubes as remoteListCubes, getCube as remoteGetCube, createCube as remoteCreateCube, assimilate as remoteAssimilate, listTemplates as remoteListTemplates, } from './remote-client.js';
15
+ import { findProjectRoot as cubesFindProjectRoot, getActiveCube as cubesGetActive, setActiveCube as cubesSetActive, inboxPathForDrone, } from './cubes.js';
16
+ import { authenticateWithGoogle } from './auth.js';
17
+ import { setTerminalTitle as setTitle } from './terminal-title.js';
18
+ export function buildDefaultAssimilateDeps() {
19
+ return {
20
+ runSync: (cmd, args, cwd) => {
21
+ const r = spawnSync(cmd, args, { cwd, encoding: 'utf-8' });
22
+ return {
23
+ status: r.status,
24
+ stdout: r.stdout ?? '',
25
+ stderr: r.stderr ?? '',
26
+ };
27
+ },
28
+ pathExists: (p) => existsSync(p),
29
+ cwd: () => process.cwd(),
30
+ chdir: (p) => process.chdir(p),
31
+ exec: (cmd, args, cwd) => new Promise((resolveExit, rejectExit) => {
32
+ const child = spawnChild(cmd, args, { cwd, stdio: 'inherit', shell: false });
33
+ child.on('error', rejectExit);
34
+ child.on('exit', (code) => resolveExit(code ?? 0));
35
+ }),
36
+ stderr: (line) => process.stderr.write(line),
37
+ stdout: (line) => process.stdout.write(line),
38
+ prompt: async (message) => {
39
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
40
+ try {
41
+ return await rl.question(message);
42
+ }
43
+ finally {
44
+ rl.close();
45
+ }
46
+ },
47
+ isTTY: () => process.stdin.isTTY === true,
48
+ getHostname: () => osHostname(),
49
+ setTerminalTitle: (label, cubeName) => {
50
+ setTitle({ label, cubeName }, cubeName);
51
+ },
52
+ getActiveCube: () => cubesGetActive(),
53
+ setActiveCube: (a) => cubesSetActive(a),
54
+ findProjectRoot: (cwd) => cubesFindProjectRoot(cwd),
55
+ getCachedAuth: async () => {
56
+ try {
57
+ const token = await getValidToken();
58
+ return { token, apiUrl: API_URL };
59
+ }
60
+ catch {
61
+ return null;
62
+ }
63
+ },
64
+ runSetup: async () => {
65
+ await authenticateWithGoogle();
66
+ const token = await getValidToken();
67
+ return { token, apiUrl: API_URL };
68
+ },
69
+ listCubes: async (_apiUrl, _token) => {
70
+ const { cubes } = await remoteListCubes();
71
+ return cubes.map((c) => ({ id: c.id, name: c.name }));
72
+ },
73
+ getCube: async (_apiUrl, _token, cubeId) => {
74
+ // BUG-2 fix (v0.9.2): remote-client now unwraps the server's
75
+ // `{cube, roles, drones}` shape, so the returned object is
76
+ // already flat with id/name/roles at the top level.
77
+ const cube = await remoteGetCube(cubeId);
78
+ return { id: cube.id, name: cube.name, roles: cube.roles };
79
+ },
80
+ createCube: async (_apiUrl, _token, params) => {
81
+ const cube = await remoteCreateCube(params.name, '', params.template ? { template: params.template } : undefined);
82
+ return { id: cube.id, name: cube.name, roles: cube.roles };
83
+ },
84
+ assimilate: async (_apiUrl, _token, params) => {
85
+ const result = await remoteAssimilate({ cube_id: params.cube_id, role_id: params.role_id }, undefined, params.hostname ?? null);
86
+ return {
87
+ cube_id: result.cube.id,
88
+ drone_id: result.drone.id,
89
+ drone_label: result.drone.label,
90
+ session_token: result.sessionToken,
91
+ role_id: result.role.id,
92
+ };
93
+ },
94
+ listTemplates: async (_apiUrl, _token) => {
95
+ const { templates } = await remoteListTemplates();
96
+ return templates.map((t) => ({ name: t.name, description: t.description }));
97
+ },
98
+ // CR-PE-F1 wiring (Phase E merge brought this seam in): compute the
99
+ // inbox file path used by the borg-inbox-monitor command in step 8
100
+ // kickoff. Pure helper from cubes.ts; same computation claude.ts uses.
101
+ getInboxPath: (cubeId, droneId) => inboxPathForDrone(cubeId, droneId),
102
+ };
103
+ }
104
+ //# sourceMappingURL=assimilate-deps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assimilate-deps.js","sourceRoot":"","sources":["../src/assimilate-deps.ts"],"names":[],"mappings":"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"}
package/dist/claude.js CHANGED
@@ -20,8 +20,11 @@ import { basename } from 'node:path';
20
20
  import chalk from 'chalk';
21
21
  import { getActiveCube, inboxPathForDrone } from './cubes.js';
22
22
  import { handleVersionFlag } from './version.js';
23
- import { parseSpawnArgs, runSpawn } from './spawn.js';
23
+ import { runSpawn } from './spawn.js';
24
24
  import { parseSyncArgs, runSync } from './sync.js';
25
+ import { parseAssimilateArgs } from './parse-assimilate-args.js';
26
+ import { runAssimilate } from './assimilate-cmd.js';
27
+ import { buildDefaultAssimilateDeps } from './assimilate-deps.js';
25
28
  import { setTerminalTitle } from './terminal-title.js';
26
29
  import { initConsolePrefix, consolePrefix } from './console-prefix.js';
27
30
  async function main() {
@@ -35,13 +38,19 @@ async function main() {
35
38
  await import('./setup.js');
36
39
  return;
37
40
  }
38
- if (process.argv[2] === 'spawn') {
39
- const parsed = parseSpawnArgs(process.argv.slice(3));
41
+ if (process.argv[2] === 'assimilate') {
42
+ const parsed = parseAssimilateArgs(process.argv.slice(3));
40
43
  if (!parsed.ok) {
41
- process.stderr.write(chalk.red(`${consolePrefix()}◼ borg spawn: ${parsed.error}\n`));
44
+ process.stderr.write(chalk.red(`${consolePrefix()}◼ borg assimilate: ${parsed.error}\n`));
42
45
  process.exit(1);
43
46
  }
44
- const code = await runSpawn(parsed.args);
47
+ const deps = buildDefaultAssimilateDeps();
48
+ const code = await runAssimilate({ role: parsed.role, flags: parsed.flags }, deps);
49
+ process.exit(code);
50
+ }
51
+ if (process.argv[2] === 'spawn') {
52
+ // Deprecated; the stub prints a redirect message and exits 2.
53
+ const code = await runSpawn();
45
54
  process.exit(code);
46
55
  }
47
56
  if (process.argv[2] === 'sync') {
@@ -1 +1 @@
1
- {"version":3,"file":"claude.js","sourceRoot":"","sources":["../src/claude.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"claude.js","sourceRoot":"","sources":["../src/claude.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Trim + reject control chars + cap length. Returns null on rejection
3
+ * so callers fall through to no-remote derivation.
4
+ */
5
+ export declare function sanitizeRemoteUrl(raw: string): string | null;
6
+ /**
7
+ * Extract the repo name from a git remote URL. Handles SSH/HTTPS/git/file
8
+ * forms and embedded credentials. Returns null when nothing parseable
9
+ * is present.
10
+ *
11
+ * Strategy: strip protocol + credentials, then take the last path segment
12
+ * after the final `/` or `:`, stripping a trailing `.git`.
13
+ */
14
+ export declare function parseGitRemote(url: string): string | null;
15
+ /**
16
+ * Normalize an arbitrary string into a valid cube name:
17
+ * lowercase, underscores+spaces → hyphens, strip [^a-z0-9-], truncate 64.
18
+ */
19
+ export declare function normalizeCubeName(raw: string): string;
20
+ /**
21
+ * Compose the full derivation: sanitize + parse + normalize, with
22
+ * project-root basename as fallback. Returns null when no valid name
23
+ * can be derived.
24
+ */
25
+ export declare function deriveCubeName(projectRoot: string, gitRemoteUrl: string | null): string | null;
26
+ //# sourceMappingURL=cube-name.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cube-name.d.ts","sourceRoot":"","sources":["../src/cube-name.ts"],"names":[],"mappings":"AAKA;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAK5D;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAYzD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAMrD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAa9F"}
@@ -0,0 +1,67 @@
1
+ import { basename } from 'node:path';
2
+ const MAX_URL_LEN = 2048;
3
+ const CONTROL_CHAR_RE = /[\x00-\x1F\x7F]/;
4
+ /**
5
+ * Trim + reject control chars + cap length. Returns null on rejection
6
+ * so callers fall through to no-remote derivation.
7
+ */
8
+ export function sanitizeRemoteUrl(raw) {
9
+ const trimmed = raw.trim();
10
+ if (trimmed.length === 0 || trimmed.length > MAX_URL_LEN)
11
+ return null;
12
+ if (CONTROL_CHAR_RE.test(trimmed))
13
+ return null;
14
+ return trimmed;
15
+ }
16
+ /**
17
+ * Extract the repo name from a git remote URL. Handles SSH/HTTPS/git/file
18
+ * forms and embedded credentials. Returns null when nothing parseable
19
+ * is present.
20
+ *
21
+ * Strategy: strip protocol + credentials, then take the last path segment
22
+ * after the final `/` or `:`, stripping a trailing `.git`.
23
+ */
24
+ export function parseGitRemote(url) {
25
+ if (!url)
26
+ return null;
27
+ let s = url.replace(/^[a-z]+:\/\//, '');
28
+ s = s.replace(/^[^@\/]*@/, '');
29
+ const lastSep = Math.max(s.lastIndexOf('/'), s.lastIndexOf(':'));
30
+ if (lastSep === -1)
31
+ return null;
32
+ let name = s.slice(lastSep + 1);
33
+ name = name.replace(/\.git$/, '');
34
+ return name.length > 0 ? name : null;
35
+ }
36
+ /**
37
+ * Normalize an arbitrary string into a valid cube name:
38
+ * lowercase, underscores+spaces → hyphens, strip [^a-z0-9-], truncate 64.
39
+ */
40
+ export function normalizeCubeName(raw) {
41
+ return raw
42
+ .toLowerCase()
43
+ .replace(/[_\s]+/g, '-')
44
+ .replace(/[^a-z0-9-]/g, '')
45
+ .slice(0, 64);
46
+ }
47
+ /**
48
+ * Compose the full derivation: sanitize + parse + normalize, with
49
+ * project-root basename as fallback. Returns null when no valid name
50
+ * can be derived.
51
+ */
52
+ export function deriveCubeName(projectRoot, gitRemoteUrl) {
53
+ if (gitRemoteUrl) {
54
+ const sanitized = sanitizeRemoteUrl(gitRemoteUrl);
55
+ if (sanitized) {
56
+ const repo = parseGitRemote(sanitized);
57
+ if (repo) {
58
+ const normalized = normalizeCubeName(repo);
59
+ if (normalized.length > 0)
60
+ return normalized;
61
+ }
62
+ }
63
+ }
64
+ const fallback = normalizeCubeName(basename(projectRoot));
65
+ return fallback.length > 0 ? fallback : null;
66
+ }
67
+ //# sourceMappingURL=cube-name.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cube-name.js","sourceRoot":"","sources":["../src/cube-name.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,MAAM,WAAW,GAAG,IAAI,CAAC;AACzB,MAAM,eAAe,GAAG,iBAAiB,CAAC;AAE1C;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAC3B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,WAAW;QAAE,OAAO,IAAI,CAAC;IACtE,IAAI,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/C,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IAEtB,IAAI,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;IACxC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IAE/B,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;IACjE,IAAI,OAAO,KAAK,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAEhC,IAAI,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;IAChC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAClC,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AACvC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,OAAO,GAAG;SACP,WAAW,EAAE;SACb,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC;SACvB,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC;SAC1B,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAClB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,WAAmB,EAAE,YAA2B;IAC7E,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,SAAS,GAAG,iBAAiB,CAAC,YAAY,CAAC,CAAC;QAClD,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,IAAI,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;YACvC,IAAI,IAAI,EAAE,CAAC;gBACT,MAAM,UAAU,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;gBAC3C,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC;oBAAE,OAAO,UAAU,CAAC;YAC/C,CAAC;QACH,CAAC;IACH,CAAC;IACD,MAAM,QAAQ,GAAG,iBAAiB,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC;IAC1D,OAAO,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;AAC/C,CAAC"}
package/dist/index.js CHANGED
@@ -703,7 +703,10 @@ async function main() {
703
703
  throw new Error('name is required');
704
704
  if (groundRules === undefined)
705
705
  throw new Error('ground_rules is required (pass empty string if none)');
706
- const { cube } = await createCube(name, groundRules);
706
+ // v0.9.2: createCube now returns the flat shape directly
707
+ // (see remote-client unwrap). `cube.id` / `cube.name` work
708
+ // verbatim on the returned object.
709
+ const cube = await createCube(name, groundRules);
707
710
  // Apply template if requested. Merges by name: any role the
708
711
  // server auto-seeded (e.g. "Drone") that the template doesn't
709
712
  // also include stays put; templated roles upsert.