genesis-compiler 1.0.0 → 1.2.0
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/.agents/plugins/marketplace.json +20 -0
- package/README.md +443 -0
- package/bin/genesis.js +15 -0
- package/docs/assurance-model.md +26 -0
- package/docs/prompt-integration.md +98 -0
- package/docs/stack-components.md +304 -0
- package/package.json +57 -7
- package/plugins/genesis/.codex-plugin/plugin.json +19 -0
- package/plugins/genesis/hooks.json +18 -0
- package/prompts/blueprint.txt +9 -0
- package/prompts/describe.txt +17 -0
- package/prompts/deslop.txt +14 -0
- package/prompts/program.txt +12 -0
- package/prompts/reconcile.txt +12 -0
- package/prompts/review.txt +12 -0
- package/prompts/start.txt +30 -0
- package/prompts/work.txt +28 -0
- package/skills/genesis-deslop/SKILL.md +36 -0
- package/skills/genesis-deslop/agents/openai.yaml +4 -0
- package/skills/genesis-program/SKILL.md +66 -0
- package/skills/genesis-program/agents/openai.yaml +4 -0
- package/skills/genesis-project/SKILL.md +53 -0
- package/skills/genesis-project/agents/openai.yaml +4 -0
- package/src/cli.js +276 -0
- package/src/index/agent-skills.js +425 -0
- package/src/index/assets.js +19 -0
- package/src/index/blueprint.js +38 -0
- package/src/index/check.js +102 -0
- package/src/index/code-index.js +283 -0
- package/src/index/code-indexers/ast-grep.js +414 -0
- package/src/index/codex-hooks.js +367 -0
- package/src/index/codex-plugin.js +73 -0
- package/src/index/context.js +137 -0
- package/src/index/environment-files.js +19 -0
- package/src/index/errors.js +26 -0
- package/src/index/git.js +26 -0
- package/src/index/init.js +48 -0
- package/src/index/launch.js +34 -0
- package/src/index/paths.js +10 -0
- package/src/index/process.js +89 -0
- package/src/index/program.js +181 -0
- package/src/index/project-files.js +24 -0
- package/src/index/project-state.js +87 -0
- package/src/index/prompt.js +347 -0
- package/src/index/stack-catalog.js +72 -0
- package/src/index/stack-command.js +65 -0
- package/src/index/stack-composition.js +38 -0
- package/src/index/stack-environment-files.js +83 -0
- package/src/index/stack-launch.js +428 -0
- package/src/index/stack-piece.js +283 -0
- package/src/index/stack-preflight.js +25 -0
- package/src/index/stack-process.js +25 -0
- package/src/index/stack-workspace-setup.js +129 -0
- package/src/index/stack.js +302 -0
- package/src/index/utils.js +85 -0
- package/src/index/verification.js +77 -0
- package/src/index/workspace-setup.js +55 -0
- package/src/index.js +102 -0
- package/stacks/pieces/cpp.md +22 -0
- package/stacks/pieces/csharp.md +22 -0
- package/stacks/pieces/go.md +22 -0
- package/stacks/pieces/java.md +22 -0
- package/stacks/pieces/jskit-mysql.md +37 -0
- package/stacks/pieces/jskit.md +70 -0
- package/stacks/pieces/kotlin.md +22 -0
- package/stacks/pieces/mysql.md +18 -0
- package/stacks/pieces/nodejs.md +25 -0
- package/stacks/pieces/php.md +23 -0
- package/stacks/pieces/python.md +23 -0
- package/stacks/pieces/ruby.md +22 -0
- package/stacks/pieces/rust.md +22 -0
- package/stacks/pieces/shell.md +23 -0
- package/stacks/pieces/vue.md +19 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: genesis-project
|
|
3
|
+
description: Work safely in a Genesis-enriched codebase using its Blueprint, Stack, subsystem Program, path-focused context, and concrete verification. Use for implementation or review in a repository containing genesis/blueprint.md.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Genesis project work
|
|
7
|
+
|
|
8
|
+
Genesis is an explanatory and verification companion. It does not replace the
|
|
9
|
+
codebase, tests, Git review, or the coding agent.
|
|
10
|
+
|
|
11
|
+
## Establish context
|
|
12
|
+
|
|
13
|
+
1. Read `genesis/blueprint.md` for non-technical product intent.
|
|
14
|
+
2. Read `genesis/stack.md` for the selected technical composition, resources,
|
|
15
|
+
and verification commands.
|
|
16
|
+
3. Locate the source involved in the request.
|
|
17
|
+
4. Run `genesis index <name-or-path>` before adding a helper or public operation.
|
|
18
|
+
Reuse an existing function when it already owns the behavior.
|
|
19
|
+
5. Run `genesis context <path...>` for the relevant Program explanations and
|
|
20
|
+
selected Stack context.
|
|
21
|
+
6. Load applicable technology skills from `.agents/skills/` or from the
|
|
22
|
+
agent's own installed skill catalog.
|
|
23
|
+
|
|
24
|
+
Program is concise, fallible explanation. Its Sources and optional
|
|
25
|
+
Implementation maps aid navigation but never substitute for reading code,
|
|
26
|
+
tests, and runtime behavior.
|
|
27
|
+
|
|
28
|
+
`.genesis/machine-city.json` is a derived detailed file/function map.
|
|
29
|
+
`.genesis/program-city.json` is a derived simpler subsystem/operation map.
|
|
30
|
+
Neither is authority or proof; both may be regenerated with `genesis index`.
|
|
31
|
+
|
|
32
|
+
## Implement ordinary local work
|
|
33
|
+
|
|
34
|
+
- Work directly in the current Git tree and leave useful edits visible in the
|
|
35
|
+
ordinary diff.
|
|
36
|
+
- Do not edit the Blueprint, Program, or `.genesis/` during implementation; the
|
|
37
|
+
separate reconciliation turn owns explanatory updates. Keep an exact Stack
|
|
38
|
+
`## Launch` declaration aligned when the implementation establishes or
|
|
39
|
+
intentionally changes how the project is started or how Vibe64 may request
|
|
40
|
+
an application preview identity. Record only capability metadata and
|
|
41
|
+
environment variable names there, never environment values or secrets.
|
|
42
|
+
- Follow established project and technology seams instead of creating parallel
|
|
43
|
+
frameworks, persistence layers, transports, validators, or UI systems.
|
|
44
|
+
- Never invent unavailable external-resource values or pass literal
|
|
45
|
+
environment-variable names as data. Report the missing resource and preserve
|
|
46
|
+
useful work.
|
|
47
|
+
- Keep the implementation direct and cohesive. Run focused checks when useful.
|
|
48
|
+
|
|
49
|
+
## Verify and report
|
|
50
|
+
|
|
51
|
+
Use `genesis verify` for the Stack's declared final checks. Report files
|
|
52
|
+
changed, checks actually run, and anything still requiring attention. Never
|
|
53
|
+
claim that an unrun check passed or that passing checks prove the whole product.
|
package/src/cli.js
ADDED
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import process from 'node:process';
|
|
2
|
+
import { parseArgs } from 'node:util';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
addStack,
|
|
6
|
+
adoptProject,
|
|
7
|
+
check,
|
|
8
|
+
generatePrompt,
|
|
9
|
+
getContext,
|
|
10
|
+
indexCodebase,
|
|
11
|
+
initialize,
|
|
12
|
+
installCodex,
|
|
13
|
+
listStackPieces,
|
|
14
|
+
verify,
|
|
15
|
+
} from './index.js';
|
|
16
|
+
import {
|
|
17
|
+
codexAdoptionRecommendation,
|
|
18
|
+
codexSessionContext,
|
|
19
|
+
completeCodexTurn,
|
|
20
|
+
discardCodexTurn,
|
|
21
|
+
recordCodexTurn,
|
|
22
|
+
} from './index/codex-hooks.js';
|
|
23
|
+
import { asDiagnostic, fail } from './index/errors.js';
|
|
24
|
+
|
|
25
|
+
const USAGE = `Usage:
|
|
26
|
+
genesis init
|
|
27
|
+
genesis adopt [product guidance...]
|
|
28
|
+
genesis codex install
|
|
29
|
+
genesis stack list
|
|
30
|
+
genesis stack add <piece...>
|
|
31
|
+
genesis context <path...>
|
|
32
|
+
genesis index [function-or-path...]
|
|
33
|
+
genesis prompt [request...]
|
|
34
|
+
genesis prompt --task <start|work|deslop|program|blueprint|describe|review> [request...]
|
|
35
|
+
genesis verify
|
|
36
|
+
genesis check
|
|
37
|
+
|
|
38
|
+
Options:
|
|
39
|
+
--project-root <path> Set the project root (default: current directory)
|
|
40
|
+
--task <task> Select the prompt task (default: work)
|
|
41
|
+
--json Emit one machine-readable result
|
|
42
|
+
-h, --help Show this help
|
|
43
|
+
|
|
44
|
+
Genesis generates prompts; it never starts or manages an AI agent. Give the
|
|
45
|
+
prompt to the agent you already use. Review all edits through the ordinary Git
|
|
46
|
+
diff, then run genesis verify for the Stack's concrete checks.
|
|
47
|
+
`;
|
|
48
|
+
|
|
49
|
+
const COMMANDS = new Set(['adopt', 'check', 'codex', 'context', 'hook', 'index', 'init', 'prompt', 'stack', 'verify']);
|
|
50
|
+
|
|
51
|
+
function parseCommand(argv) {
|
|
52
|
+
if (argv.length === 0 || argv.includes('--help') || argv.includes('-h') || argv[0] === 'help') {
|
|
53
|
+
return { command: 'help', operands: [], options: {} };
|
|
54
|
+
}
|
|
55
|
+
const [command, ...rest] = argv;
|
|
56
|
+
if (!COMMANDS.has(command)) fail('CLI_UNKNOWN_COMMAND', `Unknown command: ${command}`);
|
|
57
|
+
let parsed;
|
|
58
|
+
try {
|
|
59
|
+
parsed = parseArgs({
|
|
60
|
+
args: rest,
|
|
61
|
+
allowPositionals: true,
|
|
62
|
+
strict: true,
|
|
63
|
+
options: {
|
|
64
|
+
json: { type: 'boolean', default: false },
|
|
65
|
+
'project-root': { type: 'string' },
|
|
66
|
+
task: { type: 'string' },
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
} catch (error) {
|
|
70
|
+
fail('CLI_ARGUMENT_INVALID', error.message);
|
|
71
|
+
}
|
|
72
|
+
const options = {
|
|
73
|
+
json: parsed.values.json,
|
|
74
|
+
projectRoot: parsed.values['project-root'],
|
|
75
|
+
task: parsed.values.task,
|
|
76
|
+
};
|
|
77
|
+
const operands = parsed.positionals;
|
|
78
|
+
if (options.task !== undefined && command !== 'prompt') {
|
|
79
|
+
fail('CLI_OPTION_NOT_APPLICABLE', `Option --task is not applicable to ${command}.`);
|
|
80
|
+
}
|
|
81
|
+
if (command === 'stack') {
|
|
82
|
+
if (!['list', 'add'].includes(operands[0])) {
|
|
83
|
+
fail('CLI_STACK_ACTION_REQUIRED', 'Command stack requires list or add.');
|
|
84
|
+
}
|
|
85
|
+
if (operands[0] === 'add' && operands.length < 2) {
|
|
86
|
+
fail('CLI_STACK_PIECE_REQUIRED', 'Command stack add requires at least one piece.');
|
|
87
|
+
}
|
|
88
|
+
if (operands[0] === 'list' && operands.length !== 1) {
|
|
89
|
+
fail('CLI_EXTRA_ARGUMENT', 'Command stack list accepts no extra arguments.');
|
|
90
|
+
}
|
|
91
|
+
} else if (command === 'codex') {
|
|
92
|
+
if (operands.length !== 1 || operands[0] !== 'install') {
|
|
93
|
+
fail('CLI_CODEX_ACTION_REQUIRED', 'Command codex requires exactly: install.');
|
|
94
|
+
}
|
|
95
|
+
} else if (command === 'context' && operands.length === 0) {
|
|
96
|
+
fail('CONTEXT_PATH_REQUIRED', 'Command context requires at least one project path.');
|
|
97
|
+
} else if (command === 'hook' && (operands.length !== 1 || !['begin', 'discover', 'end', 'session', 'stop'].includes(operands[0]))) {
|
|
98
|
+
fail('CLI_HOOK_ACTION_REQUIRED', 'Command hook requires exactly one of: discover, session, begin, stop, end.');
|
|
99
|
+
} else if (!['adopt', 'context', 'hook', 'index', 'prompt'].includes(command) && operands.length > 0) {
|
|
100
|
+
fail('CLI_EXTRA_ARGUMENT', `Command ${command} accepts no arguments.`);
|
|
101
|
+
}
|
|
102
|
+
return { command, operands, options };
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function line(stream, value = '') {
|
|
106
|
+
stream.write(`${String(value).replace(/\n$/u, '')}\n`);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function namedItems(label, values) {
|
|
110
|
+
if (!Array.isArray(values) || values.length === 0) return;
|
|
111
|
+
line(process.stdout, `${label}:`);
|
|
112
|
+
for (const value of values) line(process.stdout, ` - ${value}`);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function writeCheck(result) {
|
|
116
|
+
line(process.stdout, `Blueprint: ${result.blueprint}`);
|
|
117
|
+
line(process.stdout, `Stack: ${result.stack}`);
|
|
118
|
+
line(process.stdout, `Agent Skills: ${result.skills}`);
|
|
119
|
+
line(process.stdout, `Program: ${result.program}`);
|
|
120
|
+
line(process.stdout, `Resource inputs: ${result.resources}`);
|
|
121
|
+
line(process.stdout, `Verification: ${result.verification}`);
|
|
122
|
+
namedItems('Program files', result.programFiles);
|
|
123
|
+
namedItems('Subsystems', result.subsystems);
|
|
124
|
+
for (const item of result.diagnostics) line(process.stdout, `${item.code}: ${item.message}`);
|
|
125
|
+
if (result.guidance) line(process.stdout, result.guidance);
|
|
126
|
+
line(process.stdout, `Check: ${result.status}`);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function writeResult(command, result) {
|
|
130
|
+
if (command === 'prompt') {
|
|
131
|
+
process.stdout.write(result.prompt.endsWith('\n') ? result.prompt : `${result.prompt}\n`);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
if (command === 'adopt') {
|
|
135
|
+
if (result.summary) line(process.stdout, result.summary);
|
|
136
|
+
namedItems('Changed files', result.changedFiles);
|
|
137
|
+
if (result.guidance) line(process.stdout, result.guidance);
|
|
138
|
+
line(process.stdout, '');
|
|
139
|
+
process.stdout.write(result.prompt.endsWith('\n') ? result.prompt : `${result.prompt}\n`);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
if (command === 'check') {
|
|
143
|
+
writeCheck(result);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
if (command === 'context') {
|
|
147
|
+
process.stdout.write(result.context.endsWith('\n') ? result.context : `${result.context}\n`);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
if (command === 'index') {
|
|
151
|
+
line(process.stdout, result.summary);
|
|
152
|
+
line(process.stdout, `Machine City: ${result.paths.machine}`);
|
|
153
|
+
line(process.stdout, `Program City: ${result.paths.program}`);
|
|
154
|
+
if (result.totalMatches > 0) {
|
|
155
|
+
line(process.stdout, 'Matching functions:');
|
|
156
|
+
for (const entry of result.matches) {
|
|
157
|
+
const signature = `${entry.qualifiedName}(${entry.parameters.join(', ')})`;
|
|
158
|
+
line(process.stdout, ` - ${entry.visibility} ${signature} — ${entry.path}:${entry.line}`);
|
|
159
|
+
}
|
|
160
|
+
if (result.totalMatches > result.matches.length) {
|
|
161
|
+
line(process.stdout, ` - ... and ${result.totalMatches - result.matches.length} more`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
for (const item of result.diagnostics || []) line(process.stdout, `${item.code}: ${item.message}`);
|
|
165
|
+
line(process.stdout, `index: ${result.status}`);
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
if (command === 'hook') {
|
|
169
|
+
if (['discover', 'session'].includes(result.kind) && result.output) line(process.stdout, result.output);
|
|
170
|
+
else if (result.kind === 'stop') line(process.stdout, JSON.stringify(result.output));
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
if (command === 'stack' && Array.isArray(result.pieces)) {
|
|
174
|
+
for (const piece of result.pieces) {
|
|
175
|
+
line(process.stdout, `${piece.id}: ${piece.description}`);
|
|
176
|
+
if (piece.requires.length > 0) line(process.stdout, ` requires: ${piece.requires.join(', ')}`);
|
|
177
|
+
if (piece.indexers.length > 0) line(process.stdout, ` indexers: ${piece.indexers.join(', ')}`);
|
|
178
|
+
}
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
if (result.summary) line(process.stdout, result.summary);
|
|
182
|
+
namedItems('Changed files', result.changedFiles);
|
|
183
|
+
namedItems('Commands', result.commands?.map(({ label, argv }) => `${label}: ${argv.join(' ')}`));
|
|
184
|
+
for (const item of result.diagnostics || []) {
|
|
185
|
+
line(process.stdout, `${item.code}: ${item.message}`);
|
|
186
|
+
for (const field of ['stdout', 'stderr']) {
|
|
187
|
+
const output = item.details?.[field]?.trim();
|
|
188
|
+
if (output) line(process.stdout, output);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
if (result.guidance) line(process.stdout, result.guidance);
|
|
192
|
+
line(process.stdout, `${command}: ${result.status}`);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
async function hookInput() {
|
|
196
|
+
if (process.stdin.isTTY) fail('CODEX_HOOK_INPUT_INVALID', 'Codex hook input must be supplied on stdin.');
|
|
197
|
+
const chunks = [];
|
|
198
|
+
let bytes = 0;
|
|
199
|
+
for await (const chunk of process.stdin) {
|
|
200
|
+
bytes += chunk.length;
|
|
201
|
+
if (bytes > 1024 * 1024) fail('CODEX_HOOK_INPUT_INVALID', 'Codex hook input exceeds 1 MiB.');
|
|
202
|
+
chunks.push(chunk);
|
|
203
|
+
}
|
|
204
|
+
try { return JSON.parse(Buffer.concat(chunks).toString('utf8')); } catch (error) {
|
|
205
|
+
fail('CODEX_HOOK_INPUT_INVALID', `Codex hook input is invalid JSON: ${error.message}.`);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
async function execute({ command, operands, options }) {
|
|
210
|
+
const projectRoot = options.projectRoot || process.cwd();
|
|
211
|
+
if (command === 'init') return initialize({ projectRoot });
|
|
212
|
+
if (command === 'adopt') {
|
|
213
|
+
return adoptProject({ projectRoot, request: operands.join(' ') });
|
|
214
|
+
}
|
|
215
|
+
if (command === 'codex') return installCodex();
|
|
216
|
+
if (command === 'stack') {
|
|
217
|
+
if (operands[0] === 'list') return { status: 'ok', pieces: await listStackPieces() };
|
|
218
|
+
return addStack({ pieces: operands.slice(1), projectRoot });
|
|
219
|
+
}
|
|
220
|
+
if (command === 'prompt') {
|
|
221
|
+
return generatePrompt({
|
|
222
|
+
projectRoot,
|
|
223
|
+
task: options.task || 'work',
|
|
224
|
+
request: operands.join(' '),
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
if (command === 'context') return getContext({ paths: operands, projectRoot });
|
|
228
|
+
if (command === 'index') return indexCodebase({ projectRoot, queries: operands });
|
|
229
|
+
if (command === 'hook') {
|
|
230
|
+
if (operands[0] === 'discover') {
|
|
231
|
+
return { kind: 'discover', ...await codexAdoptionRecommendation({ projectRoot }) };
|
|
232
|
+
}
|
|
233
|
+
if (operands[0] === 'session') {
|
|
234
|
+
return { kind: 'session', ...await codexSessionContext({ projectRoot }) };
|
|
235
|
+
}
|
|
236
|
+
const input = await hookInput();
|
|
237
|
+
if (operands[0] === 'begin') {
|
|
238
|
+
return { kind: 'begin', ...await recordCodexTurn({ input, projectRoot }) };
|
|
239
|
+
}
|
|
240
|
+
if (operands[0] === 'end') {
|
|
241
|
+
return { kind: 'end', ...await discardCodexTurn({ input, projectRoot }) };
|
|
242
|
+
}
|
|
243
|
+
return { kind: 'stop', status: 'ready', output: await completeCodexTurn({ input, projectRoot }) };
|
|
244
|
+
}
|
|
245
|
+
if (command === 'verify') {
|
|
246
|
+
return verify({
|
|
247
|
+
projectRoot,
|
|
248
|
+
onEvent: (event) => {
|
|
249
|
+
if (!options.json) line(process.stderr, event.message);
|
|
250
|
+
},
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
if (command === 'check') return check({ projectRoot });
|
|
254
|
+
fail('CLI_UNKNOWN_COMMAND', `Unknown command: ${command}`);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
export async function runCli(argv = process.argv.slice(2)) {
|
|
258
|
+
let options = {};
|
|
259
|
+
try {
|
|
260
|
+
const parsed = parseCommand(argv);
|
|
261
|
+
if (parsed.command === 'help') {
|
|
262
|
+
process.stdout.write(USAGE);
|
|
263
|
+
return 0;
|
|
264
|
+
}
|
|
265
|
+
options = parsed.options;
|
|
266
|
+
const result = await execute(parsed);
|
|
267
|
+
if (options.json) line(process.stdout, JSON.stringify(result));
|
|
268
|
+
else writeResult(parsed.command, result);
|
|
269
|
+
return ['blocked', 'failed', 'invalid'].includes(result?.status) ? 2 : 0;
|
|
270
|
+
} catch (error) {
|
|
271
|
+
const diagnostic = asDiagnostic(error);
|
|
272
|
+
if (options.json) line(process.stderr, JSON.stringify(diagnostic));
|
|
273
|
+
else line(process.stderr, `${diagnostic.code}: ${diagnostic.message}`);
|
|
274
|
+
return 1;
|
|
275
|
+
}
|
|
276
|
+
}
|