@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.
Files changed (98) hide show
  1. package/README.md +22 -27
  2. package/RELEASE_NOTES.md +20 -2
  3. package/cli.js +461 -225
  4. package/lib/adapters/spec-kitty-adapter.js +3 -7
  5. package/lib/global-agent-id.js +45 -0
  6. package/lib/modeling-local-ai.js +4 -2
  7. package/package.json +1 -1
  8. package/shared/build-kit/README.md +4 -19
  9. package/shared/build-kit/lib/agent-lock.js +75 -0
  10. package/shared/build-kit/lib/agent-name.js +27 -0
  11. package/shared/build-kit/lib/event-prune.js +58 -0
  12. package/shared/build-kit/lib/events-view.js +121 -0
  13. package/shared/build-kit/lib/local-ai-agent.js +14 -26
  14. package/shared/build-kit/lib/mcp-register.js +17 -1
  15. package/shared/build-kit/lib/prompt-journal.js +191 -0
  16. package/shared/build-kit/lib/prompt-replay.js +35 -0
  17. package/shared/build-kit/lib/ralph.js +201 -156
  18. package/shared/build-kit/lib/slice-curation.js +40 -0
  19. package/shared/build-kit/lib/slice-events.js +93 -0
  20. package/shared/build-kit/lib/slice-git.js +86 -0
  21. package/shared/build-kit/lib/slice-learnings.js +197 -0
  22. package/shared/build-kit/lib/slice-projection.js +101 -0
  23. package/shared/build-kit/lib/slice-run.js +181 -0
  24. package/shared/build-kit/lib/slice-state.js +182 -0
  25. package/shared/build-kit/lib/slice-tasks.js +35 -0
  26. package/shared/build-kit/ralph-claude.js +4 -2
  27. package/shared/build-kit/ralph-exec.js +4 -2
  28. package/shared/build-kit/ralph-local-ai.js +5 -3
  29. package/shared/skills/learn-eventmodelers-api/SKILL.md +13 -0
  30. package/shared/skills/request-feedback/SKILL.md +1 -2
  31. package/shared/skills/ui-contract/SKILL.md +5 -3
  32. package/stacks/axon/templates/build-kit/CLAUDE.md +3 -3
  33. package/stacks/axon/templates/build-kit/lib/AGENT.md +6 -7
  34. package/stacks/axon/templates/build-kit/lib/backend-prompt.md +20 -42
  35. package/stacks/axon/templates/build-kit/lib/prompt.md +18 -41
  36. package/stacks/blank/templates/build-kit/CLAUDE.md +3 -3
  37. package/stacks/blank/templates/build-kit/lib/AGENT.md +6 -7
  38. package/stacks/blank/templates/build-kit/lib/backend-prompt.md +20 -37
  39. package/stacks/blank/templates/build-kit/lib/prompt.md +19 -42
  40. package/stacks/classic/templates/.claude/skills/build-automation/SKILL.md +1 -1
  41. package/stacks/classic/templates/.claude/skills/build-state-change/SKILL.md +1 -1
  42. package/stacks/classic/templates/.claude/skills/build-state-view/SKILL.md +2 -2
  43. package/stacks/classic/templates/.claude/skills/record-evidence/SKILL.md +2 -2
  44. package/stacks/classic/templates/build-kit/CLAUDE.md +3 -3
  45. package/stacks/classic/templates/build-kit/lib/AGENT.md +6 -7
  46. package/stacks/classic/templates/build-kit/lib/backend-prompt.md +20 -38
  47. package/stacks/classic/templates/build-kit/lib/prompt.md +19 -42
  48. package/stacks/kurrent/templates/build-kit/CLAUDE.md +3 -4
  49. package/stacks/kurrent/templates/build-kit/lib/AGENT.md +6 -7
  50. package/stacks/kurrent/templates/build-kit/lib/backend-prompt.md +20 -42
  51. package/stacks/kurrent/templates/build-kit/lib/prompt.md +18 -41
  52. package/stacks/modeling-kit/templates/.claude/skills/detect-model-drift/SKILL.md +1 -1
  53. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-core-rules/SKILL.md +2 -0
  54. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-elaborating-scenarios/SKILL.md +7 -3
  55. package/stacks/modeling-kit/templates/.claude/skills/wdyt/SKILL.md +1 -1
  56. package/stacks/modeling-kit/templates/kit/CLAUDE-STANDALONE.md +3 -4
  57. package/stacks/modeling-kit/templates/kit/CLAUDE.md +9 -24
  58. package/stacks/modeling-kit/templates/kit/README.md +1 -1
  59. package/stacks/modeling-kit/templates/kit/lib/config.js +1 -1
  60. package/stacks/node/templates/build-kit/CLAUDE.md +3 -3
  61. package/stacks/node/templates/build-kit/lib/AGENT.md +6 -7
  62. package/stacks/node/templates/build-kit/lib/backend-prompt.md +20 -42
  63. package/stacks/node/templates/build-kit/lib/prompt.md +18 -41
  64. package/stacks/opencqrs/templates/build-kit/CLAUDE.md +3 -4
  65. package/stacks/opencqrs/templates/build-kit/lib/AGENT.md +6 -7
  66. package/stacks/opencqrs/templates/build-kit/lib/backend-prompt.md +20 -42
  67. package/stacks/opencqrs/templates/build-kit/lib/prompt.md +18 -41
  68. package/stacks/react/templates/.claude/skills/build-state-change/SKILL.md +1 -1
  69. package/stacks/react/templates/.claude/skills/build-state-view/SKILL.md +1 -1
  70. package/stacks/react/templates/build-kit/CLAUDE.md +3 -3
  71. package/stacks/react/templates/build-kit/lib/AGENT.md +6 -7
  72. package/stacks/react/templates/build-kit/lib/backend-prompt.md +20 -37
  73. package/stacks/react/templates/build-kit/lib/prompt.md +19 -42
  74. package/stacks/supabase/templates/build-kit/CLAUDE.md +3 -3
  75. package/stacks/supabase/templates/build-kit/lib/AGENT.md +6 -7
  76. package/stacks/supabase/templates/build-kit/lib/backend-prompt.md +20 -42
  77. package/stacks/supabase/templates/build-kit/lib/prompt.md +18 -41
  78. package/stacks/supabase-react/templates/.claude/skills/build-state-change/SKILL.md +2 -2
  79. package/stacks/supabase-react/templates/.claude/skills/build-state-view/SKILL.md +2 -2
  80. package/stacks/supabase-react/templates/build-kit/CLAUDE.md +3 -3
  81. package/stacks/supabase-react/templates/build-kit/lib/AGENT.md +6 -7
  82. package/stacks/supabase-react/templates/build-kit/lib/backend-prompt.md +20 -37
  83. package/stacks/supabase-react/templates/build-kit/lib/prompt.md +19 -42
  84. package/stacks/umadb/templates/build-kit/CLAUDE.md +3 -3
  85. package/stacks/umadb/templates/build-kit/lib/AGENT.md +6 -7
  86. package/stacks/umadb/templates/build-kit/lib/backend-prompt.md +20 -42
  87. package/stacks/umadb/templates/build-kit/lib/prompt.md +18 -41
  88. package/shared/bridge/spec-kitty/bridge-spec-kitty-specify/SKILL.md +0 -125
  89. package/shared/bridge/spec-kitty/bridge-spec-kitty-tasks/SKILL.md +0 -95
  90. package/shared/build-kit/lib/agent.sh +0 -20
  91. package/shared/build-kit/ralph.sh +0 -111
  92. package/shared/build-kit/realtime-agent.js +0 -20
  93. package/stacks/bridge/templates/bridge/lib/AGENT.md +0 -47
  94. package/stacks/bridge/templates/bridge/lib/prompt.md +0 -111
  95. package/stacks/bridge/templates/bridge/ralph-claude.js +0 -50
  96. package/stacks/bridge/templates/bridge/ralph-hook.js +0 -103
  97. package/stacks/bridge/templates/bridge/ralph-local-ai.js +0 -43
  98. package/stacks/bridge/templates/bridge/ralph-static.js +0 -90
