genesis-compiler 1.2.26 → 1.2.28

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.
@@ -46,7 +46,26 @@ Concise technology context.
46
46
 
47
47
  ## Resources
48
48
 
49
- - Resource `database` kind `postgresql`: `DATABASE_URL` OR `DB_HOST` + `DB_NAME`
49
+ ```json genesis-resource
50
+ {
51
+ "id": "database",
52
+ "kind": "postgresql",
53
+ "environmentAlternatives": [
54
+ {
55
+ "bindings": {
56
+ "database": "DB_NAME",
57
+ "host": "DB_HOST",
58
+ "password": "DB_PASSWORD",
59
+ "port": "DB_PORT",
60
+ "username": "DB_USER"
61
+ },
62
+ "allowEmpty": ["password"],
63
+ "preferred": true
64
+ },
65
+ { "bindings": { "url": "DATABASE_URL" } }
66
+ ]
67
+ }
68
+ ```
50
69
 
51
70
  ## Environment defaults
52
71
 
@@ -92,24 +111,27 @@ complete authoritative Agent Skill directory. `Indexers` selects installed
92
111
  structural adapters.
93
112
  `Resources`, `Environment defaults`, `Environment files`, and `Verification`
94
113
  use the small Genesis grammars documented below. Every other `##` section is an
95
- opaque extension.
114
+ opaque extension. These component sections are initial proposals. They do not
115
+ remain a hidden runtime layer beneath the project.
96
116
 
97
117
  ## Genesis-owned declarations
98
118
 
99
119
  Resources describe required external inputs as alternatives of environment
100
120
  variable names. Genesis can report which names are absent, but never reads a
101
- service, provisions infrastructure, or returns a supplied value. A project
102
- `## Resources` section replaces all component resource defaults.
121
+ service, provisions infrastructure, or returns a supplied value. Selection
122
+ materializes the composed proposal into the project's `## Resources` section.
103
123
 
104
- Environment defaults are public, non-secret constants. Component defaults
124
+ Environment defaults are public, non-secret constants. Component proposals
105
125
  compose by variable name; identical values collapse and conflicting values
106
- fail. A project `## Environment defaults` section replaces component defaults.
107
- Explicit process values always win.
126
+ fail. Selection writes the result into the project's `## Environment defaults`
127
+ section. Explicit process values always win. Conventional host, port, driver,
128
+ database, or username values may be proposed; passwords, tokens, and other
129
+ secrets must not be invented.
108
130
 
109
131
  Environment files describe safe project-relative dotenv projection paths.
110
132
  Genesis returns only the format and path. It does not materialize the file,
111
- choose which values belong there, or store secrets. A project declaration
112
- replaces component declarations; otherwise paths compose.
133
+ choose which values belong there, or store secrets. Component paths compose
134
+ during selection and are then written as the project declaration.
113
135
 
114
136
  Verification contains exact argv tokens:
115
137
 
@@ -122,8 +144,9 @@ Verification contains exact argv tokens:
122
144
 
123
145
  Genesis is the consumer of this section. `genesis verify` runs the declared
124
146
  commands directly without a shell after generic resource preflight and records
125
- the exact successful code, Stack, and command hashes. A project Verification
126
- section replaces component defaults.
147
+ the exact successful code, Stack, and command hashes. Selection writes proposed
148
+ commands into the project Verification section; only that project section is
149
+ executed afterward.
127
150
 
128
151
  ## Opaque extensions
129
152
 
@@ -131,12 +154,16 @@ Any other `##` heading is consumer-owned data. Genesis validates only the
131
154
  section name and composition. It does not parse the body, infer its purpose,
132
155
  validate a private schema, map runtimes, execute commands, or prove success.
133
156
 
134
- Composition is intentionally small:
157
+ Proposal composition is intentionally small:
158
+
159
+ 1. An existing project section remains authoritative and is never overwritten.
160
+ 2. Without a project section, one component proposal is copied unchanged.
161
+ 3. Competing component proposals produce `STACK_SECTION_AMBIGUOUS`; Genesis
162
+ never merges their bodies or guesses a winner.
135
163
 
136
- 1. A project section replaces component declarations with the same name.
137
- 2. Without a project section, one component declaration is returned unchanged.
138
- 3. Competing component declarations produce `STACK_SECTION_AMBIGUOUS`; Genesis
139
- never merges their bodies.
164
+ After selection every effective opaque section is project-owned. The component
165
+ catalog may improve later without silently changing the application's setup,
166
+ launch, deployment, packaging, signing, migration, or any other operation.
140
167
 
