@eventmodelers/cli 1.0.97 → 1.0.98

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 (41) hide show
  1. package/README.md +45 -2
  2. package/cli.js +59 -5
  3. package/lib/modeling-exec.js +4 -86
  4. package/package.json +6 -1
  5. package/shared/build-kit/README.md +12 -4
  6. package/shared/build-kit/lib/mcp-register.js +96 -0
  7. package/shared/build-kit/lib/ralph.js +49 -0
  8. package/shared/build-kit/lib/tracing.js +6 -5
  9. package/shared/build-kit/ralph-claude.js +4 -1
  10. package/shared/build-kit/ralph-exec.js +8 -8
  11. package/shared/skills/learn-eventmodelers-api/SKILL.md +0 -1
  12. package/shared/skills/request-feedback/SKILL.md +23 -32
  13. package/stacks/axon/templates/build-kit/CLAUDE.md +1 -6
  14. package/stacks/axon/templates/build-kit/lib/backend-prompt.md +1 -8
  15. package/stacks/axon/templates/build-kit/lib/prompt.md +2 -2
  16. package/stacks/blank/templates/build-kit/CLAUDE.md +1 -6
  17. package/stacks/blank/templates/build-kit/lib/backend-prompt.md +1 -8
  18. package/stacks/blank/templates/build-kit/lib/prompt.md +2 -9
  19. package/stacks/kurrent/templates/build-kit/CLAUDE.md +1 -6
  20. package/stacks/kurrent/templates/build-kit/lib/backend-prompt.md +1 -8
  21. package/stacks/kurrent/templates/build-kit/lib/prompt.md +2 -2
  22. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-brainstorming-events/SKILL.md +4 -4
  23. package/stacks/node/templates/build-kit/CLAUDE.md +1 -6
  24. package/stacks/node/templates/build-kit/lib/backend-prompt.md +1 -8
  25. package/stacks/node/templates/build-kit/lib/prompt.md +2 -2
  26. package/stacks/opencqrs/templates/build-kit/CLAUDE.md +1 -6
  27. package/stacks/opencqrs/templates/build-kit/lib/backend-prompt.md +1 -8
  28. package/stacks/opencqrs/templates/build-kit/lib/prompt.md +2 -2
  29. package/stacks/react/templates/build-kit/CLAUDE.md +1 -6
  30. package/stacks/react/templates/build-kit/lib/backend-prompt.md +1 -8
  31. package/stacks/react/templates/build-kit/lib/prompt.md +2 -9
  32. package/stacks/supabase/templates/build-kit/CLAUDE.md +1 -6
  33. package/stacks/supabase/templates/build-kit/lib/backend-prompt.md +1 -8
  34. package/stacks/supabase/templates/build-kit/lib/prompt.md +2 -2
  35. package/stacks/supabase-react/templates/build-kit/CLAUDE.md +1 -6
  36. package/stacks/supabase-react/templates/build-kit/lib/backend-prompt.md +1 -8
  37. package/stacks/supabase-react/templates/build-kit/lib/prompt.md +2 -9
  38. package/stacks/umadb/templates/build-kit/CLAUDE.md +1 -6
  39. package/stacks/umadb/templates/build-kit/lib/backend-prompt.md +1 -8
  40. package/stacks/umadb/templates/build-kit/lib/prompt.md +2 -2
  41. package/stacks/modeling-kit/templates/.claude/settings.local.json +0 -13
@@ -20,6 +20,7 @@
20
20
  import { startRalph, loadLocalConfig, resolveAgentIdentity, connectHeader } from './lib/ralph.js';
21
21
  import { createSliceTracer, usageFromHarnessEvent, sumUsage } from './lib/tracing.js';
22
22
  import { turnTimeoutMs, superviseTurn } from './lib/turn.js';
23
+ import { registerMcp, shellQuote } from './lib/mcp-register.js';
23
24
  import { spawn } from 'child_process';
24
25
  import { writeFileSync, mkdtempSync } from 'fs';
25
26
  import { tmpdir } from 'os';
@@ -33,9 +34,9 @@ const cfg = loadLocalConfig(kitDir);
33
34
  const localOnly = process.env.RALPH_LOCAL === '1';
34
35
  // Same as ralph-claude.js: childEnv is built at load time, before startRalph resolves identity.
35
36
  Object.assign(cfg, resolveAgentIdentity(kitDir, 'BUILD', cfg));
36
- const execCmd = process.env.RALPH_EXEC_CMD || cfg.localAi?.exec;
37
+ const configuredCmd = process.env.RALPH_EXEC_CMD || cfg.localAi?.exec;
37
38
 
