@jenga-ai/agent 3.1.1 → 3.4.0

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 (92) hide show
  1. package/README.md +52 -12
  2. package/agents/developer.md +31 -16
  3. package/agents/scrum-master.md +18 -17
  4. package/agents/tester.md +25 -15
  5. package/bin/jenga.js +10 -0
  6. package/lib/commands/dashboard.js +92 -0
  7. package/lib/skill-allow-list.json +7 -2
  8. package/package.json +21 -2
  9. package/project/app/api/lib/resolve-project-root.js +120 -0
  10. package/project/app/api/package.json +16 -0
  11. package/project/app/api/parsers/architecture.js +72 -0
  12. package/project/app/api/parsers/board.js +141 -0
  13. package/project/app/api/parsers/documentation.js +125 -0
  14. package/project/app/api/parsers/git-log.js +52 -0
  15. package/project/app/api/parsers/ideas.js +62 -0
  16. package/project/app/api/parsers/knowledge-graph.js +73 -0
  17. package/project/app/api/parsers/lib/markdown-dir-reader.js +163 -0
  18. package/project/app/api/parsers/rapports.js +148 -0
  19. package/project/app/api/parsers/todo.js +179 -0
  20. package/project/app/api/response.js +47 -0
  21. package/project/app/api/routes/architecture.js +23 -0
  22. package/project/app/api/routes/board.js +46 -0
  23. package/project/app/api/routes/documentation.js +24 -0
  24. package/project/app/api/routes/health.js +25 -0
  25. package/project/app/api/routes/history.js +55 -0
  26. package/project/app/api/routes/rapports.js +24 -0
  27. package/project/app/api/scripts/capture-snapshot.js +294 -0
  28. package/project/app/api/server.js +112 -0
  29. package/project/app/api/types.js +40 -0
  30. package/project/app/package.json +21 -0
  31. package/project/app/ui/dist/assets/index-7fj-vllY.js +104 -0
  32. package/project/app/ui/dist/assets/index-CdK3Qrep.css +1 -0
  33. package/project/app/ui/dist/index.html +13 -0
  34. package/project/app/ui/package.json +23 -0
  35. package/project/app/ui/scripts/build-snapshot-html.cjs +214 -0
  36. package/project/app/ui/scripts/dashboard-open.cjs +88 -0
  37. package/project/app/ui/scripts/dashboard-start.cjs +87 -0
  38. package/scripts/acquire-concurrency-slot.sh +220 -0
  39. package/scripts/audit-twin-divergence.sh +625 -0
  40. package/scripts/check-public-playbook-steps.sh +136 -0
  41. package/scripts/compute-deploy-reconcile.sh +439 -0
  42. package/scripts/jenga-permission-level-switch.sh +19 -3
  43. package/scripts/mark-deployed.sh +532 -0
  44. package/scripts/populate-knowledge-graph.js +429 -0
  45. package/scripts/release-concurrency-slot.sh +129 -0
  46. package/scripts/validate-board.sh +60 -2
  47. package/scripts/verify-consumer-install.sh +470 -0
  48. package/skills/j-close-story/SKILL.md +1 -1
  49. package/skills/j-cloud-connect/SKILL.md +95 -0
  50. package/skills/j-cloud-connect/scripts/configure-backend.sh +267 -0
  51. package/skills/j-cloud-connect/scripts/install-rclone.sh +153 -0
  52. package/skills/j-dashboard/SKILL.md +144 -0
  53. package/skills/j-dashboard/scripts/launch.sh +121 -0
  54. package/skills/j-dashboard/scripts/resolve-app-dir.sh +164 -0
  55. package/skills/j-dashboard/scripts/snapshot.sh +267 -0
  56. package/skills/j-dashboard-share/SKILL.md +96 -0
  57. package/skills/j-dashboard-share/scripts/upload-snapshot.sh +173 -0
  58. package/skills/j-do/SKILL.md +19 -19
  59. package/skills/j-doc-sync/SKILL.md +12 -1
  60. package/skills/j-idea/SKILL.md +1 -1
  61. package/skills/j-init/SKILL.md +5 -4
  62. package/skills/j-init/assets/directory_structure.txt +1 -0
  63. package/skills/j-init/scripts/detect-existing-codebase.sh +2 -2
  64. package/skills/j-init/scripts/init.sh +13 -2
  65. package/skills/j-playbook/SKILL.md +93 -0
  66. package/skills/j-playbook-new/SKILL.md +155 -0
  67. package/skills/j-playbook-new/scripts/playbook-new.sh +332 -0
  68. package/skills/j-proceed/SKILL.md +1 -1
  69. package/skills/j-publish/SKILL.md +1 -1
  70. package/skills/j-publish/adapters/npm-ci.md +29 -0
  71. package/skills/j-publish/scripts/npm_ci_pipeline.sh +9 -0
  72. package/skills/j-publish/scripts/npm_pipeline.sh +18 -0
  73. package/skills/j-publish/scripts/npm_stage_pipeline.sh +81 -41
  74. package/skills/j-reconcile/SKILL.md +1 -0
  75. package/skills/j-redo/SKILL.md +1 -1
  76. package/skills/j-status/SKILL.md +12 -0
  77. package/skills/j-todo/SKILL.md +2 -2
  78. package/skills/j-uncharted/SKILL.md +8 -7
  79. package/skills/j-uncharted/scripts/validate-proposed-items.sh +18 -2
  80. package/skills/jenga/SKILL.md +55 -16
  81. package/skills/jenga/playbooks/idea-to-committed.json +20 -0
  82. package/skills/jenga/playbooks/schema.json +1 -1
  83. package/skills/jenga/scripts/load-nl-catalog.js +22 -6
  84. package/skills/jenga/scripts/load-playbooks.sh +968 -41
  85. package/skills/jenga/scripts/match-playbook.sh +1 -1
  86. package/skills/jenga/scripts/render-playbook-confirmation.sh +162 -8
  87. package/skills/jenga/scripts/run-playbook-step.sh +535 -42
  88. package/skills/jenga-permission-level/SKILL.md +4 -4
  89. package/templates/KNOWLEDGE_GRAPH_STUB_SCHEMA_TEMPLATE.md +128 -0
  90. package/templates/SCRUM_BOARD_SCHEMA.md +18 -6
  91. package/templates/playbook-types.json +8 -0
  92. package/skills/jenga/playbooks/brainstorm-to-mirror.json +0 -22
package/README.md CHANGED
@@ -35,7 +35,7 @@ Jenga AI solves each of these with structure: persistent engineering context mai
35
35
 
36
36
  - **Three specialised agents** — Scrum Master, Developer, Tester — each with a distinct role and no self-graded work
37
37
  - **A persistent, Kanban-style scrum board** — Epics, Stories, and Tasks tracked as Markdown files with structured frontmatter, surviving every session boundary
38
- - **A coordinated skill pipeline — one agentic workflow, not a command list** — planning skills (`j.pi-plan`, `j.todo`) hand off to execution skills (`j.do`, `j.dooo`), which hand off to review skills (`j.status`, `j.reconcile`), each stage reading and writing the same board state — the old bare `/<name>` form still works everywhere as a permanent alias
38
+ - **A coordinated skill pipeline — one agentic workflow, not a command list** — planning skills (`j.pi-plan`, `j.todo`) hand off to execution skills (`j.do`, `j.dooo`), which hand off to review skills (`j.status`, `j.reconcile`), each stage reading and writing the same board state
39
39
  - **An event-driven trigger queue** — async handoffs between agents with a full audit trail in `project/logs/events.json`
40
40
  - **Isolated git worktrees per task** — the Developer never works directly on your main branch
