@1agh/maude 0.18.0 → 0.18.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@1agh/maude",
3
- "version": "0.18.0",
3
+ "version": "0.18.2",
4
4
  "description": "Marketplace of Claude Code plugins by Michal Dovrtěl: `design` (canvas-first design iteration) + `flow` (generic agentic workflow loop with .ai second brain). Ships the `maude` CLI (with `mdcc` legacy alias) to scaffold workspace, run the design dev server, and manage configs.",
5
5
  "type": "module",
6
6
  "engines": {
@@ -41,13 +41,13 @@
41
41
  "prepublishOnly": "bash scripts/check-version-parity.sh"
42
42
  },
43
43
  "optionalDependencies": {
44
- "@1agh/maude-darwin-arm64": "0.18.0",
45
- "@1agh/maude-darwin-x64": "0.18.0",
46
- "@1agh/maude-linux-arm64": "0.18.0",
47
- "@1agh/maude-linux-arm64-musl": "0.18.0",
48
- "@1agh/maude-linux-x64": "0.18.0",
49
- "@1agh/maude-linux-x64-musl": "0.18.0",
50
- "@1agh/maude-win32-x64": "0.18.0"
44
+ "@1agh/maude-darwin-arm64": "0.18.2",
45
+ "@1agh/maude-darwin-x64": "0.18.2",
46
+ "@1agh/maude-linux-arm64": "0.18.2",
47
+ "@1agh/maude-linux-arm64-musl": "0.18.2",
48
+ "@1agh/maude-linux-x64": "0.18.2",
49
+ "@1agh/maude-linux-x64-musl": "0.18.2",
50
+ "@1agh/maude-win32-x64": "0.18.2"
51
51
  },
