genesis-compiler 1.2.5 → 1.2.7
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 +45 -19
- package/docs/prompt-integration.md +1 -1
- package/docs/stack-components.md +19 -4
- package/package.json +2 -4
- package/plugins/genesis/.codex-plugin/plugin.json +1 -1
- package/prompts/adopt.txt +6 -0
- package/src/cli.js +38 -10
- package/src/index/agent-skills.js +11 -3
- package/src/index/check.js +30 -2
- package/src/index/code-index.js +7 -2
- package/src/index/context.js +2 -2
- package/src/index/contracts.js +7 -0
- package/src/index/deployment.js +4 -2
- package/src/index/environment-files.js +8 -2
- package/src/index/init.js +2 -2
- package/src/index/launch.js +4 -1
- package/src/index/process.js +119 -5
- package/src/index/prompt.js +24 -16
- package/src/index/stack-catalog.js +111 -26
- package/src/index/stack.js +60 -8
- package/src/index/verification.js +15 -1
- package/src/index/workspace-setup.js +12 -2
- package/src/index.js +29 -17
- package/stacks/pieces/cpp.md +0 -34
- package/stacks/pieces/csharp.md +0 -22
- package/stacks/pieces/go.md +0 -22
- package/stacks/pieces/java.md +0 -22
- package/stacks/pieces/jskit-mysql.md +0 -56
- package/stacks/pieces/jskit-postgresql.md +0 -56
- package/stacks/pieces/jskit.md +0 -114
- package/stacks/pieces/kotlin.md +0 -22
- package/stacks/pieces/mysql.md +0 -29
- package/stacks/pieces/nodejs.md +0 -36
- package/stacks/pieces/php.md +0 -23
- package/stacks/pieces/postgresql.md +0 -30
- package/stacks/pieces/python.md +0 -23
- package/stacks/pieces/ruby.md +0 -22
- package/stacks/pieces/rust.md +0 -22
- package/stacks/pieces/shell.md +0 -23
- package/stacks/pieces/vue.md +0 -28
package/README.md
CHANGED
|
@@ -51,6 +51,18 @@ completely or correctly explains the implementation.
|
|
|
51
51
|
|
|
52
52
|
Genesis requires Node.js 22 or newer and Git.
|
|
53
53
|
|
|
54
|
+
Install the framework-neutral compiler and the optional first-party technology
|
|
55
|
+
catalog as separate packages:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npm install --global genesis-compiler genesis-stack
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
`genesis-compiler` has no dependency on `genesis-stack` or on any framework.
|
|
62
|
+
The catalog is static Markdown and contains the complete curated set of
|
|
63
|
+
language, database, UI, and framework pieces. A host may supply another catalog
|
|
64
|
+
through the same contract.
|
|
65
|
+
|
|
54
66
|
For an existing codebase, `adopt` is the direct entry point:
|
|
55
67
|
|
|
56
68
|
```bash
|
|
@@ -102,7 +114,8 @@ that, use Codex normally. No technology is assumed until you explicitly select
|
|
|
102
114
|
Stack components:
|
|
103
115
|
|
|
104
116
|
```bash
|
|
105
|
-
genesis stack add
|
|
117
|
+
genesis stack add --stack-package genesis-stack nodejs
|
|
118
|
+
# or: genesis stack add --stack-package genesis-stack jskit jskit-mysql
|
|
106
119
|
```
|
|
107
120
|
|
|
108
121
|
Genesis does not install substitute generic `nodejs`, `vue`, `php`, or similar
|
|
@@ -110,8 +123,9 @@ skills. Official, user, or host skills retain their normal names. A Stack piece
|
|
|
110
123
|
may instead name one authoritative technology skill; Genesis copies that
|
|
111
124
|
complete directory into `.agents/skills/`, including its `references/`,
|
|
112
125
|
`scripts/`, `assets/`, and agent metadata. The agent loads those resources only
|
|
113
|
-
when the skill requires them. For example, the
|
|
114
|
-
package's own `jskit` skill. A piece's optional
|
|
126
|
+
when the skill requires them. For example, the `genesis-stack` catalog's JSKIT
|
|
127
|
+
piece installs the JSKIT package's own `jskit` skill. A piece's optional
|
|
128
|
+
`## Guidance` is concise
|
|
115
129
|
supplemental project-work guidance; it does not create or replace a generic
|
|
116
130
|
technology skill.
|
|
117
131
|
|
|
@@ -130,8 +144,8 @@ execute the same normalized recipe themselves. A concrete Stack piece may declar
|
|
|
130
144
|
ordered `## Workspace setup` recipe with labels, argument arrays expressed as
|
|
131
145
|
backticked tokens, abstract runtimes, and optional project-relative working
|
|
132
146
|
directories and readiness paths. A recipe whose declared project marker does
|
|
133
|
-
not exist remains unconfigured until a later inspection. The
|
|
134
|
-
piece waits for `package.json` and then declares `npm install`; generic
|
|
147
|
+
not exist remains unconfigured until a later inspection. The catalog's
|
|
148
|
+
`jskit` piece waits for `package.json` and then declares `npm install`; generic
|
|
135
149
|
`nodejs` and `php` deliberately declare no installer. One project section in
|
|
136
150
|
`genesis/stack.md` replaces all component defaults, including with
|
|
137
151
|
`- Nothing.`. Without that override, exactly one component recipe is used;
|
|
@@ -143,7 +157,7 @@ resources such as database variables do not gate dependency installation.
|
|
|
143
157
|
Hosts that manage project environments can call `inspectEnvironment()`.
|
|
144
158
|
Concrete Stack integrations may declare public, non-secret Environment
|
|
145
159
|
defaults such as the database driver selected by that integration. Explicit
|
|
146
|
-
host or user values take precedence. The
|
|
160
|
+
host or user values take precedence. The catalog's JSKIT MySQL and PostgreSQL
|
|
147
161
|
pieces respectively declare `DB_CLIENT=mysql2` and `DB_CLIENT=pg`, so users
|
|
148
162
|
provide connection values rather than restating a deterministic technology
|
|
149
163
|
choice.
|
|
@@ -164,7 +178,8 @@ optional readable `## Launch` section in `genesis/stack.md` declares labeled
|
|
|
164
178
|
targets, exact backticked argument tokens, relative working directories,
|
|
165
179
|
abstract runtime requirements, `{host}`/`{port}` substitutions, and an optional
|
|
166
180
|
application-owned Preview identity block. Concrete components may provide a
|
|
167
|
-
default: `jskit` declares its app-owned `npm run develop`
|
|
181
|
+
default: the catalog's `jskit` piece declares its app-owned `npm run develop`
|
|
182
|
+
command; generic
|
|
168
183
|
`nodejs` and `php` do not guess. Genesis starts nothing itself. It returns preview identity
|
|
169
184
|
command metadata and environment variable names, never their values. The host
|
|
170
185
|
continues to own pinned runtimes, ports, processes, readiness probing and
|
|
@@ -177,7 +192,7 @@ Hosts that publish applications can call the separate public
|
|
|
177
192
|
`inspectDeployment()` API. An optional readable `## Deployment` section
|
|
178
193
|
declares an ordered production recipe: project-relative workdir, abstract
|
|
179
194
|
runtimes, exact Prepare/Build/Migrate/Serve argv, and one HTTP readiness
|
|
180
|
-
predicate. A concrete component may provide the recipe; the
|
|
195
|
+
predicate. A concrete component may provide the recipe; the catalog's `jskit`
|
|
181
196
|
piece declares production dependency installation, build, database preparation,
|
|
182
197
|
`npm start`, and `/api/health`. Generic language pieces do not guess. A project
|
|
183
198
|
section replaces component defaults wholesale, and `- Nothing.` explicitly
|
|
@@ -201,8 +216,9 @@ genesis inspect deployment --json
|
|
|
201
216
|
```
|
|
202
217
|
|
|
203
218
|
Without `--json`, the commands print concise human-readable summaries. They
|
|
204
|
-
never
|
|
205
|
-
|
|
219
|
+
never start the application, probe a server, materialize environment files, or
|
|
220
|
+
deploy. `genesis prepare` is the separate explicit command that executes only
|
|
221
|
+
the finite Workspace setup recipe.
|
|
206
222
|
|
|
207
223
|
At session start, Codex receives only a short explanation of how Genesis is
|
|
208
224
|
organized. After it locates the source involved in a request, it can load the
|
|
@@ -354,17 +370,19 @@ object.
|
|
|
354
370
|
|
|
355
371
|
## Stack
|
|
356
372
|
|
|
357
|
-
List and select the
|
|
373
|
+
List and select pieces from the installed optional catalog:
|
|
358
374
|
|
|
359
375
|
```bash
|
|
360
|
-
genesis stack list
|
|
361
|
-
genesis stack add
|
|
376
|
+
genesis stack list --stack-package genesis-stack
|
|
377
|
+
genesis stack add --stack-package genesis-stack jskit jskit-mysql
|
|
362
378
|
```
|
|
363
379
|
|
|
364
|
-
`genesis/stack.md` records component ids and optional
|
|
365
|
-
commands.
|
|
366
|
-
|
|
367
|
-
|
|
380
|
+
`genesis/stack.md` records the owning Stack package, component ids, and optional
|
|
381
|
+
project verification commands. After the first selection, ordinary commands
|
|
382
|
+
resolve the recorded package without another flag. Selecting no components is
|
|
383
|
+
valid. `genesis-stack` contains the eleven common language families listed
|
|
384
|
+
above, plus Vue, MySQL, PostgreSQL, JSKIT, and JSKIT database integrations.
|
|
385
|
+
Components may contribute:
|
|
368
386
|
|
|
369
387
|
- a concise description and supplemental Guidance used across relevant tasks;
|
|
370
388
|
- existing-project Adoption requirements used only while importing a codebase;
|
|
@@ -380,8 +398,8 @@ cleanup tasks; `Adoption` adds import-only requirements; `Deslop` adds
|
|
|
380
398
|
cleanup-only rules. None shadows an official generic technology skill or
|
|
381
399
|
assumes that an upstream skill contains every rule Genesis needs.
|
|
382
400
|
|
|
383
|
-
Genesis core contains no database, framework, language, or
|
|
384
|
-
|
|
401
|
+
Genesis core contains no Stack pieces and no database, framework, language, or
|
|
402
|
+
platform dependency. See [Stack components](docs/stack-components.md).
|
|
385
403
|
|
|
386
404
|
## Verification
|
|
387
405
|
|
|
@@ -428,6 +446,8 @@ genesis check
|
|
|
428
446
|
- Blueprint and Stack validity;
|
|
429
447
|
- selected Agent Skill presence and structural validity;
|
|
430
448
|
- Program presence and structural validity;
|
|
449
|
+
- Workspace setup, environment, Launch, and Deployment as `ready`, `blocked`,
|
|
450
|
+
or honestly `unconfigured`;
|
|
431
451
|
- missing Stack-declared environment inputs (without claiming the service is
|
|
432
452
|
reachable);
|
|
433
453
|
- verification evidence as `current`, `stale`, `missing`, `invalid`, or
|
|
@@ -484,6 +504,12 @@ identity, secret, and browser policy.
|
|
|
484
504
|
`inspectDeployment()` returns the separate normalized production recipe without
|
|
485
505
|
executing or provisioning it.
|
|
486
506
|
|
|
507
|
+
Normalized operational results identify their stable public contract in the
|
|
508
|
+
`contract` field: `genesis.workspace-setup.v1`, `genesis.environment.v1`,
|
|
509
|
+
`genesis.launch.v1`, `genesis.deployment.v1`, or
|
|
510
|
+
`genesis.verification.v1`. Hosts validate that identity instead of
|
|
511
|
+
feature-detecting individual fields.
|
|
512
|
+
|
|
487
513
|
A host such as Vibe64 can send the generated prompt to its existing agent:
|
|
488
514
|
|
|
489
515
|
```js
|
|
@@ -35,7 +35,7 @@ Genesis keeps each instruction at one useful level:
|
|
|
35
35
|
project's `.agents/skills/` directory.
|
|
36
36
|
- `prompts/<task>.txt` is a task launcher. It selects the relevant
|
|
37
37
|
workflow skill and states only that turn's edit boundary.
|
|
38
|
-
- `stacks/pieces/<component>.md` supplies concise Description, supplemental
|
|
38
|
+
- a declared Stack package's `stacks/pieces/<component>.md` supplies concise Description, supplemental
|
|
39
39
|
Guidance, Adoption requirements, Resources, Deslop overlays, structural Indexers, verification
|
|
40
40
|
Commands, and an optional authoritative Agent Skill source.
|
|
41
41
|
- `genesis/blueprint.md`, `genesis/program/`, and `genesis/stack.md` are the
|
package/docs/stack-components.md
CHANGED
|
@@ -1,8 +1,23 @@
|
|
|
1
1
|
# Stack components
|
|
2
2
|
|
|
3
3
|
Genesis core knows no framework, language, database, package manager, or
|
|
4
|
-
environment-variable name
|
|
5
|
-
|
|
4
|
+
environment-variable name, and it ships no technology pieces. A Stack package
|
|
5
|
+
is an ordinary npm package with one static manifest pointer:
|
|
6
|
+
|
|
7
|
+
```json
|
|
8
|
+
{
|
|
9
|
+
"name": "example-stack",
|
|
10
|
+
"genesis": { "stackPieces": "stacks/pieces" }
|
|
11
|
+
}
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Each piece is one Markdown file in that declared directory. Genesis reads the
|
|
15
|
+
manifest and Markdown only; it never imports or executes package code. Catalog
|
|
16
|
+
names are explicit, collisions fail, and the selected package is recorded in
|
|
17
|
+
the project's `## Stack packages` section. The first-party optional
|
|
18
|
+
`genesis-stack` package contains the complete curated catalog; Genesis core does
|
|
19
|
+
not depend on it. A framework contributes to that catalog rather than requiring
|
|
20
|
+
a compiler release or a separate catalog package.
|
|
6
21
|
|
|
7
22
|
````markdown
|
|
8
23
|
# Stack piece: example
|
|
@@ -169,7 +184,7 @@ environment name and value. Selected
|
|
|
169
184
|
component defaults compose by name; identical declarations collapse and
|
|
170
185
|
different values fail rather than silently choosing one. Defaults participate
|
|
171
186
|
in Stack identity, resource preflight, prompt context, Launch inspection, and
|
|
172
|
-
verification execution. The JSKIT database integrations use this contract for
|
|
187
|
+
verification execution. The `genesis-stack` JSKIT database integrations use this contract for
|
|
173
188
|
their deterministic `DB_CLIENT` driver ids; generic database pieces do not.
|
|
174
189
|
Secrets and deployment-specific connection values remain host inputs and must
|
|
175
190
|
never be declared as defaults.
|
|
@@ -288,7 +303,7 @@ district to a region and a campus while generating
|
|
|
288
303
|
must not reclassify or filter paths. Under a matched prefix, the first directory
|
|
289
304
|
is a campus, while files directly below the prefix belong to the prefix campus.
|
|
290
305
|
Under the fallback, each top-level directory is a campus and project-root files
|
|
291
|
-
belong to the project-root campus. The
|
|
306
|
+
belong to the project-root campus. The `genesis-stack` JSKIT piece excludes exact
|
|
292
307
|
`test`, `tests`, and `__tests__` path segments plus `*.test.*` and `*.spec.*`
|
|
293
308
|
files, then declares `Packages`, `Source`, and `Everything else`.
|
|
294
309
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "genesis-compiler",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.7",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "An agent-independent prompt, multi-language code-index, cleanup, and verification companion with optional Codex hooks.",
|
|
6
6
|
"repository": {
|
|
@@ -39,8 +39,7 @@
|
|
|
39
39
|
"prompts/work.txt",
|
|
40
40
|
"plugins/genesis",
|
|
41
41
|
"skills",
|
|
42
|
-
"src"
|
|
43
|
-
"stacks/pieces"
|
|
42
|
+
"src"
|
|
44
43
|
],
|
|
45
44
|
"scripts": {
|
|
46
45
|
"test": "node --test test/*.test.js"
|
|
@@ -58,7 +57,6 @@
|
|
|
58
57
|
"@ast-grep/lang-ruby": "^0.0.7",
|
|
59
58
|
"@ast-grep/lang-rust": "^0.0.7",
|
|
60
59
|
"@ast-grep/napi": "^0.45.1",
|
|
61
|
-
"@jskit-ai/agent-docs": "0.1.134",
|
|
62
60
|
"yaml": "^2.9.0"
|
|
63
61
|
}
|
|
64
62
|
}
|
package/prompts/adopt.txt
CHANGED
|
@@ -50,6 +50,12 @@ or tool-specific manifests as evidence and carry every still-valid fact into
|
|
|
50
50
|
Genesis; never add a permanent legacy reader or shim. Do not delete an old
|
|
51
51
|
manifest until all of its live facts have been accounted for.
|
|
52
52
|
|
|
53
|
+
The resulting project contract may therefore own complete `## Resources`,
|
|
54
|
+
`## Environment defaults`, `## Environment files`, `## Workspace setup`,
|
|
55
|
+
`## Commands`, `## Launch`, and `## Deployment` sections. Treat these as one
|
|
56
|
+
operational inventory: do not preserve setup while silently dropping its
|
|
57
|
+
resource, launch, readiness, identity, verification, or deployment counterpart.
|
|
58
|
+
|
|
53
59
|
Create the non-technical Blueprint and useful subsystem-oriented Program from
|
|
54
60
|
current source and tests. Do not cite archive internals or Git object storage as
|
|
55
61
|
implementation source; Program sources must be current Git-visible files.
|
package/src/cli.js
CHANGED
|
@@ -44,6 +44,7 @@ const USAGE = `Usage:
|
|
|
44
44
|
|
|
45
45
|
Options:
|
|
46
46
|
--project-root <path> Set the project root (default: current directory)
|
|
47
|
+
--stack-package <name> Add an installed external Stack package (repeatable)
|
|
47
48
|
--task <task> Select the prompt task (default: work)
|
|
48
49
|
--json Emit one machine-readable result
|
|
49
50
|
-h, --help Show this help
|
|
@@ -70,6 +71,7 @@ function parseCommand(argv) {
|
|
|
70
71
|
options: {
|
|
71
72
|
json: { type: 'boolean', default: false },
|
|
72
73
|
'project-root': { type: 'string' },
|
|
74
|
+
'stack-package': { type: 'string', multiple: true, default: [] },
|
|
73
75
|
task: { type: 'string' },
|
|
74
76
|
},
|
|
75
77
|
});
|
|
@@ -79,6 +81,7 @@ function parseCommand(argv) {
|
|
|
79
81
|
const options = {
|
|
80
82
|
json: parsed.values.json,
|
|
81
83
|
projectRoot: parsed.values['project-root'],
|
|
84
|
+
stackPackages: parsed.values['stack-package'],
|
|
82
85
|
task: parsed.values.task,
|
|
83
86
|
};
|
|
84
87
|
const operands = parsed.positionals;
|
|
@@ -131,6 +134,10 @@ function writeCheck(result) {
|
|
|
131
134
|
line(process.stdout, `Stack: ${result.stack}`);
|
|
132
135
|
line(process.stdout, `Agent Skills: ${result.skills}`);
|
|
133
136
|
line(process.stdout, `Program: ${result.program}`);
|
|
137
|
+
line(process.stdout, `Workspace setup: ${result.workspaceSetup}`);
|
|
138
|
+
line(process.stdout, `Environment: ${result.environment}`);
|
|
139
|
+
line(process.stdout, `Launch: ${result.launch}`);
|
|
140
|
+
line(process.stdout, `Deployment: ${result.deployment}`);
|
|
134
141
|
line(process.stdout, `Resource inputs: ${result.resources}`);
|
|
135
142
|
line(process.stdout, `Verification: ${result.verification}`);
|
|
136
143
|
namedItems('Program files', result.programFiles);
|
|
@@ -262,26 +269,30 @@ async function hookInput() {
|
|
|
262
269
|
}
|
|
263
270
|
}
|
|
264
271
|
|
|
265
|
-
async function execute({ command, operands, options }) {
|
|
272
|
+
async function execute({ command, operands, options }, { signal } = {}) {
|
|
266
273
|
const projectRoot = options.projectRoot || process.cwd();
|
|
267
|
-
|
|
274
|
+
const stackPackages = options.stackPackages || [];
|
|
275
|
+
if (command === 'init') return initialize({ projectRoot, stackPackages });
|
|
268
276
|
if (command === 'adopt') {
|
|
269
|
-
return adoptProject({ projectRoot, request: operands.join(' ') });
|
|
277
|
+
return adoptProject({ projectRoot, request: operands.join(' '), stackPackages });
|
|
270
278
|
}
|
|
271
279
|
if (command === 'codex') return installCodex();
|
|
272
280
|
if (command === 'stack') {
|
|
273
|
-
if (operands[0] === 'list')
|
|
274
|
-
|
|
281
|
+
if (operands[0] === 'list') {
|
|
282
|
+
return { status: 'ok', pieces: await listStackPieces({ projectRoot, stackPackages }) };
|
|
283
|
+
}
|
|
284
|
+
return addStack({ pieces: operands.slice(1), projectRoot, stackPackages });
|
|
275
285
|
}
|
|
276
286
|
if (command === 'prompt') {
|
|
277
287
|
return generatePrompt({
|
|
278
288
|
projectRoot,
|
|
279
289
|
task: options.task || 'work',
|
|
280
290
|
request: operands.join(' '),
|
|
291
|
+
stackPackages,
|
|
281
292
|
});
|
|
282
293
|
}
|
|
283
|
-
if (command === 'context') return getContext({ paths: operands, projectRoot });
|
|
284
|
-
if (command === 'index') return indexCodebase({ projectRoot, queries: operands });
|
|
294
|
+
if (command === 'context') return getContext({ paths: operands, projectRoot, stackPackages });
|
|
295
|
+
if (command === 'index') return indexCodebase({ projectRoot, queries: operands, stackPackages });
|
|
285
296
|
if (command === 'inspect') {
|
|
286
297
|
const inspections = {
|
|
287
298
|
workspace: inspectWorkspaceSetup,
|
|
@@ -289,11 +300,16 @@ async function execute({ command, operands, options }) {
|
|
|
289
300
|
launch: inspectLaunch,
|
|
290
301
|
deployment: inspectDeployment,
|
|
291
302
|
};
|
|
292
|
-
return {
|
|
303
|
+
return {
|
|
304
|
+
inspection: operands[0],
|
|
305
|
+
...await inspections[operands[0]]({ projectRoot, stackPackages }),
|
|
306
|
+
};
|
|
293
307
|
}
|
|
294
308
|
if (command === 'prepare') {
|
|
295
309
|
return prepareWorkspace({
|
|
296
310
|
projectRoot,
|
|
311
|
+
signal,
|
|
312
|
+
stackPackages,
|
|
297
313
|
onEvent: (event) => {
|
|
298
314
|
if (!options.json) line(process.stderr, event.message);
|
|
299
315
|
},
|
|
@@ -318,17 +334,21 @@ async function execute({ command, operands, options }) {
|
|
|
318
334
|
if (command === 'verify') {
|
|
319
335
|
return verify({
|
|
320
336
|
projectRoot,
|
|
337
|
+
signal,
|
|
338
|
+
stackPackages,
|
|
321
339
|
onEvent: (event) => {
|
|
322
340
|
if (!options.json) line(process.stderr, event.message);
|
|
323
341
|
},
|
|
324
342
|
});
|
|
325
343
|
}
|
|
326
|
-
if (command === 'check') return check({ projectRoot });
|
|
344
|
+
if (command === 'check') return check({ projectRoot, stackPackages });
|
|
327
345
|
fail('CLI_UNKNOWN_COMMAND', `Unknown command: ${command}`);
|
|
328
346
|
}
|
|
329
347
|
|
|
330
348
|
export async function runCli(argv = process.argv.slice(2)) {
|
|
331
349
|
let options = {};
|
|
350
|
+
const controller = new AbortController();
|
|
351
|
+
const abort = () => controller.abort();
|
|
332
352
|
try {
|
|
333
353
|
const parsed = parseCommand(argv);
|
|
334
354
|
if (parsed.command === 'help') {
|
|
@@ -336,7 +356,12 @@ export async function runCli(argv = process.argv.slice(2)) {
|
|
|
336
356
|
return 0;
|
|
337
357
|
}
|
|
338
358
|
options = parsed.options;
|
|
339
|
-
const
|
|
359
|
+
const finiteCommand = ['prepare', 'verify'].includes(parsed.command);
|
|
360
|
+
if (finiteCommand) {
|
|
361
|
+
process.once('SIGINT', abort);
|
|
362
|
+
process.once('SIGTERM', abort);
|
|
363
|
+
}
|
|
364
|
+
const result = await execute(parsed, { signal: controller.signal });
|
|
340
365
|
if (options.json) line(process.stdout, JSON.stringify(result));
|
|
341
366
|
else writeResult(parsed.command, result);
|
|
342
367
|
return ['blocked', 'failed', 'invalid'].includes(result?.status) ? 2 : 0;
|
|
@@ -345,5 +370,8 @@ export async function runCli(argv = process.argv.slice(2)) {
|
|
|
345
370
|
if (options.json) line(process.stderr, JSON.stringify(diagnostic));
|
|
346
371
|
else line(process.stderr, `${diagnostic.code}: ${diagnostic.message}`);
|
|
347
372
|
return 1;
|
|
373
|
+
} finally {
|
|
374
|
+
process.removeListener('SIGINT', abort);
|
|
375
|
+
process.removeListener('SIGTERM', abort);
|
|
348
376
|
}
|
|
349
377
|
}
|
|
@@ -156,8 +156,14 @@ async function describeSkill(directory, source) {
|
|
|
156
156
|
};
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
-
async function packageDirectory(packageName) {
|
|
160
|
-
|
|
159
|
+
async function packageDirectory(packageName, resolveFrom = null) {
|
|
160
|
+
const roots = [
|
|
161
|
+
...(resolveFrom
|
|
162
|
+
? createRequire(path.join(resolveFrom, 'package.json')).resolve.paths(packageName) || []
|
|
163
|
+
: []),
|
|
164
|
+
...(require.resolve.paths(packageName) || []),
|
|
165
|
+
];
|
|
166
|
+
for (const modulesRoot of [...new Set(roots)]) {
|
|
161
167
|
const manifest = path.join(modulesRoot, packageName, 'package.json');
|
|
162
168
|
try {
|
|
163
169
|
const value = JSON.parse(await readFile(manifest, 'utf8'));
|
|
@@ -180,7 +186,9 @@ async function packageDirectory(packageName) {
|
|
|
180
186
|
}
|
|
181
187
|
|
|
182
188
|
async function resolveLocator(locator) {
|
|
183
|
-
const root = locator.package
|
|
189
|
+
const root = locator.package
|
|
190
|
+
? await packageDirectory(locator.package, locator.resolveFrom)
|
|
191
|
+
: packageRoot;
|
|
184
192
|
const directory = path.join(root, locator.path);
|
|
185
193
|
const source = locator.source || (
|
|
186
194
|
locator.package
|
package/src/index/check.js
CHANGED
|
@@ -7,6 +7,10 @@ import { inspectProgram } from './program.js';
|
|
|
7
7
|
import { inspectVerification } from './project-state.js';
|
|
8
8
|
import { missingStackResources } from './stack-preflight.js';
|
|
9
9
|
import { withStackEnvironmentDefaults } from './stack-environment-defaults.js';
|
|
10
|
+
import { inspectProjectEnvironment } from './environment-files.js';
|
|
11
|
+
import { inspectProjectLaunch } from './launch.js';
|
|
12
|
+
import { inspectProjectDeployment } from './deployment.js';
|
|
13
|
+
import { inspectWorkspaceSetupForStack } from './workspace-setup.js';
|
|
10
14
|
|
|
11
15
|
function invalidResult(area, error) {
|
|
12
16
|
return {
|
|
@@ -15,6 +19,10 @@ function invalidResult(area, error) {
|
|
|
15
19
|
stack: area === 'stack' ? 'invalid' : 'unknown',
|
|
16
20
|
skills: area === 'skills' ? 'invalid' : 'unknown',
|
|
17
21
|
program: 'unknown',
|
|
22
|
+
workspaceSetup: 'unknown',
|
|
23
|
+
environment: 'unknown',
|
|
24
|
+
launch: 'unknown',
|
|
25
|
+
deployment: 'unknown',
|
|
18
26
|
resources: 'unknown',
|
|
19
27
|
verification: 'unknown',
|
|
20
28
|
programFiles: [],
|
|
@@ -24,7 +32,11 @@ function invalidResult(area, error) {
|
|
|
24
32
|
};
|
|
25
33
|
}
|
|
26
34
|
|
|
27
|
-
export async function checkProject({
|
|
35
|
+
export async function checkProject({
|
|
36
|
+
environment = process.env,
|
|
37
|
+
projectRoot,
|
|
38
|
+
stackPackages = [],
|
|
39
|
+
} = {}) {
|
|
28
40
|
const root = (await gitContext(projectRoot)).repositoryRoot;
|
|
29
41
|
try {
|
|
30
42
|
await readBlueprint(root, { required: true, requireDescription: true });
|
|
@@ -34,7 +46,7 @@ export async function checkProject({ environment = process.env, projectRoot } =
|
|
|
34
46
|
|
|
35
47
|
let stack;
|
|
36
48
|
try {
|
|
37
|
-
stack = await readStack(root);
|
|
49
|
+
stack = await readStack(root, { stackPackages });
|
|
38
50
|
} catch (error) {
|
|
39
51
|
return invalidResult('stack', error);
|
|
40
52
|
}
|
|
@@ -61,10 +73,18 @@ export async function checkProject({ environment = process.env, projectRoot } =
|
|
|
61
73
|
resources: stack.resources,
|
|
62
74
|
});
|
|
63
75
|
const verification = await inspectVerification({ projectRoot: root, stack });
|
|
76
|
+
const [workspaceSetup, projectEnvironment, launch, deployment] = await Promise.all([
|
|
77
|
+
inspectWorkspaceSetupForStack({ projectRoot: root, stack }),
|
|
78
|
+
inspectProjectEnvironment({ environment, projectRoot: root, stackPackages }),
|
|
79
|
+
inspectProjectLaunch({ environment, projectRoot: root, stackPackages }),
|
|
80
|
+
inspectProjectDeployment({ projectRoot: root, stackPackages }),
|
|
81
|
+
]);
|
|
64
82
|
const diagnostics = [
|
|
65
83
|
...(program.diagnostic ? [program.diagnostic] : []),
|
|
66
84
|
...skills.diagnostics,
|
|
67
85
|
...missingResources,
|
|
86
|
+
...workspaceSetup.diagnostics.filter(({ code }) => code !== 'STACK_WORKSPACE_SETUP_WAITING'),
|
|
87
|
+
...deployment.diagnostics,
|
|
68
88
|
...(verification.status === 'invalid' ? [{
|
|
69
89
|
code: 'VERIFICATION_EVIDENCE_INVALID',
|
|
70
90
|
message: 'Saved verification evidence is malformed.',
|
|
@@ -79,6 +99,8 @@ export async function checkProject({ environment = process.env, projectRoot } =
|
|
|
79
99
|
if (missingResources.length > 0) {
|
|
80
100
|
guidance.push(`${missingResources.map(({ message }) => message).join(' ')} Prompt generation remains available.`);
|
|
81
101
|
}
|
|
102
|
+
if (workspaceSetup.status === 'blocked') guidance.push('Repair the project Workspace setup declaration.');
|
|
103
|
+
if (deployment.status === 'blocked') guidance.push('Repair the project Deployment declaration.');
|
|
82
104
|
if (['missing', 'stale'].includes(verification.status)) guidance.push('Run genesis verify to refresh concrete evidence.');
|
|
83
105
|
if (verification.status === 'unconfigured') guidance.push('Add project verification commands to genesis/stack.md.');
|
|
84
106
|
guidance.push('Use genesis prompt --task review for a semantic, evidence-based comparison.');
|
|
@@ -86,6 +108,8 @@ export async function checkProject({ environment = process.env, projectRoot } =
|
|
|
86
108
|
const needsAttention = program.status === 'missing'
|
|
87
109
|
|| skills.status === 'missing'
|
|
88
110
|
|| missingResources.length > 0
|
|
111
|
+
|| workspaceSetup.status === 'blocked'
|
|
112
|
+
|| deployment.status === 'blocked'
|
|
89
113
|
|| ['missing', 'stale', 'unconfigured'].includes(verification.status);
|
|
90
114
|
|
|
91
115
|
return {
|
|
@@ -96,6 +120,10 @@ export async function checkProject({ environment = process.env, projectRoot } =
|
|
|
96
120
|
stack: 'valid',
|
|
97
121
|
skills: skills.status,
|
|
98
122
|
program: program.status,
|
|
123
|
+
workspaceSetup: workspaceSetup.status,
|
|
124
|
+
environment: projectEnvironment.status,
|
|
125
|
+
launch: launch.status,
|
|
126
|
+
deployment: deployment.status,
|
|
99
127
|
resources: missingResources.length > 0 ? 'missing' : 'inputs-present',
|
|
100
128
|
verification: verification.status,
|
|
101
129
|
programFiles: program.files,
|
package/src/index/code-index.js
CHANGED
|
@@ -238,9 +238,14 @@ function formatCount(value, singular) {
|
|
|
238
238
|
return `${value} ${singular}${value === 1 ? '' : 's'}`;
|
|
239
239
|
}
|
|
240
240
|
|
|
241
|
-
export async function buildProjectIndex({
|
|
241
|
+
export async function buildProjectIndex({
|
|
242
|
+
projectRoot,
|
|
243
|
+
queries = [],
|
|
244
|
+
stackPackages = [],
|
|
245
|
+
write = true,
|
|
246
|
+
} = {}) {
|
|
242
247
|
const root = (await gitContext(projectRoot)).repositoryRoot;
|
|
243
|
-
const stack = await readStack(root);
|
|
248
|
+
const stack = await readStack(root, { stackPackages });
|
|
244
249
|
const states = await gitVisibleFileStates(root, { includePath: isProjectContentPath });
|
|
245
250
|
const files = [...states]
|
|
246
251
|
.filter(([filePath, state]) => (
|
package/src/index/context.js
CHANGED
|
@@ -49,7 +49,7 @@ function pathMatchesTarget(filePath, target) {
|
|
|
49
49
|
return !target || filePath === target || filePath.startsWith(`${target}/`);
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
export async function contextForProjectPaths({ paths, projectRoot } = {}) {
|
|
52
|
+
export async function contextForProjectPaths({ paths, projectRoot, stackPackages = [] } = {}) {
|
|
53
53
|
if (!Array.isArray(paths) || paths.length === 0) {
|
|
54
54
|
throw new GenesisError('CONTEXT_PATH_REQUIRED', 'Genesis context requires at least one project path.');
|
|
55
55
|
}
|
|
@@ -62,7 +62,7 @@ export async function contextForProjectPaths({ paths, projectRoot } = {}) {
|
|
|
62
62
|
modules: [],
|
|
63
63
|
diagnostic: asDiagnostic(error),
|
|
64
64
|
})),
|
|
65
|
-
readStack(root),
|
|
65
|
+
readStack(root, { stackPackages }),
|
|
66
66
|
]);
|
|
67
67
|
const modules = program.modules.filter((module) => targets.some((target) => citesTarget(module, target)));
|
|
68
68
|
const moduleSources = await Promise.all(modules.map(async (module) => ({
|
package/src/index/deployment.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { gitContext } from './git.js';
|
|
2
2
|
import { readStack } from './stack.js';
|
|
3
3
|
import { sha256, stableJson, uniqueSorted } from './utils.js';
|
|
4
|
+
import { GENESIS_CONTRACTS } from './contracts.js';
|
|
4
5
|
|
|
5
6
|
/** Read the Stack's production recipe without provisioning or publishing anything. */
|
|
6
|
-
export async function inspectProjectDeployment({ projectRoot } = {}) {
|
|
7
|
+
export async function inspectProjectDeployment({ projectRoot, stackPackages = [] } = {}) {
|
|
7
8
|
const root = (await gitContext(projectRoot)).repositoryRoot;
|
|
8
|
-
const stack = await readStack(root);
|
|
9
|
+
const stack = await readStack(root, { stackPackages });
|
|
9
10
|
const diagnostics = [...stack.deployment.diagnostics];
|
|
10
11
|
let status = 'unconfigured';
|
|
11
12
|
if (diagnostics.length > 0) status = 'blocked';
|
|
@@ -18,6 +19,7 @@ export async function inspectProjectDeployment({ projectRoot } = {}) {
|
|
|
18
19
|
steps: stack.deployment.steps,
|
|
19
20
|
};
|
|
20
21
|
return {
|
|
22
|
+
contract: GENESIS_CONTRACTS.deployment,
|
|
21
23
|
status,
|
|
22
24
|
stackHash: stack.identityHash,
|
|
23
25
|
recipeHash: status === 'ready' ? sha256(stableJson(recipe)) : '',
|
|
@@ -2,11 +2,16 @@ import { gitContext } from './git.js';
|
|
|
2
2
|
import { readStack } from './stack.js';
|
|
3
3
|
import { withStackEnvironmentDefaults } from './stack-environment-defaults.js';
|
|
4
4
|
import { missingStackResources } from './stack-preflight.js';
|
|
5
|
+
import { GENESIS_CONTRACTS } from './contracts.js';
|
|
5
6
|
|
|
6
7
|
/** Inspect Stack environment requirements without returning supplied host values. */
|
|
7
|
-
export async function inspectProjectEnvironment({
|
|
8
|
+
export async function inspectProjectEnvironment({
|
|
9
|
+
environment = process.env,
|
|
10
|
+
projectRoot,
|
|
11
|
+
stackPackages = [],
|
|
12
|
+
} = {}) {
|
|
8
13
|
const root = (await gitContext(projectRoot)).repositoryRoot;
|
|
9
|
-
const stack = await readStack(root);
|
|
14
|
+
const stack = await readStack(root, { stackPackages });
|
|
10
15
|
const diagnostics = missingStackResources({
|
|
11
16
|
environment: withStackEnvironmentDefaults(environment, stack.environmentDefaults),
|
|
12
17
|
resources: stack.resources,
|
|
@@ -15,6 +20,7 @@ export async function inspectProjectEnvironment({ environment = process.env, pro
|
|
|
15
20
|
|| stack.environmentFiles.length > 0
|
|
16
21
|
|| stack.resources.length > 0;
|
|
17
22
|
return {
|
|
23
|
+
contract: GENESIS_CONTRACTS.environment,
|
|
18
24
|
status: !configured ? 'unconfigured' : diagnostics.length > 0 ? 'missing-inputs' : 'ready',
|
|
19
25
|
stackHash: stack.identityHash,
|
|
20
26
|
components: stack.components.map(({ id }) => id),
|
package/src/index/init.js
CHANGED
|
@@ -20,14 +20,14 @@ async function createIfMissing(projectRoot, relativePath, source) {
|
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
export async function initializeProject({ projectRoot } = {}) {
|
|
23
|
+
export async function initializeProject({ projectRoot, stackPackages = [] } = {}) {
|
|
24
24
|
const root = (await gitContext(projectRoot)).repositoryRoot;
|
|
25
25
|
const created = (await Promise.all([
|
|
26
26
|
createIfMissing(root, BLUEPRINT_PATH, BLUEPRINT_SKELETON_SOURCE),
|
|
27
27
|
createIfMissing(root, STACK_PATH, EMPTY_STACK_SOURCE),
|
|
28
28
|
])).filter(Boolean);
|
|
29
29
|
await mkdir(path.join(root, PROGRAM_ROOT), { recursive: true });
|
|
30
|
-
const stack = await readStack(root);
|
|
30
|
+
const stack = await readStack(root, { stackPackages });
|
|
31
31
|
const skills = await syncProjectSkills({ projectRoot: root, stack });
|
|
32
32
|
const hooks = await installCodexHooks({ projectRoot: root });
|
|
33
33
|
const changedFiles = [...created, ...hooks.changedFiles, ...skills.changedFiles].sort();
|
package/src/index/launch.js
CHANGED
|
@@ -3,14 +3,16 @@ import { missingStackResources } from './stack-preflight.js';
|
|
|
3
3
|
import { withStackEnvironmentDefaults } from './stack-environment-defaults.js';
|
|
4
4
|
import { readStack } from './stack.js';
|
|
5
5
|
import { uniqueSorted } from './utils.js';
|
|
6
|
+
import { GENESIS_CONTRACTS } from './contracts.js';
|
|
6
7
|
|
|
7
8
|
/** Read the Stack's launch declaration without choosing or starting a runtime. */
|
|
8
9
|
export async function inspectProjectLaunch({
|
|
9
10
|
environment = process.env,
|
|
10
11
|
projectRoot,
|
|
12
|
+
stackPackages = [],
|
|
11
13
|
} = {}) {
|
|
12
14
|
const root = (await gitContext(projectRoot)).repositoryRoot;
|
|
13
|
-
const stack = await readStack(root);
|
|
15
|
+
const stack = await readStack(root, { stackPackages });
|
|
14
16
|
const diagnostics = missingStackResources({
|
|
15
17
|
environment: withStackEnvironmentDefaults(environment, stack.environmentDefaults),
|
|
16
18
|
resources: stack.resources,
|
|
@@ -27,6 +29,7 @@ export async function inspectProjectLaunch({
|
|
|
27
29
|
if (targets.length === 0) status = 'unconfigured';
|
|
28
30
|
else if (diagnostics.length > 0) status = 'blocked';
|
|
29
31
|
return {
|
|
32
|
+
contract: GENESIS_CONTRACTS.launch,
|
|
30
33
|
status,
|
|
31
34
|
stackHash: stack.identityHash,
|
|
32
35
|
components: stack.components.map(({ id }) => id),
|