@stackbilt/cli 0.9.2 → 0.11.0

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.
Files changed (103) hide show
  1. package/LICENSE +17 -1
  2. package/README.md +57 -0
  3. package/dist/__tests__/auth-wiring.test.d.ts +2 -0
  4. package/dist/__tests__/auth-wiring.test.d.ts.map +1 -0
  5. package/dist/__tests__/auth-wiring.test.js +158 -0
  6. package/dist/__tests__/auth-wiring.test.js.map +1 -0
  7. package/dist/__tests__/bootstrap.test.d.ts +2 -0
  8. package/dist/__tests__/bootstrap.test.d.ts.map +1 -0
  9. package/dist/__tests__/bootstrap.test.js +134 -0
  10. package/dist/__tests__/bootstrap.test.js.map +1 -0
  11. package/dist/__tests__/credentials.test.d.ts +2 -0
  12. package/dist/__tests__/credentials.test.d.ts.map +1 -0
  13. package/dist/__tests__/credentials.test.js +145 -0
  14. package/dist/__tests__/credentials.test.js.map +1 -0
  15. package/dist/__tests__/integration/precommit-hook.test.js +4 -4
  16. package/dist/__tests__/login.test.d.ts +2 -0
  17. package/dist/__tests__/login.test.d.ts.map +1 -0
  18. package/dist/__tests__/login.test.js +43 -0
  19. package/dist/__tests__/login.test.js.map +1 -0
  20. package/dist/__tests__/named-scaffolds.test.d.ts +2 -0
  21. package/dist/__tests__/named-scaffolds.test.d.ts.map +1 -0
  22. package/dist/__tests__/named-scaffolds.test.js +58 -0
  23. package/dist/__tests__/named-scaffolds.test.js.map +1 -0
  24. package/dist/__tests__/score.test.d.ts +2 -0
  25. package/dist/__tests__/score.test.d.ts.map +1 -0
  26. package/dist/__tests__/score.test.js +234 -0
  27. package/dist/__tests__/score.test.js.map +1 -0
  28. package/dist/commands/adf-named-scaffolds.d.ts +45 -0
  29. package/dist/commands/adf-named-scaffolds.d.ts.map +1 -0
  30. package/dist/commands/adf-named-scaffolds.js +114 -0
  31. package/dist/commands/adf-named-scaffolds.js.map +1 -0
  32. package/dist/commands/adf-tidy.d.ts.map +1 -1
  33. package/dist/commands/adf-tidy.js +6 -3
  34. package/dist/commands/adf-tidy.js.map +1 -1
  35. package/dist/commands/adf.d.ts +1 -0
  36. package/dist/commands/adf.d.ts.map +1 -1
  37. package/dist/commands/adf.js +39 -15
  38. package/dist/commands/adf.js.map +1 -1
  39. package/dist/commands/architect.d.ts.map +1 -1
  40. package/dist/commands/architect.js +7 -3
  41. package/dist/commands/architect.js.map +1 -1
  42. package/dist/commands/audit.js +24 -7
  43. package/dist/commands/audit.js.map +1 -1
  44. package/dist/commands/blast.d.ts +13 -0
  45. package/dist/commands/blast.d.ts.map +1 -0
  46. package/dist/commands/blast.js +226 -0
  47. package/dist/commands/blast.js.map +1 -0
  48. package/dist/commands/bootstrap.d.ts.map +1 -1
  49. package/dist/commands/bootstrap.js +300 -101
  50. package/dist/commands/bootstrap.js.map +1 -1
  51. package/dist/commands/doctor.d.ts.map +1 -1
  52. package/dist/commands/doctor.js +9 -2
  53. package/dist/commands/doctor.js.map +1 -1
  54. package/dist/commands/init.d.ts.map +1 -1
  55. package/dist/commands/init.js +127 -8
  56. package/dist/commands/init.js.map +1 -1
  57. package/dist/commands/login.d.ts +4 -1
  58. package/dist/commands/login.d.ts.map +1 -1
  59. package/dist/commands/login.js +27 -6
  60. package/dist/commands/login.js.map +1 -1
  61. package/dist/commands/run.d.ts.map +1 -1
  62. package/dist/commands/run.js +8 -5
  63. package/dist/commands/run.js.map +1 -1
  64. package/dist/commands/score.d.ts +9 -0
  65. package/dist/commands/score.d.ts.map +1 -0
  66. package/dist/commands/score.js +1273 -0
  67. package/dist/commands/score.js.map +1 -0
  68. package/dist/commands/serve.d.ts.map +1 -1
  69. package/dist/commands/serve.js +44 -0
  70. package/dist/commands/serve.js.map +1 -1
  71. package/dist/commands/setup.js +2 -2
  72. package/dist/commands/setup.js.map +1 -1
  73. package/dist/commands/surface.d.ts +15 -0
  74. package/dist/commands/surface.d.ts.map +1 -0
  75. package/dist/commands/surface.js +112 -0
  76. package/dist/commands/surface.js.map +1 -0
  77. package/dist/commands/validate-ontology.d.ts +14 -0
  78. package/dist/commands/validate-ontology.d.ts.map +1 -0
  79. package/dist/commands/validate-ontology.js +328 -0
  80. package/dist/commands/validate-ontology.js.map +1 -0
  81. package/dist/commands/validate.d.ts.map +1 -1
  82. package/dist/commands/validate.js +44 -0
  83. package/dist/commands/validate.js.map +1 -1
  84. package/dist/config.d.ts +25 -0
  85. package/dist/config.d.ts.map +1 -1
  86. package/dist/config.js +1 -0
  87. package/dist/config.js.map +1 -1
  88. package/dist/credentials.d.ts +22 -1
  89. package/dist/credentials.d.ts.map +1 -1
  90. package/dist/credentials.js +35 -1
  91. package/dist/credentials.js.map +1 -1
  92. package/dist/http-client.d.ts +13 -4
  93. package/dist/http-client.d.ts.map +1 -1
  94. package/dist/http-client.js +3 -2
  95. package/dist/http-client.js.map +1 -1
  96. package/dist/index.d.ts.map +1 -1
  97. package/dist/index.js +22 -3
  98. package/dist/index.js.map +1 -1
  99. package/dist/types/scaffold-contract-types.d.ts +90 -0
  100. package/dist/types/scaffold-contract-types.d.ts.map +1 -0
  101. package/dist/types/scaffold-contract-types.js +22 -0
  102. package/dist/types/scaffold-contract-types.js.map +1 -0
  103. package/package.json +12 -9
