@laitszkin/apollo-toolkit 3.11.1 → 3.11.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/CHANGELOG.md CHANGED
@@ -10,6 +10,18 @@ All notable changes to this repository are documented in this file.
10
10
 
11
11
  ### Fixed
12
12
 
13
+ ## [v3.11.2] - 2026-05-11
14
+
15
+ ### Fixed
16
+
17
+ - `apltk architecture` / `resolveProjectRoot`: auto-create `resources/project-architecture/` on every command; when no atlas marker is found walking parent directories, use the current working directory as the project root (explicit `--project` still wins). `open` renders a fresh `index.html` when the file is missing so an empty tree bootstraps in one step.
18
+ - Legacy `init-project-html/scripts/architecture.js` `open` / `diff`: same directory creation and one-shot `render` bootstrap via `architecture-bootstrap-render.js` when `index.html` is absent.
19
+
20
+ ### Added
21
+
22
+ - `init-project-html/scripts/architecture-bootstrap-render.js` helper invoked by the legacy sync `open` path.
23
+ - Tests: `test/atlas-cli.test.js` covers `--project` on a bare directory (layout + `index.html`); `test/architecture-script.test.js` expects legacy `open` to exit 0 when `index.html` is missing after bootstrap.
24
+
13
25
  ## [v3.11.1] - 2026-05-11
14
26
 
15
27
  ### Added
@@ -22,7 +22,7 @@
22
22
  // help / --help / -h usage
23
23
  //
24
24
  // Global flags:
25
- // --project <root> project root (default: nearest ancestor with resources/project-architecture/)
25
+ // --project <root> project root; creates resources/project-architecture/ if missing
26
26
  // --spec <spec_dir> spec directory; mutations go to <spec_dir>/architecture_diff/atlas/
27
27
  // --no-render skip auto-render after a mutation
28
28
  // --no-open for open/diff: skip launching the browser
@@ -67,7 +67,7 @@ Verbs:
67
67
  help show this help
68
68
 
69
69
  Global flags:
70
- --project <root> project root (default: nearest ancestor with resources/project-architecture/)
70
+ --project <root> explicit project root (default: nearest ancestor with atlas markers, else cwd); missing directories under resources/project-architecture/ are created automatically
71
71
  --spec <spec_dir> mutations write to <spec_dir>/architecture_diff/atlas/
72
72
  --no-render skip auto-render after a mutation
73
73
  --no-open for open/diff: skip launching the browser
@@ -98,6 +98,10 @@ function openInBrowser(filePath) {
98
98
  } catch (_e) { /* best effort */ }
99
99
  }
100
100
 
