genesis-compiler 1.2.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -13,7 +13,7 @@ interaction.
13
13
  ```text
14
14
  genesis/
15
15
  blueprint.md non-technical product intent
16
- stack.md selected technology guidance, checks, setup, and launch data
16
+ stack.md selected technology guidance, checks, setup, launch, and deployment data
17
17
  stack/ optional per-component Description, Guidance, and Deslop customization
18
18
  program/ concise explanations grouped into conceptual subsystems
19
19
  .agents/skills/
@@ -98,7 +98,7 @@ that, use Codex normally. No technology is assumed until you explicitly select
98
98
  Stack components:
99
99
 
100
100
  ```bash
101
- genesis stack add nodejs # or jskit jskit-mysql
101
+ genesis stack add nodejs # or jskit jskit-mysql / jskit-postgresql
102
102
  ```
103
103
 
104
104
  Genesis does not install substitute generic `nodejs`, `vue`, `php`, or similar
@@ -131,25 +131,51 @@ Genesis does not run the recipe. Stack resources such as database variables do
131
131
  not gate dependency installation.
132
132
 
133
133
  Hosts that manage project environments can call `inspectEnvironment()`.
134
+ Concrete Stack integrations may declare public, non-secret Environment
135
+ defaults such as the database driver selected by that integration. Explicit
136
+ host or user values take precedence. The built-in JSKIT MySQL and PostgreSQL
137
+ pieces respectively declare `DB_CLIENT=mysql2` and `DB_CLIENT=pg`, so users
138
+ provide connection values rather than restating a deterministic technology
139
+ choice.
134
140
  An optional readable `## Environment files` section declares safe
135
141
  project-relative dotenv projections such as `.env`. A project declaration
136
142
  replaces component defaults, including with `- Nothing.`; otherwise component
137
- paths compose. Genesis reports resource declarations, value-free missing-input
138
- diagnostics, and paths. It never returns values, writes files, stores secrets,
139
- or decides which resolved values a host should materialize.
143
+ paths compose. Genesis reports public defaults, resource declarations,
144
+ value-free missing-input diagnostics, and paths. It never returns supplied
145
+ environment values, writes files, stores secrets, or decides which resolved
146
+ host values should be materialized.
140
147
 
141
148
  Hosts that provide previews can call the public `inspectLaunch()` API. An
142
149
  optional readable `## Launch` section in `genesis/stack.md` declares labeled
143
150
  targets, exact backticked argument tokens, relative working directories,
144
151
  abstract runtime requirements, `{host}`/`{port}` substitutions, and an optional
145
152
  application-owned Preview identity block. Concrete components may provide a
146
- default: `jskit` declares build followed by `npm start`; generic `nodejs` and
147
- `php` do not guess. Genesis starts nothing itself. It returns preview identity
153
+ default: `jskit` declares its app-owned `npm run develop` command; generic
154
+ `nodejs` and `php` do not guess. Genesis starts nothing itself. It returns preview identity
148
155
  command metadata and environment variable names, never their values. The host
149
- continues to own pinned runtimes, ports, processes, readiness, identity-command
150
- execution and secrets, browser binaries, Git, and credentials. See
156
+ continues to own pinned runtimes, ports, processes, readiness probing and
157
+ timeouts, identity-command execution and secrets, browser binaries, Git, and
158
+ credentials. Genesis owns only the exact HTTP readiness predicate declared by
159
+ the selected Stack. See
151
160
  [`docs/stack-components.md`](docs/stack-components.md) for the v1 contract.
152
161
 
162
+ Hosts that publish applications can call the separate public
163
+ `inspectDeployment()` API. An optional readable `## Deployment` section
164
+ declares an ordered production recipe: project-relative workdir, abstract
165
+ runtimes, exact Prepare/Build/Migrate/Serve argv, and one HTTP readiness
166
+ predicate. A concrete component may provide the recipe; the built-in `jskit`
167
+ piece declares production dependency installation, build, database preparation,
168
+ `npm start`, and `/api/health`. Generic language pieces do not guess. A project
169
+ section replaces component defaults wholesale, and `- Nothing.` explicitly
170
+ disables publishing.
171
+
172
+ Genesis only validates and reports this recipe and the Stack's abstract resource
173
+ requirements. It does not provision a database, resolve credentials, copy a
174
+ release, run commands, start a service, reserve a port, route traffic, issue TLS,
175
+ or roll back. A deployment host owns all of those operational responsibilities,
176
+ including the mapping from `mysql` or `postgresql` resources to its managed
177
+ services.
178
+
153
179
  At session start, Codex receives only a short explanation of how Genesis is
