@eventmodelers/cli 1.0.161 → 1.0.162
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 +1 -0
- package/cli.js +2 -1
- package/package.json +1 -1
- package/shared/build-kit/lib/ralph.js +5 -2
- package/shared/build-kit/ralph.sh +8 -5
package/README.md
CHANGED
|
@@ -680,6 +680,7 @@ Flow: `Ready → Planned → InProgress → Handover → InProgress → Done`. P
|
|
|
680
680
|
- **Both sides need the new kit.** An already-installed backend kit keeps its old `ralph.js` and prompts and silently ignores `--handover` (slices still end at `Done`); `re-init` it to pick the feature up.
|
|
681
681
|
- **The platform must know the `Ready` / `Handover` statuses.**
|
|
682
682
|
- A kit declares what it claims in `lib/kit.json` — `{ "pickupStatus": "Handover" }`; absent means `Planned`.
|
|
683
|
+
- `run --status-trigger <status>` overrides that pickup status for a single run (e.g. `--status-trigger Ready`); nothing is saved.
|
|
683
684
|
|
|
684
685
|
The contract itself is the shared `ui-contract` skill's job (see above); it also owns the rule for which status a slice ends at.
|
|
685
686
|
|
package/cli.js
CHANGED
|
@@ -3718,6 +3718,7 @@ credentialFlags(program
|
|
|
3718
3718
|
.option('--dangerously-skip-permissions', 'Run the modeling agent\'s Claude process with --dangerously-skip-permissions, as before the lockdown: every tool call is approved — any shell command, curl to anywhere, any file the user can read or write, every MCP server the machine configures. Off by default because the agent takes chat messages and snippet clicks from any collaborator on the board; pass it only for a board whose collaborators you trust with your shell. Default Claude runner of --modeling/--standalone/--worker/--global only — not with --agent, --exec or --local-ai, which bring their own permission flags.')
|
|
3719
3719
|
.option('--browser', 'Give the locked-down modeling agent a browser: the Playwright MCP server (npx @playwright/mcp) next to the eventmodelers one, for discover-storyboard. Off by default because a browser can reach any site, which the lockdown otherwise rules out. Default Claude runner only; --dangerously-skip-permissions already loads every MCP server the machine configures.')
|
|
3720
3720
|
.option('--handover', 'Backend build kit: for this run only, finish slices that have a UI at `Handover` instead of `Done` (same as the project setting `handover: true`, which `init --handover` / `config --handover on` save — this flag writes nothing). Without it the project setting applies; without both, slices end at `Done`.')
|
|
3721
|
+
.option('--status-trigger <status>', 'Build kit: the slice status the agent picks work up from, for this run only (e.g. Ready, Planned, Handover). Defaults to the kit\'s own pickup status — `Planned` for backend kits, `Handover` for the UI kits. Nothing is written to disk.')
|
|
3721
3722
|
.option('--verbose', 'Log every tool call\'s full input (commands, skill args, file paths) and assistant reasoning text. Default is condensed, high-level per-step logging only.')
|
|
3722
3723
|
.option('--id <id>', 'Pin the agent id this run identifies itself with on the platform. A project install otherwise mints one id per project and reuses it on every restart; --global/--standalone mints a fresh one per run, since two ad-hoc agents for one board must not share a row (the heartbeat is keyed on token + agent_id + agent_type, so the second would replace the first). Pass this when an agent has to keep ONE identity across restarts — a supervisor that already knows the id, or a board where it is the starred "preferred agent". Per-run only: nothing is written to disk.')
|
|
3723
3724
|
.option('--name <name>', 'A human-readable name for this agent, sent with every heartbeat so the board shows which agent is live rather than a bare uuid (e.g. "ci-builder", "martins-laptop"). Per-run only, like --id: the persistent name is `agentName` in config.json (set via `init --name` / `init-config --name`), and this overrides it for one run without writing anything.')
|
|
@@ -3988,7 +3989,7 @@ credentialFlags(program
|
|
|
3988
3989
|
// local-only branch even when .eventmodelers/config.json has valid credentials.
|
|
3989
3990
|
// RALPH_AGENT_ID/RALPH_AGENT_NAME (--id/--name) are read in ralph.js's startRalph, so
|
|
3990
3991
|
// they reach both node runners but not ralph.sh, which has no heartbeat to identify.
|
|
3991
|
-
execSync(cmd, { cwd: kitDir, stdio: 'inherit', env: { ...process.env, RALPH_VERBOSE: opts.verbose ? '1' : '', RALPH_LOCAL: opts.local ? '1' : '', RALPH_HANDOVER: opts.handover ? '1' : '', RALPH_AGENT_ID: identity.agentId ?? '', RALPH_AGENT_NAME: identity.agentName ?? '', ...(typeof localAiTarget === 'string' ? { LOCAL_AI_TARGET: localAiTarget } : {}), ...(typeof opts.exec === 'string' ? { RALPH_EXEC_CMD: opts.exec } : {}) } });
|
|
3992
|
+
execSync(cmd, { cwd: kitDir, stdio: 'inherit', env: { ...process.env, RALPH_VERBOSE: opts.verbose ? '1' : '', RALPH_LOCAL: opts.local ? '1' : '', RALPH_HANDOVER: opts.handover ? '1' : '', RALPH_STATUS_TRIGGER: opts.statusTrigger ? String(opts.statusTrigger).trim() : '', RALPH_AGENT_ID: identity.agentId ?? '', RALPH_AGENT_NAME: identity.agentName ?? '', ...(typeof localAiTarget === 'string' ? { LOCAL_AI_TARGET: localAiTarget } : {}), ...(typeof opts.exec === 'string' ? { RALPH_EXEC_CMD: opts.exec } : {}) } });
|
|
3992
3993
|
} catch (err) {
|
|
3993
3994
|
process.exit(err.status || 1);
|
|
3994
3995
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eventmodelers/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.162",
|
|
4
4
|
"description": "Eventmodelers CLI — real-time Claude agent + skills for Claude Code, for any stack (Node, Supabase, Axon, OpenCQRS, UmaDB, Kurrent, or modeling-only)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -521,8 +521,11 @@ function hasPendingTasks(kitDir) {
|
|
|
521
521
|
|
|
522
522
|
// The slice status this kit claims work from. A stack declares it in `lib/kit.json`
|
|
523
523
|
// ({ "pickupStatus": "Handover" } for the UI kits, which build what a backend kit handed over);
|
|
524
|
-
// absent means "Planned", the backend default.
|
|
524
|
+
// absent means "Planned", the backend default. `run --status-trigger <status>` (RALPH_STATUS_TRIGGER)
|
|
525
|
+
// overrides either for that run.
|
|
525
526
|
export function readPickupStatus(kitDir) {
|
|
527
|
+
const override = (process.env.RALPH_STATUS_TRIGGER || '').trim();
|
|
528
|
+
if (override) return override;
|
|
526
529
|
try {
|
|
527
530
|
const s = JSON.parse(readFileSync(join(kitDir, 'lib', 'kit.json'), 'utf-8')).pickupStatus;
|
|
528
531
|
if (typeof s === 'string' && s.trim()) return s.trim();
|
|
@@ -703,7 +706,7 @@ function taskRequest(planned = null, cfg = null, pickupStatus = 'Planned') {
|
|
|
703
706
|
: 'process the pending tasks in tasks.json';
|
|
704
707
|
// Stated explicitly so the agent never has to work it out from config.json: this run's effective
|
|
705
708
|
// value, which is what the `ui-contract` skill (Step 4) follows. UI kits (pickup Handover) ignore it.
|
|
706
|
-
const handover = planned && pickupStatus
|
|
709
|
+
const handover = planned && pickupStatus.toLowerCase() !== 'handover' ? `\nHandover: ${resolveHandover(cfg) ? 'on' : 'off'}\n` : '';
|
|
707
710
|
return `\n\n---\n\nYour task now: ${task}, following the instructions above. Start immediately.\n${handover}`;
|
|
708
711
|
}
|
|
709
712
|
|
|
@@ -41,9 +41,12 @@ has_pending_tasks() {
|
|
|
41
41
|
[[ "$content" != "[]" && -n "$content" ]]
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
#
|
|
44
|
+
# Status this loop picks work up from — `run --status-trigger <status>` (RALPH_STATUS_TRIGGER), default Planned
|
|
45
|
+
PICKUP_STATUS="${RALPH_STATUS_TRIGGER:-Planned}"
|
|
46
|
+
|
|
47
|
+
# Returns 0 if any JSON under .build-kit/.slices/ contains a slice in the pickup status
|
|
45
48
|
has_planned_slices() {
|
|
46
|
-
grep -rqi
|
|
49
|
+
grep -rqi "\"status\"[[:space:]]*:[[:space:]]*\"$PICKUP_STATUS\"" "$KIT_DIR/.slices/" --include='index.json' 2>/dev/null
|
|
47
50
|
}
|
|
48
51
|
|
|
49
52
|
# Returns the title of the first "Planned" slice, or empty string
|
|
@@ -54,10 +57,10 @@ get_planned_slice_title() {
|
|
|
54
57
|
title=$(node -e "
|
|
55
58
|
try {
|
|
56
59
|
const d = JSON.parse(require('fs').readFileSync(process.argv[1], 'utf-8'));
|
|
57
|
-
const s = (d.slices||[]).find(s => (s.status||'').toLowerCase() ===
|
|
60
|
+
const s = (d.slices||[]).find(s => (s.status||'').toLowerCase() === process.argv[2].toLowerCase());
|
|
58
61
|
if (s) process.stdout.write(s.slice || s.id || '');
|
|
59
62
|
} catch(e) {}
|
|
60
|
-
" "$index_file" 2>/dev/null)
|
|
63
|
+
" "$index_file" "$PICKUP_STATUS" 2>/dev/null)
|
|
61
64
|
if [[ -n "$title" ]]; then
|
|
62
65
|
echo "$title"
|
|
63
66
|
return
|
|
@@ -95,7 +98,7 @@ while [[ "$ITERATIONS" -eq 0 || "$cycle" -lt "$ITERATIONS" ]]; do
|
|
|
95
98
|
|
|
96
99
|
if has_planned_slices; then
|
|
97
100
|
slice_title=$(get_planned_slice_title)
|
|
98
|
-
run_agent "onPlannedSlice: building \"$slice_title\"..." "$(cat "$BACKEND_PROMPT_FILE"; task_request "build the
|
|
101
|
+
run_agent "onPlannedSlice: building \"$slice_title\"..." "$(cat "$BACKEND_PROMPT_FILE"; task_request "build the $PICKUP_STATUS slice \"$slice_title\"")"
|
|
99
102
|
echo "[$(date -u +%H:%M:%S)] Slice \"$slice_title\" build complete — waiting for next slice"
|
|
100
103
|
ran_something=true
|
|
101
104
|
fi
|