141
168
  Call `inspectStackSection({ name, projectRoot })` or:
142
169
 
@@ -152,12 +179,18 @@ firmware, desktop software, and future systems Genesis has never seen.
152
179
 
153
180
  ## Selection and identity
154
181
 
155
- `genesis stack add` records selected packages and component dependency closure
156
- without discarding project declarations. Stack identity includes component ids,
157
- resources, environment declarations, Verification commands, City presentation,
158
- and every opaque extension body. Changing any executable or consumer-owned
159
- contract therefore stales prior Genesis verification evidence even though
160
- Genesis does not interpret the extension.
182
+ `genesis stack add` records selected packages and component dependency closure,
183
+ materializes every missing operation proposal, and preserves existing project
184
+ declarations. It then returns one preparation prompt containing every exact
185
+ project contract heading and body. The current agent must make the source and
186
+ commands satisfy those contracts or replace a complete section with evidenced
187
+ reality. Repeating an already-complete selection is quiet.
188
+
189
+ Stack identity includes component ids, project-owned resources, environment
190
+ declarations, Verification commands, City presentation, and every opaque
191
+ extension body. Changing any executable or consumer-owned contract therefore
192
+ stales prior Genesis verification evidence even though Genesis does not
193
+ interpret the extension.
161
194
 
162
195
  Prose and Agent Skill contents are instructions rather than verification
163
196
  evidence. Changes to Description, Guidance, Adoption, Post-change, Deslop, or
@@ -212,7 +245,16 @@ const operation = await inspectStackSection({
212
245
  });