154
180
  organized. After it locates the source involved in a request, it can load the
155
181
  specific explanatory and technology context with:
@@ -300,13 +326,13 @@ List and select the built-in Stack components:
300
326
 
301
327
  ```bash
302
328
  genesis stack list
303
- genesis stack add jskit jskit-mysql
329
+ genesis stack add jskit jskit-mysql # or jskit-postgresql
304
330
  ```
305
331
 
306
332
  `genesis/stack.md` records component ids and optional project verification
307
333
  commands. Selecting no components is valid. Built-in components include the
308
- eleven common language families listed above, plus Vue, MySQL, JSKIT, and JSKIT
309
- with MySQL. Components may contribute:
334
+ eleven common language families listed above, plus Vue, MySQL, PostgreSQL,
335
+ JSKIT, and JSKIT database integrations. Components may contribute:
310
336
 
311
337
  - a concise description and supplemental Guidance used across relevant tasks;
312
338
  - one authoritative Agent Skill directory when the component owns one;
@@ -321,7 +347,7 @@ cleanup tasks; `Deslop` adds cleanup-only rules. Neither shadows an official
321
347
  generic technology skill nor assumes that an upstream skill contains every rule
322
348
  Genesis needs.
323
349
 
324
- Genesis core contains no MySQL, JSKIT, Vue, Laravel, or other platform-specific
350
+ Genesis core contains no database, framework, language, or platform-specific
325
351
  controller behavior. See [Stack components](docs/stack-components.md).
326
352
 
327
353
  ## Verification
@@ -332,8 +358,11 @@ Run the Stack's declared checks explicitly:
332
358
  genesis verify
333
359
  ```
334
360
 
335
- Genesis first evaluates generic Stack resource declarations, then runs each
336
- declared command without a shell. A complete successful run writes only
361
+ Genesis first waits for any technology-declared Workspace setup marker. A
362
+ missing marker is `unconfigured`, not a failed command. Once the workspace
363
+ exists, Genesis applies public Stack defaults beneath explicit environment
364
+ values, evaluates generic resource declarations, and runs each declared
365
+ command without a shell. A complete successful run writes only
337
366
  `.genesis/verification.json`, recording:
338
367
 
339
368
  - the exact Git-visible code hash;
@@ -413,10 +442,10 @@ to execute with its own pinned runtimes, caches, process isolation, and
413
442
  credentials. A configured recipe may remain unconfigured while it waits for a
414
443
  technology-declared project marker.
415
444
  `inspectEnvironment()` returns normalized Stack resource declarations,
416
- value-free missing-input diagnostics, and dotenv projection paths without
417
- returning any environment value.
445
+ public non-secret defaults, value-free missing-input diagnostics, and dotenv
446
+ projection paths without returning any supplied environment value.
418
447
  `inspectLaunch()` returns a validated, normalized Stack launch declaration for
419
- a host to execute with its own runtime, port, process, readiness, preview
448
+ a host to execute with its own runtime, port, process, readiness probe, preview
420
449
  identity, secret, and browser policy.
421
450
 
422
451
  A host such as Vibe64 can send the generated prompt to its existing agent:
@@ -29,6 +29,7 @@ What this component contributes.
29
29
  ```json genesis-resource
