@eventmodelers/cli 1.0.140 → 1.0.142

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/cli.js CHANGED
@@ -4101,7 +4101,7 @@ program
4101
4101
 
4102
4102
  program
4103
4103
  .command('activate-context')
4104
- .description('Choose which fetched context is active — writes .slices/current_context.json, which `run`/bridge/listen treat as sticky and never cross out of on their own')
4104
+ .description('Choose which fetched context is active — writes .slices/current_context.json, which `run` works through first; once it has no planned slices left, `run` moves on to the next context that does')
4105
4105
  .action(async () => {
4106
4106
  const cwd = process.cwd();
4107
4107
  const kitDir = findInstalledKitDir(cwd);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eventmodelers/cli",
3
- "version": "1.0.140",
3
+ "version": "1.0.142",
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": {
@@ -232,9 +232,8 @@ async function fetchAndPersistSlices(cfg, kitDir) {
232
232
  contexts[contextSlug].slices.push(slice);
233
233
  }
234
234
 
235
- // current_context.json is STICKY. We work within ONE context at a time and must
236
- // not auto-jump to another context just because it happens to have planned work.
237
- // Keep the existing context if it still exists; only seed it when absent or stale.
235
+ // current_context.json is the context being worked on. Keep it here while it exists; the
236
+ // run loop (getFirstPlannedSlice) advances it when that context has no planned work left.
238
237
  const ctxPath = join(slicesDir, 'current_context.json');
239
238
  let activeCtx = null;
240
239
  if (existsSync(ctxPath)) {
@@ -563,19 +562,32 @@ function readTicketNumber(kitDir, ctx, folder) {
563
562
  }
564
563
  }
565
564
 
566
- // Returns the first Planned slice IN THE CURRENT CONTEXT ONLY. If the current
567
- // context has no planned work, returns null so the loop waits — it must NEVER
568
- // cross into another context to find something to build.
565
+ // Returns the first Planned slice, preferring the current context so a context is finished
566
+ // before the next one starts. When the current context has no planned work, the first other
567
+ // context that does becomes the current one (current_context.json is rewritten), so a slice
568
+ // set to Planned in any context is eventually built.
569
569
  function getFirstPlannedSlice(kitDir) {
570
+ const slicesDir = join(kitDir, '.slices');
570
571
  const currentCtx = readCurrentContext(kitDir);
571
- if (!currentCtx) return null;
572
- const indexPath = join(kitDir, '.slices', currentCtx, 'index.json');
573
- if (!existsSync(indexPath)) return null;
572
+ let others = [];
574
573
  try {
575
- const { slices } = JSON.parse(readFileSync(indexPath, 'utf-8'));
576
- const planned = slices && slices.find((s) => (s.status || '').toLowerCase() === 'planned');
577
- if (planned) return { id: planned.id ?? null, title: planned.slice || planned.id || null, ctx: currentCtx, ticketNumber: readTicketNumber(kitDir, currentCtx, planned.folder) };
574
+ others = readdirSync(slicesDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name).sort();
578
575
  } catch {}
576
+ const candidates = [...(currentCtx ? [currentCtx] : []), ...others.filter((c) => c !== currentCtx)];
577
+ for (const ctx of candidates) {
578
+ const indexPath = join(slicesDir, ctx, 'index.json');
579
+ if (!existsSync(indexPath)) continue;
580
+ try {
581
+ const { slices } = JSON.parse(readFileSync(indexPath, 'utf-8'));
582
+ const planned = slices && slices.find((s) => (s.status || '').toLowerCase() === 'planned');
583
+ if (!planned) continue;
584
+ if (ctx !== currentCtx) {
585
+ writeFileSync(join(slicesDir, 'current_context.json'), JSON.stringify({ name: ctx }, null, 2), 'utf-8');
586
+ console.log(`[ralph] No planned slices in context "${currentCtx}" — switching to "${ctx}".`);
587
+ }
588
+ return { id: planned.id ?? null, title: planned.slice || planned.id || null, ctx, ticketNumber: readTicketNumber(kitDir, ctx, planned.folder) };
589
+ } catch {}
590
+ }
579
591
  return null;
580
592
  }
581
593
 
@@ -755,10 +767,10 @@ async function ralphLoop(kitDir, cfg, onTask, onPlannedSlice, localOnly = false)
755
767
  }
756
768
 
757
769
  if (!didWork) {
758
- // No planned work in the current context — wait, do NOT switch contexts.
770
+ // No planned work in any context — wait.
759
771
  const ctx = readCurrentContext(kitDir);
760
772
  if (ctx !== lastIdleCtx) {
761
- console.log(`[ralph] No planned slices in current context "${ctx}" — waiting. Switch context on the board to continue.`);
773
+ console.log(`[ralph] No planned slices in any context — waiting.`);
762
774
  lastIdleCtx = ctx;
763
775
  }
764
776
  await sleep(10_000);
@@ -36,7 +36,7 @@ Write tools take their items as an array (`nodeIds[]`, `elements[]`, `connection
36
36
  | `get_board_events` | `boardId`, `since?`, `seq?` | A page of at most 300 board events, oldest first, as `{events, pageSize, hasMore}`. Not the whole log: while `hasMore` is true, page on by passing the last event's `seq` as `since`. `seq` returns only the event of exactly that seq | §1 `GET .../events` |
37
37
  | `submit_node_events` | `boardId`, `events[]`, `autoConnect?`, `compact?` | Create/update nodes (raw `NodeChangeEvent`/edge events). Every event property is described on the tool's own `events[]` schema — read that rather than this skill when all you need is the event shape. An event needs its own `id` (required — a fresh uuid per event, never the node id) and its `eventType`, plus the keys of its kind (`nodeId`/`meta`/`node`, or `edgeId`/`source`/`target`). The `id` keys the returned `hashes` map and makes a resubmit idempotent — the same event sent twice under one id writes a single board event. Don't send `boardId` or `timestamp` per event — the server takes the board from the call and stamps the time itself, and ignores both if sent. `autoConnect: false` places freshly-created nodes without wiring them to their own/previous-column neighbors (avoids a stray nearest-left edge); `compact: true` returns `{persisted: <count>}` instead of the per-node hash map | §3 `POST .../nodes/events` |
38
38
  | `delete_node` | `boardId`, `nodeIds[]` | Delete nodes, applied in order — one failure doesn't stop the rest; answers `{results}`. Deleting a chapter (timeline) cascades — every node placed in one of its cells, plus any node parented to it (e.g. SLICE_BORDER), is deleted too, along with all their edges | (via `node:deleted` event, §3) |
39
- | `create_drawing` | `boardId`, `drawings[]` (each `kind`, `x`, `y`, `width`, `height`, ...) | Freehand canvas annotation (path/rect/text/sticky) — never placed in a cell. An annotation is rarely one stroke: an arrow plus its label is one call with several `drawings` entries, applied in order, not several calls. **"Hotspot"** means a red feedback note: `kind: "sticky"` with `fill: "#ef4444"` (a sticky with no `fill` renders yellow), `content` = the problem/question, placed right next to the element it concerns | — (REST `POST .../drawing/draw` accepts a single drawing or an array) |
39
+ | `create_drawing` | `boardId`, `drawings[]` (each `kind`, `x`, `y`, `width`, `height`, ...) | Freehand canvas annotation — **never** for a diagram the person asked to "draw/sketch" (that is a chat snippet) (path/rect/text/sticky) — never placed in a cell. An annotation is rarely one stroke: an arrow plus its label is one call with several `drawings` entries, applied in order, not several calls. **"Hotspot"** means a red feedback note: `kind: "sticky"` with `fill: "#ef4444"` (a sticky with no `fill` renders yellow), `content` = the problem/question, placed right next to the element it concerns | — (REST `POST .../drawing/draw` accepts a single drawing or an array) |
40
40
  | `create_chapter` | `boardId`, `x?`, `y?`, `title?`, `columns?`, `lanes?: [{type, label?, height?}]` | Create a timeline. Omitting `x`/`y` auto-stacks it below the lowest existing chapter (by its *actual current* row-height total, not the height it was created with — safe even after `add_lane` growth), plus a fixed margin. Pass `title` to name it, `columns` for a known column count, and `lanes` to create named lanes (or several of one type, e.g. one swimlane per context) — none of the three needs a follow-up call, and the lanes are sorted into the required order automatically. The response carries every `columnId` and lane id, so the chapter needn't be read back before placing into it | §2 `POST .../chapters` |
41
41
  | `get_chapter_bounds` | `boardId` | Absolute canvas bounding box `{id, title, x, y, width, height}` of every chapter on the board — width/height derived from each chapter's current row/column layout, not a guessed default. Use before picking explicit `x`/`y` for `create_chapter` (e.g. placing below the chapter with the largest `y + height`) to avoid overlapping one that grew since it was created | §2 `GET .../chapters/bounds` |
42
42
  | `add_column` | `boardId`, `timelineId`, `index?`, `beforeNodeId?`, `afterNodeId?`, `count?` | Add one or more columns in one call. `count` inserts that many contiguously starting at the insertion point (default 1). Position with at most one of `index` (0-based), `beforeNodeId`, or `afterNodeId` (resolves the index from where that already-placed node currently sits) — omit all three to append | §2 `POST .../timelines/:id/columns` |
@@ -6,12 +6,12 @@ The structure defined in the Project-Skills is relevant.
6
6
 
7
7
  ## Context Boundary (READ FIRST — NON-NEGOTIABLE)
8
8
 
9
- You work within **exactly ONE context at a time** — the one named in `.build-kit/.slices/current_context.json`.
9
+ You work within **exactly ONE context at a time** — the one named in `.build-kit/.slices/current_context.json` (the runner picks it).
10
10
 
11
11
  - **ONLY** look for and build slices inside `.build-kit/.slices/<currentContext>/`.
12
12
  - **NEVER** read, scan, or build slices from any other context directory, even if it has "Planned" slices, and even if the current context has no work left.
13
13
  - A "Planned" slice in a *different* context (e.g. "Rename organization" while you are in "Board Invitations") is **NOT yours to build**. Ignore it completely.
14
- - If the current context has no "Planned" slice, you are **done for this iteration** — reply `<promise>NO_TASKS</promise>` and stop. Do not go looking elsewhere. The context is only ever changed on the board, never by you.
14
+ - If the current context has no "Planned" slice, you are **done for this iteration** — reply `<promise>NO_TASKS</promise>` and stop. Do not go looking elsewhere. The runner moves `current_context.json` on to the next context with planned work between iterations — never change it yourself.
15
15
 
16
16
  ## Your Task
17
17
 
@@ -6,12 +6,12 @@ The structure defined in the Project-Skills is relevant.
6
6
 
7
7
  ## Context Boundary (READ FIRST — NON-NEGOTIABLE)
8
8
 
9
- You work within **exactly ONE context at a time** — the one named in `.build-kit/.slices/current_context.json`.
9
+ You work within **exactly ONE context at a time** — the one named in `.build-kit/.slices/current_context.json` (the runner picks it).
10
10
 
11
11
  - **ONLY** look for and build slices inside `.build-kit/.slices/<currentContext>/`.
12
12
  - **NEVER** read, scan, or build slices from any other context directory, even if it has "Planned" slices, and even if the current context has no work left.
13
13
  - A "Planned" slice in a *different* context is **NOT yours to build**. Ignore it completely.
14
- - If the current context has no "Planned" slice, you are **done for this iteration** — reply `<promise>NO_TASKS</promise>` and stop. Do not go looking elsewhere. The context is only ever changed on the board, never by you.
14
+ - If the current context has no "Planned" slice, you are **done for this iteration** — reply `<promise>NO_TASKS</promise>` and stop. Do not go looking elsewhere. The runner moves `current_context.json` on to the next context with planned work between iterations — never change it yourself.
15
15
 
16
16
  ## Your Task
17
17
 
@@ -8,13 +8,13 @@ Usually this is a legacy system being extended: the event model was built from t
8
8
 
9
9
  ## Context Boundary (READ FIRST — NON-NEGOTIABLE)
10
10
 
11
- You work within **exactly ONE context at a time** — the one named in `.build-kit/.slices/current_context.json`.
11
+ You work within **exactly ONE context at a time** — the one named in `.build-kit/.slices/current_context.json` (the runner picks it).
12
12
 
13
13
  - **ONLY** look for and build slices inside `.build-kit/.slices/<currentContext>/`.
14
14
  - **NEVER** read, scan, or build slices from any other context directory, even if it has "Planned" slices, and even if the current context has no work left.
15
15
  - A "Planned" slice in a *different* context is **NOT yours to build**. Ignore it completely.
16
16
  - The one exception is **reading** `Done` slices of other contexts as precedents (through the Slice map in `ARCHITECTURE.md`, or by `/learn-architecture` building that map) — they show how the codebase builds things, they are never built.
17
- - If the current context has no "Planned" slice, you are **done for this iteration** — reply `<promise>NO_TASKS</promise>` and stop. Do not go looking elsewhere. The context is only ever changed on the board, never by you.
17
+ - If the current context has no "Planned" slice, you are **done for this iteration** — reply `<promise>NO_TASKS</promise>` and stop. Do not go looking elsewhere. The runner moves `current_context.json` on to the next context with planned work between iterations — never change it yourself.
18
18
 
19
19
  ## Your Task
20
20
 
@@ -6,12 +6,12 @@ The structure defined in the Project-Skills is relevant.
6
6
 
7
7
  ## Context Boundary (READ FIRST — NON-NEGOTIABLE)
8
8
 
9
- You work within **exactly ONE context at a time** — the one named in `.build-kit/.slices/current_context.json`.
9
+ You work within **exactly ONE context at a time** — the one named in `.build-kit/.slices/current_context.json` (the runner picks it).
10
10
 
11
11
  - **ONLY** look for and build slices inside `.build-kit/.slices/<currentContext>/`.
12
12
  - **NEVER** read, scan, or build slices from any other context directory, even if it has "Planned" slices, and even if the current context has no work left.
13
13
  - A "Planned" slice in a *different* context (e.g. "Rename organization" while you are in "Board Invitations") is **NOT yours to build**. Ignore it completely.
14
- - If the current context has no "Planned" slice, you are **done for this iteration** — reply `<promise>NO_TASKS</promise>` and stop. Do not go looking elsewhere. The context is only ever changed on the board, never by you.
14
+ - If the current context has no "Planned" slice, you are **done for this iteration** — reply `<promise>NO_TASKS</promise>` and stop. Do not go looking elsewhere. The runner moves `current_context.json` on to the next context with planned work between iterations — never change it yourself.
15
15
 
16
16
  ## Your Task
17
17
 
@@ -71,8 +71,11 @@ transition but not the lifecycle.
71
71
  - `layout`: `"horizontal"` or `"vertical"` — how the beats are laid out in the storyline editor.
72
72
  - Each beat has an `instanceId` (unique per beat, even when the same `refId` repeats — this is what
73
73
  lets the *same* element, like the Todos read model above, appear multiple times across the
74
- walkthrough, once per state) and a `refId` (the board node this beat walks through — any element
75
- type, not just EVENT/COMMAND/READMODEL — e.g. a SCREEN beat to show the resulting UI).
74
+ walkthrough, once per state) and a `refId` (the board node this beat walks through).
75
+ - **Beat order rules** (the same ones the storyline editor enforces): the first beat is a
76
+ READMODEL; after a READMODEL comes an EVENT (or several); after an EVENT comes another EVENT or a
77
+ READMODEL. Beats are only READMODEL or EVENT — no COMMAND, SCREEN or other types. Every `refId`
78
+ must be on the same timeline.
76
79
  - `isError` marks a beat as an alternate/error branch off the previous beat.
77
80
  - `fields`, `expectEmptyList`, `exampleMode`, `examples` mirror the same fields GWT scenario steps
78
81
  use, letting a beat show concrete example data the same way a "then" readmodel step does.
@@ -196,6 +196,8 @@ Only post questions that are **genuinely unclear or missing** — don't post obs
196
196
 
197
197
  ### 4.2 Arrows (every relational finding, always)
198
198
 
199
+ > **Arrows are for relational findings only.** Never use `create_drawing` (stickies, arrows, shapes) to draw a diagram the person asked for ("draw/sketch a UML diagram") — that is a snippet in the chat, not a board change.
200
+
199
201
  **Prefer MCP:** `mcp__eventmodelers__create_drawing` — one call per drawing, no auth headers needed.
200
202
 
201
203
  **Fallback (no MCP):** `POST /api/org/{orgId}/boards/{boardId}/drawing/draw` (auth headers same as every other call — `x-token`, `x-user-id: wdyt`). Same fields as the tool args below.
@@ -309,6 +309,9 @@ for it. Instead:
309
309
  - a **screen idea** in the conversation ("what could that screen look like?") → `screen`, a sandboxed HTML mock-up in the chat; putting a screen on the board is `/html-screen` work;
310
310
  - **where one piece of information comes from and where it is used** → `dataJourney` (the `/data-journey` skill);
311
311
  - **who does what with which work object, per chapter** → an `svg` domain story (the `/domain-story` skill);
312
+ - **"draw" / "sketch" / "diagram" something** (a UML diagram, a flow, a class model) → a snippet in the chat (`svg`, or a
313
+ `code` block with Mermaid/PlantUML/ASCII), **never** drawn on the board with stickies, arrows or `create_drawing`.
314
+ Only an explicit request to put it on the board changes that, and then as an image (`/domain-story` § board), not rebuilt from shapes;
312
315
  - **rows and columns** — a comparison, a matrix, a short list with a few attributes per item → `table`.
313
316
  - anything the customer defined **their own snippet type** for → `custom` with its `ref`: `list_snippet_types`
314
317
  shows them with `instructions` on when to use each; prefer a fitting one over a built-in kind. A click on it arrives
@@ -6,12 +6,12 @@ The structure defined in the Project-Skills is relevant.
6
6
 
7
7
  ## Context Boundary (READ FIRST — NON-NEGOTIABLE)
8
8
 
9
- You work within **exactly ONE context at a time** — the one named in `.build-kit/.slices/current_context.json`.
9
+ You work within **exactly ONE context at a time** — the one named in `.build-kit/.slices/current_context.json` (the runner picks it).
10
10
 
11
11
  - **ONLY** look for and build slices inside `.build-kit/.slices/<currentContext>/`.
12
12
  - **NEVER** read, scan, or build slices from any other context directory, even if it has "Planned" slices, and even if the current context has no work left.
13
13
  - A "Planned" slice in a *different* context (e.g. "Rename organization" while you are in "Board Invitations") is **NOT yours to build**. Ignore it completely.
14
- - If the current context has no "Planned" slice, you are **done for this iteration** — reply `<promise>NO_TASKS</promise>` and stop. Do not go looking elsewhere. The context is only ever changed on the board, never by you.
14
+ - If the current context has no "Planned" slice, you are **done for this iteration** — reply `<promise>NO_TASKS</promise>` and stop. Do not go looking elsewhere. The runner moves `current_context.json` on to the next context with planned work between iterations — never change it yourself.
15
15
 
16
16
  ## Your Task
17
17
 
@@ -6,12 +6,12 @@ The structure defined in the Project-Skills is relevant.
6
6
 
7
7
  ## Context Boundary (READ FIRST — NON-NEGOTIABLE)
8
8
 
9
- You work within **exactly ONE context at a time** — the one named in `.build-kit/.slices/current_context.json`.
9
+ You work within **exactly ONE context at a time** — the one named in `.build-kit/.slices/current_context.json` (the runner picks it).
10
10
 
11
11
  - **ONLY** look for and build slices inside `.build-kit/.slices/<currentContext>/`.
12
12
  - **NEVER** read, scan, or build slices from any other context directory, even if it has "Planned" slices, and even if the current context has no work left.
13
13
  - A "Planned" slice in a *different* context (e.g. "Rename organization" while you are in "Board Invitations") is **NOT yours to build**. Ignore it completely.
14
- - If the current context has no "Planned" slice, you are **done for this iteration** — reply `<promise>NO_TASKS</promise>` and stop. Do not go looking elsewhere. The context is only ever changed on the board, never by you.
14
+ - If the current context has no "Planned" slice, you are **done for this iteration** — reply `<promise>NO_TASKS</promise>` and stop. Do not go looking elsewhere. The runner moves `current_context.json` on to the next context with planned work between iterations — never change it yourself.
15
15
 
16
16
  ## Your Task
17
17
 
@@ -6,12 +6,12 @@ The structure defined in the Project-Skills is relevant.
6
6
 
7
7
  ## Context Boundary (READ FIRST — NON-NEGOTIABLE)
8
8
 
9
- You work within **exactly ONE context at a time** — the one named in `.build-kit/.slices/current_context.json`.
9
+ You work within **exactly ONE context at a time** — the one named in `.build-kit/.slices/current_context.json` (the runner picks it).
10
10
 
11
11
  - **ONLY** look for and build slices inside `.build-kit/.slices/<currentContext>/`.
12
12
  - **NEVER** read, scan, or build slices from any other context directory, even if it has "Planned" slices, and even if the current context has no work left.
13
13
  - A "Planned" slice in a *different* context is **NOT yours to build**. Ignore it completely.
14
- - If the current context has no "Planned" slice, you are **done for this iteration** — reply `<promise>NO_TASKS</promise>` and stop. Do not go looking elsewhere. The context is only ever changed on the board, never by you.
14
+ - If the current context has no "Planned" slice, you are **done for this iteration** — reply `<promise>NO_TASKS</promise>` and stop. Do not go looking elsewhere. The runner moves `current_context.json` on to the next context with planned work between iterations — never change it yourself.
15
15
 
16
16
  ## Your Task
17
17
 
@@ -6,12 +6,12 @@ The structure defined in the Project-Skills is relevant.
6
6
 
7
7
  ## Context Boundary (READ FIRST — NON-NEGOTIABLE)
8
8
 
9
- You work within **exactly ONE context at a time** — the one named in `.build-kit/.slices/current_context.json`.
9
+ You work within **exactly ONE context at a time** — the one named in `.build-kit/.slices/current_context.json` (the runner picks it).
10
10
 
11
11
  - **ONLY** look for and build slices inside `.build-kit/.slices/<currentContext>/`.
12
12
  - **NEVER** read, scan, or build slices from any other context directory, even if it has "Planned" slices, and even if the current context has no work left.
13
13
  - A "Planned" slice in a *different* context (e.g. "Rename organization" while you are in "Board Invitations") is **NOT yours to build**. Ignore it completely.
14
- - If the current context has no "Planned" slice, you are **done for this iteration** — reply `<promise>NO_TASKS</promise>` and stop. Do not go looking elsewhere. The context is only ever changed on the board, never by you.
14
+ - If the current context has no "Planned" slice, you are **done for this iteration** — reply `<promise>NO_TASKS</promise>` and stop. Do not go looking elsewhere. The runner moves `current_context.json` on to the next context with planned work between iterations — never change it yourself.
15
15
 
16
16
  ## Your Task
17
17
 
@@ -6,12 +6,12 @@ The structure defined in the Project-Skills is relevant.
6
6
 
7
7
  ## Context Boundary (READ FIRST — NON-NEGOTIABLE)
8
8
 
9
- You work within **exactly ONE context at a time** — the one named in `.build-kit/.slices/current_context.json`.
9
+ You work within **exactly ONE context at a time** — the one named in `.build-kit/.slices/current_context.json` (the runner picks it).
10
10
 
11
11
  - **ONLY** look for and build slices inside `.build-kit/.slices/<currentContext>/`.
12
12
  - **NEVER** read, scan, or build slices from any other context directory, even if it has "Planned" slices, and even if the current context has no work left.
13
13
  - A "Planned" slice in a *different* context is **NOT yours to build**. Ignore it completely.
14
- - If the current context has no "Planned" slice, you are **done for this iteration** — reply `<promise>NO_TASKS</promise>` and stop. Do not go looking elsewhere. The context is only ever changed on the board, never by you.
14
+ - If the current context has no "Planned" slice, you are **done for this iteration** — reply `<promise>NO_TASKS</promise>` and stop. Do not go looking elsewhere. The runner moves `current_context.json` on to the next context with planned work between iterations — never change it yourself.
15
15
 
16
16
  ## Your Task
17
17
 
@@ -6,12 +6,12 @@ The structure defined in the Project-Skills is relevant.
6
6
 
7
7
  ## Context Boundary (READ FIRST — NON-NEGOTIABLE)
8
8
 
9
- You work within **exactly ONE context at a time** — the one named in `.build-kit/.slices/current_context.json`.
9
+ You work within **exactly ONE context at a time** — the one named in `.build-kit/.slices/current_context.json` (the runner picks it).
10
10
 
11
11
  - **ONLY** look for and build slices inside `.build-kit/.slices/<currentContext>/`.
12
12
  - **NEVER** read, scan, or build slices from any other context directory, even if it has "Planned" slices, and even if the current context has no work left.
13
13
  - A "Planned" slice in a *different* context (e.g. "Rename organization" while you are in "Board Invitations") is **NOT yours to build**. Ignore it completely.
14
- - If the current context has no "Planned" slice, you are **done for this iteration** — reply `<promise>NO_TASKS</promise>` and stop. Do not go looking elsewhere. The context is only ever changed on the board, never by you.
14
+ - If the current context has no "Planned" slice, you are **done for this iteration** — reply `<promise>NO_TASKS</promise>` and stop. Do not go looking elsewhere. The runner moves `current_context.json` on to the next context with planned work between iterations — never change it yourself.
15
15
 
16
16
  ## Your Task
17
17