213
246
  ```
214
247
 
215
- `inspectEnvironment()` uses `genesis.environment.v1` and never returns supplied
248
+ `inspectEnvironment()` uses `genesis.environment.v2` and never returns supplied
216
249
  values. `inspectStackSection()` uses `genesis.stack-section.v1` and never
217
250
  interprets the section. There is no generic Genesis API that executes an opaque
218
251
  operation.
252
+
253
+ ## Project format migration
254
+
255
+ Project format 2 removes runtime inheritance of operation declarations from
256
+ the catalog. `genesis migrate` upgrades format 1 projects by composing the
257
+ previously effective declarations once and writing them into
258
+ `genesis/stack.md`. Existing project sections win exactly as they did before.
259
+ Current-format reads reject a selected component whose required contract was
260
+ not materialized, so a tool upgrade cannot quietly substitute a new proposal.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genesis-compiler",
3
- "version": "1.2.26",
3
+ "version": "1.2.28",
4
4
  "type": "module",
5
5
  "description": "An agent-independent prompt, multi-language code-index, cleanup, and verification companion with project agent guidance.",
6
6
  "repository": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genesis",
3
- "version": "1.2.26",
3
+ "version": "1.2.28",
4
4
  "description": "Makes Codex aware of optional Genesis adoption for existing projects.",
5
5
  "author": {
6
6
  "name": "Mobily Enterprises"
@@ -50,8 +50,7 @@ export const GenesisProjectGuidance = async ({ directory, worktree } = {}) => {
50
50
  const sessionId = String(input.sessionID || input.sessionId || "").trim();
51
51
  if (!sessionId) return;
52
52
  const context = await contextForSession(sessionId);
53
- const system = Array.isArray(output.system) ? output.system : [];
54
- if (!system.includes(context)) output.system = [...system, context];
53
+ if (!output.system.includes(context)) output.system.push(context);
55
54
  }
56
55
  };
57
56
  };
package/prompts/adopt.txt CHANGED
@@ -26,8 +26,9 @@ Adoption requirements.
26
26
 
27
27
  Read every selected technology skill named by the regenerated prompt and its
28
28
  relevant existing-application migration reference. Apply all SELECTED STACK
29
- ADOPTION GUIDANCE. Component defaults describe current foundations and are
30
- hypotheses until they match this source. They do not upgrade an older project.
29
+ ADOPTION GUIDANCE. Materialized component proposals describe current
30
+ foundations and remain hypotheses until they match this source. They do not
31
+ upgrade an older project.
31
32
 
32
33
  Build one evidence-backed import inventory covering the selected technologies,
33
34
  public environment/resource declarations, concrete Verification commands, and
@@ -36,8 +37,8 @@ selected technology skill and the section's declared schema for any
36
37
  consumer-specific detail; do not invent a generic operational grammar.
37
38
 
38
39
  Translate observed contracts into exact project-owned Stack sections whenever
39
- the selected components' defaults differ. A project section replaces the
40
- component declaration for that concern, so it must be complete. Inspect retired
40
+ a materialized proposal differs. Replace the complete section for that concern;
41
+ do not leave a proposal that the implementation cannot perform. Inspect retired
41
42
  or tool-specific manifests as evidence and carry every still-valid fact into
42
43
  Genesis; never add a permanent legacy reader or shim. Do not delete an old
43
44
  manifest until all of its live facts have been accounted for.
@@ -1,4 +1,6 @@
1
- Read and follow `.agents/skills/genesis-deslop/SKILL.md` completely.
1
+ This Deslop task has already been rendered by Genesis. Do not generate another
2
+ Deslop prompt. Read and follow `.agents/skills/genesis-deslop/SKILL.md`
3
+ completely.
2
4
 
3
5
  This is an explicitly requested behavior-preserving cleanup of committed work.
4
6
  Resolve the commit or first-parent commit range from USER REQUEST exactly; when
package/prompts/start.txt CHANGED
@@ -1,15 +1,37 @@
1
1
  Read and follow `.agents/skills/genesis-project/SKILL.md` completely.
2
2
 
3
- This is the project-opening conversation. Do not begin implementation until
4
- the product direction and any technology choice needed for the first useful
5
- step are clear.
3
+ This is the project-opening conversation. For a new project, do not begin
4
+ technology research or create source until the user has made clear what is
5
+ being built, who or what will use or invoke it, and the first observable useful
6
+ outcome. Ask only unresolved high-impact questions. A reply confirms only what
7
+ it explicitly answers; Stack confirmation is not product intent.
6
8
 
7
- When `projectKind` is `new`, first ask what the app is about. Ask up to three
8
- concise, high-impact questions at a time. Use `availableStackPieces` to present
9
- only the relevant choices, explain them in product language, and let the user
10
- decide. Never silently select a technology. After an explicit choice, use the
11
- Genesis `stack add <piece...>` operation; do not edit `genesis/stack.md` by
12
- hand. Establish the non-technical Blueprint from the user's answers before
9
+ When the user explicitly names a technology, framework, language, or database
10
+ that is not selected, make the existing Genesis `stack list` operation the
11
+ first technology action. If one catalog component exactly matches that choice,
12
+ ask: "<Technology> is available in Genesis. Would you like me to add it to this
13
+ project and prepare the app with its official guidance?" Do not run `stack add
14
+ <piece...>` without that confirmation. If confirmed, add it, let Genesis apply
15
+ its declared dependency closure and synchronize any skill the component
16
+ declares. Follow the preparation prompt returned by `stack add` in this same
17
+ task: make each materialized project contract true or replace a complete
18
+ section with evidenced reality. Then run `context .` (or the relevant source
19
+ path once source exists), load the applicable installed skill if present, and
20
+ follow the technology-owned guidance to prepare actual project dependencies.
21
+ Never infer an install command from a component id. If declined, continue
22
+ without adding it or asking again.
23
+ If no component matches, do not invent one; continue normally using
24
+ authoritative technology documentation.
25
+
26
+ When `projectKind` is `new`, establish what is being built, who or what will use
27
+ or invoke it, and its first observable useful outcome. Ask up to three concise,
28
+ high-impact questions at a time, and ask access, data, platform, or interface
29
+ questions only when they are material to that product. Use
30
+ `availableStackPieces` to present only the relevant choices, explain them in
31
+ product language, and let the user decide. Never silently select a technology.
32
+ After the user confirms the proposed component selection, use the Genesis
33
+ `stack add <piece...>` operation; do not edit `genesis/stack.md` by hand.
34
+ Establish the non-technical Blueprint from the user's answers before
13
35
  implementation.
14
36
  If the product direction becomes clear while Stack is still empty, do not end
15
37
  the turn after only writing or summarizing the Blueprint: present the relevant
@@ -35,13 +57,13 @@ If the existing implementation is not yet explained, recommend the Genesis
35
57
  description/adoption path instead of pretending its intent is known.
36
58
  When an existing implementation has no selected Stack yet, inspect its actual
37
59
  package scripts, build files, setup commands, server entrypoint, and readiness
38
- route before recording the user's technology choice. Consumer-owned sections
39
- declared by a component describe that component's current operational
40
- foundation; selecting the component does not port an older implementation to
41
- it. If the existing facts differ, add exact project-owned replacements using
42
- the consumer's current schema and the code that exists. Never report an
43
- inherited operation as usable merely because the component was selected, and
44
- never add compatibility implementation without the user asking for a port.
60
+ route before recording the user's technology choice. Materialized component
61
+ proposals describe that component's current operational foundation; selecting
62
+ the component does not port an older implementation to it. If the existing
63
+ facts differ, replace the complete project-owned section using the consumer's
64
+ current schema and the code that exists. Never report a proposed operation as
65
+ usable merely because the component was selected, and never add compatibility
66
+ implementation without the user asking for a port.
45
67
 
46
68
  When `projectKind` is `existing-uninitialized`, ask what the user wants to
47
69
  understand or change and strongly recommend preparing the existing project for
@@ -53,5 +75,13 @@ operation yourself and follow its adoption prompt. If they decline, continue
53
75
  normally and do not repeat the recommendation.
54
76
 
55
77
  If the request already contains an unambiguous product description and an
56
- explicit Stack choice, you may apply that choice and establish the Blueprint.
57
- Otherwise this is a conversational turn: ask, listen, and preserve the source.
78
+ explicit Stack choice, establish the Blueprint and ask for the component
79
+ confirmation described above before applying that choice. Otherwise this is a
80
+ conversational turn: ask, listen, and preserve the source.
81
+
82
+ Once product direction and any relevant Stack selection are clear, choose one
83
+ smallest implementation path through the applicable technology guidance, or
84
+ authoritative technology documentation when the catalog has no match, and read
85
+ only what that path requires. Do not survey alternative foundations, clone
86
+ whole technology repositories, inspect unrelated package internals, or
87
+ delegate research unless one concrete failure requires one exact investigation.
package/prompts/work.txt CHANGED
@@ -3,7 +3,12 @@ implement the request in the ordinary local Git tree.
3
3
 
4
4
  Load the applicable official or project technology skills listed below. Use
5
5
  their normal generators, commands, packages, and established seams. Do not
6
- search package internals or unrelated manuals merely to reconfirm an exact lane.
6
+ turn technology choices into another product questionnaire. Choose one smallest
7
+ implementation path through selected guidance, or authoritative technology
8
+ documentation when the catalog has no match, and read only what that path
9
+ requires. Do not survey alternative foundations, clone whole technology
10
+ repositories, inspect unrelated package internals, or delegate research unless
11
+ one concrete failure requires one exact investigation.
7
12
  Before adding a helper or public operation, query the Genesis
8
13
  `index <name-or-path>` operation and reuse an existing function when it already
9
14
  owns the behavior.
@@ -20,8 +25,11 @@ a genuinely missing resource instead of constructing a parallel fallback.
20
25
 
21
26
  Apply any supplied Stack Post-change guidance before reporting completion. It
22
27
  belongs to this implementation turn and does not request a follow-up agent turn.
23
- Run focused checks when useful. Summarize files changed, checks actually run,
24
- and anything still requiring attention.
28
+ Run focused checks when useful. Before reporting completion, compare the
29
+ requested observable behavior, required inputs and resources, declared project
30
+ operations, and focused evidence with what actually exists. Summarize
31
+ files changed, checks actually run, anything not proven, and anything still
32
+ requiring attention.
25
33
 
26
34
  If no Stack components are selected, continue the project-opening
27
35
  conversation instead of guessing a technology. Use the Genesis `stack list`
@@ -15,6 +15,23 @@ package. Otherwise use `genesis <arguments>` only when that executable is
15
15
  already available on `PATH`. Never install or update Genesis merely to satisfy
16
16
  a workflow instruction.
17
17
 
18
+ ## Load the effective project instructions once
19
+
20
+ A Deslop request may arrive either as a complete Genesis-generated prompt or
21
+ as a direct request such as `Deslop` in an agent session.
22
+
23
+ If the current task already contains `GENESIS CONTEXT` whose task is `deslop`,
24
+ continue with it directly. Do not generate another prompt.
25
+
26
+ Otherwise, before resolving Git scope, run the Genesis
27
+ `prompt --task deslop` operation once using the invocation rule above. For a
28
+ bare `Deslop` request, pass no request argument. When the user names a count,
29
+ commit, or range, pass that exact request as one safely quoted argument. Treat
30
+ the printed prompt as the instructions for this same turn; do not dispatch it
31
+ to another agent and do not generate it again. This step composes the selected
32
+ Stack's technology-specific Deslop guidance and any project customization with
33
+ the portable contract below.
34
+
18
35
  ## Resolve the committed scope
19
36
 
20
37
  Before reading or editing the selected change, require a clean worktree and
@@ -8,6 +8,21 @@ description: Work safely in a Genesis-enriched codebase using its Blueprint, Sta
8
8
  Genesis is an explanatory and verification companion. It does not replace the
9
9
  codebase, tests, Git review, or the coding agent.
10
10
 
11
+ ## Establish new-product direction
12
+
13
+ For a new project whose Blueprint does not yet establish product direction,
14
+ do not research technology or create source until the user has made clear what
15
+ is being built, who or what will use or invoke it, and the first observable
16
+ useful outcome. Ask only unresolved high-impact questions. A reply confirms only
17
+ what it explicitly answers; Stack confirmation is not product intent.
18
+
19
+ Once product direction is clear, choose one smallest implementation path
20
+ through selected technology guidance, or authoritative technology documentation
21
+ when the catalog has no match, and read only what that path requires. Do not
22
+ survey alternatives, clone whole technology repositories, inspect unrelated
23
+ package internals, or delegate research unless one concrete failure requires
24
+ one exact investigation.
25
+
11
26
  ## Run Genesis commands
12
27
 
13
28
  When this repository is Genesis itself or has `genesis-compiler` installed
@@ -17,6 +32,28 @@ package. Otherwise use `genesis <arguments>` only when that executable is
17
32
  already available on `PATH`. Never install or update Genesis merely to satisfy
18
33
  a workflow instruction.
19
34
 
35
+ ## Resolve explicit technology choices
36
+
37
+ Before external technology research or implementation, when the user explicitly
38
+ names a technology, framework, language, or database that is not selected:
39
+
40
+ 1. Run the Genesis `stack list` operation as the first technology action.
41
+ 2. If one catalog component exactly matches the choice, ask: "<Technology> is
42
+ available in Genesis. Would you like me to add it to this project and prepare
43
+ the app with its official guidance?" Do not run `stack add <piece...>`
44
+ without that confirmation.
45
+ 3. If confirmed, add the component, let Genesis apply its declared dependency
46
+ closure and synchronize any authoritative Agent Skill declared by that
47
+ component. Follow the preparation prompt returned by `stack add` in the same
48
+ task: make each materialized project contract true or replace a complete
49
+ section with evidenced reality. Then run `context .`, or the relevant source
50
+ path once source exists, load the applicable installed skill if present, and
51
+ follow that technology-owned guidance to prepare actual project
52
+ dependencies. Never infer an installation command from a component id.
53
+ 4. If declined, continue without adding the component or asking again. If no
54
+ catalog component matches, do not invent one; continue normally using
55
+ authoritative documentation owned by that technology.
56
+
20
57
  ## Establish context
21
58
 
22
59
  1. Read `genesis/blueprint.md` for non-technical product intent.
@@ -34,13 +71,13 @@ a workflow instruction.
34
71
  agent's own installed skill catalog.
35
72
 
36
73
  For an existing application's first Stack selection, inspect its real setup,
37
- build, and output commands before relying on component defaults. A selected
38
- component describes its current foundation; it does not silently port older
39
- source. When the existing commands differ, keep the implementation unchanged
40
- and declare exact project-owned consumer-operation overrides (for Vibe64,
41
- `## Workspace setup` and `## Outputs`). Genesis composes those sections as
74
+ build, and output commands before accepting materialized component proposals.
75
+ A selected component describes its current foundation; it does not silently
76
+ port older source. When the existing commands differ, keep the implementation
77
+ unchanged and replace the complete project-owned consumer operation (for
78
+ Vibe64, `## Workspace setup` or `## Outputs`). Genesis treats those sections as
42
79
  opaque text; the named consumer alone owns their meaning and execution. Do not
