genesis-compiler 1.2.28 → 1.2.29

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
@@ -200,9 +200,9 @@ complete directory into `.agents/skills/`, including its `references/`,
200
200
  must resolve within that same Skill directory after relocation; a missing
201
201
  target or path that escapes the Skill root makes the Skill invalid. The agent
202
202
  loads valid resources only when the Skill requires them. A technology does not
203
- need a Skill to be selectable: the curated JSKIT piece, like ordinary framework
204
- pieces, links its authoritative framework documentation through Stack prose and
205
- declares no Skill. A piece's optional `## Guidance` is concise supplemental
203
+ need a Skill to be selectable: the curated JSKIT and Vue pieces link their
204
+ authoritative framework documentation through Stack prose and declare no Skill.
205
+ A piece's optional `## Guidance` is concise supplemental
206
206
  project-work guidance; it does not create or replace a generic technology
207
207
  skill.
208
208
 
@@ -518,8 +518,13 @@ The eight task types are deliberately explicit:
518
518
  - `start` opens the project conversation. For a new project it establishes what
519
519
  is being built, who or what will use or invoke it, and the first useful
520
520
  observable outcome before presenting relevant choices from the live Stack
521
- catalog. A partial reply resolves only what it explicitly answers. For an
522
- existing project it asks what the person wants to understand or change.
521
+ and engineering-profile catalogs. A partial reply resolves only what it
522
+ explicitly answers. An existing project receives none of those new-project
523
+ questions or catalogs. Its opening contains the full Blueprint, concise
524
+ selected Stack and Program summaries, and full selected Guidance separated by
525
+ component headings; detailed Program modules, sources, operations, indexes,
526
+ and skills are loaded later with `genesis context <relevant-path...>`. It
527
+ checks `genesis stack list` before proposing an additional technology.
523
528
  - `adopt` imports an existing application's factual operational and product
524
529
  contracts into Genesis metadata. It composes technology-specific Adoption
525
530
  requirements from the selected Stack and does not change application code.
@@ -645,7 +650,10 @@ General `Guidance` enriches implementation, review, Program, description, and
645
650
  cleanup tasks; `Adoption` adds import-only requirements; `Post-change` adds
646
651
  work to finish in the original implementation turn; `Deslop` adds
647
652
  technology-specific cleanup rules to Genesis's invariant behavior-preserving
648
- contract. None shadows an official generic technology skill or assumes that an
653
+ contract. When several components contribute one of these prose fields,
654
+ Genesis retains each complete contribution under its component heading in
655
+ dependency-first selected order; it does not blend or semantically deduplicate
656
+ their instructions. None shadows an official generic technology skill or assumes that an
649
657
  upstream skill contains every rule Genesis needs.
650
658
 
651
659
  Genesis core contains no Stack pieces and no database, framework, language, or
@@ -17,9 +17,16 @@ await currentAgent.send(work.prompt);
17
17
 
18
18
  Tasks are `start`, `adopt`, `work`, `deslop`, `program`, `blueprint`, `describe`, and `review`.
19
19
  `start` is the host-independent first conversation: it classifies an initialized
20
- project from current Genesis facts, asks what a new app is about, exposes the
21
- live Stack catalog for an explicit user choice, or asks what the person wants
22
- to do with an existing project. For an existing uninitialized codebase it owns
20
+ project from its selected Stack and Git-visible project paths without building
21
+ the code index. A new project gets the product questions and live Stack and
22
+ engineering-profile catalogs. An existing project gets none of that
23
+ new-project launcher or catalog: its opening JSON contains the full Blueprint,
24
+ selected component summaries, and only bounded Program status, subsystem names,
25
+ and a module count. The complete effective Guidance remains present once under
26
+ component headings. Exact Program modules, sources, project contracts, indexed
27
+ functions, verification commands, and skills are deferred to `genesis context
28
+ <relevant-path...>`. A new technology request goes through `genesis stack list`
29
+ before selection. For an existing uninitialized codebase it owns
23
30
  the adoption recommendation as part of the same portable prompt. A host such as Vibe64 sends this prompt on the
24
31
  first chat turn; it does not recreate the questions or Stack catalog.