52
52
  "files": [
53
53
  "cli",
@@ -1,90 +1,87 @@
1
- // Boot-time self-healcovers the gap between marketplace-cache installs
2
- // (git clone, honors .gitignore, no `npm install`) and what server.ts needs
3
- // at runtime. Two artifacts can be missing on a fresh clone:
1
+ // Boot-time artifact check Phase 19 / DDR-044, simplified in v0.18.1.
4
2
  //
5
- // - dist/client.bundle.js → 404 on /_client/*
6
- // - node_modules/react → 500 on /_canvas-runtime/*
3
+ // The two artifacts the server cannot run without:
4
+ // - dist/client.bundle.js (the React shell that hydrates the / route)
5
+ // - dist/runtime/react.js (pre-built canvas-runtime bundle for TSX iframes)
7
6
  //
8
- // Per DDR-044 we commit the bundle + styles, so dist/ should be present.
9
- // For node_modules/ we self-heal: detect missing react, run `bun install
10
- // --production`. Opt out with MAUDE_NO_AUTOBUILD=1 for read-only-filesystem
11
- // deployments (e.g. immutable infra).
7
+ // Both are committed to git per DDR-044 and ship in every distribution:
8
+ // npm tarball (via package.json#files override of .gitignore), marketplace
9
+ // cache (negation entries in .gitignore preserve them through git clone),
10
+ // and bun --compile binary (embedded via the build pipeline).
12
11
  //
13
- // Phase 19. DDR-044.
12
+ // v0.18.0 ALSO tried to `bun install --production` if node_modules/react
13
+ // was missing. That assumption was wrong: (a) npm install of the root
14
+ // @1agh/maude package never installs nested workspace deps, (b) the
15
+ // compiled binary's import.meta.url resolves to the virtual /$bunfs/root
16
+ // so existsSync against it always failed and the self-heal false-triggered,
17
+ // (c) standalone bun --compile binaries don't inherit shell PATH the same
18
+ // way subshells do, so even when bun WAS available, Bun.spawn(['bun',...])
19
+ // failed with ENOENT. The greenfield npm-install user hit all three at
20
+ // once and got a stacktrace. v0.18.1 drops the install/build attempt
21
+ // entirely — pre-built runtime bundles ship with the artifact, no fix-up
22
+ // pass needed.
14
23
 
15
24
  import { existsSync } from 'node:fs';
16
- import { dirname, join } from 'node:path';
17
- import { fileURLToPath } from 'node:url';
25
+ import { join } from 'node:path';
26
+
27
+ import { DEV_SERVER_ROOT, DIST_DIR, RUNTIME_BUNDLES_DIR } from './paths.ts';
18
28
 
19
29
  export interface SelfHealOptions {
20
- /** Plugin install directory (the dev-server root). Defaults to this file's dir. */
30
+ /** Defaults to DEV_SERVER_ROOT from paths.ts (real disk install dir). */
21
31
  here?: string;
22
- /** Defaults to process.env.MAUDE_NO_AUTOBUILD === '1'. */
23
- optOut?: boolean;
24
- /** Defaults to Bun.spawn; tests override. */
25
- spawn?: (cmd: readonly string[], cwd: string) => Promise<{ code: number }>;
26
32
  /** Defaults to console.error; tests override to capture. */
27
33
  log?: (msg: string) => void;
28
- /** Defaults to process.exit; tests override to assert. */
34
+ /** Defaults to process.exit; tests override to assert without aborting. */
29
35
  exit?: (code: number) => never;
30
36
  }
31
37
 
32
38
  export interface SelfHealResult {
33
- ran: ('install' | 'build')[];
34
- skipped: 'all-present' | null;
39
+ /** Names of artifacts the check verified are present. */
40
+ verified: ('client.bundle.js' | 'runtime/react.js')[];
35
41
  }
36
42
 
43
+ /**
44
+ * Verify the committed artifacts the dev-server depends on are reachable
45
+ * from the resolved install dir. If anything is missing, exit with a clear
46
+ * remediation message — this means the install is broken, not a transient
47
+ * first-boot gap. Always passes for npm installs, marketplace cache clones,
48
+ * and `bun --compile` binaries built on a freshly-built repo.
49
+ */
37
50
  export async function bootSelfHeal(opts: SelfHealOptions = {}): Promise<SelfHealResult> {
38
- const here = opts.here ?? dirname(fileURLToPath(import.meta.url));
39
- const optOut = opts.optOut ?? process.env.MAUDE_NO_AUTOBUILD === '1';
51
+ const here = opts.here ?? DEV_SERVER_ROOT;
40
52
  const log = opts.log ?? ((m) => console.error(m));
41
53
  const exit =
42
54
  opts.exit ??
43
55
  ((code: number) => {
44
56
  process.exit(code);
45
57
  });
46
- const spawn = opts.spawn ?? defaultSpawn;
47
58
 
48
- const distMissing = !existsSync(join(here, 'dist', 'client.bundle.js'));
49
- const depsMissing = !existsSync(join(here, 'node_modules', 'react', 'package.json'));
59
+ const dist = here === DEV_SERVER_ROOT ? DIST_DIR : join(here, 'dist');
60
+ const runtime = here === DEV_SERVER_ROOT ? RUNTIME_BUNDLES_DIR : join(dist, 'runtime');
50
61
 
51
- if (!distMissing && !depsMissing) return { ran: [], skipped: 'all-present' };
62
+ const missing: string[] = [];
63
+ if (!existsSync(join(dist, 'client.bundle.js'))) missing.push('dist/client.bundle.js');
64
+ if (!existsSync(join(runtime, 'react.js'))) missing.push('dist/runtime/react.js');
52
65
 
53
- if (optOut) {
54
- const missing = [
55
- distMissing ? 'dist/client.bundle.js (run `bun run build.ts`)' : null,
56
- depsMissing ? 'node_modules/react (run `bun install --production`)' : null,
57
- ]
58
- .filter(Boolean)
59
- .join('\n - ');
60
- log(`\n first-boot artifacts missing and MAUDE_NO_AUTOBUILD=1 is set:\n - ${missing}\n`);
66
+ if (missing.length > 0) {
67
+ log(
68
+ [
69
+ '',
70
+ ' ⚠ dev-server install is missing committed artifacts:',
71
+ ...missing.map((m) => ` - ${m}`),
72
+ '',
73
+ ` Looked under: ${here}`,
74
+ '',
75
+ ' This means your install is corrupted or pre-Phase-19.1. Fix:',
76
+ ' npm uninstall -g @1agh/maude && npm i -g @1agh/maude',
77
+ ' (or remove + re-add the marketplace plugin in Claude Code)',
78
+ '',
79
+ ].join('\n')
80
+ );
61
81
  exit(1);
62
82
  }
63
83
 
64
- const ran: ('install' | 'build')[] = [];
65
- if (depsMissing) {
66
- log(' ⚠ first-boot: installing runtime deps (one-time, ~15s)…');
67
- const { code } = await spawn(['bun', 'install', '--production'], here);
68
- if (code !== 0) {
69
- log(` ⚠ \`bun install --production\` exited ${code}. Set MAUDE_NO_AUTOBUILD=1 and run manually.`);
70
- exit(1);
71
- }
72
- ran.push('install');
73
- }
74
- if (distMissing) {
75
- log(' ⚠ first-boot: building client assets (one-time, ~2s)…');
76
- const { code } = await spawn(['bun', 'run', 'build.ts'], here);
77
- if (code !== 0) {
78
- log(` ⚠ \`bun run build.ts\` exited ${code}. Set MAUDE_NO_AUTOBUILD=1 and run manually.`);
79
- exit(1);
80
- }
81
- ran.push('build');
82
- }
83
- return { ran, skipped: null };
84
- }
85
-
86
- async function defaultSpawn(cmd: readonly string[], cwd: string): Promise<{ code: number }> {
87
- const proc = Bun.spawn([...cmd], { cwd, stdout: 'inherit', stderr: 'inherit' });
88
- const code = await proc.exited;
89
- return { code };
84
+ return {
85
+ verified: ['client.bundle.js', 'runtime/react.js'],
86
+ };
90
87
  }
@@ -136,6 +136,35 @@ async function buildCss(): Promise<{ outBytes: number; outPath: string }> {
136
136
  return { outBytes: code.byteLength, outPath };
137
137
  }
138
138
 
139
+ // ---------- (b.5) Pre-built runtime bundles (Phase 19.1 / v0.18.1) ----------
140
+ //
141
+ // /_canvas-runtime/<slug>.js used to lazy-build on first request via Bun.build.
142
+ // That required a real disk node_modules/react reachable by walking up from
143
+ // the dev-server dir — false in compiled binaries (paths are virtual) AND
144
+ // false in npm installs (npm doesn't install nested workspace deps).
145
+ // Pre-building all 6 sub-bundles at release time + shipping in dist/runtime/
146
+ // eliminates the runtime dependency on disk node_modules entirely.
147
+
148
+ async function buildRuntimeBundles(): Promise<{ outDir: string; count: number; bytes: number }> {
149
+ // Defer import so build.ts can run in --dry-run without pulling react.
150
+ const { RUNTIME_PACKAGES, getRuntimeBundle, slugFor } = await import('./runtime-bundle.ts');
151
+ const outDir = join(DIST, 'runtime');
152
+ if (!existsSync(outDir)) mkdirSync(outDir, { recursive: true });
153
+ let bytes = 0;
154
+ for (const pkg of RUNTIME_PACKAGES) {
155
+ const slug = slugFor(pkg);
156
+ // skipPrebuilt: don't reuse a previous build's output. minify in release.
157
+ const bundle = await getRuntimeBundle(pkg, {
158
+ skipPrebuilt: true,
159
+ minify: MODE === 'release',
160
+ });
161
+ const outPath = join(outDir, `${slug}.js`);
162
+ await Bun.write(outPath, bundle.js);
163
+ bytes += bundle.js.length;
164
+ }
165
+ return { outDir, count: RUNTIME_PACKAGES.length, bytes };
166
+ }
167
+
139
168
  // ---------- (c) Server binary (bun build --compile, per-platform) ----------
140
169
 
141
170
  // Per-target oxc-parser binding embed. Bun 1.3.4+ regressed `--compile` NAPI
@@ -373,6 +402,15 @@ async function main() {
373
402
  `[build] styles.css ${css.outBytes.toLocaleString()} B (${(t2 - t1).toFixed(0)} ms)`
374
403
  );
375
404
 
405
+ // Pre-built runtime bundles — ship to disk so /_canvas-runtime/* never
406
+ // needs a runtime Bun.build (which would need disk node_modules/react,
407
+ // absent in compiled binaries + npm installs). Phase 19.1 / v0.18.1.
408
+ const runtime = await buildRuntimeBundles();
409
+ const t2b = performance.now();
410
+ console.log(
411
+ `[build] dist/runtime/*.js ${runtime.bytes.toLocaleString()} B in ${runtime.count} files (${(t2b - t2).toFixed(0)} ms)`
412
+ );
413
+
376
414
  if (MODE === 'release') {
377
415
  const targets: PlatformTarget[] = FLAG_TARGET
378
416
  ? [FLAG_TARGET as PlatformTarget]