43
- claim the inherited component recipe is usable until it matches the source.
80
+ claim a proposed recipe is usable until it matches the source.
44
81
 
45
82
  Program is concise, fallible explanation. Its Sources and optional
46
83
  Implementation maps aid navigation but never substitute for reading code,
@@ -90,6 +127,8 @@ Neither is authority or proof; both may be regenerated with the Genesis
90
127
  After the selected technology's workspace substrate exists, use the Genesis
91
128
  `verify` operation for the Stack's declared final checks. An unconfigured result
92
129
  means the declared workspace or checks do not exist yet; it is not a failing
93
- check. Report files changed, checks actually run, and anything still requiring
94
- attention. Never claim that an unrun check passed or that passing checks prove
95
- the whole product.
130
+ check. Before reporting completion, compare the requested observable behavior,
131
+ required inputs and resources, declared project operations, and focused evidence
132
+ with what actually exists. Report files changed, checks actually run,
133
+ anything not proven, and anything still requiring attention. Never claim that
134
+ an unrun check passed or that passing checks prove the whole product.
package/src/cli.js CHANGED
@@ -29,6 +29,8 @@ import {
29
29
  projectFormatDiagnostic,
30
30
  } from './index/project-format.js';
31
31
  import { projectSessionContext } from './index/session-context.js';
