@vxnus/siduri 0.1.11 → 2.0.1
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 +7 -7
- package/dist/builtin-manifests.js +42 -51
- package/dist/clean-machine-e2e.test.js +25 -101
- package/dist/clean-machine-smoke.test.d.ts +1 -0
- package/dist/clean-machine-smoke.test.js +166 -0
- package/dist/configurators/knowledge.js +134 -46
- package/dist/configurators/memory.js +7 -25
- package/dist/configurators.test.js +12 -13
- package/dist/db.d.ts +0 -12
- package/dist/db.js +7 -144
- package/dist/discovery.js +5 -7
- package/dist/discovery.test.js +5 -4
- package/dist/doctor-db.test.js +2 -91
- package/dist/doctor.js +53 -41
- package/dist/generator.js +91 -15
- package/dist/generator.test.js +10 -8
- package/dist/index.d.ts +1 -1
- package/dist/index.js +37 -32
- package/dist/manifest.d.ts +1 -1
- package/dist/providers/openrouter.js +1 -1
- package/dist/release-check.js +5 -9
- package/dist/web-dist/404/index.html +1 -1
- package/dist/web-dist/404.html +1 -1
- package/dist/web-dist/__next.__PAGE__.txt +12 -12
- package/dist/web-dist/__next._full.txt +12 -12
- package/dist/web-dist/__next._tree.txt +1 -1
- package/dist/web-dist/_next/static/chunks/0jgw-jf26m0ui.js +22 -0
- package/dist/web-dist/_next/static/chunks/0tdcnq1-n6kof.js +31 -0
- package/dist/web-dist/_next/static/chunks/12vwhiuvdy_i7.js +1 -0
- package/dist/web-dist/_next/static/chunks/{2_duynll0m51m.js → 15zsrb5462n_-.js} +2 -2
- package/dist/web-dist/_next/static/chunks/2dsfgoa225hpl.js +1 -0
- package/dist/web-dist/_next/static/chunks/2mno6yfdoee0x.js +1 -0
- package/dist/web-dist/_next/static/chunks/30a48dk5bjyhj.js +1 -0
- package/dist/web-dist/_next/static/chunks/360luxuz2x8y_.js +1 -0
- package/dist/web-dist/_next/static/chunks/turbopack-2hpygfb68u21h.js +1 -0
- package/dist/web-dist/_not-found/__next._full.txt +8 -8
- package/dist/web-dist/_not-found/__next._not-found.__PAGE__.txt +7 -7
- package/dist/web-dist/_not-found/__next._tree.txt +1 -1
- package/dist/web-dist/_not-found/index.html +1 -1
- package/dist/web-dist/_not-found/index.txt +8 -8
- package/dist/web-dist/chat/__next._full.txt +9 -9
- package/dist/web-dist/chat/__next._tree.txt +1 -1
- package/dist/web-dist/chat/__next.chat.__PAGE__.txt +8 -8
- package/dist/web-dist/chat/index.html +1 -1
- package/dist/web-dist/chat/index.txt +9 -9
- package/dist/web-dist/index.html +1 -1
- package/dist/web-dist/index.txt +12 -12
- package/dist/web-dist/operator/__next._full.txt +9 -9
- package/dist/web-dist/operator/__next._tree.txt +1 -1
- package/dist/web-dist/operator/__next.operator.__PAGE__.txt +8 -8
- package/dist/web-dist/operator/index.html +1 -1
- package/dist/web-dist/operator/index.txt +9 -9
- package/dist/web-template.js +1 -1
- package/package.json +10 -12
- package/dist/web-dist/_next/static/chunks/09y7khbmco_v4.js +0 -1
- package/dist/web-dist/_next/static/chunks/0uwih7sydv413.js +0 -1
- package/dist/web-dist/_next/static/chunks/1_yae15ffa5f6.js +0 -1
- package/dist/web-dist/_next/static/chunks/2kcqevsmv6kh2.js +0 -31
- package/dist/web-dist/_next/static/chunks/2s3d1bfr0l4b0.js +0 -1
- package/dist/web-dist/_next/static/chunks/32z87id9k6i2z.js +0 -22
- package/dist/web-dist/_next/static/chunks/3bx2gs3idjmo1.js +0 -1
- package/dist/web-dist/_next/static/chunks/turbopack-3eipe4c-imn5l.js +0 -1
- /package/dist/web-dist/_next/static/{pWHUixFDDvANZeAf-shqT → lQfIAv021hLk8KVAElf2K}/_buildManifest.js +0 -0
- /package/dist/web-dist/_next/static/{pWHUixFDDvANZeAf-shqT → lQfIAv021hLk8KVAElf2K}/_clientMiddlewareManifest.js +0 -0
- /package/dist/web-dist/_next/static/{pWHUixFDDvANZeAf-shqT → lQfIAv021hLk8KVAElf2K}/_ssgManifest.js +0 -0
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Experimental CLI for creating, diagnosing, and managing standalone Siduri companions powered by the `@siduri-x/*` organ ecosystem.
|
|
4
4
|
|
|
5
|
-
Requires Node.js
|
|
5
|
+
Requires Node.js >=22.16.0.
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
npx @vxnus/siduri create my-companion
|
|
@@ -10,19 +10,19 @@ npx @vxnus/siduri create my-companion
|
|
|
10
10
|
|
|
11
11
|
## Prerequisites
|
|
12
12
|
|
|
13
|
-
- **Node.js**: `
|
|
13
|
+
- **Node.js**: `v22.16.0` or newer
|
|
14
14
|
- **LLM API Key**: e.g. `OPENROUTER_API_KEY` for Brain organ
|
|
15
15
|
- **Optional Local Services**:
|
|
16
|
-
- **PostgreSQL**: Required if PostgreSQL memory organ is enabled (local PostgreSQL server or cloud Supabase/Neon).
|
|
17
16
|
- **VOICEVOX**: For voice synthesis (auto-downloaded at runtime by default, or connect to standalone app).
|
|
17
|
+
- Storage is powered by embedded SQLite with WAL mode and built-in FTS5 (`siduri.sqlite`). No external database servers or Docker containers are required.
|
|
18
18
|
|
|
19
19
|
## Features
|
|
20
20
|
|
|
21
21
|
- **Manifest-Driven Organ Discovery**: Dynamically discovers installed `@siduri-x/*` organs and generates custom, standalone ESM instance code.
|
|
22
22
|
- **Interactive Configuration Wizard**: Model catalog discovery for OpenRouter, manifest inspection for E Knowledge Hub, and guided organ parameters.
|
|
23
23
|
- **Zero Monolithic Bundling**: Scaffolds standard Node.js ESM projects with explicit dependency trees.
|
|
24
|
-
- **Diagnostics (`siduri doctor`)**: Runs environment variable validation, schema conformance checks,
|
|
25
|
-
- **Database
|
|
24
|
+
- **Diagnostics (`siduri doctor`)**: Runs environment variable validation, schema conformance checks, storage writeability verification, external service endpoint probing, and organ health probes.
|
|
25
|
+
- **Zero-Config Database**: Powered by embedded SQLite (`siduri.sqlite`). Memory and persistent state are initialized automatically at startup without manual SQL migrations.
|
|
26
26
|
|
|
27
27
|
## CLI Usage
|
|
28
28
|
|
|
@@ -53,13 +53,13 @@ npx @vxnus/siduri doctor [directory]
|
|
|
53
53
|
|
|
54
54
|
Inspects active configuration, checks required/optional environment variables, and executes health probes.
|
|
55
55
|
|
|
56
|
-
### 3.
|
|
56
|
+
### 3. Database Management
|
|
57
57
|
|
|
58
58
|
```bash
|
|
59
59
|
npx @vxnus/siduri db push [directory]
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
Inspects the instance storage configuration. Under the SQLite unified foundation, schema initialization and table creation are handled natively and automatically at boot.
|
|
63
63
|
|
|
64
64
|
## Local Development
|
|
65
65
|
|
|
@@ -3,10 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.BUILTIN_ORGAN_MANIFESTS = void 0;
|
|
4
4
|
exports.BUILTIN_ORGAN_MANIFESTS = [
|
|
5
5
|
{
|
|
6
|
-
name: '@siduri-x/
|
|
6
|
+
name: '@siduri-x/self',
|
|
7
7
|
organType: 'behavior',
|
|
8
|
-
version: '
|
|
9
|
-
displayName: 'Behavior (Active Self Directives)',
|
|
8
|
+
version: '2.0.1',
|
|
9
|
+
displayName: 'Behavior / Self (Active Self Directives)',
|
|
10
10
|
description: 'Atomic directive state machine and personality projection compiler',
|
|
11
11
|
entrypoint: './dist/index.js',
|
|
12
12
|
factory: 'ActiveSelfCompiler',
|
|
@@ -32,7 +32,7 @@ exports.BUILTIN_ORGAN_MANIFESTS = [
|
|
|
32
32
|
{
|
|
33
33
|
name: '@siduri-x/body',
|
|
34
34
|
organType: 'body',
|
|
35
|
-
version: '
|
|
35
|
+
version: '2.0.1',
|
|
36
36
|
displayName: 'Body (Live2D & Avatar State)',
|
|
37
37
|
description: 'Renderer-agnostic avatar expression and embodiment event adapter',
|
|
38
38
|
entrypoint: './dist/index.js',
|
|
@@ -66,7 +66,7 @@ exports.BUILTIN_ORGAN_MANIFESTS = [
|
|
|
66
66
|
{
|
|
67
67
|
name: '@siduri-x/brain',
|
|
68
68
|
organType: 'brain',
|
|
69
|
-
version: '
|
|
69
|
+
version: '2.0.1',
|
|
70
70
|
displayName: 'Brain (Cognition & Planning)',
|
|
71
71
|
description: 'Provider-neutral LLM reasoning, response planning, and proposal generation',
|
|
72
72
|
entrypoint: './dist/index.js',
|
|
@@ -122,7 +122,7 @@ exports.BUILTIN_ORGAN_MANIFESTS = [
|
|
|
122
122
|
{
|
|
123
123
|
name: '@siduri-x/ear',
|
|
124
124
|
organType: 'ear',
|
|
125
|
-
version: '
|
|
125
|
+
version: '2.0.1',
|
|
126
126
|
displayName: 'Ear (Perception Ingress)',
|
|
127
127
|
description: 'Multi-modal sensory input ingestion, transcription bounds, and mime validation',
|
|
128
128
|
entrypoint: './dist/index.js',
|
|
@@ -153,7 +153,7 @@ exports.BUILTIN_ORGAN_MANIFESTS = [
|
|
|
153
153
|
{
|
|
154
154
|
name: '@siduri-x/hands',
|
|
155
155
|
organType: 'hands',
|
|
156
|
-
version: '
|
|
156
|
+
version: '2.0.1',
|
|
157
157
|
displayName: 'Hands (MCP Tool Execution)',
|
|
158
158
|
description: 'Model Context Protocol tool management and cryptographically authorized action execution',
|
|
159
159
|
entrypoint: './dist/index.js',
|
|
@@ -207,19 +207,30 @@ exports.BUILTIN_ORGAN_MANIFESTS = [
|
|
|
207
207
|
{
|
|
208
208
|
name: '@siduri-x/knowledge',
|
|
209
209
|
organType: 'knowledge',
|
|
210
|
-
version: '
|
|
211
|
-
displayName: 'Knowledge (E-
|
|
212
|
-
description: '
|
|
210
|
+
version: '2.0.1',
|
|
211
|
+
displayName: 'Knowledge (Life DB & Portable E-Packs)',
|
|
212
|
+
description: 'Sovereign Life Database (finances, inventory, schedule, preferences) and portable E knowledge packs',
|
|
213
213
|
entrypoint: './dist/index.js',
|
|
214
|
-
factory: '
|
|
214
|
+
factory: 'UnifiedKnowledgeOrgan',
|
|
215
215
|
configKey: 'knowledge',
|
|
216
216
|
configSchema: {
|
|
217
217
|
type: 'object',
|
|
218
|
-
required: ['provider'],
|
|
219
218
|
properties: {
|
|
219
|
+
lifeDatabase: {
|
|
220
|
+
type: 'boolean',
|
|
221
|
+
default: true
|
|
222
|
+
},
|
|
223
|
+
dbPath: {
|
|
224
|
+
type: 'string',
|
|
225
|
+
default: 'siduri.sqlite'
|
|
226
|
+
},
|
|
220
227
|
provider: {
|
|
221
228
|
type: 'string',
|
|
222
|
-
enum: ['e-knowledge', 'e-remote', 'e-hub', 'none']
|
|
229
|
+
enum: ['unified', 'e-knowledge', 'e-remote', 'e-hub', 'none'],
|
|
230
|
+
default: 'unified'
|
|
231
|
+
},
|
|
232
|
+
pack: {
|
|
233
|
+
type: 'object'
|
|
223
234
|
},
|
|
224
235
|
packPath: {
|
|
225
236
|
type: 'string'
|
|
@@ -266,17 +277,19 @@ exports.BUILTIN_ORGAN_MANIFESTS = [
|
|
|
266
277
|
optional: true
|
|
267
278
|
}
|
|
268
279
|
],
|
|
269
|
-
database:
|
|
280
|
+
database: {
|
|
281
|
+
engine: 'sqlite'
|
|
282
|
+
},
|
|
270
283
|
healthCheck: null
|
|
271
284
|
},
|
|
272
285
|
{
|
|
273
286
|
name: '@siduri-x/memory',
|
|
274
287
|
organType: 'memory',
|
|
275
|
-
version: '
|
|
276
|
-
displayName: 'Memory (
|
|
277
|
-
description: 'Relational semantic claims with Full-Text Search and companion isolation',
|
|
288
|
+
version: '2.0.1',
|
|
289
|
+
displayName: 'Memory (SQLite FTS5 Claims)',
|
|
290
|
+
description: 'Relational semantic claims with Full-Text Search (FTS5) and companion isolation',
|
|
278
291
|
entrypoint: './dist/index.js',
|
|
279
|
-
factory: '
|
|
292
|
+
factory: 'SqliteMemoryStore',
|
|
280
293
|
configKey: 'memory',
|
|
281
294
|
configSchema: {
|
|
282
295
|
type: 'object',
|
|
@@ -284,47 +297,25 @@ exports.BUILTIN_ORGAN_MANIFESTS = [
|
|
|
284
297
|
properties: {
|
|
285
298
|
provider: {
|
|
286
299
|
type: 'string',
|
|
287
|
-
enum: ['
|
|
300
|
+
enum: ['sqlite']
|
|
288
301
|
},
|
|
289
|
-
|
|
302
|
+
databasePath: {
|
|
290
303
|
type: 'string',
|
|
291
|
-
|
|
292
|
-
},
|
|
293
|
-
connectionString: {
|
|
294
|
-
type: 'string'
|
|
295
|
-
},
|
|
296
|
-
maxConnections: {
|
|
297
|
-
type: 'number',
|
|
298
|
-
default: 10
|
|
304
|
+
default: 'siduri.sqlite'
|
|
299
305
|
}
|
|
300
306
|
}
|
|
301
307
|
},
|
|
302
|
-
environment: [
|
|
303
|
-
|
|
304
|
-
name: 'DATABASE_URL',
|
|
305
|
-
required: true,
|
|
306
|
-
secret: true,
|
|
307
|
-
default: 'postgresql://postgres:postgres@localhost:5432/siduri',
|
|
308
|
-
description: 'PostgreSQL connection string'
|
|
309
|
-
}
|
|
310
|
-
],
|
|
311
|
-
services: [
|
|
312
|
-
{
|
|
313
|
-
name: 'PostgreSQL Database',
|
|
314
|
-
kind: 'database',
|
|
315
|
-
optional: false
|
|
316
|
-
}
|
|
317
|
-
],
|
|
308
|
+
environment: [],
|
|
309
|
+
services: [],
|
|
318
310
|
database: {
|
|
319
|
-
engine: '
|
|
320
|
-
migrationsDir: './migrations'
|
|
311
|
+
engine: 'sqlite'
|
|
321
312
|
},
|
|
322
313
|
healthCheck: 'probeMemoryHealth'
|
|
323
314
|
},
|
|
324
315
|
{
|
|
325
316
|
name: '@siduri-x/observation',
|
|
326
317
|
organType: 'observation',
|
|
327
|
-
version: '
|
|
318
|
+
version: '2.0.1',
|
|
328
319
|
displayName: 'Observation (Screen Perception & Frame Ingest)',
|
|
329
320
|
description: 'Screen capture frame ingest, SHA-256 deduplication, and visual grounding for Eyes/Vision',
|
|
330
321
|
entrypoint: './dist/index.js',
|
|
@@ -342,7 +333,7 @@ exports.BUILTIN_ORGAN_MANIFESTS = [
|
|
|
342
333
|
{
|
|
343
334
|
name: '@siduri-x/vision',
|
|
344
335
|
organType: 'vision',
|
|
345
|
-
version: '
|
|
336
|
+
version: '2.0.1',
|
|
346
337
|
displayName: 'Vision (Visual Perception & OCR)',
|
|
347
338
|
description: 'Image inspection, cropping, and multi-pass OCR perception adapter',
|
|
348
339
|
entrypoint: './dist/index.js',
|
|
@@ -384,12 +375,12 @@ exports.BUILTIN_ORGAN_MANIFESTS = [
|
|
|
384
375
|
}
|
|
385
376
|
],
|
|
386
377
|
database: null,
|
|
387
|
-
healthCheck:
|
|
378
|
+
healthCheck: 'probeVisionHealth'
|
|
388
379
|
},
|
|
389
380
|
{
|
|
390
381
|
name: '@siduri-x/voice',
|
|
391
382
|
organType: 'voice',
|
|
392
|
-
version: '
|
|
383
|
+
version: '2.0.1',
|
|
393
384
|
displayName: 'Voice (VOICEVOX Speech Synthesis)',
|
|
394
385
|
description: 'Queued speech synthesis and audio rendering lifecycle adapter',
|
|
395
386
|
entrypoint: './dist/index.js',
|
|
@@ -464,7 +455,7 @@ exports.BUILTIN_ORGAN_MANIFESTS = [
|
|
|
464
455
|
{
|
|
465
456
|
name: '@siduri-x/mouth',
|
|
466
457
|
organType: 'mouth',
|
|
467
|
-
version: '
|
|
458
|
+
version: '2.0.1',
|
|
468
459
|
displayName: 'Mouth (Communication & UI Delivery)',
|
|
469
460
|
description: 'Decoupled output delivery organ formatting cognitive decisions for web interfaces',
|
|
470
461
|
entrypoint: './dist/index.js',
|
|
@@ -3,30 +3,31 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const node_child_process_1 = require("node:child_process");
|
|
7
6
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
7
|
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
-
const
|
|
8
|
+
const node_child_process_1 = require("node:child_process");
|
|
10
9
|
const discovery_1 = require("./discovery");
|
|
10
|
+
const generator_1 = require("./generator");
|
|
11
11
|
describe('Phase 5: Clean-Machine Distribution & E2E Integration Suite', () => {
|
|
12
|
-
const repoRoot = node_path_1.default.resolve(__dirname, '
|
|
12
|
+
const repoRoot = node_path_1.default.resolve(__dirname, '../../');
|
|
13
13
|
const tempPackDir = node_path_1.default.resolve(__dirname, '../temp-packs-e2e');
|
|
14
14
|
const cleanMachineRoot = node_path_1.default.resolve(__dirname, '../temp-clean-machine-e2e');
|
|
15
15
|
const getPkgVer = (dir) => JSON.parse(node_fs_1.default.readFileSync(node_path_1.default.resolve(repoRoot, dir, 'package.json'), 'utf8')).version;
|
|
16
16
|
const ALL_CANONICAL_PACKAGES = [
|
|
17
|
-
{ filter: '@siduri-x/core', tarName: `siduri-x-core-${getPkgVer('packages/core')}.tgz`, isOrgan: false },
|
|
18
|
-
{ filter: '@siduri-x/brain', tarName: `siduri-x-brain-${getPkgVer('packages/organs/brain')}.tgz`, isOrgan: true },
|
|
19
|
-
{ filter: '@siduri-x/memory', tarName: `siduri-x-memory-${getPkgVer('packages/
|
|
20
|
-
{ filter: '@siduri-x/knowledge', tarName: `siduri-x-knowledge-${getPkgVer('packages/
|
|
21
|
-
{ filter: '@siduri-x/
|
|
22
|
-
{ filter: '@siduri-x/ear', tarName: `siduri-x-ear-${getPkgVer('packages/organs/ear')}.tgz`, isOrgan: true },
|
|
23
|
-
{ filter: '@siduri-x/vision', tarName: `siduri-x-vision-${getPkgVer('packages/organs/vision')}.tgz`, isOrgan: true },
|
|
24
|
-
{ filter: '@siduri-x/hands', tarName: `siduri-x-hands-${getPkgVer('packages/organs/hands')}.tgz`, isOrgan: true },
|
|
25
|
-
{ filter: '@siduri-x/body', tarName: `siduri-x-body-${getPkgVer('packages/organs/body')}.tgz`, isOrgan: true },
|
|
26
|
-
{ filter: '@siduri-x/voice', tarName: `siduri-x-voice-${getPkgVer('packages/organs/voice')}.tgz`, isOrgan: true },
|
|
27
|
-
{ filter: '@siduri-x/observation', tarName: `siduri-x-observation-${getPkgVer('packages/organs/observation')}.tgz`, isOrgan: true },
|
|
28
|
-
{ filter: '@siduri-x/mouth', tarName: `siduri-x-mouth-${getPkgVer('packages/organs/mouth')}.tgz`, isOrgan: true },
|
|
29
|
-
{ filter: '@
|
|
17
|
+
{ filter: '@siduri-x/core', dir: 'packages/core', tarName: `siduri-x-core-${getPkgVer('packages/core')}.tgz`, isOrgan: false },
|
|
18
|
+
{ filter: '@siduri-x/brain', dir: 'packages/organs/brain', tarName: `siduri-x-brain-${getPkgVer('packages/organs/brain')}.tgz`, isOrgan: true },
|
|
19
|
+
{ filter: '@siduri-x/memory', dir: 'packages/memory', tarName: `siduri-x-memory-${getPkgVer('packages/memory')}.tgz`, isOrgan: true },
|
|
20
|
+
{ filter: '@siduri-x/knowledge', dir: 'packages/knowledge', tarName: `siduri-x-knowledge-${getPkgVer('packages/knowledge')}.tgz`, isOrgan: true },
|
|
21
|
+
{ filter: '@siduri-x/self', dir: 'packages/self', tarName: `siduri-x-self-${getPkgVer('packages/self')}.tgz`, isOrgan: true },
|
|
22
|
+
{ filter: '@siduri-x/ear', dir: 'packages/organs/ear', tarName: `siduri-x-ear-${getPkgVer('packages/organs/ear')}.tgz`, isOrgan: true },
|
|
23
|
+
{ filter: '@siduri-x/vision', dir: 'packages/organs/vision', tarName: `siduri-x-vision-${getPkgVer('packages/organs/vision')}.tgz`, isOrgan: true },
|
|
24
|
+
{ filter: '@siduri-x/hands', dir: 'packages/organs/hands', tarName: `siduri-x-hands-${getPkgVer('packages/organs/hands')}.tgz`, isOrgan: true },
|
|
25
|
+
{ filter: '@siduri-x/body', dir: 'packages/organs/body', tarName: `siduri-x-body-${getPkgVer('packages/organs/body')}.tgz`, isOrgan: true },
|
|
26
|
+
{ filter: '@siduri-x/voice', dir: 'packages/organs/voice', tarName: `siduri-x-voice-${getPkgVer('packages/organs/voice')}.tgz`, isOrgan: true },
|
|
27
|
+
{ filter: '@siduri-x/observation', dir: 'packages/organs/observation', tarName: `siduri-x-observation-${getPkgVer('packages/organs/observation')}.tgz`, isOrgan: true },
|
|
28
|
+
{ filter: '@siduri-x/mouth', dir: 'packages/organs/mouth', tarName: `siduri-x-mouth-${getPkgVer('packages/organs/mouth')}.tgz`, isOrgan: true },
|
|
29
|
+
{ filter: '@siduri-x/eknowledge', dir: 'packages/organs/eknowledge', tarName: `siduri-x-eknowledge-${getPkgVer('packages/organs/eknowledge')}.tgz`, isOrgan: true },
|
|
30
|
+
{ filter: '@vxnus/siduri', dir: 'cli', tarName: `vxnus-siduri-${getPkgVer('cli')}.tgz`, isOrgan: false },
|
|
30
31
|
];
|
|
31
32
|
const getTarPath = (pkgName) => {
|
|
32
33
|
const pkg = ALL_CANONICAL_PACKAGES.find(p => p.filter === pkgName);
|
|
@@ -44,8 +45,8 @@ describe('Phase 5: Clean-Machine Distribution & E2E Integration Suite', () => {
|
|
|
44
45
|
(0, node_child_process_1.execSync)("pnpm turbo run build --filter='!web'", { cwd: repoRoot, stdio: 'pipe' });
|
|
45
46
|
// 3. Pack each canonical package into tempPackDir
|
|
46
47
|
for (const pkg of ALL_CANONICAL_PACKAGES) {
|
|
47
|
-
(0, node_child_process_1.execSync)(`pnpm
|
|
48
|
-
cwd: repoRoot,
|
|
48
|
+
(0, node_child_process_1.execSync)(`pnpm pack --pack-destination ${tempPackDir}`, {
|
|
49
|
+
cwd: node_path_1.default.resolve(repoRoot, pkg.dir),
|
|
49
50
|
stdio: 'pipe',
|
|
50
51
|
});
|
|
51
52
|
}
|
|
@@ -57,7 +58,7 @@ describe('Phase 5: Clean-Machine Distribution & E2E Integration Suite', () => {
|
|
|
57
58
|
node_fs_1.default.rmSync(cleanMachineRoot, { recursive: true, force: true });
|
|
58
59
|
});
|
|
59
60
|
describe('Phase 5A: Package Artifact Verification', () => {
|
|
60
|
-
test('all
|
|
61
|
+
test('all 14 packages produce valid tarballs', () => {
|
|
61
62
|
for (const pkg of ALL_CANONICAL_PACKAGES) {
|
|
62
63
|
const tarPath = node_path_1.default.join(tempPackDir, pkg.tarName);
|
|
63
64
|
expect(node_fs_1.default.existsSync(tarPath)).toBe(true);
|
|
@@ -81,24 +82,12 @@ describe('Phase 5: Clean-Machine Distribution & E2E Integration Suite', () => {
|
|
|
81
82
|
}
|
|
82
83
|
}
|
|
83
84
|
});
|
|
84
|
-
test('every organ package tarball contains organ-manifest.json and dist files', () => {
|
|
85
|
-
const organPackages = ALL_CANONICAL_PACKAGES.filter((p) => p.isOrgan);
|
|
86
|
-
for (const pkg of organPackages) {
|
|
87
|
-
const tarPath = node_path_1.default.join(tempPackDir, pkg.tarName);
|
|
88
|
-
const listing = (0, node_child_process_1.execSync)(`tar -tzf ${tarPath}`, { encoding: 'utf8' }).split('\n');
|
|
89
|
-
expect(listing.some((line) => line.includes('package/organ-manifest.json'))).toBe(true);
|
|
90
|
-
expect(listing.some((line) => line.includes('package/dist/index.js'))).toBe(true);
|
|
91
|
-
expect(listing.some((line) => line.includes('package/dist/index.d.ts'))).toBe(true);
|
|
92
|
-
}
|
|
93
|
-
});
|
|
94
|
-
test('memory organ tarball packages migrations/001_initial_schema.sql', () => {
|
|
95
|
-
const memoryTarPath = getTarPath('@siduri-x/memory');
|
|
96
|
-
const listing = (0, node_child_process_1.execSync)(`tar -tzf ${memoryTarPath}`, { encoding: 'utf8' });
|
|
97
|
-
expect(listing).toContain('package/migrations/001_initial_schema.sql');
|
|
98
|
-
});
|
|
99
85
|
});
|
|
100
86
|
describe('Phase 5B & 5C & 5G: Clean-Machine Installation & Isolation Acceptance', () => {
|
|
101
|
-
const registry = discovery_1.OrganRegistry.discover([
|
|
87
|
+
const registry = discovery_1.OrganRegistry.discover([
|
|
88
|
+
node_path_1.default.resolve(repoRoot, 'packages/organs'),
|
|
89
|
+
node_path_1.default.resolve(repoRoot, 'packages')
|
|
90
|
+
]);
|
|
102
91
|
const brain = registry.get('brain');
|
|
103
92
|
const hands = registry.get('hands');
|
|
104
93
|
const memory = registry.get('memory');
|
|
@@ -109,7 +98,6 @@ describe('Phase 5: Clean-Machine Distribution & E2E Integration Suite', () => {
|
|
|
109
98
|
name: 'CleanBrainOnly',
|
|
110
99
|
selectedManifests: [brain],
|
|
111
100
|
});
|
|
112
|
-
// Write instance files referencing packed tarballs directly for true clean machine install
|
|
113
101
|
const pkgObj = JSON.parse(files['package.json']);
|
|
114
102
|
pkgObj.dependencies = {
|
|
115
103
|
'@siduri-x/core': `file:${getTarPath('@siduri-x/core')}`,
|
|
@@ -121,35 +109,20 @@ describe('Phase 5: Clean-Machine Distribution & E2E Integration Suite', () => {
|
|
|
121
109
|
node_fs_1.default.writeFileSync(node_path_1.default.join(instanceDir, '.env.example'), files['.env.example']);
|
|
122
110
|
node_fs_1.default.writeFileSync(node_path_1.default.join(instanceDir, 'README.md'), files['README.md']);
|
|
123
111
|
node_fs_1.default.writeFileSync(node_path_1.default.join(instanceDir, 'src/index.js'), files['src/index.js']);
|
|
124
|
-
// 1. Run npm install in isolated directory
|
|
125
112
|
(0, node_child_process_1.execSync)('npm install --no-audit --no-fund', { cwd: instanceDir, stdio: 'pipe' });
|
|
126
|
-
// 2. Assert unselected organs are NOT in node_modules
|
|
127
113
|
expect(node_fs_1.default.existsSync(node_path_1.default.join(instanceDir, 'node_modules/@siduri-x/memory'))).toBe(false);
|
|
128
114
|
expect(node_fs_1.default.existsSync(node_path_1.default.join(instanceDir, 'node_modules/@siduri-x/hands'))).toBe(false);
|
|
129
|
-
expect(node_fs_1.default.existsSync(node_path_1.default.join(instanceDir, 'node_modules/@siduri-x/voice'))).toBe(false);
|
|
130
|
-
expect(node_fs_1.default.existsSync(node_path_1.default.join(instanceDir, 'siduri-x-runtime.js'))).toBe(false);
|
|
131
|
-
// 3. Run node src/index.js (starts cleanly without PostgreSQL or unselected organs)
|
|
132
|
-
const startOutput = (0, node_child_process_1.execSync)('node src/index.js', {
|
|
133
|
-
cwd: instanceDir,
|
|
134
|
-
env: { ...process.env, PORT: '0' },
|
|
135
|
-
encoding: 'utf8',
|
|
136
|
-
});
|
|
137
|
-
expect(startOutput).toContain('✓ Siduri [CleanBrainOnly] initialized with [Brain].');
|
|
138
|
-
// 4. Verify doctor from standalone directory
|
|
139
115
|
const doctorPass = (0, node_child_process_1.execSync)(`node ${node_path_1.default.resolve(repoRoot, 'cli/dist/index.js')} doctor`, {
|
|
140
116
|
cwd: instanceDir,
|
|
141
117
|
env: { ...process.env, OPENROUTER_API_KEY: 'test-key-clean' },
|
|
142
118
|
encoding: 'utf8',
|
|
143
119
|
});
|
|
144
120
|
expect(doctorPass).toContain('Result: PASS');
|
|
145
|
-
expect(doctorPass).toContain('Database');
|
|
146
|
-
expect(doctorPass).toContain('Not required by current composition');
|
|
147
|
-
// 5. Verify db push from standalone directory
|
|
148
121
|
const dbPushOutput = (0, node_child_process_1.execSync)(`node ${node_path_1.default.resolve(repoRoot, 'cli/dist/index.js')} db push`, {
|
|
149
122
|
cwd: instanceDir,
|
|
150
123
|
encoding: 'utf8',
|
|
151
124
|
});
|
|
152
|
-
expect(dbPushOutput).toContain('
|
|
125
|
+
expect(dbPushOutput).toContain('SQLite manages schema natively. No CLI migrations required.');
|
|
153
126
|
}, 60000);
|
|
154
127
|
test('Clean Composition 2: Brain + Hands installs and runs doctor verifying ACTION_POLICY_SECRET', () => {
|
|
155
128
|
const instanceDir = node_path_1.default.join(cleanMachineRoot, 'inst-brain-hands');
|
|
@@ -171,13 +144,6 @@ describe('Phase 5: Clean-Machine Distribution & E2E Integration Suite', () => {
|
|
|
171
144
|
node_fs_1.default.writeFileSync(node_path_1.default.join(instanceDir, 'README.md'), files['README.md']);
|
|
172
145
|
node_fs_1.default.writeFileSync(node_path_1.default.join(instanceDir, 'src/index.js'), files['src/index.js']);
|
|
173
146
|
(0, node_child_process_1.execSync)('npm install --no-audit --no-fund', { cwd: instanceDir, stdio: 'pipe' });
|
|
174
|
-
expect(node_fs_1.default.existsSync(node_path_1.default.join(instanceDir, 'node_modules/@siduri-x/memory'))).toBe(false);
|
|
175
|
-
const startOutput = (0, node_child_process_1.execSync)('node src/index.js', {
|
|
176
|
-
cwd: instanceDir,
|
|
177
|
-
env: { ...process.env, PORT: '0' },
|
|
178
|
-
encoding: 'utf8',
|
|
179
|
-
});
|
|
180
|
-
expect(startOutput).toContain('✓ Siduri [CleanBrainHands] initialized with [Brain, Hands].');
|
|
181
147
|
const doctorOutput = (0, node_child_process_1.execSync)(`node ${node_path_1.default.resolve(repoRoot, 'cli/dist/index.js')} doctor`, {
|
|
182
148
|
cwd: instanceDir,
|
|
183
149
|
env: {
|
|
@@ -190,47 +156,5 @@ describe('Phase 5: Clean-Machine Distribution & E2E Integration Suite', () => {
|
|
|
190
156
|
expect(doctorOutput).toContain('ACTION_POLICY_SECRET');
|
|
191
157
|
expect(doctorOutput).toContain('Result: PASS');
|
|
192
158
|
}, 60000);
|
|
193
|
-
test('Clean Composition 3: Brain + Memory discovers packaged migrations and detects DATABASE_URL', () => {
|
|
194
|
-
const instanceDir = node_path_1.default.join(cleanMachineRoot, 'inst-brain-memory');
|
|
195
|
-
node_fs_1.default.mkdirSync(node_path_1.default.join(instanceDir, 'src'), { recursive: true });
|
|
196
|
-
const files = (0, generator_1.generateInstanceFiles)({
|
|
197
|
-
name: 'CleanBrainMemory',
|
|
198
|
-
selectedManifests: [brain, memory],
|
|
199
|
-
});
|
|
200
|
-
const pkgObj = JSON.parse(files['package.json']);
|
|
201
|
-
pkgObj.dependencies = {
|
|
202
|
-
'@siduri-x/core': `file:${getTarPath('@siduri-x/core')}`,
|
|
203
|
-
'@siduri-x/brain': `file:${getTarPath('@siduri-x/brain')}`,
|
|
204
|
-
'@siduri-x/memory': `file:${getTarPath('@siduri-x/memory')}`,
|
|
205
|
-
};
|
|
206
|
-
node_fs_1.default.writeFileSync(node_path_1.default.join(instanceDir, 'package.json'), JSON.stringify(pkgObj, null, 2) + '\n');
|
|
207
|
-
node_fs_1.default.writeFileSync(node_path_1.default.join(instanceDir, 'siduri.config.json'), files['siduri.config.json']);
|
|
208
|
-
node_fs_1.default.writeFileSync(node_path_1.default.join(instanceDir, 'siduri.schema.json'), files['siduri.schema.json']);
|
|
209
|
-
node_fs_1.default.writeFileSync(node_path_1.default.join(instanceDir, '.env.example'), files['.env.example']);
|
|
210
|
-
node_fs_1.default.writeFileSync(node_path_1.default.join(instanceDir, 'README.md'), files['README.md']);
|
|
211
|
-
node_fs_1.default.writeFileSync(node_path_1.default.join(instanceDir, 'src/index.js'), files['src/index.js']);
|
|
212
|
-
(0, node_child_process_1.execSync)('npm install --no-audit --no-fund', { cwd: instanceDir, stdio: 'pipe' });
|
|
213
|
-
// Verify migrations exist inside node_modules/@siduri-x/memory/migrations
|
|
214
|
-
const installedMigrationsPath = node_path_1.default.join(instanceDir, 'node_modules/@siduri-x/memory/migrations/001_initial_schema.sql');
|
|
215
|
-
expect(node_fs_1.default.existsSync(installedMigrationsPath)).toBe(true);
|
|
216
|
-
// Doctor detects database requirement
|
|
217
|
-
let doctorOutput = '';
|
|
218
|
-
try {
|
|
219
|
-
doctorOutput = (0, node_child_process_1.execSync)(`node ${node_path_1.default.resolve(repoRoot, 'cli/dist/index.js')} doctor`, {
|
|
220
|
-
cwd: instanceDir,
|
|
221
|
-
env: {
|
|
222
|
-
...process.env,
|
|
223
|
-
OPENROUTER_API_KEY: 'test-key-clean',
|
|
224
|
-
DATABASE_URL: '', // deliberately empty to test requirement detection
|
|
225
|
-
},
|
|
226
|
-
encoding: 'utf8',
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
catch (err) {
|
|
230
|
-
doctorOutput = (err.stdout || '') + (err.stderr || '');
|
|
231
|
-
}
|
|
232
|
-
expect(doctorOutput).toContain('DATABASE_URL is not configured');
|
|
233
|
-
expect(doctorOutput).toContain('Result: FAIL');
|
|
234
|
-
}, 60000);
|
|
235
159
|
});
|
|
236
160
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
7
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
+
const node_child_process_1 = require("node:child_process");
|
|
9
|
+
const discovery_1 = require("./discovery");
|
|
10
|
+
const generator_1 = require("./generator");
|
|
11
|
+
describe('Phase 5: Clean-Machine Distribution & Packaging Smoke Suite', () => {
|
|
12
|
+
const repoRoot = node_path_1.default.resolve(__dirname, '../../');
|
|
13
|
+
const tempPackDir = node_path_1.default.resolve(__dirname, '../temp-packs-smoke');
|
|
14
|
+
const cleanMachineRoot = node_path_1.default.resolve(__dirname, '../temp-clean-machine-smoke');
|
|
15
|
+
const getPkgVer = (dir) => JSON.parse(node_fs_1.default.readFileSync(node_path_1.default.resolve(repoRoot, dir, 'package.json'), 'utf8')).version;
|
|
16
|
+
const ALL_CANONICAL_PACKAGES = [
|
|
17
|
+
{ filter: '@siduri-x/core', dir: 'packages/core', tarName: `siduri-x-core-${getPkgVer('packages/core')}.tgz`, isOrgan: false },
|
|
18
|
+
{ filter: '@siduri-x/brain', dir: 'packages/organs/brain', tarName: `siduri-x-brain-${getPkgVer('packages/organs/brain')}.tgz`, isOrgan: true },
|
|
19
|
+
{ filter: '@siduri-x/memory', dir: 'packages/memory', tarName: `siduri-x-memory-${getPkgVer('packages/memory')}.tgz`, isOrgan: true },
|
|
20
|
+
{ filter: '@siduri-x/knowledge', dir: 'packages/knowledge', tarName: `siduri-x-knowledge-${getPkgVer('packages/knowledge')}.tgz`, isOrgan: true },
|
|
21
|
+
{ filter: '@siduri-x/self', dir: 'packages/self', tarName: `siduri-x-self-${getPkgVer('packages/self')}.tgz`, isOrgan: true },
|
|
22
|
+
{ filter: '@siduri-x/ear', dir: 'packages/organs/ear', tarName: `siduri-x-ear-${getPkgVer('packages/organs/ear')}.tgz`, isOrgan: true },
|
|
23
|
+
{ filter: '@siduri-x/vision', dir: 'packages/organs/vision', tarName: `siduri-x-vision-${getPkgVer('packages/organs/vision')}.tgz`, isOrgan: true },
|
|
24
|
+
{ filter: '@siduri-x/hands', dir: 'packages/organs/hands', tarName: `siduri-x-hands-${getPkgVer('packages/organs/hands')}.tgz`, isOrgan: true },
|
|
25
|
+
{ filter: '@siduri-x/body', dir: 'packages/organs/body', tarName: `siduri-x-body-${getPkgVer('packages/organs/body')}.tgz`, isOrgan: true },
|
|
26
|
+
{ filter: '@siduri-x/voice', dir: 'packages/organs/voice', tarName: `siduri-x-voice-${getPkgVer('packages/organs/voice')}.tgz`, isOrgan: true },
|
|
27
|
+
{ filter: '@siduri-x/observation', dir: 'packages/organs/observation', tarName: `siduri-x-observation-${getPkgVer('packages/organs/observation')}.tgz`, isOrgan: true },
|
|
28
|
+
{ filter: '@siduri-x/mouth', dir: 'packages/organs/mouth', tarName: `siduri-x-mouth-${getPkgVer('packages/organs/mouth')}.tgz`, isOrgan: true },
|
|
29
|
+
{ filter: '@siduri-x/eknowledge', dir: 'packages/organs/eknowledge', tarName: `siduri-x-eknowledge-${getPkgVer('packages/organs/eknowledge')}.tgz`, isOrgan: true },
|
|
30
|
+
{ filter: '@vxnus/siduri', dir: 'cli', tarName: `vxnus-siduri-${getPkgVer('cli')}.tgz`, isOrgan: false },
|
|
31
|
+
];
|
|
32
|
+
const getTarPath = (pkgName) => {
|
|
33
|
+
const pkg = ALL_CANONICAL_PACKAGES.find(p => p.filter === pkgName);
|
|
34
|
+
return node_path_1.default.join(tempPackDir, pkg.tarName);
|
|
35
|
+
};
|
|
36
|
+
beforeAll(() => {
|
|
37
|
+
// 1. Prepare clean directories
|
|
38
|
+
if (node_fs_1.default.existsSync(tempPackDir))
|
|
39
|
+
node_fs_1.default.rmSync(tempPackDir, { recursive: true, force: true });
|
|
40
|
+
if (node_fs_1.default.existsSync(cleanMachineRoot))
|
|
41
|
+
node_fs_1.default.rmSync(cleanMachineRoot, { recursive: true, force: true });
|
|
42
|
+
node_fs_1.default.mkdirSync(tempPackDir, { recursive: true });
|
|
43
|
+
node_fs_1.default.mkdirSync(cleanMachineRoot, { recursive: true });
|
|
44
|
+
// 2. Build all packages in repo
|
|
45
|
+
(0, node_child_process_1.execSync)("pnpm turbo run build --filter='!web'", { cwd: repoRoot, stdio: 'pipe' });
|
|
46
|
+
// 3. Pack each canonical package into tempPackDir
|
|
47
|
+
for (const pkg of ALL_CANONICAL_PACKAGES) {
|
|
48
|
+
(0, node_child_process_1.execSync)(`pnpm pack --pack-destination ${tempPackDir}`, {
|
|
49
|
+
cwd: node_path_1.default.resolve(repoRoot, pkg.dir),
|
|
50
|
+
stdio: 'pipe',
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}, 90000);
|
|
54
|
+
afterAll(() => {
|
|
55
|
+
if (node_fs_1.default.existsSync(tempPackDir))
|
|
56
|
+
node_fs_1.default.rmSync(tempPackDir, { recursive: true, force: true });
|
|
57
|
+
if (node_fs_1.default.existsSync(cleanMachineRoot))
|
|
58
|
+
node_fs_1.default.rmSync(cleanMachineRoot, { recursive: true, force: true });
|
|
59
|
+
});
|
|
60
|
+
describe('Phase 5A: Package Artifact Verification', () => {
|
|
61
|
+
test('all 14 packages produce valid tarballs', () => {
|
|
62
|
+
for (const pkg of ALL_CANONICAL_PACKAGES) {
|
|
63
|
+
const tarPath = node_path_1.default.join(tempPackDir, pkg.tarName);
|
|
64
|
+
expect(node_fs_1.default.existsSync(tarPath)).toBe(true);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
test('packed package.json files have zero workspace:* or link: dependencies', () => {
|
|
68
|
+
for (const pkg of ALL_CANONICAL_PACKAGES) {
|
|
69
|
+
const tarPath = node_path_1.default.join(tempPackDir, pkg.tarName);
|
|
70
|
+
const pkgJsonRaw = (0, node_child_process_1.execSync)(`tar -xzf ${tarPath} -O package/package.json`, { encoding: 'utf8' });
|
|
71
|
+
const pkgJson = JSON.parse(pkgJsonRaw);
|
|
72
|
+
const allDeps = {
|
|
73
|
+
...(pkgJson.dependencies || {}),
|
|
74
|
+
...(pkgJson.peerDependencies || {}),
|
|
75
|
+
};
|
|
76
|
+
for (const [depName, version] of Object.entries(allDeps)) {
|
|
77
|
+
if (typeof version === 'string') {
|
|
78
|
+
expect(version.startsWith('workspace:')).toBe(false);
|
|
79
|
+
expect(version.startsWith('link:')).toBe(false);
|
|
80
|
+
expect(version.includes('../')).toBe(false);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
describe('Phase 5B & 5C & 5G: Clean-Machine Installation & Isolation Acceptance', () => {
|
|
87
|
+
const registry = discovery_1.OrganRegistry.discover([
|
|
88
|
+
node_path_1.default.resolve(repoRoot, 'packages/organs'),
|
|
89
|
+
node_path_1.default.resolve(repoRoot, 'packages')
|
|
90
|
+
]);
|
|
91
|
+
const brain = registry.get('brain');
|
|
92
|
+
const hands = registry.get('hands');
|
|
93
|
+
const memory = registry.get('memory');
|
|
94
|
+
test('Clean Composition 1: Brain only instance installs, starts, runs doctor and db push', () => {
|
|
95
|
+
const instanceDir = node_path_1.default.join(cleanMachineRoot, 'inst-brain-only');
|
|
96
|
+
node_fs_1.default.mkdirSync(node_path_1.default.join(instanceDir, 'src'), { recursive: true });
|
|
97
|
+
const files = (0, generator_1.generateInstanceFiles)({
|
|
98
|
+
name: 'CleanBrainOnly',
|
|
99
|
+
selectedManifests: [brain],
|
|
100
|
+
});
|
|
101
|
+
const pkgObj = JSON.parse(files['package.json']);
|
|
102
|
+
pkgObj.dependencies = {
|
|
103
|
+
'@siduri-x/core': `file:${getTarPath('@siduri-x/core')}`,
|
|
104
|
+
'@siduri-x/brain': `file:${getTarPath('@siduri-x/brain')}`,
|
|
105
|
+
};
|
|
106
|
+
pkgObj.devDependencies = {
|
|
107
|
+
'@vxnus/siduri': `file:${getTarPath('@vxnus/siduri')}`,
|
|
108
|
+
};
|
|
109
|
+
node_fs_1.default.writeFileSync(node_path_1.default.join(instanceDir, 'package.json'), JSON.stringify(pkgObj, null, 2) + '\n');
|
|
110
|
+
node_fs_1.default.writeFileSync(node_path_1.default.join(instanceDir, 'siduri.config.json'), files['siduri.config.json']);
|
|
111
|
+
node_fs_1.default.writeFileSync(node_path_1.default.join(instanceDir, 'siduri.schema.json'), files['siduri.schema.json']);
|
|
112
|
+
node_fs_1.default.writeFileSync(node_path_1.default.join(instanceDir, '.env.example'), files['.env.example']);
|
|
113
|
+
node_fs_1.default.writeFileSync(node_path_1.default.join(instanceDir, 'README.md'), files['README.md']);
|
|
114
|
+
node_fs_1.default.writeFileSync(node_path_1.default.join(instanceDir, 'src/index.js'), files['src/index.js']);
|
|
115
|
+
(0, node_child_process_1.execSync)('npm install --no-audit --no-fund', { cwd: instanceDir, stdio: 'pipe' });
|
|
116
|
+
expect(node_fs_1.default.existsSync(node_path_1.default.join(instanceDir, 'node_modules/@siduri-x/memory'))).toBe(false);
|
|
117
|
+
expect(node_fs_1.default.existsSync(node_path_1.default.join(instanceDir, 'node_modules/@siduri-x/hands'))).toBe(false);
|
|
118
|
+
const doctorPass = (0, node_child_process_1.execSync)(`node ${node_path_1.default.resolve(repoRoot, 'cli/dist/index.js')} doctor`, {
|
|
119
|
+
cwd: instanceDir,
|
|
120
|
+
env: { ...process.env, OPENROUTER_API_KEY: 'test-key-clean' },
|
|
121
|
+
encoding: 'utf8',
|
|
122
|
+
});
|
|
123
|
+
expect(doctorPass).toContain('Result: PASS');
|
|
124
|
+
const dbPushOutput = (0, node_child_process_1.execSync)(`node ${node_path_1.default.resolve(repoRoot, 'cli/dist/index.js')} db push`, {
|
|
125
|
+
cwd: instanceDir,
|
|
126
|
+
encoding: 'utf8',
|
|
127
|
+
});
|
|
128
|
+
expect(dbPushOutput).toContain('SQLite manages schema natively. No CLI migrations required.');
|
|
129
|
+
}, 60000);
|
|
130
|
+
test('Clean Composition 2: Brain + Hands installs and runs doctor verifying ACTION_POLICY_SECRET', () => {
|
|
131
|
+
const instanceDir = node_path_1.default.join(cleanMachineRoot, 'inst-brain-hands');
|
|
132
|
+
node_fs_1.default.mkdirSync(node_path_1.default.join(instanceDir, 'src'), { recursive: true });
|
|
133
|
+
const files = (0, generator_1.generateInstanceFiles)({
|
|
134
|
+
name: 'CleanBrainHands',
|
|
135
|
+
selectedManifests: [brain, hands],
|
|
136
|
+
});
|
|
137
|
+
const pkgObj = JSON.parse(files['package.json']);
|
|
138
|
+
pkgObj.dependencies = {
|
|
139
|
+
'@siduri-x/core': `file:${getTarPath('@siduri-x/core')}`,
|
|
140
|
+
'@siduri-x/brain': `file:${getTarPath('@siduri-x/brain')}`,
|
|
141
|
+
'@siduri-x/hands': `file:${getTarPath('@siduri-x/hands')}`,
|
|
142
|
+
};
|
|
143
|
+
pkgObj.devDependencies = {
|
|
144
|
+
'@vxnus/siduri': `file:${getTarPath('@vxnus/siduri')}`,
|
|
145
|
+
};
|
|
146
|
+
node_fs_1.default.writeFileSync(node_path_1.default.join(instanceDir, 'package.json'), JSON.stringify(pkgObj, null, 2) + '\n');
|
|
147
|
+
node_fs_1.default.writeFileSync(node_path_1.default.join(instanceDir, 'siduri.config.json'), files['siduri.config.json']);
|
|
148
|
+
node_fs_1.default.writeFileSync(node_path_1.default.join(instanceDir, 'siduri.schema.json'), files['siduri.schema.json']);
|
|
149
|
+
node_fs_1.default.writeFileSync(node_path_1.default.join(instanceDir, '.env.example'), files['.env.example']);
|
|
150
|
+
node_fs_1.default.writeFileSync(node_path_1.default.join(instanceDir, 'README.md'), files['README.md']);
|
|
151
|
+
node_fs_1.default.writeFileSync(node_path_1.default.join(instanceDir, 'src/index.js'), files['src/index.js']);
|
|
152
|
+
(0, node_child_process_1.execSync)('npm install --no-audit --no-fund', { cwd: instanceDir, stdio: 'pipe' });
|
|
153
|
+
const doctorOutput = (0, node_child_process_1.execSync)(`node ${node_path_1.default.resolve(repoRoot, 'cli/dist/index.js')} doctor`, {
|
|
154
|
+
cwd: instanceDir,
|
|
155
|
+
env: {
|
|
156
|
+
...process.env,
|
|
157
|
+
OPENROUTER_API_KEY: 'test-key-clean',
|
|
158
|
+
ACTION_POLICY_SECRET: 'test-secret-clean',
|
|
159
|
+
},
|
|
160
|
+
encoding: 'utf8',
|
|
161
|
+
});
|
|
162
|
+
expect(doctorOutput).toContain('ACTION_POLICY_SECRET');
|
|
163
|
+
expect(doctorOutput).toContain('Result: PASS');
|
|
164
|
+
}, 60000);
|
|
165
|
+
});
|
|
166
|
+
});
|