25
32
  `describe` creates or refreshes the complete Blueprint and useful Program in one
@@ -33,8 +40,9 @@ Genesis keeps each instruction at one useful level:
33
40
  - `skills/genesis-project/`, `skills/genesis-program/`, and
34
41
  `skills/genesis-deslop/` are the reusable workflow sources copied into each
35
42
  project's `.agents/skills/` directory.
36
- - `prompts/<task>.txt` is a task launcher. It selects the relevant
37
- workflow skill and states only that turn's edit boundary.
43
+ - `prompts/<task>.txt` is a task launcher. `start.txt` is only the common opening
44
+ seam; one of its new, existing, or existing-uninitialized launchers is appended
45
+ after classification. Each launcher states only its own project kind's work.
38
46
  - a declared Stack package's `stacks/pieces/<component>.md` supplies concise Description, supplemental
39
47
  Guidance, Adoption requirements, initial operation proposals, Deslop overlays,
40
48
  structural Indexers, and an optional authoritative Agent Skill source.
@@ -50,7 +58,8 @@ Detailed technology manuals belong to the technology's authoritative
50
58
  documentation, which Stack prose may link directly. A technology may also
51
59
  offer a separately installable Skill with its own `references/` directory.
52
60
  Concise rules needed in project prompts belong in Stack `Guidance`; they are
53
- composed without creating a colliding generic skill.
61
+ composed dependency-first without semantic blending and retain a heading for
62
+ each contributing component.
54
63
 
55
64
  ## Existing projects
56
65
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genesis-compiler",
3
- "version": "1.2.28",
3
+ "version": "1.2.29",
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": {
@@ -34,6 +34,9 @@
34
34
  "prompts/program.txt",
35
35
  "prompts/review.txt",
36
36
  "prompts/start.txt",
37
+ "prompts/start-existing.txt",
38
+ "prompts/start-existing-uninitialized.txt",
39
+ "prompts/start-new.txt",
37
40
  "prompts/work.txt",
38
41
  "plugins/genesis",
39
42
  "plugins/opencode",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genesis",
3
- "version": "1.2.28",
3
+ "version": "1.2.29",
4
4
  "description": "Makes Codex aware of optional Genesis adoption for existing projects.",