package/README.md CHANGED
@@ -92,7 +92,6 @@ your-project/
92
92
  │ ├── ralph-claude.js ← realtime agent + task loop
93
93
  │ ├── ralph-local-ai.js ← same, via a local/self-hosted model
94
94
  │ ├── ralph-exec.js ← same, via an external agent command (Codex CLI, OpenCode, …)
95
- │ ├── ralph.sh ← bash-only loop (no realtime)
96
95
  │ ├── lib/ ← stack-specific agent prompts + helpers
97
96
  │ └── .slices/ ← board slices, written by `fetch`/`listen` (or pre-seeded by `init --demo`)
98
97
  ├── .claude/
@@ -149,7 +148,6 @@ npx @eventmodelers/cli run --local-ai [target] # board work only via a loca
149
148
  npx @eventmodelers/cli run --agent <name> # pick the agent: claude (default), opencode, codex, gemini — bare --agent lists them with their exact commands
150
149
  npx @eventmodelers/cli run --agent <name> --model <id> # …on a given model: -m for opencode/codex/gemini, --model for Claude, LOCAL_AI_MODEL for --local-ai
151
150
  npx @eventmodelers/cli run --exec "<command>" # manual fallback for any other harness (ralph-exec.js) — agent tracing needs its JSON flag, e.g. "codex exec --json --full-auto"
