robrain 2.4.6 → 2.4.7

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.
@@ -216,7 +216,7 @@ export async function installCommand(opts) {
216
216
  // Display only (status) — the thin client never embeds locally.
217
217
  ...(provisioned.embeddingProvider ? { embeddingProvider: provisioned.embeddingProvider } : {}),
218
218
  installedAt: new Date().toISOString(),
219
- version: '2.4.6',
219
+ version: '2.4.7',
220
220
  });
221
221
  spinner.succeed('MCP servers configured');
222
222
  // ── Done ───────────────────────────────────────────────────
@@ -404,7 +404,7 @@ async function installSelfHosted(opts) {
404
404
  ...(perceptionKey ? { perceptionKey } : {}),
405
405
  embeddingProvider: provider,
406
406
  installedAt: new Date().toISOString(),
407
- version: '2.4.6',
407
+ version: '2.4.7',
408
408
  selfHosted: true,
409
409
  });
410
410
  spinner.succeed('MCP servers configured for self-hosted mode');
@@ -1 +1 @@
1
- {"version":3,"file":"synth.d.ts","sourceRoot":"","sources":["../../src/commands/synth.ts"],"names":[],"mappings":"AAuBA,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,2FAA2F;IAC3F,IAAI,CAAC,EAAE,OAAO,CAAA;CACf;AAED,wBAAsB,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAiDpE"}
1
+ {"version":3,"file":"synth.d.ts","sourceRoot":"","sources":["../../src/commands/synth.ts"],"names":[],"mappings":"AAwBA,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,2FAA2F;IAC3F,IAAI,CAAC,EAAE,OAAO,CAAA;CACf;AAED,wBAAsB,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAsFpE"}
@@ -11,7 +11,8 @@ import { existsSync } from 'fs';
11
11
  import { dirname, join } from 'path';
12
12
  import { fileURLToPath } from 'url';
13
13
  import chalk from 'chalk';
14
- import { applyStackEnvFallback } from '../lib/load-env.js';
14
+ import { isCloudInstall } from '../lib/config.js';
15
+ import { applyEnvFileFallback, applyStackEnvFallback } from '../lib/load-env.js';
15
16
  import { resolveSynthesisEntry, SynthesisResolveError } from '../lib/synthesis-bundle.js';
16
17
  /** Absolute path to this CLI's `bin/robrain.js` (checkout or published layout). */
