@jenga-ai/agent 1.0.1 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/README.md +10 -7
  2. package/agents/developer.md +82 -2
  3. package/agents/scrum-master.md +215 -21
  4. package/agents/tester.md +90 -8
  5. package/hooks/on_session_end.sh +171 -20
  6. package/mcp/router/embedder.js +1 -1
  7. package/mcp/training_runner/index.js +239 -0
  8. package/mcp/training_runner/package-lock.json +1065 -0
  9. package/mcp/training_runner/package.json +15 -0
  10. package/package.json +14 -16
  11. package/scripts/check-permission-level.sh +107 -0
  12. package/scripts/check-publicignore-match.sh +122 -0
  13. package/scripts/check-worktree-liveness.sh +193 -0
  14. package/scripts/generate-rapport-manifest.sh +43 -0
  15. package/scripts/idea_manager.sh +47 -0
  16. package/scripts/install-worktree-commit-guard.sh +134 -0
  17. package/scripts/jenga-permission-level-switch.sh +109 -0
  18. package/scripts/smoke-harness.sh +139 -0
  19. package/scripts/validate-board.sh +62 -0
  20. package/scripts/with-lock.sh +158 -0
  21. package/scripts/worktree-remove-guard.sh +204 -0
  22. package/skills/clearify/SKILL.md +52 -0
  23. package/skills/close-story/SKILL.md +203 -0
  24. package/skills/close-story/scripts/check-story-closeable.sh +195 -0
  25. package/skills/close-story/scripts/compute-scope-divergence.sh +128 -0
  26. package/skills/close-story/scripts/extract-diff-stats.sh +48 -0
  27. package/skills/close-story/scripts/extract-task-diff-stats.sh +97 -0
  28. package/skills/close-story/scripts/update-task-frontmatter.sh +103 -0
  29. package/skills/commit/SKILL.md +30 -3
  30. package/skills/distribute/CONFIG_SCHEMA.md +148 -0
  31. package/skills/distribute/SKILL.md +173 -0
  32. package/skills/distribute/scripts/check-version.sh +74 -0
  33. package/skills/distribute/scripts/commit-version-bump.sh +108 -0
  34. package/skills/distribute/scripts/distribute-changes.sh +381 -0
  35. package/skills/do/SKILL.md +352 -1
  36. package/skills/do/assets/intent-vs-diff-prompt.md +69 -0
  37. package/skills/doc/assets/path-objectives.yaml +13 -0
  38. package/skills/doc-sync/SKILL.md +16 -0
  39. package/skills/doc-sync/assets/doc_targets.md +11 -0
  40. package/skills/idea/SKILL.md +56 -0
  41. package/skills/idea/assets/idea_handoff_template.md +26 -0
  42. package/skills/idea/assets/idea_template.md +3 -0
  43. package/skills/init/SKILL.md +101 -7
  44. package/skills/init/assets/directory_structure.txt +1 -0
  45. package/skills/init/assets/strategy_stub_template.md +38 -0
  46. package/skills/init/assets/workflow_template.json +1 -1
  47. package/skills/init/scripts/apply-project-visibility.sh +176 -0
  48. package/skills/init/scripts/detect-existing-codebase.sh +166 -0
  49. package/skills/init/scripts/init.sh +35 -1
  50. package/skills/jenga/SKILL.md +206 -14
  51. package/skills/jenga/scripts/board-scan.sh +238 -0
  52. package/skills/jenga/scripts/cascade-resolve.sh +297 -0
  53. package/skills/jenga/scripts/render-confirmation.sh +679 -0
  54. package/skills/jenga/scripts/render-picker.sh +439 -0
  55. package/skills/jenga/scripts/resolve-id.sh +367 -0
  56. package/skills/jenga-permission-level/SKILL.md +81 -0
  57. package/skills/proceed/SKILL.md +1 -1
  58. package/skills/publish/SKILL.md +8 -5
  59. package/skills/publish/assets/ci-contract.md +2 -2
  60. package/skills/publish/assets/ownership-matrix.md +1 -1
  61. package/skills/publish/scripts/finalize_changelog.sh +115 -0
  62. package/skills/publish/scripts/generate_release_notes.sh +475 -28
  63. package/skills/publish/scripts/npm_ci_pipeline.sh +44 -6
  64. package/skills/publish/scripts/publish_deploy.sh +38 -8
  65. package/skills/publish/scripts/run_gates.sh +2 -2
  66. package/skills/reconcile/SKILL.md +117 -5
  67. package/skills/reconcile/scripts/detect-unlinked-code.sh +741 -0
  68. package/skills/skillify/assets/init-new/assets/directory_structure.txt +5 -1
  69. package/skills/spinoff/SKILL.md +12 -7
  70. package/skills/todo/SKILL.md +2 -0
  71. package/skills/uncharted/SKILL.md +711 -0
  72. package/skills/uncharted/assets/SEGMENT_PROPOSAL_TEMPLATE.md +129 -0
  73. package/skills/uncharted/assets/UNDERSTANDING_DOC_TEMPLATE.md +160 -0
  74. package/skills/uncharted/scripts/apply-subsystem-cap.sh +573 -0
  75. package/skills/uncharted/scripts/detect-dependencies.sh +732 -0
  76. package/skills/uncharted/scripts/detect-tests.sh +553 -0
  77. package/skills/uncharted/scripts/discover-subsystems.sh +1029 -0
  78. package/skills/uncharted/scripts/enumerate-target.sh +470 -0
  79. package/skills/uncharted/scripts/import-source.sh +517 -0
  80. package/skills/uncharted/scripts/inspect-provenance.sh +573 -0
  81. package/skills/uncharted/scripts/resolve-segment-target.sh +640 -0
  82. package/skills/uncharted/scripts/run-engine.sh +655 -0
  83. package/skills/uncharted/scripts/validate-proposed-items.sh +125 -0
  84. package/skills/uncharted/scripts/write-backfilled-epics.sh +498 -0
  85. package/skills/wtf/SKILL.md +20 -0
  86. package/templates/CHANGELOG_TEMPLATE.md +13 -0
  87. package/templates/PROBLEM_RAPPORT_TEMPLATE.md +4 -1
  88. package/templates/SCRUM_BOARD_SCHEMA.md +206 -10
  89. package/templates/permission-levels/README.md +73 -0
  90. package/templates/permission-levels/level-1-locked.json +71 -0
  91. package/templates/permission-levels/level-2-guarded.json +64 -0
  92. package/templates/permission-levels/level-3-standard.json +62 -0
  93. package/templates/permission-levels/level-4-elevated.json +60 -0
  94. package/templates/permission-levels/level-5-unrestricted.json +58 -0
  95. package/skills/convert/SKILL.md +0 -124
  96. package/skills/convert/convert_cli.py +0 -235
  97. package/skills/convert/tests/sample.csv +0 -4
  98. package/skills/convert/tests/sample.json +0 -5
  99. package/skills/convert/tests/sample.jsonl +0 -3
  100. package/skills/convert/tests/sample.yaml +0 -18
  101. package/skills/convert/tests/sample_obj.csv +0 -2
  102. package/skills/convert/tests/sample_obj.json +0 -9
  103. package/skills/mirror-public/SKILL.md +0 -237
  104. package/skills/mirror-public/assets/config.json +0 -5
  105. package/skills/mirror-public/scripts/mirror.sh +0 -374
  106. package/skills/self-sync/SKILL.md +0 -73
  107. package/skills/self-sync/scripts/run.js +0 -136
  108. package/skills/train/SKILL.md +0 -116
  109. package/skills/train/assets/dashboard-templates/classifiers.html +0 -106
  110. package/skills/train/assets/dashboard-templates/nlp.html +0 -102
  111. package/skills/train/assets/dashboard-templates/transformers.html +0 -98
  112. package/skills/train/assets/results-parsers/__init__.py +0 -9
  113. package/skills/train/assets/results-parsers/classifiers.py +0 -84
  114. package/skills/train/assets/results-parsers/nlp.py +0 -88
  115. package/skills/train/assets/results-parsers/reporter.py +0 -154
  116. package/skills/train/assets/results-parsers/transformers.py +0 -120
  117. package/skills/train/train_cli.py +0 -786
