@jenga-ai/agent 3.1.1 → 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.
- package/agents/developer.md +15 -15
- package/agents/scrum-master.md +17 -17
- package/agents/tester.md +25 -15
- package/lib/skill-allow-list.json +3 -2
- package/package.json +1 -1
- package/scripts/audit-twin-divergence.sh +625 -0
- package/scripts/check-public-playbook-steps.sh +136 -0
- package/skills/j-close-story/SKILL.md +1 -1
- package/skills/j-do/SKILL.md +19 -19
- package/skills/j-doc-sync/SKILL.md +12 -1
- package/skills/j-idea/SKILL.md +1 -1
- package/skills/j-init/SKILL.md +5 -4
- package/skills/j-init/assets/directory_structure.txt +1 -0
- package/skills/j-init/scripts/detect-existing-codebase.sh +2 -2
- package/skills/j-init/scripts/init.sh +13 -2
- package/skills/j-playbook/SKILL.md +81 -0
- package/skills/j-proceed/SKILL.md +1 -1
- package/skills/j-publish/SKILL.md +1 -1
- package/skills/j-publish/adapters/npm-ci.md +29 -0
- package/skills/j-publish/scripts/npm_ci_pipeline.sh +3 -0
- package/skills/j-publish/scripts/npm_pipeline.sh +18 -0
- package/skills/j-publish/scripts/npm_stage_pipeline.sh +81 -41
- package/skills/j-reconcile/SKILL.md +1 -0
- package/skills/j-redo/SKILL.md +1 -1
- package/skills/j-status/SKILL.md +12 -0
- package/skills/j-todo/SKILL.md +2 -2
- package/skills/j-uncharted/SKILL.md +8 -7
- package/skills/j-uncharted/scripts/validate-proposed-items.sh +18 -2
- package/skills/jenga/SKILL.md +55 -16
- package/skills/jenga/playbooks/idea-to-committed.json +20 -0
- package/skills/jenga/playbooks/schema.json +1 -1
- package/skills/jenga/scripts/load-playbooks.sh +855 -27
- package/skills/jenga/scripts/match-playbook.sh +1 -1
- package/skills/jenga/scripts/render-playbook-confirmation.sh +162 -8
- package/skills/jenga/scripts/run-playbook-step.sh +535 -42
- package/skills/jenga-permission-level/SKILL.md +4 -4
- package/templates/KNOWLEDGE_GRAPH_STUB_SCHEMA_TEMPLATE.md +128 -0
- package/templates/playbook-types.json +8 -0
- package/skills/jenga/playbooks/brainstorm-to-mirror.json +0 -22
package/agents/developer.md
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
95
|
-
6. **Write an execution plan** to `project/documentation/plans/<E##_S##_T##>-plan.md` using
|
|
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
|
|
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
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
package/agents/scrum-master.md
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
72
|
-
2. **Review the reason** — check the rapport's Problem Description against the concrete-reason bar defined in
|
|
73
|
-
3. **Accept branch** — if the reason is concrete, apply the escalation to the target item's board file through
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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 (
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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-
|
|
3
|
-
"skill_count":
|
|
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.
|
|
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": {
|