@jenga-ai/agent 3.1.0 → 3.2.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 (44) hide show
  1. package/README.md +3 -3
  2. package/agents/developer.md +15 -15
  3. package/agents/scrum-master.md +17 -17
  4. package/agents/tester.md +25 -15
  5. package/lib/skill-allow-list.json +3 -2
  6. package/package.json +1 -1
  7. package/scripts/audit-twin-divergence.sh +625 -0
  8. package/scripts/build-pages-site.sh +268 -0
  9. package/scripts/check-public-playbook-steps.sh +136 -0
  10. package/skills/j-close-story/SKILL.md +1 -1
  11. package/skills/j-do/SKILL.md +19 -19
  12. package/skills/j-doc-sync/SKILL.md +12 -1
  13. package/skills/j-idea/SKILL.md +1 -1
  14. package/skills/j-init/SKILL.md +5 -4
  15. package/skills/j-init/assets/directory_structure.txt +1 -0
  16. package/skills/j-init/scripts/detect-existing-codebase.sh +2 -2
  17. package/skills/j-init/scripts/init.sh +13 -2
  18. package/skills/j-playbook/SKILL.md +81 -0
  19. package/skills/j-proceed/SKILL.md +1 -1
  20. package/skills/j-publish/SKILL.md +1 -1
  21. package/skills/j-publish/adapters/npm-ci.md +29 -0
  22. package/skills/j-publish/scripts/npm_ci_pipeline.sh +3 -0
  23. package/skills/j-publish/scripts/npm_pipeline.sh +18 -0
  24. package/skills/j-publish/scripts/npm_stage_pipeline.sh +81 -41
  25. package/skills/j-reconcile/SKILL.md +1 -0
  26. package/skills/j-redo/SKILL.md +1 -1
  27. package/skills/j-status/SKILL.md +12 -0
  28. package/skills/j-todo/SKILL.md +2 -2
  29. package/skills/j-uncharted/SKILL.md +8 -7
  30. package/skills/j-uncharted/scripts/elicitation-state.sh +15 -1
  31. package/skills/j-uncharted/scripts/validate-proposed-items.sh +18 -2
  32. package/skills/jenga/SKILL.md +80 -9
  33. package/skills/jenga/playbooks/idea-to-committed.json +20 -0
  34. package/skills/jenga/playbooks/schema.json +42 -0
  35. package/skills/jenga/scripts/detect-nl-intent.sh +179 -0
  36. package/skills/jenga/scripts/load-nl-catalog.js +206 -0
  37. package/skills/jenga/scripts/load-nl-catalog.sh +65 -0
  38. package/skills/jenga/scripts/load-playbooks.sh +1022 -0
  39. package/skills/jenga/scripts/match-playbook.sh +262 -0
  40. package/skills/jenga/scripts/render-playbook-confirmation.sh +517 -0
  41. package/skills/jenga/scripts/run-playbook-step.sh +766 -0
  42. package/skills/jenga-permission-level/SKILL.md +4 -4
  43. package/templates/KNOWLEDGE_GRAPH_STUB_SCHEMA_TEMPLATE.md +128 -0
  44. package/templates/playbook-types.json +8 -0
package/README.md CHANGED
@@ -40,7 +40,7 @@ Jenga AI solves each of these with structure: persistent engineering context mai
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
42
42
 