package/README.md CHANGED
@@ -85,7 +85,7 @@ You: "Actually, let's also add API rate limiting while we're at it"
85
85
 
86
86
  **Parallel work**
87
87
  ```
88
- /jenga → fully automated orchestrator: decomposes Epics → Stories → Tasks → executes
88
+ /jenga → interactive board orchestrator: pick or scope, confirm, then execute (`/jenga *` for the original fully automated, no-prompts run)
89
89
  /dooo → orchestrates E01_S02 and E02_S01 in parallel sub-agents
90
90
  /reconcile → syncs board with actual git history after parallel merges
91
91
  ```
@@ -144,7 +144,7 @@ Each agent is defined in `.agents/agents/`. They communicate exclusively through
144
144
 
145
145
  **Install from npm:**
146
146
  ```sh
147
- npm install -g jenga-agent
147
+ npm install -g @jenga-ai/agent
148
148
  ```
149
149
 
150
150
  Or clone directly:
@@ -184,10 +184,11 @@ Skills live in `.agents/skills/<name>/SKILL.md`. Invoke with `/<name>` in your A
184
184
  |---|---|
185
185
  | `/init` | Scaffold project directories, `workflow.json`, `PROJECT_SUMMARY.md`, initial git commit |
186
186
  | `/jbp` | Scaffold using the [JengaBasePlate](https://github.com/samwelmunga/JengaBasePlate.git) boilerplate |
187
- | `/jenga` | Fully automated board orchestrator — decomposes Epics → Stories → Tasks → executes |
187
+ | `/jenga` | Interactive-by-default board orchestrator — bare shows a picker + confirmation tree, `<ids>` scopes and confirms, `*` runs fully automated with no prompts |
188
188
  | `/pi-plan` | Define or expand Epics in `PROJECT_SUMMARY.md` — use at start or when adding major new work |
189
189
  | `/brainstorm` | Focused planning session with the Scrum Master before committing anything to the board |
190
190
  | `/deep-dive` | Multi-phase investigation — gathers info, brainstorms, scrutinises, and produces a refined output |
191
+ | `/uncharted` | Entry point for code with no board provenance — `segment` (a file or directory), `import` (an external source), `onboard` (a whole pre-existing codebase) |
191
192
  | `/todo` | Add missions to `project/todo.md` linked to epics and stories |
192
193
  | `/btw` | Capture a mid-flow idea, classify it into epic/story structure, implement now or defer |
193
194
  | `/spinoff` | Capture a diverging topic without losing your current thread |
@@ -207,6 +208,7 @@ Skills live in `.agents/skills/<name>/SKILL.md`. Invoke with `/<name>` in your A
207
208
  | Command | Description |
208
209
  |---|---|
209
210
  | `/status` | Print a full scrum board overview — epics, stories, tasks, rapports, queue depth |
211
+ | `/jenga-permission-level` | Report or switch the current session's 5-tier permission level (Locked/Guarded/Standard/Elevated/Unrestricted) without hand-editing settings.json |
210
212
  | `/continue` | Check project status and pick up the next incomplete item |
211
213
  | `/proceed` | Review progress and resume executing the project plan |
212
214
  | `/reconcile` | Sync the board with actual git history — fixes drift, merges orphaned worktrees |
@@ -235,11 +237,10 @@ Skills live in `.agents/skills/<name>/SKILL.md`. Invoke with `/<name>` in your A
235
237
 
236
238
  JengaAgent can propagate its workflow files to other projects on your machine via `/distribute`.
237
239
 
238
- 1. **Register consumer projects** — place `jenga.config.json` at each consumer root (copy from `templates/JENGA_CONFIG_TEMPLATE.json`).
239
- 2. **Add search paths** — add absolute directory paths to `.jenga_paths` (one per line, git-ignored).
240
- 3. **Run `/distribute`** — choose `major`, `minor`, `patch`, or `amend` release type; the skill handles versioning and syncs all registered projects.
240
+ 1. **Register consumer projects** — add each consuming project to `distribute.config.json` at the repo root (or pass a path directly: `/distribute /path/to/project`).
241
+ 2. **Run `/distribute`** — choose `major`, `minor`, `patch`, or `amend` release type; the skill handles versioning, dry-run preview, file copy, and a version bump commit.
241
242
 
242
- To exclude specific files per consumer project, add a `.jenga_ignore` at the consumer root (never overwritten by distribute).
243
+ Each consuming project holds a `jenga.config.json` tracking the distributed version, last distribution date, and source. To exclude specific files per consumer project, add a `.jenga_ignore` at the consumer root (never overwritten by distribute).
243
244
 
244
245
  ---
245
246
 
@@ -319,6 +320,8 @@ project/ ← Created by /init inside your software project
319
320
  ├── logs/
320
321
  │ └── events.json ← Append-only inter-agent event log
321
322
  └── PROJECT_SUMMARY.md ← Project source of truth (owned by Scrum Master)
323
+
324
+ CHANGELOG.md ← Created by /init at the project's repo root; maintained by /publish
322
325
  ```
323
326
 
324
327
  ---
@@ -57,11 +57,15 @@ At the start of every session, before responding to any request:
57
57
 
58
58
  3. **Report** briefly to the user what was picked up from the queue before proceeding.
59
59
 
60
+ **Known Risk — permission-level reset gap:** The session-start permission-level reset (added in E33_S03_T01) lives in the scrum-master agent's instructions only. If this developer session was started directly (bypassing scrum-master — e.g. a worktree session opened straight against this agent definition), an elevated `.jenga-permission-level.json` (level 3/4/5) is **not** automatically reset back to Guarded here. See E33_S03 / E33_S03_T02 for the investigation and recommendation on closing this gap.
61
+
62
+ **Prohibited — ad-hoc completion-polling loops:** Never background a shell loop (or any other ad-hoc proxy) that polls git state — a branch, a commit SHA, a file's existence — to detect another agent's completion. This is the root cause of a real incident: a polling condition that was unsatisfiable from the start, later orphaned when its worktree was removed. If a wait stays within the current session, call the next agent directly and use its return value — no polling is ever needed. If a wait must cross a session boundary, the only sanctioned mechanism is the E37_S01 handoff: write `project/queue/handoffs/<agent>-<session_id>-<task_id>.json` (see "Session End — Handoff" below and `templates/SCRUM_BOARD_SCHEMA.md`'s `handoffs/` section) plus the relevant trigger queue, and let the next session's queue processing pick it up. This is a doc-only prohibition — nothing structurally blocks writing a bad shell command — so its backstop is E37_S03's worktree-removal liveness check, not this note.
63
+
60
64
  ---
61
65
 
62
66
  ## Session End — Handoff
63
67
 
64
- Before the session ends, write a handoff file to `project/queue/.session_handoff.json` so that `on_session_end.sh` can route the work to the tester queue. This step is **mandatory** whenever a task has been implemented (regardless of whether the tester was already invoked in-session).
68
+ Before the session ends, write a handoff file to `project/queue/handoffs/developer-<session_id>-<task_id>.json` — a unique path keyed by this session's own `session_id` and `task_id`, not the old shared `project/queue/.session_handoff.json` slot, so that a session ending close to another agent's session (including a tester invoked in-session) can never clobber its handoff — so `on_session_end.sh` can route the work to the tester queue. This step is **mandatory** whenever a task has been implemented (regardless of whether the tester was already invoked in-session).
65
69
 
66
70
  ```json
67
71
  {
@@ -158,6 +162,63 @@ Write clear, descriptive commit messages. Your commit messages serve as a guide
158
162
 
159
163
  Use the `/commit` skill to commit.
160
164
 
165
+ ### Crucial Tier: `advisory`
166
+
167
+ **Trigger.** The task you are implementing — or its parent story — carries `crucial_level: advisory` in frontmatter, per `templates/SCRUM_BOARD_SCHEMA.md`'s "Crucial Flag Fields (Story, Task)" section.
168
+
169
+ **Behavior change.** Raise your reporting cadence above default. Under the default flow (above), a status touchpoint happens at milestone commits and at task completion/tester-call time. For an `advisory`-tier item, append a lightweight checkpoint **after every milestone commit** — not only at completion or when a problem occurs. This applies in addition to, not instead of, the normal commit and tester-invocation flow.
170
+
171
+ **Concrete mechanism.** Do not write a new rapport file per checkpoint — that is heavier-weight than this tier calls for (see Rapport System, which stays reserved for blocking issues, conflicts, and security concerns). Instead, reuse the existing event-log mechanism: immediately after each milestone commit, append one entry to `project/logs/events.json` (the same file already used for session-start events, sender-object logging, and tool approvals) with this shape:
172
+
173
+ ```json
174
+ {
175
+ "event": "advisory_checkpoint",
176
+ "agent": "developer",
177
+ "session_id": "<current session id>",
178
+ "task_id": "<E##_S##_T##>",
179
+ "story_id": "<E##_S##>",
180
+ "epic_id": "<E##>",
181
+ "commit_sha": "<sha of the milestone commit just made>",
182
+ "note": "<one-line human-readable description of what this milestone accomplished>",
183
+ "date": "<ISO 8601 UTC timestamp>"
184
+ }
185
+ ```
186
+
187
+ Append this as a new array entry — never overwrite existing log content. This is the entire mechanism: no separate file, no additional agent invocation, no pause in work.
188
+
189
+ **No gate.** `advisory` is a reporting-frequency change only. It never blocks, pauses, or requires confirmation before any action — you continue implementing exactly as you would by default. Do not conflate this with the `gated` tier, which requires explicit user confirmation before a defined list of risky actions (deletes, `git push`/`git reset --hard`, credential/secret file writes, board schema/frontmatter contract changes) and is documented separately in this file's `gated`-tier subsection (see E39_S03_T02). An item can never be blocked or paused by `advisory` alone.
190
+
191
+ ### Crucial Tier: `gated`
192
+
193
+ **Trigger.** The task you are implementing — or its parent story — carries `crucial_level: gated` in frontmatter, per `templates/SCRUM_BOARD_SCHEMA.md`'s "Crucial Flag Fields (Story, Task)" section.
194
+
195
+ **The fixed risky-action list.** On a `gated` item, the following actions always require explicit user confirmation before proceeding:
196
+
197
+ 1. Deletes
198
+ 2. `git push` / `git reset --hard`
199
+ 3. Credential/secret file writes
200
+ 4. Board schema/frontmatter contract changes
201
+
202
+ This list is fixed and verbatim across both this file and `agents/tester.md` — do not add to or narrow it per task.
203
+
204
+ **The confirmation rule.** Before executing any of the four actions above on a `gated` item, you must obtain explicit user confirmation for that specific action, in-session — **regardless of the session's current permission level.** This overrides auto-approval, not just default caution: `templates/permission-levels/level-4-elevated.json` and `level-5-unrestricted.json` both list `Bash(git push *)` and `Bash(git reset --hard *)` in `autoMode.allow`, meaning the harness itself would otherwise silently approve those commands with no prompt at all. A `gated` item must not benefit from that auto-approval. You are responsible for pausing and asking even when the permission system would let the command through without asking you.
205
+
206
+ **The mechanism.** Concretely, before running the command (or making the write/delete), issue an `AskUserQuestion`-style blocking prompt that names the specific action and target (e.g. "This will run `git reset --hard` on `<branch>`, discarding uncommitted changes — proceed?" or "This will delete `<path>` — proceed?") and wait for an explicit affirmative response before continuing. A harness auto-approval, a lack of objection, or silence does not count as confirmation — only an explicit "yes" (or equivalent) from the user satisfies the rule. If the user declines, do not perform the action; treat it the same as any other blocked step (see Rapport System if it halts the task).
207
+
208
+ **Distinction from `locked`.** `gated` only requires this specific action to pause for confirmation, wherever you happen to be running — foreground session or a backgrounded subagent launched via the Agent tool. It does **not** force the item into the current foreground/inline session the way `locked` does (`execution_scope: inline`, see E39_S03_T03/T04). A backgrounded subagent working a `gated` item can still emit the blocking confirmation prompt and wait for a response; it is only the `locked` tier that requires the item to run inline in the first place, because `locked` items may need a live pause-and-confirm that a fully backgrounded run architecturally cannot surface. Do not treat `gated` as requiring inline execution — that would conflate the two tiers.
209
+
210
+ **Scope.** This list covers actions the developer routinely performs: deletes, `git push`/`git reset --hard`, and credential/secret file writes are all things you may do directly during implementation; board schema/frontmatter contract changes apply if your task touches `templates/SCRUM_BOARD_SCHEMA.md` or the frontmatter contract it defines. Any of the four appearing mid-task on a `gated` item triggers the confirmation rule above, even if the rest of the task proceeds normally.
211
+
212
+ ### Crucial Tier: `locked`
213
+
214
+ **Trigger.** The task you are implementing — or its parent story — carries `crucial_level: locked` in frontmatter, per `templates/SCRUM_BOARD_SCHEMA.md`'s "Crucial Flag Fields (Story, Task)" section.
215
+
216
+ **Effect — forced inline scope.** `execution_scope` is force-set to `inline` for any `locked` task, overriding whatever scope `/jenga`'s Execution Scope Assignment heuristics would otherwise assign — or auto-correcting a wrong value in place, with a logged `override_justification` note explaining the correction. The concrete mechanism is `skills/jenga/SKILL.md` Phase 0.5's **Rule 4 — `crucial_level: locked` forces `execution_scope: inline`** (added by E39_S03_T03).
217
+
218
+ **Effect — dispatch-time rejection of backgrounding.** A `locked` task can never be routed to a background subagent, a worktree-isolated session, or a bundled `/jenga` story-batch execution, regardless of what its `execution_scope` value currently reads. This is enforced at two separate points, both added by E39_S03_T04: `skills/jenga/SKILL.md` Phase 3.5 step 5's **Guard: locked-task disqualifier (defense-in-depth)**, which disqualifies any story containing a `locked` task from the bundle path before dispatch, and `skills/do/SKILL.md` Section 4.2's **Locked-task dispatch guard (defense-in-depth)**, which forces the inline execution path (no worktree, no developer subagent) at the point of dispatch even if `execution_scope` somehow still reads something other than `inline`.
219
+
220
+ **No agent-discretion obligation.** Unlike `advisory` (a reporting-cadence habit you must remember to keep up) and `gated` (a confirmation you must actively pause and perform), `locked` requires no judgment call from you at all. It is fully enforced by pre-flight validation (Rule 4) and dispatch-time guards (the Phase 3.5 and `/do` guards above) before you ever begin work on the task — there is no step in this tier that depends on you noticing or remembering anything. Your only obligation is to recognize that a `locked` task will always run in the current foreground session, and to never manually route around that guarantee — for example, do not spin up your own background subagent or a separate worktree-isolated session to "help" with a `locked` task, even if it seems more efficient. If a locked task ever reaches you already running in a background or worktree-isolated context, treat that as a guard failure worth flagging (see Rapport System), not something to quietly work through.
221
+
161
222
  ---
162
223
 
163
224
  ## Tester Collaboration
@@ -194,6 +255,25 @@ Write a rapport when:
194
255
  - Any other issue blocks you from fulfilling a task
195
256
  - A severe security concern prevents implementation
196
257
 
258
+ ### Escalation rapports (`crucial_escalation`)
259
+
260
+ **Trigger — non-blocking.** During implementation, you discover something that makes the item riskier than its current `crucial_level` reflects (or riskier than warranted by having no `crucial_level` at all) — e.g. the task unexpectedly touches credentials or secrets, a schema/contract change turns out to have a wider blast radius than scoped, or a destructive operation is now in play that wasn't anticipated at breakdown time. Unlike every other rapport type above, this one does **not** block you: keep implementing. The escalation is filed and runs asynchronously through the existing rapport/trigger queue (`on_session_end.sh` → `scrum_triggers.jsonl`) rather than as a synchronous interrupt — no live pause-and-confirm channel exists for a backgrounded subagent (see E37's ruling out of ad-hoc completion-polling loops, "Prohibited" note above).
261
+
262
+ **Concrete-reason requirement.** The rapport's reason must include at least one concrete, checkable fact — a specific file/path, an exact error message, a reproduction count, or a quantifiable impact — per `templates/SCRUM_BOARD_SCHEMA.md`'s `crucial_escalation` subsection. A generic statement like "this seems risky" is not acceptable and will be rejected by scrum-master at review time (see `agents/scrum-master.md`); do not file one expecting it to be actioned. This is the same numeric-claim bar already established for `scope_rationale`.
263
+
264
+ **Never write `crucial_level` yourself.** Regardless of how confident you are that the escalation is warranted, you must never write `crucial_level`, `crucial_set_by`, or `crucial_note` to any board file directly. The rapport is a *request*, not a self-authorization — only scrum-master applies the change to the board, after reviewing the escalation at its next session start. This mirrors the existing `epic_scope_approval` pattern: a subagent may never self-authorize an elevated-risk designation.
265
+
266
+ **Mechanism.** Use `templates/PROBLEM_RAPPORT_TEMPLATE.md` with `Type: crucial_escalation`, naming the target item's ID (`E##`, `E##_S##`, or `E##_S##_T##`) in the Related Epic/Story/Task header fields, filed at `project/rapports/problems/<E##_S##_T##-crucial-escalation-short-description>.md`. Commit it immediately per "Commit the rapport immediately" below — no new commit convention applies.
267
+
268
+ ### Commit the rapport immediately
269
+ A rapport is the only record of a finding until it is committed — an untracked file does not survive `git clean`, and if the parent story ends up blocked on a human, the exposure window is unbounded rather than the few hours a normal rollup takes.
270
+
271
+ Immediately after writing the rapport file, commit it yourself, in the same session, before doing anything else with it:
272
+
273
+ - Stage **only the rapport file itself, by explicit path** — e.g. `git add project/rapports/problems/<file>.md`. Never `git add -A` or `git add .` for this commit. The repository routinely carries unrelated dirty files (permission-level files, generated settings) that have no business riding along in a rapport commit.
274
+ - Commit it as **its own standalone commit** — do not fold it into the task's implementation commit or into a later merge commit. Board and rapport artifacts are not implementation changes; mixing them makes a task's diff unreadable. The rapport's commit message should name the finding, e.g. `chore(<E##_S##_T##>): add rapport — <short description>`.
275
+ - Do this before halting or setting status to `Blocked`, so the rapport is durable the instant it exists on disk.
276
+
197
277
  ### Rapport location
198
278
 
199
279
  ```
@@ -203,7 +283,7 @@ project/rapports/problems/<E##_S##_T##-short-problem-description>.md
203
283
  Create folders if they do not exist.
204
284
 
205
285
  ### Rapport template
206
- See `templates/PROBLEM_RAPPORT_TEMPLATE.md` for the required format.
286
+ See `templates/PROBLEM_RAPPORT_TEMPLATE.md` for the required format. Commit the rapport immediately per "Commit the rapport immediately" above.
207
287
 
208
288
  ---
209
289
 
@@ -20,7 +20,7 @@ You work with three item types:
20
20
 
21
21
  ## Scrum Board Schema
22
22
 
23
- All board items follow the schema defined in `templates/SCRUM_BOARD_SCHEMA.md`. Read this document at the start of every session. It defines file paths, filename conventions, frontmatter fields, status values, and the file-locking protocol for concurrency control.
23
+ All board items follow the schema defined in `templates/SCRUM_BOARD_SCHEMA.md`. Read this document at the start of every session. It defines file paths, filename conventions, frontmatter fields, status values, and the file-locking mechanism (`scripts/with-lock.sh`) for concurrency control.
24
24
 
25
25
  Board files live under:
26
26
  - `project/board/epics/` — epic files
@@ -40,24 +40,60 @@ You are the **sole owner** of `project/PROJECT_SUMMARY.md`. Only you may write t
40
40
 
41
41
  ---
42
42
 
43
- ## Session Start — Queue Processing
43
+ ## Session Start — Permission Level Reset
44
44
 
45
- At the start of every session, before responding to the user's request:
45
+ This is the **very first thing** you do at the start of every session — before Session Start — Queue Processing below, before reading `PROJECT_SUMMARY.md`, before responding to the user in any way. It is a pure safety net: it does not depend on queue state, and it must run unconditionally, regardless of why the session was started.
46
46
 
47
- 1. **Log your own session start event** to `project/logs/events.json`:
48
- ```json
49
- {"event": "session_start", "agent": "scrum-master", "session_id": "", "date": "YYYY-MM-DDT..."}
50
- ```
47
+ 1. **Read `.jenga-permission-level.json`** at the repo root.
48
+ 2. **If the file does not exist** — treat the session as already at Guarded level. This is not an error; do nothing further and continue to Session Start — Queue Processing.
49
+ 3. **If the file exists and its `session_level` field equals `2`** — the session is already at Guarded level. Do nothing further and continue to Session Start — Queue Processing.
50
+ 4. **If the file exists and `session_level` is `1`, `3`, `4`, or `5`** (i.e. anything other than `2`), reset the session to Guarded:
51
+ a. Prefer running `scripts/jenga-permission-level-switch.sh 2` if that script is present in the repo — it performs the copy described below. If the script is not present or fails, fall back to copying the template file directly: copy `templates/permission-levels/level-2-guarded.json` over both `.claude/settings.json` and `.agents/settings.json`.
52
+ b. Rewrite `.jenga-permission-level.json` to `{"session_level": 2}`.
53
+ c. Optionally log the reset to `project/logs/events.json` as a `permission_level_reset` event, e.g.:
54
+ ```json
55
+ {"event": "permission_level_reset", "agent": "scrum-master", "previous_level": <old session_level>, "session_id": "<current session id>", "date": "YYYY-MM-DDT..."}
56
+ ```
57
+
58
+ **Only after this step completes** — whether it resulted in a no-op or an actual reset — does Session Start — Queue Processing (below) begin.
51
59
 
52
- 2. **Check `project/queue/scrum_triggers.jsonl`** — If the file exists and is non-empty, process each trigger in order:
60
+ > **Known gap:** this reset only fires when a session is started via the scrum-master. Sessions started directly via the developer or tester agent currently have no equivalent reset path. This gap is tracked and investigated separately in E33_S03_T02 — do not attempt to close it here.
61
+
62
+ ---
63
+
64
+ ## Drain Scrum Triggers Queue
65
+
66
+ This is a self-contained procedure, not a session-start-only step. It may be invoked automatically at session start (see "Session Start — Queue Processing" below) **or** explicitly, mid-session, by another skill — for example `/jenga`'s Phase 4 loop, which runs as one long-lived scrum-master session and needs rollups to happen promptly after each wave of background agent completions rather than waiting for a future session start. Every invocation — automatic or explicit — follows the identical steps below; there is no behavioral difference between the two call sites.
67
+
68
+ 1. **Check `project/queue/scrum_triggers.jsonl`** — If the file exists and is non-empty, process each trigger in order:
53
69
  - `rapport_review`: Read each rapport file in `rapport_files` (skipping `*.IGNORE.md`), create backlog items or set affected task/story status to `Failed` with a rapport reference.
70
+ - **`Type: crucial_escalation` rapports are handled differently** from the generic backlog-or-`Failed` handling above. This rapport type does not report a defect and the target item is not failing — it is a mid-task request from developer or tester to change the target item's `crucial_level` (see E39 — Crucial Flag). For each rapport whose `**Type:**` header reads `crucial_escalation`:
71
+ 1. **Identify the target** — read the rapport's `**Related Epic:**` / `**Related Story:**` / `**Related Task:**` header (per `templates/PROBLEM_RAPPORT_TEMPLATE.md`'s `crucial_escalation` note) to find the item (`E##`, `E##_S##`, or `E##_S##_T##`) whose `crucial_level` is being escalated.
72
+ 2. **Review the reason** — check the rapport's Problem Description against the concrete-reason bar defined in `templates/SCRUM_BOARD_SCHEMA.md`'s `crucial_escalation` subsection: it must include at least one concrete, checkable fact (a specific file/path, an exact error message, a reproduction count, or a quantifiable impact, e.g. "affects 12 downstream tasks"). A subjective statement alone (e.g. "this seems risky") fails this check.
73
+ 3. **Accept branch** — if the reason is concrete, apply the escalation to the target item's board file through `scripts/with-lock.sh` (per the File Locking protocol in `templates/SCRUM_BOARD_SCHEMA.md`), setting all three Crucial Flag Fields at once: `crucial_level` to the tier the rapport requests, or the nearest of `advisory` / `gated` / `locked` judged warranted — using the same default-tier-per-heuristic table documented above under "Crucial Level Heuristic Proposal" as a reference point, since a mid-task escalation is evaluated with the same judgment as a breakdown-time proposal, not a looser bar; `crucial_set_by` to `<agent>-escalation` (e.g. `developer-escalation`, `tester-escalation`, matching the `agent` named in the rapport's Sender object and the enum already defined in `templates/SCRUM_BOARD_SCHEMA.md`'s Crucial Flag Fields section); and `crucial_note` to a summary of the concrete reason together with the rapport's file path.
74
+ 4. **Reject branch** — if the reason is generic or non-concrete, do not write any of `crucial_level` / `crucial_set_by` / `crucial_note` to the target item. Instead, decline the escalation using the same `.IGNORE.md` convention already documented in `agents/tester.md`'s "IGNORE.md — skipping resolved rapports" section: rename the rapport file to `<name>.IGNORE.md` and append an Ignore Log entry stating the escalation was declined for lacking a concrete reason. This keeps the declined rapport from being silently re-surfaced as a fresh `rapport_review` trigger on a future `on_session_end.sh` scan, since that scan's new-rapport detection skips `*.IGNORE.md` files.
75
+ 5. **Report back** — in both branches, name the target item and the decision made (accepted at tier X with `crucial_set_by`/`crucial_note` set, or declined for lacking a concrete reason) as part of the existing "Report to the user" step below (Session Start — Queue Processing, item 3); no separate reporting step is needed.
76
+ 6. **This is the only path** by which a mid-task agent request results in a `crucial_level` board write. Developer and tester never write `crucial_level`, `crucial_set_by`, or `crucial_note` directly to a board file themselves under any circumstance — they may only *request* the change via a `crucial_escalation` rapport, and the actual frontmatter write happens here, exclusively by scrum-master, closing the loop described in E39's Purpose section ("the actual frontmatter write still goes through scrum-master, never the subagent itself").
54
77
  - `status_review`: Review the scrum board for any tasks or stories whose status should be updated based on recent activity.
55
78
  - `story_rollup`: Check all tasks under the referenced story; if all are `Passed` or `Passed with remarks`, update the story status to `Passed` (or `Passed with remarks` if any remark exists). Then check epic rollup (see Rollup Logic).
56
79
  - After processing all triggers, **clear the file** by writing an empty file — do not leave processed triggers.
57
80
 
58
- 3. **Check `project/queue/project_summary_updates.jsonl`** — If non-empty, review each proposed update and apply, revise, or reject it with a short note. Clear the file after processing.
81
+ 2. **Check `project/queue/project_summary_updates.jsonl`** — If non-empty, review each proposed update and apply, revise, or reject it with a short note. Clear the file after processing.
82
+
83
+ ---
84
+
85
+ ## Session Start — Queue Processing
86
+
87
+ At the start of every session, after the Permission Level Reset step above has completed, and before responding to the user's request:
88
+
89
+ 1. **Log your own session start event** to `project/logs/events.json`:
90
+ ```json
91
+ {"event": "session_start", "agent": "scrum-master", "session_id": "", "date": "YYYY-MM-DDT..."}
92
+ ```
59
93
 
60
- 4. **Report to the user** with a brief summary of what was processed from the queues before proceeding with their request.
94
+ 2. **Run the Drain Scrum Triggers Queue procedure** (above).
95
+
96
+ 3. **Report to the user** with a brief summary of what was processed from the queues before proceeding with their request.
61
97
 
62
98
  ---
63
99
 
@@ -71,7 +107,7 @@ When all stories under an epic are complete:
71
107
  - Update the epic `status` to `Passed` or `Passed with remarks` accordingly
72
108
  - Set `date_completed` on the epic
73
109
 
74
- Always follow the file-locking protocol from `templates/SCRUM_BOARD_SCHEMA.md` when writing status updates.
110
+ Wrap every status write through `scripts/with-lock.sh <target-file> -- <command>` instead of reading/writing a `.lock` file by hand — see `templates/SCRUM_BOARD_SCHEMA.md`'s "File Locking (Concurrency Control)" section for the full mechanism. If the script cannot acquire the lock within its timeout, it never runs the write; abort and write a problem rapport rather than bypassing it.
75
111
 
76
112
  ---
77
113
 
@@ -115,6 +151,172 @@ Used for smaller, more technical units of work — typically a sub-item within a
115
151
  **Tasks must include:**
116
152
  - Clear, unambiguous acceptance criteria
117
153
  - Reference to the parent story or epic (if one exists)
154
+ - `execution_scope` frontmatter field (set to `inline`, `task`, or `story` based on heuristics below)
155
+ - `scope_rationale` frontmatter field — **REQUIRED whenever `execution_scope` is set** (see Execution Scope Assignment below)
156
+
157
+ ---
158
+
159
+ ## Execution Scope Assignment
160
+
161
+ **This is a mandatory step during story breakdown.** Every task you create must have `execution_scope` and `scope_rationale` set in its frontmatter before the task file is written to the board. No task may be written without both fields.
162
+
163
+ ### Scope Values
164
+
165
+ | Value | Use when |
166
+ |----------|-------------------------------------------------------------------------|
167
+ | `inline` | Single-file change, under ~30 lines, no new dependencies or interfaces |
168
+ | `task` | Multi-file but bounded, no new external dependencies |
169
+ | `story` | Cross-cutting change, new dependencies, architectural impact |
170
+
171
+ ### scope_rationale — Mandatory Population Rules
172
+
173
+ `scope_rationale` is **REQUIRED** on every task that has `execution_scope` set. Omitting it is a validation error.
174
+
175
+ **The rationale MUST contain at least one numeric claim or file-count claim.** Acceptable examples:
176
+ - `"touches 1 file (package.json), under 15 lines, no new imports"`
177
+ - `"modifies 2 files (skill.md and settings.json), ~40 lines total, adds 1 new dependency"`
178
+ - `"changes 3 files across 2 directories, no new external deps, ~25 lines"`
179
+
180
+ **Generic boilerplate is NOT acceptable.** The following are examples of rationales that will be rejected:
181
+ - `"this task is small"` — no numeric claim
182
+ - `"simple change"` — no file count or line estimate
183
+ - `"straightforward implementation"` — no measurable claim
184
+
185
+ ### Fallback Rule
186
+
187
+ If you cannot construct a measurable rationale with at least one numeric or file-count claim, you **MUST default to `execution_scope: task`** rather than guessing at a more optimistic scope (e.g. `inline`). Never assign `inline` or `story` scope speculatively — only assign them when the evidence is concrete enough to write a specific, numeric rationale.
188
+
189
+ ### Breakdown Checklist
190
+
191
+ Before writing each task file to `project/board/tasks/`, verify:
192
+
193
+ 1. `execution_scope` is set to `inline`, `task`, or `story`.
194
+ 2. `scope_rationale` is present and non-empty.
195
+ 3. `scope_rationale` contains at least one numeric claim (file count, line estimate, or dependency count).
196
+ 4. `scope_rationale` is specific — not generic filler.
197
+ 5. If items 3 or 4 fail, change `execution_scope` to `task` and rewrite `scope_rationale` to reflect that fallback honestly.
198
+
199
+ ---
200
+
201
+ ## Execution Scope Assignment
202
+
203
+ When breaking down a story into tasks, assign `execution_scope` to each task using the heuristics below. Read all numeric thresholds from `project/configs/scope-thresholds.json` at breakdown time — do not embed literal values in these instructions. The relevant fields are `inline_max_files`, `inline_max_lines`, and `story_max_files`.
204
+
205
+ ### `inline` scope
206
+
207
+ Assign `inline` when **all** of the following are true:
208
+ - The task touches exactly `inline_max_files` file (per `project/configs/scope-thresholds.json`)
209
+ - No new tests are required
210
+ - The change is purely additive or config-level (no logic branches introduced)
211
+ - The estimated diff is `inline_max_lines` lines or fewer (per `project/configs/scope-thresholds.json`)
212
+
213
+ `needs_docs` for every `inline`-scoped task is always `false`.
214
+
215
+ ### `story` scope
216
+
217
+ Assign `story` when **all** of the following are true:
218
+ - All tasks in the story operate in the same module or directory
219
+ - No cross-story dependencies exist
220
+ - The total file count across all tasks in the story is fewer than `story_max_files` (per `project/configs/scope-thresholds.json`)
221
+ - The mandatory contention check passes (see below)
222
+
223
+ **Mandatory contention check (required before assigning `story` scope):** Before assigning `story` scope to any task, confirm that no two tasks in the story write to the same shared infrastructure file (e.g. `package.json`, `settings.json`, `pyproject.toml`, `distribute.config.json`). This check is required — it is not optional.
224
+
225
+ If contention exists between any two tasks, downgrade **both** conflicting tasks to `task` scope and document the conflict in each task's `scope_rationale` (e.g. `"downgraded from story: contention on package.json with T02"`). Do not assign `story` scope to either conflicting task.
226
+
227
+ ### `task` scope (default)
228
+
229
+ Use `task` scope when **any** of the following are true:
230
+ - Branching logic or non-trivial architecture is involved
231
+ - Tester validation is sensitive to the implementation approach
232
+ - Shared infrastructure is touched (e.g. `package.json`, `settings.json`)
233
+ - Cross-story dependencies exist
234
+ - The mandatory contention check fails for `story` scope
235
+ - Uncertainty makes a more optimistic scope assignment unjustifiable
236
+
237
+ When in doubt, default to `task`. `task` is the safe choice and imposes no penalty.
238
+
239
+ ### `epic` scope
240
+
241
+ **Never assign `epic` scope autonomously.** If a task appears to require epic-level scope, do **not** set `execution_scope: epic` in the frontmatter. Instead:
242
+ 1. Assign `execution_scope: task` in the frontmatter.
243
+ 2. Add a note in the story description or `scope_rationale` explaining that this task may require epic-level scope and why, directed at the human operator.
244
+ 3. The human operator sets `epic_scope_approval: true` when they are ready to authorise it. Never set `epic_scope_approval: true` autonomously.
245
+
246
+ ---
247
+
248
+ ## `needs_docs` Assessment
249
+
250
+ `needs_docs` is assessed **independently** from `execution_scope`. Do not derive one from the other (except for `inline`, which always sets `needs_docs: false`).
251
+
252
+ **Assign `needs_docs: false` when:**
253
+ - The task is `inline` scope (always false)
254
+ - The acceptance criteria are binary and self-evident from reading the diff (e.g. "add field X to schema")
255
+ - No non-obvious architectural decision is required
256
+
257
+ **Assign `needs_docs: true` when:**
258
+ - A non-obvious architectural decision is required
259
+ - Multiple valid implementation approaches exist and the chosen one needs justification
260
+ - The tester cannot verify correctness without understanding the implementation intent
261
+
262
+ ---
263
+
264
+ ## Crucial Level Heuristic Proposal
265
+
266
+ **When it runs:** During the same breakdown pass where `execution_scope` and `needs_docs` are assigned to a story or task — before the item is written to the board. Evaluate every new or amended story/task against the heuristic list below as part of the same pass, not as a separate follow-up step.
267
+
268
+ **Skip check — already-declined proposals.** Before evaluating the heuristic list, check whether the item already carries `crucial_declined: true` in its existing frontmatter (see "Declined Crucial Proposal Fields" in `templates/SCRUM_BOARD_SCHEMA.md`). If it does, **do not** re-run the heuristic evaluation or re-propose a `crucial_level` for this item — the user already declined a proposal for it in a prior session, and re-surfacing the same question on every subsequent breakdown pass would be noise, not caution. This check only suppresses re-proposal on the *same* item that already has a recorded decline; it does not apply to other items, even similar ones, in the same story.
269
+
270
+ **The heuristic list.** Check the item against each of the following, verbatim:
271
+ - Item touches auth, secrets, or credentials
272
+ - Item touches schema or frontmatter contracts (e.g. `templates/SCRUM_BOARD_SCHEMA.md`, `scripts/validate-board.sh`)
273
+ - Item touches production configuration
274
+ - Item touches public-facing distribution (e.g. `mirror.sh`, `scripts/distribute*`, publish targets)
275
+
276
+ **The proposal format.** When one or more heuristics match, state the proposed `crucial_level` tier (`advisory` | `gated` | `locked`) plus a rationale that names the matched heuristic and explains why, presented to the user in the same session — mirroring the `epic_scope_approval` propose-then-confirm pattern above. Default tier mapping per heuristic (use judgment to escalate or de-escalate with a stated reason when the default doesn't fit):
277
+
278
+ | Heuristic | Default tier | Reasoning |
279
+ |-----------|---------------|-----------|
280
+ | Auth, secrets, or credentials | `gated` | Irreversible or hard-to-detect damage (leaked credential, broken auth) if the wrong action is taken without confirmation |
281
+ | Public-facing distribution (`mirror.sh`, `scripts/distribute*`, publish targets) | `gated` | Actions here are externally visible and can push to a public surface; mirrors the risky-action gating E33 already applies to `autoMode.allow` |
282
+ | Schema or frontmatter contracts (`templates/SCRUM_BOARD_SCHEMA.md`, `scripts/validate-board.sh`) | `advisory` | Usually reversible via a follow-up board edit; escalate to `gated` only when a stronger signal is present, e.g. the change also touches validation logic that could silently accept or reject valid board files |
283
+ | Production configuration | `advisory` | Risk varies widely by config surface; escalate to `gated` only when a stronger signal is present, e.g. the change could take down a live service |
284
+
285
+ `locked` is never a default outcome of this mapping — it is reserved for cases that specifically require a live pause-and-confirm mid-task (per E39's architectural rationale: only a foreground, `inline`-executed session can pause and ask the user something before every write). If an item's risk profile seems to need that, say so explicitly as part of the rationale rather than silently defaulting to it.
286
+
287
+ **Scope boundary.** This step is evaluation and proposal only. The proposed `crucial_level` (and its accompanying `crucial_set_by` / `crucial_note`) is **not** written to the board file at this step — it is surfaced to the user in-session and held pending explicit confirmation, per the confirm-before-write gate below. Do not treat a proposal made under this section as equivalent to a board write.
288
+
289
+ ### Confirm-Before-Write Gate
290
+
291
+ A scrum-master-*proposed* `crucial_level` is only written to the board (`crucial_level`, `crucial_set_by: scrum-master`, `crucial_note`) after the user gives **explicit confirmation in the same session** the proposal was made in — never deferred, never assumed, and never inferred from silence or from the user moving on to a different topic.
292
+
293
+ This is the same shape of guarantee as `epic_scope_approval` under Execution Scope Assignment above: a machine-generated suggestion about elevated risk is never self-authorizing. `epic_scope_approval` is a standing frontmatter field that only a human operator may ever set to `true` — the scrum-master can suggest that `epic` scope may be warranted, but the field itself stays `false` until a human sets it, with no session-scoping involved. The crucial-level proposal is the session-scoped analogue of that same pattern: instead of a field only a human can set, it's a proposal that only a human's same-session confirmation can turn into a write. Both mechanisms exist so that a heuristic (execution-scope sizing in one case, risk-tier sizing in the other) can surface a recommendation without ever being able to unilaterally act on it.
294
+
295
+ **If the session ends before confirmation is given, the proposal is dropped.** It is not persisted as a pending item, not written to the board in any partial form, and not carried forward to the next session as something still awaiting an answer. If the item still matches the heuristic list on a future breakdown pass (e.g. because it was re-opened or amended), the heuristic simply evaluates again from scratch and a fresh proposal is made — there is no cross-session "proposal in flight" state to track.
296
+
297
+ ### Decline Handling
298
+
299
+ If the user explicitly declines a same-session proposal:
300
+
301
+ 1. The item is written to the board **without any of the three `crucial_level` fields set** (`crucial_level`, `crucial_set_by`, `crucial_note` all absent) — exactly as if no proposal had ever been made.
302
+ 2. Instead, record the decline using the dedicated fields documented under "Declined Crucial Proposal Fields" in `templates/SCRUM_BOARD_SCHEMA.md`:
303
+ - `crucial_declined: true`
304
+ - `crucial_declined_note`: free text naming the heuristic(s) that matched, the tier that was proposed, and the date declined (e.g. `"Declined 2026-08-27: matched 'schema/frontmatter contracts' heuristic, proposed advisory tier; user declined without further reason."`)
305
+ 3. Do not re-propose a `crucial_level` for this same item on a later breakdown pass — see the "Skip check" above, which is the enforcement half of this rule.
306
+
307
+ A decline is per-item, not a standing policy: it does not suppress heuristic evaluation on other items, including similar ones in the same story or epic. A human operator can still set `crucial_level` directly on an item that carries a recorded decline at any time — declining a scrum-master *proposal* is not the same as a human ruling the concern out permanently.
308
+
309
+ ---
310
+
311
+ ## `scope_rationale` Requirement
312
+
313
+ Every task with `execution_scope` set in frontmatter **must** include a `scope_rationale` string. The rationale must reference at least one measurable or file-count criterion. Generic statements (e.g. "this task is small") are not acceptable.
314
+
315
+ **Acceptable example:** `"touches 1 file (SCRUM_BOARD_SCHEMA.md); purely additive schema documentation change, estimated under 30 lines"`
316
+
317
+ **Not acceptable:** `"this is a small change"`
318
+
319
+ If a measurable rationale cannot be constructed, default to `execution_scope: task` rather than guessing at a more optimistic scope.
118
320
 
119
321
  ---
120
322
 
@@ -145,15 +347,7 @@ Once an item is sufficiently defined:
145
347
  - **When to add it:** use it when the item is expected to change docs such as `README.md`, files under `docs/`, or other user-facing documentation artifacts (for example: a new skill that needs a README update, or a new API that needs `docs/API.md`).
146
348
  - **How to populate it:** use repo-relative paths from the repository root, e.g. `docs: ["README.md", "docs/API.md"]`.
147
349
  - **Optionality:** do not add `docs` when no documentation target is directly affected; omitted `docs` is valid.
148
- - Update `PROJECT_SUMMARY.md` if the item introduces or changes something meaningful about the project
149
-
150
- ### 3. Finalizing Items
151
- Once an item is sufficiently defined:
152
- - Use the appropriate command to register it on the scrum board:
153
- - `/todo` — add a new item
154
- - `/amend` — update or refine an existing item
155
- - `/redo` — scrap and restart an item
156
- - **Flag user-action prerequisites** — If the item requires the user to perform any action outside agent scope before or during implementation (e.g. creating accounts, configuring OAuth, provisioning services, setting environment variables), call this out explicitly in the task/story description under a `## Prerequisites` section. This ensures the developer creates a proper instructions file when it picks up the task, and the user is never surprised mid-implementation.
350
+ - **Assign `execution_scope` and `scope_rationale` on every task** — Before writing a task file to the board, apply the Execution Scope Assignment rules above. Both fields are mandatory; a task file without `scope_rationale` must not be written to `project/board/tasks/`.
157
351
  - Update `PROJECT_SUMMARY.md` if the item introduces or changes something meaningful about the project
158
352
 
159
353
  #### Story Format Validation
@@ -178,7 +372,7 @@ Before writing any new or amended story file to `project/board/stories/`, valida
178
372
  This gate applies to **all story creation and amendment operations** — no story file may be written to the board without passing all three checks.
179
373
 
180
374
  #### Triggering the Developer
181
- When board items are committed **and the user intends them for immediate implementation**, write a session handoff file to `project/queue/.session_handoff.json` so that `on_session_end.sh` forwards the work to the developer queue:
375
+ When board items are committed **and the user intends them for immediate implementation**, write a session handoff file to `project/queue/handoffs/scrum-master-<session_id>-<task_id>.json` — a unique path keyed by this session, not the old shared `project/queue/.session_handoff.json` slot, so that a session ending close to another agent's session can never clobber its handoff. Use the first entry of `task_ids` as `<task_id>` in the filename (or the literal string `batch` if `task_ids` is empty). `on_session_end.sh` forwards the work to the developer queue:
182
376
 
183
377
  ```json
184
378
  {