17
18
  function resolveCliBin() {
@@ -19,18 +20,6 @@ function resolveCliBin() {
19
20
  return existsSync(candidate) ? candidate : undefined;
20
21
  }
21
22
  export async function synthCommand(opts) {
22
- let resolved;
23
- try {
24
- resolved = resolveSynthesisEntry();
25
- }
26
- catch (err) {
27
- if (err instanceof SynthesisResolveError) {
28
- console.error(chalk.red(`✗ robrain synth: ${err.message}`));
29
- process.exitCode = 1;
30
- return;
31
- }
32
- throw err;
33
- }
34
23
  const env = { ...process.env };
35
24
  // Env precedence for the child, lowest to highest — two deliberate layers:
36
25
  // 1. ~/.robrain/stack/.env (filled here, gaps only — `robrain up` output)
@@ -41,6 +30,50 @@ export async function synthCommand(opts) {
41
30
  // The CLI-side shell-wins vs shared .env-wins split is a recorded decision,
42
31
  // not drift — don't "unify" these.
43
32
  applyStackEnvFallback(env);
33
+ // Resolve before deciding: a resolved checkout's `.env` is a store the child
34
+ // would find via its own loadEnv, so it has to count as "there is a local
35
+ // store" — otherwise we decline work that would have succeeded. Errors are
36
+ // held, not thrown: on a cloud install "no local Synthesis" is the expected
37
+ // state, and the message below beats a resolution failure.
38
+ let resolved;
39
+ let resolveError;
40
+ try {
41
+ resolved = resolveSynthesisEntry();
42
+ }
43
+ catch (err) {
44
+ if (!(err instanceof SynthesisResolveError))
45
+ throw err;
46
+ resolveError = err;
47
+ }
48
+ if (resolved?.repoRoot)
49
+ applyEnvFileFallback(env, join(resolved.repoRoot, '.env'));
50
+ // Synthesis is a batch job that opens the decision store directly — there is
51
+ // no local store on a cloud install, and judgment already runs server-side.
52
+ // Without this the spawned bundle dies on `Missing env var: DATABASE_URL`,
53
+ // which reads like a broken install rather than "this command isn't yours".
54
+ //
55
+ // A reachable DATABASE_URL overrides the install mode on purpose: a stale
56
+ // cloud token (logged in once, never `logout`) must not talk someone out of
57
+ // running the pass over a store they demonstrably have. Config decides only
58
+ // when there is no store to point at.
59
+ if (isCloudInstall() && !env.DATABASE_URL) {
60
+ console.log();
61
+ console.log(chalk.yellow(' Synthesis runs server-side on Rory Plans cloud — nothing to run locally.'));
62
+ console.log(chalk.dim(' Its results reach you the same way as everything else: the always-on'));
63
+ console.log(chalk.dim(' summary at session start, and ') + chalk.cyan('npx robrain review') + chalk.dim('.'));
64
+ console.log();
65
+ console.log(chalk.dim(' Self-hosting instead? Start your stack with ') + chalk.cyan('npx robrain up')
66
+ + chalk.dim(' (or set DATABASE_URL).'));
67
+ console.log(chalk.dim(' Seeing this after switching off cloud? The install still holds a Rory'));
68
+ console.log(chalk.dim(' token — ') + chalk.cyan('npx robrain logout') + chalk.dim(' clears it.'));
69
+ console.log();
70
+ return;
71
+ }
72
+ if (resolveError || !resolved) {
73
+ console.error(chalk.red(`✗ robrain synth: ${resolveError?.message ?? 'could not resolve the Synthesis bundle.'}`));
74
+ process.exitCode = 1;
75
+ return;
76
+ }
44
77
  if (opts.dryRun)
45
78
  env.SYNTHESIS_DRY_RUN = 'true';
46
79
  if (opts.full)
@@ -65,9 +98,15 @@ export async function synthCommand(opts) {
65
98
  stdio: 'inherit',
66
99
  env,
67
100
  });
68
- await new Promise((res, rej) => {
101
+ // The child inherits stdio, so it has already printed whatever went wrong —
102
+ // rethrowing here just stacks a second (useless) Node trace on top of it.
103
+ const code = await new Promise((res, rej) => {
69
104
  child.on('error', rej);
70
- child.on('exit', code => code === 0 ? res() : rej(new Error(`synthesis exited with code ${code}`)));
105
+ child.on('exit', c => res(c ?? 1));
71
106
  });
107
+ if (code !== 0) {
108
+ console.error(chalk.red(`\n✗ Synthesis failed (exit ${code}) — see the error above.`));
109
+ process.exitCode = code;
110
+ }
72
111
  }
73
112
  //# sourceMappingURL=synth.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"synth.js","sourceRoot":"","sources":["../../src/commands/synth.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"synth.js","sourceRoot":"","sources":["../../src/commands/synth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=synth.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"synth.test.d.ts","sourceRoot":"","sources":["../../src/commands/synth.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,161 @@
1
+ import { mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
2
+ import { tmpdir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ import { after, describe, it } from 'node:test';
5
+ import assert from 'node:assert/strict';
6
+ // config.ts resolves homedir() at import time — pin a hermetic HOME (and kill
7
+ // colour, so assertions match plain substrings) BEFORE the dynamic imports.
8
+ const fakeHome = mkdtempSync(join(tmpdir(), 'robrain-synth-'));
9
+ process.env.HOME = fakeHome;
10
+ process.env.FORCE_COLOR = '0';
11
+ mkdirSync(join(fakeHome, '.robrain'), { recursive: true });
12
+ // A directory that is deliberately NOT a robrain checkout. Entry resolution
13
+ // fails fast there, which is what makes this file hermetic: a run that reached
14
+ // resolution is distinguishable from one the cloud guard short-circuited —
15
+ // and neither ever spawns Synthesis or touches a database.
16
+ const notACheckout = join(fakeHome, 'not-a-checkout');
17
+ mkdirSync(notACheckout, { recursive: true });
18
+ process.env.ROBRAIN_REPO = notACheckout;
19
+ // Ambient DATABASE_URL would flip the mode routing below — own it per test.
20
+ delete process.env.DATABASE_URL;
21
+ const { isCloudInstall } = await import('../lib/config.js');
22
+ const { synthCommand } = await import('./synth.js');
23
+ function writeInstallConfig(config) {
24
+ writeFileSync(join(fakeHome, '.robrain', 'config.json'), JSON.stringify(config));
25
+ }
26
+ /** Run `robrain synth` with console captured and a clean exit code. */
27
+ async function runSynth() {
28
+ const lines = [];
29
+ const { log, error } = console;
30
+ console.log = (...args) => { lines.push(args.join(' ')); };
31
+ console.error = (...args) => { lines.push(args.join(' ')); };
32
+ process.exitCode = 0;
33
+ try {
34
+ await synthCommand({});
35
+ }
36
+ finally {
37
+ console.log = log;
38
+ console.error = error;
39
+ }
40
+ const exitCode = Number(process.exitCode ?? 0);
41
+ process.exitCode = 0;
42
+ return { out: lines.join('\n'), exitCode };
43
+ }
44
+ const CLOUD_MESSAGE = 'Synthesis runs server-side on Rory Plans cloud';
45
+ const RESOLVE_FAILURE = 'does not look like a robrain checkout';
46
+ after(() => {
47
+ rmSync(fakeHome, { recursive: true, force: true });
48
+ });
49
+ describe('isCloudInstall', () => {
50
+ it('is true for a cloud thin-client install', () => {
51
+ writeInstallConfig({ token: 'rory_x', email: 'dev@example.com', thin: true });
52
+ assert.equal(isCloudInstall(), true);
53
+ });
54
+ it('is false for a self-hosted install', () => {
55
+ writeInstallConfig({ selfHosted: true, perceptionUrl: 'http://127.0.0.1:3001' });
56
+ assert.equal(isCloudInstall(), false);
57
+ });
58
+ it('is false when a cloud login also runs a local stack (selfHosted wins)', () => {
59
+ // `robrain up` merges selfHosted onto an existing cloud config — that user
60
+ // does have a local Postgres, so synth must stay available to them.
61
+ writeInstallConfig({ token: 'rory_x', thin: true, selfHosted: true });
62
+ assert.equal(isCloudInstall(), false);
63
+ });
64
+ it('is true for a legacy cloud install that predates the thin flag', () => {
65
+ // Cloud installs before `thin` existed carry only token/email. Nothing
66
+ // self-hosted writes a Rory token, so token-without-thin means cloud.
67
+ writeInstallConfig({ token: 'rory_x', email: 'dev@example.com', perceptionUrl: 'https://api.roryplans.ai' });
68
+ assert.equal(isCloudInstall(), true);
69
+ });
70
+ it('is false for a legacy self-hosted install with no flags', () => {
71
+ // Pre-`selfHosted` installs: Perception configured, never logged into Rory.
72
+ writeInstallConfig({ perceptionUrl: 'http://127.0.0.1:3001', installedAt: '2026-01-01T00:00:00Z' });
73
+ assert.equal(isCloudInstall(), false);
74
+ });
75
+ it('is false with no config at all', () => {
76
+ writeInstallConfig({});
77
+ assert.equal(isCloudInstall(), false);
78
+ });
79
+ });
80
+ describe('robrain synth — install mode routing', () => {
81
+ it('explains itself and exits 0 on a cloud install', async () => {
82
+ writeInstallConfig({ token: 'rory_x', email: 'dev@example.com', thin: true });
83
+ const { out, exitCode } = await runSynth();
84
+ assert.match(out, new RegExp(CLOUD_MESSAGE));
85
+ assert.match(out, /npx robrain review/); // says where results DO surface
86
+ assert.match(out, /npx robrain up/); // …and how to opt into a local pass
87
+ assert.equal(exitCode, 0, 'a cloud install is not an error state');
88
+ // The guard must short-circuit BEFORE entry resolution — otherwise a cloud
89
+ // user still eats a resolution/DATABASE_URL failure.
90
+ assert.doesNotMatch(out, new RegExp(RESOLVE_FAILURE));
91
+ });
92
+ it('runs the normal path on a self-hosted install', async () => {
93
+ writeInstallConfig({ selfHosted: true, perceptionUrl: 'http://127.0.0.1:3001' });
94
+ const { out, exitCode } = await runSynth();
95
+ // Same environment as the cloud case — only the install mode differs, and
96
+ // here we reach entry resolution (which this fake HOME makes fail cleanly).
97
+ assert.match(out, new RegExp(RESOLVE_FAILURE));
98
+ assert.doesNotMatch(out, new RegExp(CLOUD_MESSAGE));
99
+ assert.equal(exitCode, 1, 'a real synth failure must stay non-zero for scripts');
100
+ });
101
+ it('still runs when a stale cloud token sits on top of a real DATABASE_URL', async () => {
102
+ // Logged into Rory once, never logged out, now self-hosting by hand (no
103
+ // `robrain up`, so no selfHosted flag). Refusing here would tell someone
104
+ // with a working local store that there is nothing to run — silently, and
105
+ // with exit 0. A store you can point at wins over a leftover token.
106
+ writeInstallConfig({ token: 'rory_stale', email: 'dev@example.com', thin: true });
107
+ process.env.DATABASE_URL = 'postgres://robrain:pw@127.0.0.1:5432/robrain';
108
+ try {
109
+ const { out, exitCode } = await runSynth();
110
+ assert.doesNotMatch(out, new RegExp(CLOUD_MESSAGE));
111
+ assert.match(out, new RegExp(RESOLVE_FAILURE)); // reached resolution = would have run
112
+ assert.equal(exitCode, 1);
113
+ }
114
+ finally {
115
+ delete process.env.DATABASE_URL;
116
+ }
117
+ });
118
+ it('counts a resolved checkout\'s .env as a local store, like the child would', async () => {
119
+ // The narrow case the config-only guard still got wrong: cloud token, no
120
+ // `robrain up`, DATABASE_URL living ONLY in a checkout's .env — a file the
121
+ // parent never reads but the child's own loadEnv does. Declining here
122
+ // refuses work that would have succeeded.
123
+ const checkout = join(fakeHome, 'checkout');
124
+ const distDir = join(checkout, 'packages', 'synthesis', 'dist');
125
+ mkdirSync(distDir, { recursive: true });
126
+ // Stand-in for the Synthesis bundle: records the DATABASE_URL it was
127
+ // handed, so this asserts what the child actually got — not just that the
128
+ // parent decided to spawn. CJS on purpose (no package.json type here).
129
+ const marker = join(fakeHome, 'child-saw.txt');
130
+ writeFileSync(join(distDir, 'index.js'), `require('fs').writeFileSync(${JSON.stringify(marker)}, String(process.env.DATABASE_URL))\n`);
131
+ const repoDbUrl = 'postgres://robrain:pw@127.0.0.1:5432/from_checkout_env';
132
+ writeFileSync(join(checkout, '.env'), `DATABASE_URL=${repoDbUrl}\n`);
133
+ writeInstallConfig({ token: 'rory_stale', email: 'dev@example.com', thin: true });
134
+ process.env.ROBRAIN_REPO = checkout;
135
+ try {
136
+ const { out, exitCode } = await runSynth();
137
+ assert.doesNotMatch(out, new RegExp(CLOUD_MESSAGE), 'a store in the checkout .env must win over the token');
138
+ assert.equal(exitCode, 0);
139
+ assert.equal(readFileSync(marker, 'utf8'), repoDbUrl, 'child must receive the checkout .env DATABASE_URL');
140
+ }
141
+ finally {
142
+ process.env.ROBRAIN_REPO = notACheckout;
143
+ }
144
+ });
145
+ it('prefers the cloud explanation over a resolution failure', async () => {
146
+ // A cloud install has no local Synthesis to find — "we could not locate the
147
+ // bundle" is a true but useless answer; the mode is the actual reason.
148
+ writeInstallConfig({ token: 'rory_x', email: 'dev@example.com', thin: true });
149
+ const { out, exitCode } = await runSynth();
150
+ assert.match(out, new RegExp(CLOUD_MESSAGE));
151
+ assert.doesNotMatch(out, new RegExp(RESOLVE_FAILURE));
152
+ assert.equal(exitCode, 0);
153
+ });
154
+ it('names the stale-token escape hatch when it does decline', async () => {
155
+ writeInstallConfig({ token: 'rory_stale', email: 'dev@example.com', thin: true });
156
+ const { out } = await runSynth();
157
+ assert.match(out, /npx robrain logout/);
158
+ assert.match(out, /DATABASE_URL/);
159
+ });
160
+ });
161
+ //# sourceMappingURL=synth.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"synth.test.js","sourceRoot":"","sources":["../../src/commands/synth.test.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -30,7 +30,7 @@ import { projectsListCommand, projectsMergeCommand } from './commands/projects.j
30
30
  import { upCommand, downCommand, DEFAULT_IMAGE_REPO } from './commands/up.js';
31
31
  import { mcpCommand } from './commands/mcp.js';
32
32
  import { installHermesPlugin, resolveHermesHome } from './lib/hermes-plugin.js';
33
- const VERSION = '2.4.6';
33
+ const VERSION = '2.4.7';
34
34
  program
35
35
  .name('robrain')
36
36
  .description('Institutional memory for AI coding agents — by Rory Plans')
@@ -25,6 +25,13 @@ export declare function writeConfig(config: RoMemoryConfig): void;
25
25
  export declare function mergeConfig(updates: Partial<RoMemoryConfig>): void;
26
26
  /** True if Rory cloud login, or OSS self-hosted install (no Rory token). */
27
27
  export declare function isAuthenticated(): boolean;
28
+ /**
29
+ * True when this install talks to the managed Rory Plans API rather than a
30
+ * local stack — i.e. there is no local Postgres for batch jobs to open.
31
+ * `selfHosted` wins: `robrain up` merges that flag in, so a user who has both
32
+ * a cloud login and a local stack still counts as self-hosted.
33
+ */
34
+ export declare function isCloudInstall(): boolean;
28
35
  export declare function getToken(): string | undefined;
29
36
  export declare const RORY_API_BASE: string;
30
37
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAW,MAAM,CAAA;IACvB,KAAK,CAAC,EAAW,MAAM,CAAA;IACvB,2DAA2D;IAC3D,UAAU,CAAC,EAAM,OAAO,CAAA;IACxB,2FAA2F;IAC3F,IAAI,CAAC,EAAY,OAAO,CAAA;IACxB,aAAa,CAAC,EAAG,MAAM,CAAA;IACvB,aAAa,CAAC,EAAG,MAAM,CAAA;IACvB,WAAW,CAAC,EAAK,MAAM,CAAA;IACvB,WAAW,CAAC,EAAK,MAAM,CAAA;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,YAAY,CAAC,EAAI,MAAM,CAAA;IACvB,WAAW,CAAC,EAAK,MAAM,CAAA;IACvB,OAAO,CAAC,EAAS,MAAM,CAAA;CACxB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAWxD;AAED,wBAAgB,UAAU,IAAI,cAAc,CAS3C;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAKxD;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI,CAGlE;AAED,4EAA4E;AAC5E,wBAAgB,eAAe,IAAI,OAAO,CAWzC;AAED,wBAAgB,QAAQ,IAAI,MAAM,GAAG,SAAS,CAE7C;AAGD,eAAO,MAAM,aAAa,QAA0D,CAAA"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAW,MAAM,CAAA;IACvB,KAAK,CAAC,EAAW,MAAM,CAAA;IACvB,2DAA2D;IAC3D,UAAU,CAAC,EAAM,OAAO,CAAA;IACxB,2FAA2F;IAC3F,IAAI,CAAC,EAAY,OAAO,CAAA;IACxB,aAAa,CAAC,EAAG,MAAM,CAAA;IACvB,aAAa,CAAC,EAAG,MAAM,CAAA;IACvB,WAAW,CAAC,EAAK,MAAM,CAAA;IACvB,WAAW,CAAC,EAAK,MAAM,CAAA;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,YAAY,CAAC,EAAI,MAAM,CAAA;IACvB,WAAW,CAAC,EAAK,MAAM,CAAA;IACvB,OAAO,CAAC,EAAS,MAAM,CAAA;CACxB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAWxD;AAED,wBAAgB,UAAU,IAAI,cAAc,CAS3C;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAKxD;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI,CAGlE;AAED,4EAA4E;AAC5E,wBAAgB,eAAe,IAAI,OAAO,CAWzC;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAIxC;AAED,wBAAgB,QAAQ,IAAI,MAAM,GAAG,SAAS,CAE7C;AAGD,eAAO,MAAM,aAAa,QAA0D,CAAA"}
@@ -62,6 +62,18 @@ export function isAuthenticated() {
62
62
  !config.token &&
63
63
  !config.email);
64
64
  }
65
+ /**
66
+ * True when this install talks to the managed Rory Plans API rather than a
67
+ * local stack — i.e. there is no local Postgres for batch jobs to open.
68
+ * `selfHosted` wins: `robrain up` merges that flag in, so a user who has both
69
+ * a cloud login and a local stack still counts as self-hosted.
70
+ */
71
+ export function isCloudInstall() {
72
+ const config = readConfig();
73
+ if (config.selfHosted)
74
+ return false;
75
+ return Boolean(config.thin || config.token);
76
+ }
65
77
  export function getToken() {
66
78
  return readConfig().token;
67
79
  }
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB,gEAAgE;AAChE,gEAAgE;AAChE,sEAAsE;AACtE,gEAAgE;AAEhE,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,IAAI,CAAA;AACvE,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAA;AAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAE3B,MAAM,UAAU,GAAI,IAAI,CAAC,OAAO,EAAE,EAAE,UAAU,CAAC,CAAA;AAC/C,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAA;AAmBnD;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAW;IAC9C,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;QACtB,IAAI,CAAC,CAAC,QAAQ,KAAK,WAAW,EAAE,CAAC;YAC/B,CAAC,CAAC,QAAQ,GAAG,WAAW,CAAA;YACxB,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;QACxC,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,oCAAoC;IACtC,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC;QAAE,OAAO,EAAE,CAAA;IACvC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,WAAW,EAAE,MAAM,CAAC,CAAmB,CAAA;QAC9E,IAAI,MAAM,CAAC,aAAa;YAAE,MAAM,CAAC,aAAa,GAAG,oBAAoB,CAAC,MAAM,CAAC,aAAa,CAAC,CAAA;QAC3F,OAAO,MAAM,CAAA;IACf,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAA;IACX,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAsB;IAChD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC5C,CAAC;IACD,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAA;AACrE,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,OAAgC;IAC1D,MAAM,OAAO,GAAG,UAAU,EAAE,CAAA;IAC5B,WAAW,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,OAAO,EAAE,CAAC,CAAA;AACzC,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,eAAe;IAC7B,MAAM,MAAM,GAAG,UAAU,EAAE,CAAA;IAC3B,IAAI,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK;QAAE,OAAO,IAAI,CAAA;IAC7C,IAAI,MAAM,CAAC,UAAU;QAAE,OAAO,IAAI,CAAA;IAClC,2FAA2F;IAC3F,OAAO,OAAO,CACZ,MAAM,CAAC,aAAa;QAClB,MAAM,CAAC,WAAW;QAClB,CAAC,MAAM,CAAC,KAAK;QACb,CAAC,MAAM,CAAC,KAAK,CAChB,CAAA;AACH,CAAC;AAED,MAAM,UAAU,QAAQ;IACtB,OAAO,UAAU,EAAE,CAAC,KAAK,CAAA;AAC3B,CAAC;AAED,iFAAiF;AACjF,MAAM,CAAC,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,0BAA0B,CAAA"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,15 @@ export declare function loadCliEnv(repoRoot?: string): void;
8
8
  * runs first and this only fills the gaps.
9
9
  */
10
10
  export declare function applyStackEnvFallback(env: NodeJS.ProcessEnv, stackEnvPath?: string): void;
11
+ /**
12
+ * Fill vars still unset/empty in `env` from an arbitrary `.env` file; no-op
13
+ * when it does not exist. Gaps only — never overrides what `env` already has.
14
+ *
15
+ * Lets a parent process see the same values a child that runs its own
16
+ * `loadEnv(<root>)` would (e.g. `robrain synth` deciding whether a store
17
+ * exists before spawning Synthesis against a checkout it resolved).
18
+ */
19
+ export declare function applyEnvFileFallback(env: NodeJS.ProcessEnv, envPath: string): void;
11
20
  /**
12
21
  * When running the CLI from a git checkout (e.g. `node packages/cli/bin/robrain.js`),
13
22
  * find that checkout's root so repo `.env` matches `pnpm docker:up` / docker-compose.
@@ -1 +1 @@
1
- {"version":3,"file":"load-env.d.ts","sourceRoot":"","sources":["../../src/lib/load-env.ts"],"names":[],"mappings":"AAiDA,uFAAuF;AACvF,wBAAgB,UAAU,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAIlD;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,YAAY,SAA+C,GAC1D,IAAI,CAON;AAED;;;;GAIG;AACH,wBAAgB,6BAA6B,IAAI,MAAM,GAAG,SAAS,CAclE;AAED,6FAA6F;AAC7F,wBAAgB,+BAA+B,IAAI,MAAM,GAAG,SAAS,CASpE;AAED,yFAAyF;AACzF,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAO/E"}
1
+ {"version":3,"file":"load-env.d.ts","sourceRoot":"","sources":["../../src/lib/load-env.ts"],"names":[],"mappings":"AAiDA,uFAAuF;AACvF,wBAAgB,UAAU,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAIlD;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,YAAY,SAA+C,GAC1D,IAAI,CAEN;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAOlF;AAED;;;;GAIG;AACH,wBAAgB,6BAA6B,IAAI,MAAM,GAAG,SAAS,CAclE;AAED,6FAA6F;AAC7F,wBAAgB,+BAA+B,IAAI,MAAM,GAAG,SAAS,CASpE;AAED,yFAAyF;AACzF,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAO/E"}
@@ -50,9 +50,20 @@ export function loadCliEnv(repoRoot) {
50
50
  * runs first and this only fills the gaps.
51
51
  */
52
52
  export function applyStackEnvFallback(env, stackEnvPath = join(homedir(), '.robrain', 'stack', '.env')) {
53
- if (!existsSync(stackEnvPath))
53
+ applyEnvFileFallback(env, stackEnvPath);
54
+ }
55
+ /**
56
+ * Fill vars still unset/empty in `env` from an arbitrary `.env` file; no-op
57
+ * when it does not exist. Gaps only — never overrides what `env` already has.
58
+ *
59
+ * Lets a parent process see the same values a child that runs its own
60
+ * `loadEnv(<root>)` would (e.g. `robrain synth` deciding whether a store
61
+ * exists before spawning Synthesis against a checkout it resolved).
62
+ */
63
+ export function applyEnvFileFallback(env, envPath) {
64
+ if (!existsSync(envPath))
54
65
  return;
55
- const parsed = dotenvParse().parse(readFileSync(stackEnvPath));
66
+ const parsed = dotenvParse().parse(readFileSync(envPath));
56
67
  for (const [key, value] of Object.entries(parsed)) {
57
68
  if (!isUnsetOrEmptyShell(env[key]) || value === '')
58
69
  continue;
@@ -1 +1 @@
1
- {"version":3,"file":"load-env.js","sourceRoot":"","sources":["../../src/lib/load-env.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"load-env.js","sourceRoot":"","sources":["../../src/lib/load-env.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "robrain",
3
- "version": "2.4.6",
3
+ "version": "2.4.7",
4
4
  "type": "module",
5
5
  "description": "RoBrain CLI for installation, setup, and memory workflows",
6
6
  "author": "Rory Plans, Inc.",
@@ -57,7 +57,7 @@
57
57
  "build": "tsc",
58
58
  "dev": "tsc --watch",
59
59
  "typecheck": "tsc --noEmit",
60
- "test": "pnpm build && node --test dist/lib/editor.codex.test.js dist/lib/editor.stale-block.test.js dist/lib/release-guard.test.js dist/lib/mcp-bundle.test.js dist/lib/control-bundle.test.js dist/lib/claude-plugin.test.js dist/lib/hermes-plugin.test.js dist/lib/codex-hooks.test.js dist/commands/outcomes.test.js dist/commands/export-interchange.test.js dist/commands/up.test.js dist/commands/mcp.test.js dist/commands/install.test.js dist/lib/synthesis-bundle.test.js",
60
+ "test": "pnpm build && node --test dist/lib/editor.codex.test.js dist/lib/editor.stale-block.test.js dist/lib/release-guard.test.js dist/lib/mcp-bundle.test.js dist/lib/control-bundle.test.js dist/lib/claude-plugin.test.js dist/lib/hermes-plugin.test.js dist/lib/codex-hooks.test.js dist/commands/outcomes.test.js dist/commands/export-interchange.test.js dist/commands/up.test.js dist/commands/mcp.test.js dist/commands/install.test.js dist/commands/synth.test.js dist/lib/synthesis-bundle.test.js",
61
61
  "pack:verify": "node scripts/verify-publish-tarball.mjs",
62
62
  "postinstall": "node scripts/chmod-bin.cjs"
63
63
  }
@@ -23297,7 +23297,7 @@ function resolveSessionId(raw) {
23297
23297
  function buildServer() {
23298
23298
  const server = new McpServer({
23299
23299
  name: "sensing-mcp",
23300
- version: "2.4.6"
23300
+ version: "2.4.7"
23301
23301
  });
23302
23302
  server.tool(
23303
23303
  "sensing_start_session",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robrain/sensing-mcp",
3
- "version": "2.4.6",
3
+ "version": "2.4.7",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "main": "./dist/index.js"
@@ -16501,7 +16501,16 @@ var config = {
16501
16501
  };
16502
16502
  function requireEnv(key) {
16503
16503
  const v2 = process.env[key];
16504
- if (!v2) throw new Error(`Missing env var: ${key}`);
16504
+ if (!v2) {
16505
+ const hints = {
16506
+ DATABASE_URL: "Synthesis reads the decision store directly, so it needs a Postgres URL.\n \u2022 Self-hosted: start the stack with `npx robrain up` (writes ~/.robrain/stack/.env),\n or run from a robrain checkout whose .env has DATABASE_URL (or set ROBRAIN_REPO to it).\n \u2022 Rory Plans cloud: there is no local store \u2014 Synthesis runs server-side, and its\n results arrive via the always-on summary and `npx robrain review`."
16507
+ };
16508
+ const hint = hints[key];
16509
+ throw new Error(`Missing env var: ${key}${hint ? `
16510
+
16511
+ ${hint}
16512
+ ` : ""}`);
16513
+ }
16505
16514
  return v2;
16506
16515
  }
16507
16516
  if (config.llmProvider === "anthropic" && !config.anthropicKey) {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robrain/synthesis",
3
- "version": "2.4.6",
3
+ "version": "2.4.7",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "main": "./dist/index.js"