43
- > 📖 **Full reference:** [project/.wiki/documentation.md](project/.wiki/documentation.md) | [Intro Guide](project/.wiki/intro-guide.md)
43
+ > 📖 **Full reference:** [Docs site](https://samwelmunga.github.io/jenga-npm/reference.html) · **Intro Guide:** [Docs site](https://samwelmunga.github.io/jenga-npm/getting-started.html) — mirrored at [project/.wiki/documentation.md](project/.wiki/documentation.md) / [intro-guide.md](project/.wiki/intro-guide.md)
44
44
 
45
45
  ### "Isn't this just an LLM grading another LLM?"
46
46
 
@@ -215,7 +215,7 @@ Skills live in `.agents/skills/<name>/SKILL.md`. Invoke with `j.<name>` in your
215
215
  | `j.do` | Execute tasks from the scrum board, drives the Developer agent through the full loop |
216
216
  | `j.status` | Print a full scrum board overview — epics, stories, tasks, rapports, queue depth |
217
217
 
218
- > 📖 **Full skill list** (planning, review, committing & maintenance commands): [project/.wiki/documentation.md](project/.wiki/documentation.md#skills)
218
+ > 📖 **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
219
 
220
220
  ---
221
221
 
@@ -232,4 +232,4 @@ Skills live in `.agents/skills/<name>/SKILL.md`. Invoke with `j.<name>` in your
232
232
  - You're doing a quick one-off script or single-session experiment
233
233
  - Your project has no meaningful test surface
234
234
 
235
- 📖 **Full reference:** [project/.wiki/documentation.md](project/.wiki/documentation.md)
235
+ 📖 **Full reference:** [Docs site](https://samwelmunga.github.io/jenga-npm/reference.html) — mirrored at [project/.wiki/documentation.md](project/.wiki/documentation.md)
@@ -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,9 @@ 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
+ 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
229
 
230
230
  ```json
231
231
  {
@@ -238,7 +238,7 @@ When you reach a meaningful milestone within a task where verification is approp
238
238
  "date": "<ISO 8601 UTC timestamp>",
239
239
  "paths": ["<list of commit SHAs for this work>"],
240
240
  "worktree": "<absolute path to the worktree>",
241
- "resolved_context": "<path returned by scripts/write-context-digest.sh, or omit if no digest was written>"
241
+ "resolved_context": "<path returned by write-context-digest.sh (see the Tester Collaboration resolution above), or omit if no digest was written>"
242
242
  }
243
243
  }
244
244
  ```
@@ -260,11 +260,11 @@ Write a rapport when:
260
260
 
261
261
  **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
262
 
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`.
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 `$([ -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
264
 
265
265
  **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
266
 
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.
267
+ **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
268
 
269
269
  ### Commit the rapport immediately
270
270
  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 +284,7 @@ project/rapports/problems/<E##_S##_T##-short-problem-description>.md
284
284
  Create folders if they do not exist.
285
285
 
286
286
  ### Rapport template
287
- See `templates/PROBLEM_RAPPORT_TEMPLATE.md` for the required format. Commit the rapport immediately per "Commit the rapport immediately" above.
287
+ 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
288
 
289
289
  ---
290
290
 
@@ -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,9 +68,9 @@ 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").
@@ -108,7 +108,7 @@ When all stories under an epic are complete:
108
108
  - Update the epic `status` to `Passed` or `Passed with remarks` accordingly
109
109
  - Set `date_completed` on the epic
110
110
 
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.
111
+ 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
112
 
113
113
  ---
114
114
 
@@ -225,7 +225,7 @@ Assign `inline` when **all** of the following are true:
225
225
 
226
226
  ### `light` scope
227
227
 
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.
228
+ `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
229
 
230
230
  Assign `light` when **any** of the following are true:
231
231
  - 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 +236,7 @@ Assign `light` when **any** of the following are true:
236
236
 
237
237
  **Distinguishing `light` from `task`:** assign `light`, not `task`, only when **all** of the following also hold:
238
238
  - 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
239
+ - 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
240
  - 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
241
  - The task has no cross-story dependencies and tester validation is not sensitive to the specific implementation approach chosen
242
242
 
@@ -297,11 +297,11 @@ When in doubt, default to `task`. `task` is the safe choice and imposes no penal
297
297
 
298
298
  **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
299
 
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.
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 `$([ -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
301
 
302
302
  **The heuristic list.** Check the item against each of the following, verbatim:
303
303
  - Item touches auth, secrets, or credentials
304
- - Item touches schema or frontmatter contracts (e.g. `templates/SCRUM_BOARD_SCHEMA.md`, `scripts/validate-board.sh`)
304
+ - 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
305
  - Item touches production configuration
306
306
  - Item touches public-facing distribution (e.g. `mirror.sh`, `scripts/distribute*`, publish targets)
307
307
 
@@ -311,7 +311,7 @@ When in doubt, default to `task`. `task` is the safe choice and imposes no penal
311
311
  |-----------|---------------|-----------|
312
312
  | Auth, secrets, or credentials | `gated` | Irreversible or hard-to-detect damage (leaked credential, broken auth) if the wrong action is taken without confirmation |
313
313
  | 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 |
314
+ | 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
315
  | 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
316
 
317
317
  `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 +331,7 @@ This is the same shape of guarantee as `epic_scope_approval` under Execution Sco
331
331
  If the user explicitly declines a same-session proposal:
332
332
 
333
333
  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`:
334
+ 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
335
  - `crucial_declined: true`
336
336
  - `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
337
  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 +384,7 @@ Once an item is sufficiently defined:
384
384
 
385
385
  #### Story Format Validation
386
386
 
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).
387
+ 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
388
 
389
389
  **Steps:**
390
390
  1. Before persisting the story file, inspect the draft content for the following:
@@ -399,12 +399,12 @@ Before writing any new or amended story file to `project/board/stories/`, valida
399
399
  - Log what was corrected (e.g. `"Fixed: converted plain DoD bullets to - [ ] checkboxes"`).
400
400
  - Re-verify the fixed content passes all three checks before persisting.
401
401
  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.
402
+ 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
403
 
404
404
  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
405
 
406
406
  #### 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:
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 `$([ -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
408
 
409
409
  ```json
410
410
  {
@@ -414,12 +414,12 @@ When board items are committed **and the user intends them for immediate impleme
414
414
  "task_ids": ["<E##_S##_T##>", "..."],
415
415
  "story_id": "<E##_S##>",
416
416
  "epic_id": "<E##>",
417
- "resolved_context": "<path returned by scripts/write-context-digest.sh, or omit if no digest was written>",
417
+ "resolved_context": "<path returned by write-context-digest.sh (see the Triggering the Developer resolution above), or omit if no digest was written>",
418
418
  "date": "<ISO 8601 UTC timestamp>"
419
419
  }
420
420
  ```
421
421
 
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.
422
+ 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
423
 
424
424
  If the user wants to defer implementation (e.g., brainstorming only, or items are backlogged for later), do **not** write the handoff file.
425
425
 
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.
@@ -1,6 +1,6 @@
1
1
  {
2
- "generated_at": "2026-09-08T02:00:42.924Z",
3
- "skill_count": 36,
2
+ "generated_at": "2026-09-10T17:03:15.911Z",
3
+ "skill_count": 37,
4
4
  "skills": [
5
5
  "brainstorm",
6
6
  "btw",
@@ -27,6 +27,7 @@
27
27
  "jenga-permission-level",
28
28
  "lgtm",
29
29
  "pi-plan",
30
+ "playbook",
30
31
  "proceed",
31
32
  "publish",
32
33
  "reconcile",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jenga-ai/agent",
3
- "version": "3.1.0",
3
+ "version": "3.2.0",
4
4
  "description": "An agentic development workflow for Claude Code, Copilot, and Codex — with a persistent Epic/Story/Task board, an isolated git worktree per task, and a separate tester agent that runs your test suite before anything is marked done.",
5
5
  "type": "module",
6
6
  "publishConfig": {