30
30
  {
31
31
  "id": "service",
32
+ "kind": "example-service",
32
33
  "environmentAlternatives": [
33
34
  { "required": ["SERVICE_URL"] },
34
35
  { "required": ["SERVICE_HOST", "SERVICE_PORT"] }
@@ -36,6 +37,10 @@ What this component contributes.
36
37
  }
37
38
  ```
38
39
 
40
+ ## Environment defaults
41
+
42
+ - Default `EXAMPLE_DRIVER`: `example`
43
+
39
44
  ## Guidance
40
45
 
41
46
  ### Technology-specific behavior
@@ -68,6 +73,7 @@ What this component contributes.
68
73
  - Workdir: `.`
69
74
  - Preferred port: `3000`
70
75
  - URL path: `/`
76
+ - Ready when: `GET` `/api/health` returns `200`
71
77
  - Runtimes: `nodejs`
72
78
  - Prepare `Build`: `npm` `run` `build`
73
79
  - Serve `Start`: `npm` `run` `server` `--` `--host` `{host}` `--port` `{port}`
@@ -92,7 +98,9 @@ from Genesis or from the declared npm package. Its `SKILL.md`, `references/`,
92
98
  Genesis expanding every manual into every prompt. `Resources` declares generic
93
99
  alternative environment-name sets reported by prompt generation and checked
94
100
  before verification. `allowEmpty` may name a required variable whose empty
95
- string is valid. `Guidance` is supplemental prose used by work, review, Program,
101
+ string is valid. `Environment defaults` declares public non-secret constants
102
+ owned by a concrete integration; explicit host values take precedence.
103
+ `Guidance` is supplemental prose used by work, review, Program,
96
104
  description, and cleanup prompts, as well as path-focused context. `Deslop`
97
105
  adds cleanup-only prose to explicit cleanup and the automatic Codex cleanup
98
106
  continuation. With no selected component, only the `genesis-deslop` skill
@@ -131,6 +139,16 @@ Precedence is intentionally small and deterministic:
131
139
  General Stack resources do not gate Workspace setup. In particular, missing
132
140
  database variables do not prevent an otherwise independent dependency install.
133
141
 
142
+ Each `Environment defaults` entry is one `Default` bullet with a backticked
143
+ environment name and value. Selected
144
+ component defaults compose by name; identical declarations collapse and
145
+ different values fail rather than silently choosing one. Defaults participate
146
+ in Stack identity, resource preflight, prompt context, Launch inspection, and
147
+ verification execution. The JSKIT database integrations use this contract for
148
+ their deterministic `DB_CLIENT` driver ids; generic database pieces do not.
149
+ Secrets and deployment-specific connection values remain host inputs and must
150
+ never be declared as defaults.
151
+
134
152
  `Environment files` optionally declares project-relative dotenv projections a
135
153
  host may materialize from its own resolved project environment. Genesis
136
154
  validates and returns only the format and path; it never reads environment
@@ -144,8 +162,9 @@ The declaration is useful independently of Launch and Workspace setup.
144
162
  offer a preview without guessing how a concrete technology starts. Repeat a
145
163
  ``### Target `id`: label`` block to declare several targets. Default, Workdir,
146
164
  Preferred port, URL path, and Runtimes are optional; their normalized defaults
147
- are false, `.`, null, `/`, and no runtime requirements. Every Prepare or Serve
148
- command and argument is a separate backticked value returned as an `argv`
165
+ are false, `.`, null, `/`, and no runtime requirements. Every target declares
166
+ one HTTP readiness predicate with a project path and an exact successful status
167
+ from 200 through 399. Every Prepare or Serve command and argument is a separate backticked value returned as an `argv`
149
168
  array, never a shell program. A target has exactly one final Serve step; any
150
169
  earlier steps must be Prepare steps. Workdir is canonical and project-relative,
151
170
  Preferred port is only a hint from 1024 through 65535, and URL path is an
@@ -154,7 +173,8 @@ application path rather than a URL. The only substitutions are `{host}` and
154
173
  Launch section to disable component targets.
155
174
 
156
175
  Genesis validates and reports Launch data but does not select a runtime,
157
- reserve a port, start a process, decide readiness, or control a browser.
176
+ reserve a port, start a process, probe readiness, or control a browser. The host
177
+ executes the declared predicate and owns its timeout and retry policy.
158
178
 
159
179
  The optional `#### Preview identity` block is specific to hosts that implement
160
180
  the declared `vibe64.preview-identity.command.v1` protocol. Its executable is a
@@ -175,7 +195,41 @@ the ids it supports to its own pinned runtime packs; for example, it may map
175
195
  dependencies such as `composer`, or treats an unknown id as something similar.
176
196
  Declare each independently required runtime. Generic language pieces such as
177
197
  `nodejs` and `php` provide no Launch recipe. A concrete piece such as `jskit`
178
- may declare one; Genesis does not invent missing targets.
198
+ may declare its app-owned `npm run develop` command; Genesis does not invent
199
+ missing targets or supervise framework-specific subprocesses.
200
+
201
+ `Deployment` is a separate optional readable production recipe. It must not be
202
+ inferred from Launch because preview preparation and production publication have
203
+ different safety, dependency, migration, artifact, and rollback concerns. Its
204
+ complete form is:
205
+
206
+ ```markdown
207
+ ## Deployment
208
+
209
+ - Workdir: `.`
210
+ - Runtimes: `nodejs`
211
+ - Ready when: `GET` `/api/health` returns `200`
212
+ - Prepare `Install production dependencies`: `npm` `install` `--omit=dev`
213
+ - Build `Build`: `npm` `run` `build`
214
+ - Migrate `Prepare database`: `npm` `run` `db:prepare`
215
+ - Serve `Start`: `npm` `start`
216
+ ```
217
+
218
+ Every command and argument is a separate backticked value returned as an argv
219
+ array; shell source is rejected. Workdir is canonical and project-relative.
220
+ Prepare, Build, and Migrate steps are optional and retain their declared order.
221
+ There is exactly one final Serve step and one exact HTTP readiness predicate
222
+ whose successful status is from 200 through 399. Runtime ids remain abstract.
223
+
224
+ A project `## Deployment` section replaces every component recipe as one unit,
225
+ including with `- Nothing.`. Without a project section, exactly one selected
226
+ component recipe may apply; several are blocked as ambiguous and never merged.
227
+ Genesis returns the Stack's existing resource declarations with the recipe but
228
+ does not check production values, provision services, execute commands, package
229
+ artifacts, start processes, probe health, route traffic, manage TLS, or retain
230
+ releases. Those are host responsibilities. This keeps the same project portable:
231
+ Genesis alone explains the production requirements, while a host such as Vibe64
232
+ Online can map `mysql` or `postgresql` to a pinned managed service.
179
233
 
180
234
  `Indexers` selects installed structural adapters for the derived Machine City.
181
235
  The shared ast-grep engine owns traversal, bounds, diagnostics, JSON, and
@@ -229,7 +283,7 @@ Replacement component description.
229
283
  Each field is optional. `Override` replaces only that installed field; `Add`
230
284
  then follows the installed or overridden value. These files cannot alter
231
285
  dependencies, conflicts, Agent Skill source, indexers, resources, environment
232
- files, commands, Workspace setup, or Launch declarations.
286
+ defaults, environment files, commands, Workspace setup, or Launch declarations.
233
287
  `genesis stack add` preserves the files and composes their effective prose after
234
288
  dependency resolution.
235
289
 
@@ -247,8 +301,8 @@ rather than a prompt or controller special case.
247
301
  Description, Guidance, Agent Skill, and Deslop prose are instructions, not
248
302
  verification evidence. Changes to them do not stale an exact successful
249
303
  verification record; selected component ids, resources, environment files,
250
- Workspace setup, launch targets, and verification commands remain part of the
251
- Stack identity.
304
+ environment defaults, Workspace setup, launch targets, and verification
305
+ commands remain part of the Stack identity.
252
306
 
253
307
  Hosts inspect normalized environment requirements independently:
254
308
 
@@ -259,9 +313,10 @@ const projectEnvironment = await inspectEnvironment({ environment, projectRoot }
259
313
  ```
260
314
 
261
315
  The result has `status` (`ready`, `missing-inputs`, or `unconfigured`),
262
- `stackHash`, selected `components`, declared `resources`, value-free
263
- `diagnostics`, and normalized `files`. Each file contains `format`, `path`, and
264
- `source`. Environment values never cross this API boundary.
316
+ `stackHash`, selected `components`, public non-secret `environmentDefaults`,
317
+ declared `resources`, value-free `diagnostics`, and normalized `files`. Each default has
318
+ `name`, `value`, and component `sources`; each file contains `format`, `path`,
319
+ and `source`. Supplied environment values never cross this API boundary.
265
320
 
266
321
  Fresh-workspace hosts read setup from the package root:
267
322
 
@@ -291,11 +346,12 @@ const launch = await inspectLaunch({ projectRoot, environment });
291
346
  ```
292
347
 
293
348
  The result has `status` (`ready`, `blocked`, or `unconfigured`), `stackHash`,
294
- selected `components`, distinct `runtimeRequirements`, declared `resources`,
349
+ selected `components`, public `environmentDefaults`, distinct
350
+ `runtimeRequirements`, declared `resources`,
295
351
  normalized `targets`, and resource `diagnostics`. Each target reports its
296
352
  `source`, `available`, and `disabledReason`, plus its normalized
297
- `previewIdentity` declaration when present. Environment values are inspected
298
- but never returned. Here, `available` means only that the Stack's declared
353
+ `previewIdentity` declaration when present. Supplied environment values are
354
+ inspected but never returned. Here, `available` means only that the Stack's declared
299
355
  resource inputs are present: the host must still reject runtime requirements it
300
356
  cannot map. `unconfigured` means there are no targets, `blocked` means declared
301
357
  resource inputs are missing, and `ready` means neither condition applies. The
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genesis-compiler",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
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": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genesis",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "description": "Makes Codex aware of optional Genesis adoption for existing projects.",
5
5
  "author": {
6
6
  "name": "Mobily Enterprises"
package/prompts/start.txt CHANGED
@@ -13,6 +13,11 @@ the non-technical Blueprint from the user's answers before implementation.
13
13
  If the product direction becomes clear while Stack is still empty, do not end
14
14
  the turn after only writing or summarizing the Blueprint: present the relevant
15
15
  Stack choices in that same turn and ask the user to select one explicitly.
16
+ This opening turn owns product direction and Stack selection, not final
17
+ verification. Do not run `genesis verify` before implementation has created
18
+ the selected technology's workspace substrate. If structural validation is
19
+ useful, run `genesis check`; treat missing workspace markers as unconfigured,
20
+ not as an implementation failure.
16
21
 
17
22
  When `projectKind` is `existing`, ask what the user wants to understand or
18
23
  change. Use the current Blueprint, Stack, Program, and code index when present.
@@ -48,6 +48,9 @@ Neither is authority or proof; both may be regenerated with `genesis index`.
48
48
 
49
49
  ## Verify and report
50
50
 
51
- Use `genesis verify` for the Stack's declared final checks. Report files
52
- changed, checks actually run, and anything still requiring attention. Never
53
- claim that an unrun check passed or that passing checks prove the whole product.
51
+ After the selected technology's workspace substrate exists, use `genesis
52
+ verify` for the Stack's declared final checks. An unconfigured result means the
53
+ declared workspace or checks do not exist yet; it is not a failing check. Report
54
+ files changed, checks actually run, and anything still requiring attention.
55
+ Never claim that an unrun check passed or that passing checks prove the whole
56
+ product.
@@ -6,6 +6,7 @@ import { gitContext } from './git.js';
6
6
  import { inspectProgram } from './program.js';
7
7
  import { inspectVerification } from './project-state.js';
8
8
  import { missingStackResources } from './stack-preflight.js';
9
+ import { withStackEnvironmentDefaults } from './stack-environment-defaults.js';
9
10
 
10
11
  function invalidResult(area, error) {
11
12
  return {
@@ -55,7 +56,10 @@ export async function checkProject({ environment = process.env, projectRoot } =
55
56
  } catch (error) {
56
57
  skills = { status: 'invalid', diagnostics: [asDiagnostic(error)], skills: [] };
57
58
  }
58
- const missingResources = missingStackResources({ environment, resources: stack.resources });
59
+ const missingResources = missingStackResources({
60
+ environment: withStackEnvironmentDefaults(environment, stack.environmentDefaults),
61
+ resources: stack.resources,
62
+ });
59
63
  const verification = await inspectVerification({ projectRoot: root, stack });
60
64
  const diagnostics = [
61
65
  ...(program.diagnostic ? [program.diagnostic] : []),
@@ -0,0 +1,31 @@
1
+ import { gitContext } from './git.js';
2
+ import { readStack } from './stack.js';
3
+ import { sha256, stableJson, uniqueSorted } from './utils.js';
4
+
5
+ /** Read the Stack's production recipe without provisioning or publishing anything. */
6
+ export async function inspectProjectDeployment({ projectRoot } = {}) {
7
+ const root = (await gitContext(projectRoot)).repositoryRoot;
8
+ const stack = await readStack(root);
9
+ const diagnostics = [...stack.deployment.diagnostics];
10
+ let status = 'unconfigured';
11
+ if (diagnostics.length > 0) status = 'blocked';
12
+ else if (stack.deployment.steps.length > 0) status = 'ready';
13
+ const recipe = {
14
+ version: stack.deployment.version,
15
+ workdir: stack.deployment.workdir,
16
+ runtimeRequirements: stack.deployment.runtimeRequirements,
17
+ readiness: stack.deployment.readiness,
18
+ steps: stack.deployment.steps,
19
+ };
20
+ return {
21
+ status,
22
+ stackHash: stack.identityHash,
23
+ recipeHash: status === 'ready' ? sha256(stableJson(recipe)) : '',
24
+ components: stack.components.map(({ id }) => id),
25
+ source: stack.deployment.source,
26
+ runtimeRequirements: uniqueSorted(stack.deployment.runtimeRequirements),
27
+ resources: stack.resources,
28
+ ...recipe,
29
+ diagnostics,
30
+ };
31
+ }
@@ -1,17 +1,24 @@
1
1
  import { gitContext } from './git.js';
2
2
  import { readStack } from './stack.js';
3
+ import { withStackEnvironmentDefaults } from './stack-environment-defaults.js';
3
4
  import { missingStackResources } from './stack-preflight.js';
4
5
 
5
- /** Inspect Stack environment requirements without returning or writing values. */
6
+ /** Inspect Stack environment requirements without returning supplied host values. */
6
7
  export async function inspectProjectEnvironment({ environment = process.env, projectRoot } = {}) {
7
8
  const root = (await gitContext(projectRoot)).repositoryRoot;
8
9
  const stack = await readStack(root);
9
- const diagnostics = missingStackResources({ environment, resources: stack.resources });
10
- const configured = stack.environmentFiles.length > 0 || stack.resources.length > 0;
10
+ const diagnostics = missingStackResources({
11
+ environment: withStackEnvironmentDefaults(environment, stack.environmentDefaults),
12
+ resources: stack.resources,
13
+ });
14
+ const configured = stack.environmentDefaults.length > 0
15
+ || stack.environmentFiles.length > 0
16
+ || stack.resources.length > 0;
11
17
  return {
12
18
  status: !configured ? 'unconfigured' : diagnostics.length > 0 ? 'missing-inputs' : 'ready',
13
19
  stackHash: stack.identityHash,
14
20
  components: stack.components.map(({ id }) => id),
21
+ environmentDefaults: stack.environmentDefaults,
15
22
  files: stack.environmentFiles,
16
23
  resources: stack.resources,
17
24
  diagnostics,
@@ -1,5 +1,6 @@
1
1
  import { gitContext } from './git.js';
2
2
  import { missingStackResources } from './stack-preflight.js';
3
+ import { withStackEnvironmentDefaults } from './stack-environment-defaults.js';
3
4
  import { readStack } from './stack.js';
4
5
  import { uniqueSorted } from './utils.js';
5
6
 
@@ -10,7 +11,10 @@ export async function inspectProjectLaunch({
10
11
  } = {}) {
11
12
  const root = (await gitContext(projectRoot)).repositoryRoot;
12
13
  const stack = await readStack(root);
13
- const diagnostics = missingStackResources({ environment, resources: stack.resources });
14
+ const diagnostics = missingStackResources({
15
+ environment: withStackEnvironmentDefaults(environment, stack.environmentDefaults),
16
+ resources: stack.resources,
17
+ });
14
18
  const disabledReason = diagnostics.length === 0
15
19
  ? null
16
20
  : diagnostics.map(({ message }) => message).join(' ');
@@ -26,6 +30,7 @@ export async function inspectProjectLaunch({
26
30
  status,
27
31
  stackHash: stack.identityHash,
28
32
  components: stack.components.map(({ id }) => id),
33
+ environmentDefaults: stack.environmentDefaults,
29
34
  runtimeRequirements: uniqueSorted(targets.flatMap((target) => target.runtimeRequirements)),
30
35
  resources: stack.resources,
31
36
  targets,
@@ -9,6 +9,7 @@ import { gitContext } from './git.js';
9
9
  import { inspectProgram } from './program.js';
10
10
  import { inspectVerification } from './project-state.js';
11
11
  import { missingStackResources } from './stack-preflight.js';
12
+ import { withStackEnvironmentDefaults } from './stack-environment-defaults.js';
12
13
  import { stableJson } from './utils.js';
13
14
  import { gitVisibleFileStates } from './project-files.js';
14
15
  import { isProjectContentPath } from './paths.js';
@@ -305,7 +306,10 @@ export async function generateProjectPrompt({
305
306
  buildProjectIndex({ projectRoot: root, write: false }),
306
307
  inspectProjectSkills({ projectRoot: root, stack }),
307
308
  ]);
308
- const missing = missingStackResources({ environment, resources: stack.resources });
309
+ const missing = missingStackResources({
310
+ environment: withStackEnvironmentDefaults(environment, stack.environmentDefaults),
311
+ resources: stack.resources,
312
+ });
309
313
  const warnings = [
310
314
  ...(program.diagnostic ? [program.diagnostic] : []),
311
315
  ...missing,
@@ -64,6 +64,7 @@ export async function listBuiltinStackPieces() {
64
64
  requires: piece.requires,
65
65
  conflicts: piece.conflicts,
66
66
  indexers: piece.indexers,
67
+ environmentDefaults: piece.environmentDefaults,
67
68
  launchTargets: piece.launchTargets.map(({ id }) => id),
68
69
  workspaceSetup: piece.workspaceSetupSteps,
69
70
  skill: piece.skill === null ? null : piece.skill.path,