5
5
  "author": {
6
6
  "name": "Mobily Enterprises"
@@ -0,0 +1,8 @@
1
+ This is an existing project without Genesis project context. Do not ask
2
+ new-project product-discovery questions. Ask what the person wants to understand
3
+ or change and strongly recommend preparing the project for guided editing before
4
+ substantial work. Explain in product language that preparation preserves the
5
+ implementation while importing its current product, setup, run, data, preview,
6
+ and verification facts. Do not require the person to know Genesis terminology or
7
+ type a command. If they approve, run the Genesis `adopt` operation and follow its
8
+ prompt. If they decline, continue normally and do not repeat the recommendation.
@@ -0,0 +1,23 @@
1
+ The project already exists. Do not ask new-project product-discovery questions
2
+ and do not offer an unselected technology catalog. Use the Blueprint as product
3
+ intent, the selected Stack summary and full guidance as technical direction, and
4
+ the compact Program status only as orientation. If USER REQUEST is actionable,
5
+ proceed with it. Otherwise ask what the person wants to understand or change.
6
+
7
+ After locating the relevant source, run the Genesis `context <relevant-path...>`
8
+ operation before implementation to load the exact Program modules, project
9
+ contracts, indexed functions, verification commands, and applicable skills.
10
+
11
+ If the user requests an unselected technology, run the Genesis `stack list`
12
+ operation first. For one exact match, ask whether to add it and prepare the
13
+ project with its official guidance; only after confirmation run `stack add
14
+ <piece...>` and follow its preparation prompt. If nothing matches, use the
15
+ technology's authoritative documentation without inventing a component.
16
+
17
+ When no Stack is selected, inspect the project's actual scripts, build and setup
18
+ files, server entrypoint, and readiness behavior before recording a technology.
19
+ Component proposals are not evidence, and selecting a component does not port an
20
+ older implementation. Preserve evidenced project-owned contracts in their
21
+ consumer's current schema. If the existing implementation is not usefully
22
+ explained, recommend the Genesis description path instead of pretending its
23
+ intent or operations are known.
@@ -0,0 +1,27 @@
1
+ The project is new. Before technology research or source creation, establish
2
+ what is being built, who or what will use or invoke it, and the first observable
3
+ useful outcome. Ask at most three concise questions at a time, and do not repeat
4
+ facts already supplied by the user. A Stack choice is not product intent.
5
+
6
+ Use `availableStackPieces` to offer only relevant technology choices in product
7
+ language. Never silently select one. If the user names an unselected technology,
8
+ run the Genesis `stack list` operation first. For one exact match, ask whether to
9
+ add it and prepare the project with its official guidance. On confirmation, run
10
+ the Genesis `stack add <piece...>` operation, follow its preparation prompt in
11
+ this task, then run `context .` or `context <relevant-path>` and load any
12
+ applicable installed skill. Never infer an install command from a component id.
13
+ If the user declines, do not ask again; if nothing matches, use the technology's
14
+ authoritative documentation without inventing a component.
15
+
16
+ Establish the non-technical Blueprint before implementation. If product intent
17
+ is clear while Stack is empty, present the relevant Stack choices in this same
18
+ turn. The default `focused.v1` engineering profile suits ordinary work; use
19
+ `availableEngineeringProfiles` only when the user requests another approach or
20
+ the product has material long-lived compatibility, operational, security,
21
+ reliability, or compliance constraints. Apply an explicit choice with the
22
+ Genesis `engineering set <profile>` operation.
23
+
24
+ This opening owns product direction and Stack selection, not final verification.
25
+ Do not run the Genesis `verify` operation before implementation exists. Use
26
+ `check` only when structural validation is useful. Once direction and Stack are
27
+ clear, follow one smallest implementation path through the selected guidance.
package/prompts/start.txt CHANGED
@@ -1,87 +1,5 @@
1
1
  Read and follow `.agents/skills/genesis-project/SKILL.md` completely.
2
2
 
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.
8
-
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
35
- implementation.
36
- If the product direction becomes clear while Stack is still empty, do not end
37
- the turn after only writing or summarizing the Blueprint: present the relevant
38
- Stack choices in that same turn and ask the user to select one explicitly.
39
- The default `focused.v1` engineering profile is already suitable for ordinary
40
- work, so do not force a separate profile question. When the user asks for a
41
- different engineering approach, or the product clearly has long-lived
42
- compatibility, operational, security, reliability, or compliance constraints,
43
- use `availableEngineeringProfiles` to explain only the relevant choices in
44
- product language. After an explicit choice, run the Genesis `engineering set
45
- <profile>` operation; do not invent or duplicate a built-in profile. Record
46
- additional explicit obligations in `genesis/engineering.md` under Project
47
- requirements.
48
- This opening turn owns product direction and Stack selection, not final
49
- verification. Do not run the Genesis `verify` operation before implementation
50
- exists. If structural validation is useful, run the Genesis `check` operation;
51
- consumer-owned operations remain governed by their own tools and must not be
52
- inferred here.
53
-
54
- When `projectKind` is `existing`, ask what the user wants to understand or
55
- change. Use the current Blueprint, Stack, Program, and code index when present.
56
- If the existing implementation is not yet explained, recommend the Genesis
57
- description/adoption path instead of pretending its intent is known.
58
- When an existing implementation has no selected Stack yet, inspect its actual
59
- package scripts, build files, setup commands, server entrypoint, and readiness
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.
67
-
68
- When `projectKind` is `existing-uninitialized`, ask what the user wants to
69
- understand or change and strongly recommend preparing the existing project for
70
- guided editing before substantial work. Explain in product language that this
71
- preserves the implementation while importing its current setup, run, database,
72
- preview, verification, and product context. Do not require the user to know
73
- Genesis terminology or type a command. If they approve, run the Genesis `adopt`
74
- operation yourself and follow its adoption prompt. If they decline, continue
75
- normally and do not repeat the recommendation.
76
-
77
- If the request already contains an unambiguous product description and an
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.
3
+ This is the project-opening conversation. Follow only the project-kind
4
+ instructions below. Treat USER REQUEST as the person's actual request, preserve
5
+ what it already establishes, and ask only unresolved high-impact questions.
@@ -3,6 +3,9 @@ import { readFile } from 'node:fs/promises';
3
3
  const root = new URL('../../', import.meta.url);
4
4
  const assets = {
5
5
  start: new URL('prompts/start.txt', root),
6
+ 'start-new': new URL('prompts/start-new.txt', root),
7
+ 'start-existing': new URL('prompts/start-existing.txt', root),
8
+ 'start-existing-uninitialized': new URL('prompts/start-existing-uninitialized.txt', root),
6
9
  adopt: new URL('prompts/adopt.txt', root),
7
10
  work: new URL('prompts/work.txt', root),
8
11
  describe: new URL('prompts/describe.txt', root),
@@ -3,9 +3,8 @@ import path from 'node:path';
3
3
 
4
4
  import { GenesisError } from './errors.js';
5
5
  import { gitContext } from './git.js';
6
- import { isProjectContentPath } from './paths.js';
7
- import { runGit } from './process.js';
8
- import { normalizeRelative, pathState, writeFileAtomic } from './utils.js';
6
+ import { classifyProjectKind } from './project-files.js';
7
+ import { pathState, writeFileAtomic } from './utils.js';
9
8
 
10
9
  const HOOKS_PATH = '.codex/hooks.json';
11
10
  const LEGACY_GENESIS_HOOKS_DESCRIPTION = 'Genesis project hooks.';
@@ -90,20 +89,15 @@ export async function installCodexHooks({ projectRoot } = {}) {
90
89
  return { status: 'updated', changedFiles: [HOOKS_PATH] };
91
90
  }
92
91
 
93
- function zeroPaths(buffer) {
94
- return [...new Set(buffer.toString('utf8').split('\0').map(normalizeRelative).filter(Boolean))];
95
- }
96
-
97
92
  export async function codexAdoptionRecommendation({ projectRoot = process.cwd() } = {}) {
98
93
  let root;
99
94
  try { root = (await gitContext(projectRoot)).repositoryRoot; } catch { return { status: 'not-applicable', output: '' }; }
100
95
  if ((await pathState(path.join(root, 'genesis/blueprint.md'))).exists) {
101
96
  return { status: 'not-applicable', output: '' };
102
97
  }
103
- const files = zeroPaths((await runGit(root, [
104
- 'ls-files', '-z', '--cached', '--others', '--exclude-standard',
105
- ])).stdout).filter(isProjectContentPath);
106
- if (files.length === 0) return { status: 'not-applicable', output: '' };
98
+ if (await classifyProjectKind({ projectRoot: root }) === 'new') {
99
+ return { status: 'not-applicable', output: '' };
100
+ }
107
101
  return {
108
102
  status: 'ready',
109
103
  output: [
@@ -31,18 +31,13 @@ function stackSummary(stack) {
31
31
  }
32
32
 
33
33
  function stackGuidance(stack) {
34
- const pieces = stack.components.filter(({ guidance }) => guidance);
35
- if (pieces.length === 0) return [];
34
+ if (!stack.guidance) return [];
36
35
  return [
37
36
  '',
38
37
  '## Selected Stack guidance',
39
38
  '',
40
- ...pieces.flatMap(({ id, guidance }) => [
41
- `### ${id}`,
42
- '',
43
- guidance,
44
- '',
45
- ]),
39
+ stack.guidance,
40
+ '',
46
41
  ];
47
42
  }
48
43
 
@@ -2,9 +2,9 @@ import { readFile } from 'node:fs/promises';
2
2
  import path from 'node:path';
3
3
 
4
4
  import { gitContext } from './git.js';
5
+ import { OPENCODE_PLUGIN_PATH } from './paths.js';
5
6
  import { writeFileAtomic } from './utils.js';
6
7
 
7
- const OPENCODE_PLUGIN_PATH = '.opencode/plugins/genesis-project-guidance.js';
8
8
  const OPENCODE_PLUGIN_SOURCE = new URL('../../plugins/opencode/project-guidance.js', import.meta.url);
9
9
 
10
10
  async function existingSource(location) {
@@ -4,6 +4,7 @@ export const STACK_PATH = 'genesis/stack.md';
4
4
  export const PROGRAM_ROOT = 'genesis/program';
5
5
  export const PROJECT_VERSION_PATH = 'genesis/version';
6
6
  export const VERIFICATION_PATH = '.genesis/verification.json';
7
+ export const OPENCODE_PLUGIN_PATH = '.opencode/plugins/genesis-project-guidance.js';
7
8
 
8
9
  export function isProjectContentPath(file) {
9
10
  const first = file.split('/')[0];
@@ -1,5 +1,6 @@
1
1
  import path from 'node:path';
2
2
 
3
+ import { isProjectContentPath, OPENCODE_PLUGIN_PATH } from './paths.js';
3
4
  import { runGit } from './process.js';
4
5
  import { pathState } from './utils.js';
5
6
 
@@ -22,3 +23,14 @@ export async function gitVisibleFileStates(projectRoot, { includePath = () => tr
22
23
  }
23
24
  return states;
24
25
  }
26
+
27
+ /** Classifies opening behavior from cheap Git-visible paths and selected Stack state. */
28
+ export async function classifyProjectKind({ projectRoot, stackComponents = [] } = {}) {
29
+ if (stackComponents.length > 0) return 'existing';
30
+ const existing = (await visiblePaths(projectRoot)).some((file) => (
31
+ isProjectContentPath(file)
32
+ && file !== OPENCODE_PLUGIN_PATH
33
+ && !file.split('/').includes('node_modules')
34
+ ));
35
+ return existing ? 'existing' : 'new';
36
+ }
@@ -17,8 +17,7 @@ import { inspectVerification } from './project-state.js';
17
17
  import { missingStackResources } from './stack-preflight.js';
18
18
  import { withStackEnvironmentDefaults } from './stack-environment-defaults.js';
19
19
  import { stableJson } from './utils.js';
20
- import { gitVisibleFileStates } from './project-files.js';
21
- import { isProjectContentPath } from './paths.js';
20
+ import { classifyProjectKind } from './project-files.js';
22
21
 
23
22
  const TASKS = new Set(['start', 'adopt', 'work', 'deslop', 'program', 'blueprint', 'describe', 'review']);
24
23
  const DEFAULT_REQUEST = {
@@ -83,6 +82,26 @@ function programContext(program) {
83
82
  };
84
83
  }
85
84
 
85
+ function startProgramContext(program) {
86
+ return {
87
+ status: program.status,
88
+ subsystems: program.subsystems,
89
+ moduleCount: program.modules.length,
90
+ ...(program.diagnostic ? { diagnostic: program.diagnostic } : {}),
91
+ };
92
+ }
93
+
94
+ function startStackContext(stack) {
95
+ return {
96
+ components: stack.components.map(({ id, description }) => ({ id, description })),
97
+ };
98
+ }
99
+
100
+ async function startInstructions(instructions, projectKind) {
101
+ const specific = await readInstalledAsset(`start-${projectKind}`);
102
+ return `${instructions.trim()}\n\n${specific.trim()}`;
103
+ }
104
+
86
105
  function codeIndexContext(index) {
87
106
  return {
88
107
  machineCity: {
@@ -231,21 +250,17 @@ async function generateStartPrompt({
231
250
  root,
232
251
  stackPackages,
233
252
  }) {
234
- const availableEngineeringProfiles = (await listEngineeringProfileCatalog())
235
- .map(({ id, name, description }) => ({ id, name, description }));
236
253
  let blueprint;
237
254
  try {
238
255
  blueprint = await readBlueprint(root, { required: true });
239
256
  } catch (error) {
240
257
  if (error?.code !== 'BLUEPRINT_REQUIRED') throw error;
241
- const files = await gitVisibleFileStates(root, { includePath: isProjectContentPath });
242
- const existing = [...files.values()].some((state) => state.exists);
243
- if (!existing) throw error;
258
+ if (await classifyProjectKind({ projectRoot: root }) === 'new') throw error;
244
259
  return {
245
260
  status: 'ready',
246
261
  task: 'start',
247
262
  prompt: renderPrompt({
248
- instructions,
263
+ instructions: await startInstructions(instructions, 'existing-uninitialized'),
249
264
  request,
250
265
  context: {
251
266
  task: 'start',
@@ -253,8 +268,6 @@ async function generateStartPrompt({
253
268
  projectKind: 'existing-uninitialized',
254
269
  genesis: { initialized: false },
255
270
  engineering: engineeringPromptContext(engineering),
256
- availableEngineeringProfiles,
257
- program: programContext(program),
258
271
  },
259
272
  engineeringGuidance: engineering.guidance,
260
273
  }),
@@ -263,42 +276,51 @@ async function generateStartPrompt({
263
276
  };
264
277
  }
265
278
  const stack = await readStack(root, { stackPackages });
279
+ const projectKind = await classifyProjectKind({
280
+ projectRoot: root,
281
+ stackComponents: stack.components,
282
+ });
266
283
  const availableStackPackages = [...new Set([...stack.stackPackages, ...stackPackages])];
267
- const [index, catalog] = await Promise.all([
268
- buildProjectIndex({ projectRoot: root, stackPackages, write: false }),
269
- listStackCatalogPieces({ projectRoot: root, stackPackages: availableStackPackages }),
284
+ const [catalog, availableEngineeringProfiles, projectSkills, renderedInstructions] = await Promise.all([
285
+ projectKind === 'new'
286
+ ? listStackCatalogPieces({ projectRoot: root, stackPackages: availableStackPackages })
287
+ : Promise.resolve([]),
288
+ projectKind === 'new'
289
+ ? listEngineeringProfileCatalog()
290
+ .then((profiles) => profiles.map(({ id, name, description }) => ({ id, name, description })))
291
+ : Promise.resolve([]),
292
+ inspectProjectSkills({ projectRoot: root, stack }),
293
+ startInstructions(instructions, projectKind),
270
294
  ]);
271
- const projectSkills = await inspectProjectSkills({ projectRoot: root, stack });
272
- const newProject = stack.components.length === 0 && index.fileCount === 0;
273
295
  return {
274
296
  status: 'ready',
275
297
  task: 'start',
276
298
  prompt: renderPrompt({
277
- instructions,
299
+ instructions: renderedInstructions,
278
300
  request,
279
301
  context: {
280
302
  task: 'start',
281
303
  projectRoot: root,
282
- projectKind: newProject ? 'new' : 'existing',
304
+ projectKind,
283
305
  blueprint: {
284
306
  path: blueprint.path,
285
307
  description: blueprint.description,
286
308
  },
287
309
  engineering: engineeringPromptContext(engineering),
288
- availableEngineeringProfiles,
289
- stack: stackPromptContext(stack),
290
- availableStackPieces: stackCatalogContext(catalog, hiddenStackPieces),
291
- program: programContext(program),
292
- codeIndex: codeIndexContext(index),
310
+ stack: startStackContext(stack),
311
+ ...(projectKind === 'new'
312
+ ? {
313
+ availableEngineeringProfiles,
314
+ availableStackPieces: stackCatalogContext(catalog, hiddenStackPieces),
315
+ }
316
+ : { program: startProgramContext(program) }),
293
317
  },
294
318
  engineeringGuidance: engineering.guidance,
295
319
  guidance: stack.guidance,
296
- skills: renderAgentSkillCatalog(projectSkills.skills),
297
320
  }),
298
321
  warnings: [
299
322
  ...(program.diagnostic ? [program.diagnostic] : []),
300
323
  ...projectSkills.diagnostics,
301
- ...index.diagnostics,
302
324
  ],
303
325
  verificationCommands: [],
304
326
  };
@@ -271,8 +271,8 @@ export async function materializeProjectStackContracts({ projectRoot, stackPacka
271
271
 
272
272
  function composedProse(components, field) {
273
273
  return components
274
- .map((piece) => piece[field] || '')
275
- .filter(Boolean)
274
+ .filter((piece) => piece[field])
275
+ .map((piece) => `### \`${piece.id}\`\n\n${piece[field]}`)
276
276
  .join('\n\n');
277
277
  }
278
278