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.
Files changed (73) hide show
  1. package/.agents/plugins/marketplace.json +20 -0
  2. package/README.md +443 -0
  3. package/bin/genesis.js +15 -0
  4. package/docs/assurance-model.md +26 -0
  5. package/docs/prompt-integration.md +98 -0
  6. package/docs/stack-components.md +304 -0
  7. package/package.json +57 -7
  8. package/plugins/genesis/.codex-plugin/plugin.json +19 -0
  9. package/plugins/genesis/hooks.json +18 -0
  10. package/prompts/blueprint.txt +9 -0
  11. package/prompts/describe.txt +17 -0
  12. package/prompts/deslop.txt +14 -0
  13. package/prompts/program.txt +12 -0
  14. package/prompts/reconcile.txt +12 -0
  15. package/prompts/review.txt +12 -0
  16. package/prompts/start.txt +30 -0
  17. package/prompts/work.txt +28 -0
  18. package/skills/genesis-deslop/SKILL.md +36 -0
  19. package/skills/genesis-deslop/agents/openai.yaml +4 -0
  20. package/skills/genesis-program/SKILL.md +66 -0
  21. package/skills/genesis-program/agents/openai.yaml +4 -0
  22. package/skills/genesis-project/SKILL.md +53 -0
  23. package/skills/genesis-project/agents/openai.yaml +4 -0
  24. package/src/cli.js +276 -0
  25. package/src/index/agent-skills.js +425 -0
  26. package/src/index/assets.js +19 -0
  27. package/src/index/blueprint.js +38 -0
  28. package/src/index/check.js +102 -0
  29. package/src/index/code-index.js +283 -0
  30. package/src/index/code-indexers/ast-grep.js +414 -0
  31. package/src/index/codex-hooks.js +367 -0
  32. package/src/index/codex-plugin.js +73 -0
  33. package/src/index/context.js +137 -0
  34. package/src/index/environment-files.js +19 -0
  35. package/src/index/errors.js +26 -0
  36. package/src/index/git.js +26 -0
  37. package/src/index/init.js +48 -0
  38. package/src/index/launch.js +34 -0
  39. package/src/index/paths.js +10 -0
  40. package/src/index/process.js +89 -0
  41. package/src/index/program.js +181 -0
  42. package/src/index/project-files.js +24 -0
  43. package/src/index/project-state.js +87 -0
  44. package/src/index/prompt.js +347 -0
  45. package/src/index/stack-catalog.js +72 -0
  46. package/src/index/stack-command.js +65 -0
  47. package/src/index/stack-composition.js +38 -0
  48. package/src/index/stack-environment-files.js +83 -0
  49. package/src/index/stack-launch.js +428 -0
  50. package/src/index/stack-piece.js +283 -0
  51. package/src/index/stack-preflight.js +25 -0
  52. package/src/index/stack-process.js +25 -0
  53. package/src/index/stack-workspace-setup.js +129 -0
  54. package/src/index/stack.js +302 -0
  55. package/src/index/utils.js +85 -0
  56. package/src/index/verification.js +77 -0
  57. package/src/index/workspace-setup.js +55 -0
  58. package/src/index.js +102 -0
  59. package/stacks/pieces/cpp.md +22 -0
  60. package/stacks/pieces/csharp.md +22 -0
  61. package/stacks/pieces/go.md +22 -0
  62. package/stacks/pieces/java.md +22 -0
  63. package/stacks/pieces/jskit-mysql.md +37 -0
  64. package/stacks/pieces/jskit.md +70 -0
  65. package/stacks/pieces/kotlin.md +22 -0
  66. package/stacks/pieces/mysql.md +18 -0
  67. package/stacks/pieces/nodejs.md +25 -0
  68. package/stacks/pieces/php.md +23 -0
  69. package/stacks/pieces/python.md +23 -0
  70. package/stacks/pieces/ruby.md +22 -0
  71. package/stacks/pieces/rust.md +22 -0
  72. package/stacks/pieces/shell.md +23 -0
  73. package/stacks/pieces/vue.md +19 -0
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Genesis Program"
3
+ short_description: "Explain product intent and public operations"
4
+ default_prompt: "Use $genesis-program to reconcile the Blueprint and subsystem Program with this codebase."
@@ -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.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Genesis Project"
3
+ short_description: "Work safely in a Genesis project"
4
+ default_prompt: "Use $genesis-project to make this change with the project Blueprint, Program, Stack, and verification context."
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
+ }