genesis-compiler 1.2.6 → 1.2.7
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 +34 -17
- package/docs/prompt-integration.md +1 -1
- package/docs/stack-components.md +19 -4
- package/package.json +2 -4
- package/plugins/genesis/.codex-plugin/plugin.json +1 -1
- package/src/cli.js +20 -8
- package/src/index/agent-skills.js +11 -3
- package/src/index/check.js +9 -5
- package/src/index/code-index.js +7 -2
- package/src/index/context.js +2 -2
- package/src/index/deployment.js +2 -2
- package/src/index/environment-files.js +6 -2
- package/src/index/init.js +2 -2
- package/src/index/launch.js +2 -1
- package/src/index/prompt.js +24 -16
- package/src/index/stack-catalog.js +111 -26
- package/src/index/stack.js +60 -8
- package/src/index/verification.js +2 -1
- package/src/index/workspace-setup.js +4 -2
- package/src/index.js +27 -17
- package/stacks/pieces/cpp.md +0 -34
- package/stacks/pieces/csharp.md +0 -22
- package/stacks/pieces/go.md +0 -22
- package/stacks/pieces/java.md +0 -22
- package/stacks/pieces/jskit-mysql.md +0 -56
- package/stacks/pieces/jskit-postgresql.md +0 -56
- package/stacks/pieces/jskit.md +0 -114
- package/stacks/pieces/kotlin.md +0 -22
- package/stacks/pieces/mysql.md +0 -29
- package/stacks/pieces/nodejs.md +0 -36
- package/stacks/pieces/php.md +0 -23
- package/stacks/pieces/postgresql.md +0 -30
- package/stacks/pieces/python.md +0 -23
- package/stacks/pieces/ruby.md +0 -22
- package/stacks/pieces/rust.md +0 -22
- package/stacks/pieces/shell.md +0 -23
- package/stacks/pieces/vue.md +0 -28
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
1
2
|
import { readdir, readFile } from 'node:fs/promises';
|
|
2
3
|
import path from 'node:path';
|
|
3
|
-
import { fileURLToPath } from 'node:url';
|
|
4
4
|
|
|
5
5
|
import { GenesisError } from './errors.js';
|
|
6
6
|
import {
|
|
@@ -8,54 +8,138 @@ import {
|
|
|
8
8
|
parseStackPieceSource,
|
|
9
9
|
} from './stack-piece.js';
|
|
10
10
|
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
const require = createRequire(import.meta.url);
|
|
12
|
+
const PACKAGE_NAME = /^(?:@[a-z0-9._-]+\/)?[a-z0-9._-]+$/u;
|
|
13
|
+
|
|
14
|
+
export function normalizeStackPackageName(value) {
|
|
15
|
+
const name = String(value ?? '').trim();
|
|
16
|
+
if (!PACKAGE_NAME.test(name)) {
|
|
17
|
+
throw new GenesisError(
|
|
18
|
+
'STACK_PACKAGE_INVALID',
|
|
19
|
+
'Stack package names must be ordinary npm package names.',
|
|
20
|
+
{ package: value },
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
return name;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async function packageDirectory(packageName, projectRoot) {
|
|
27
|
+
const roots = [
|
|
28
|
+
...(projectRoot ? createRequire(path.join(projectRoot, 'package.json')).resolve.paths(packageName) || [] : []),
|
|
29
|
+
...(require.resolve.paths(packageName) || []),
|
|
30
|
+
];
|
|
31
|
+
for (const modulesRoot of [...new Set(roots)]) {
|
|
32
|
+
const manifest = path.join(modulesRoot, packageName, 'package.json');
|
|
33
|
+
try {
|
|
34
|
+
const value = JSON.parse(await readFile(manifest, 'utf8'));
|
|
35
|
+
if (value?.name === packageName) return { directory: path.dirname(manifest), manifest: value };
|
|
36
|
+
} catch (error) {
|
|
37
|
+
if (!['ENOENT', 'ENOTDIR'].includes(error?.code)) {
|
|
38
|
+
throw new GenesisError(
|
|
39
|
+
'STACK_PACKAGE_INVALID',
|
|
40
|
+
`Cannot read Stack package ${packageName}: ${error.message}.`,
|
|
41
|
+
{ package: packageName },
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
throw new GenesisError(
|
|
47
|
+
'STACK_PACKAGE_UNAVAILABLE',
|
|
48
|
+
`Selected Stack package is unavailable: ${packageName}. Install it beside Genesis or in the project.`,
|
|
49
|
+
{ package: packageName },
|
|
50
|
+
);
|
|
14
51
|
}
|
|
15
52
|
|
|
16
|
-
|
|
53
|
+
async function readPieceDirectory(
|
|
54
|
+
directory,
|
|
55
|
+
sourcePrefix,
|
|
56
|
+
stackPackage = null,
|
|
57
|
+
stackPackageRoot = null,
|
|
58
|
+
) {
|
|
17
59
|
let entries;
|
|
18
60
|
try {
|
|
19
|
-
entries = await readdir(
|
|
61
|
+
entries = await readdir(directory, { withFileTypes: true });
|
|
20
62
|
} catch (error) {
|
|
21
|
-
if (
|
|
63
|
+
if (['ENOENT', 'ENOTDIR'].includes(error?.code)) {
|
|
22
64
|
throw new GenesisError(
|
|
23
65
|
'STACK_CATALOG_INVALID',
|
|
24
|
-
|
|
25
|
-
{
|
|
66
|
+
`Stack catalog is missing its pieces directory: ${sourcePrefix}.`,
|
|
67
|
+
{ directory, package: stackPackage },
|
|
26
68
|
);
|
|
27
69
|
}
|
|
28
70
|
throw error;
|
|
29
71
|
}
|
|
30
|
-
|
|
31
72
|
const files = entries
|
|
32
73
|
.filter((entry) => entry.isFile() && entry.name.endsWith('.md'))
|
|
33
74
|
.map((entry) => entry.name)
|
|
34
75
|
.sort();
|
|
35
|
-
|
|
76
|
+
if (files.length === 0) {
|
|
77
|
+
throw new GenesisError(
|
|
78
|
+
'STACK_CATALOG_INVALID',
|
|
79
|
+
`Stack catalog contains no pieces: ${sourcePrefix}.`,
|
|
80
|
+
{ directory, package: stackPackage },
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
return Promise.all(files.map(async (file) => {
|
|
36
84
|
const id = normalizeStackPieceId(file.slice(0, -3));
|
|
37
|
-
const source = await readFile(
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
85
|
+
const source = await readFile(path.join(directory, file), 'utf8');
|
|
86
|
+
const piece = parseStackPieceSource(source, { expectedId: id, path: `${sourcePrefix}:${id}` });
|
|
87
|
+
return {
|
|
88
|
+
...piece,
|
|
89
|
+
skill: piece.skill === null ? null : { ...piece.skill, resolveFrom: stackPackageRoot },
|
|
90
|
+
stackPackage,
|
|
91
|
+
};
|
|
42
92
|
}));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async function readExternalStackPieces(packageName, projectRoot) {
|
|
96
|
+
const resolved = await packageDirectory(packageName, projectRoot);
|
|
97
|
+
const relative = resolved.manifest?.genesis?.stackPieces;
|
|
98
|
+
if (
|
|
99
|
+
typeof relative !== 'string'
|
|
100
|
+
|| !relative
|
|
101
|
+
|| relative.includes('\\')
|
|
102
|
+
|| path.isAbsolute(relative)
|
|
103
|
+
|| relative.split('/').some((part) => !part || ['.', '..'].includes(part))
|
|
104
|
+
) {
|
|
105
|
+
throw new GenesisError(
|
|
106
|
+
'STACK_PACKAGE_INVALID',
|
|
107
|
+
`Stack package ${packageName} must declare one safe genesis.stackPieces directory.`,
|
|
108
|
+
{ package: packageName },
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
return readPieceDirectory(
|
|
112
|
+
path.join(resolved.directory, relative),
|
|
113
|
+
`npm:${packageName}`,
|
|
114
|
+
packageName,
|
|
115
|
+
resolved.directory,
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export async function readStackCatalog({ projectRoot, stackPackages = [] } = {}) {
|
|
43
120
|
const catalog = new Map();
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
121
|
+
const packages = [...new Set(stackPackages.map(normalizeStackPackageName))].sort();
|
|
122
|
+
for (const packageName of packages) {
|
|
123
|
+
for (const piece of await readExternalStackPieces(packageName, projectRoot)) {
|
|
124
|
+
const previous = catalog.get(piece.id);
|
|
125
|
+
if (previous) {
|
|
126
|
+
throw new GenesisError(
|
|
127
|
+
'STACK_CATALOG_COLLISION',
|
|
128
|
+
`Stack package ${packageName} collides with installed piece ${piece.id}.`,
|
|
129
|
+
{
|
|
130
|
+
piece: piece.id,
|
|
131
|
+
packages: [previous.stackPackage || 'genesis-compiler', packageName],
|
|
132
|
+
},
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
catalog.set(piece.id, piece);
|
|
51
136
|
}
|
|
52
|
-
catalog.set(piece.id, piece);
|
|
53
137
|
}
|
|
54
138
|
return catalog;
|
|
55
139
|
}
|
|
56
140
|
|
|
57
|
-
export async function
|
|
58
|
-
return [...(await
|
|
141
|
+
export async function listStackCatalogPieces(options = {}) {
|
|
142
|
+
return [...(await readStackCatalog(options)).values()]
|
|
59
143
|
.sort((left, right) => left.id.localeCompare(right.id))
|
|
60
144
|
.map((piece) => ({
|
|
61
145
|
id: piece.id,
|
|
@@ -71,6 +155,7 @@ export async function listBuiltinStackPieces() {
|
|
|
71
155
|
launchTargets: piece.launchTargets.map(({ id }) => id),
|
|
72
156
|
workspaceSetup: piece.workspaceSetupSteps,
|
|
73
157
|
skill: piece.skill === null ? null : piece.skill.path,
|
|
158
|
+
stackPackage: piece.stackPackage,
|
|
74
159
|
resources: piece.resources.map(({ id }) => id),
|
|
75
160
|
}));
|
|
76
161
|
}
|
package/src/index/stack.js
CHANGED
|
@@ -3,7 +3,10 @@ import path from 'node:path';
|
|
|
3
3
|
|
|
4
4
|
import { syncProjectSkills } from './agent-skills.js';
|
|
5
5
|
import { GenesisError } from './errors.js';
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
normalizeStackPackageName,
|
|
8
|
+
readStackCatalog,
|
|
9
|
+
} from './stack-catalog.js';
|
|
7
10
|
import { parseStackCommandLines } from './stack-command.js';
|
|
8
11
|
import { composeStackCityPresentation } from './stack-city-presentation.js';
|
|
9
12
|
import { composeStackDeployment, parseStackDeploymentLines } from './stack-deployment.js';
|
|
@@ -31,8 +34,10 @@ import { STACK_PATH } from './paths.js';
|
|
|
31
34
|
import { sha256, stableJson, writeFileAtomic } from './utils.js';
|
|
32
35
|
|
|
33
36
|
const COMPONENT_LINE = /^- `([a-z0-9]+(?:-[a-z0-9]+)*)`$/u;
|
|
37
|
+
const STACK_PACKAGE_LINE = /^- `((?:@[a-z0-9._-]+\/)?[a-z0-9._-]+)`$/u;
|
|
34
38
|
export const EMPTY_STACK_SOURCE = '# Stack\n\n## Components\n';
|
|
35
39
|
const STACK_SECTIONS = new Set([
|
|
40
|
+
'Stack packages',
|
|
36
41
|
'Components',
|
|
37
42
|
'Resources',
|
|
38
43
|
'Environment defaults',
|
|
@@ -86,6 +91,27 @@ function componentIds(sections) {
|
|
|
86
91
|
return ids;
|
|
87
92
|
}
|
|
88
93
|
|
|
94
|
+
function stackPackageNames(sections) {
|
|
95
|
+
const lines = (sections.get('Stack packages') || []).filter((line) => line.trim());
|
|
96
|
+
const names = lines.map((line) => {
|
|
97
|
+
const match = line.trim().match(STACK_PACKAGE_LINE);
|
|
98
|
+
if (!match) {
|
|
99
|
+
throw new GenesisError(
|
|
100
|
+
'STACK_INVALID',
|
|
101
|
+
'Each Stack package must be exactly one bullet containing its backticked npm package name.',
|
|
102
|
+
{ path: STACK_PATH, observed: line },
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
return normalizeStackPackageName(match[1]);
|
|
106
|
+
});
|
|
107
|
+
if (new Set(names).size !== names.length) {
|
|
108
|
+
throw new GenesisError('STACK_INVALID', 'Stack contains a duplicate Stack package.', {
|
|
109
|
+
path: STACK_PATH,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
return names;
|
|
113
|
+
}
|
|
114
|
+
|
|
89
115
|
function knownPieces(resolution) {
|
|
90
116
|
if (resolution.unknown.length > 0) {
|
|
91
117
|
throw new GenesisError(
|
|
@@ -112,10 +138,14 @@ function renderStack({
|
|
|
112
138
|
environmentFileLines = null,
|
|
113
139
|
launchLines = null,
|
|
114
140
|
resourceLines = null,
|
|
141
|
+
stackPackages = [],
|
|
115
142
|
workspaceSetupLines = null,
|
|
116
143
|
}) {
|
|
117
144
|
return [
|
|
118
145
|
'# Stack',
|
|
146
|
+
...(stackPackages.length > 0
|
|
147
|
+
? ['', '## Stack packages', ...stackPackages.map((name) => `- \`${name}\``)]
|
|
148
|
+
: []),
|
|
119
149
|
'',
|
|
120
150
|
'## Components',
|
|
121
151
|
...componentIdsValue.map((id) => `- \`${id}\``),
|
|
@@ -140,7 +170,7 @@ function renderStack({
|
|
|
140
170
|
].join('\n');
|
|
141
171
|
}
|
|
142
172
|
|
|
143
|
-
export async function addStackPieces({ pieces, projectRoot }) {
|
|
173
|
+
export async function addStackPieces({ pieces, projectRoot, stackPackages = [] }) {
|
|
144
174
|
if (!Array.isArray(pieces) || pieces.length === 0) {
|
|
145
175
|
throw new GenesisError('STACK_PIECE_REQUIRED', 'genesis stack add requires at least one component.');
|
|
146
176
|
}
|
|
@@ -158,11 +188,21 @@ export async function addStackPieces({ pieces, projectRoot }) {
|
|
|
158
188
|
}
|
|
159
189
|
const sections = parseSections(source);
|
|
160
190
|
const existing = componentIds(sections);
|
|
161
|
-
const
|
|
162
|
-
const
|
|
191
|
+
const declaredPackages = stackPackageNames(sections);
|
|
192
|
+
const availablePackages = [...new Set([
|
|
193
|
+
...declaredPackages,
|
|
194
|
+
...stackPackages.map(normalizeStackPackageName),
|
|
195
|
+
])].sort();
|
|
196
|
+
const catalog = await readStackCatalog({ projectRoot, stackPackages: availablePackages });
|
|
197
|
+
const selectedPieces = await Promise.all(
|
|
163
198
|
knownPieces(resolveStackPieces({ catalog, existing, requested }))
|
|
164
199
|
.map((piece) => customizePiece(projectRoot, piece)),
|
|
165
|
-
)
|
|
200
|
+
);
|
|
201
|
+
const selected = selectedPieces.map(({ id }) => id);
|
|
202
|
+
const selectedPackages = [...new Set([
|
|
203
|
+
...declaredPackages,
|
|
204
|
+
...selectedPieces.map(({ stackPackage }) => stackPackage).filter(Boolean),
|
|
205
|
+
])].sort();
|
|
166
206
|
const commandLines = parseStackCommandLines(sections.get('Commands') || [], { path: STACK_PATH })
|
|
167
207
|
.map(({ label, argv }) => `- Verify \`${label}\`: ${argv.map((value) => `\`${value}\``).join(' ')}`);
|
|
168
208
|
const resourceLines = sections.has('Resources') ? sections.get('Resources') : null;
|
|
@@ -203,11 +243,15 @@ export async function addStackPieces({ pieces, projectRoot }) {
|
|
|
203
243
|
environmentFileLines,
|
|
204
244
|
launchLines,
|
|
205
245
|
resourceLines,
|
|
246
|
+
stackPackages: selectedPackages,
|
|
206
247
|
workspaceSetupLines,
|
|
207
248
|
});
|
|
208
249
|
const stackChanged = rendered !== source;
|
|
209
250
|
if (stackChanged) await writeFileAtomic(location, rendered);
|
|
210
|
-
const skills = await syncProjectSkills({
|
|
251
|
+
const skills = await syncProjectSkills({
|
|
252
|
+
projectRoot,
|
|
253
|
+
stack: await readStack(projectRoot, { stackPackages: availablePackages }),
|
|
254
|
+
});
|
|
211
255
|
const changedFiles = [
|
|
212
256
|
...(stackChanged ? [STACK_PATH] : []),
|
|
213
257
|
...skills.changedFiles,
|
|
@@ -262,7 +306,7 @@ async function customizePiece(projectRoot, piece) {
|
|
|
262
306
|
}));
|
|
263
307
|
}
|
|
264
308
|
|
|
265
|
-
export async function readStack(projectRoot) {
|
|
309
|
+
export async function readStack(projectRoot, { stackPackages = [] } = {}) {
|
|
266
310
|
const location = path.join(projectRoot, STACK_PATH);
|
|
267
311
|
let source;
|
|
268
312
|
try {
|
|
@@ -277,7 +321,12 @@ export async function readStack(projectRoot) {
|
|
|
277
321
|
throw error;
|
|
278
322
|
}
|
|
279
323
|
const sections = parseSections(source);
|
|
280
|
-
const
|
|
324
|
+
const declaredPackages = stackPackageNames(sections);
|
|
325
|
+
const availablePackages = [...new Set([
|
|
326
|
+
...declaredPackages,
|
|
327
|
+
...stackPackages.map(normalizeStackPackageName),
|
|
328
|
+
])].sort();
|
|
329
|
+
const catalog = await readStackCatalog({ projectRoot, stackPackages: availablePackages });
|
|
281
330
|
const components = await Promise.all(knownPieces(resolveStackPieces({
|
|
282
331
|
catalog,
|
|
283
332
|
requested: componentIds(sections),
|
|
@@ -325,6 +374,7 @@ export async function readStack(projectRoot) {
|
|
|
325
374
|
return {
|
|
326
375
|
path: STACK_PATH,
|
|
327
376
|
identityHash: sha256(stableJson({
|
|
377
|
+
stackPackages: declaredPackages,
|
|
328
378
|
components: components.map(({ id }) => id),
|
|
329
379
|
cityExclusions: cityPresentation.exclusions,
|
|
330
380
|
cityRegions: cityPresentation.regions,
|
|
@@ -337,6 +387,7 @@ export async function readStack(projectRoot) {
|
|
|
337
387
|
workspaceSetup,
|
|
338
388
|
})),
|
|
339
389
|
components,
|
|
390
|
+
stackPackages: declaredPackages,
|
|
340
391
|
cityExclusions: cityPresentation.exclusions,
|
|
341
392
|
cityRegions: cityPresentation.regions,
|
|
342
393
|
commands,
|
|
@@ -354,6 +405,7 @@ export async function readStack(projectRoot) {
|
|
|
354
405
|
|
|
355
406
|
export function stackPromptContext(stack) {
|
|
356
407
|
return {
|
|
408
|
+
stackPackages: stack.stackPackages,
|
|
357
409
|
components: stack.components.map((piece) => ({
|
|
358
410
|
id: piece.id,
|
|
359
411
|
description: piece.description,
|
|
@@ -20,10 +20,11 @@ export async function verifyProject({
|
|
|
20
20
|
processRunner = runProcess,
|
|
21
21
|
projectRoot,
|
|
22
22
|
signal,
|
|
23
|
+
stackPackages = [],
|
|
23
24
|
timeoutMs = DEFAULT_FINITE_COMMAND_TIMEOUT_MS,
|
|
24
25
|
} = {}) {
|
|
25
26
|
const root = (await gitContext(projectRoot)).repositoryRoot;
|
|
26
|
-
const stack = await readStack(root);
|
|
27
|
+
const stack = await readStack(root, { stackPackages });
|
|
27
28
|
const workspaceSetup = await inspectWorkspaceSetupForStack({ projectRoot: root, stack });
|
|
28
29
|
if (workspaceSetup.status === 'blocked') {
|
|
29
30
|
return {
|
|
@@ -74,9 +74,10 @@ export async function inspectWorkspaceSetupForStack({ projectRoot: root, stack }
|
|
|
74
74
|
/** Read the Stack's workspace preparation recipe without executing it. */
|
|
75
75
|
export async function inspectProjectWorkspaceSetup({
|
|
76
76
|
projectRoot,
|
|
77
|
+
stackPackages = [],
|
|
77
78
|
} = {}) {
|
|
78
79
|
const root = (await gitContext(projectRoot)).repositoryRoot;
|
|
79
|
-
const stack = await readStack(root);
|
|
80
|
+
const stack = await readStack(root, { stackPackages });
|
|
80
81
|
return inspectWorkspaceSetupForStack({ projectRoot: root, stack });
|
|
81
82
|
}
|
|
82
83
|
|
|
@@ -87,10 +88,11 @@ export async function prepareProjectWorkspace({
|
|
|
87
88
|
processRunner = runProcess,
|
|
88
89
|
projectRoot,
|
|
89
90
|
signal,
|
|
91
|
+
stackPackages = [],
|
|
90
92
|
timeoutMs = DEFAULT_FINITE_COMMAND_TIMEOUT_MS,
|
|
91
93
|
} = {}) {
|
|
92
94
|
const root = (await gitContext(projectRoot)).repositoryRoot;
|
|
93
|
-
const stack = await readStack(root);
|
|
95
|
+
const stack = await readStack(root, { stackPackages });
|
|
94
96
|
const setup = await inspectWorkspaceSetupForStack({ projectRoot: root, stack });
|
|
95
97
|
if (setup.status !== 'ready') {
|
|
96
98
|
const summary = setup.diagnostics.map(({ message }) => message).join(' ')
|
package/src/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import { installCodexPlugin } from './index/codex-plugin.js';
|
|
|
9
9
|
import { inspectProjectEnvironment } from './index/environment-files.js';
|
|
10
10
|
import { inspectProjectDeployment } from './index/deployment.js';
|
|
11
11
|
import { inspectProjectLaunch } from './index/launch.js';
|
|
12
|
-
import {
|
|
12
|
+
import { listStackCatalogPieces } from './index/stack-catalog.js';
|
|
13
13
|
import { addStackPieces } from './index/stack.js';
|
|
14
14
|
import { verifyProject } from './index/verification.js';
|
|
15
15
|
import {
|
|
@@ -31,21 +31,26 @@ function withIndexResult(result, index) {
|
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
async function initializeWithIndex(projectRoot) {
|
|
35
|
-
const initialized = await initializeProject({ projectRoot });
|
|
36
|
-
const index = await buildProjectIndex({ projectRoot });
|
|
34
|
+
async function initializeWithIndex(projectRoot, stackPackages = []) {
|
|
35
|
+
const initialized = await initializeProject({ projectRoot, stackPackages });
|
|
36
|
+
const index = await buildProjectIndex({ projectRoot, stackPackages });
|
|
37
37
|
return withIndexResult(initialized, index);
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
export function initialize({ projectRoot = process.cwd() } = {}) {
|
|
41
|
-
return initializeWithIndex(projectRoot);
|
|
40
|
+
export function initialize({ projectRoot = process.cwd(), stackPackages = [] } = {}) {
|
|
41
|
+
return initializeWithIndex(projectRoot, stackPackages);
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
export async function adoptProject({
|
|
45
|
-
|
|
44
|
+
export async function adoptProject({
|
|
45
|
+
projectRoot = process.cwd(),
|
|
46
|
+
request = '',
|
|
47
|
+
stackPackages = [],
|
|
48
|
+
} = {}) {
|
|
49
|
+
const initialized = await initializeWithIndex(projectRoot, stackPackages);
|
|
46
50
|
const description = await generateProjectPrompt({
|
|
47
51
|
projectRoot,
|
|
48
52
|
request,
|
|
53
|
+
stackPackages,
|
|
49
54
|
task: 'adopt',
|
|
50
55
|
});
|
|
51
56
|
return {
|
|
@@ -64,15 +69,15 @@ export function installCodex({ environment = process.env } = {}) {
|
|
|
64
69
|
return installCodexPlugin({ environment });
|
|
65
70
|
}
|
|
66
71
|
|
|
67
|
-
export async function addStack({ pieces, projectRoot = process.cwd() } = {}) {
|
|
72
|
+
export async function addStack({ pieces, projectRoot = process.cwd(), stackPackages = [] } = {}) {
|
|
68
73
|
const root = path.resolve(projectRoot);
|
|
69
|
-
const selected = await addStackPieces({ pieces, projectRoot: root });
|
|
70
|
-
const index = await buildProjectIndex({ projectRoot: root });
|
|
74
|
+
const selected = await addStackPieces({ pieces, projectRoot: root, stackPackages });
|
|
75
|
+
const index = await buildProjectIndex({ projectRoot: root, stackPackages });
|
|
71
76
|
return withIndexResult(selected, index);
|
|
72
77
|
}
|
|
73
78
|
|
|
74
|
-
export function listStackPieces() {
|
|
75
|
-
return
|
|
79
|
+
export function listStackPieces(options = {}) {
|
|
80
|
+
return listStackCatalogPieces(options);
|
|
76
81
|
}
|
|
77
82
|
|
|
78
83
|
export function inspectLaunch(options) {
|
|
@@ -99,12 +104,17 @@ export function generatePrompt(options) {
|
|
|
99
104
|
return generateProjectPrompt(options);
|
|
100
105
|
}
|
|
101
106
|
|
|
102
|
-
export function getContext({ paths, projectRoot = process.cwd() } = {}) {
|
|
103
|
-
return contextForProjectPaths({ paths, projectRoot });
|
|
107
|
+
export function getContext({ paths, projectRoot = process.cwd(), stackPackages = [] } = {}) {
|
|
108
|
+
return contextForProjectPaths({ paths, projectRoot, stackPackages });
|
|
104
109
|
}
|
|
105
110
|
|
|
106
|
-
export function indexCodebase({
|
|
107
|
-
|
|
111
|
+
export function indexCodebase({
|
|
112
|
+
projectRoot = process.cwd(),
|
|
113
|
+
queries = [],
|
|
114
|
+
stackPackages = [],
|
|
115
|
+
write = true,
|
|
116
|
+
} = {}) {
|
|
117
|
+
return buildProjectIndex({ projectRoot, queries, stackPackages, write });
|
|
108
118
|
}
|
|
109
119
|
|
|
110
120
|
export function verify(options) {
|
package/stacks/pieces/cpp.md
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
# Stack piece: cpp
|
|
2
|
-
|
|
3
|
-
## Description
|
|
4
|
-
|
|
5
|
-
C and C++ translation-unit, header, callable, ownership, build, and test conventions.
|
|
6
|
-
|
|
7
|
-
## Requires
|
|
8
|
-
|
|
9
|
-
- Nothing.
|
|
10
|
-
|
|
11
|
-
## Indexers
|
|
12
|
-
|
|
13
|
-
- `cpp`
|
|
14
|
-
|
|
15
|
-
## Adoption
|
|
16
|
-
|
|
17
|
-
- Identify the actual build system and presets, compiler and language level,
|
|
18
|
-
package/runtime dependencies, generated-source steps, and supported build
|
|
19
|
-
configurations without substituting a preferred CMake or Meson layout.
|
|
20
|
-
- Record exact configure/build/test commands and the executable argv, workdir,
|
|
21
|
-
host/port handling, HTTP readiness predicate, and signal/shutdown contract for
|
|
22
|
-
every web-service target.
|
|
23
|
-
- Preserve public headers, ABI and platform assumptions. Treat databases,
|
|
24
|
-
queues, TLS material, and external service credentials as explicit Resources,
|
|
25
|
-
not implicit properties of the native binary.
|
|
26
|
-
|
|
27
|
-
## Deslop
|
|
28
|
-
|
|
29
|
-
- Preserve public header boundaries, ABI expectations, build configuration,
|
|
30
|
-
const correctness, lifetime ownership, and the codebase's C or C++ level.
|
|
31
|
-
- Keep file-local helpers internal and near their callers. Consolidate repeated
|
|
32
|
-
allocation, cleanup, conversion, and error paths with explicit ownership.
|
|
33
|
-
- Remove unused wrappers, speculative templates, duplicate overload plumbing,
|
|
34
|
-
and abstractions that obscure control flow without protecting a real boundary.
|
package/stacks/pieces/csharp.md
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# Stack piece: csharp
|
|
2
|
-
|
|
3
|
-
## Description
|
|
4
|
-
|
|
5
|
-
C# namespace, public type, dependency, lifecycle, and test conventions.
|
|
6
|
-
|
|
7
|
-
## Requires
|
|
8
|
-
|
|
9
|
-
- Nothing.
|
|
10
|
-
|
|
11
|
-
## Indexers
|
|
12
|
-
|
|
13
|
-
- `csharp`
|
|
14
|
-
|
|
15
|
-
## Deslop
|
|
16
|
-
|
|
17
|
-
- Preserve established namespaces, public contracts, dependency injection,
|
|
18
|
-
async ownership, disposal, nullable annotations, and project conventions.
|
|
19
|
-
- Keep private helpers with their owning type. Consolidate repeated mapping,
|
|
20
|
-
validation, and error translation at an existing application boundary.
|
|
21
|
-
- Remove redundant service wrappers, interfaces with no useful substitution
|
|
22
|
-
boundary, and extension methods that only rename direct framework behavior.
|
package/stacks/pieces/go.md
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# Stack piece: go
|
|
2
|
-
|
|
3
|
-
## Description
|
|
4
|
-
|
|
5
|
-
Go package, exported callable, interface, concurrency, resource, and test conventions.
|
|
6
|
-
|
|
7
|
-
## Requires
|
|
8
|
-
|
|
9
|
-
- Nothing.
|
|
10
|
-
|
|
11
|
-
## Indexers
|
|
12
|
-
|
|
13
|
-
- `go`
|
|
14
|
-
|
|
15
|
-
## Deslop
|
|
16
|
-
|
|
17
|
-
- Preserve package ownership, exported APIs, context propagation, error
|
|
18
|
-
wrapping, goroutine lifetime, and standard Go tooling conventions.
|
|
19
|
-
- Keep unexported helpers close to their caller. Consolidate repeated setup,
|
|
20
|
-
validation, cleanup, and conversion only at a clear package boundary.
|
|
21
|
-
- Remove unnecessary interfaces, constructor wrappers, channels, and generic
|
|
22
|
-
helpers that make direct control flow harder to follow.
|
package/stacks/pieces/java.md
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# Stack piece: java
|
|
2
|
-
|
|
3
|
-
## Description
|
|
4
|
-
|
|
5
|
-
Java package, public type, dependency, lifecycle, and test conventions.
|
|
6
|
-
|
|
7
|
-
## Requires
|
|
8
|
-
|
|
9
|
-
- Nothing.
|
|
10
|
-
|
|
11
|
-
## Indexers
|
|
12
|
-
|
|
13
|
-
- `java`
|
|
14
|
-
|
|
15
|
-
## Deslop
|
|
16
|
-
|
|
17
|
-
- Preserve established packages, public interfaces, dependency injection,
|
|
18
|
-
lifecycle ownership, checked-error policy, and build-tool conventions.
|
|
19
|
-
- Keep private helpers with their owning class. Consolidate repeated mapping,
|
|
20
|
-
validation, and resource handling at an existing service or domain boundary.
|
|
21
|
-
- Remove empty facades, single-implementation abstractions, and builder or DTO
|
|
22
|
-
layers that do not protect a real public or compatibility boundary.
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
# Stack piece: jskit-mysql
|
|
2
|
-
|
|
3
|
-
## Description
|
|
4
|
-
|
|
5
|
-
JSKIT MySQL runtime, live-schema CRUD generation, and persistence conventions.
|
|
6
|
-
|
|
7
|
-
## Requires
|
|
8
|
-
|
|
9
|
-
- `jskit`
|
|
10
|
-
- `mysql`
|
|
11
|
-
|
|
12
|
-
## Conflicts
|
|
13
|
-
|
|
14
|
-
- `jskit-postgresql`
|
|
15
|
-
|
|
16
|
-
## Environment defaults
|
|
17
|
-
|
|
18
|
-
- Default `DB_CLIENT`: `mysql2`
|
|
19
|
-
|
|
20
|
-
## Resources
|
|
21
|
-
|
|
22
|
-
```json genesis-resource
|
|
23
|
-
{
|
|
24
|
-
"id": "database",
|
|
25
|
-
"kind": "mysql",
|
|
26
|
-
"environmentAlternatives": [
|
|
27
|
-
{
|
|
28
|
-
"required": ["DATABASE_URL"]
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
"required": ["DB_HOST", "DB_PORT", "DB_NAME", "DB_USER", "DB_PASSWORD"],
|
|
32
|
-
"allowEmpty": ["DB_PASSWORD"]
|
|
33
|
-
}
|
|
34
|
-
]
|
|
35
|
-
}
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
## Adoption
|
|
39
|
-
|
|
40
|
-
- Confirm that the application's effective MySQL environment alternatives and
|
|
41
|
-
driver match this Resource declaration; add a project Resource contract when
|
|
42
|
-
the existing application legitimately differs.
|
|
43
|
-
- Verify from source that the database preparation path discovers every
|
|
44
|
-
package-owned migration, preserves the existing ledger, orders cross-package
|
|
45
|
-
constraints safely, and invokes an app-owned idempotent seed. Do not execute
|
|
46
|
-
it during adoption.
|
|
47
|
-
|
|
48
|
-
## Deslop
|
|
49
|
-
|
|
50
|
-
- Use the installed JSKIT database runtime and generated resource/repository
|
|
51
|
-
seams; do not add a second client, connection factory, CRUD transport, or
|
|
52
|
-
file-persistence fallback.
|
|
53
|
-
- Keep environment normalization, transactions, row mapping, and database
|
|
54
|
-
error translation at one established persistence boundary.
|
|
55
|
-
- Never compete with or rewrite a generator-owned baseline migration. Preserve
|
|
56
|
-
retained migration history and data semantics.
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
# Stack piece: jskit-postgresql
|
|
2
|
-
|
|
3
|
-
## Description
|
|
4
|
-
|
|
5
|
-
JSKIT PostgreSQL runtime, live-schema CRUD generation, and persistence conventions.
|
|
6
|
-
|
|
7
|
-
## Requires
|
|
8
|
-
|
|
9
|
-
- `jskit`
|
|
10
|
-
- `postgresql`
|
|
11
|
-
|
|
12
|
-
## Conflicts
|
|
13
|
-
|
|
14
|
-
- `jskit-mysql`
|
|
15
|
-
|
|
16
|
-
## Environment defaults
|
|
17
|
-
|
|
18
|
-
- Default `DB_CLIENT`: `pg`
|
|
19
|
-
|
|
20
|
-
## Resources
|
|
21
|
-
|
|
22
|
-
```json genesis-resource
|
|
23
|
-
{
|
|
24
|
-
"id": "database",
|
|
25
|
-
"kind": "postgresql",
|
|
26
|
-
"environmentAlternatives": [
|
|
27
|
-
{
|
|
28
|
-
"required": ["DATABASE_URL"]
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
"required": ["DB_HOST", "DB_PORT", "DB_NAME", "DB_USER", "DB_PASSWORD"],
|
|
32
|
-
"allowEmpty": ["DB_PASSWORD"]
|
|
33
|
-
}
|
|
34
|
-
]
|
|
35
|
-
}
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
## Adoption
|
|
39
|
-
|
|
40
|
-
- Confirm that the application's effective PostgreSQL environment alternatives
|
|
41
|
-
and driver match this Resource declaration; add a project Resource contract
|
|
42
|
-
when the existing application legitimately differs.
|
|
43
|
-
- Verify from source that the database preparation path discovers every
|
|
44
|
-
package-owned migration, preserves the existing ledger, orders cross-package
|
|
45
|
-
constraints safely, and invokes an app-owned idempotent seed. Do not execute
|
|
46
|
-
it during adoption.
|
|
47
|
-
|
|
48
|
-
## Deslop
|
|
49
|
-
|
|
50
|
-
- Use the installed JSKIT database runtime and generated resource/repository
|
|
51
|
-
seams; do not add a second client, connection factory, CRUD transport, or
|
|
52
|
-
file-persistence fallback.
|
|
53
|
-
- Keep environment normalization, transactions, row mapping, and database
|
|
54
|
-
error translation at one established persistence boundary.
|
|
55
|
-
- Never compete with or rewrite a generator-owned baseline migration. Preserve
|
|
56
|
-
retained migration history and data semantics.
|