101
+ function ensureResourcesLayout(projectRoot) {
102
+ fs.mkdirSync(path.join(projectRoot, ATLAS_REL), { recursive: true });
103
+ }
104
+
101
105
  function findProjectRoot(startDir) {
102
106
  let dir = path.resolve(startDir);
103
107
  while (true) {
@@ -154,10 +158,15 @@ function requireFlag(flags, name) {
154
158
  }
155
159
 
156
160
  function resolveProjectRoot(flags) {
157
- if (flags.project) return path.resolve(String(flags.project));
158
- const root = findProjectRoot(process.cwd());
159
- if (!root) throw new Error('Could not find resources/project-architecture/. Pass --project <root> or run inside the project.');
160
- return root;
161
+ const finish = (root) => {
162
+ ensureResourcesLayout(root);
163
+ return root;
164
+ };
165
+ if (flags.project) return finish(path.resolve(String(flags.project)));
166
+ const discovered = findProjectRoot(process.cwd());
167
+ if (discovered) return finish(discovered);
168
+ // No marker walking parents — use cwd and create resources/project-architecture/.
169
+ return finish(process.cwd());
161
170
  }
162
171
 
163
172
  function specOverlayDir(projectRoot, specFlag) {
@@ -655,14 +664,10 @@ async function verbUndo(flags, projectRoot, io) {
655
664
  async function verbOpen(flags, projectRoot, io) {
656
665
  const atlas = path.join(projectRoot, ATLAS_INDEX_REL);
657
666
  if (!fs.existsSync(atlas)) {
658
- // Try to render fresh if state exists
659
- const baseDir = baseAtlasDir(projectRoot);
660
- if (fs.existsSync(path.join(baseDir, stateLib.INDEX_FILE))) {
661
- await runRender({ projectRoot, flags: { ...flags, spec: undefined } });
662
- }
667
+ await runRender({ projectRoot, flags: { ...flags, spec: undefined } });
663
668
  }
664
669
  if (!fs.existsSync(atlas)) {
665
- io.stderr.write(`Atlas not found: ${atlas}\n`);
670
+ io.stderr.write(`Atlas not found after render: ${atlas}\n`);
666
671
  return 1;
667
672
  }
668
673
  io.stdout.write(`${atlas}\n`);
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ // One-shot helper: `node architecture-bootstrap-render.js render --project <root> ...`
5
+ // Invoked synchronously from architecture.js (legacy open) when index.html is missing
6
+ // so the sync `main()` can still bootstrap an empty tree without duplicating elk layout.
7
+
8
+ const cli = require('../lib/atlas/cli');
9
+
10
+ (async () => {
11
+ const code = await cli.dispatch(process.argv.slice(2));
12
+ process.exit(typeof code === 'number' ? code : 1);
13
+ })().catch((err) => {
14
+ process.stderr.write(`${err && err.stack ? err.stack : err}\n`);
15
+ process.exit(1);
16
+ });
@@ -15,7 +15,7 @@
15
15
 
16
16
  const fs = require('node:fs');
17
17
  const path = require('node:path');
18
- const { spawn } = require('node:child_process');
18
+ const { spawn, spawnSync } = require('node:child_process');
19
19
 
20
20
  const newCli = require('../lib/atlas/cli');
21
21
 
@@ -47,7 +47,7 @@ Usage:
47
47
  apltk architecture --help Show this help
48
48
 
49
49
  Global flags:
50
- --project <root> Project root (default: nearest ancestor with resources/project-architecture/)
50
+ --project <root> Project root (default: nearest ancestor with resources/project-architecture/, else cwd); missing layout dirs are created when needed
51
51
  --spec <spec_dir> Mutations write to <spec_dir>/architecture_diff/atlas/
52
52
  --no-render Skip auto-render after a mutation
53
53
  --no-open For open/diff: skip launching the browser
@@ -221,14 +221,24 @@ function renderViewer({ changes, projectRoot, outDir }) {
221
221
  }
222
222
 
223
223
  function runOpen(opts, io) {
224
- const projectRoot = opts.projectRoot || findProjectRoot(process.cwd());
224
+ let projectRoot = opts.projectRoot
225
+ ? path.resolve(opts.projectRoot)
226
+ : findProjectRoot(process.cwd());
225
227
  if (!projectRoot) {
226
- io.stderr.write(
227
- `Could not find resources/project-architecture/index.html. Pass --project <root> or generate the atlas via the init-project-html skill.\n`,
228
- );
229
- return 1;
228
+ projectRoot = process.cwd();
230
229
  }
230
+ fs.mkdirSync(path.join(projectRoot, RESOURCES_REL), { recursive: true });
231
231
  const atlas = path.join(projectRoot, ATLAS_REL);
232
+ if (!fs.existsSync(atlas)) {
233
+ const bootstrap = path.join(__dirname, 'architecture-bootstrap-render.js');
234
+ const result = spawnSync(process.execPath, [bootstrap, 'render', '--project', projectRoot, '--no-open'], {
235
+ stdio: 'ignore',
236
+ });
237
+ if (result.status !== 0) {
238
+ io.stderr.write(`Atlas not found and render failed: ${atlas}\n`);
239
+ return 1;
240
+ }
241
+ }
232
242
  if (!fs.existsSync(atlas)) {
233
243
  io.stderr.write(`Atlas not found: ${atlas}\n`);
234
244
  return 1;
@@ -239,13 +249,13 @@ function runOpen(opts, io) {
239
249
  }
240
250
 
241
251
  function runDiff(opts, io) {
242
- const projectRoot = opts.projectRoot || findProjectRoot(process.cwd());
252
+ let projectRoot = opts.projectRoot
253
+ ? path.resolve(opts.projectRoot)
254
+ : findProjectRoot(process.cwd());
243
255
  if (!projectRoot) {
244
- io.stderr.write(
245
- `Could not find resources/project-architecture/index.html. Pass --project <root> or generate the atlas via the init-project-html skill.\n`,
246
- );
247
- return 1;
256
+ projectRoot = process.cwd();
248
257
  }
258
+ fs.mkdirSync(path.join(projectRoot, RESOURCES_REL), { recursive: true });
249
259
  const outDir = opts.out || path.join(projectRoot, DEFAULT_OUT_REL);
250
260
  fs.mkdirSync(outDir, { recursive: true });
251
261
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@laitszkin/apollo-toolkit",
3
- "version": "3.11.1",
3
+ "version": "3.11.2",
4
4
  "description": "Apollo Toolkit npm installer for managed skill copying across Codex, OpenClaw, and Trae.",
5
5
  "license": "MIT",
6
6
  "author": "LaiTszKin",