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 +14 -6
- package/docs/prompt-integration.md +15 -6
- package/package.json +4 -1
- package/plugins/genesis/.codex-plugin/plugin.json +1 -1
- package/prompts/start-existing-uninitialized.txt +8 -0
- package/prompts/start-existing.txt +23 -0
- package/prompts/start-new.txt +27 -0
- package/prompts/start.txt +3 -85
- package/src/index/assets.js +3 -0
- package/src/index/codex-hooks.js +5 -11
- package/src/index/context.js +3 -8
- package/src/index/opencode-plugin.js +1 -1
- package/src/index/paths.js +1 -0
- package/src/index/project-files.js +12 -0
- package/src/index/prompt.js +46 -24
- package/src/index/stack.js +2 -2
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
|
|
204
|
-
|
|
205
|
-
|
|
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
|
-
|
|
522
|
-
|
|
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.
|
|
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
|
|
21
|
-
|
|
22
|
-
|
|
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.
|
|
37
|
-
|
|
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
|
|
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.
|
|
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",
|
|
@@ -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.
|
|
4
|
-
|
|
5
|
-
|
|
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.
|
package/src/index/assets.js
CHANGED
|
@@ -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),
|
package/src/index/codex-hooks.js
CHANGED
|
@@ -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 {
|
|
7
|
-
import {
|
|
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
|
-
|
|
104
|
-
|
|
105
|
-
|
|
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: [
|
package/src/index/context.js
CHANGED
|
@@ -31,18 +31,13 @@ function stackSummary(stack) {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
function stackGuidance(stack) {
|
|
34
|
-
|
|
35
|
-
if (pieces.length === 0) return [];
|
|
34
|
+
if (!stack.guidance) return [];
|
|
36
35
|
return [
|
|
37
36
|
'',
|
|
38
37
|
'## Selected Stack guidance',
|
|
39
38
|
'',
|
|
40
|
-
|
|
41
|
-
|
|
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) {
|
package/src/index/paths.js
CHANGED
|
@@ -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
|
+
}
|
package/src/index/prompt.js
CHANGED
|
@@ -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 {
|
|
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
|
-
|
|
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 [
|
|
268
|
-
|
|
269
|
-
|
|
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
|
|
304
|
+
projectKind,
|
|
283
305
|
blueprint: {
|
|
284
306
|
path: blueprint.path,
|
|
285
307
|
description: blueprint.description,
|
|
286
308
|
},
|
|
287
309
|
engineering: engineeringPromptContext(engineering),
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
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
|
};
|
package/src/index/stack.js
CHANGED
|
@@ -271,8 +271,8 @@ export async function materializeProjectStackContracts({ projectRoot, stackPacka
|
|
|
271
271
|
|
|
272
272
|
function composedProse(components, field) {
|
|
273
273
|
return components
|
|
274
|
-
.
|
|
275
|
-
.
|
|
274
|
+
.filter((piece) => piece[field])
|
|
275
|
+
.map((piece) => `### \`${piece.id}\`\n\n${piece[field]}`)
|
|
276
276
|
.join('\n\n');
|
|
277
277
|
}
|
|
278
278
|
|