152
- npx @eventmodelers/cli run --bash # bash-only loop, no realtime (ralph.sh)
153
151
  npx @eventmodelers/cli run --local # skip platform config/credential lookup entirely — local-only, no board sync
154
152
  npx @eventmodelers/cli run --modeling # modeling-kit: warm Claude process driven by the board's prompt queue
155
153
  npx @eventmodelers/cli run --standalone # same, plus acting on board changes unprompted — and needs no install at all
@@ -210,7 +208,7 @@ Installing both a build stack and `init-modeling` into the same project reuses t
210
208
 
211
209
  A modeling-kit install has one runtime: a warm Claude process the CLI keeps alive across
212
210
  turns and feeds directly over stdin, so a prompt typed (or spoken) on the board is picked up
213
- with no cold start and no `tasks.json` round trip.
211
+ with no cold start and no task-queue round trip.
214
212
 
215
213
  ```bash
216
214
  npx @eventmodelers/cli run --modeling # react to prompts sent to this board
@@ -273,7 +271,7 @@ pass `--model <id>` as usual.
273
271
 
274
272
  Claude and Gemini need a gateway (e.g. LiteLLM) in front of a non-native server, since they only speak their own protocol.
275
273
 
276
- `--agent`, `--exec`, `--local-ai` and `--bash` each pick the runner, so pass at most one of them —
274
+ `--agent`, `--exec` and `--local-ai` each pick the runner, so pass at most one of them —
277
275
  any two together are rejected. For a local or self-hosted model use `--local-ai`, not `--agent`.
278
276
 
279
277
  To drive either one with a local model instead of Claude, see [Running the modeling agent on a local model](#running-the-modeling-agent-on-a-local-model).
@@ -524,40 +522,37 @@ npx @eventmodelers/cli init-modeling --global
524
522
 
525
523
  Everything else (the kit dir, project scaffold, credentials, MCP registration) still targets the current directory as usual — `--global` only changes where skills land.
526
524
 
527
- ### Bridging to another spec framework
525
+ ### Syncing a context to Spec Kitty
528
526
 
529
- If you drive development with a different spec/task framework (Spec Kitty today; more later) instead of build-kit's own code generation, a **bridge** kit keeps that framework's artifacts in sync with the board instead of writing application code:
527
+ If you drive development with Spec Kitty instead of build-kit's own code generation, `fetch` can restate a context for it in one shot:
530
528
 
531
529
  ```bash
