genesis-compiler 1.2.25 → 1.2.26
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 +13 -10
- package/docs/prompt-integration.md +7 -4
- package/package.json +3 -2
- package/plugins/genesis/.codex-plugin/plugin.json +1 -1
- package/plugins/opencode/project-guidance.js +57 -0
- package/src/cli.js +2 -2
- package/src/index/codex-hooks.js +1 -55
- package/src/index/init.js +15 -4
- package/src/index/opencode-plugin.js +28 -0
- package/src/index/session-context.js +55 -0
package/README.md
CHANGED
|
@@ -21,7 +21,8 @@ genesis/
|
|
|
21
21
|
.agents/skills/
|
|
22
22
|
genesis-* Genesis workflow skills
|
|
23
23
|
<technology>/ authoritative skills installed by selected Stack pieces
|
|
24
|
-
.codex/hooks.json
|
|
24
|
+
.codex/hooks.json project-local Codex lifecycle integration
|
|
25
|
+
.opencode/plugins/ project-local OpenCode lifecycle integration
|
|
25
26
|
.genesis/
|
|
26
27
|
machine-city.json derived detailed source and function map
|
|
27
28
|
program-city.json derived simple subsystem and operation map
|
|
@@ -108,12 +109,13 @@ empty or already-adopted project.
|
|
|
108
109
|
|
|
109
110
|
`genesis init` creates an empty Blueprint, a focused engineering approach, an
|
|
110
111
|
empty optional Stack, the current `genesis/version`, three project Agent Skills,
|
|
111
|
-
and
|
|
112
|
+
and project-local guidance adapters for Codex and OpenCode. The skills are ordinary
|
|
112
113
|
[Agent Skills](https://agentskills.io): `genesis-project`, `genesis-program`,
|
|
113
114
|
and `genesis-deslop`, each with standard `SKILL.md` and `agents/openai.yaml`
|
|
114
|
-
metadata. Open `/hooks` once in Codex to review and trust the guidance hook
|
|
115
|
-
|
|
116
|
-
|
|
115
|
+
metadata. Open `/hooks` once in Codex to review and trust the guidance hook;
|
|
116
|
+
OpenCode discovers its local project plugin automatically. Both use the same
|
|
117
|
+
Genesis-owned operating guide for new sessions and after compaction. No
|
|
118
|
+
technology is assumed until you explicitly select Stack components:
|
|
117
119
|
|
|
118
120
|
```bash
|
|
119
121
|
genesis stack add --stack-package genesis-stack nodejs
|
|
@@ -263,11 +265,12 @@ Python, Java, C#, C/C++, PHP, Go, Rust, Ruby, Kotlin, and Shell. A future techno
|
|
|
263
265
|
adds its adapter through its Stack piece rather than teaching Genesis prompts
|
|
264
266
|
to parse that language.
|
|
265
267
|
|
|
266
|
-
The project Codex hook
|
|
267
|
-
|
|
268
|
-
follow-up turn. Implementation prompts
|
|
269
|
-
guidance into the original implementation
|
|
270
|
-
intentional Blueprint and affected Program
|
|
268
|
+
The project Codex hook and OpenCode plugin use the same short operating guide
|
|
269
|
+
for a new session and after compaction. They record no conversation message,
|
|
270
|
+
block no completion, and request no follow-up turn. Implementation prompts
|
|
271
|
+
compose selected Stack `Post-change` guidance into the original implementation
|
|
272
|
+
turn, and the project skill keeps intentional Blueprint and affected Program
|
|
273
|
+
changes aligned there.
|
|
271
274
|
|
|
272
275
|
Deslop runs only when explicitly requested. With no stated scope it reviews the
|
|
273
276
|
latest commit; “the last N commits” reviews the net surviving first-parent
|
|
@@ -77,10 +77,13 @@ does not perform adoption automatically. If the user accepts, Codex runs the
|
|
|
77
77
|
command itself and follows its returned prompt in the same conversation. Other
|
|
78
78
|
hosts can call `adoptProject()` and send its `prompt` directly.
|
|
79
79
|
|
|
80
|
-
Codex can
|
|
81
|
-
|
|
82
|
-
compaction.
|
|
83
|
-
|
|
80
|
+
Codex and OpenCode can use the project-local adapters installed by `genesis
|
|
81
|
+
init`. Both receive the same short operating guide for a new session and after
|
|
82
|
+
compaction. Codex uses `SessionStart` for startup, clear, and compact events.
|
|
83
|
+
OpenCode renders once per session, keeps that value active in its stateless
|
|
84
|
+
model requests, and rerenders after its `session.compacted` event. Neither
|
|
85
|
+
adapter records a user message, authorizes edits, intercepts completion, or
|
|
86
|
+
requests another model turn. Selected `Post-change` contributions are included
|
|
84
87
|
in the original implementation prompt, whose project skill also keeps
|
|
85
88
|
intentional Blueprint and affected Program changes aligned.
|
|
86
89
|
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "genesis-compiler",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.26",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "An agent-independent prompt, multi-language code-index, cleanup, and verification companion with
|
|
5
|
+
"description": "An agent-independent prompt, multi-language code-index, cleanup, and verification companion with project agent guidance.",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "git+https://github.com/mobily-enterprises/genesis-compiler.git"
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
"prompts/start.txt",
|
|
37
37
|
"prompts/work.txt",
|
|
38
38
|
"plugins/genesis",
|
|
39
|
+
"plugins/opencode",
|
|
39
40
|
"profiles",
|
|
40
41
|
"skills",
|
|
41
42
|
"src"
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// Generated by Genesis. Run `genesis migrate` to refresh this project plugin.
|
|
2
|
+
import { execFile } from "node:child_process";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { promisify } from "node:util";
|
|
5
|
+
|
|
6
|
+
const execute = promisify(execFile);
|
|
7
|
+
|
|
8
|
+
async function renderProjectContext(projectRoot) {
|
|
9
|
+
const { stdout } = await execute(
|
|
10
|
+
"genesis",
|
|
11
|
+
["hook", "session", "--project-root", projectRoot],
|
|
12
|
+
{
|
|
13
|
+
cwd: projectRoot,
|
|
14
|
+
maxBuffer: 256 * 1024,
|
|
15
|
+
timeout: 5_000
|
|
16
|
+
}
|
|
17
|
+
);
|
|
18
|
+
return stdout.trimEnd();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function eventSessionId(event = {}) {
|
|
22
|
+
return String(
|
|
23
|
+
event.properties?.sessionID || event.properties?.info?.id || ""
|
|
24
|
+
).trim();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const GenesisProjectGuidance = async ({ directory, worktree } = {}) => {
|
|
28
|
+
const projectRoot = path.resolve(worktree || directory || process.cwd());
|
|
29
|
+
const contexts = new Map();
|
|
30
|
+
|
|
31
|
+
function contextForSession(sessionId) {
|
|
32
|
+
let context = contexts.get(sessionId);
|
|
33
|
+
if (!context) {
|
|
34
|
+
context = renderProjectContext(projectRoot);
|
|
35
|
+
contexts.set(sessionId, context);
|
|
36
|
+
context.catch(() => {
|
|
37
|
+
if (contexts.get(sessionId) === context) contexts.delete(sessionId);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
return context;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
event: async ({ event } = {}) => {
|
|
45
|
+
if (!["session.compacted", "session.deleted"].includes(event?.type)) return;
|
|
46
|
+
const sessionId = eventSessionId(event);
|
|
47
|
+
if (sessionId) contexts.delete(sessionId);
|
|
48
|
+
},
|
|
49
|
+
"experimental.chat.system.transform": async (input = {}, output = {}) => {
|
|
50
|
+
const sessionId = String(input.sessionID || input.sessionId || "").trim();
|
|
51
|
+
if (!sessionId) return;
|
|
52
|
+
const context = await contextForSession(sessionId);
|
|
53
|
+
const system = Array.isArray(output.system) ? output.system : [];
|
|
54
|
+
if (!system.includes(context)) output.system = [...system, context];
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
};
|
package/src/cli.js
CHANGED
|
@@ -21,7 +21,6 @@ import {
|
|
|
21
21
|
} from './index.js';
|
|
22
22
|
import {
|
|
23
23
|
codexAdoptionRecommendation,
|
|
24
|
-
codexSessionContext,
|
|
25
24
|
} from './index/codex-hooks.js';
|
|
26
25
|
import { engineeringProfile, readEngineeringBaseline } from './index/engineering.js';
|
|
27
26
|
import { asDiagnostic, fail } from './index/errors.js';
|
|
@@ -29,6 +28,7 @@ import {
|
|
|
29
28
|
inspectProjectFormat,
|
|
30
29
|
projectFormatDiagnostic,
|
|
31
30
|
} from './index/project-format.js';
|
|
31
|
+
import { projectSessionContext } from './index/session-context.js';
|
|
32
32
|
|
|
33
33
|
const USAGE = `Usage:
|
|
34
34
|
genesis init
|
|
@@ -362,7 +362,7 @@ async function execute({ command, operands, options }, { signal } = {}) {
|
|
|
362
362
|
if (operands[0] === 'discover') {
|
|
363
363
|
return { kind: 'discover', ...await codexAdoptionRecommendation({ projectRoot }) };
|
|
364
364
|
}
|
|
365
|
-
return { kind: 'session', ...await
|
|
365
|
+
return { kind: 'session', ...await projectSessionContext({ projectRoot }) };
|
|
366
366
|
}
|
|
367
367
|
if (command === 'verify') {
|
|
368
368
|
return verify({
|
package/src/index/codex-hooks.js
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
|
|
4
|
-
import { readEngineering, readEngineeringBaseline } from './engineering.js';
|
|
5
4
|
import { GenesisError } from './errors.js';
|
|
6
5
|
import { gitContext } from './git.js';
|
|
7
6
|
import { isProjectContentPath } from './paths.js';
|
|
8
7
|
import { runGit } from './process.js';
|
|
9
|
-
import { readStack } from './stack.js';
|
|
10
8
|
import { normalizeRelative, pathState, writeFileAtomic } from './utils.js';
|
|
11
9
|
|
|
12
10
|
const HOOKS_PATH = '.codex/hooks.json';
|
|
@@ -20,7 +18,7 @@ function hookCommand(action) {
|
|
|
20
18
|
const SESSION_HOOK = {
|
|
21
19
|
event: 'SessionStart',
|
|
22
20
|
group: {
|
|
23
|
-
matcher: '^(startup|
|
|
21
|
+
matcher: '^(startup|clear|compact)$',
|
|
24
22
|
hooks: [{
|
|
25
23
|
type: 'command',
|
|
26
24
|
command: hookCommand('session'),
|
|
@@ -90,58 +88,6 @@ export async function installCodexHooks({ projectRoot } = {}) {
|
|
|
90
88
|
return { status: 'updated', changedFiles: [HOOKS_PATH] };
|
|
91
89
|
}
|
|
92
90
|
|
|
93
|
-
async function optionalStack(projectRoot) {
|
|
94
|
-
try { return await readStack(projectRoot); } catch { return null; }
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
async function optionalEngineering(projectRoot) {
|
|
98
|
-
try {
|
|
99
|
-
return await readEngineering(projectRoot);
|
|
100
|
-
} catch {
|
|
101
|
-
return {
|
|
102
|
-
guidance: [
|
|
103
|
-
'## Universal complexity gate',
|
|
104
|
-
'',
|
|
105
|
-
await readEngineeringBaseline(),
|
|
106
|
-
'',
|
|
107
|
-
'The project engineering profile is invalid. Do not infer a replacement; run the Genesis `check` operation and ask the user before implementation if the selected approach matters.',
|
|
108
|
-
].join('\n'),
|
|
109
|
-
profile: null,
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export async function codexSessionContext({ projectRoot } = {}) {
|
|
115
|
-
const root = (await gitContext(projectRoot)).repositoryRoot;
|
|
116
|
-
const [stack, engineering] = await Promise.all([
|
|
117
|
-
optionalStack(root),
|
|
118
|
-
optionalEngineering(root),
|
|
119
|
-
]);
|
|
120
|
-
const selected = stack?.components.map(({ id }) => id) || [];
|
|
121
|
-
const stackStatus = stack
|
|
122
|
-
? (selected.length > 0 ? selected.join(', ') : 'none')
|
|
123
|
-
: 'unavailable; run the Genesis `check` operation';
|
|
124
|
-
return {
|
|
125
|
-
status: 'ready',
|
|
126
|
-
output: [
|
|
127
|
-
'This is a Genesis-enriched project.',
|
|
128
|
-
'- Read `genesis/blueprint.md`, `genesis/engineering.md`, and `genesis/stack.md` for product intent, engineering approach, and selected technology.',
|
|
129
|
-
'- Use the relevant project Agent Skills below `.agents/skills/`.',
|
|
130
|
-
'- After locating source, run `genesis context <path...>`; before adding a helper or public operation, run `genesis index <name-or-path...>` and reuse an existing owner.',
|
|
131
|
-
'- Program is fallible explanation; code, tests, and runtime behavior remain evidence.',
|
|
132
|
-
'- Keep Blueprint and affected Program explanations aligned with intentional observable product behavior in the same implementation turn. Private restructuring may need only source citations or no explanatory change.',
|
|
133
|
-
'- Deslop only when explicitly requested. Genesis defines its behavior-preserving committed scope; selected Stack components may add technology-specific cleanup guidance.',
|
|
134
|
-
'- This guidance refreshes after startup, resume, clear, and compaction. Continue the active request without restarting completed work.',
|
|
135
|
-
`Engineering profile: ${engineering.profile?.id || 'invalid; run the Genesis `check` operation'}.`,
|
|
136
|
-
`Selected Stack components: ${stackStatus}.`,
|
|
137
|
-
'',
|
|
138
|
-
'ENGINEERING APPROACH',
|
|
139
|
-
'',
|
|
140
|
-
engineering.guidance,
|
|
141
|
-
].join('\n'),
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
|
|
145
91
|
function zeroPaths(buffer) {
|
|
146
92
|
return [...new Set(buffer.toString('utf8').split('\0').map(normalizeRelative).filter(Boolean))];
|
|
147
93
|
}
|
package/src/index/init.js
CHANGED
|
@@ -6,6 +6,7 @@ import { BLUEPRINT_SKELETON_SOURCE } from './blueprint.js';
|
|
|
6
6
|
import { installCodexHooks } from './codex-hooks.js';
|
|
7
7
|
import { ENGINEERING_SKELETON_SOURCE } from './engineering.js';
|
|
8
8
|
import { gitContext } from './git.js';
|
|
9
|
+
import { installOpenCodePlugin } from './opencode-plugin.js';
|
|
9
10
|
import {
|
|
10
11
|
BLUEPRINT_PATH,
|
|
11
12
|
ENGINEERING_PATH,
|
|
@@ -44,22 +45,32 @@ export async function initializeProject({ projectRoot, stackPackages = [] } = {}
|
|
|
44
45
|
await mkdir(path.join(root, PROGRAM_ROOT), { recursive: true });
|
|
45
46
|
const stack = await readStack(root, { stackPackages });
|
|
46
47
|
const skills = await syncProjectSkills({ projectRoot: root, stack });
|
|
47
|
-
const hooks = await
|
|
48
|
+
const [hooks, openCodePlugin] = await Promise.all([
|
|
49
|
+
installCodexHooks({ projectRoot: root }),
|
|
50
|
+
installOpenCodePlugin({ projectRoot: root }),
|
|
51
|
+
]);
|
|
48
52
|
const version = projectFormat.status === 'uninitialized'
|
|
49
53
|
? await createIfMissing(root, PROJECT_VERSION_PATH, CURRENT_PROJECT_FORMAT_SOURCE)
|
|
50
54
|
: null;
|
|
51
|
-
const changedFiles = [
|
|
55
|
+
const changedFiles = [
|
|
56
|
+
...created,
|
|
57
|
+
...hooks.changedFiles,
|
|
58
|
+
...openCodePlugin.changedFiles,
|
|
59
|
+
...skills.changedFiles,
|
|
60
|
+
version,
|
|
61
|
+
]
|
|
52
62
|
.filter(Boolean)
|
|
53
63
|
.sort();
|
|
54
64
|
return {
|
|
55
65
|
status: changedFiles.length > 0 ? 'updated' : 'unchanged',
|
|
56
66
|
summary: changedFiles.length > 0
|
|
57
|
-
? 'Initialized Genesis, Agent Skills, and
|
|
58
|
-
: 'Genesis, its Agent Skills, and
|
|
67
|
+
? 'Initialized Genesis, Agent Skills, and project guidance for Codex and OpenCode.'
|
|
68
|
+
: 'Genesis, its Agent Skills, and project guidance for Codex and OpenCode are already initialized.',
|
|
59
69
|
changedFiles,
|
|
60
70
|
diagnostics: skills.diagnostics,
|
|
61
71
|
guidance: [
|
|
62
72
|
'Open Codex and use /hooks to review and trust the project guidance hook.',
|
|
73
|
+
'OpenCode loads the project guidance plugin automatically.',
|
|
63
74
|
'Genesis workflow skills are available in .agents/skills/.',
|
|
64
75
|
'Describe product intent in genesis/blueprint.md.',
|
|
65
76
|
'Choose the project engineering approach with genesis engineering set <profile>.',
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
|
|
4
|
+
import { gitContext } from './git.js';
|
|
5
|
+
import { writeFileAtomic } from './utils.js';
|
|
6
|
+
|
|
7
|
+
const OPENCODE_PLUGIN_PATH = '.opencode/plugins/genesis-project-guidance.js';
|
|
8
|
+
const OPENCODE_PLUGIN_SOURCE = new URL('../../plugins/opencode/project-guidance.js', import.meta.url);
|
|
9
|
+
|
|
10
|
+
async function existingSource(location) {
|
|
11
|
+
try {
|
|
12
|
+
return await readFile(location, 'utf8');
|
|
13
|
+
} catch (error) {
|
|
14
|
+
if (['ENOENT', 'ENOTDIR'].includes(error?.code)) return null;
|
|
15
|
+
throw error;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export async function installOpenCodePlugin({ projectRoot } = {}) {
|
|
20
|
+
const root = (await gitContext(projectRoot)).repositoryRoot;
|
|
21
|
+
const location = path.join(root, OPENCODE_PLUGIN_PATH);
|
|
22
|
+
const source = await readFile(OPENCODE_PLUGIN_SOURCE, 'utf8');
|
|
23
|
+
if (await existingSource(location) === source) {
|
|
24
|
+
return { status: 'unchanged', changedFiles: [] };
|
|
25
|
+
}
|
|
26
|
+
await writeFileAtomic(location, source);
|
|
27
|
+
return { status: 'updated', changedFiles: [OPENCODE_PLUGIN_PATH] };
|
|
28
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { readEngineering, readEngineeringBaseline } from './engineering.js';
|
|
2
|
+
import { gitContext } from './git.js';
|
|
3
|
+
import { readStack } from './stack.js';
|
|
4
|
+
|
|
5
|
+
async function optionalStack(projectRoot, stackPackages) {
|
|
6
|
+
try { return await readStack(projectRoot, { stackPackages }); } catch { return null; }
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
async function optionalEngineering(projectRoot) {
|
|
10
|
+
try {
|
|
11
|
+
return await readEngineering(projectRoot);
|
|
12
|
+
} catch {
|
|
13
|
+
return {
|
|
14
|
+
guidance: [
|
|
15
|
+
'## Universal complexity gate',
|
|
16
|
+
'',
|
|
17
|
+
await readEngineeringBaseline(),
|
|
18
|
+
'',
|
|
19
|
+
'The project engineering profile is invalid. Do not infer a replacement; run the Genesis `check` operation and ask the user before implementation if the selected approach matters.',
|
|
20
|
+
].join('\n'),
|
|
21
|
+
profile: null,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export async function projectSessionContext({ projectRoot, stackPackages = [] } = {}) {
|
|
27
|
+
const root = (await gitContext(projectRoot)).repositoryRoot;
|
|
28
|
+
const [stack, engineering] = await Promise.all([
|
|
29
|
+
optionalStack(root, stackPackages),
|
|
30
|
+
optionalEngineering(root),
|
|
31
|
+
]);
|
|
32
|
+
const selected = stack?.components.map(({ id }) => id) || [];
|
|
33
|
+
const stackStatus = stack
|
|
34
|
+
? (selected.length > 0 ? selected.join(', ') : 'none')
|
|
35
|
+
: 'unavailable; run the Genesis `check` operation';
|
|
36
|
+
return {
|
|
37
|
+
status: 'ready',
|
|
38
|
+
output: [
|
|
39
|
+
'This is a Genesis-enriched project.',
|
|
40
|
+
'- Read `genesis/blueprint.md`, `genesis/engineering.md`, and `genesis/stack.md` for product intent, engineering approach, and selected technology.',
|
|
41
|
+
'- Use the relevant project Agent Skills below `.agents/skills/`.',
|
|
42
|
+
'- After locating source, run `genesis context <path...>`; before adding a helper or public operation, run `genesis index <name-or-path...>` and reuse an existing owner.',
|
|
43
|
+
'- Program is fallible explanation; code, tests, and runtime behavior remain evidence.',
|
|
44
|
+
'- Keep Blueprint and affected Program explanations aligned with intentional observable product behavior in the same implementation turn. Private restructuring may need only source citations or no explanatory change.',
|
|
45
|
+
'- Deslop only when explicitly requested. Genesis defines its behavior-preserving committed scope; selected Stack components may add technology-specific cleanup guidance.',
|
|
46
|
+
'- This guidance is loaded for a new session and refreshed after compaction. Continue the active request without restarting completed work.',
|
|
47
|
+
`Engineering profile: ${engineering.profile?.id || 'invalid; run the Genesis `check` operation'}.`,
|
|
48
|
+
`Selected Stack components: ${stackStatus}.`,
|
|
49
|
+
'',
|
|
50
|
+
'ENGINEERING APPROACH',
|
|
51
|
+
'',
|
|
52
|
+
engineering.guidance,
|
|
53
|
+
].join('\n'),
|
|
54
|
+
};
|
|
55
|
+
}
|