@eventmodelers/cli 1.0.163 → 2.0.1
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 +22 -27
- package/RELEASE_NOTES.md +20 -2
- package/cli.js +461 -225
- package/lib/adapters/spec-kitty-adapter.js +3 -7
- package/lib/global-agent-id.js +45 -0
- package/lib/modeling-local-ai.js +4 -2
- package/package.json +1 -1
- package/shared/build-kit/README.md +4 -19
- package/shared/build-kit/lib/agent-lock.js +75 -0
- package/shared/build-kit/lib/agent-name.js +27 -0
- package/shared/build-kit/lib/event-prune.js +58 -0
- package/shared/build-kit/lib/events-view.js +121 -0
- package/shared/build-kit/lib/local-ai-agent.js +14 -26
- package/shared/build-kit/lib/mcp-register.js +17 -1
- package/shared/build-kit/lib/prompt-journal.js +191 -0
- package/shared/build-kit/lib/prompt-replay.js +35 -0
- package/shared/build-kit/lib/ralph.js +201 -156
- package/shared/build-kit/lib/slice-curation.js +40 -0
- package/shared/build-kit/lib/slice-events.js +93 -0
- package/shared/build-kit/lib/slice-git.js +86 -0
- package/shared/build-kit/lib/slice-learnings.js +197 -0
- package/shared/build-kit/lib/slice-projection.js +101 -0
- package/shared/build-kit/lib/slice-run.js +181 -0
- package/shared/build-kit/lib/slice-state.js +182 -0
- package/shared/build-kit/lib/slice-tasks.js +35 -0
- package/shared/build-kit/ralph-claude.js +4 -2
- package/shared/build-kit/ralph-exec.js +4 -2
- package/shared/build-kit/ralph-local-ai.js +5 -3
- package/shared/skills/learn-eventmodelers-api/SKILL.md +13 -0
- package/shared/skills/request-feedback/SKILL.md +1 -2
- package/shared/skills/ui-contract/SKILL.md +5 -3
- package/stacks/axon/templates/build-kit/CLAUDE.md +3 -3
- package/stacks/axon/templates/build-kit/lib/AGENT.md +6 -7
- package/stacks/axon/templates/build-kit/lib/backend-prompt.md +20 -42
- package/stacks/axon/templates/build-kit/lib/prompt.md +18 -41
- package/stacks/blank/templates/build-kit/CLAUDE.md +3 -3
- package/stacks/blank/templates/build-kit/lib/AGENT.md +6 -7
- package/stacks/blank/templates/build-kit/lib/backend-prompt.md +20 -37
- package/stacks/blank/templates/build-kit/lib/prompt.md +19 -42
- package/stacks/classic/templates/.claude/skills/build-automation/SKILL.md +1 -1
- package/stacks/classic/templates/.claude/skills/build-state-change/SKILL.md +1 -1
- package/stacks/classic/templates/.claude/skills/build-state-view/SKILL.md +2 -2
- package/stacks/classic/templates/.claude/skills/record-evidence/SKILL.md +2 -2
- package/stacks/classic/templates/build-kit/CLAUDE.md +3 -3
- package/stacks/classic/templates/build-kit/lib/AGENT.md +6 -7
- package/stacks/classic/templates/build-kit/lib/backend-prompt.md +20 -38
- package/stacks/classic/templates/build-kit/lib/prompt.md +19 -42
- package/stacks/kurrent/templates/build-kit/CLAUDE.md +3 -4
- package/stacks/kurrent/templates/build-kit/lib/AGENT.md +6 -7
- package/stacks/kurrent/templates/build-kit/lib/backend-prompt.md +20 -42
- package/stacks/kurrent/templates/build-kit/lib/prompt.md +18 -41
- package/stacks/modeling-kit/templates/.claude/skills/detect-model-drift/SKILL.md +1 -1
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-core-rules/SKILL.md +2 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-elaborating-scenarios/SKILL.md +7 -3
- package/stacks/modeling-kit/templates/.claude/skills/wdyt/SKILL.md +1 -1
- package/stacks/modeling-kit/templates/kit/CLAUDE-STANDALONE.md +3 -4
- package/stacks/modeling-kit/templates/kit/CLAUDE.md +9 -24
- package/stacks/modeling-kit/templates/kit/README.md +1 -1
- package/stacks/modeling-kit/templates/kit/lib/config.js +1 -1
- package/stacks/node/templates/build-kit/CLAUDE.md +3 -3
- package/stacks/node/templates/build-kit/lib/AGENT.md +6 -7
- package/stacks/node/templates/build-kit/lib/backend-prompt.md +20 -42
- package/stacks/node/templates/build-kit/lib/prompt.md +18 -41
- package/stacks/opencqrs/templates/build-kit/CLAUDE.md +3 -4
- package/stacks/opencqrs/templates/build-kit/lib/AGENT.md +6 -7
- package/stacks/opencqrs/templates/build-kit/lib/backend-prompt.md +20 -42
- package/stacks/opencqrs/templates/build-kit/lib/prompt.md +18 -41
- package/stacks/react/templates/.claude/skills/build-state-change/SKILL.md +1 -1
- package/stacks/react/templates/.claude/skills/build-state-view/SKILL.md +1 -1
- package/stacks/react/templates/build-kit/CLAUDE.md +3 -3
- package/stacks/react/templates/build-kit/lib/AGENT.md +6 -7
- package/stacks/react/templates/build-kit/lib/backend-prompt.md +20 -37
- package/stacks/react/templates/build-kit/lib/prompt.md +19 -42
- package/stacks/supabase/templates/build-kit/CLAUDE.md +3 -3
- package/stacks/supabase/templates/build-kit/lib/AGENT.md +6 -7
- package/stacks/supabase/templates/build-kit/lib/backend-prompt.md +20 -42
- package/stacks/supabase/templates/build-kit/lib/prompt.md +18 -41
- package/stacks/supabase-react/templates/.claude/skills/build-state-change/SKILL.md +2 -2
- package/stacks/supabase-react/templates/.claude/skills/build-state-view/SKILL.md +2 -2
- package/stacks/supabase-react/templates/build-kit/CLAUDE.md +3 -3
- package/stacks/supabase-react/templates/build-kit/lib/AGENT.md +6 -7
- package/stacks/supabase-react/templates/build-kit/lib/backend-prompt.md +20 -37
- package/stacks/supabase-react/templates/build-kit/lib/prompt.md +19 -42
- package/stacks/umadb/templates/build-kit/CLAUDE.md +3 -3
- package/stacks/umadb/templates/build-kit/lib/AGENT.md +6 -7
- package/stacks/umadb/templates/build-kit/lib/backend-prompt.md +20 -42
- package/stacks/umadb/templates/build-kit/lib/prompt.md +18 -41
- package/shared/bridge/spec-kitty/bridge-spec-kitty-specify/SKILL.md +0 -125
- package/shared/bridge/spec-kitty/bridge-spec-kitty-tasks/SKILL.md +0 -95
- package/shared/build-kit/lib/agent.sh +0 -20
- package/shared/build-kit/ralph.sh +0 -111
- package/shared/build-kit/realtime-agent.js +0 -20
- package/stacks/bridge/templates/bridge/lib/AGENT.md +0 -47
- package/stacks/bridge/templates/bridge/lib/prompt.md +0 -111
- package/stacks/bridge/templates/bridge/ralph-claude.js +0 -50
- package/stacks/bridge/templates/bridge/ralph-hook.js +0 -103
- package/stacks/bridge/templates/bridge/ralph-local-ai.js +0 -43
- package/stacks/bridge/templates/bridge/ralph-static.js +0 -90
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// Bridge loop that hands each batch of slice changes to an arbitrary external
|
|
3
|
-
// command instead of an AI agent — e.g. commit + push .slices/ and let a CI
|
|
4
|
-
// pipeline take it from there. No Claude/Ollama call happens in this mode.
|
|
5
|
-
//
|
|
6
|
-
// Configure the hook with `bridge --hook "<command>"` (one-off) or persist a
|
|
7
|
-
// default with `init --bridge --target <name> --hook "<command>"`.
|
|
8
|
-
//
|
|
9
|
-
// Usage: node ralph-hook.js [project_dir]
|
|
10
|
-
// BRIDGE_HOOK_CMD="git add .slices && git commit -m sync && git push" node ralph-hook.js
|
|
11
|
-
|
|
12
|
-
import { startRalph } from './lib/ralph.js';
|
|
13
|
-
import { spawn } from 'child_process';
|
|
14
|
-
import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs';
|
|
15
|
-
import { dirname, join, resolve } from 'path';
|
|
16
|
-
import { fileURLToPath } from 'url';
|
|
17
|
-
|
|
18
|
-
const kitDir = dirname(fileURLToPath(import.meta.url));
|
|
19
|
-
const projectDir = process.argv[2] ? resolve(process.argv[2]) : resolve(kitDir, '..');
|
|
20
|
-
|
|
21
|
-
// bridge.json (not .eventmodelers/config.json) — a plain, committed sibling
|
|
22
|
-
// file, since target/hookCommand are project policy meant to be shared with
|
|
23
|
-
// every teammate and CI runner, not gitignored per-machine state.
|
|
24
|
-
function loadBridgeConfig() {
|
|
25
|
-
const p = join(kitDir, 'bridge.json');
|
|
26
|
-
if (!existsSync(p)) return {};
|
|
27
|
-
try { return JSON.parse(readFileSync(p, 'utf-8')); } catch { return {}; }
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const hookCmd = process.env.BRIDGE_HOOK_CMD || loadBridgeConfig().hookCommand;
|
|
31
|
-
if (!hookCmd) {
|
|
32
|
-
console.error('[bridge-hook] No hook command configured.');
|
|
33
|
-
console.error(' Set one for this run: eventmodelers bridge --hook "<command>"');
|
|
34
|
-
console.error(' Or persist a default: eventmodelers init --bridge --target <name> --hook "<command>"');
|
|
35
|
-
process.exit(1);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const tasksPath = join(kitDir, 'tasks.json');
|
|
39
|
-
|
|
40
|
-
function readTasks() {
|
|
41
|
-
try {
|
|
42
|
-
return JSON.parse(readFileSync(tasksPath, 'utf-8'));
|
|
43
|
-
} catch {
|
|
44
|
-
return [];
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Batched, not one-task-at-a-time: a hook like "commit + push .slices/" acts
|
|
49
|
-
// on the whole current board export in one shot (already fresh — lib/ralph.js
|
|
50
|
-
// re-syncs .slices/ before every task is queued), not on a single slice's
|
|
51
|
-
// translation the way an AI agent does. Only the tasks present at invocation
|
|
52
|
-
// time are cleared afterward — anything the realtime agent queues *while* the
|
|
53
|
-
// hook is still running is left in place for the next tick, so a slice change
|
|
54
|
-
// arriving mid-run is never silently dropped.
|
|
55
|
-
function runHook() {
|
|
56
|
-
const batch = readTasks();
|
|
57
|
-
if (!batch.length) return Promise.resolve();
|
|
58
|
-
|
|
59
|
-
const batchFilePath = join(kitDir, 'last-hook-batch.json');
|
|
60
|
-
mkdirSync(kitDir, { recursive: true });
|
|
61
|
-
writeFileSync(batchFilePath, JSON.stringify(batch, null, 2));
|
|
62
|
-
|
|
63
|
-
const latest = batch[batch.length - 1]?.payload ?? {};
|
|
64
|
-
|
|
65
|
-
return new Promise((resolvePromise, reject) => {
|
|
66
|
-
console.log(`[bridge-hook] Running hook for ${batch.length} change(s): ${hookCmd}`);
|
|
67
|
-
const proc = spawn(hookCmd, {
|
|
68
|
-
cwd: projectDir,
|
|
69
|
-
shell: true,
|
|
70
|
-
stdio: 'inherit',
|
|
71
|
-
env: {
|
|
72
|
-
...process.env,
|
|
73
|
-
BRIDGE_BATCH_FILE: batchFilePath,
|
|
74
|
-
BRIDGE_TASK_COUNT: String(batch.length),
|
|
75
|
-
BRIDGE_SLICE_ID: latest.sliceId ?? '',
|
|
76
|
-
BRIDGE_SLICE_TITLE: latest.sliceTitle ?? '',
|
|
77
|
-
BRIDGE_SLICE_STATUS: latest.sliceStatus ?? '',
|
|
78
|
-
BRIDGE_BOARD_ID: latest.boardId ?? '',
|
|
79
|
-
BRIDGE_ORGANIZATION_ID: latest.organizationId ?? '',
|
|
80
|
-
},
|
|
81
|
-
});
|
|
82
|
-
proc.on('close', (code) => {
|
|
83
|
-
if (code !== 0) return reject(new Error(`hook exited ${code}`));
|
|
84
|
-
const handledIds = new Set(batch.map((t) => t.id));
|
|
85
|
-
const remaining = readTasks().filter((t) => !handledIds.has(t.id));
|
|
86
|
-
writeFileSync(tasksPath, JSON.stringify(remaining, null, 2), 'utf-8');
|
|
87
|
-
resolvePromise();
|
|
88
|
-
});
|
|
89
|
-
proc.on('error', reject);
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
startRalph({
|
|
94
|
-
kitDir,
|
|
95
|
-
projectDir,
|
|
96
|
-
onTask: runHook,
|
|
97
|
-
// onPlannedSlice omitted — see stacks/bridge/templates/bridge/ralph-claude.js
|
|
98
|
-
agentType: 'BRIDGE',
|
|
99
|
-
queueAllStatuses: true,
|
|
100
|
-
}).catch((err) => {
|
|
101
|
-
console.error('[ralph] Fatal:', err);
|
|
102
|
-
process.exit(1);
|
|
103
|
-
});
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// Bridge loop using a local AI model as the executor. Same caveats as
|
|
3
|
-
// build-kit's ralph-local-ai.js — lib/local-ai-agent.js is shared as-is (see
|
|
4
|
-
// useShared in cli.js), unmodified for bridge.
|
|
5
|
-
// Backend is selected by dialect, not by a separate runner: Ollama (native
|
|
6
|
-
// /api/chat) or any OpenAI-compatible server (vLLM, LM Studio, llama.cpp, TGI).
|
|
7
|
-
//
|
|
8
|
-
// Usage: node ralph-local-ai.js [project_dir]
|
|
9
|
-
// LOCAL_AI_TARGET=ollama node ralph-local-ai.js # run `ollama serve` first
|
|
10
|
-
// LOCAL_AI_TARGET=vllm node ralph-local-ai.js
|
|
11
|
-
// LOCAL_AI_URL=http://gpu-box:8000/v1 LOCAL_AI_MODEL=Qwen/Qwen3-8B node ralph-local-ai.js
|
|
12
|
-
import { startRalph } from './lib/ralph.js';
|
|
13
|
-
import { spawn } from 'child_process';
|
|
14
|
-
import { dirname, join, resolve } from 'path';
|
|
15
|
-
import { fileURLToPath } from 'url';
|
|
16
|
-
|
|
17
|
-
const kitDir = dirname(fileURLToPath(import.meta.url));
|
|
18
|
-
const projectDir = process.argv[2] ? resolve(process.argv[2]) : resolve(kitDir, '..');
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
function runLocalAi() {
|
|
22
|
-
return new Promise((resolve, reject) => {
|
|
23
|
-
const proc = spawn('node', [join(kitDir, 'lib', 'local-ai-agent.js')], {
|
|
24
|
-
cwd: projectDir,
|
|
25
|
-
stdio: 'inherit',
|
|
26
|
-
env: process.env,
|
|
27
|
-
});
|
|
28
|
-
proc.on('close', (code) => (code === 0 ? resolve() : reject(new Error(`local-ai-agent exited ${code}`))));
|
|
29
|
-
proc.on('error', reject);
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
startRalph({
|
|
34
|
-
kitDir,
|
|
35
|
-
projectDir,
|
|
36
|
-
onTask: runLocalAi,
|
|
37
|
-
// onPlannedSlice omitted — local-ai-agent manages its own task queue
|
|
38
|
-
agentType: 'BRIDGE',
|
|
39
|
-
queueAllStatuses: true,
|
|
40
|
-
}).catch((err) => {
|
|
41
|
-
console.error('[ralph] Fatal:', err);
|
|
42
|
-
process.exit(1);
|
|
43
|
-
});
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// Bridge loop that hands each batch of slice changes to a deterministic JS
|
|
3
|
-
// adapter instead of an AI agent or an arbitrary shell hook — no LLM call
|
|
4
|
-
// happens in this mode. Which adapter runs is picked by bridge.json's target
|
|
5
|
-
// (adapters/<target>-adapter.js); if the installed target has no adapter file
|
|
6
|
-
// yet, this exits with a clear error rather than silently doing nothing.
|
|
7
|
-
//
|
|
8
|
-
// Usage: node ralph-static.js [project_dir]
|
|
9
|
-
|
|
10
|
-
import { startRalph, loadLocalConfig, fetchPlatformConfig } from './lib/ralph.js';
|
|
11
|
-
import { existsSync, readFileSync } from 'fs';
|
|
12
|
-
import { dirname, join, resolve } from 'path';
|
|
13
|
-
import { fileURLToPath, pathToFileURL } from 'url';
|
|
14
|
-
|
|
15
|
-
const kitDir = dirname(fileURLToPath(import.meta.url));
|
|
16
|
-
const projectDir = process.argv[2] ? resolve(process.argv[2]) : resolve(kitDir, '..');
|
|
17
|
-
|
|
18
|
-
function loadBridgeConfig() {
|
|
19
|
-
const p = join(kitDir, 'bridge.json');
|
|
20
|
-
if (!existsSync(p)) return {};
|
|
21
|
-
try {
|
|
22
|
-
return JSON.parse(readFileSync(p, 'utf-8'));
|
|
23
|
-
} catch {
|
|
24
|
-
return {};
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const target = loadBridgeConfig().target;
|
|
29
|
-
if (!target) {
|
|
30
|
-
console.error('[bridge-static] No target configured in bridge.json — run `eventmodelers init --bridge --target <name>` first.');
|
|
31
|
-
process.exit(1);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const adapterPath = join(kitDir, 'adapters', `${target}-adapter.js`);
|
|
35
|
-
if (!existsSync(adapterPath)) {
|
|
36
|
-
console.error(`[bridge-static] No static adapter for target "${target}" (expected ${adapterPath}).`);
|
|
37
|
-
console.error(' Use the default Claude runner for this target instead: `eventmodelers bridge`.');
|
|
38
|
-
process.exit(1);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const local = loadLocalConfig(kitDir);
|
|
42
|
-
|
|
43
|
-
// The adapter itself doesn't know about the bridge loop's .slices/ convention
|
|
44
|
-
// (fetch --spec-kitty calls the same run() with a context name of its own) —
|
|
45
|
-
// this is the one place that convention still applies, so resolve it here.
|
|
46
|
-
function readCurrentContext() {
|
|
47
|
-
const ctxPath = join(kitDir, '.slices', 'current_context.json');
|
|
48
|
-
if (!existsSync(ctxPath)) return null;
|
|
49
|
-
try {
|
|
50
|
-
return JSON.parse(readFileSync(ctxPath, 'utf-8')).name || null;
|
|
51
|
-
} catch {
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
async function runAdapter() {
|
|
57
|
-
const contextName = readCurrentContext();
|
|
58
|
-
if (!contextName) {
|
|
59
|
-
console.log('[bridge-static] No .slices/current_context.json yet — waiting for the first board sync.');
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const { run } = await import(pathToFileURL(adapterPath).href);
|
|
64
|
-
const cfg = await fetchPlatformConfig(local);
|
|
65
|
-
try {
|
|
66
|
-
await run({ cfg, projectDir, contextName });
|
|
67
|
-
} catch (err) {
|
|
68
|
-
// lib/ralph.js retries any onTask failure after 60s forever — right for
|
|
69
|
-
// transient errors (network blips, a slow spec-kitty command), wrong for
|
|
70
|
-
// a missing one-time setup step that retrying can never fix on its own.
|
|
71
|
-
// Adapters flag those with `err.fatal` so we stop instead of looping.
|
|
72
|
-
if (err.fatal) {
|
|
73
|
-
console.error(`[bridge-static] ${err.message}`);
|
|
74
|
-
process.exit(1);
|
|
75
|
-
}
|
|
76
|
-
throw err;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
startRalph({
|
|
81
|
-
kitDir,
|
|
82
|
-
projectDir,
|
|
83
|
-
onTask: runAdapter,
|
|
84
|
-
// onPlannedSlice omitted — see ralph-claude.js in this same directory.
|
|
85
|
-
agentType: 'BRIDGE',
|
|
86
|
-
queueAllStatuses: true,
|
|
87
|
-
}).catch((err) => {
|
|
88
|
-
console.error('[ralph] Fatal:', err);
|
|
89
|
-
process.exit(1);
|
|
90
|
-
});
|