532
- npx @eventmodelers/cli init --bridge --target spec-kitty
533
- npx @eventmodelers/cli bridge
530
+ npx @eventmodelers/cli fetch --context Ticketing --spec-kitty
534
531
  ```
535
532
 
536
- `init --bridge` installs a `.bridge-kit/` (mirrors `.build-kit/`'s realtime + task-queue loop) plus only the skills for the chosen `--target` (`shared/bridge/<target>/`) — a `spec-kitty` bridge never installs Kiro's skills, and vice versa. `bridge` starts the loop: on every board slice change (not just "Planned", unlike build-kit), it regenerates that framework's spec artifacts from the current board state. It doesn't build code and doesn't claim slices.
537
-
538
- For `spec-kitty`, that sync is deterministic and stops well short of writing Spec Kitty's own artifacts — `lib/adapters/spec-kitty-adapter.js` fetches full slice detail and restates it as a plain markdown mission brief (one section per slice, its scenarios verbatim, nothing invented), then calls `spec-kitty intake --force` to install it at `.kittify/mission-brief.md`. It deliberately doesn't create the mission, write `spec.md`, or author work packages — Spec Kitty's own `/spec-kitty.specify` → `/spec-kitty.plan` → `/spec-kitty.tasks` pipeline does that, because those steps need real judgment (work package boundaries, which files a WP owns, which agent profile fits) that only makes sense with actual codebase context, which this adapter doesn't have. What it replaces is Spec Kitty's *interactive discovery interview*: `/spec-kitty.specify`'s own "Brief Context Detection" step reads `.kittify/mission-brief.md` when present and extracts requirements from it instead of asking the user, so the event model — not a live Q&A — becomes the input. No LLM call happens in this adapter's own path, and `bridge` picks it automatically whenever a target has one (`--claude` forces the Claude runner instead). Targets without a static adapter yet fall back to Claude re-running `bridge-<target>-specify`; pass `--local-ai` for the local-model runner instead (same caveat as build-kit's `--local-ai`: `lib/local-ai-agent.js` is shared as-is).
533
+ That sync is deterministic and stops well short of writing Spec Kitty's own artifacts — `lib/adapters/spec-kitty-adapter.js` fetches full slice detail and restates it as a plain markdown mission brief (one section per slice, its scenarios verbatim, nothing invented), then calls `spec-kitty intake --force` to install it at `.kittify/mission-brief.md`. It deliberately doesn't create the mission, write `spec.md`, or author work packages — Spec Kitty's own `/spec-kitty.specify` → `/spec-kitty.plan` → `/spec-kitty.tasks` pipeline does that, because those steps need real judgment (work package boundaries, which files a WP owns, which agent profile fits) that only makes sense with actual codebase context, which this adapter doesn't have. What it replaces is Spec Kitty's *interactive discovery interview*: `/spec-kitty.specify`'s own "Brief Context Detection" step reads `.kittify/mission-brief.md` when present and extracts requirements from it instead of asking the user, so the event model — not a live Q&A — becomes the input. No LLM call happens in this adapter.
539
534
 
540
- Don't want the standing loop at all? `fetch` can call the same adapter for a single one-shot sync, no `.bridge-kit/` install required:
541
-
542
- ```bash
543
- npx @eventmodelers/cli fetch --context Ticketing --spec-kitty
544
- ```
535
+ `spec-kitty init` (Spec Kitty's own project setup) has to have already been run in the project root — the adapter checks for `.kittify/` first and stops with the exact command to run if it's missing, rather than failing deep inside a cryptic `spec-kitty` CLI error. After the sync, run `/spec-kitty.specify` in your coding agent to turn the brief into an actual mission (the plain `spec-kitty specify` CLI command only scaffolds — brief detection is in the agent-driven prompt).
545
536
 
546
- Either way, `spec-kitty init` (Spec Kitty's own project setup) has to have already been run in the project root — the adapter checks for `.kittify/` first and stops with the exact command to run if it's missing, rather than failing deep inside a cryptic `spec-kitty` CLI error. After the sync, run `/spec-kitty.specify` in your coding agent to turn the brief into an actual mission (the plain `spec-kitty specify` CLI command only scaffolds — brief detection is in the agent-driven prompt).
537
+ (The standing bridge loop — `init --bridge` / `bridge` — is retired for now.)
547
538
 
548
- ### Overriding the executor with a hook
539
+ ### Reading the event log
549
540
 
550
- Claude is only the default — some teams don't want an AI agent in this loop at all, e.g. they'd rather just commit + push the board export and let a CI pipeline own the actual translation. `--hook` replaces the AI executor with an arbitrary shell command, run once per batch of slice changes:
541
+ Everything an agent does to a slice, a task, a prompt or a learning is an event in the kit's log (`.build-kit/events/` and `events.log`, or `.agent-modeling-kit/` for a modeling agent). `eventmodelers events` decodes it in the terminal — one line per event, with the slice's title and the first four characters of the agent that wrote it:
551
542
 
552
543
  ```bash