32
+ import { installedFirstPartyStackPackages } from './index/stack-catalog.js';
33
+ import { readStack } from './index/stack.js';
32
34
 
33
35
  const USAGE = `Usage:
34
36
  genesis init
@@ -283,12 +285,27 @@ function writeResult(command, result) {
283
285
  }
284
286
  }
285
287
  if (result.guidance) line(process.stdout, result.guidance);
288
+ if (result.prompt) {
289
+ line(process.stdout, '');
290
+ process.stdout.write(result.prompt.endsWith('\n') ? result.prompt : `${result.prompt}\n`);
291
+ }
286
292
  line(process.stdout, `${command}: ${result.status}`);
287
293
  }
288
294
 
295
+ async function cliStackPackages(projectRoot, supplied) {
296
+ if (supplied.length > 0) return supplied;
297
+ try {
298
+ const stack = await readStack(projectRoot);
299
+ if (stack.stackPackages.length > 0) return [];
300
+ } catch (error) {
301
+ if (error?.code !== 'STACK_REQUIRED') return [];
302
+ }
303
+ return installedFirstPartyStackPackages({ projectRoot });
304
+ }
305
+
289
306
  async function execute({ command, operands, options }, { signal } = {}) {
290
307
  const projectRoot = options.projectRoot || process.cwd();
291
- const stackPackages = options.stackPackages || [];
308
+ const stackPackages = await cliStackPackages(projectRoot, options.stackPackages || []);
292
309
  if (command === 'init') return initialize({ projectRoot, stackPackages });
293
310
  if (command === 'migrate') return migrate({ projectRoot, stackPackages });
294
311
  if (command === 'adopt') {
@@ -362,7 +379,7 @@ async function execute({ command, operands, options }, { signal } = {}) {
362
379
  if (operands[0] === 'discover') {
363
380
  return { kind: 'discover', ...await codexAdoptionRecommendation({ projectRoot }) };
364
381
  }
365
- return { kind: 'session', ...await projectSessionContext({ projectRoot }) };
382
+ return { kind: 'session', ...await projectSessionContext({ projectRoot, stackPackages }) };
366
383
  }
367
384
  if (command === 'verify') {
368
385
  return verify({
@@ -8,6 +8,7 @@ import { runGit } from './process.js';
8
8
  import { normalizeRelative, pathState, writeFileAtomic } from './utils.js';
9
9
 
10
10
  const HOOKS_PATH = '.codex/hooks.json';
11
+ const LEGACY_GENESIS_HOOKS_DESCRIPTION = 'Genesis project hooks.';
11
12
  const PROJECT_HOOK_ACTIONS = ['session', 'begin', 'stop', 'end'];
12
13
 
13
14
  function hookCommand(action) {
@@ -68,7 +69,7 @@ async function installedHooksSource(location) {
68
69
  return { source, value };
69
70
  } catch (error) {
70
71
  if (['ENOENT', 'ENOTDIR'].includes(error?.code)) {
71
- return { source: null, value: { description: 'Genesis project hooks.', hooks: {} } };
72
+ return { source: null, value: { hooks: {} } };
72
73
  }
73
74
  throw new GenesisError('CODEX_HOOKS_INVALID', `${HOOKS_PATH} is not valid hook configuration: ${error.message}.`);
74
75
  }
@@ -78,6 +79,7 @@ export async function installCodexHooks({ projectRoot } = {}) {
78
79
  const root = (await gitContext(projectRoot)).repositoryRoot;
79
80
  const location = path.join(root, HOOKS_PATH);
80
81
  const { source, value } = await installedHooksSource(location);
82
+ if (value.description === LEGACY_GENESIS_HOOKS_DESCRIPTION) delete value.description;
81
83
  value.hooks ||= {};
82
84
  removeGenesisProjectHooks(value.hooks);
83
85
  const groups = value.hooks[SESSION_HOOK.event] ||= [];
@@ -46,6 +46,25 @@ function stackGuidance(stack) {
46
46
  ];
47
47
  }
48
48
 
49
+ function stackContracts(stack) {
50
+ if (stack.projectContracts.length === 0) return [];
51
+ return [
52
+ '',
53
+ '## Project Stack contracts',
54
+ '',
55
+ 'These exact project-owned sections in `genesis/stack.md` are authoritative. Genesis executes only Verification; each other named consumer owns its section.',
56
+ '',
57
+ ...stack.projectContracts.flatMap(({ name, lines }) => [
58
+ `### \`## ${name}\``,
59
+ '',
60
+ '```markdown',
61
+ ...lines,
62
+ '```',
63
+ '',
64
+ ]),
65
+ ];
66
+ }
67
+
49
68
  function pathMatchesTarget(filePath, target) {
50
69
  return !target || filePath === target || filePath.startsWith(`${target}/`);
51
70
  }