41
41
  - **Works with any AI coding agent or AI-native IDE** — Claude Code, GitHub Copilot, and Codex CLI are all supported today
@@ -56,7 +56,7 @@ The Tester doesn't read your code and form an opinion about it. It executes the
56
56
 
57
57
  `CLAUDE.md` and `AGENTS.md` are generated unconditionally by `j.init` — every agent gets a real, populated root-level context file, not just a pointer. If either file already exists as a genuine pre-existing user file, Jenga leaves it untouched, writes its own copy as `J-CLAUDE.md` / `J-AGENTS.md`, and inserts a short reference line into the original.
58
58
 
59
- `.github/copilot-instructions.md` follows a different path, because Copilot needs it before `j.init` may ever run: `npm install` triggers `scripts/postinstall.js`, which writes it unconditionally and non-interactively, so `j.<name>` routing (the bare `/<name>` form still resolves too, as a permanent alias) works from a consumer's very first Copilot command. A later `jenga init` run refines that same file using the project's actual chosen skills path.
59
+ `.github/copilot-instructions.md` follows a different path, because Copilot needs it before `j.init` may ever run: `npm install` triggers `scripts/postinstall.js`, which writes it unconditionally and non-interactively, so `j.<name>` (and `/j-<name>`) routing works from a consumer's very first Copilot command. A later `jenga init` run refines that same file using the project's actual chosen skills path.
60
60
 
61
61
  ---
62
62
 
@@ -171,6 +171,8 @@ Or clone directly:
171
171
 
172
172
  Run `j.status` at any time to see where the project stands.
173
173
 