553
- npx @eventmodelers/cli init --bridge --target spec-kitty --hook "git add .slices && git commit -m sync && git push"
554
- npx @eventmodelers/cli bridge
544
+ npx @eventmodelers/cli events # the build kit of this project, else its modeling kit
545
+ npx @eventmodelers/cli events --type claimed,settled # only these event types
546
+ npx @eventmodelers/cli events --slice "Add item" # a slice by id prefix or part of its title
547
+ npx @eventmodelers/cli events --tag ci --last 20 # by tag; only the last 20 that remain
548
+ npx @eventmodelers/cli events --state # what the log folds to: slices, queue, open prompts, learnings
549
+ npx @eventmodelers/cli events --json # the raw events, one per line (pipe to jq)
550
+ npx @eventmodelers/cli events --follow # keep printing as events are appended
551
+ npx @eventmodelers/cli events --kit ../other/.build-kit # another kit's log, from anywhere
552
+ npx @eventmodelers/cli events --global # the global install's log (~/.eventmodelers/kit): what runs without a project install wrote
553
+ npx @eventmodelers/cli events --global --board c2b3b7da # that log mixes every board; --board keeps one (an id prefix)
555
554
  ```
556
555
 
557
- `init --bridge --hook` persists the command to `.bridge-kit/bridge.json` — a plain, **committed** file (unlike `.eventmodelers/config.json`, which is gitignored for credentials) since the hook is project policy meant to be shared by every teammate and CI runner, not per-machine state. `bridge --hook "<command>"` overrides it for a single run without touching that file. Only one executor runs per invocation — `--local-ai`, `--hook`, and `--claude` are mutually exclusive.
558
-
559
- The hook command runs with `BRIDGE_TASK_COUNT`, `BRIDGE_SLICE_ID`/`_TITLE`/`_STATUS` (the most recent change in the batch), and `BRIDGE_BATCH_FILE` (path to the full batch as JSON) in its environment. It's invoked once per batch, not once per slice — any change that arrives while the hook is still running is left queued for the next batch rather than dropped.
560
-
561
556
  ### Claude execution & config resolution
562
557
 
563
558
  During install you can optionally point the agent at a local LLM server instead of the default
@@ -630,7 +625,7 @@ npx @eventmodelers/cli init-config --name ci-builder # name the agent this c
630
625
 
631
626
  ### Naming an agent
632
627
 
633
- Every agent identifies itself to the platform with an `agentId`, and the board's live-agent view shows that bare uuid. A **project install** mints one on first use and reuses it on every restart (`agentIds` in the project root's `.eventmodelers/config.json`). A **standalone/global run** mints a fresh one per run instead: nothing stops two ad-hoc agents running for one board, and since the heartbeat is keyed on `(token, agentId, agentType)`, a shared id would make the second agent replace the first — one agent visible however many are running, and their board writes indistinguishable.
628
+ Every agent identifies itself to the platform with an `agentId`, and the board's live-agent view shows it. An agent keeps **one id**: a **project install** mints it on first use (`agentIds` in the project root's `.eventmodelers/config.json`), a **standalone/global run** keeps one per board and repo — the directory it is started in — in `~/.eventmodelers/agent-ids.json`. It is the same agent on every restart, with its chat sessions, its star on the board and the prompts it holds. Two live processes must not share an id (the heartbeat is keyed on `(token, agentId, agentType)`, so the second would replace the first, and its start-up recovery would hand back the first one's prompts), so each run takes a small lock on its id (`.eventmodelers/locks/` in the project, `~/.eventmodelers/locks/` globally); if another live process already holds it, this run gets a fresh id and, unless you named it, an instance-marked name (`cart-service (modeling) · 3f9a`). `--id` is used as given, with no such check — for a second agent on purpose, or a supervisor that knows the id it wants. Without a name an agent shows as `<repo> (<type>)`, the repo being the `origin` remote's name or the folder.
634
629
 
635
630
  `--name` gives an agent a readable label instead of the uuid — accepted by `init`, `re-init`, and `init-config`, saved into `config.json` as `agentName`, and sent with every heartbeat from then on:
636
631
 
@@ -763,7 +758,7 @@ npx @eventmodelers/cli re-init --modeling # refresh the modeling kit
763
758
  npx @eventmodelers/cli re-init --stack supabase # override which stack to refresh from (manifest missing/stale, or switching stacks)
764
759
  ```