package/LICENSE CHANGED
@@ -1,3 +1,19 @@
1
+ Copyright 2026 Stackbilt LLC
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
14
+
15
+ ---
16
+
1
17
  Apache License
2
18
  Version 2.0, January 2004
3
19
  http://www.apache.org/licenses/
@@ -175,7 +191,7 @@
175
191
 
176
192
  END OF TERMS AND CONDITIONS
177
193
 
178
- Copyright 2026 StackBilt, Smart Brand Strategies LLC
194
+ Copyright 2026 Stackbilt LLC
179
195
 
180
196
  Licensed under the Apache License, Version 2.0 (the "License");
181
197
  you may not use this file except in compliance with the License.
package/README.md CHANGED
@@ -69,8 +69,25 @@ charter adf migrate --dry-run # preview agent config → ADF migration
69
69
  charter adf sync --check # verify .adf files match locked hashes
70
70
  charter adf evidence --auto-measure --format json # validate metric ceilings
71
71
  charter telemetry report --period 24h --format json # passive local usage summary
72
+ charter blast src/foo.ts --depth 3 # reverse dep graph → files affected by changing this seed
73
+ charter surface --markdown # extract routes (Hono/Express) + D1 schema as markdown
72
74
  ```
73
75
 
76
+ ## Authentication (optional)
77
+
78
+ Governance commands (`validate`, `drift`, `blast`, `surface`, etc.) run locally and require no authentication.
79
+
80
+ Commands that reach the Stackbilt engine (`run`, `architect`) read their API key from the `STACKBILT_API_KEY` environment variable. A custom engine URL can be supplied via `STACKBILT_API_BASE_URL`:
81
+
82
+ ```bash
83
+ export STACKBILT_API_KEY=ea_xxx # or sb_live_xxx, sb_test_xxx
84
+ export STACKBILT_API_BASE_URL=https://engine.example # optional, for self-hosted engines
85
+ ```
86
+
87
+ Environment variables are inherited by any child processes spawned from the same shell and may appear in `/proc/<pid>/environ`. In CI, prefer setting the variable per-invocation (e.g., a job-scoped secret) rather than exporting it globally in a shared developer shell.
88
+
89
+ The legacy `charter login --key …` command still works but is deprecated and will be removed in `@stackbilt/cli` 1.0 when gateway-bound commands move to a separate package.
90
+
74
91
  ## Human Onboarding (Copy/Paste)
75
92
 
76
93
  Run this in the target repository:
@@ -299,6 +316,44 @@ charter adf migrate [--dry-run] [--source <file>] [--no-backup]
299
316
  - `metrics recalibrate`: Re-measure current LOC from manifest metric sources, propose and apply new ceilings using configurable headroom, and append rationale records to `BUDGET_RATIONALES`. Requires explicit rationale (`--reason`) unless `--auto-rationale` is used.
300
317
  - `migrate`: Scan existing agent config files (CLAUDE.md, .cursorrules, agents.md, GEMINI.md, copilot-instructions.md), classify content using the ADX-002 decision tree, and migrate into ADF modules. `--dry-run` previews the migration plan without writing files. `--source <file>` targets a single file. `--no-backup` skips `.pre-adf-migrate.bak` creation. `--merge-strategy` controls deduplication: `dedupe` (default, skip items already in ADF), `append` (always add), or `replace`. Environment-specific rules (WSL, PATH, credential helpers) are retained in the thin pointer.
301
318
 
319
+ ### `charter blast`
320
+
321
+ Compute the blast radius of a change: which files transitively depend on the given seed files? Builds a reverse dependency graph (TS/JS imports — handles ESM `.js → .ts`, tsconfig path aliases including `extends` chains, `src/index.*` fallback, cycles, comments) and BFS-traverses up to a configurable depth.
322
+
323
+ ```bash
324
+ charter blast src/kernel/dispatch.ts # default depth 3
325
+ charter blast src/a.ts src/b.ts --depth 4 # multi-seed
326
+ charter blast src/foo.ts --format json # structured output
327
+ charter blast src/foo.ts --root ./packages/x # scan a subdirectory
328
+ ```
329
+
330
+ Reports:
331
+ - `affected` — relative paths of transitively dependent files
332
+ - `hotFiles` — top 20 most-imported files in the graph (architectural hubs)
333
+ - `summary.totalAffected`, `summary.depthHistogram`
334
+
335
+ Blast radius ≥20 files triggers a `CROSS_CUTTING` warning — a signal for governance gates to escalate the change. Pure heuristic, no LLM calls, zero runtime dependencies. Backed by `@stackbilt/blast`.
336
+
337
+ ### `charter surface`
338
+
339
+ Extract the API surface of a project: HTTP routes and database schema. Designed for Cloudflare Worker projects but works on any Node.js HTTP backend.
340
+
341
+ ```bash
342
+ charter surface # text summary
343
+ charter surface --format json # machine-readable
344
+ charter surface --markdown # for .ai/surface.adf injection
345
+ charter surface --root ./packages/worker # scan a subdirectory
346
+ charter surface --schema db/schema.sql # explicit schema path
347
+ ```
348
+
349
+ Detects:
350
+ - **Routes** — Hono, Express, itty-router via regex (requires `/` path prefix; strips comments before scanning)
351
+ - **Schema** — D1/SQLite `CREATE TABLE` statements with column flags (pk, unique, nullable, default)
352
+
353
+ Ignores `__tests__/`, `*.test.*`, `*.spec.*` to avoid false positives from test fixtures.
354
+
355
+ Use cases: breaking change detection (diff surfaces before/after a PR), auto-generated AI context maps, deploy pipeline gates, mission brief fingerprinting for autonomous task runners. Backed by `@stackbilt/surface`.
356
+
302
357
  ### `charter telemetry`
303
358
 
304
359
  Passive local observability for Charter/ADF usage. Every CLI run appends command metadata (timestamp, command path, flags, duration, exit code) to `.charter/telemetry/events.ndjson`.
@@ -372,6 +427,8 @@ Setup-only options:
372
427
  - `@stackbilt/drift` -- blessed-stack pattern drift detection
373
428
  - `@stackbilt/validate` -- citation validation and intent classification
374
429
  - `@stackbilt/adf` -- ADF parser, formatter, patcher, and bundler
430
+ - `@stackbilt/blast` -- reverse dependency graph + blast radius analysis
431
+ - `@stackbilt/surface` -- API surface extraction (routes + D1 schema)
375
432
  - `@stackbilt/ci` -- GitHub Actions integration helpers
376
433
 
377
434
  ## License
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=auth-wiring.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-wiring.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/auth-wiring.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,158 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const fs = __importStar(require("node:fs"));
37
+ const os = __importStar(require("node:os"));
38
+ const path = __importStar(require("node:path"));
39
+ const vitest_1 = require("vitest");
40
+ // Hoisted mock state: vi.mock factories run before any imports, so the
41
+ // EngineClient class mock must reach these via vi.hoisted.
42
+ const hoisted = vitest_1.vi.hoisted(() => ({
43
+ buildFn: vitest_1.vi.fn(),
44
+ scaffoldFn: vitest_1.vi.fn(),
45
+ constructorArgs: [],
46
+ }));
47
+ vitest_1.vi.mock('../credentials', async () => {
48
+ const actual = await vitest_1.vi.importActual('../credentials');
49
+ return { ...actual, resolveApiKey: vitest_1.vi.fn() };
50
+ });
51
+ vitest_1.vi.mock('../http-client', () => {
52
+ return {
53
+ EngineClient: class {
54
+ constructor(opts) {
55
+ hoisted.constructorArgs.push(opts);
56
+ }
57
+ build = hoisted.buildFn;
58
+ scaffold = hoisted.scaffoldFn;
59
+ health = vitest_1.vi.fn();
60
+ catalog = vitest_1.vi.fn();
61
+ },
62
+ };
63
+ });
64
+ const credentials_1 = require("../credentials");
65
+ const architect_1 = require("../commands/architect");
66
+ const run_1 = require("../commands/run");
67
+ const mockedResolveApiKey = vitest_1.vi.mocked(credentials_1.resolveApiKey);
68
+ const options = {
69
+ format: 'json',
70
+ configPath: '.charter',
71
+ ciMode: false,
72
+ yes: true,
73
+ };
74
+ function fakeBuildResult() {
75
+ return {
76
+ stack: [],
77
+ compatibility: {
78
+ pairs: [],
79
+ totalScore: 0,
80
+ normalizedScore: 0,
81
+ dominant: '',
82
+ tensions: [],
83
+ },
84
+ scaffold: {},
85
+ seed: 1,
86
+ receipt: 'receipt',
87
+ requirements: {
88
+ description: 'anything',
89
+ keywords: [],
90
+ constraints: {},
91
+ complexity: 'moderate',
92
+ },
93
+ };
94
+ }
95
+ function fakeScaffoldResult() {
96
+ return {
97
+ files: [],
98
+ fileSource: 'engine',
99
+ nextSteps: [],
100
+ };
101
+ }
102
+ let tmpCwd;
103
+ (0, vitest_1.beforeEach)(() => {
104
+ tmpCwd = fs.mkdtempSync(path.join(os.tmpdir(), 'charter-wiring-'));
105
+ process.chdir(tmpCwd);
106
+ fs.mkdirSync(path.join(tmpCwd, '.charter'), { recursive: true });
107
+ hoisted.buildFn.mockReset().mockResolvedValue(fakeBuildResult());
108
+ hoisted.scaffoldFn.mockReset().mockResolvedValue(fakeScaffoldResult());
109
+ hoisted.constructorArgs.length = 0;
110
+ mockedResolveApiKey.mockReset();
111
+ vitest_1.vi.spyOn(console, 'log').mockImplementation(() => { });
112
+ vitest_1.vi.spyOn(process.stdout, 'write').mockImplementation(() => true);
113
+ vitest_1.vi.spyOn(process.stderr, 'write').mockImplementation(() => true);
114
+ });
115
+ (0, vitest_1.afterEach)(() => {
116
+ vitest_1.vi.restoreAllMocks();
117
+ process.chdir(os.tmpdir());
118
+ fs.rmSync(tmpCwd, { recursive: true, force: true });
119
+ });
120
+ (0, vitest_1.describe)('architect — auth wiring', () => {
121
+ (0, vitest_1.it)('forwards the env-sourced API key (and custom baseUrl) to EngineClient', async () => {
122
+ mockedResolveApiKey.mockReturnValue({
123
+ apiKey: 'ea_env_wiring',
124
+ source: 'env',
125
+ baseUrl: 'https://engine.example',
126
+ });
127
+ await (0, architect_1.architectCommand)(options, ['a simple project description']);
128
+ (0, vitest_1.expect)(hoisted.constructorArgs).toHaveLength(1);
129
+ (0, vitest_1.expect)(hoisted.constructorArgs[0].apiKey).toBe('ea_env_wiring');
130
+ (0, vitest_1.expect)(hoisted.constructorArgs[0].baseUrl).toBe('https://engine.example');
131
+ });
132
+ (0, vitest_1.it)('passes apiKey=null to EngineClient when resolveApiKey returns null', async () => {
133
+ mockedResolveApiKey.mockReturnValue(null);
134
+ await (0, architect_1.architectCommand)(options, ['unauthenticated fallback']);
135
+ (0, vitest_1.expect)(hoisted.constructorArgs[0].apiKey).toBeNull();
136
+ });
137
+ });
138
+ (0, vitest_1.describe)('run — gateway vs engine routing', () => {
139
+ (0, vitest_1.it)('uses the gateway (scaffold) when the env var provides an API key', async () => {
140
+ mockedResolveApiKey.mockReturnValue({ apiKey: 'ea_env_gateway', source: 'env' });
141
+ await (0, run_1.runCommand)(options, ['a description', '--dry-run']);
142
+ (0, vitest_1.expect)(hoisted.scaffoldFn).toHaveBeenCalledTimes(1);
143
+ (0, vitest_1.expect)(hoisted.buildFn).not.toHaveBeenCalled();
144
+ });
145
+ (0, vitest_1.it)('falls back to engine /build when no API key is resolved', async () => {
146
+ mockedResolveApiKey.mockReturnValue(null);
147
+ await (0, run_1.runCommand)(options, ['a description', '--dry-run']);
148
+ (0, vitest_1.expect)(hoisted.buildFn).toHaveBeenCalledTimes(1);
149
+ (0, vitest_1.expect)(hoisted.scaffoldFn).not.toHaveBeenCalled();
150
+ });
151
+ (0, vitest_1.it)('uses the gateway when login-stored credentials are resolved (parity with env path)', async () => {
152
+ mockedResolveApiKey.mockReturnValue({ apiKey: 'sb_live_stored', source: 'credentials' });
153
+ await (0, run_1.runCommand)(options, ['a description', '--dry-run']);
154
+ (0, vitest_1.expect)(hoisted.scaffoldFn).toHaveBeenCalledTimes(1);
155
+ (0, vitest_1.expect)(hoisted.buildFn).not.toHaveBeenCalled();
156
+ });
157
+ });
158
+ //# sourceMappingURL=auth-wiring.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-wiring.test.js","sourceRoot":"","sources":["../../src/__tests__/auth-wiring.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=bootstrap.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrap.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/bootstrap.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const fs = __importStar(require("node:fs"));
37
+ const os = __importStar(require("node:os"));
38
+ const path = __importStar(require("node:path"));
39
+ const vitest_1 = require("vitest");
40
+ const bootstrap_1 = require("../commands/bootstrap");
41
+ const baseOptions = {
42
+ configPath: '.charter',
43
+ format: 'text',
44
+ ciMode: false,
45
+ yes: false,
46
+ };
47
+ (0, vitest_1.describe)('bootstrapCommand', () => {
48
+ let originalCwd;
49
+ let tempDir;
50
+ let logs;
51
+ (0, vitest_1.beforeEach)(() => {
52
+ originalCwd = process.cwd();
53
+ tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'charter-bootstrap-test-'));
54
+ process.chdir(tempDir);
55
+ logs = [];
56
+ vitest_1.vi.spyOn(console, 'log').mockImplementation((...args) => {
57
+ logs.push(args.map(String).join(' '));
58
+ });
59
+ });
60
+ (0, vitest_1.afterEach)(() => {
61
+ process.chdir(originalCwd);
62
+ fs.rmSync(tempDir, { recursive: true, force: true });
63
+ vitest_1.vi.restoreAllMocks();
64
+ });
65
+ (0, vitest_1.it)('keeps custom ADF files when run with --yes but without --force', async () => {
66
+ fs.mkdirSync('.ai', { recursive: true });
67
+ const customCore = `ADF: 0.1
68
+
69
+ CONTEXT:
70
+ - Custom core instructions
71
+ `;
72
+ fs.writeFileSync(path.join('.ai', 'core.adf'), customCore);
73
+ const exitCode = await (0, bootstrap_1.bootstrapCommand)({ ...baseOptions, yes: true }, ['--yes', '--preset', 'worker', '--skip-install', '--skip-doctor']);
74
+ (0, vitest_1.expect)(exitCode).toBe(0);
75
+ (0, vitest_1.expect)(fs.readFileSync(path.join('.ai', 'core.adf'), 'utf-8')).toBe(customCore);
76
+ (0, vitest_1.expect)(fs.existsSync(path.join('.ai', '.backup'))).toBe(false);
77
+ (0, vitest_1.expect)(fs.existsSync(path.join('.ai', 'manifest.adf'))).toBe(true);
78
+ (0, vitest_1.expect)(fs.existsSync(path.join('.ai', 'state.adf'))).toBe(true);
79
+ const skipWarning = logs.find(l => l.includes('.ai/core.adf has custom content') && l.includes('skipping scaffold overwrite'));
80
+ (0, vitest_1.expect)(skipWarning).toBeDefined();
81
+ (0, vitest_1.expect)(skipWarning).toMatch(/\d+ bytes/);
82
+ });
83
+ (0, vitest_1.it)('backs up and overwrites custom ADF files when run with --force', async () => {
84
+ fs.mkdirSync('.ai', { recursive: true });
85
+ const customCore = `ADF: 0.1
86
+
87
+ CONTEXT:
88
+ - Preserve me in backup
89
+ `;
90
+ const customState = `ADF: 0.1
91
+ STATE:
92
+ CURRENT: Custom state
93
+ `;
94
+ fs.writeFileSync(path.join('.ai', 'core.adf'), customCore);
95
+ fs.writeFileSync(path.join('.ai', 'state.adf'), customState);
96
+ const exitCode = await (0, bootstrap_1.bootstrapCommand)(baseOptions, ['--force', '--preset', 'worker', '--skip-install', '--skip-doctor']);
97
+ (0, vitest_1.expect)(exitCode).toBe(0);
98
+ // Backup files should exist with timestamp suffix
99
+ const backupDir = path.join('.ai', '.backup');
100
+ (0, vitest_1.expect)(fs.existsSync(backupDir)).toBe(true);
101
+ const backupFiles = fs.readdirSync(backupDir);
102
+ const coreBackup = backupFiles.find(f => f.startsWith('core.adf.'));
103
+ const stateBackup = backupFiles.find(f => f.startsWith('state.adf.'));
104
+ (0, vitest_1.expect)(coreBackup).toBeDefined();
105
+ (0, vitest_1.expect)(stateBackup).toBeDefined();
106
+ (0, vitest_1.expect)(fs.readFileSync(path.join(backupDir, coreBackup), 'utf-8')).toBe(customCore);
107
+ (0, vitest_1.expect)(fs.readFileSync(path.join(backupDir, stateBackup), 'utf-8')).toBe(customState);
108
+ // Originals should be overwritten with scaffold content
109
+ (0, vitest_1.expect)(fs.readFileSync(path.join('.ai', 'core.adf'), 'utf-8')).not.toBe(customCore);
110
+ (0, vitest_1.expect)(fs.readFileSync(path.join('.ai', 'state.adf'), 'utf-8')).not.toBe(customState);
111
+ (0, vitest_1.expect)(logs).toContain(' Backed up 2 files to .ai/.backup/');
112
+ });
113
+ (0, vitest_1.it)('detects orphaned .adf modules and auto-registers them in --yes mode', async () => {
114
+ // Pre-create .ai/ with extra modules that won't be in the scaffold manifest
115
+ fs.mkdirSync('.ai', { recursive: true });
116
+ fs.writeFileSync(path.join('.ai', 'agent.adf'), 'ADF: 0.1\n\nCONTEXT:\n - Agent rules\n');
117
+ fs.writeFileSync(path.join('.ai', 'persona.adf'), 'ADF: 0.1\n\nCONTEXT:\n - Persona rules\n');
118
+ const exitCode = await (0, bootstrap_1.bootstrapCommand)({ ...baseOptions, yes: true }, ['--yes', '--preset', 'worker', '--skip-install', '--skip-doctor']);
119
+ (0, vitest_1.expect)(exitCode).toBe(0);
120
+ // Should warn about the two unregistered modules
121
+ const orphanWarning = logs.find(l => l.includes('unregistered .adf module'));
122
+ (0, vitest_1.expect)(orphanWarning).toBeDefined();
123
+ (0, vitest_1.expect)(orphanWarning).toContain('agent.adf');
124
+ (0, vitest_1.expect)(orphanWarning).toContain('persona.adf');
125
+ // In --yes mode, orphans should be auto-registered in manifest
126
+ const registerLog = logs.find(l => l.includes('Registered 2 module(s) as ON_DEMAND'));
127
+ (0, vitest_1.expect)(registerLog).toBeDefined();
128
+ // Verify manifest contains the orphan entries
129
+ const manifest = fs.readFileSync(path.join('.ai', 'manifest.adf'), 'utf-8');
130
+ (0, vitest_1.expect)(manifest).toContain('agent.adf');
131
+ (0, vitest_1.expect)(manifest).toContain('persona.adf');
132
+ });
133
+ });
134
+ //# sourceMappingURL=bootstrap.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrap.test.js","sourceRoot":"","sources":["../../src/__tests__/bootstrap.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=credentials.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/credentials.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const vitest_1 = require("vitest");
37
+ // Isolate loadCredentials from the developer's real ~/.charter/credentials.json
38
+ // by mocking node:fs. Each test configures the fs mock explicitly.
39
+ vitest_1.vi.mock('node:fs', async () => {
40
+ const actual = await vitest_1.vi.importActual('node:fs');
41
+ return {
42
+ ...actual,
43
+ existsSync: vitest_1.vi.fn(() => false),
44
+ readFileSync: vitest_1.vi.fn(),
45
+ };
46
+ });
47
+ const fs = __importStar(require("node:fs"));
48
+ const credentials_1 = require("../credentials");
49
+ const mockedFs = fs;
50
+ function stubStoredCredentials(apiKey, baseUrl) {
51
+ mockedFs.existsSync.mockReturnValue(true);
52
+ mockedFs.readFileSync.mockReturnValue(JSON.stringify({ apiKey, baseUrl }));
53
+ }
54
+ function stubNoStoredCredentials() {
55
+ mockedFs.existsSync.mockReturnValue(false);
56
+ mockedFs.readFileSync.mockImplementation(() => {
57
+ throw new Error('readFileSync should not be called when existsSync=false');
58
+ });
59
+ }
60
+ (0, vitest_1.describe)('resolveApiKey', () => {
61
+ const originalKeyEnv = process.env[credentials_1.API_KEY_ENV_VAR];
62
+ const originalBaseUrlEnv = process.env[credentials_1.API_BASE_URL_ENV_VAR];
63
+ (0, vitest_1.beforeEach)(() => {
64
+ delete process.env[credentials_1.API_KEY_ENV_VAR];
65
+ delete process.env[credentials_1.API_BASE_URL_ENV_VAR];
66
+ mockedFs.existsSync.mockReset();
67
+ mockedFs.readFileSync.mockReset();
68
+ stubNoStoredCredentials();
69
+ });
70
+ (0, vitest_1.afterEach)(() => {
71
+ if (originalKeyEnv === undefined)
72
+ delete process.env[credentials_1.API_KEY_ENV_VAR];
73
+ else
74
+ process.env[credentials_1.API_KEY_ENV_VAR] = originalKeyEnv;
75
+ if (originalBaseUrlEnv === undefined)
76
+ delete process.env[credentials_1.API_BASE_URL_ENV_VAR];
77
+ else
78
+ process.env[credentials_1.API_BASE_URL_ENV_VAR] = originalBaseUrlEnv;
79
+ });
80
+ (0, vitest_1.it)('returns env var when set', () => {
81
+ process.env[credentials_1.API_KEY_ENV_VAR] = 'ea_test_from_env_12345';
82
+ const result = (0, credentials_1.resolveApiKey)();
83
+ (0, vitest_1.expect)(result).not.toBeNull();
84
+ (0, vitest_1.expect)(result.source).toBe('env');
85
+ (0, vitest_1.expect)(result.apiKey).toBe('ea_test_from_env_12345');
86
+ });
87
+ (0, vitest_1.it)('env var wins when both env var and stored credentials are present', () => {
88
+ process.env[credentials_1.API_KEY_ENV_VAR] = 'ea_env_wins';
89
+ stubStoredCredentials('sb_live_should_be_ignored', 'https://stored.example');
90
+ const result = (0, credentials_1.resolveApiKey)();
91
+ (0, vitest_1.expect)(result).not.toBeNull();
92
+ (0, vitest_1.expect)(result.source).toBe('env');
93
+ (0, vitest_1.expect)(result.apiKey).toBe('ea_env_wins');
94
+ });
95
+ (0, vitest_1.it)('trims whitespace from the env var', () => {
96
+ process.env[credentials_1.API_KEY_ENV_VAR] = ' sb_test_abc ';
97
+ const result = (0, credentials_1.resolveApiKey)();
98
+ (0, vitest_1.expect)(result).not.toBeNull();
99
+ (0, vitest_1.expect)(result.source).toBe('env');
100
+ (0, vitest_1.expect)(result.apiKey).toBe('sb_test_abc');
101
+ });
102
+ (0, vitest_1.it)('empty env var falls through to stored credentials', () => {
103
+ process.env[credentials_1.API_KEY_ENV_VAR] = '';
104
+ stubStoredCredentials('sb_live_from_disk');
105
+ const result = (0, credentials_1.resolveApiKey)();
106
+ (0, vitest_1.expect)(result).not.toBeNull();
107
+ (0, vitest_1.expect)(result.source).toBe('credentials');
108
+ (0, vitest_1.expect)(result.apiKey).toBe('sb_live_from_disk');
109
+ });
110
+ (0, vitest_1.it)('whitespace-only env var falls through to stored credentials', () => {
111
+ process.env[credentials_1.API_KEY_ENV_VAR] = ' \t ';
112
+ stubStoredCredentials('sb_live_from_disk');
113
+ const result = (0, credentials_1.resolveApiKey)();
114
+ (0, vitest_1.expect)(result).not.toBeNull();
115
+ (0, vitest_1.expect)(result.source).toBe('credentials');
116
+ (0, vitest_1.expect)(result.apiKey).toBe('sb_live_from_disk');
117
+ });
118
+ (0, vitest_1.it)('returns null when neither env var nor stored credentials are present', () => {
119
+ stubNoStoredCredentials();
120
+ const result = (0, credentials_1.resolveApiKey)();
121
+ (0, vitest_1.expect)(result).toBeNull();
122
+ });
123
+ (0, vitest_1.it)('env-var path adopts STACKBILT_API_BASE_URL when set', () => {
124
+ process.env[credentials_1.API_KEY_ENV_VAR] = 'ea_with_custom_url';
125
+ process.env[credentials_1.API_BASE_URL_ENV_VAR] = 'https://engine.internal.example';
126
+ const result = (0, credentials_1.resolveApiKey)();
127
+ (0, vitest_1.expect)(result).not.toBeNull();
128
+ (0, vitest_1.expect)(result.source).toBe('env');
129
+ (0, vitest_1.expect)(result.baseUrl).toBe('https://engine.internal.example');
130
+ });
131
+ (0, vitest_1.it)('env-var path leaves baseUrl undefined when STACKBILT_API_BASE_URL is unset', () => {
132
+ process.env[credentials_1.API_KEY_ENV_VAR] = 'ea_without_custom_url';
133
+ const result = (0, credentials_1.resolveApiKey)();
134
+ (0, vitest_1.expect)(result).not.toBeNull();
135
+ (0, vitest_1.expect)(result.baseUrl).toBeUndefined();
136
+ });
137
+ (0, vitest_1.it)('credentials path carries baseUrl from the stored file', () => {
138
+ stubStoredCredentials('sb_live_from_disk', 'https://engine.custom.example');
139
+ const result = (0, credentials_1.resolveApiKey)();
140
+ (0, vitest_1.expect)(result).not.toBeNull();
141
+ (0, vitest_1.expect)(result.source).toBe('credentials');
142
+ (0, vitest_1.expect)(result.baseUrl).toBe('https://engine.custom.example');
143
+ });
144
+ });
145
+ //# sourceMappingURL=credentials.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.test.js","sourceRoot":"","sources":["../../src/__tests__/credentials.test.ts"],"names":[],"mappings":"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"}
@@ -170,7 +170,7 @@ function writeHookFixtureRepo(tmp) {
170
170
  // v3 Pre-commit Hook Simulation
171
171
  // ============================================================================
172
172
  (0, vitest_1.describe)('pre-commit hook auto-tidy (integration)', () => {
173
- (0, vitest_1.it)('auto-tidies bloated CLAUDE.md during git commit', { timeout: 30000 }, () => {
173
+ (0, vitest_1.it)('auto-tidies bloated CLAUDE.md during git commit', { timeout: 60000 }, () => {
174
174
  const tmp = makeTempDir('hook-tidy');
175
175
  writeHookFixtureRepo(tmp);
176
176
  // Inject bloat into CLAUDE.md
@@ -197,7 +197,7 @@ function writeHookFixtureRepo(tmp) {
197
197
  (0, vitest_1.expect)(finalContent).not.toContain('## Database Rules');
198
198
  (0, vitest_1.expect)(finalContent).toContain('## Environment');
199
199
  });
200
- (0, vitest_1.it)('passes through cleanly when CLAUDE.md has no bloat', { timeout: 30000 }, () => {
200
+ (0, vitest_1.it)('passes through cleanly when CLAUDE.md has no bloat', { timeout: 60000 }, () => {
201
201
  const tmp = makeTempDir('hook-clean');
202
202
  writeHookFixtureRepo(tmp);
203
203
  // Make a trivial change to CLAUDE.md (add env item, not bloat)
@@ -210,7 +210,7 @@ function writeHookFixtureRepo(tmp) {
210
210
  const finalContent = fs.readFileSync(path.join(tmp, 'CLAUDE.md'), 'utf-8');
211
211
  (0, vitest_1.expect)(finalContent).toContain('DO NOT add rules');
212
212
  });
213
- (0, vitest_1.it)('skips tidy when CHARTER_SKIP_TIDY=1 is set', { timeout: 30000 }, () => {
213
+ (0, vitest_1.it)('skips tidy when CHARTER_SKIP_TIDY=1 is set', { timeout: 60000 }, () => {
214
214
  const tmp = makeTempDir('hook-skip');
215
215
  writeHookFixtureRepo(tmp);
216
216
  // Inject bloat
@@ -237,7 +237,7 @@ function writeHookFixtureRepo(tmp) {
237
237
  const finalContent = fs.readFileSync(path.join(tmp, 'CLAUDE.md'), 'utf-8');
238
238
  (0, vitest_1.expect)(finalContent).toContain('## Architecture');
239
239
  });
240
- (0, vitest_1.it)('re-stages modified .adf modules after tidy', { timeout: 30000 }, () => {
240
+ (0, vitest_1.it)('re-stages modified .adf modules after tidy', { timeout: 60000 }, () => {
241
241
  const tmp = makeTempDir('hook-restage');
242
242
  writeHookFixtureRepo(tmp);
243
243
  // Inject bloat with trigger keywords that route to backend.adf
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=login.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/login.test.ts"],"names":[],"mappings":""}