@@ -108,6 +127,7 @@ export async function contextForProjectPaths({ paths, projectRoot, stackPackages
108
127
  '',
109
128
  ...stackSummary(stack),
110
129
  ...stackGuidance(stack),
130
+ ...stackContracts(stack),
111
131
  '',
112
132
  '## Existing functions',
113
133
  '',
@@ -11,14 +11,17 @@ import {
11
11
  writeProjectFormatVersion,
12
12
  } from './project-format.js';
13
13
  import { PROJECT_VERSION_PATH } from './paths.js';
14
- import { readStack } from './stack.js';
14
+ import {
15
+ materializeProjectStackContracts,
16
+ readLegacyStack,
17
+ } from './stack.js';
15
18
  import { uniqueSorted } from './utils.js';
16
19
 
17
20
  async function validateLegacyProject({ projectRoot, stackPackages }) {
18
21
  try {
19
22
  await readBlueprint(projectRoot, { required: true });
20
23
  await readEngineering(projectRoot);
21
- await readStack(projectRoot, { stackPackages });
24
+ await readLegacyStack(projectRoot, { stackPackages });
22
25
  try {
23
26
  await inspectProgram(projectRoot);
24
27
  } catch (error) {
@@ -33,8 +36,13 @@ async function validateLegacyProject({ projectRoot, stackPackages }) {
33
36
  }
34
37
  }
35
38
 
39
+ async function materializeProjectContracts({ projectRoot, stackPackages }) {
40
+ return materializeProjectStackContracts({ projectRoot, stackPackages });
41
+ }
42
+
36
43
  const MIGRATIONS = new Map([
37
44
  [0, validateLegacyProject],
45
+ [1, materializeProjectContracts],
38
46
  ]);
39
47
 
40
48
  export async function migrateProject({ projectRoot, stackPackages = [] } = {}) {
@@ -62,7 +70,8 @@ export async function migrateProject({ projectRoot, stackPackages = [] } = {}) {
62
70
  { projectVersion: version, supportedVersion: CURRENT_PROJECT_FORMAT_VERSION },
63
71
  );
64
72
  }
65
- await migration({ projectRoot: root, stackPackages });
73
+ const result = await migration({ projectRoot: root, stackPackages });
74
+ migratedFiles.push(...(result?.changedFiles || []));
66
75
  version += 1;
67
76
  await writeProjectFormatVersion(root, version);
68
77
  migratedFiles.push(PROJECT_VERSION_PATH);
@@ -12,7 +12,7 @@ import {
12
12
  } from './paths.js';
13
13
  import { normalizeSource, pathState, writeFileAtomic } from './utils.js';
14
14
 
15
- export const CURRENT_PROJECT_FORMAT_VERSION = 1;
15
+ export const CURRENT_PROJECT_FORMAT_VERSION = 2;
16
16
  export const CURRENT_PROJECT_FORMAT_SOURCE = `${CURRENT_PROJECT_FORMAT_VERSION}\n`;
17
17
 
18
18
  const VERSION_PATTERN = /^(0|[1-9][0-9]*)\n?$/u;
@@ -1,6 +1,7 @@
1
1
  import { readEngineering, readEngineeringBaseline } from './engineering.js';
2
2
  import { gitContext } from './git.js';
3
3
  import { readStack } from './stack.js';
4
+ import { listStackCatalogPieces } from './stack-catalog.js';
4
5
 
5
6
  async function optionalStack(projectRoot, stackPackages) {
6
7
  try { return await readStack(projectRoot, { stackPackages }); } catch { return null; }
@@ -23,12 +24,23 @@ async function optionalEngineering(projectRoot) {
23
24
  }
24
25
  }
25
26
 
27
+ async function optionalStackComponentIds(projectRoot, stack, stackPackages) {
28
+ try {
29
+ const packages = [...new Set([...(stack?.stackPackages || []), ...stackPackages])];
30
+ return (await listStackCatalogPieces({ projectRoot, stackPackages: packages }))
31
+ .map(({ id }) => id);
32
+ } catch {
33
+ return [];
34
+ }
35
+ }
36
+
26
37
  export async function projectSessionContext({ projectRoot, stackPackages = [] } = {}) {
27
38
  const root = (await gitContext(projectRoot)).repositoryRoot;
28
39
  const [stack, engineering] = await Promise.all([
29
40
  optionalStack(root, stackPackages),
30
41
  optionalEngineering(root),
31
42
  ]);
43
+ const availableComponents = await optionalStackComponentIds(root, stack, stackPackages);
32
44
  const selected = stack?.components.map(({ id }) => id) || [];
33
45
  const stackStatus = stack
34
46
  ? (selected.length > 0 ? selected.join(', ') : 'none')
@@ -38,10 +50,16 @@ export async function projectSessionContext({ projectRoot, stackPackages = [] }
38
50
  output: [
39
51
  'This is a Genesis-enriched project.',
40
52
  '- Read `genesis/blueprint.md`, `genesis/engineering.md`, and `genesis/stack.md` for product intent, engineering approach, and selected technology.',
53
+ '- For a new project whose Blueprint does not yet establish product direction, do not research technology or create source until the user has made clear what is being built, who or what will use or invoke it, and the first observable useful outcome. Ask only unresolved high-impact questions. A reply confirms only what it explicitly answers; Stack confirmation is not product intent.',
54
+ '- Once product direction is clear, choose one smallest implementation path through selected technology guidance, or authoritative technology documentation when the catalog has no match, and read only what that path requires. Do not survey alternatives, clone whole technology repositories, inspect unrelated package internals, or delegate research unless one concrete failure requires one exact investigation.',
55
+ `- Available Stack components: ${availableComponents.length > 0 ? availableComponents.map((id) => `\`${id}\``).join(', ') : 'none'}.`,
56
+ '- When the user names an unselected technology that exactly matches this catalog, run `genesis stack list`, ask whether to add and prepare it, and wait for confirmation. If confirmed, run `genesis stack add <piece...>` and follow its returned preparation prompt in the same task; then use `genesis context` and any installed technology skill. Never infer dependency commands from a component id. If declined or unmatched, continue through authoritative technology documentation without inventing a component.',
57
+ '- Project-owned operation sections in `genesis/stack.md` are the durable application contract. Make the implementation satisfy them or update a complete section to match evidenced reality; Genesis executes only Verification.',
41
58
  '- Use the relevant project Agent Skills below `.agents/skills/`.',
42
59
  '- After locating source, run `genesis context <path...>`; before adding a helper or public operation, run `genesis index <name-or-path...>` and reuse an existing owner.',
43
60
  '- Program is fallible explanation; code, tests, and runtime behavior remain evidence.',
44
61
  '- Keep Blueprint and affected Program explanations aligned with intentional observable product behavior in the same implementation turn. Private restructuring may need only source citations or no explanatory change.',
62
+ '- Before reporting completion, compare the requested observable behavior, required inputs and resources, declared project operations, and focused evidence with what actually exists. State anything not proven.',
45
63
  '- Deslop only when explicitly requested. Genesis defines its behavior-preserving committed scope; selected Stack components may add technology-specific cleanup guidance.',
46
64
  '- This guidance is loaded for a new session and refreshed after compaction. Continue the active request without restarting completed work.',
47
65
  `Engineering profile: ${engineering.profile?.id || 'invalid; run the Genesis `check` operation'}.`,