765
760
 
766
- `re-init` re-runs `init` against whichever stack `install-manifest.json` says was installed (no need to pass `--stack` again), but skips step 2 of `init` entirely — the root project scaffold (`package.json`, `src/`, `server.ts`, `docker-compose.yml`, etc.) and the root `CLAUDE.md` router are never touched. Use it after upgrading the CLI to pick up fixes to `ralph.js`/`ralph.sh`/skills without re-scaffolding a project you've since built on top of.
761
+ `re-init` re-runs `init` against whichever stack `install-manifest.json` says was installed (no need to pass `--stack` again), but skips step 2 of `init` entirely — the root project scaffold (`package.json`, `src/`, `server.ts`, `docker-compose.yml`, etc.) and the root `CLAUDE.md` router are never touched. Use it after upgrading the CLI to pick up fixes to `ralph.js`/skills without re-scaffolding a project you've since built on top of.
767
762
 
768
763
  You don't have to remember to: on startup every command prints a 💡 hint (on stderr) when a newer CLI is on npm, or when a kit in the current directory was installed by an older CLI than the one running — naming the exact `re-init` command to run. The npm lookup happens at most once a day (cached in `~/.eventmodelers/update-check.json`, 1.5 s timeout, silent when offline). Set `EVENTMODELERS_NO_UPDATE_CHECK=1` to turn it off; it is also off when `CI` is set.
769
764
 
package/RELEASE_NOTES.md CHANGED
@@ -1,6 +1,24 @@
1
- ## Unreleased
1
+ ## v2.0.0
2
+
3
+ ### Architecture: the kit now runs on an event log
4
+ The CLI's local state used to live in mutable files — `tasks.json` as the queue, `progress.txt` as the learnings journal, a `.claim.json` claim record, and status edited in place in `index.json`/`slice.json`. Concurrent writers, a stale board refresh or a crash could each leave those files disagreeing with the board or with each other (the failure modes are written down in `slice-state-learnings.md`). 2.0.0 replaces all of it with **event sourcing**: everything an agent does to a slice, a task, a prompt or a learning is an immutable event appended to a log, and every other file is a projection folded from that log.
5
+
6
+ - **The store.** One JSON file per event under `.build-kit/events/` (`.agent-modeling-kit/` for the modeling agent), written whole before its id is appended to `events.log`; the index line is what commits the event, so concurrent writers cannot tear the log whatever the event size. Events carry tags and `agent_id`/`organization_id`/`board_id` metadata. The store is git-ignored, and the loop's git rules now live in `.git/info/exclude` and `.git/info/attributes`, so starting an agent never dirties the tracked tree.
7
+ - **A pure core.** `fold` derives status, claim, pending outcome, attempts, blocked state, the task queue, open prompts and learnings from the event list; `decideSettle` and `decideRecovery` turn that into push/discard/release actions. Side effects sit around the fold, not inside it.
8
+ - **Slice lifecycle as events.** The loop claims a slice (`claimed`/`claim-confirmed`), settles it after the build by executing `decideSettle` (push the recorded outcome, or discard the attempt, record `attempt-failed` and put the slice back to its pickup status), and settles claims left by dead processes at the top of every iteration. Board refreshes are recorded as `board-observed`, so a stale refresh during a build can no longer revert what the agent recorded. The build agent records its outcome with `eventmodelers slice-status <status>`; the loop owns the status on the board.
9
+ - **Attempts and auto-blocks come from the log**, not from an in-memory map, so a restart no longer hands a stuck slice a fresh budget.
10
+ - **The task queue is the log.** A slice change arrives as `task-queued` (a newer change to the same slice replaces its task); the loop replays the log for the oldest task, hands it to the agent and appends `task-done`. A change landing mid-turn is just another event.
11
+ - **Prompts are journaled.** `prompt-received`/`prompt-finished` bracket every prompt the modeling agent takes; on start, what a crash left open is looked up on the platform and handed back unless it already finished. Recovery asks the platform who holds a prompt (`claimed_by`) rather than tracking process ids.
12
+ - **Learnings are events.** `eventmodelers learn` records one (topic, tags, scope; duplicates skipped) and `learn --retract` withdraws it; `learnings` lists them. `AGENTS.md` is rendered from the events and adopts lines added by hand, so regenerating never loses them. After `RALPH_CURATE_AFTER` (default 10) new learnings, a curator turn that can only merge and retract tidies the list (`learning-merged`, `learnings-curated`).
13
+ - **Look at it.** `eventmodelers events` decodes the log in the terminal — one line per event with the slice title and the writing agent; `--type`, `--slice`, `--tag`, `--last`, `--json`, `--state` (what the log folds to), `--follow`, `--kit`, `--global` and `--board` narrow or redirect it.
14
+ - **One agent id, one live process.** A standalone run keeps a stable agent id per board and repo, and takes an exclusive lock on it, so two processes never share an id, a heartbeat row or each other's prompts. A global install records nothing, so one board's learnings never surface in another's.
15
+
16
+ ### Breaking changes
17
+ - `tasks.json` is gone. Nothing reads or writes a queue file any more; the stacks' `prompt.md` files lose their queue steps and the `IDLE` reply, and `AGENT.md` is now a reference.
18
+ - `progress.txt` is gone. Learnings go through `eventmodelers learn`, a failed attempt is read from the slice's `lastAttempt`, and a block reason lives on its event.
19
+ - `run --bash` (the bash-only loop: `ralph.sh`, `lib/agent.sh`, `realtime-agent.js`) is retired. The flag is still recognised, only to say so.
20
+ - The bridge kit is retired: `init --bridge` (with `--target`/`--hook`), the `bridge` command and `uninstall --bridge-kit`. `fetch --spec-kitty` keeps working on its own.
2
21
 