38
- if (!execCmd) {
39
+ if (!configuredCmd) {
39
40
  console.error('[ralph-exec] No agent command configured.');
40
41
  console.error(' Set one for this run: eventmodelers run --exec "codex exec --full-auto"');
41
42
  console.error(' Or persist a default as localAi.exec in .eventmodelers/config.json');
@@ -60,6 +61,7 @@ const tracer = createSliceTracer({
60
61
  baseUrl: cfg.baseUrl,
61
62
  token: cfg.token,
62
63
  organizationId: cfg.organizationId,
64
+ boardId: cfg.boardId,
63
65
  agentId: cfg.agentId,
64
66
  traceFile: join(projectDir, '.eventmodelers', 'trace', 'slices.jsonl'),
65
67
  log: (line) => console.log(`[ralph-exec] ${line}`),
@@ -68,12 +70,10 @@ const tracer = createSliceTracer({
68
70
 
69
71
  const promptDir = mkdtempSync(join(tmpdir(), 'ralph-exec-'));
70
72
 
71
- // POSIX single-quote escaping: close, insert an escaped quote, reopen. The prompt is
72
- // multi-line Markdown with backticks and $ in it, so it cannot go in unquoted.
73
- function shellQuote(s) {
74
- return `'${String(s).replace(/'/g, `'\\''`)}'`;
75
- }
76
-
73
+ // A known harness (OpenCode, Gemini, Codex) learns about the eventmodelers MCP server here, with the
74
+ // platform URL from the config — rewritten every run so a changed baseUrl never goes stale. A local-only
75
+ // run has no platform to register, and an unknown command is left to the skills' REST fallback.
76
+ const execCmd = localOnly ? configuredCmd : registerMcp(configuredCmd, projectDir, cfg.baseUrl, (line) => console.log(`[ralph-exec] ${line}`)).command;
77
77
  console.log(`[ralph-exec] command: ${execCmd}`);
78
78
 
79
79
  // Parses a harness's stdout for usage while still passing it through. Most harnesses emit JSONL;
@@ -124,7 +124,6 @@ MODEL_CONTEXT // Context/domain modeling container
124
124
  CHAPTER // Timeline/sequence container — a "chapter" IS a timeline (chapterId === timelineId); the terms are used interchangeably across the API
125
125
  ACTOR // System participant (swimlane label)
126
126
  AUTOMATION // Automated action
127
- API // External service
128
127
  SCREEN // UI screen
129
128
  COMMAND // State-changing operation
130
129
  EVENT // Domain event
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: request-feedback
3
- description: Post a comment on a slice and mark it Blocked when the slice's requirements are genuinely ambiguous, contradictory, or missing something a decision depends on. This is an escalation path, not a routine step — reach for it only when you cannot proceed without guessing.
3
+ description: Post a comment on a slice and mark it Blocked — ONLY when the slice literally cannot be built, even with reasonable assumptions. The absolute exception; for unclear or missing details, assume and build instead.
4
4
  ---
5
5
 
6
6
  # Request Feedback
@@ -11,41 +11,32 @@ Prefer `mcp__eventmodelers__*` tools when available (registered by the `connect`
11
11
 
12
12
  ---
13
13
 
14
- ## When to use this skill — the exception, not the rule
14
+ ## When to use this skill — the absolute exception
15
15
 
16
- Building a slice is normally unambiguous: `slice.json` names every command field, event field, and
17
- GWT scenario, and the matching build skill (`build-state-change`, `build-state-view`,
18
- `build-automation`, ...) tells you exactly how to turn that into code. **Read `slice.json` fully, and
19
- read the build skill's own instructions and reference docs, before ever concluding something is
20
- missing.** Most slices need none of this.
16
+ **The default is to assume and build.** A missing example value, an unclear field type, a status
17
+ mapping, a referenced event that isn't modeled yet, a dependency slice that isn't built yet — none of
18
+ these is a reason to stop. Pick the most sensible interpretation from `slice.json`, its
19
+ `specifications[]` and the surrounding model, build the slice, and record each assumption in one line
20
+ in `progress.txt` and as a code comment. **Read `slice.json` fully, and read the build skill's own
21
+ instructions and reference docs, before concluding anything is missing.**
21
22
 
22
- Only invoke `request-feedback` when, after that reading, a decision the implementation depends on
23
- still cannot be made without guessing — for example:
24
-
25
- - A business rule mentioned in `description`/`comments`/`notes` isn't backed by any field, event, or
26
- `specifications[]` scenario, so there's no way to encode it.
27
- - Two fields, or a field and an `idAttribute` flag, contradict each other about what the slice is
28
- supposed to do.
29
- - A `specifications[]` scenario references a prior event or state that no command/event in this slice
30
- (or its declared dependencies) actually produces.
31
- - The slice depends on another slice, screen, or read model that doesn't exist yet and it's unclear
32
- whether one should be created, or the dependency was meant to point elsewhere.
23
+ Invoke `request-feedback` **only if the slice literally cannot be built**: even with sensible
24
+ assumptions, nothing runnable and tested can be produced. For example, the slice has no elements at
25
+ all (no command/read model, no fields), or two parts of it contradict each other so that no single
26
+ implementation satisfies both.
33
27
 
34
28
  **Do not use this skill for:**
35
- - Implementation-detail choices the build skill's own instructions already answer (e.g. package
36
- naming, file layout, which annotation to use) — those aren't ambiguity in the slice, they're just
37
- reading the skill more carefully.
38
- - Style or naming preferences with no functional consequence — pick the reasonable option and move on.
39
- - "This would be nice to confirm" — if you *can* proceed correctly from what `slice.json` says, proceed.
40
-
41
- When in doubt, prefer finishing the slice over escalating. Escalating on every minor uncertainty
42
- defeats the purpose — it should be rare enough that a `Blocked` slice reliably means "a human needs to
43
- look at this," not "the agent didn't feel like deciding."
44
-
45
- **When this skill does apply: do not guess and build anyway.** Post the question and stop work on this
46
- slice for this run — do not implement your best interpretation first. A wrong guess encoded into
47
- working, tested, committed code is harder to catch and undo than an unbuilt slice waiting for an
48
- answer.
29
+ - Missing examples, field types, names, or status values — assume, build, note the assumption.
30
+ - A dependency (event, command, other slice) that isn't implemented yet — assume its definition from
31
+ the model and build against it.
32
+ - Implementation-detail choices the build skill's own instructions already answer.
33
+ - Style or naming preferences, or "this would be nice to confirm".
34
+
35
+ A `Blocked` slice must reliably mean "impossible without a human", never "the agent preferred to ask".
36
+ When in doubt, build.
37
+
38
+ **When this skill does apply:** post the question and stop work on this slice for this run — an
39
+ impossible build can't be finished by guessing.
49
40
 
50
41
  ---
51
42
 
@@ -42,12 +42,7 @@ When starting to work on a slice, invoke the `update-slice-status` skill with `I
42
42
  **CRITICAL: You MUST always use the provided skills to build slices. NEVER implement a slice manually.**
43
43
  **ALL fields, event names, command names, and business rules MUST come exclusively from slice.json. Do NOT invent, assume, or guess any field or logic not present in the slice definition.**
44
44
 
45
- **If, at any point below, the slice's requirements are genuinely ambiguous, contradictory, or missing
46
- a decision you need in order to proceed — do not guess, and do not build anyway.** Invoke the
47
- `request-feedback` skill with the specific question; it posts the question as a comment on the slice
48
- and marks it `Blocked`, and you then stop work on this slice for this run. This is an escalation path,
49
- not a routine step — read `slice.json` and the matching build skill's own instructions fully first;
50
- most slices are fully specified and need none of this.
45
+ **Default: make a reasonable assumption and build the slice.** If a detail is unclear or missing (an example value, a field type, a status mapping, a referenced event that isn't modeled yet, ...), pick the most sensible interpretation from `slice.json`, its specifications and the surrounding model, build it, and record each assumption in one line in `progress.txt` and as a code comment. Ambiguity alone is never a reason to stop. **Only if the slice literally cannot be built** — nothing runnable can be produced even with sensible assumptions — invoke `/request-feedback` with the specific question; it posts the question as a comment on the slice and marks it `Blocked`. That must be the absolute exception; a `Blocked` slice should mean "impossible without a human", never "the agent preferred to ask".
51
46
 
52
47
  When asked to build a slice, always follow this flow:
53
48
 
@@ -50,14 +50,7 @@ You work within **exactly ONE context at a time** — the one named in `.build-k
50
50
 
51
51
  ## Escalating Ambiguity
52
52
 
53
- **If the slice's requirements are genuinely ambiguous, contradictory, or missing a decision you need
54
- in order to proceed — do not guess, and do not build anyway.** Invoke `/request-feedback` with the
55
- specific question; it posts the question as a comment on the slice and marks it `Blocked` on the
56
- board (overriding the `InProgress` set earlier), then stop this iteration without finishing the
57
- build — reply `<promise>DONE</promise>` as if the iteration's work was to raise the question, not to
58
- implement the slice. This is an escalation path, not a routine step — read the slice.json and the
59
- matching build skill's own instructions fully first; most slices are fully specified and need none of
60
- this.
53
+ **Default: make a reasonable assumption and build the slice.** If a detail is unclear or missing (an example value, a field type, a status mapping, a referenced event that isn't modeled yet, ...), pick the most sensible interpretation from `slice.json`, its specifications and the surrounding model, build it, and record each assumption in one line in `progress.txt` and as a code comment. Ambiguity alone is never a reason to stop. **Only if the slice literally cannot be built** — nothing runnable can be produced even with sensible assumptions — invoke `/request-feedback` with the specific question; it posts the question as a comment on the slice and marks it `Blocked`. That must be the absolute exception; a `Blocked` slice should mean "impossible without a human", never "the agent preferred to ask".
61
54
 
62
55
  ## Progress Report Format
63
56
 
@@ -48,13 +48,13 @@ Inspect the `sliceStatus` in the payload:
48
48
 
49
49
  This is the build trigger. Setting `InProgress` and building are one atomic step:
50
50
 
51
- **If the slice's requirements are genuinely ambiguous, contradictory, or missing a decision you need in order to proceed — do not guess, and do not build anyway.** Invoke `/request-feedback` with the specific question; it posts the question as a comment on the slice and marks it `Blocked` (superseding the `InProgress` set in step 1), then drop this task without finishing the build. This is an escalation path, not a routine step — most slices are fully specified.
51
+ **Default: make a reasonable assumption and build the slice.** If a detail is unclear or missing (an example value, a field type, a status mapping, a referenced event that isn't modeled yet, ...), pick the most sensible interpretation from `slice.json`, its specifications and the surrounding model, build it, and record each assumption in one line in `progress.txt` and as a code comment. Ambiguity alone is never a reason to stop. **Only if the slice literally cannot be built** — nothing runnable can be produced even with sensible assumptions — invoke `/request-feedback` with the specific question; it posts the question as a comment on the slice and marks it `Blocked`. That must be the absolute exception; a `Blocked` slice should mean "impossible without a human", never "the agent preferred to ask".
52
52
 
53
53
  1. Immediately call `/update-slice-status` to set the slice to `InProgress` on the board.
54
54
 
55
55
  **Claim conflict**: if this call reports the slice is already in `InProgress` (or any status other than `Planned`), another agent already claimed it first — this is expected, not an error. Log it in `progress.txt`, drop this task without building, and continue the loop (the next task will naturally cover the next slice). Do not retry.
56
56
 
57
- 2. Read the slice definition from `.build-kit/.slices/<contextSlug>/<sliceFolder>/slice.json` (written by `/load-slice`).
57
+ 2. Run `/load-slice sliceId=<payload.sliceId>` to fetch the full slice, then read the slice definition from `.build-kit/.slices/<contextSlug>/<sliceFolder>/slice.json`. The runner keeps a `slice.json` fresh from a summary endpoint, so a file holding only `id`, `title`, `status` and `sliceType` is that stub, not an empty slice — never conclude a slice has no elements from it. Only if the full fetch itself returns no commands/events/read models/fields is the slice actually empty.
58
58
 
59
59
  3. Determine the **slice type** from the slice.json:
60
60
  - **Translation** — `sliceType === "TRANSLATION"` → read `description` and `notes` from slice.json for hints; default to `/build-automation` if nothing else is specified
@@ -32,12 +32,7 @@ When starting to work on a slice, invoke the `update-slice-status` skill with `I
32
32
  **CRITICAL: You MUST always use the provided skills to build slices. NEVER implement a slice manually.**
33
33
  **ALL fields, event names, command names, and business rules MUST come exclusively from slice.json. Do NOT invent, assume, or guess any field or logic not present in the slice definition.**
34
34
 
35
- **If, at any point below, the slice's requirements are genuinely ambiguous, contradictory, or missing
36
- a decision you need in order to proceed — do not guess, and do not build anyway.** Invoke the
37
- `request-feedback` skill with the specific question; it posts the question as a comment on the slice
38
- and marks it `Blocked`, and you then stop work on this slice for this run. This is an escalation path,
39
- not a routine step — read `slice.json` and the matching build skill's own instructions fully first;
40
- most slices are fully specified and need none of this.
35
+ **Default: make a reasonable assumption and build the slice.** If a detail is unclear or missing (an example value, a field type, a status mapping, a referenced event that isn't modeled yet, ...), pick the most sensible interpretation from `slice.json`, its specifications and the surrounding model, build it, and record each assumption in one line in `progress.txt` and as a code comment. Ambiguity alone is never a reason to stop. **Only if the slice literally cannot be built** — nothing runnable can be produced even with sensible assumptions — invoke `/request-feedback` with the specific question; it posts the question as a comment on the slice and marks it `Blocked`. That must be the absolute exception; a `Blocked` slice should mean "impossible without a human", never "the agent preferred to ask".
41
36
 
42
37
  When asked to build a slice, always follow this flow:
43
38
 
@@ -40,14 +40,7 @@ You work within **exactly ONE context at a time** — the one named in `.build-k
40
40
 
41
41
  ## Escalating Ambiguity
42
42
 
43
- **If the slice's requirements are genuinely ambiguous, contradictory, or missing a decision you need
44
- in order to proceed — do not guess, and do not build anyway.** Invoke `/request-feedback` with the
45
- specific question; it posts the question as a comment on the slice and marks it `Blocked` on the
46
- board (overriding the `InProgress` set in step 5), then stop this iteration without finishing the
47
- build — reply `<promise>DONE</promise>` as if the iteration's work was to raise the question, not to
48
- implement the slice. This is an escalation path, not a routine step — read the slice.json and the
49
- matching build skill's own instructions fully first; most slices are fully specified and need none of
50
- this.
43
+ **Default: make a reasonable assumption and build the slice.** If a detail is unclear or missing (an example value, a field type, a status mapping, a referenced event that isn't modeled yet, ...), pick the most sensible interpretation from `slice.json`, its specifications and the surrounding model, build it, and record each assumption in one line in `progress.txt` and as a code comment. Ambiguity alone is never a reason to stop. **Only if the slice literally cannot be built** — nothing runnable can be produced even with sensible assumptions — invoke `/request-feedback` with the specific question; it posts the question as a comment on the slice and marks it `Blocked`. That must be the absolute exception; a `Blocked` slice should mean "impossible without a human", never "the agent preferred to ask".
51
44
 
52
45
  ## Progress Report Format
53
46
 
@@ -52,7 +52,7 @@ This is the build trigger. Setting `InProgress` and building are one atomic step
52
52
 
53
53
  **Claim conflict**: if this call reports the slice is already in `InProgress` (or any status other than `Planned`), another agent already claimed it first — this is expected, not an error. Log it in `progress.txt`, drop this task without building, and continue the loop (the next task will naturally cover the next slice). Do not retry.
54
54
 
55
- 2. Read the slice definition from `.build-kit/.slices/<contextSlug>/<sliceFolder>/slice.json` (written by `/load-slice`).
55
+ 2. Run `/load-slice sliceId=<payload.sliceId>` to fetch the full slice, then read the slice definition from `.build-kit/.slices/<contextSlug>/<sliceFolder>/slice.json`. The runner keeps a `slice.json` fresh from a summary endpoint, so a file holding only `id`, `title`, `status` and `sliceType` is that stub, not an empty slice — never conclude a slice has no elements from it. Only if the full fetch itself returns no commands/events/read models/fields is the slice actually empty.
56
56
 
57
57
  3. Determine the **slice type** from the slice.json:
58
58
  - **Translation** — `sliceType === "TRANSLATION"` → read `description` and `notes` from slice.json for hints; default to `/build-automation` if nothing else is specified
@@ -93,14 +93,7 @@ After completing a task, remove it from the array and write the updated array ba
93
93
 
94
94
  ## Escalating Ambiguity
95
95
 
96
- **If the slice's requirements are genuinely ambiguous, contradictory, or missing a decision you need
97
- in order to proceed — do not guess, and do not build anyway.** Invoke `/request-feedback` with the
98
- specific question; it posts the question as a comment on the slice and marks it `Blocked` on the
99
- board (overriding the `InProgress` set earlier), then stop this iteration without finishing the
100
- build — reply `<promise>DONE</promise>` as if the iteration's work was to raise the question, not to
101
- implement the slice. This is an escalation path, not a routine step — read the slice.json and the
102
- matching build skill's own instructions fully first; most slices are fully specified and need none of
103
- this.
96
+ **Default: make a reasonable assumption and build the slice.** If a detail is unclear or missing (an example value, a field type, a status mapping, a referenced event that isn't modeled yet, ...), pick the most sensible interpretation from `slice.json`, its specifications and the surrounding model, build it, and record each assumption in one line in `progress.txt` and as a code comment. Ambiguity alone is never a reason to stop. **Only if the slice literally cannot be built** — nothing runnable can be produced even with sensible assumptions — invoke `/request-feedback` with the specific question; it posts the question as a comment on the slice and marks it `Blocked`. That must be the absolute exception; a `Blocked` slice should mean "impossible without a human", never "the agent preferred to ask".
104
97
 
105
98
  ## Progress Report Format
106
99
 
@@ -76,12 +76,7 @@ doing anything else.
76
76
  **ALL fields, event names, command names, and business rules MUST come exclusively from slice.json. Do NOT
77
77
  invent, assume, or guess any field or logic not present in the slice definition.**
78
78
 
79
- **If, at any point below, the slice's requirements are genuinely ambiguous, contradictory, or missing a
80
- decision you need in order to proceed — do not guess, and do not build anyway.** Invoke the
81
- `request-feedback` skill with the specific question; it posts the question as a comment on the slice and
82
- marks it `Blocked`, and you then stop work on this slice for this run. This is an escalation path, not a
83
- routine step — read `slice.json` and the matching build skill's own instructions fully first; most slices
84
- are fully specified and need none of this.
79
+ **Default: make a reasonable assumption and build the slice.** If a detail is unclear or missing (an example value, a field type, a status mapping, a referenced event that isn't modeled yet, ...), pick the most sensible interpretation from `slice.json`, its specifications and the surrounding model, build it, and record each assumption in one line in `progress.txt` and as a code comment. Ambiguity alone is never a reason to stop. **Only if the slice literally cannot be built** — nothing runnable can be produced even with sensible assumptions — invoke `/request-feedback` with the specific question; it posts the question as a comment on the slice and marks it `Blocked`. That must be the absolute exception; a `Blocked` slice should mean "impossible without a human", never "the agent preferred to ask".
85
80
 
86
81
  When asked to build a slice, always follow this flow:
87
82
 
@@ -50,14 +50,7 @@ You work within **exactly ONE context at a time** — the one named in `.build-k
50
50
 
51
51
  ## Escalating Ambiguity
52
52
 
53
- **If the slice's requirements are genuinely ambiguous, contradictory, or missing a decision you need
54
- in order to proceed — do not guess, and do not build anyway.** Invoke `/request-feedback` with the
55
- specific question; it posts the question as a comment on the slice and marks it `Blocked` on the
56
- board (overriding the `InProgress` set earlier), then stop this iteration without finishing the
57
- build — reply `<promise>DONE</promise>` as if the iteration's work was to raise the question, not to
58
- implement the slice. This is an escalation path, not a routine step — read the slice.json and the
59
- matching build skill's own instructions fully first; most slices are fully specified and need none of
60
- this.
53
+ **Default: make a reasonable assumption and build the slice.** If a detail is unclear or missing (an example value, a field type, a status mapping, a referenced event that isn't modeled yet, ...), pick the most sensible interpretation from `slice.json`, its specifications and the surrounding model, build it, and record each assumption in one line in `progress.txt` and as a code comment. Ambiguity alone is never a reason to stop. **Only if the slice literally cannot be built** — nothing runnable can be produced even with sensible assumptions — invoke `/request-feedback` with the specific question; it posts the question as a comment on the slice and marks it `Blocked`. That must be the absolute exception; a `Blocked` slice should mean "impossible without a human", never "the agent preferred to ask".
61
54
 
62
55
  ## Progress Report Format
63
56
 
@@ -48,13 +48,13 @@ Inspect the `sliceStatus` in the payload:
48
48
 
49
49
  This is the build trigger. Setting `InProgress` and building are one atomic step:
50
50
 
51
- **If the slice's requirements are genuinely ambiguous, contradictory, or missing a decision you need in order to proceed — do not guess, and do not build anyway.** Invoke `/request-feedback` with the specific question; it posts the question as a comment on the slice and marks it `Blocked` (superseding the `InProgress` set in step 1), then drop this task without finishing the build. This is an escalation path, not a routine step — most slices are fully specified.
51
+ **Default: make a reasonable assumption and build the slice.** If a detail is unclear or missing (an example value, a field type, a status mapping, a referenced event that isn't modeled yet, ...), pick the most sensible interpretation from `slice.json`, its specifications and the surrounding model, build it, and record each assumption in one line in `progress.txt` and as a code comment. Ambiguity alone is never a reason to stop. **Only if the slice literally cannot be built** — nothing runnable can be produced even with sensible assumptions — invoke `/request-feedback` with the specific question; it posts the question as a comment on the slice and marks it `Blocked`. That must be the absolute exception; a `Blocked` slice should mean "impossible without a human", never "the agent preferred to ask".
52
52
 
53
53
  1. Immediately call `/update-slice-status` to set the slice to `InProgress` on the board.
54
54
 
55
55
  **Claim conflict**: if this call reports the slice is already in `InProgress` (or any status other than `Planned`), another agent already claimed it first — this is expected, not an error. Log it in `progress.txt`, drop this task without building, and continue the loop (the next task will naturally cover the next slice). Do not retry.
56
56
 
57
- 2. Read the slice definition from `.build-kit/.slices/<contextSlug>/<sliceFolder>/slice.json` (written by `/load-slice`).
57
+ 2. Run `/load-slice sliceId=<payload.sliceId>` to fetch the full slice, then read the slice definition from `.build-kit/.slices/<contextSlug>/<sliceFolder>/slice.json`. The runner keeps a `slice.json` fresh from a summary endpoint, so a file holding only `id`, `title`, `status` and `sliceType` is that stub, not an empty slice — never conclude a slice has no elements from it. Only if the full fetch itself returns no commands/events/read models/fields is the slice actually empty.
58
58
 
59
59
  3. Determine the **slice type** from the slice.json:
60
60
  - **Translation** — `sliceType === "TRANSLATION"` → read `description` and `notes` from slice.json for hints; default to `/build-automation` if nothing else is specified
@@ -91,7 +91,7 @@ For each group, create a chapter on the board **before placing any events**. Reu
91
91
 
92
92
  **Prefer MCP — create a chapter:**
93
93
  ```
94
- mcp__eventmodelers__create_chapter { "boardId": "<BOARD_ID>", "x": 0, "y": 1200, "columns": <numberOfEventsInGroup> }
94
+ mcp__eventmodelers__create_chapter { "boardId": "<BOARD_ID>", "columns": <numberOfEventsInGroup> }
95
95
  ```
96
96
  (`x`/`y` are optional — see the vertical-stacking note below. `columns` is optional too — the group's event count is already known at this point, so pass it here to create the chapter with exactly the columns this group needs, instead of the default 3 plus a follow-up `add_column` batch. Response includes the new `timelineId` and `columnIds` — one id per column, left to right, ready to use directly in Step A below.)
97
97
 
@@ -115,11 +115,11 @@ mcp__eventmodelers__submit_node_events {
115
115
  **Fallback (no MCP):** see `references/api-fallback.md` — "Timeline Discovery — Step 2: Create one chapter per group — set its title".
116
116
 
117
117
  **Stack timelines vertically so they do not overlap, and in general place new chapters close to existing ones they relate to.**
118
- After creating each chapter, position it below the previous one. Use `y = index * 1200` (0-based creation order), `x = 0`. If existing chapters are already on the board, query their positions first. Prefer placing the new chapter directly below the existing chapter it is most closely related to (e.g. the same bounded context or an adjacent workflow), rather than mechanically appending below the lowest one — this keeps related chapters visually near each other on the canvas. Only fall back to `y = maxExistingY + 1200` when no related chapter exists yet. Pass this directly as `x`/`y` on `create_chapter` above, or reposition an existing chapter with:
118
+ Omit `x`/`y` on `create_chapter`: the backend stacks the new chapter below the lowest existing one, using each chapter's real current size plus a generous gap, so titles never overlap. Do not use a fixed offset like `index * 1200` — chapters are taller than that. Only pass a position to put a chapter elsewhere; if the box overlaps an existing chapter the backend moves it below everything. Prefer placing the new chapter directly below the existing chapter it is most closely related to (e.g. the same bounded context or an adjacent workflow), rather than mechanically appending below the lowest one — this keeps related chapters visually near each other on the canvas. Otherwise leave the position to the backend. To place next to a related chapter, read `get_chapter_bounds` and use `y = related.y + related.height + 600`, or reposition an existing chapter with:
119
119
 
120
120
  **Prefer MCP:**
121
121
  ```
122
- mcp__eventmodelers__move_timeline_position { "boardId": "<BOARD_ID>", "timelineId": "<TL>", "x": 0, "y": 1200 }
122
+ mcp__eventmodelers__move_timeline_position { "boardId": "<BOARD_ID>", "timelineId": "<TL>", "x": 0, "y": <y> }
123
123
  ```
124
124
 
125
125
  **Fallback (no MCP):** see `references/api-fallback.md` — "Timeline Discovery — Step 2: Reposition an existing chapter".
@@ -426,6 +426,6 @@ Include error and boundary conditions:
426
426
  - [ ] Events group into at least one recognizable business process flow
427
427
  - [ ] No overlapping event semantics — two events don't mean the same thing
428
428
  - [ ] Every event is placed into a **named chapter** — no event left in an untitled or default timeline
429
- - [ ] **Multiple chapters are stacked vertically** (y offset of 1200 per chapter) — no two chapters overlap on the canvas
429
+ - [ ] **Multiple chapters are stacked vertically** (auto-stacked by the backend) — no two chapters overlap on the canvas
430
430
  - [ ] No unnecessary swimlanes created — a swimlane exists only to mark integration with another system; never added for a new actor, a new role, or visual grouping
431
431
  - [ ] **When a second (external-system) swimlane exists, events follow one continuous story from this chapter's own swimlane throughout** — the external swimlane only ever holds isolated single-column handovers, never a run of its own, and the story resumes in this chapter's swimlane immediately after each one
@@ -37,12 +37,7 @@ When starting to work on a slice, invoke the `update-slice-status` skill with `I
37
37
  **CRITICAL: You MUST always use the provided skills to build slices. NEVER implement a slice manually.**
38
38
  **ALL fields, event names, command names, and business rules MUST come exclusively from slice.json. Do NOT invent, assume, or guess any field or logic not present in the slice definition.**
39
39
 
40
- **If, at any point below, the slice's requirements are genuinely ambiguous, contradictory, or missing
41
- a decision you need in order to proceed — do not guess, and do not build anyway.** Invoke the
42
- `request-feedback` skill with the specific question; it posts the question as a comment on the slice
43
- and marks it `Blocked`, and you then stop work on this slice for this run. This is an escalation path,
44
- not a routine step — read `slice.json` and the matching build skill's own instructions fully first;
45
- most slices are fully specified and need none of this.
40
+ **Default: make a reasonable assumption and build the slice.** If a detail is unclear or missing (an example value, a field type, a status mapping, a referenced event that isn't modeled yet, ...), pick the most sensible interpretation from `slice.json`, its specifications and the surrounding model, build it, and record each assumption in one line in `progress.txt` and as a code comment. Ambiguity alone is never a reason to stop. **Only if the slice literally cannot be built** — nothing runnable can be produced even with sensible assumptions — invoke `/request-feedback` with the specific question; it posts the question as a comment on the slice and marks it `Blocked`. That must be the absolute exception; a `Blocked` slice should mean "impossible without a human", never "the agent preferred to ask".
46
41
 
47
42
  When asked to build a slice, always follow this flow:
48
43
 
@@ -44,14 +44,7 @@ You work within **exactly ONE context at a time** — the one named in `.build-k
44
44
 
45
45
  ## Escalating Ambiguity
46
46
 
47
- **If the slice's requirements are genuinely ambiguous, contradictory, or missing a decision you need
48
- in order to proceed — do not guess, and do not build anyway.** Invoke `/request-feedback` with the
49
- specific question; it posts the question as a comment on the slice and marks it `Blocked` on the
50
- board (overriding the `InProgress` set earlier), then stop this iteration without finishing the
51
- build — reply `<promise>DONE</promise>` as if the iteration's work was to raise the question, not to
52
- implement the slice. This is an escalation path, not a routine step — read the slice.json and the
53
- matching build skill's own instructions fully first; most slices are fully specified and need none of
54
- this.
47
+ **Default: make a reasonable assumption and build the slice.** If a detail is unclear or missing (an example value, a field type, a status mapping, a referenced event that isn't modeled yet, ...), pick the most sensible interpretation from `slice.json`, its specifications and the surrounding model, build it, and record each assumption in one line in `progress.txt` and as a code comment. Ambiguity alone is never a reason to stop. **Only if the slice literally cannot be built** — nothing runnable can be produced even with sensible assumptions — invoke `/request-feedback` with the specific question; it posts the question as a comment on the slice and marks it `Blocked`. That must be the absolute exception; a `Blocked` slice should mean "impossible without a human", never "the agent preferred to ask".
55
48
 
56
49
  ## Progress Report Format
57
50
 
@@ -48,13 +48,13 @@ Inspect the `sliceStatus` in the payload:
48
48
 
49
49
  This is the build trigger. Setting `InProgress` and building are one atomic step:
50
50
 
51
- **If the slice's requirements are genuinely ambiguous, contradictory, or missing a decision you need in order to proceed — do not guess, and do not build anyway.** Invoke `/request-feedback` with the specific question; it posts the question as a comment on the slice and marks it `Blocked` (superseding the `InProgress` set in step 1), then drop this task without finishing the build. This is an escalation path, not a routine step — most slices are fully specified.
51
+ **Default: make a reasonable assumption and build the slice.** If a detail is unclear or missing (an example value, a field type, a status mapping, a referenced event that isn't modeled yet, ...), pick the most sensible interpretation from `slice.json`, its specifications and the surrounding model, build it, and record each assumption in one line in `progress.txt` and as a code comment. Ambiguity alone is never a reason to stop. **Only if the slice literally cannot be built** — nothing runnable can be produced even with sensible assumptions — invoke `/request-feedback` with the specific question; it posts the question as a comment on the slice and marks it `Blocked`. That must be the absolute exception; a `Blocked` slice should mean "impossible without a human", never "the agent preferred to ask".
52
52
 
53
53
  1. Immediately call `/update-slice-status` to set the slice to `InProgress` on the board.
54
54
 
55
55
  **Claim conflict**: if this call reports the slice is already in `InProgress` (or any status other than `Planned`), another agent already claimed it first — this is expected, not an error. Log it in `progress.txt`, drop this task without building, and continue the loop (the next task will naturally cover the next slice). Do not retry.
56
56
 
57
- 2. Read the slice definition from `.build-kit/.slices/<contextSlug>/<sliceFolder>/slice.json` (written by `/load-slice`).
57
+ 2. Run `/load-slice sliceId=<payload.sliceId>` to fetch the full slice, then read the slice definition from `.build-kit/.slices/<contextSlug>/<sliceFolder>/slice.json`. The runner keeps a `slice.json` fresh from a summary endpoint, so a file holding only `id`, `title`, `status` and `sliceType` is that stub, not an empty slice — never conclude a slice has no elements from it. Only if the full fetch itself returns no commands/events/read models/fields is the slice actually empty.
58
58
 
59
59
  3. Determine the **slice type** from the slice.json:
60
60
  - **Translation** — `sliceType === "TRANSLATION"` → read `description` and `notes` from slice.json for hints; default to `/build-automation` if nothing else is specified
@@ -62,12 +62,7 @@ doing anything else.
62
62
  **ALL fields, event names, command names, and business rules MUST come exclusively from slice.json. Do NOT
63
63
  invent, assume, or guess any field or logic not present in the slice definition.**
64
64
 
65
- **If, at any point below, the slice's requirements are genuinely ambiguous, contradictory, or missing a
66
- decision you need in order to proceed — do not guess, and do not build anyway.** Invoke the
67
- `request-feedback` skill with the specific question; it posts the question as a comment on the slice and
68
- marks it `Blocked`, and you then stop work on this slice for this run. This is an escalation path, not a
69
- routine step — read `slice.json` and the matching build skill's own instructions fully first; most slices
70
- are fully specified and need none of this.
65
+ **Default: make a reasonable assumption and build the slice.** If a detail is unclear or missing (an example value, a field type, a status mapping, a referenced event that isn't modeled yet, ...), pick the most sensible interpretation from `slice.json`, its specifications and the surrounding model, build it, and record each assumption in one line in `progress.txt` and as a code comment. Ambiguity alone is never a reason to stop. **Only if the slice literally cannot be built** — nothing runnable can be produced even with sensible assumptions — invoke `/request-feedback` with the specific question; it posts the question as a comment on the slice and marks it `Blocked`. That must be the absolute exception; a `Blocked` slice should mean "impossible without a human", never "the agent preferred to ask".
71
66
 
72
67
  When asked to build a slice, always follow this flow:
73
68
 
@@ -50,14 +50,7 @@ You work within **exactly ONE context at a time** — the one named in `.build-k
50
50
 
51
51
  ## Escalating Ambiguity
52
52
 
53
- **If the slice's requirements are genuinely ambiguous, contradictory, or missing a decision you need
54
- in order to proceed — do not guess, and do not build anyway.** Invoke `/request-feedback` with the
55
- specific question; it posts the question as a comment on the slice and marks it `Blocked` on the
56
- board (overriding the `InProgress` set earlier), then stop this iteration without finishing the
57
- build — reply `<promise>DONE</promise>` as if the iteration's work was to raise the question, not to
58
- implement the slice. This is an escalation path, not a routine step — read the slice.json and the
59
- matching build skill's own instructions fully first; most slices are fully specified and need none of
60
- this.
53
+ **Default: make a reasonable assumption and build the slice.** If a detail is unclear or missing (an example value, a field type, a status mapping, a referenced event that isn't modeled yet, ...), pick the most sensible interpretation from `slice.json`, its specifications and the surrounding model, build it, and record each assumption in one line in `progress.txt` and as a code comment. Ambiguity alone is never a reason to stop. **Only if the slice literally cannot be built** — nothing runnable can be produced even with sensible assumptions — invoke `/request-feedback` with the specific question; it posts the question as a comment on the slice and marks it `Blocked`. That must be the absolute exception; a `Blocked` slice should mean "impossible without a human", never "the agent preferred to ask".
61
54
 
62
55
  ## Progress Report Format
63
56
 
@@ -48,13 +48,13 @@ Inspect the `sliceStatus` in the payload:
48
48
 
49
49
  This is the build trigger. Setting `InProgress` and building are one atomic step:
50
50
 
51
- **If the slice's requirements are genuinely ambiguous, contradictory, or missing a decision you need in order to proceed — do not guess, and do not build anyway.** Invoke `/request-feedback` with the specific question; it posts the question as a comment on the slice and marks it `Blocked` (superseding the `InProgress` set in step 1), then drop this task without finishing the build. This is an escalation path, not a routine step — most slices are fully specified.
51
+ **Default: make a reasonable assumption and build the slice.** If a detail is unclear or missing (an example value, a field type, a status mapping, a referenced event that isn't modeled yet, ...), pick the most sensible interpretation from `slice.json`, its specifications and the surrounding model, build it, and record each assumption in one line in `progress.txt` and as a code comment. Ambiguity alone is never a reason to stop. **Only if the slice literally cannot be built** — nothing runnable can be produced even with sensible assumptions — invoke `/request-feedback` with the specific question; it posts the question as a comment on the slice and marks it `Blocked`. That must be the absolute exception; a `Blocked` slice should mean "impossible without a human", never "the agent preferred to ask".
52
52
 
53
53
  1. Immediately call `/update-slice-status` to set the slice to `InProgress` on the board.
54
54
 
55
55
  **Claim conflict**: if this call reports the slice is already in `InProgress` (or any status other than `Planned`), another agent already claimed it first — this is expected, not an error. Log it in `progress.txt`, drop this task without building, and continue the loop (the next task will naturally cover the next slice). Do not retry.
56
56
 
57
- 2. Read the slice definition from `.build-kit/.slices/<contextSlug>/<sliceFolder>/slice.json` (written by `/load-slice`).
57
+ 2. Run `/load-slice sliceId=<payload.sliceId>` to fetch the full slice, then read the slice definition from `.build-kit/.slices/<contextSlug>/<sliceFolder>/slice.json`. The runner keeps a `slice.json` fresh from a summary endpoint, so a file holding only `id`, `title`, `status` and `sliceType` is that stub, not an empty slice — never conclude a slice has no elements from it. Only if the full fetch itself returns no commands/events/read models/fields is the slice actually empty.
58
58
 
59
59
  3. Determine the **slice type** from the slice.json:
60
60
  - **Translation** — `sliceType === "TRANSLATION"` → read `description` and `notes` from slice.json for hints; default to `/build-automation` if nothing else is specified
@@ -32,12 +32,7 @@ When starting to work on a slice, invoke the `update-slice-status` skill with `I
32
32
  **CRITICAL: You MUST always use the provided skills to build slices. NEVER implement a slice manually.**
33
33
  **ALL fields, event names, command names, and business rules MUST come exclusively from slice.json. Do NOT invent, assume, or guess any field or logic not present in the slice definition.**
34
34
 
35
- **If, at any point below, the slice's requirements are genuinely ambiguous, contradictory, or missing
36
- a decision you need in order to proceed — do not guess, and do not build anyway.** Invoke the
37
- `request-feedback` skill with the specific question; it posts the question as a comment on the slice
38
- and marks it `Blocked`, and you then stop work on this slice for this run. This is an escalation path,
39
- not a routine step — read `slice.json` and the matching build skill's own instructions fully first;
40
- most slices are fully specified and need none of this.
35
+ **Default: make a reasonable assumption and build the slice.** If a detail is unclear or missing (an example value, a field type, a status mapping, a referenced event that isn't modeled yet, ...), pick the most sensible interpretation from `slice.json`, its specifications and the surrounding model, build it, and record each assumption in one line in `progress.txt` and as a code comment. Ambiguity alone is never a reason to stop. **Only if the slice literally cannot be built** — nothing runnable can be produced even with sensible assumptions — invoke `/request-feedback` with the specific question; it posts the question as a comment on the slice and marks it `Blocked`. That must be the absolute exception; a `Blocked` slice should mean "impossible without a human", never "the agent preferred to ask".
41
36
 
42
37
  When asked to build a slice, always follow this flow:
43
38
 
@@ -40,14 +40,7 @@ You work within **exactly ONE context at a time** — the one named in `.build-k
40
40
 
41
41
  ## Escalating Ambiguity
42
42
 
43
- **If the slice's requirements are genuinely ambiguous, contradictory, or missing a decision you need
44
- in order to proceed — do not guess, and do not build anyway.** Invoke `/request-feedback` with the
45
- specific question; it posts the question as a comment on the slice and marks it `Blocked` on the
46
- board (overriding the `InProgress` set in step 5), then stop this iteration without finishing the
47
- build — reply `<promise>DONE</promise>` as if the iteration's work was to raise the question, not to
48
- implement the slice. This is an escalation path, not a routine step — read the slice.json and the
49
- matching build skill's own instructions fully first; most slices are fully specified and need none of
50
- this.
43
+ **Default: make a reasonable assumption and build the slice.** If a detail is unclear or missing (an example value, a field type, a status mapping, a referenced event that isn't modeled yet, ...), pick the most sensible interpretation from `slice.json`, its specifications and the surrounding model, build it, and record each assumption in one line in `progress.txt` and as a code comment. Ambiguity alone is never a reason to stop. **Only if the slice literally cannot be built** — nothing runnable can be produced even with sensible assumptions — invoke `/request-feedback` with the specific question; it posts the question as a comment on the slice and marks it `Blocked`. That must be the absolute exception; a `Blocked` slice should mean "impossible without a human", never "the agent preferred to ask".
51
44
 
52
45
  ## Progress Report Format
53
46
 
@@ -52,7 +52,7 @@ This is the build trigger. Setting `InProgress` and building are one atomic step
52
52
 
53
53
  **Claim conflict**: if this call reports the slice is already in `InProgress` (or any status other than `Planned`), another agent already claimed it first — this is expected, not an error. Log it in `progress.txt`, drop this task without building, and continue the loop (the next task will naturally cover the next slice). Do not retry.
54
54
 
55
- 2. Read the slice definition from `.build-kit/.slices/<contextSlug>/<sliceFolder>/slice.json` (written by `/load-slice`).
55
+ 2. Run `/load-slice sliceId=<payload.sliceId>` to fetch the full slice, then read the slice definition from `.build-kit/.slices/<contextSlug>/<sliceFolder>/slice.json`. The runner keeps a `slice.json` fresh from a summary endpoint, so a file holding only `id`, `title`, `status` and `sliceType` is that stub, not an empty slice — never conclude a slice has no elements from it. Only if the full fetch itself returns no commands/events/read models/fields is the slice actually empty.
56
56
 
57
57
  3. Determine the **slice type** from the slice.json:
58
58
  - **Translation** — `sliceType === "TRANSLATION"` → read `description` and `notes` from slice.json for hints; default to `/build-automation` if nothing else is specified
@@ -93,14 +93,7 @@ After completing a task, remove it from the array and write the updated array ba
93
93
 
94
94
  ## Escalating Ambiguity
95
95
 
96
- **If the slice's requirements are genuinely ambiguous, contradictory, or missing a decision you need
97
- in order to proceed — do not guess, and do not build anyway.** Invoke `/request-feedback` with the
98
- specific question; it posts the question as a comment on the slice and marks it `Blocked` on the
99
- board (overriding the `InProgress` set earlier), then stop this iteration without finishing the
100
- build — reply `<promise>DONE</promise>` as if the iteration's work was to raise the question, not to
101
- implement the slice. This is an escalation path, not a routine step — read the slice.json and the
102
- matching build skill's own instructions fully first; most slices are fully specified and need none of
103
- this.
96
+ **Default: make a reasonable assumption and build the slice.** If a detail is unclear or missing (an example value, a field type, a status mapping, a referenced event that isn't modeled yet, ...), pick the most sensible interpretation from `slice.json`, its specifications and the surrounding model, build it, and record each assumption in one line in `progress.txt` and as a code comment. Ambiguity alone is never a reason to stop. **Only if the slice literally cannot be built** — nothing runnable can be produced even with sensible assumptions — invoke `/request-feedback` with the specific question; it posts the question as a comment on the slice and marks it `Blocked`. That must be the absolute exception; a `Blocked` slice should mean "impossible without a human", never "the agent preferred to ask".
104
97
 
105
98
  ## Progress Report Format
106
99
 
@@ -37,12 +37,7 @@ When starting to work on a slice, invoke the `update-slice-status` skill with `I
37
37
  **CRITICAL: You MUST always use the provided skills to build slices. NEVER implement a slice manually.**
38
38
  **ALL fields, event names, command names, and business rules MUST come exclusively from slice.json. Do NOT invent, assume, or guess any field or logic not present in the slice definition.**
39
39
 
40
- **If, at any point below, the slice's requirements are genuinely ambiguous, contradictory, or missing
41
- a decision you need in order to proceed — do not guess, and do not build anyway.** Invoke the
42
- `request-feedback` skill with the specific question; it posts the question as a comment on the slice
43
- and marks it `Blocked`, and you then stop work on this slice for this run. This is an escalation path,
44
- not a routine step — read `slice.json` and the matching build skill's own instructions fully first;
45
- most slices are fully specified and need none of this.
40
+ **Default: make a reasonable assumption and build the slice.** If a detail is unclear or missing (an example value, a field type, a status mapping, a referenced event that isn't modeled yet, ...), pick the most sensible interpretation from `slice.json`, its specifications and the surrounding model, build it, and record each assumption in one line in `progress.txt` and as a code comment. Ambiguity alone is never a reason to stop. **Only if the slice literally cannot be built** — nothing runnable can be produced even with sensible assumptions — invoke `/request-feedback` with the specific question; it posts the question as a comment on the slice and marks it `Blocked`. That must be the absolute exception; a `Blocked` slice should mean "impossible without a human", never "the agent preferred to ask".
46
41
 
47
42
  When asked to build a slice, always follow this flow:
48
43
 
@@ -44,14 +44,7 @@ You work within **exactly ONE context at a time** — the one named in `.build-k
44
44
 
45
45
  ## Escalating Ambiguity
46
46
 
47
- **If the slice's requirements are genuinely ambiguous, contradictory, or missing a decision you need
48
- in order to proceed — do not guess, and do not build anyway.** Invoke `/request-feedback` with the
49
- specific question; it posts the question as a comment on the slice and marks it `Blocked` on the
50
- board (overriding the `InProgress` set earlier), then stop this iteration without finishing the
51
- build — reply `<promise>DONE</promise>` as if the iteration's work was to raise the question, not to
52
- implement the slice. This is an escalation path, not a routine step — read the slice.json and the
53
- matching build skill's own instructions fully first; most slices are fully specified and need none of
54
- this.
47
+ **Default: make a reasonable assumption and build the slice.** If a detail is unclear or missing (an example value, a field type, a status mapping, a referenced event that isn't modeled yet, ...), pick the most sensible interpretation from `slice.json`, its specifications and the surrounding model, build it, and record each assumption in one line in `progress.txt` and as a code comment. Ambiguity alone is never a reason to stop. **Only if the slice literally cannot be built** — nothing runnable can be produced even with sensible assumptions — invoke `/request-feedback` with the specific question; it posts the question as a comment on the slice and marks it `Blocked`. That must be the absolute exception; a `Blocked` slice should mean "impossible without a human", never "the agent preferred to ask".
55
48
 
56
49
  ## Progress Report Format
57
50
 
@@ -48,13 +48,13 @@ Inspect the `sliceStatus` in the payload:
48
48
 
49
49
  This is the build trigger. Setting `InProgress` and building are one atomic step:
50
50
 
51
- **If the slice's requirements are genuinely ambiguous, contradictory, or missing a decision you need in order to proceed — do not guess, and do not build anyway.** Invoke `/request-feedback` with the specific question; it posts the question as a comment on the slice and marks it `Blocked` (superseding the `InProgress` set in step 1), then drop this task without finishing the build. This is an escalation path, not a routine step — most slices are fully specified.
51
+ **Default: make a reasonable assumption and build the slice.** If a detail is unclear or missing (an example value, a field type, a status mapping, a referenced event that isn't modeled yet, ...), pick the most sensible interpretation from `slice.json`, its specifications and the surrounding model, build it, and record each assumption in one line in `progress.txt` and as a code comment. Ambiguity alone is never a reason to stop. **Only if the slice literally cannot be built** — nothing runnable can be produced even with sensible assumptions — invoke `/request-feedback` with the specific question; it posts the question as a comment on the slice and marks it `Blocked`. That must be the absolute exception; a `Blocked` slice should mean "impossible without a human", never "the agent preferred to ask".
52
52
 
53
53
  1. Immediately call `/update-slice-status` to set the slice to `InProgress` on the board.
54
54
 
55
55
  **Claim conflict**: if this call reports the slice is already in `InProgress` (or any status other than `Planned`), another agent already claimed it first — this is expected, not an error. Log it in `progress.txt`, drop this task without building, and continue the loop (the next task will naturally cover the next slice). Do not retry.
56
56
 
57
- 2. Read the slice definition from `.build-kit/.slices/<contextSlug>/<sliceFolder>/slice.json` (written by `/load-slice`).
57
+ 2. Run `/load-slice sliceId=<payload.sliceId>` to fetch the full slice, then read the slice definition from `.build-kit/.slices/<contextSlug>/<sliceFolder>/slice.json`. The runner keeps a `slice.json` fresh from a summary endpoint, so a file holding only `id`, `title`, `status` and `sliceType` is that stub, not an empty slice — never conclude a slice has no elements from it. Only if the full fetch itself returns no commands/events/read models/fields is the slice actually empty.
58
58
 
59
59
  3. Determine the **slice type** from the slice.json:
60
60
  - **Webhook** — `sliceType === "WEBHOOK"` → invoke `/build-webhook`