@chem-x/starter-kit 26.9.20-1298 → 26.9.20-1318

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/README.md CHANGED
@@ -18,6 +18,47 @@ Access the interactive book, prompt generator, and asset vault at [https://chemi
18
18
 
19
19
  ---
20
20
 
21
+ ## Quickstart: Scaffolding a New Project
22
+
23
+ Create a brand new molecular architecture project in seconds using your preferred package manager:
24
+
25
+ ```bash
26
+ # npm (interactive or pass project directory)
27
+ npm create chemx my-molecular-app
28
+
29
+ # Automated / Agent / Headless mode (skips prompts, scaffolds Community Edition immediately)
30
+ npm create chemx my-molecular-app -- --yes
31
+
32
+ # npx
33
+ npx create-chemx my-molecular-app --yes
34
+
35
+ # pnpm / yarn / bun
36
+ pnpm create chemx my-molecular-app
37
+ yarn create chemx my-molecular-app
38
+ bun create chemx my-molecular-app
39
+ ```
40
+
41
+ ### Headless & Autonomous Agent Mode
42
+ When running in unattended environments (CI/CD pipelines, Cursor Agent, Windsurf, Claude Code, Antigravity), pass `--yes` (or `-y`, `--ci`, `--headless`) to bypass interactive terminal menus and immediately scaffold the free Community Edition with recommended architectural pillars:
43
+
44
+ ```bash
45
+ npx create-chemx my-molecular-app --yes
46
+ ```
47
+
48
+ ### Package Architecture: Scaffolder vs Command Engine
49
+ Chemical X provides two coordinated packages:
50
+ - **`create-chemx`**: Dedicated zero-dependency project scaffolder (`npm create chemx`). Directly provisions project templates, test suites, and architectural configurations.
51
+ - **`chemx`**: The full Molecular Architecture CLI & AST Query Engine. Manages audits, verifications, AST query lookups, code patching, and multi-agent swarm task coordination.
52
+
53
+ ```bash
54
+ # Install chemx CLI globally or in your project:
55
+ npm install -g chemx
56
+ # or run on-demand:
57
+ npx chemx --help
58
+ ```
59
+
60
+ ---
61
+
21
62
  ## Structure
22
63
 
23
64
  ```
@@ -138,6 +179,106 @@ $ npx chemx verify --dir=blueprints
138
179
 
139
180
  ---
140
181
 
182
+ ## CLI Command Reference & Workflow
183
+
184
+ The `chemx` command suite is specifically tailored for token conservation, instant feedback, and zero terminal clutter:
185
+
186
+ ### 1. Verification & Quality
187
+ ```bash
188
+ # Full verification pipeline (AST Audit + Typecheck + Tests) -> ~45 token status card
189
+ chemx verify
190
+ chemx verify --json
191
+
192
+ # Run 7-Pillar static AST audit
193
+ chemx audit
194
+ chemx audit --unroll # Inspect individual hazard lines and explanations
195
+ chemx audit --strict # Fail on any violation, including minor style warnings
196
+ chemx audit --json # Machine-readable format for agent pipelines
197
+
198
+ # Silent TypeScript compilation check (suppresses passing noise, returns error lines)
199
+ chemx typecheck
200
+ chemx typecheck --json
201
+
202
+ # Silent test runner (suppresses passing tests, extracts only failing assertions & stack diffs)
203
+ chemx test
204
+ chemx test --json
205
+
206
+ # Silent build audit (categorizes diagnostics into TypeScript, Rollup, and style budgets)
207
+ chemx build
208
+ chemx build --json
209
+ ```
210
+
211
+ ### 2. AST Query Engine & Surgical Inspection
212
+ ```bash
213
+ # Hybrid search (BM25 keyword + cosine vector similarity via Reciprocal Rank Fusion)
214
+ chemx q "useAttentionCardController" --hybrid --json
215
+
216
+ # Transitive blast radius analysis before refactoring foundational capsules
217
+ chemx q "a-button" --blast-radius --json
218
+
219
+ # Inspect component props, hooks, and types without reading entire files
220
+ chemx q "m-task-list" --inspect
221
+
222
+ # Surgical token-optimized file reader (AST outlines, stripped comments, specific symbols)
223
+ chemx read src/components/m-card.vue --symbol=useCardController
224
+ chemx read src/components/m-card.vue --outline
225
+ chemx read src/components/m-card.vue --start=10 --end=40
226
+
227
+ # Surgical file patching without full-file rewrites
228
+ chemx patch <file> --target="oldCode" --replacement="newCode"
229
+ ```
230
+
231
+ ### 3. Crystalline Capsule Generator
232
+ Scaffold production-ready component capsules matching strict zero-raw-DOM standards:
233
+ ```bash
234
+ # Molecule capsule (component, controller, glass styling, types, spec)
235
+ chemx m-task-card
236
+
237
+ # Atom foundation (the only tier permitted raw HTML elements)
238
+ chemx a-status-pill
239
+
240
+ # Organism module (complex grouping of molecules and atoms)
241
+ chemx o-workspace-header
242
+
243
+ # Pure reactive hook / domain composable
244
+ chemx use-task-filter
245
+ ```
246
+
247
+ ### 4. Database-Driven Multi-Agent Swarm Coordination
248
+ Coordinate multi-agent swarms using the local SQLite store (`.chemx/index.db`) without multi-thousand-token markdown specification bloat:
249
+ ```bash
250
+ # Auto-triage: convert AST audit hazards directly into assignable team tasks
251
+ chemx team task triage
252
+
253
+ # List tasks assigned to a specific agent
254
+ chemx team task list --agent=@agent-alpha
255
+
256
+ # Claim an open task
257
+ chemx team task claim 1 --as=@agent-alpha
258
+
259
+ # Mark task complete (automatically re-audits target file on disk to guarantee zero hazards)
260
+ chemx team task done 1 --as=@agent-alpha
261
+
262
+ # Inspect multi-agent swarm status and lock queues
263
+ chemx team status
264
+ ```
265
+
266
+ ---
267
+
268
+ ## The 7 Molecular Architecture Pillars
269
+
270
+ Chemical X enforces seven core architectural directives configured via `chemx pillars`:
271
+
272
+ 1. **Strict Molecular Line Budgets (< 100 Lines)**: Single-purpose files. Approaching 100 lines is a decomposition trigger. Eliminates context rot and cuts token ingestion costs.
273
+ 2. **Strict Component Tiers & Zero-Raw-DOM**: Raw HTML elements (`<button>`, `<input>`, `<div>`) are strictly isolated inside foundational **Atoms** (`a-*`). Molecules, Organisms, Templates, and Views assemble atoms and never contain raw tags.
274
+ 3. **Table-of-Contents Views**: Top-level page views are clean, 10–20 line declarative blueprints assembling self-contained molecules and organisms via named slots (`#header`, `#default`, `#modals`).
275
+ 4. **Molecular Composable Contracts**: Composables return plain destructurable objects with a strict 3-to-5 property limit (State + Status + Actions). Domain types use discriminated unions (zero impossible states).
276
+ 5. **Silent Verification Pipeline**: Verification tools suppress passing checkmarks and compiler banners, returning token-compact summaries (~45 tokens) to protect AI agent context windows.
277
+ 6. **AST Codebase Query Engine**: In-band AST symbol graph lookups, blast radius calculations, and outline extraction eliminate blind full-file context dumps.
278
+ 7. **Database-First Swarm Coordination**: Task backlogs, file locks, and agent communications live in local SQLite (`.chemx/index.db`) rather than monolithic markdown specifications.
279
+
280
+ ---
281
+
141
282
  ## Model Context Protocol (MCP) Server
142
283
 
143
284
  Chemical X includes a high-performance, zero-dependency JSON-RPC 2.0 Stdio MCP server that connects directly to AI agent hosts (Cursor, Claude Desktop, Windsurf, Antigravity, VS Code).
package/cli/create.js ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { runScaffold } from './scaffold.js';
4
+ import { runAudit } from './index.js';
5
+ import { sanitizeOutputStreams } from './terminal.js';
6
+ import { installGlobalErrorCatcher } from './errors/index.js';
7
+
8
+ sanitizeOutputStreams();
9
+ installGlobalErrorCatcher();
10
+
11
+ const rawArgs = process.argv.slice(2);
12
+ const nonFlagArgs = rawArgs.filter((arg) => !arg.startsWith('-'));
13
+ const dirArg = (nonFlagArgs[0] === 'create' || nonFlagArgs[0] === 'init' || nonFlagArgs[0] === 'scaffold')
14
+ ? nonFlagArgs[1]
15
+ : nonFlagArgs[0];
16
+
17
+ await runScaffold(dirArg, rawArgs, runAudit);
@@ -0,0 +1,146 @@
1
+ import { test, describe, afterEach } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { spawnSync } from 'node:child_process';
4
+ import path from 'node:path';
5
+ import fs from 'node:fs';
6
+ import os from 'node:os';
7
+
8
+ const CLI_DIR = path.resolve(import.meta.dirname);
9
+ const CREATE_BIN = path.join(CLI_DIR, 'create.js');
10
+ const INDEX_BIN = path.join(CLI_DIR, 'index.js');
11
+
12
+ describe('Scaffolding Entrypoint Invocations', () => {
13
+ const cleanupDirs = [];
14
+
15
+ afterEach(() => {
16
+ while (cleanupDirs.length > 0) {
17
+ const dir = cleanupDirs.pop();
18
+ if (fs.existsSync(dir)) {
19
+ try {
20
+ fs.rmSync(dir, { recursive: true, force: true });
21
+ } catch {
22
+ // ignore cleanup errors
23
+ }
24
+ }
25
+ }
26
+ });
27
+
28
+ test('node cli/create.js <dir> --yes scaffolds project directly into target directory', () => {
29
+ const tmpBase = fs.mkdtempSync(path.join(os.tmpdir(), 'chemx-test-'));
30
+ cleanupDirs.push(tmpBase);
31
+ const targetDir = path.join(tmpBase, 'test-target-app');
32
+
33
+ const result = spawnSync('node', [CREATE_BIN, targetDir, '--yes'], {
34
+ encoding: 'utf-8',
35
+ cwd: tmpBase,
36
+ timeout: 15000
37
+ });
38
+
39
+ assert.equal(result.status, 0, `Expected exit 0, got: ${result.status}\nStdout: ${result.stdout}\nStderr: ${result.stderr}`);
40
+ assert.ok(fs.existsSync(path.join(targetDir, 'package.json')), 'package.json should be created in targetDir');
41
+ assert.ok(fs.existsSync(path.join(targetDir, 'molecule-capsule')), 'molecule-capsule/ should be created in targetDir');
42
+ });
43
+
44
+ test('node cli/create.js --yes (no dir argument) scaffolds into default my-molecular-app', () => {
45
+ const tmpBase = fs.mkdtempSync(path.join(os.tmpdir(), 'chemx-test-'));
46
+ cleanupDirs.push(tmpBase);
47
+ const defaultTarget = path.join(tmpBase, 'my-molecular-app');
48
+
49
+ const result = spawnSync('node', [CREATE_BIN, '--yes'], {
50
+ encoding: 'utf-8',
51
+ cwd: tmpBase,
52
+ timeout: 15000
53
+ });
54
+
55
+ assert.equal(result.status, 0, `Expected exit 0, got: ${result.status}\nStdout: ${result.stdout}\nStderr: ${result.stderr}`);
56
+ assert.ok(fs.existsSync(path.join(defaultTarget, 'package.json')), 'package.json should exist in default directory');
57
+ });
58
+
59
+ test('node cli/create.js create <dir> --yes tolerates redundant create argument', () => {
60
+ const tmpBase = fs.mkdtempSync(path.join(os.tmpdir(), 'chemx-test-'));
61
+ cleanupDirs.push(tmpBase);
62
+ const targetDir = path.join(tmpBase, 'redundant-create-app');
63
+
64
+ const result = spawnSync('node', [CREATE_BIN, 'create', targetDir, '--yes'], {
65
+ encoding: 'utf-8',
66
+ cwd: tmpBase,
67
+ timeout: 15000
68
+ });
69
+
70
+ assert.equal(result.status, 0, `Expected exit 0, got: ${result.status}\nStdout: ${result.stdout}\nStderr: ${result.stderr}`);
71
+ assert.ok(fs.existsSync(path.join(targetDir, 'package.json')), 'package.json should be created in targetDir');
72
+ });
73
+
74
+ test('node cli/index.js create <dir> --yes scaffolds project via chemx create', () => {
75
+ const tmpBase = fs.mkdtempSync(path.join(os.tmpdir(), 'chemx-test-'));
76
+ cleanupDirs.push(tmpBase);
77
+ const targetDir = path.join(tmpBase, 'chemx-create-app');
78
+
79
+ const result = spawnSync('node', [INDEX_BIN, 'create', targetDir, '--yes'], {
80
+ encoding: 'utf-8',
81
+ cwd: tmpBase,
82
+ timeout: 15000
83
+ });
84
+
85
+ assert.equal(result.status, 0, `Expected exit 0, got: ${result.status}\nStdout: ${result.stdout}\nStderr: ${result.stderr}`);
86
+ assert.ok(fs.existsSync(path.join(targetDir, 'package.json')), 'package.json should exist');
87
+ });
88
+
89
+ test('node cli/index.js create --yes scaffolds project via chemx create without positional dir', () => {
90
+ const tmpBase = fs.mkdtempSync(path.join(os.tmpdir(), 'chemx-test-'));
91
+ cleanupDirs.push(tmpBase);
92
+ const defaultTarget = path.join(tmpBase, 'my-molecular-app');
93
+
94
+ const result = spawnSync('node', [INDEX_BIN, 'create', '--yes'], {
95
+ encoding: 'utf-8',
96
+ cwd: tmpBase,
97
+ timeout: 15000
98
+ });
99
+
100
+ assert.equal(result.status, 0, `Expected exit 0, got: ${result.status}\nStdout: ${result.stdout}\nStderr: ${result.stderr}`);
101
+ assert.ok(fs.existsSync(path.join(defaultTarget, 'package.json')), 'package.json should exist');
102
+ });
103
+
104
+ test('executing via create-chemx symlink scaffolds successfully', () => {
105
+ const tmpBase = fs.mkdtempSync(path.join(os.tmpdir(), 'chemx-test-'));
106
+ cleanupDirs.push(tmpBase);
107
+ const symlinkPath = path.join(tmpBase, 'create-chemx');
108
+ fs.symlinkSync(CREATE_BIN, symlinkPath);
109
+ const targetDir = path.join(tmpBase, 'symlink-app');
110
+
111
+ const result = spawnSync(symlinkPath, [targetDir, '--yes'], {
112
+ encoding: 'utf-8',
113
+ cwd: tmpBase,
114
+ timeout: 15000
115
+ });
116
+
117
+ assert.equal(result.status, 0, `Expected exit 0, got: ${result.status}\nStdout: ${result.stdout}\nStderr: ${result.stderr}`);
118
+ assert.ok(fs.existsSync(path.join(targetDir, 'package.json')), 'package.json should exist');
119
+ });
120
+
121
+ test('node cli/create.js <dir> -y (short flag) scaffolds successfully', () => {
122
+ const tmpBase = fs.mkdtempSync(path.join(os.tmpdir(), 'chemx-test-'));
123
+ cleanupDirs.push(tmpBase);
124
+ const targetDir = path.join(tmpBase, 'short-flag-app');
125
+
126
+ const result = spawnSync('node', [CREATE_BIN, targetDir, '-y'], {
127
+ encoding: 'utf-8',
128
+ cwd: tmpBase,
129
+ timeout: 15000
130
+ });
131
+
132
+ assert.equal(result.status, 0, `Expected exit 0, got: ${result.status}\nStdout: ${result.stdout}\nStderr: ${result.stderr}`);
133
+ assert.ok(fs.existsSync(path.join(targetDir, 'package.json')), 'package.json should exist');
134
+ });
135
+
136
+ test('node cli/index.js config still fails fast as unknown command', () => {
137
+ const result = spawnSync('node', [INDEX_BIN, 'config'], {
138
+ encoding: 'utf-8',
139
+ timeout: 5000
140
+ });
141
+
142
+ assert.equal(result.status, 1, 'Unknown command should exit with code 1');
143
+ assert.match(result.stderr, /Unknown command "config"/, 'Should report unknown command');
144
+ });
145
+ });
146
+
package/cli/index.js CHANGED
@@ -3,6 +3,7 @@
3
3
  import './silence-warnings.js';
4
4
  import fs from 'node:fs';
5
5
  import path from 'node:path';
6
+ import { fileURLToPath } from 'node:url';
6
7
  import {
7
8
  runAudit as executeAstAudit,
8
9
  auditFile,
@@ -83,7 +84,10 @@ const loadProjectConfig = () => {
83
84
  }
84
85
  };
85
86
  const isCreateInvoked =
86
- invokedBin.includes('create-chemx') || (rawArgs[0] && rawArgs[0] === 'create');
87
+ invokedBin.includes('create') ||
88
+ Boolean(process.argv[1] && process.argv[1].includes('create-chemx')) ||
89
+ Boolean(process.env.npm_lifecycle_event && process.env.npm_lifecycle_event.includes('create')) ||
90
+ Boolean(rawArgs[0] && (rawArgs[0] === 'create' || rawArgs[0] === 'init' || rawArgs[0] === 'scaffold'));
87
91
 
88
92
  export const runAudit = async (customDir = null, isCli = false) => {
89
93
  const projectConfig = loadProjectConfig();
@@ -293,7 +297,10 @@ const main = async () => {
293
297
  const firstArg = rawArgs[0];
294
298
 
295
299
  if (isCreateInvoked) {
296
- const dirArg = firstArg === 'create' ? rawArgs[1] : firstArg;
300
+ const nonFlagArgs = rawArgs.filter((arg) => !arg.startsWith('-'));
301
+ const dirArg = (nonFlagArgs[0] === 'create' || nonFlagArgs[0] === 'init' || nonFlagArgs[0] === 'scaffold')
302
+ ? nonFlagArgs[1]
303
+ : nonFlagArgs[0];
297
304
  await runScaffold(dirArg, rawArgs, runAudit);
298
305
  return;
299
306
  }
@@ -339,9 +346,11 @@ const main = async () => {
339
346
  case 'init':
340
347
  await runInit(rawArgs[1] || 'src/chemical-x', rawArgs, runAudit);
341
348
  break;
342
- case 'create':
343
- await runScaffold(rawArgs[1], rawArgs, runAudit);
349
+ case 'create': {
350
+ const nonFlagArgs = rawArgs.slice(1).filter((arg) => !arg.startsWith('-'));
351
+ await runScaffold(nonFlagArgs[0], rawArgs, runAudit);
344
352
  break;
353
+ }
345
354
  case 'hook':
346
355
  case 'hooks':
347
356
  case 'install-hooks':
@@ -433,11 +442,24 @@ const main = async () => {
433
442
  }
434
443
  };
435
444
 
436
- main().catch(async (err) => {
437
- await handleError(err, {
438
- command: process.argv.slice(2).join(' '),
439
- cwd: process.cwd(),
440
- exitCode: 1
445
+ const isDirectExecution = () => {
446
+ if (!process.argv[1]) return false;
447
+ try {
448
+ const currentFile = fileURLToPath(import.meta.url);
449
+ const invokedFile = fs.realpathSync(process.argv[1]);
450
+ return currentFile === invokedFile;
451
+ } catch {
452
+ return false;
453
+ }
454
+ };
455
+
456
+ if (isDirectExecution()) {
457
+ main().catch(async (err) => {
458
+ await handleError(err, {
459
+ command: process.argv.slice(2).join(' '),
460
+ cwd: process.cwd(),
461
+ exitCode: 1
462
+ });
463
+ process.exit(1);
441
464
  });
442
- process.exit(1);
443
- });
465
+ }
package/cli/scaffold.js CHANGED
@@ -25,7 +25,7 @@ export const runScaffold = async (projectName, rawArgs = [], onRunAudit = null)
25
25
  files = await fetchStarterKitFiles(licenseKey);
26
26
  }
27
27
 
28
- let targetName = projectName;
28
+ let targetName = (projectName && !projectName.startsWith('-')) ? projectName : null;
29
29
  if (!targetName) {
30
30
  const isHeadless =
31
31
  rawArgs.includes('--headless') ||
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@chem-x/starter-kit",
3
- "version": "26.9.20-1298",
3
+ "version": "26.9.20-1318",
4
4
  "description": "Chemical X Protocol: Private drop-in architecture starter kit and capsule generator",
5
5
  "type": "module",
6
6
  "bin": {
7
- "create-chemx": "cli/index.js",
7
+ "create-chemx": "cli/create.js",
8
8
  "chemx": "cli/index.js",
9
9
  "chem-x": "cli/index.js",
10
10
  "chemical-x": "cli/index.js"
@@ -26,13 +26,13 @@ const TARGETS = [
26
26
  {
27
27
  name: 'create-chemx',
28
28
  isScoped: false,
29
- bin: { 'create-chemx': 'cli/index.js', chemx: 'cli/index.js' }
29
+ bin: { 'create-chemx': 'cli/create.js', chemx: 'cli/index.js' }
30
30
  },
31
31
  {
32
32
  name: '@chemx/starter-kit',
33
33
  isScoped: true,
34
34
  bin: {
35
- 'create-chemx': 'cli/index.js',
35
+ 'create-chemx': 'cli/create.js',
36
36
  chemx: 'cli/index.js',
37
37
  'chem-x': 'cli/index.js',
38
38
  'chemical-x': 'cli/index.js'
@@ -42,7 +42,7 @@ const TARGETS = [
42
42
  name: '@chem-x/starter-kit',
43
43
  isScoped: true,
44
44
  bin: {
45
- 'create-chemx': 'cli/index.js',
45
+ 'create-chemx': 'cli/create.js',
46
46
  chemx: 'cli/index.js',
47
47
  'chem-x': 'cli/index.js',
48
48
  'chemical-x': 'cli/index.js'
@@ -51,17 +51,17 @@ const TARGETS = [
51
51
  {
52
52
  name: '@chemx/create-chemx',
53
53
  isScoped: true,
54
- bin: { 'create-chemx': 'cli/index.js', chemx: 'cli/index.js' }
54
+ bin: { 'create-chemx': 'cli/create.js', chemx: 'cli/index.js' }
55
55
  },
56
56
  {
57
57
  name: '@chem-x/create-chemx',
58
58
  isScoped: true,
59
- bin: { 'create-chemx': 'cli/index.js', chemx: 'cli/index.js' }
59
+ bin: { 'create-chemx': 'cli/create.js', chemx: 'cli/index.js' }
60
60
  },
61
61
  {
62
62
  name: 'chemx',
63
63
  isScoped: false,
64
- bin: { chemx: 'cli/index.js', 'create-chemx': 'cli/index.js' }
64
+ bin: { chemx: 'cli/index.js', 'create-chemx': 'cli/create.js' }
65
65
  }
66
66
  ];
67
67