3
- ### Features
4
22
  - `run --modeling`/`run --standalone` accept `--local-ai`, so the modeling agent can be driven by a local or self-hosted model instead of Claude. It was previously rejected as a build-kit-only flag, which conflated two different things: `--bash`/`--exec` select a *queue* the modeling loop has no equivalent of, while `--local-ai` selects a *model*. Both wire dialects are supported — `--local-ai` (bare) or `--local-ai ollama` for Ollama's native `POST /api/chat`, and `--local-ai vllm`/`lmstudio`/`llamacpp` for the OpenAI-compatible `POST /v1/chat/completions` that vLLM, LM Studio, llama.cpp-server, TGI and SGLang serve; anything else OpenAI-compatible works via `LOCAL_AI_URL`. The loop itself is untouched: the prompt queue, the standalone board-change lane and its damping, the idle review and the platform's full MCP tool set all behave as before, because everything Claude-specific already sat behind a single `runTurn(text)` seam. What a local model cannot bring along is the part that is not a wire format — the skills (`/place-element`, `/timeline`, `eventmodeling-*`) and the subagent fan-out are Claude Code features — so a self-directed turn does the most valuable piece of work itself, inline, and the board rules it needs come from the new runner's system prompt (`lib/modeling-local-ai.js`) instead of `.agent-modeling-kit/CLAUDE.md`. `--max-agents` is ignored in this mode. Ollama's `num_ctx` is raised to 49152 by default (the MCP tool schemas alone are ~16k tokens, well past Ollama's 4096 default, which would silently truncate the tool block), with a warning when the schemas still fill >60% of it and a turn cap of 24 tool iterations.
5
23
 
6
24
  - `run --non-interactive` never asks anything: the board and credentials that resolve from flags, `EVENTMODELERS_*` env vars and the config files are final, and an incomplete set fails the run with the reason instead of being interviewed for. A missing TTY already implied this, which covered CI and most supervisors, but not a container started with `-it` or a loop started from a terminal — stdin is a TTY nobody is watching, and the run stopped on the board confirmation or the credentials question forever. `EVENTMODELERS_TOKEN` also now answers the credentials question on its own, the way `EVENTMODELERS_BOARD_ID` always answered the board question: an env var that outranks every config file makes asking where the credentials come from moot. The README gains a container recipe, including the two things a container needs that a laptop already had — a writable HOME for the global kit and per-board credentials, and a `LOCAL_AI_URL` that isn't `localhost`.