174
+ 📖 **New to Jenga AI?** The [Intro Guide](https://samwelmunga.github.io/jenga-npm/getting-started.html) walks through the philosophy, the three pillars (role separation, board hierarchy, session continuity), and a full first-15-minutes walkthrough for both a new project and an existing codebase — mirrored at [project/.wiki/intro-guide.md](project/.wiki/intro-guide.md).
175
+
174
176
  **CLI maintenance commands.** The `jenga` binary installed alongside the package (`jenga --help`)
175
177
  also ships a couple of maintenance commands, distinct from the in-agent `j.<name>` skills above:
176
178
 
@@ -196,29 +198,67 @@ The framework is platform-agnostic by design — any AI agent that can read Mark
196
198
 
197
199
  ## Skills (Slash Commands)
198
200
 
199
- Skills live in `.agents/skills/<name>/SKILL.md`. Invoke with `j.<name>` in your AI agent or IDE's command interface — the old bare `/<name>` form also keeps working permanently as an alias. A handful of the most foundational commands:
201
+ Skills live in `.agents/skills/<name>/SKILL.md`. Invoke with `j.<name>` in your AI agent or IDE's command interface, or with its `/j-<name>` directory form (e.g. `/j-init`) — both resolve to the same skill. A handful of the most foundational commands:
200
202
 
201
- > ⚠️ **Command collision with a host tool?** Some host tools ship their own built-in command that can
202
- > shadow one of Jenga's — e.g. GitHub Copilot's own built-in `/init`, which could silently shadow
203
- > Jenga's `/init` skill. Every skill (except `init`, already handled) has a collision-safe `/j-<name>`
204
- > directory-twin form — e.g. `/j-init` — that always resolves to the genuine Jenga skill regardless of
205
- > what else is installed. This is separate from the `j.<name>` prefix form above: it's a real duplicate
206
- > directory under a distinct name, not a routing alias, generated and kept in sync via
207
- > `scripts/generate-j-alias.sh`. If a `j.<name>` or bare `/<name>` command isn't behaving as
208
- > documented, try its `/j-<name>` form instead.
203
+ > **Why `/j-<name>`, not a bare `/<name>`?** Some host tools ship their own built-in command that can
204
+ > shadow one of Jenga's — e.g. GitHub Copilot's own built-in `/init`. Jenga sidesteps this
205
+ > structurally: every skill ships under the collision-safe `/j-<name>` directory name, so there's no
206
+ > bare `/<name>` directory for a host tool's own command to collide with in the first place.
207
+ > `/j-<name>` isn't a fallback to reach for when something misbehaves — it's simply how the skill is
208
+ > named. Two permanent exceptions ship bare-only, with no `/j-<name>` form: `/jenga` and
209
+ > `/jenga-permission-level` — deliberately excluded, since neither is the kind of skill a host tool's
210
+ > own built-in command is likely to name-collide with.
209
211
 
210
212
  | Command | Description |
211
213
  |---|---|
212
214
  | `j.init` | Scaffold project directories, `workflow.json`, `PROJECT_SUMMARY.md`, initial git commit |
213
- | `j.jenga` | Interactive-by-default board orchestrator — bare shows a picker + confirmation tree, `<ids>` scopes and confirms, `*` runs fully automated with no prompts |
214
215
  | `j.todo` | Add missions to `project/todo.md` linked to epics and stories |
215
216
  | `j.do` | Execute tasks from the scrum board, drives the Developer agent through the full loop |
216
217
  | `j.status` | Print a full scrum board overview — epics, stories, tasks, rapports, queue depth |
217
218
 
219
+ ### `/jenga` — one command, several behaviors
220
+
221
+ `/jenga` doesn't fit the table above, because what it does depends entirely on how it's invoked:
222
+
223
+ | Invocation | Behavior |
224
+ |---|---|
225
+ | `/jenga` (bare) | Renders a picker + confirmation tree before scoping the run |
226
+ | `/jenga <ids>` | Resolves an explicit fuzzy-ID scope and confirms it |
227
+ | `/jenga *` | Fully automated — decomposes, queues, and executes everything eligible, no prompts |
228
+ | `/jenga <free text>` | Natural-language dispatch — matches a single skill directly, or proposes a multi-skill [playbook](#playbooks) when the request spans more than one |
229
+
230
+ It's one of the two permanent bare-only exceptions noted above — there's no `/j-jenga` form.
231
+
218
232
  > 📖 **Full skill list** (planning, review, committing & maintenance commands): [Docs site](https://samwelmunga.github.io/jenga-npm/skills.html) — mirrored at [project/.wiki/documentation.md#skills](project/.wiki/documentation.md#skills)
219
233
 
220
234
  ---
221
235
 
236
+ ## Playbooks
237
+
238
+ Some workflows are always the same sequence of skills — plan it, build it, commit it. A **playbook** is a named, pre-defined chain of skills, run and confirmed as one unit instead of typed out one skill at a time.
239
+
240
+ Invoke one by describing what you want in plain language to `j.jenga` — it proposes a matching playbook as a numbered, editable list before anything runs — or name one directly:
241
+
242
+ ```
243
+ j.playbook idea-to-committed
244
+ ```
245
+
246
+ which resolves to:
247
+
248
+ ```
249
+ j.brainstorm → j.todo → j.do → j.commit
250
+ ```
251
+
252
+ Calling `j.playbook` with no id prints a table of every available playbook (id, name, and steps) instead of resolving one.
253
+
254
+ Nothing executes until you confirm the chain, and any step can be unchecked first. `brainstorm-to-mirror` extends the same chain through `j.dev-done` and `j.mirror-public` for a full public release; `understand-then-ship` prepends `j.uncharted` investigation for unfamiliar code before running the same pipeline.
255
+
256
+ When a step forwards its result into the next one, that value has a declared **output type** (a plain string, a list of board IDs, a list of files) so the chain can be validated before it runs. See [Getting Started](https://samwelmunga.github.io/jenga-npm/getting-started.html#how-playbooks-know-what-a-skill-produces) for how that works.
257
+
258
+ Want your own recurring chain? `j.playbook-new` walks you through authoring one — id, name, description, keywords, examples, and an ordered list of skills — writes it to `project/.playbooks/<id>.json` alongside the built-in ones, and self-validates the result before reporting success.
259
+
260
+ ---
261
+
222
262
  ## When to Use Jenga AI
223
263
 
224
264
  **Use it when:**
@@ -17,7 +17,7 @@ You do not update the status of tasks, stories, or epics. Status changes are exc
17
17
 
18
18
  ## Scrum Board Schema
19
19
 
20
- All board items follow the schema defined in `templates/SCRUM_BOARD_SCHEMA.md`. Read this document once and reference it for all file paths, field names, ID formats, and status values. Board files live under `project/board/epics/`, `project/board/stories/`, and `project/board/tasks/`.
20
+ All board items follow the schema defined in `$([ -f templates/SCRUM_BOARD_SCHEMA.md ] && echo templates/SCRUM_BOARD_SCHEMA.md || echo node_modules/@jenga-ai/agent/templates/SCRUM_BOARD_SCHEMA.md)`. Read this document once and reference it for all file paths, field names, ID formats, and status values. Board files live under `project/board/epics/`, `project/board/stories/`, and `project/board/tasks/`.
21
21
 
22
22
  ---
23
23
 
@@ -59,7 +59,7 @@ At the start of every session, before responding to any request:
59
59
 
60
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
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.
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 `$([ -f templates/SCRUM_BOARD_SCHEMA.md ] && echo templates/SCRUM_BOARD_SCHEMA.md || echo node_modules/@jenga-ai/agent/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
63
 
64
64
  ---
65
65
 
@@ -91,8 +91,8 @@ If no implementation work was performed during the session (e.g., a planning-onl
91
91
  2. Read `PROJECT_SUMMARY.md`
92
92
  3. Read the task/story file from the scrum board to fully understand what is expected
93
93
  4. Assess what the implementation requires — dependencies, affected files, security considerations, reuse opportunities
94
- 5. **Identify user-action prerequisites** — If the task requires any configuration, setup, or action that must be performed by the user outside the agent's scope (e.g. registering an OAuth app, configuring environment variables, provisioning external services), create an instructions file immediately at `project/instructions/<E##_S##_T##>_INSTRUCTIONS.md` using `templates/USER_INSTRUCTIONS_TEMPLATE.md` (create the `project/instructions/` directory if it does not yet exist). Do not proceed until this file is written and the user has been notified. This applies to all out-of-scope prerequisites, not only secrets.
95
- 6. **Write an execution plan** to `project/documentation/plans/<E##_S##_T##>-plan.md` using `templates/EXECUTION_PLAN_TEMPLATE.md`. Fill in all sections before writing any code. This step is mandatory.
94
+ 5. **Identify user-action prerequisites** — If the task requires any configuration, setup, or action that must be performed by the user outside the agent's scope (e.g. registering an OAuth app, configuring environment variables, provisioning external services), create an instructions file immediately at `project/instructions/<E##_S##_T##>_INSTRUCTIONS.md` using `$([ -f templates/USER_INSTRUCTIONS_TEMPLATE.md ] && echo templates/USER_INSTRUCTIONS_TEMPLATE.md || echo node_modules/@jenga-ai/agent/templates/USER_INSTRUCTIONS_TEMPLATE.md)` (create the `project/instructions/` directory if it does not yet exist). Do not proceed until this file is written and the user has been notified. This applies to all out-of-scope prerequisites, not only secrets.
95
+ 6. **Write an execution plan** to `project/documentation/plans/<E##_S##_T##>-plan.md` using `$([ -f templates/EXECUTION_PLAN_TEMPLATE.md ] && echo templates/EXECUTION_PLAN_TEMPLATE.md || echo node_modules/@jenga-ai/agent/templates/EXECUTION_PLAN_TEMPLATE.md)`. Fill in all sections before writing any code. This step is mandatory.
96
96
  6. If the scope of a single request maps to multiple items, identify them all before starting
97
97
  7. Create a dedicated worktree for the work (see Worktree Management below)
98
98
  8. Implement, commit at milestones, and call the tester agent when ready
@@ -164,7 +164,7 @@ Use the `j.commit` skill to commit.
164
164
 
165
165
  ### Crucial Tier: `advisory`
166
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.
167
+ **Trigger.** The task you are implementing — or its parent story — carries `crucial_level: advisory` in frontmatter, per `$([ -f templates/SCRUM_BOARD_SCHEMA.md ] && echo templates/SCRUM_BOARD_SCHEMA.md || echo node_modules/@jenga-ai/agent/templates/SCRUM_BOARD_SCHEMA.md)`'s "Crucial Flag Fields (Story, Task)" section.
168
168
 
169
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
170
 
@@ -190,7 +190,7 @@ Append this as a new array entry — never overwrite existing log content. This
190
190
 
191
191
  ### Crucial Tier: `gated`
192
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.
193
+ **Trigger.** The task you are implementing — or its parent story — carries `crucial_level: gated` in frontmatter, per `$([ -f templates/SCRUM_BOARD_SCHEMA.md ] && echo templates/SCRUM_BOARD_SCHEMA.md || echo node_modules/@jenga-ai/agent/templates/SCRUM_BOARD_SCHEMA.md)`'s "Crucial Flag Fields (Story, Task)" section.
194
194
 
195
195
  **The fixed risky-action list.** On a `gated` item, the following actions always require explicit user confirmation before proceeding:
196
196
 
@@ -201,17 +201,17 @@ Append this as a new array entry — never overwrite existing log content. This
201
201
 
202
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
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.
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: `$([ -f templates/permission-levels/level-4-elevated.json ] && echo templates/permission-levels/level-4-elevated.json || echo node_modules/@jenga-ai/agent/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
205
 
206
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
207
 
208
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
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.
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 `$([ -f templates/SCRUM_BOARD_SCHEMA.md ] && echo templates/SCRUM_BOARD_SCHEMA.md || echo node_modules/@jenga-ai/agent/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
211
 
212
212
  ### Crucial Tier: `locked`
213
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.
214
+ **Trigger.** The task you are implementing — or its parent story — carries `crucial_level: locked` in frontmatter, per `$([ -f templates/SCRUM_BOARD_SCHEMA.md ] && echo templates/SCRUM_BOARD_SCHEMA.md || echo node_modules/@jenga-ai/agent/templates/SCRUM_BOARD_SCHEMA.md)`'s "Crucial Flag Fields (Story, Task)" section.
215
215
 
216
216
  **Effect — forced inline scope.** `execution_scope` is force-set to `inline` for any `locked` task, overriding whatever scope `j.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
217
 
@@ -223,9 +223,24 @@ This list is fixed and verbatim across both this file and `agents/tester.md` —
223
223
 
224
224
  ## Tester Collaboration
225
225
 
226
- You do not run tests. Before calling the tester agent, **write an execution summary** to `project/documentation/summaries/<E##_S##_T##>-summary.md` using `templates/EXECUTION_SUMMARY_TEMPLATE.md`. Fill in all sections — what was implemented, files changed, commit SHAs, acceptance criteria coverage, and any concerns for the tester. This step is mandatory before every tester invocation.
226
+ You do not run tests. Before calling the tester agent, **write an execution summary** to `project/documentation/summaries/<E##_S##_T##>-summary.md` using `$([ -f templates/EXECUTION_SUMMARY_TEMPLATE.md ] && echo templates/EXECUTION_SUMMARY_TEMPLATE.md || echo node_modules/@jenga-ai/agent/templates/EXECUTION_SUMMARY_TEMPLATE.md)`. Fill in all sections — what was implemented, files changed, commit SHAs, acceptance criteria coverage, and any concerns for the tester. This step is mandatory before every tester invocation.
227
227
 
228
- When you reach a meaningful milestone within a task where verification is appropriate — or when the task is complete — call the tester agent. Before invoking the tester, compose a short `resolved_context` digest of what you already resolved during implementation — which files you touched and why, which acceptance criteria map to which changes, any conventions or precedent you followed — and persist it by calling `scripts/write-context-digest.sh --agent developer --session-id <session_id> --task-id <task_id>` with that content (stays under the ~100-line/few-hundred-token cap defined in `templates/SCRUM_BOARD_SCHEMA.md`'s `resolved_context` subsection; the script rejects oversized input rather than truncating it). Place the script's returned path in the sender object's `resolved_context` field. Always pass the following sender object when invoking the tester:
228
+ ### Tester Concurrency Cap (acquire before invoking, release on every exit)
229
+
230
+ Before any in-session tester invocation described below, acquire a tester slot:
231
+
232
+ ```
233
+ scripts/acquire-concurrency-slot.sh tester <task_id> <orchestrator_session_id>
234
+ ```
235
+
236
+ `<orchestrator_session_id>` is the same session-id concept already used elsewhere in this file to name `project/queue/concurrency-slots-<session_id>.json` and `project/queue/handoffs/developer-<session_id>-<task_id>.json` — thread through that same value rather than inventing a new one (when this developer session is itself the orchestrating session, that is simply the current session's `session_id`).
237
+
238
+ - **On success (exit 0):** proceed with the tester invocation exactly as documented below, in-session. When the tester's session ends — regardless of outcome (`Passed`, `Failed`, `Rejected`, or `"error"`) — call `scripts/release-concurrency-slot.sh tester <task_id> <orchestrator_session_id>`. Every exit path out of the tester invocation releases the slot; a failed or errored tester run is not an exception to this.
239
+ - **On a full cap (non-zero exit):** do not poll or wait for a slot to free up — the "Prohibited — ad-hoc completion-polling loops" rule (Session Start — Queue Processing, above) applies here without exception; a retry loop waiting on the counter file would be exactly the kind of ad-hoc polling that rule forbids. Instead, skip the in-session tester invocation entirely and fall back to the existing mandatory mechanism in "Session End — Handoff" above: write `project/queue/handoffs/developer-<session_id>-<task_id>.json` in its documented shape (`status: "implementation_complete"`), unchanged from what's already specified there. A later tester session picks up the work via `on_session_end.sh`'s normal routing to the tester queue. A routine cap-full condition is expected flow control, not a blocking issue — do not write a problem rapport for it.
240
+
241
+ This gate governs only the in-session tester call described in this section; it does not change worktree creation, commit discipline, or the handoff file's shape.
242
+
243
+ When you reach a meaningful milestone within a task where verification is appropriate — or when the task is complete — call the tester agent. Before invoking the tester, compose a short `resolved_context` digest of what you already resolved during implementation — which files you touched and why, which acceptance criteria map to which changes, any conventions or precedent you followed — and persist it by calling `bash "$([ -f scripts/write-context-digest.sh ] && echo scripts/write-context-digest.sh || echo node_modules/@jenga-ai/agent/scripts/write-context-digest.sh)" --agent developer --session-id <session_id> --task-id <task_id>` with that content (stays under the ~100-line/few-hundred-token cap defined in `$([ -f templates/SCRUM_BOARD_SCHEMA.md ] && echo templates/SCRUM_BOARD_SCHEMA.md || echo node_modules/@jenga-ai/agent/templates/SCRUM_BOARD_SCHEMA.md)`'s `resolved_context` subsection; the script rejects oversized input rather than truncating it). Place the script's returned path in the sender object's `resolved_context` field. Always pass the following sender object when invoking the tester:
229
244
 
230
245
  ```json
231
246
  {
@@ -238,14 +253,14 @@ When you reach a meaningful milestone within a task where verification is approp
238
253
  "date": "<ISO 8601 UTC timestamp>",
239
254
  "paths": ["<list of commit SHAs for this work>"],
240
255
  "worktree": "<absolute path to the worktree>",
241
- "resolved_context": "<path returned by scripts/write-context-digest.sh, or omit if no digest was written>"
256
+ "resolved_context": "<path returned by write-context-digest.sh (see the Tester Collaboration resolution above), or omit if no digest was written>"
242
257
  }
243
258
  }
244
259
  ```
245
260
 
246
261
  All fields must be present except `resolved_context`, which is optional. This digest is a starting point only, never a restriction: the tester may and should still read the full execution summary, the diff itself, or any other source file when the digest doesn't cover what it needs. In addition to the sender object, include a short plain-text implementation summary: what was implemented, which files changed, and any known edge cases or concerns. Reference the execution summary at `project/documentation/summaries/<E##_S##_T##>-summary.md` for full detail.
247
262
 
248
- Wait for the tester's response before continuing. If the tester returns `"failed"` or `"error"`, address the findings before proceeding.
263
+ Wait for the tester's response before continuing. If the tester returns `"failed"` or `"error"`, address the findings before proceeding. Either way — pass, fail, or error — release the tester slot now per "Tester Concurrency Cap" above; the slot must not remain held once the tester's response has been received.
249
264
 
250
265
  ---
251
266
 
@@ -260,11 +275,11 @@ Write a rapport when:
260
275
 
261
276
  **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).
262
277
 
263
- **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`.
278
+ **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 `$([ -f templates/SCRUM_BOARD_SCHEMA.md ] && echo templates/SCRUM_BOARD_SCHEMA.md || echo node_modules/@jenga-ai/agent/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`.
264
279
 
265
280
  **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.
266
281
 
267
- **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.
282
+ **Mechanism.** Use `$([ -f templates/PROBLEM_RAPPORT_TEMPLATE.md ] && echo templates/PROBLEM_RAPPORT_TEMPLATE.md || echo node_modules/@jenga-ai/agent/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.
268
283
 
269
284
  ### Commit the rapport immediately
270
285
  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.
@@ -284,7 +299,7 @@ project/rapports/problems/<E##_S##_T##-short-problem-description>.md
284
299
  Create folders if they do not exist.
285
300
 
286
301
  ### Rapport template
287
- See `templates/PROBLEM_RAPPORT_TEMPLATE.md` for the required format. Commit the rapport immediately per "Commit the rapport immediately" above.
302
+ See `$([ -f templates/PROBLEM_RAPPORT_TEMPLATE.md ] && echo templates/PROBLEM_RAPPORT_TEMPLATE.md || echo node_modules/@jenga-ai/agent/templates/PROBLEM_RAPPORT_TEMPLATE.md)` for the required format. Commit the rapport immediately per "Commit the rapport immediately" above.
288
303
 
289
304
  ---
290
305
 
@@ -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 mechanism (`scripts/with-lock.sh`) for concurrency control.
23
+ All board items follow the schema defined in `$([ -f templates/SCRUM_BOARD_SCHEMA.md ] && echo templates/SCRUM_BOARD_SCHEMA.md || echo node_modules/@jenga-ai/agent/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
@@ -48,7 +48,7 @@ This is the **very first thing** you do at the start of every session — before
48
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
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
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`.
51
+ a. Prefer running `bash "$([ -f scripts/jenga-permission-level-switch.sh ] && echo scripts/jenga-permission-level-switch.sh || echo node_modules/@jenga-ai/agent/scripts/jenga-permission-level-switch.sh)" 2` if that script is present (monorepo checkout or installed npm package) — it performs the copy described below. If the script is not present or fails, fall back to copying the template file directly: copy `$([ -f templates/permission-levels/level-2-guarded.json ] && echo templates/permission-levels/level-2-guarded.json || echo node_modules/@jenga-ai/agent/templates/permission-levels/level-2-guarded.json)` over both `.claude/settings.json` and `.agents/settings.json`.
52
52
  b. Rewrite `.jenga-permission-level.json` to `{"session_level": 2}`.
53
53
  c. Optionally log the reset to `project/logs/events.json` as a `permission_level_reset` event, e.g.:
54
54
  ```json
@@ -68,15 +68,16 @@ This is a self-contained procedure, not a session-start-only step. It may be inv
68
68
  1. **Check `project/queue/scrum_triggers.jsonl`** — If the file exists and is non-empty, process each trigger in order:
69
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
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.
71
+ 1. **Identify the target** — read the rapport's `**Related Epic:**` / `**Related Story:**` / `**Related Task:**` header (per `$([ -f templates/PROBLEM_RAPPORT_TEMPLATE.md ] && echo templates/PROBLEM_RAPPORT_TEMPLATE.md || echo node_modules/@jenga-ai/agent/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 `$([ -f templates/SCRUM_BOARD_SCHEMA.md ] && echo templates/SCRUM_BOARD_SCHEMA.md || echo node_modules/@jenga-ai/agent/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 `$([ -f scripts/with-lock.sh ] && echo scripts/with-lock.sh || echo node_modules/@jenga-ai/agent/scripts/with-lock.sh)` (per the File Locking protocol in `$([ -f templates/SCRUM_BOARD_SCHEMA.md ] && echo templates/SCRUM_BOARD_SCHEMA.md || echo node_modules/@jenga-ai/agent/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 `$([ -f templates/SCRUM_BOARD_SCHEMA.md ] && echo templates/SCRUM_BOARD_SCHEMA.md || echo node_modules/@jenga-ai/agent/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
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
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
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").
77
77
  - `status_review`: Review the scrum board for any tasks or stories whose status should be updated based on recent activity.
78
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).
79
79
  - `elicitation_resume`: A `j.uncharted` conversational architecture elicitation session (`onboard`'s default flow, or `segment --mode investigate` — E20_S08_T03) ended mid-run without converging. Read `state_file` (`project/queue/elicitation-state/<elicitation_id>.json`, written by `skills/uncharted/scripts/elicitation-state.sh`) to see exactly where it left off — which nodes already converged, which are still pending or flagged, and any directory-triage/checkpoint data already confirmed — then resume the conversational flow documented in `skills/uncharted/SKILL.md`'s Multi-Session Persistence subsection from that point rather than restarting the elicitation from scratch. If the state file is missing or unreadable, report that to the user rather than silently starting a fresh elicitation under the same id.
80
+ - `capacity_starvation`: `skills/do/SKILL.md`'s per-session concurrency cap (E32_S15) blocked the same board item for 3 consecutive dispatch waves because its role (`developer` or `tester`) stayed at cap. Surface a plain warning naming the affected item and its consecutive-block wave count, suggesting the configured cap (`max_concurrent_developers` / `max_concurrent_testers` in `project/configs/scope-thresholds.json`) may be too low or the session may be starved. No automatic remediation — this trigger is informational only.
80
81
  - After processing all triggers, **clear the file** by writing an empty file — do not leave processed triggers.
81
82
 
82
83
  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.
@@ -108,7 +109,7 @@ When all stories under an epic are complete:
108
109
  - Update the epic `status` to `Passed` or `Passed with remarks` accordingly
109
110
  - Set `date_completed` on the epic
110
111
 
111
- 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.
112
+ Wrap every status write through `"$([ -f scripts/with-lock.sh ] && echo scripts/with-lock.sh || echo node_modules/@jenga-ai/agent/scripts/with-lock.sh)" <target-file> -- <command>` instead of reading/writing a `.lock` file by hand — see `$([ -f templates/SCRUM_BOARD_SCHEMA.md ] && echo templates/SCRUM_BOARD_SCHEMA.md || echo node_modules/@jenga-ai/agent/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.
112
113
 
113
114
  ---
114
115
 
@@ -225,7 +226,7 @@ Assign `inline` when **all** of the following are true:
225
226
 
226
227
  ### `light` scope
227
228
 
228
- `light` sits between `inline` and `task`: a single developer subagent pass with no worktree, self-verified via `scripts/smoke-harness.sh` in lieu of a separate tester invocation. If the smoke harness fails, execution falls back to `task` scope automatically at runtime — see `templates/SCRUM_BOARD_SCHEMA.md`'s Execution Scope Fields section for the full runtime contract.
229
+ `light` sits between `inline` and `task`: a single developer subagent pass with no worktree, self-verified via `$([ -f scripts/smoke-harness.sh ] && echo scripts/smoke-harness.sh || echo node_modules/@jenga-ai/agent/scripts/smoke-harness.sh)` in lieu of a separate tester invocation. If the smoke harness fails, execution falls back to `task` scope automatically at runtime — see `$([ -f templates/SCRUM_BOARD_SCHEMA.md ] && echo templates/SCRUM_BOARD_SCHEMA.md || echo node_modules/@jenga-ai/agent/templates/SCRUM_BOARD_SCHEMA.md)`'s Execution Scope Fields section for the full runtime contract.
229
230
 
230
231
  Assign `light` when **any** of the following are true:
231
232
  - The task exceeds `inline_max_files` or `inline_max_lines` (per `project/configs/scope-thresholds.json`), but remains a single, tightly-bounded change (one file, or a small handful of directly related files)
@@ -236,7 +237,7 @@ Assign `light` when **any** of the following are true:
236
237
 
237
238
  **Distinguishing `light` from `task`:** assign `light`, not `task`, only when **all** of the following also hold:
238
239
  - The task does **not** require worktree isolation — it can be implemented directly by a single developer subagent pass
239
- - The task does **not** require independent tester verification — a `scripts/smoke-harness.sh` self-check is sufficient to catch regressions
240
+ - The task does **not** require independent tester verification — a `$([ -f scripts/smoke-harness.sh ] && echo scripts/smoke-harness.sh || echo node_modules/@jenga-ai/agent/scripts/smoke-harness.sh)` self-check is sufficient to catch regressions
240
241
  - No shared-infrastructure contention exists (same contention concept as the `story` scope's mandatory contention check below — e.g. `package.json`, `settings.json`, `pyproject.toml`)
241
242
  - The task has no cross-story dependencies and tester validation is not sensitive to the specific implementation approach chosen
242
243
 
@@ -297,11 +298,11 @@ When in doubt, default to `task`. `task` is the safe choice and imposes no penal
297
298
 
298
299
  **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.
299
300
 
300
- **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.
301
+ **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 `$([ -f templates/SCRUM_BOARD_SCHEMA.md ] && echo templates/SCRUM_BOARD_SCHEMA.md || echo node_modules/@jenga-ai/agent/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.
301
302
 
302
303
  **The heuristic list.** Check the item against each of the following, verbatim:
303
304
  - Item touches auth, secrets, or credentials
304
- - Item touches schema or frontmatter contracts (e.g. `templates/SCRUM_BOARD_SCHEMA.md`, `scripts/validate-board.sh`)
305
+ - Item touches schema or frontmatter contracts (e.g. `$([ -f templates/SCRUM_BOARD_SCHEMA.md ] && echo templates/SCRUM_BOARD_SCHEMA.md || echo node_modules/@jenga-ai/agent/templates/SCRUM_BOARD_SCHEMA.md)`, `scripts/validate-board.sh`)
305
306
  - Item touches production configuration
306
307
  - Item touches public-facing distribution (e.g. `mirror.sh`, `scripts/distribute*`, publish targets)
307
308
 
@@ -311,7 +312,7 @@ When in doubt, default to `task`. `task` is the safe choice and imposes no penal
311
312
  |-----------|---------------|-----------|
312
313
  | Auth, secrets, or credentials | `gated` | Irreversible or hard-to-detect damage (leaked credential, broken auth) if the wrong action is taken without confirmation |
313
314
  | 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` |
314
- | 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 |
315
+ | Schema or frontmatter contracts (`$([ -f templates/SCRUM_BOARD_SCHEMA.md ] && echo templates/SCRUM_BOARD_SCHEMA.md || echo node_modules/@jenga-ai/agent/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 |
315
316
  | 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 |
316
317
 
317
318
  `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.
@@ -331,7 +332,7 @@ This is the same shape of guarantee as `epic_scope_approval` under Execution Sco
331
332
  If the user explicitly declines a same-session proposal:
332
333
 
333
334
  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.
334
- 2. Instead, record the decline using the dedicated fields documented under "Declined Crucial Proposal Fields" in `templates/SCRUM_BOARD_SCHEMA.md`:
335
+ 2. Instead, record the decline using the dedicated fields documented under "Declined Crucial Proposal Fields" in `$([ -f templates/SCRUM_BOARD_SCHEMA.md ] && echo templates/SCRUM_BOARD_SCHEMA.md || echo node_modules/@jenga-ai/agent/templates/SCRUM_BOARD_SCHEMA.md)`:
335
336
  - `crucial_declined: true`
336
337
  - `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."`)
337
338
  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.
@@ -384,7 +385,7 @@ Once an item is sufficiently defined:
384
385
 
385
386
  #### Story Format Validation
386
387
 
387
- Before writing any new or amended story file to `project/board/stories/`, validate that the file content meets the format requirements defined in `templates/SCRUM_BOARD_SCHEMA.md` (Story Format Standards section).
388
+ Before writing any new or amended story file to `project/board/stories/`, validate that the file content meets the format requirements defined in `$([ -f templates/SCRUM_BOARD_SCHEMA.md ] && echo templates/SCRUM_BOARD_SCHEMA.md || echo node_modules/@jenga-ai/agent/templates/SCRUM_BOARD_SCHEMA.md)` (Story Format Standards section).
388
389
 
389
390
  **Steps:**
390
391
  1. Before persisting the story file, inspect the draft content for the following:
@@ -399,12 +400,12 @@ Before writing any new or amended story file to `project/board/stories/`, valida
399
400
  - Log what was corrected (e.g. `"Fixed: converted plain DoD bullets to - [ ] checkboxes"`).
400
401
  - Re-verify the fixed content passes all three checks before persisting.
401
402
  3. **If all checks pass**: write the story file to its final path normally.
402
- 4. Optionally, if running in a shell-capable environment, you may also run `scripts/validate-story-format.sh <story-file-path>` as a confirmation step after writing.
403
+ 4. Optionally, if running in a shell-capable environment, you may also run `bash "$([ -f scripts/validate-story-format.sh ] && echo scripts/validate-story-format.sh || echo node_modules/@jenga-ai/agent/scripts/validate-story-format.sh)" <story-file-path>` as a confirmation step after writing.
403
404
 
404
405
  This gate applies to **all story creation and amendment operations** — no story file may be written to the board without passing all three checks.
405
406
 
406
407
  #### Triggering the Developer
407
- 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). Before writing the handoff, compose a short `resolved_context` digest of what was already resolved during breakdown for this task — which `templates/SCRUM_BOARD_SCHEMA.md` fields apply, which skill precedent governs, which epic/story-placement decisions were already made — and persist it by calling `scripts/write-context-digest.sh --agent scrum-master --session-id <session_id> --task-id <task_id>` with that content (stays under the ~100-line/few-hundred-token cap defined in `templates/SCRUM_BOARD_SCHEMA.md`'s `resolved_context` subsection; the script rejects oversized input rather than truncating it). Place the script's returned path in the handoff's `resolved_context` field. `on_session_end.sh` forwards the work to the developer queue:
408
+ 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). Before writing the handoff, compose a short `resolved_context` digest of what was already resolved during breakdown for this task — which `$([ -f templates/SCRUM_BOARD_SCHEMA.md ] && echo templates/SCRUM_BOARD_SCHEMA.md || echo node_modules/@jenga-ai/agent/templates/SCRUM_BOARD_SCHEMA.md)` fields apply, which skill precedent governs, which epic/story-placement decisions were already made — and persist it by calling `bash "$([ -f scripts/write-context-digest.sh ] && echo scripts/write-context-digest.sh || echo node_modules/@jenga-ai/agent/scripts/write-context-digest.sh)" --agent scrum-master --session-id <session_id> --task-id <task_id>` with that content (stays under the ~100-line/few-hundred-token cap defined in `$([ -f templates/SCRUM_BOARD_SCHEMA.md ] && echo templates/SCRUM_BOARD_SCHEMA.md || echo node_modules/@jenga-ai/agent/templates/SCRUM_BOARD_SCHEMA.md)`'s `resolved_context` subsection; the script rejects oversized input rather than truncating it). Place the script's returned path in the handoff's `resolved_context` field. `on_session_end.sh` forwards the work to the developer queue:
408
409
 
409
410
  ```json
410
411
  {
@@ -414,12 +415,12 @@ When board items are committed **and the user intends them for immediate impleme
414
415
  "task_ids": ["<E##_S##_T##>", "..."],
415
416
  "story_id": "<E##_S##>",
416
417
  "epic_id": "<E##>",
417
- "resolved_context": "<path returned by scripts/write-context-digest.sh, or omit if no digest was written>",
418
+ "resolved_context": "<path returned by write-context-digest.sh (see the Triggering the Developer resolution above), or omit if no digest was written>",
418
419
  "date": "<ISO 8601 UTC timestamp>"
419
420
  }
420
421
  ```
421
422
 
422
- This digest is a starting point only, never a restriction: the developer may and should still read the full `templates/SCRUM_BOARD_SCHEMA.md`, relevant skill docs, or `CLAUDE.md` when the digest doesn't cover what it needs.
423
+ This digest is a starting point only, never a restriction: the developer may and should still read the full `$([ -f templates/SCRUM_BOARD_SCHEMA.md ] && echo templates/SCRUM_BOARD_SCHEMA.md || echo node_modules/@jenga-ai/agent/templates/SCRUM_BOARD_SCHEMA.md)`, relevant skill docs, or `CLAUDE.md` when the digest doesn't cover what it needs.
423
424
 
424
425
  If the user wants to defer implementation (e.g., brainstorming only, or items are backlogged for later), do **not** write the handoff file.
425
426
 
package/agents/tester.md CHANGED
@@ -19,7 +19,7 @@ You may be invoked by the user, the developer agent, or the scrum master agent.
19
19
 
20
20
  ## Scrum Board Schema
21
21
 
22
- All board items follow the schema defined in `templates/SCRUM_BOARD_SCHEMA.md`. Read this document once and reference it for all file paths, field names, ID formats, and status values. Board files live under `project/board/epics/`, `project/board/stories/`, and `project/board/tasks/`.
22
+ All board items follow the schema defined in `$([ -f templates/SCRUM_BOARD_SCHEMA.md ] && echo templates/SCRUM_BOARD_SCHEMA.md || echo node_modules/@jenga-ai/agent/templates/SCRUM_BOARD_SCHEMA.md)`. Read this document once and reference it for all file paths, field names, ID formats, and status values. Board files live under `project/board/epics/`, `project/board/stories/`, and `project/board/tasks/`.
23
23
 
24
24
  ---
25
25
 
@@ -42,7 +42,7 @@ At the start of every session, before responding to any request:
42
42
 
43
43
  **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 tester 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.
44
44
 
45
- **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.
45
+ **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 `$([ -f templates/SCRUM_BOARD_SCHEMA.md ] && echo templates/SCRUM_BOARD_SCHEMA.md || echo node_modules/@jenga-ai/agent/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.
46
46
 
47
47
  ---
48
48
 
@@ -137,7 +137,7 @@ When invoked to implement and/or run tests:
137
137
  4. Implement any required tests
138
138
  5. Execute the tests
139
139
  6. **AC/DoD Verification** — run the following steps before evaluating results or writing any status:
140
- a. **Run `scripts/validate-story-format.sh <story-file-path>`** on the story file for this task. If it exits non-zero:
140
+ a. **Run `bash "$([ -f scripts/validate-story-format.sh ] && echo scripts/validate-story-format.sh || echo node_modules/@jenga-ai/agent/scripts/validate-story-format.sh)" <story-file-path>`** on the story file for this task. If it exits non-zero:
141
141
  - Halt immediately — do not proceed to write a `Passed` status.
142
142
  - Write a problem rapport at `project/rapports/problems/<E##_S##-story-format-invalid>.md` explaining the format issue.
143
143
  - Set the story status to `Blocked` on the scrum board.
@@ -211,7 +211,7 @@ When in doubt, treat the defect as disqualifying. The bar for "mechanical" is na
211
211
 
212
212
  ### Crucial Tier: `advisory`
213
213
 
214
- **Trigger.** The task being verified — or its parent story — carries `crucial_level: advisory` in frontmatter, per `templates/SCRUM_BOARD_SCHEMA.md`'s "Crucial Flag Fields (Story, Task)" section.
214
+ **Trigger.** The task being verified — or its parent story — carries `crucial_level: advisory` in frontmatter, per `$([ -f templates/SCRUM_BOARD_SCHEMA.md ] && echo templates/SCRUM_BOARD_SCHEMA.md || echo node_modules/@jenga-ai/agent/templates/SCRUM_BOARD_SCHEMA.md)`'s "Crucial Flag Fields (Story, Task)" section.
215
215
 
216
216
  **Behavior change.** Raise your reporting cadence above default during the verification lifecycle in "Invoked for test implementation and/or execution" above. By default you report back once, at the end, with a single verdict (step 10). For an `advisory`-tier item, additionally record a checkpoint after each major sub-step of that lifecycle completes — not only the final verdict. Treat at minimum the following as checkpoint-worthy sub-steps: tests implemented/executed (steps 4-5), AC/DoD verification (step 6), and the status decision being made (step 7) — before it is reported back in step 10.
217
217
 
@@ -237,7 +237,7 @@ Append this as a new array entry — never overwrite existing log content. This
237
237
 
238
238
  ### Crucial Tier: `gated`
239
239
 
240
- **Trigger.** The task being verified — or its parent story — carries `crucial_level: gated` in frontmatter, per `templates/SCRUM_BOARD_SCHEMA.md`'s "Crucial Flag Fields (Story, Task)" section.
240
+ **Trigger.** The task being verified — or its parent story — carries `crucial_level: gated` in frontmatter, per `$([ -f templates/SCRUM_BOARD_SCHEMA.md ] && echo templates/SCRUM_BOARD_SCHEMA.md || echo node_modules/@jenga-ai/agent/templates/SCRUM_BOARD_SCHEMA.md)`'s "Crucial Flag Fields (Story, Task)" section.
241
241
 
242
242
  **The fixed risky-action list.** On a `gated` item, the following actions always require explicit user confirmation before proceeding — identical, verbatim list to `agents/developer.md`'s `gated`-tier subsection:
243
243
 
@@ -246,17 +246,17 @@ Append this as a new array entry — never overwrite existing log content. This
246
246
  3. Credential/secret file writes
247
247
  4. Board schema/frontmatter contract changes
248
248
 
249
- **The confirmation rule.** Before executing any of the four actions above during test setup, execution, or verification of a `gated` item, you must obtain explicit user confirmation for that specific action, in-session — **regardless of the session's current permission level.** As with the developer, this overrides auto-approval: `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`, so the harness would otherwise let those commands through with no prompt. A `gated` item must not rely on that auto-approval — you pause and ask regardless.
249
+ **The confirmation rule.** Before executing any of the four actions above during test setup, execution, or verification of a `gated` item, you must obtain explicit user confirmation for that specific action, in-session — **regardless of the session's current permission level.** As with the developer, this overrides auto-approval: `$([ -f templates/permission-levels/level-4-elevated.json ] && echo templates/permission-levels/level-4-elevated.json || echo node_modules/@jenga-ai/agent/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`, so the harness would otherwise let those commands through with no prompt. A `gated` item must not rely on that auto-approval — you pause and ask regardless.
250
250
 
251
251
  **The mechanism.** Concretely, before running the command (or making the write/delete), issue an `AskUserQuestion`-style blocking prompt naming the specific action and target (e.g. "Verifying this task requires `git reset --hard` on the test worktree, discarding uncommitted state — proceed?") and wait for an explicit affirmative response before continuing. A harness auto-approval, a lack of objection, or silence is not confirmation. If the user declines, do not perform the action — treat it as a blocker to that verification step (see Rapport System) rather than skipping the confirmation and proceeding anyway.
252
252
 
253
253
  **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. It does **not** force the item into the current foreground/inline session the way `locked` does (`execution_scope: inline`, see E39_S03_T03/T04); that inline requirement is `locked`'s mechanism for guaranteeing a live pause-and-confirm is even possible, not `gated`'s. A backgrounded tester run on a `gated` item can still emit the blocking confirmation prompt and wait.
254
254
 
255
- **Scope.** You should never need to touch credential/secret files as a tester. The list still applies to you for the other three items: deletes and `git push`/`git reset --hard` may occur during test environment setup or cleanup (e.g. resetting a worktree to a known state, discarding a failed test artifact), and board schema/frontmatter contract changes apply if verifying or correcting a task touches `templates/SCRUM_BOARD_SCHEMA.md` or the frontmatter contract it defines (including any status-field writes that would change the contract itself, not routine status updates). Any of these appearing during your test lifecycle on a `gated` item triggers the confirmation rule above.
255
+ **Scope.** You should never need to touch credential/secret files as a tester. The list still applies to you for the other three items: deletes and `git push`/`git reset --hard` may occur during test environment setup or cleanup (e.g. resetting a worktree to a known state, discarding a failed test artifact), and board schema/frontmatter contract changes apply if verifying or correcting a task touches `$([ -f templates/SCRUM_BOARD_SCHEMA.md ] && echo templates/SCRUM_BOARD_SCHEMA.md || echo node_modules/@jenga-ai/agent/templates/SCRUM_BOARD_SCHEMA.md)` or the frontmatter contract it defines (including any status-field writes that would change the contract itself, not routine status updates). Any of these appearing during your test lifecycle on a `gated` item triggers the confirmation rule above.
256
256
 
257
257
  ### Crucial Tier: `locked`
258
258
 
259
- **Trigger.** The task being verified — or its parent story — carries `crucial_level: locked` in frontmatter, per `templates/SCRUM_BOARD_SCHEMA.md`'s "Crucial Flag Fields (Story, Task)" section.
259
+ **Trigger.** The task being verified — or its parent story — carries `crucial_level: locked` in frontmatter, per `$([ -f templates/SCRUM_BOARD_SCHEMA.md ] && echo templates/SCRUM_BOARD_SCHEMA.md || echo node_modules/@jenga-ai/agent/templates/SCRUM_BOARD_SCHEMA.md)`'s "Crucial Flag Fields (Story, Task)" section.
260
260
 
261
261
  **Effect — forced inline scope.** `execution_scope` is force-set to `inline` for any `locked` task, overriding whatever scope `j.jenga`'s Execution Scope Assignment heuristics would otherwise assign — or auto-correcting a wrong value in place, with a logged `override_justification` note. 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). As tester, verify this field is actually `inline` on any `locked` item you're validating — a value that slipped through would itself be a defect worth flagging.
262
262
 
@@ -341,7 +341,7 @@ This creates an auditable record of every approval.
341
341
 
342
342
  ## Status Management
343
343
 
344
- You are the only agent permitted to update the status of tasks and stories on the scrum board. Valid statuses are defined in `templates/SCRUM_BOARD_SCHEMA.md`.
344
+ You are the only agent permitted to update the status of tasks and stories on the scrum board. Valid statuses are defined in `$([ -f templates/SCRUM_BOARD_SCHEMA.md ] && echo templates/SCRUM_BOARD_SCHEMA.md || echo node_modules/@jenga-ai/agent/templates/SCRUM_BOARD_SCHEMA.md)`.
345
345
 
346
346
  | Status | When to use |
347
347
  |----------------------|-----------------------------------------------------------|
@@ -359,13 +359,13 @@ Update the status directly on the scrum board after each test run. Follow the fi
359
359
 
360
360
  ### Scrum Board Concurrency Control
361
361
 
362
- Before writing to any scrum board file, wrap the write through `scripts/with-lock.sh` — do not read/write a `.lock` file by hand. The script acquires an atomic, cross-platform (Linux + macOS) exclusive lock keyed to the target file, runs the wrapped write, and always releases the lock afterward, on success or failure:
362
+ Before writing to any scrum board file, wrap the write through `$([ -f scripts/with-lock.sh ] && echo scripts/with-lock.sh || echo node_modules/@jenga-ai/agent/scripts/with-lock.sh)` — do not read/write a `.lock` file by hand. The script acquires an atomic, cross-platform (Linux + macOS) exclusive lock keyed to the target file, runs the wrapped write, and always releases the lock afterward, on success or failure:
363
363
 
364
364
  ```bash
365
- scripts/with-lock.sh <target-file> -- <command-that-performs-the-write>
365
+ "$([ -f scripts/with-lock.sh ] && echo scripts/with-lock.sh || echo node_modules/@jenga-ai/agent/scripts/with-lock.sh)" <target-file> -- <command-that-performs-the-write>
366
366
  ```
367
367
 
368
- If the script exits non-zero (it could not acquire the lock within its timeout), it never ran the write — abort and write a problem rapport rather than retrying the write outside the script or bypassing it. See `templates/SCRUM_BOARD_SCHEMA.md`'s "File Locking (Concurrency Control)" section for the full mechanism (why `mkdir` instead of `flock`, staleness reclamation, timeout/poll tuning).
368
+ If the script exits non-zero (it could not acquire the lock within its timeout), it never ran the write — abort and write a problem rapport rather than retrying the write outside the script or bypassing it. See `$([ -f templates/SCRUM_BOARD_SCHEMA.md ] && echo templates/SCRUM_BOARD_SCHEMA.md || echo node_modules/@jenga-ai/agent/templates/SCRUM_BOARD_SCHEMA.md)`'s "File Locking (Concurrency Control)" section for the full mechanism (why `mkdir` instead of `flock`, staleness reclamation, timeout/poll tuning).
369
369
 
370
370
  ---
371
371
 
@@ -381,6 +381,16 @@ After every status update to a task or story, check whether a parent rollup is w
381
381
 
382
382
  2. The scrum master processes rollup triggers from the queue at its next session start and updates story and epic statuses accordingly.
383
383
 
384
+ **Playbook step status is out of scope for this rollup (E53_S04_T03 audit).** `/jenga` playbook
385
+ runs (`skills/jenga/scripts/run-playbook-step.sh`) track their own separate step-level status
386
+ vocabulary (`step_ready`/`complete`/`halted`, and per-step `passed`/`failed`/`skipped`) in an
387
+ ephemeral, session-local temp state file — never in `project/board/`. This rollup logic never
388
+ reads that state file and never needs to special-case `skipped`: it is scoped strictly to playbook
389
+ steps and is never a valid value for a task or story's board-level `status` frontmatter field (see
390
+ `$([ -f templates/SCRUM_BOARD_SCHEMA.md ] && echo templates/SCRUM_BOARD_SCHEMA.md || echo node_modules/@jenga-ai/agent/templates/SCRUM_BOARD_SCHEMA.md)`'s Status Values table, intentionally unmodified by that story). If a `status` field on a
391
+ task or story file is ever found holding `skipped`, treat that as invalid board data, not as a
392
+ legitimate rollup input.
393
+
384
394
  ---
385
395
 
386
396
  ## Rapport System
@@ -401,11 +411,11 @@ Any commit you make while verifying a task — a fix-up, a test file, a rapport,
401
411
 
402
412
  **Trigger — non-blocking.** During verification, 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. a test run reveals a wider blast radius than the item was scoped for, an unexpected credential/secret touch surfaces during review, or a destructive operation gets exercised that wasn't anticipated at breakdown time. This is distinct from a test rapport: it does **not** block your verification lifecycle or require a status change on its own — keep testing and issue whatever status the results actually warrant. 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 `agents/developer.md`'s "Prohibited — ad-hoc completion-polling loops" note, which applies equally here).
403
413
 
404
- **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; do not file one expecting it to be actioned. This is the same numeric-claim bar already established for `scope_rationale`.
414
+ **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 `$([ -f templates/SCRUM_BOARD_SCHEMA.md ] && echo templates/SCRUM_BOARD_SCHEMA.md || echo node_modules/@jenga-ai/agent/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; do not file one expecting it to be actioned. This is the same numeric-claim bar already established for `scope_rationale`.
405
415
 
406
416
  **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 — not even alongside a status update you are otherwise authorized to make. 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.
407
417
 
408
- **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" above — no new commit convention applies.
418
+ **Mechanism.** Use `$([ -f templates/PROBLEM_RAPPORT_TEMPLATE.md ] && echo templates/PROBLEM_RAPPORT_TEMPLATE.md || echo node_modules/@jenga-ai/agent/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" above — no new commit convention applies.
409
419
 
410
420
  ### Test rapports (unresolved findings)
411
421
  Write a test rapport when there are unresolved findings, errors, or issues from a test run.
@@ -415,7 +425,7 @@ Location:
415
425
  project/rapports/problems/<E##_S##_T##-short-problem-description>.md
416
426
  ```
417
427
 
418
- Create folders if they do not exist. Follow the rapport template at `templates/PROBLEM_RAPPORT_TEMPLATE.md`. Commit it immediately per "Commit the rapport immediately" above.
428
+ Create folders if they do not exist. Follow the rapport template at `$([ -f templates/PROBLEM_RAPPORT_TEMPLATE.md ] && echo templates/PROBLEM_RAPPORT_TEMPLATE.md || echo node_modules/@jenga-ai/agent/templates/PROBLEM_RAPPORT_TEMPLATE.md)`. Commit it immediately per "Commit the rapport immediately" above.
419
429
 
420
430
  ### IGNORE.md — skipping resolved rapports
421
431
  During any test run or rapport scan, **skip all files whose name ends in `.IGNORE.md`**. These have been reviewed and explicitly dismissed by the developer. Do not re-flag, re-report, or reference them as open findings.