@eventmodelers/cli 1.0.141 → 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.141",
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);
@@ -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
 
@@ -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