@jenga-ai/agent 3.5.0 → 4.0.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/README.md +85 -78
- package/agents/developer.md +1 -1
- package/agents/scrum-master.md +20 -2
- package/agents/tester.md +3 -3
- package/hooks/on_session_end.sh +5 -5
- package/lib/generate-agent-context.js +2 -2
- package/lib/generate-copilot-hooks.js +1 -1
- package/lib/generate-skill-allow-list.js +79 -8
- package/lib/mirror.js +1 -1
- package/lib/postinstall-manifest.js +1 -1
- package/lib/skill-allow-list.json +2 -2
- package/mcp/help/index.js +8 -17
- package/mcp/help/scan.js +73 -0
- package/package.json +5 -1
- package/project/app/api/lib/resolve-project-root.js +1 -1
- package/project/app/api/parsers/knowledge-graph.js +100 -9
- package/project/app/api/routes/health.js +36 -0
- package/project/app/api/scripts/capture-snapshot.js +9 -6
- package/project/app/package.json +4 -0
- package/project/app/ui/dist/assets/index-BADc5mmH.css +1 -0
- package/project/app/ui/dist/assets/index-C3oiuli_.js +104 -0
- package/project/app/ui/dist/index.html +2 -2
- package/project/app/ui/package.json +4 -0
- package/project/app/ui/scripts/build-snapshot-html.cjs +63 -2
- package/scripts/acquire-concurrency-slot.sh +35 -5
- package/scripts/apply-j-prefix.sh +46 -5
- package/scripts/build-pages-site.sh +1 -1
- package/scripts/check-public-playbook-steps.sh +158 -52
- package/scripts/check-publicignore-match.sh +2 -2
- package/scripts/compute-deploy-reconcile.sh +5 -5
- package/scripts/delete-bare-skill-dirs.sh +329 -0
- package/scripts/generate-legacy-shipped-paths.js +2 -2
- package/scripts/idea_manager.sh +273 -3
- package/scripts/mark-deployed.sh +2 -2
- package/scripts/populate-knowledge-graph.entity-resolution.test.js +254 -0
- package/scripts/populate-knowledge-graph.js +213 -5
- package/scripts/populate-knowledge-graph.staleness.test.js +130 -0
- package/scripts/postinstall.js +1 -1
- package/scripts/release-concurrency-slot.sh +34 -4
- package/scripts/render-ranked-list.sh +270 -0
- package/scripts/repoint-dead-bare-path-prose.py +81 -0
- package/scripts/repoint-skill-refs.sh +539 -0
- package/scripts/rewrite-stale-skill-preambles.py +188 -0
- package/scripts/strip-polyfill-frontmatter.py +166 -0
- package/scripts/todo_manager.sh +16 -1
- package/scripts/validate-typed-object.sh +750 -0
- package/scripts/verify-legacy-seed-reconcile.sh +10 -10
- package/scripts/verify-postinstall-reconcile.sh +7 -7
- package/scripts/write-context-digest.sh +1 -1
- package/skills/j-brainstorm/SKILL.md +3 -4
- package/skills/j-btw/SKILL.md +3 -4
- package/skills/j-clearify/SKILL.md +5 -6
- package/skills/j-close-story/SKILL.md +11 -12
- package/skills/j-close-story/scripts/check-privatized.sh +4 -4
- package/skills/j-close-story/scripts/check-story-closeable.sh +11 -4
- package/skills/j-commit/SKILL.md +3 -4
- package/skills/j-continue/SKILL.md +5 -6
- package/skills/j-deep-dive/SKILL.md +3 -4
- package/skills/j-distribute/CONFIG_SCHEMA.md +82 -5
- package/skills/j-distribute/SKILL.md +3 -4
- package/skills/j-do/SKILL.md +100 -18
- package/skills/j-doc/SKILL.md +3 -4
- package/skills/j-doc-sync/SKILL.md +4 -4
- package/skills/j-dooo/SKILL.md +6 -15
- package/skills/j-error/SKILL.md +3 -4
- package/skills/j-evaluate/SKILL.md +3 -4
- package/skills/j-examplify/SKILL.md +3 -4
- package/skills/j-gitignore/SKILL.md +157 -0
- package/skills/j-gitignore/assets/jenga-paths.txt +50 -0
- package/skills/j-gitignore/scripts/_catalog.sh +105 -0
- package/skills/j-gitignore/scripts/audit-gitignore.sh +194 -0
- package/skills/j-gitignore/scripts/repair-gitignore.sh +226 -0
- package/skills/j-gitignore/scripts/untrack-jenga-files.sh +210 -0
- package/skills/j-help/SKILL.md +3 -4
- package/skills/j-idea/SKILL.md +80 -9
- package/skills/j-idea/assets/idea_template.md +1 -1
- package/skills/j-improve/SKILL.md +4 -5
- package/skills/j-init/SKILL.md +23 -14
- package/skills/j-init/assets/scope-thresholds_template.json +5 -2
- package/skills/j-init/scripts/apply-scaffold-visibility.sh +9 -7
- package/skills/j-init/scripts/init.sh +4 -4
- package/skills/j-jbp/SKILL.md +3 -4
- package/skills/j-lgtm/SKILL.md +3 -4
- package/skills/j-pi-plan/SKILL.md +3 -4
- package/skills/j-playbook/SKILL.md +1 -1
- package/skills/j-proceed/SKILL.md +3 -4
- package/skills/j-publish/SKILL.md +4 -5
- package/skills/j-publish/adapters/npm-ci.md +6 -1
- package/skills/j-publish/adapters/npm.md +1 -1
- package/skills/j-publish/scripts/generate_release_notes.sh +1 -1
- package/skills/j-publish/scripts/npm_stage_inspect.sh +61 -0
- package/skills/j-publish/scripts/run_gates.sh +1 -1
- package/skills/j-reconcile/SKILL.md +40 -7
- package/skills/j-reconcile/assets/report_format.md +11 -0
- package/skills/j-reconcile/scripts/detect-unlinked-code.sh +13 -13
- package/skills/j-reconcile-origin/SKILL.md +3 -4
- package/skills/j-redo/SKILL.md +4 -5
- package/skills/j-skillify/SKILL.md +3 -4
- package/skills/j-spinoff/SKILL.md +4 -5
- package/skills/j-status/SKILL.md +18 -4
- package/skills/j-todo/SKILL.md +44 -5
- package/skills/j-todo/scripts/argument-is-not-ranked-list.sh +92 -0
- package/skills/j-todo/scripts/argument-is-ranked-list.sh +78 -0
- package/skills/j-uncharted/SKILL.md +252 -13
- package/skills/j-uncharted/scripts/detect-dependencies.sh +80 -22
- package/skills/j-uncharted/scripts/detect-tests.sh +1 -1
- package/skills/j-uncharted/scripts/diff-since-baseline.sh +600 -0
- package/skills/j-uncharted/scripts/elicitation-state.sh +1 -1
- package/skills/j-uncharted/scripts/find-scan-baseline.sh +545 -0
- package/skills/j-uncharted/scripts/run-engine.sh +36 -2
- package/skills/j-uncharted/scripts/validate-proposed-items.sh +1 -1
- package/skills/j-uncharted/scripts/write-scan-record.sh +361 -0
- package/skills/j-wtf/SKILL.md +4 -5
- package/skills/jenga/SKILL.md +106 -11
- package/skills/jenga/playbooks/board-hygiene.json +32 -0
- package/skills/jenga/playbooks/schema.json +73 -6
- package/skills/jenga/playbooks/understand-then-commit.json +19 -0
- package/skills/jenga/scripts/load-nl-catalog.js +5 -2
- package/skills/jenga/scripts/load-nl-catalog.sh +1 -1
- package/skills/jenga/scripts/load-playbooks.sh +290 -5
- package/skills/jenga/scripts/match-playbook.sh +4 -4
- package/skills/jenga/scripts/run-playbook-step.sh +267 -1
- package/templates/SCRUM_BOARD_SCHEMA.md +14 -1
- package/templates/SKILL_TEMPLATE.md +12 -0
- package/templates/permission-levels/level-1-locked.json +1 -1
- package/templates/permission-levels/level-2-guarded.json +1 -1
- package/templates/permission-levels/level-3-standard.json +1 -1
- package/templates/permission-levels/level-4-elevated.json +2 -2
- package/templates/permission-levels/level-5-unrestricted.json +2 -2
- package/templates/playbook-types.json +40 -6
- package/project/app/ui/dist/assets/index-7fj-vllY.js +0 -104
- package/project/app/ui/dist/assets/index-CdK3Qrep.css +0 -1
- package/scripts/audit-twin-divergence.sh +0 -625
- package/scripts/generate-j-alias.sh +0 -333
- package/skills/j-dev-done/SKILL.md +0 -53
- package/skills/j-dev-done/scripts/classify-commit-outcome.sh +0 -114
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# jenga.config.json — Schema Reference
|
|
2
2
|
|
|
3
|
-
This document is the canonical reference for the `jenga.config.json` file written into **consuming projects** during framework distribution. The file is created and maintained by `distribute-changes.sh`, with the `project_files_visibility` field written by `skills/init/scripts/apply-project-visibility.sh` during `/init`; it should not be edited by hand.
|
|
3
|
+
This document is the canonical reference for the `jenga.config.json` file written into **consuming projects** during framework distribution. The file is created and maintained by `distribute-changes.sh`, with the `project_files_visibility` field written by `skills/j-init/scripts/apply-project-visibility.sh` during `/init` and the `scaffold_visibility` field written by `skills/j-init/scripts/apply-scaffold-visibility.sh`, also during `/init`; it should not be edited by hand.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -28,7 +28,8 @@ This document is the canonical reference for the `jenga.config.json` file writte
|
|
|
28
28
|
"updated_at": "2026-08-11",
|
|
29
29
|
"last_distributed": "2026-08-11T10:00:00Z",
|
|
30
30
|
"source": "private",
|
|
31
|
-
"project_files_visibility": "visible"
|
|
31
|
+
"project_files_visibility": "visible",
|
|
32
|
+
"scaffold_visibility": "visible"
|
|
32
33
|
}
|
|
33
34
|
```
|
|
34
35
|
|
|
@@ -44,7 +45,8 @@ This document is the canonical reference for the `jenga.config.json` file writte
|
|
|
44
45
|
| `updated_at` | string (ISO 8601 date) | yes | — | Date of the last successful distribution, in `YYYY-MM-DD` format. Does **not** include a time component. |
|
|
45
46
|
| `last_distributed` | string (ISO 8601 datetime) | yes | — | Full UTC timestamp of the last successful distribution, in `YYYY-MM-DDTHH:MM:SSZ` format. Provides more precision than `updated_at` and is useful for audit and ordering purposes. |
|
|
46
47
|
| `source` | string | yes | `"private"` | Distribution channel. Always `"private"` for projects that receive updates via the filesystem distribution mechanism. Distinguishes these projects from any future npm-installed consumers. Do not change this value manually. |
|
|
47
|
-
| `project_files_visibility` | string (enum) | no | `"visible"` | How Jenga AI's own working files appear in the consuming project. Exactly one of `visible` or `ignored` — no other value is accepted. Written by `/init`, not by distribution. See [Project files visibility](#project-files-visibility) below. |
|
|
48
|
+
| `project_files_visibility` | string (enum) | no | `"visible"` | How Jenga AI's own working files (`project/`) appear in the consuming project. Exactly one of `visible` or `ignored` — no other value is accepted. Written by `/init`, not by distribution. See [Project files visibility](#project-files-visibility) below. |
|
|
49
|
+
| `scaffold_visibility` | string (enum) | no | `"visible"` | How the distributed `.claude`/`.agents` framework scaffold appears in the consuming project. Exactly one of `visible` or `ignored` — no other value is accepted. A **distinct** flag from `project_files_visibility`, written by `/init`, not by distribution. See [Scaffold visibility](#scaffold-visibility) below. |
|
|
48
50
|
|
|
49
51
|
---
|
|
50
52
|
|
|
@@ -96,12 +98,87 @@ The default is **`visible`**, used whenever `/init` runs non-interactively or th
|
|
|
96
98
|
|
|
97
99
|
### Who writes it
|
|
98
100
|
|
|
99
|
-
The field is written during `/init` by `skills/init/scripts/apply-project-visibility.sh`, which also performs the corresponding on-disk change. The script merges the field into any existing `jenga.config.json` rather than overwriting the file, since `/init` normally runs before the first `/distribute` has created it.
|
|
101
|
+
The field is written during `/init` by `skills/j-init/scripts/apply-project-visibility.sh`, which also performs the corresponding on-disk change. The script merges the field into any existing `jenga.config.json` rather than overwriting the file, since `/init` normally runs before the first `/distribute` has created it.
|
|
100
102
|
|
|
101
103
|
Changing the value after the initial `/init` is not currently supported — there is no toggle or migration path. Re-running the applier with a different mode is not a supported upgrade route.
|
|
102
104
|
|
|
103
105
|
---
|
|
104
106
|
|
|
107
|
+
## Scaffold visibility
|
|
108
|
+
|
|
109
|
+
`scaffold_visibility` controls how the **distributed framework scaffold** — `.claude/` and
|
|
110
|
+
`.agents/`, the mirrored skill and agent definitions that make Jenga AI's own commands
|
|
111
|
+
(`/init`, `/do`, `/commit`, etc.) available inside a consuming project — appears in that
|
|
112
|
+
project's git history.
|
|
113
|
+
|
|
114
|
+
### Why this is a separate flag from `project_files_visibility`
|
|
115
|
+
|
|
116
|
+
This field was filed as new, adjacent scope under `E31_S07`, from a problem rapport
|
|
117
|
+
(`project/rapports/problems/E31_S05-consumer-scaffold-committed-despite-ignored-visibility.md`)
|
|
118
|
+
reporting that a consumer who selected `project_files_visibility: ignored` still had 342
|
|
119
|
+
files under `.claude/`/`.agents/` swept into their `/init` commit — `project_files_visibility`
|
|
120
|
+
never covered that tree in the first place.
|
|
121
|
+
|
|
122
|
+
`E31_S05`'s own Background section explicitly scoped `project_files_visibility` to the
|
|
123
|
+
`project/` working tree — the scrum board, `todo.md`, `queue/`, `rapports/`, and `logs/` —
|
|
124
|
+
and explicitly said this was **not** about "the distributed skill/agent definitions
|
|
125
|
+
themselves." Two ways to close the resulting gap were considered when `E31_S07_T01` made
|
|
126
|
+
this decision:
|
|
127
|
+
|
|
128
|
+
- **(a) Extend** `project_files_visibility`'s `ignored` mode to also gitignore `.claude/`
|
|
129
|
+
and `.agents/`. Rejected: this erases the documented boundary from `E31_S05` — a single
|
|
130
|
+
flag would then silently govern two trees with different lifecycles (`project/`
|
|
131
|
+
accumulates as the user works; `.claude/`/`.agents/` are overwritten wholesale by every
|
|
132
|
+
`/distribute` run or npm upgrade), and a consumer reading `ignored` for one tree would
|
|
133
|
+
have no way to tell it also silently applies to the other.
|
|
134
|
+
- **(b) Introduce a distinct, separately-named flag** (`scaffold_visibility`), chosen. Costs
|
|
135
|
+
one extra config field and one extra `/init` prompt, but keeps each flag's semantics
|
|
136
|
+
unambiguous and independently selectable — a consumer can, for example, keep `project/`
|
|
137
|
+
visible (to track their own board in git) while still excluding the vendored
|
|
138
|
+
`.claude/`/`.agents/` scaffold, or vice versa.
|
|
139
|
+
|
|
140
|
+
`scaffold_visibility` reuses `project_files_visibility`'s exact two-value enum and
|
|
141
|
+
semantics (same mental model, different target directories) rather than inventing new
|
|
142
|
+
vocabulary.
|
|
143
|
+
|
|
144
|
+
### Allowed values
|
|
145
|
+
|
|
146
|
+
Exactly two values are accepted. Any other value is rejected with a non-zero exit code.
|
|
147
|
+
|
|
148
|
+
| Value | On-disk effect |
|
|
149
|
+
|---|---|
|
|
150
|
+
| `visible` | `.claude/`/`.agents/` are tracked and committed normally — unchanged from `/init`'s behavior before this field existed. |
|
|
151
|
+
| `ignored` | `.claude/` and `.agents/` are appended to the project's `.gitignore` (whichever of the two exist, or will later be created by `/distribute` or an npm install), so they exist on disk but are never committed. |
|
|
152
|
+
|
|
153
|
+
### Default
|
|
154
|
+
|
|
155
|
+
The default is **`visible`**, used whenever `/init` runs non-interactively or the user is
|
|
156
|
+
not prompted — this is an additive capability, not a change to the previously-unconditional
|
|
157
|
+
commit behavior. `visible` reproduces exactly what every `/init` run did before this field
|
|
158
|
+
existed: the scaffold is committed regardless of `project_files_visibility`'s value. An
|
|
159
|
+
absent field (a `jenga.config.json` written before this field existed) is also read as
|
|
160
|
+
`visible`.
|
|
161
|
+
|
|
162
|
+
### Who writes it
|
|
163
|
+
|
|
164
|
+
The field is written during `/init` by `skills/j-init/scripts/apply-scaffold-visibility.sh`,
|
|
165
|
+
which also performs the corresponding `.gitignore` change. Like
|
|
166
|
+
`apply-project-visibility.sh`, it merges the field into any existing `jenga.config.json`
|
|
167
|
+
rather than overwriting the file, and gitignores `.claude/`/`.agents/` unconditionally
|
|
168
|
+
(not only when they already exist on disk), so a scaffold created by a later
|
|
169
|
+
`/distribute` run or npm install is covered too — not only one already present at `/init`
|
|
170
|
+
time.
|
|
171
|
+
|
|
172
|
+
`init.sh` applies both `project_files_visibility` and `scaffold_visibility` before its
|
|
173
|
+
final `git add -A && git commit` step, so any `.gitignore` entries from either flag are
|
|
174
|
+
already in place — and therefore respected by `git add -A` — before the first commit is
|
|
175
|
+
made.
|
|
176
|
+
|
|
177
|
+
Changing the value after the initial `/init` is not currently supported, matching
|
|
178
|
+
`project_files_visibility`'s own limitation above.
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
105
182
|
## First distribution
|
|
106
183
|
|
|
107
184
|
When `distribute-changes.sh` runs against a project for the first time and no `jenga.config.json` exists in the project root, the script creates the file from scratch. All six fields are populated using:
|
|
@@ -115,7 +192,7 @@ When `distribute-changes.sh` runs against a project for the first time and no `j
|
|
|
115
192
|
|
|
116
193
|
The directory referenced by `target_dir` is created if it does not already exist.
|
|
117
194
|
|
|
118
|
-
> **Known gap:** `distribute-changes.sh` rebuilds `jenga.config.json` from scratch on every run and emits only the six fields above, so a `project_files_visibility` value written by `/init` is dropped by the next `/distribute`. Making the rebuild preserve fields it does not own is tracked as follow-up work; until then, treat the on-disk layout (not the config field) as the source of truth for which mode a project is in.
|
|
195
|
+
> **Known gap:** `distribute-changes.sh` rebuilds `jenga.config.json` from scratch on every run and emits only the six fields above, so a `project_files_visibility` or `scaffold_visibility` value written by `/init` is dropped by the next `/distribute`. Making the rebuild preserve fields it does not own is tracked as follow-up work; until then, treat the on-disk layout (not the config field) as the source of truth for which mode a project is in.
|
|
119
196
|
|
|
120
197
|
---
|
|
121
198
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: j.distribute
|
|
3
|
-
description:
|
|
3
|
+
description: Distribute Jenga AI framework files from this private monorepo to one or more consuming projects via the local filesystem. Manages release type selection, version bumping, dry-run preview, per-target file copy, and a post-distribution git commit.
|
|
4
4
|
keywords:
|
|
5
5
|
- distribute
|
|
6
6
|
- private distribution
|
|
@@ -9,7 +9,6 @@ keywords:
|
|
|
9
9
|
- version bump
|
|
10
10
|
- distribute to projects
|
|
11
11
|
- j-distribute
|
|
12
|
-
- polyfill
|
|
13
12
|
examples:
|
|
14
13
|
- "/distribute"
|
|
15
14
|
- "/distribute /path/to/consuming-project"
|
|
@@ -19,9 +18,9 @@ examples:
|
|
|
19
18
|
|
|
20
19
|
# Distribute
|
|
21
20
|
|
|
22
|
-
|
|
21
|
+
`skills/j-distribute/` is the **canonical, hand-edited** directory for this skill, per CLAUDE.md's "The Canonical Naming Contract" (the `E50` reopening of 2026-09-09, which promoted `skills/j-distribute/` from generated twin to sole canonical form). The `j-` prefix is there for collision safety — a real directory under a distinct name, so a host tool shipping its own same-named built-in command cannot shadow it (Claude Code's native skill resolution is a literal-string, directory-name-based match; see `docs/skill-authoring.md`'s "Invocation Convention").
|
|
23
22
|
|
|
24
|
-
|
|
23
|
+
> ⚠️ **`scripts/generate-j-alias.sh` was retired by `E50_S14` and no longer exists — there is nothing to run.** This file was previously generated from a bare `skills/distribute/SKILL.md` source; `E50_S15` deleted that directory. This file is now the sole canonical, hand-edited source for this skill — edit it directly.
|
|
25
24
|
|
|
26
25
|
Copies Jenga AI framework files from this monorepo to all active consuming projects registered in `distribute.config.json`. Manages the full version lifecycle: release type selection, `package.json` version bump, dry-run preview, per-target file copy, and a final git commit of the version bump.
|
|
27
26
|
|
package/skills/j-do/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: j.do
|
|
3
|
-
description:
|
|
3
|
+
description: Execute tasks from the scrum board. Reads from project/todo.md, resolves each entry to its full scrum board context, and drives the developer agent through implementation with the correct sender object and communication contract. Loops until all selected tasks are done or the user exits.
|
|
4
4
|
keywords:
|
|
5
5
|
- do
|
|
6
6
|
- execute
|
|
@@ -8,24 +8,31 @@ keywords:
|
|
|
8
8
|
- work on
|
|
9
9
|
- build
|
|
10
10
|
- j-do
|
|
11
|
-
- polyfill
|
|
12
11
|
examples:
|
|
13
12
|
- "implement the login feature"
|
|
14
13
|
- "work on the API endpoint"
|
|
15
14
|
- "j-do"
|
|
16
|
-
metadata:
|
|
15
|
+
metadata:
|
|
17
16
|
prefered_agent: developer
|
|
18
17
|
---
|
|
19
18
|
|
|
20
19
|
# Do — Execute Scrum Board Tasks
|
|
21
20
|
|
|
22
|
-
|
|
21
|
+
`skills/j-do/` is the **canonical, hand-edited** directory for this skill, per CLAUDE.md's "The
|
|
22
|
+
Canonical Naming Contract" (the `E50` reopening of 2026-09-09, which promoted `skills/j-<name>/`
|
|
23
|
+
from generated twin to sole canonical form). The `j-` prefix is there for collision safety — a real
|
|
24
|
+
directory under a distinct name, so a host tool shipping its own same-named built-in command cannot
|
|
25
|
+
shadow it (Claude Code's native skill resolution is a literal-string, directory-name-based match; see
|
|
26
|
+
`docs/skill-authoring.md`'s "Invocation Convention").
|
|
23
27
|
|
|
24
|
-
|
|
28
|
+
> ⚠️ **`scripts/generate-j-alias.sh` was retired by `E50_S14` and no longer exists — there is
|
|
29
|
+
> nothing to run.** This file was previously generated from a bare `skills/do/SKILL.md` source;
|
|
30
|
+
> `E50_S15` deleted that directory. This file is now the sole canonical, hand-edited source for
|
|
31
|
+
> this skill — edit it directly.
|
|
25
32
|
|
|
26
33
|
## `--trivial` Flag
|
|
27
34
|
|
|
28
|
-
**Syntax:** `/do <id> --trivial` — a dispatch-time override, distinct from `/todo --trivial` (a creation-time flag documented in `skills/todo/SKILL.md`). Where `/todo --trivial` writes a brand-new task straight to `execution_scope: inline`, `/do <id> --trivial` overrides an **already-existing** task's `execution_scope` — whatever it currently is, including absent (legacy tasks with no execution-scope fields at all) — to `inline` at the moment it's dispatched. See `### 4.1.5. \`--trivial\` Dispatch-Time Override` below for the full mechanics.
|
|
35
|
+
**Syntax:** `/do <id> --trivial` — a dispatch-time override, distinct from `/todo --trivial` (a creation-time flag documented in `skills/j-todo/SKILL.md`). Where `/todo --trivial` writes a brand-new task straight to `execution_scope: inline`, `/do <id> --trivial` overrides an **already-existing** task's `execution_scope` — whatever it currently is, including absent (legacy tasks with no execution-scope fields at all) — to `inline` at the moment it's dispatched. See `### 4.1.5. \`--trivial\` Dispatch-Time Override` below for the full mechanics.
|
|
29
36
|
|
|
30
37
|
**No softer fallback tier — hard fallback to the full pipeline instead.** Unlike `light` scope (which sits between `inline` and `task`), `--trivial` always forces `inline` directly, with no intermediate tier to fall back to first. To compensate, a `--trivial`-forced run that fails `scripts/smoke-harness.sh` or shows detected scope creep mid-run automatically re-routes to the full `task` pipeline (worktree + developer + tester) via the same `#### Fallback to Full Task-Scope Pipeline` procedure the `light`-tier fallback uses — see `### 4.2`'s failure-handling branches and the shared Fallback subsection under `### 4.3`.
|
|
31
38
|
|
|
@@ -145,7 +152,11 @@ After acquiring the epic lock and before writing the bundle manifest, scan all o
|
|
|
145
152
|
|
|
146
153
|
2. **Invoke rollback anchor**: write a bundle manifest at `project/queue/bundle-<E##_S##>.json` before the first task executes. See "### Bundle Manifest and Rollback Anchor" below for the full procedure.
|
|
147
154
|
|
|
148
|
-
3. **
|
|
155
|
+
3. **Acquire a developer concurrency slot, then spawn one developer subagent** in one shared worktree named `bundle-<E##_S##>`. This is the only developer subagent for the entire story bundle — do not spawn additional subagents per task, and correspondingly this bundle acquires **exactly one** developer slot for its entire lifetime, never one per task inside it.
|
|
156
|
+
|
|
157
|
+
a. **Acquire.** Follow `### 4.4. Developer Concurrency Slot Enforcement` below, with `<id>` = this bundle's story id (`<E##_S##>`).
|
|
158
|
+
b. **On a full cap (`capacity_blocked` outcome)**: do not spawn the shared subagent. Undo the bundle setup already performed above so no orphaned state survives this aborted attempt: delete the bundle manifest (`rm -f project/queue/bundle-<E##_S##>.json`) and release the epic lock (`rm -f project/queue/epic-lock-<E##>.json`) — the same two cleanup actions the failure path below performs, since from the epic lock's perspective an aborted-before-it-started bundle is indistinguishable from a failed one. None of the bundle's tasks have had their status touched yet (the per-task `status: In Progress` write in step 4a below hasn't run), so there is nothing to revert to `Pending` — they are still whatever they were before this bundle attempt (normally `Pending` already). Stop here; `/jenga` Phase 4's normal Pending-rescan picks the story back up on a later wave once a slot frees up.
|
|
159
|
+
c. **On success**: proceed to spawn the shared subagent as before. Release this slot exactly once, when the entire bundle concludes — step 6 (success) or step 4d (failure) below — never per individual task inside the bundle.
|
|
149
160
|
|
|
150
161
|
4. **Execute tasks sequentially** in `tasks:` list order, within the same shared developer subagent context:
|
|
151
162
|
|
|
@@ -222,14 +233,14 @@ After acquiring the epic lock and before writing the bundle manifest, scan all o
|
|
|
222
233
|
2. Create the lock file: write the current ISO 8601 timestamp into `project/board/tasks/<task_id>_*.md.lock`.
|
|
223
234
|
3. Update the task frontmatter field `status: Failed`.
|
|
224
235
|
4. Delete the lock file immediately after the write completes.
|
|
225
|
-
Then invoke the rollback anchor cleanup procedure (see "### Bundle Manifest and Rollback Anchor" — failure path). After the rollback anchor completes, **release the epic lock**: run `rm -f project/queue/epic-lock-<E##>.json`. Mark the bundle as failed and **halt** — do not execute any remaining tasks in the sequence.
|
|
236
|
+
Then invoke the rollback anchor cleanup procedure (see "### Bundle Manifest and Rollback Anchor" — failure path). After the rollback anchor completes, **release the developer concurrency slot** acquired in step 3 above: `"$([ -f scripts/release-concurrency-slot.sh ] && echo scripts/release-concurrency-slot.sh || echo node_modules/@jenga-ai/agent/scripts/release-concurrency-slot.sh)" developer <E##_S##> <orchestrator_session_id>` (per `### 4.4` step 2 below). Then **release the epic lock**: run `rm -f project/queue/epic-lock-<E##>.json`. Mark the bundle as failed and **halt** — do not execute any remaining tasks in the sequence.
|
|
226
237
|
|
|
227
238
|
5. **Post-bundle verification** (runs only if all tasks completed without failure):
|
|
228
239
|
- Inspect each task in the bundle for `needs_docs: true` in its frontmatter.
|
|
229
240
|
- **If any task has `needs_docs: true`**: invoke the tester agent once for the full story. Pass the story ID, the list of all task IDs in the bundle, and the shared worktree path. The tester is responsible for updating individual task statuses.
|
|
230
241
|
- **If all tasks have `needs_docs: false`**: the developer agent self-verifies — reviews each task's implementation against its acceptance criteria without invoking the tester. After self-verification passes, write `status: Passed` and `date_completed: <YYYY-MM-DD>` (today's date) to each task file using the file-locking protocol (steps c.1–c.4 above). No tester invocation occurs.
|
|
231
242
|
|
|
232
|
-
6. **Cleanup**: on successful bundle completion, invoke the rollback anchor success path (see "### Bundle Manifest and Rollback Anchor" — success path) to delete the bundle manifest. Then **release the epic lock**: run `rm -f project/queue/epic-lock-<E##>.json`.
|
|
243
|
+
6. **Cleanup**: on successful bundle completion, invoke the rollback anchor success path (see "### Bundle Manifest and Rollback Anchor" — success path) to delete the bundle manifest. Then **release the developer concurrency slot** acquired in step 3 above: `"$([ -f scripts/release-concurrency-slot.sh ] && echo scripts/release-concurrency-slot.sh || echo node_modules/@jenga-ai/agent/scripts/release-concurrency-slot.sh)" developer <E##_S##> <orchestrator_session_id>` (per `### 4.4` step 2 below). Then **release the epic lock**: run `rm -f project/queue/epic-lock-<E##>.json`.
|
|
233
244
|
|
|
234
245
|
### Bundle Manifest and Rollback Anchor
|
|
235
246
|
|
|
@@ -349,7 +360,7 @@ After override validation (step 4.1) and before branching on `execution_scope` i
|
|
|
349
360
|
```
|
|
350
361
|
override_justification: "/do --trivial dispatch-time override on <date>: execution_scope forced from '<prior_tier>' to 'inline' by human operator."
|
|
351
362
|
```
|
|
352
|
-
- Also set (or append to) `scope_rationale`, mirroring the phrasing convention `skills/todo/scripts/add_trivial_task.sh` already uses for the creation-time flag, so both audit fields agree on the prior tier:
|
|
363
|
+
- Also set (or append to) `scope_rationale`, mirroring the phrasing convention `skills/j-todo/scripts/add_trivial_task.sh` already uses for the creation-time flag, so both audit fields agree on the prior tier:
|
|
353
364
|
```
|
|
354
365
|
scope_rationale: "forced inline via /do --trivial (dispatch-time override); prior execution_scope was '<prior_tier>'"
|
|
355
366
|
```
|
|
@@ -428,9 +439,9 @@ After resolving the task context (step 4), passing override validation (step 4.1
|
|
|
428
439
|
|
|
429
440
|
`light` sits between `inline` and `task`: unlike `inline`, it spawns a real developer subagent (so it can handle small branching logic that inline's main-session execution isn't suited for); unlike `task`, it does not create a dedicated worktree and does not invoke the tester as a separate step.
|
|
430
441
|
|
|
431
|
-
1. **
|
|
442
|
+
1. **Acquire a developer concurrency slot, then spawn a developer subagent.** Acquire first, per `### 4.4. Developer Concurrency Slot Enforcement` below (`<id>` = this task's id). On a full cap (`capacity_blocked` outcome), do not spawn anything — `### 4.4` already reverts this task's status to `Pending`, logs the `capacity_blocked` event, and tracks the consecutive-block count; stop here and let `/jenga` Phase 4 retry this task on a later wave once a slot frees up. On a successful acquire, spawn the subagent (Agent tool, `subagent_type: "developer"`) with the same sender object and context payload as step 5 would use, but with an explicit instruction added to the dispatch prompt: **do not create a worktree** — implement directly against the current checkout (the session's existing working tree), not an isolated `.claude/worktrees/<slug>` copy. This is the one concrete difference from the step-5 `task` path: everything else about how the subagent implements the task (reading the task file, following acceptance criteria, following repo conventions) is unchanged.
|
|
432
443
|
|
|
433
|
-
2. **After the developer subagent reports implementation complete**, run the smoke test harness using the same invocation convention as `### 4.2. Inline Execution Path`:
|
|
444
|
+
2. **After the developer subagent reports implementation complete**, first **release the developer concurrency slot** acquired in step 1: `"$([ -f scripts/release-concurrency-slot.sh ] && echo scripts/release-concurrency-slot.sh || echo node_modules/@jenga-ai/agent/scripts/release-concurrency-slot.sh)" developer <task_id> <orchestrator_session_id>` (per `### 4.4` step 2) — this subagent's session has ended, so the slot is released now regardless of what it reports, before the smoke test result is even known. Then run the smoke test harness using the same invocation convention as `### 4.2. Inline Execution Path`:
|
|
434
445
|
- Run `bash "$([ -f scripts/smoke-harness.sh ] && echo scripts/smoke-harness.sh || echo node_modules/@jenga-ai/agent/scripts/smoke-harness.sh)" <changed_file>...`, passing the paths the subagent changed. With no arguments the harness infers them from `git diff --name-only HEAD`. It exits `0` on pass and `1` on failure.
|
|
435
446
|
- If neither `scripts/smoke-harness.sh` nor `node_modules/@jenga-ai/agent/scripts/smoke-harness.sh` exists, log a warning and treat the result as a pass:
|
|
436
447
|
```
|
|
@@ -453,9 +464,10 @@ This is a self-contained, reusable procedure with two current callers — `### 4
|
|
|
453
464
|
|
|
454
465
|
1. **Do not mark the task `Failed`.** A smoke-harness failure (or detected scope creep) under a reduced-overhead scope means the scope was too small for the task, not that the task itself is unworkable — the correct response is to retry under full isolation, not to reject the work.
|
|
455
466
|
2. **Create a worktree** for the task, named `<E##_S##_T##-short-slug>` per standard Worktree Management conventions, if one does not already exist for this task. (A task dispatched under `light` scope, or forced `inline` via `--trivial`, never had one — both premises skip worktree creation — so this step always creates a fresh worktree in that case.)
|
|
456
|
-
3. **
|
|
457
|
-
4. **
|
|
458
|
-
5. **
|
|
467
|
+
3. **Acquire a developer concurrency slot** (per `### 4.4. Developer Concurrency Slot Enforcement` below, `<id>` = this task's id). This fallback spawn is a distinct developer-subagent lifecycle from whatever `light`/`trivial` attempt preceded it — that attempt's own slot, if any, was already acquired and released around it (`### 4.3` step 1/2, or no slot at all for a `--trivial`-forced inline attempt, which never spawns a subagent) — so this step always acquires its own fresh slot. On a full cap (`capacity_blocked` outcome), do not spawn anything here either: apply `### 4.4`'s Pending-revert/log/consecutive-block handling for this task id and stop the fallback. The task remains exactly as the reduced-overhead attempt left it (any commits already made by that attempt stay in the worktree/branch just created in step 2), and `/jenga` Phase 4 retries it on a later wave once a slot frees up.
|
|
468
|
+
4. **Spawn a developer subagent** in that worktree and have it pick up from the current state of the code (the changes already made by the reduced-overhead attempt are still present in the working tree / already committed, if any commit occurred — the subagent continues from there rather than starting over).
|
|
469
|
+
5. **Invoke the tester agent** per the normal `### 5. Invoke the developer agent` flow's contract — full sender object, commit SHAs, worktree path. The tester is responsible for the terminal status write, exactly as in the standard `task`-scope pipeline. Once this developer subagent's session ends — tester-verified, failed, or errored — **release the slot** acquired in step 3: `"$([ -f scripts/release-concurrency-slot.sh ] && echo scripts/release-concurrency-slot.sh || echo node_modules/@jenga-ai/agent/scripts/release-concurrency-slot.sh)" developer <task_id> <orchestrator_session_id>` (per `### 4.4` step 2).
|
|
470
|
+
6. **Emit a clear, non-fatal fallback notice** to the user/orchestrator, using the message matching the caller's origin:
|
|
459
471
|
- origin `light`:
|
|
460
472
|
```
|
|
461
473
|
LIGHT SCOPE FALLBACK [<task_id>]: smoke test failed; re-routing to full task-scope pipeline (worktree + developer + tester).
|
|
@@ -464,12 +476,80 @@ This is a self-contained, reusable procedure with two current callers — `### 4
|
|
|
464
476
|
```
|
|
465
477
|
TRIVIAL OVERRIDE FALLBACK [<task_id>]: smoke test failed (or scope creep detected); re-routing to full task-scope pipeline (worktree + developer + tester).
|
|
466
478
|
```
|
|
467
|
-
|
|
479
|
+
7. Resume normal `task`-scope processing (steps 6–8 below) once the tester returns a verdict.
|
|
480
|
+
|
|
481
|
+
### 4.4. Developer Concurrency Slot Enforcement (Shared Procedure)
|
|
482
|
+
|
|
483
|
+
This is a self-contained, reusable procedure with four current callers — the Story-Bundle Execution Mode's developer-subagent spawn (`### 1.5` step 3, one acquire for the whole bundle, never one per task inside it), the Light Execution Path's developer-subagent spawn (`### 4.3` step 1/2), the standard task-scope developer invocation (`### 5` below), and the `Fallback to Full Task-Scope Pipeline`'s developer-subagent spawn (step 3/5 above). Every one of these is a genuine "spawn a developer subagent" moment — `inline` scope (`### 4.2`, including a `--trivial`-forced run that hasn't yet fallen back) is the only path that never spawns a subagent and therefore never calls this procedure at all.
|
|
484
|
+
|
|
485
|
+
**`<id>`** is the task id (`E##_S##_T##`) for a single-task dispatch (the `### 5`, `### 4.3`, and Fallback call sites), or the story id (`E##_S##`) for the bundle path — one acquire call covers the whole bundle, never one per task inside it.
|
|
486
|
+
|
|
487
|
+
**`<orchestrator_session_id>`** is the `session_id` value already being populated into this dispatch's sender object per `assets/sender_template.json` (`### 5`'s "Sender object" step) — the same session identity already used for this invocation's sender object, handoff files, and event log entries. Reuse that exact value; do not fabricate a second, separate identifier for this call. This is what keeps every developer spawn issued by the same orchestrating run sharing one counter file (`project/queue/concurrency-slots-<orchestrator_session_id>.json`), regardless of which of the four call sites above triggered it.
|
|
488
|
+
|
|
489
|
+
**Where that value comes from — two cases (`E32_S16_T02`).** `### 5`'s "Sender object" step says to populate `session_id`, but does not by itself say where that value originates. It is always exactly one of the following two cases, decided once at the top of this `/do` invocation, before any of the four call sites above ever runs:
|
|
490
|
+
|
|
491
|
+
- **(a) Standalone invocation.** `/do` was invoked directly — by a human, or by another skill that did not pass along a session identity of its own (e.g. a bare `/do`, or `/do <id>` typed by a user). In this case `/do` generates its own `session_id`, exactly as it always has — this is no behavior change, only making the previously-implicit behavior explicit. Follow this repo's existing session-id string convention for an orchestrator-minted id (see `skills/jenga/SKILL.md` Phase 0.9's `jenga-<UTC ISO 8601 basic timestamp>` format for the same convention applied to an orchestrating skill) — a short prefix naming the invoking context plus a UTC timestamp, with no `/` or `..` characters, since the value is used verbatim in filenames such as this section's own counter file.
|
|
492
|
+
- **(b) Caller-supplied invocation.** `/do` was invoked by another orchestrator that already has its own session identity and passes it along as part of the dispatch context — for example `/jenga` Phase 4 threading its own `orchestrator_session_id` (generated once in `skills/jenga/SKILL.md` Phase 0.9) into each sub-agent's sender object, or Phase 3.5 step 7b's bundle `/do <E##_S##>` call doing the same. In this case `/do` **MUST reuse that caller-supplied value verbatim** as this invocation's `session_id` — it must never generate a new one. This is what lets every `/do` sub-agent a single `/jenga` run (or any other orchestrator) dispatches share one `project/queue/concurrency-slots-<id>.json` counter file, which is the entire point of `<orchestrator_session_id>` in this section.
|
|
493
|
+
|
|
494
|
+
Detecting which case applies is mechanical: if the dispatch context already contains a `session_id` populated by the calling skill/agent, this is case (b) and that value is used as-is; if it does not, this is case (a) and `/do` mints its own. Once decided, that single value is what gets copied into `assets/sender_template.json`'s `session_id` field in `### 5` below and referenced everywhere in this document as `<orchestrator_session_id>`.
|
|
495
|
+
|
|
496
|
+
1. **Acquire.** Before spawning the developer subagent (or the bundle's shared developer subagent), run:
|
|
497
|
+
```
|
|
498
|
+
"$([ -f scripts/acquire-concurrency-slot.sh ] && echo scripts/acquire-concurrency-slot.sh || echo node_modules/@jenga-ai/agent/scripts/acquire-concurrency-slot.sh)" developer <id> <orchestrator_session_id>
|
|
499
|
+
```
|
|
500
|
+
Per that script's own exit-code contract:
|
|
501
|
+
- **Exit `0`** — slot acquired. Proceed to spawn the subagent exactly as documented at the calling site, and carry out step 2 below (release) once that subagent's session ends.
|
|
502
|
+
- **Exit `3`** — the `developer` role is at/over its configured cap (`max_concurrent_developers`) after stale-reclaim; the counter file was **not** mutated. This, and only this exit code, is a **`capacity_blocked` outcome**. Do NOT spawn anything. Handle it as follows:
|
|
503
|
+
a. Revert the item's board status to `Pending`, using the same file-locking protocol already used elsewhere in this skill for status writes.
|
|
504
|
+
b. Read the current holders snapshot for the `developer` role from `project/queue/concurrency-slots-<orchestrator_session_id>.json` (`.developer.holders`). If the file does not exist yet, treat the snapshot as `{}`. Note this snapshot may still include not-yet-reclaimed stale (TTL-expired) entries, since a blocked acquire call never mutates the counter file — it is a best-effort audit snapshot, not a guaranteed-fresh one.
|
|
505
|
+
c. Read/update the per-item consecutive-block counter per step 3 below, and use the resulting count as this event's `wave` value.
|
|
506
|
+
d. Append one entry to `project/logs/events.json` (read the file's existing entries first to match its established array-of-objects shape):
|
|
507
|
+
```json
|
|
508
|
+
{
|
|
509
|
+
"event": "capacity_blocked",
|
|
510
|
+
"agent": "orchestrator",
|
|
511
|
+
"session_id": "<orchestrator_session_id>",
|
|
512
|
+
"role": "developer",
|
|
513
|
+
"item_id": "<id>",
|
|
514
|
+
"wave": <consecutive-block count from step 3, after incrementing>,
|
|
515
|
+
"holders": <the holders snapshot from (b)>,
|
|
516
|
+
"date": "<ISO 8601 UTC timestamp>"
|
|
517
|
+
}
|
|
518
|
+
```
|
|
519
|
+
e. Do not proceed to step 2 (release) — nothing was acquired. Report this outcome to the user/orchestrator as "deferred: developer capacity is currently full for this session", never as "failed".
|
|
520
|
+
- **Exit `1`, `2`, or `5`** — a usage error, a `with-lock.sh` timeout, or an environment error (missing `jq`, missing/invalid config). This is **not** a capacity block — the cap itself was never actually evaluated. Treat it as an ordinary `/do` error: do not spawn the subagent, do not write a `capacity_blocked` event, do not touch the consecutive-block counter, and fall through to the pre-existing failure→skip→`Pending` handling (`skills/jenga/SKILL.md`'s Edge Cases: "`/do` failure (background agent) — treated as a skip; mark the item's status back to `Pending`..."). Report the script's stderr so the underlying script/lock/environment problem is visible, rather than silently reporting it as a capacity issue.
|
|
521
|
+
|
|
522
|
+
2. **Release — on every subagent exit path.** Once the spawned developer subagent's session ends — whether it reports success, failure, or an error/exception — run:
|
|
523
|
+
```
|
|
524
|
+
"$([ -f scripts/release-concurrency-slot.sh ] && echo scripts/release-concurrency-slot.sh || echo node_modules/@jenga-ai/agent/scripts/release-concurrency-slot.sh)" developer <id> <orchestrator_session_id>
|
|
525
|
+
```
|
|
526
|
+
This call is unconditional and must be reached from every branch that follows a successful acquire in step 1: the success path, the ordinary `/do` failure→skip→`Pending` path, and any other error/exception branch that aborts the calling section early. `release-concurrency-slot.sh` is idempotent by its own contract (a no-op success if the holder entry is already absent), so calling it defensively — even in a code path where it is uncertain whether the acquire actually landed — is always safe and never an error.
|
|
527
|
+
|
|
528
|
+
3. **Per-item consecutive-block counter (across waves).** Maintain a small session-scoped state file at `project/queue/capacity-block-state-<orchestrator_session_id>.json`, shaped as a flat map from item id to its current consecutive-block count:
|
|
529
|
+
```json
|
|
530
|
+
{ "<id>": <int> }
|
|
531
|
+
```
|
|
532
|
+
This file lives alongside `project/queue/concurrency-slots-<orchestrator_session_id>.json` under the identical session-scoped naming convention — it belongs to exactly the one orchestrating session named in its filename and must never be read or written for a different `orchestrator_session_id`, for the same reason `scripts/acquire-concurrency-slot.sh`'s own header comment gives for its own counter file. Because `/do` is very often re-dispatched as a brand-new background subagent on every wave (per `/jenga` Phase 4's Pending-rescan loop), this state cannot rely on in-session memory alone — persisting it here is what lets the "3 consecutive blocked waves" count survive across those separate dispatches. Because multiple different items can each be blocked in the same wave, all writing to this one shared file, every read-modify-write against it must go through `scripts/with-lock.sh` (mirroring `project/queue/concurrency-slots-<session_id>.json`'s own locking discipline) rather than the bare tmp-file-rename pattern used for the (single-writer-at-a-time) bundle manifest elsewhere in this skill.
|
|
533
|
+
|
|
534
|
+
- **On a `capacity_blocked` outcome (step 1's exit-3 branch):** read this item's current count (default `0` if the key is absent), increment it by `1`, and write the incremented value back. Use this same incremented value as the `wave` field in the `capacity_blocked` event (step 1d above).
|
|
535
|
+
- **Escalation.** If the incremented count has reached `3`: append one line to `project/queue/scrum_triggers.jsonl`, matching the existing trigger shape documented in `templates/SCRUM_BOARD_SCHEMA.md`'s Queue Trigger Types section (the same `{"type": ..., ..., "sender": {...}, "message": "..."}` shape already used by `story_rollup` entries):
|
|
536
|
+
```json
|
|
537
|
+
{"type": "capacity_starvation", "item_id": "<id>", "wave": 3, "role": "developer", "date": "<ISO 8601 UTC timestamp>", "sender": {"agent": "orchestrator", "session_id": "<orchestrator_session_id>", "task_id": "<id>", "date": "<ISO 8601 UTC timestamp>"}, "message": "Item <id> has been capacity_blocked for 3 consecutive waves against the developer role cap (max_concurrent_developers)."}
|
|
538
|
+
```
|
|
539
|
+
Then **reset this item's count back to `0`** in the state file. This is a passive audit/escalation write only — it does not itself retry anything; retry keeps working purely via `/jenga` Phase 4's existing Pending-rescan-per-wave loop, unrelated to this trigger. `capacity_starvation` handling (surfacing a plain warning, no automatic remediation) is documented separately in `agents/scrum-master.md`'s Drain Scrum Triggers Queue procedure (`E32_S15_T06`) — out of scope for this file.
|
|
540
|
+
- **On a successful acquire (step 1's exit-0 branch):** if this item already has an entry in the state file, reset its count back to `0` (a successful dispatch clears the streak — the counter tracks *consecutive* blocked waves, not a cumulative total). If it has no entry, there is nothing to reset.
|
|
541
|
+
|
|
542
|
+
**`capacity_blocked` vs. the existing failure→skip→`Pending` path.** A `capacity_blocked` outcome and `/do`'s pre-existing failure handling (documented in `skills/jenga/SKILL.md`'s Edge Cases as "`/do` failure (background agent) — treated as a skip; mark the item's status back to `Pending` and continue the loop with remaining candidates.") arrive at the **same board-visible result** — the item ends up `Pending` again, picked back up by `/jenga` Phase 4's next wave rescan — but for a **different, never-conflated reason**:
|
|
543
|
+
- **Ordinary failure:** the developer subagent (or bundle subagent) was actually spawned and ran; either the implementation itself failed or an unexpected error occurred mid-run. No `capacity_blocked` event is written, and the consecutive-block counter above is untouched. Retry works purely because the item is `Pending` again — no concurrency accounting is involved.
|
|
544
|
+
- **`capacity_blocked`:** no subagent was ever spawned at all — the item never got a chance to run because the session's `developer` role was already at its configured cap (`max_concurrent_developers` in `project/configs/scope-thresholds.json`) at dispatch time. This is a passive audit write only: it does not itself drive retry, and it must never be reported to the user as "the task failed" — it is reported as "the task was deferred, developer capacity was full for this session."
|
|
468
545
|
|
|
469
546
|
### 5. Invoke the developer agent
|
|
470
|
-
Pass the following to the developer agent:
|
|
471
547
|
|
|
472
|
-
**
|
|
548
|
+
**Acquire a developer concurrency slot first.** Follow `### 4.4. Developer Concurrency Slot Enforcement` above with `<id>` = this task's id, before doing anything else in this section. On a full cap (`capacity_blocked` outcome), do not invoke the developer agent at all — `### 4.4` already reverts the task's status to `Pending`, logs the `capacity_blocked` event, and tracks the consecutive-block count for this task; simply stop here and let `/jenga` Phase 4 retry this task on a later wave once a slot frees up. This is a distinct outcome from the ordinary `/do` failure→skip→`Pending` path below — see `### 4.4`'s "capacity_blocked vs. the existing failure→skip→Pending path" note.
|
|
549
|
+
|
|
550
|
+
On a successful acquire, pass the following to the developer agent:
|
|
551
|
+
|
|
552
|
+
**Sender object**: Copy `assets/sender_template.json` and populate all known fields — `session_id` per `### 4.4`'s standalone-vs-caller-supplied cases immediately above (generate one if this is a standalone invocation, case (a); reuse the caller-supplied value verbatim if one was already passed into the dispatch context, case (b) — never regenerate in that case), plus `task_id`, `story_id`, `epic_id`, and the current ISO 8601 UTC date.
|
|
473
553
|
|
|
474
554
|
**Context payload** (plain text alongside the sender object):
|
|
475
555
|
- Full task/story file content (title, description, acceptance criteria)
|
|
@@ -482,6 +562,8 @@ The developer agent will:
|
|
|
482
562
|
- Implement, commit at milestones, and invoke the tester agent
|
|
483
563
|
- Return when the tester has verified the work
|
|
484
564
|
|
|
565
|
+
**Release the slot on every exit path.** Once the developer agent's session ends — whether it returns having implemented and been verified by the tester, fails outright, or errors — release the slot immediately: `"$([ -f scripts/release-concurrency-slot.sh ] && echo scripts/release-concurrency-slot.sh || echo node_modules/@jenga-ai/agent/scripts/release-concurrency-slot.sh)" developer <task_id> <orchestrator_session_id>` (per `### 4.4` step 2). This applies uniformly to the success path above, `/jenga`'s existing "`/do` failure (background agent)" skip-to-`Pending` path (`skills/jenga/SKILL.md`'s Edge Cases), and any other error/exception that aborts this section early.
|
|
566
|
+
|
|
485
567
|
### 5.1. Intent-vs-Diff Check (needs_docs: false only)
|
|
486
568
|
|
|
487
569
|
After the developer agent returns (or after inline execution completes), run the following check if the task has `needs_docs: false` in its frontmatter. If `needs_docs: true`, skip this check entirely — the full documentation lifecycle handles divergence detection for those tasks.
|
package/skills/j-doc/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: j.doc
|
|
3
|
-
description:
|
|
3
|
+
description: Generate or update a documentation file by resolving a target path to a clear documentation objective before writing.
|
|
4
4
|
metadata:
|
|
5
5
|
prefered_agent: developer
|
|
6
6
|
keywords:
|
|
@@ -10,7 +10,6 @@ keywords:
|
|
|
10
10
|
- generate docs
|
|
11
11
|
- update docs
|
|
12
12
|
- j-doc
|
|
13
|
-
- polyfill
|
|
14
13
|
examples:
|
|
15
14
|
- "/doc"
|
|
16
15
|
- "/doc docs/API.md"
|
|
@@ -22,9 +21,9 @@ examples:
|
|
|
22
21
|
|
|
23
22
|
# Doc — Documentation Synthesis and Regeneration
|
|
24
23
|
|
|
25
|
-
|
|
24
|
+
`skills/j-doc/` is the **canonical, hand-edited** directory for this skill, per CLAUDE.md's "The Canonical Naming Contract" (the `E50` reopening of 2026-09-09, which promoted `skills/j-doc/` from generated twin to sole canonical form). The `j-` prefix is there for collision safety — a real directory under a distinct name, so a host tool shipping its own same-named built-in command cannot shadow it (Claude Code's native skill resolution is a literal-string, directory-name-based match; see `docs/skill-authoring.md`'s "Invocation Convention").
|
|
26
25
|
|
|
27
|
-
|
|
26
|
+
> ⚠️ **`scripts/generate-j-alias.sh` was retired by `E50_S14` and no longer exists — there is nothing to run.** This file was previously generated from a bare `skills/doc/SKILL.md` source; `E50_S15` deleted that directory. This file is now the sole canonical, hand-edited source for this skill — edit it directly.
|
|
28
27
|
|
|
29
28
|
## Input Format
|
|
30
29
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: j.doc-sync
|
|
3
|
-
description:
|
|
3
|
+
description: Compare the current state of a project with its documentation and update documentation to reflect changes. Accepts `update:`, `source:`, `exclude:`, and `minify:` arguments to control scope. Use when documentation may be out of date with implementation, or when the user asks to sync, refresh, update, or shrink docs.
|
|
4
|
+
output_types: file_list
|
|
4
5
|
keywords:
|
|
5
6
|
- doc-sync
|
|
6
7
|
- documentation
|
|
7
8
|
- update docs
|
|
8
9
|
- sync docs
|
|
9
10
|
- j-doc-sync
|
|
10
|
-
- polyfill
|
|
11
11
|
examples:
|
|
12
12
|
- "update the documentation"
|
|
13
13
|
- "sync docs with current state"
|
|
@@ -16,9 +16,9 @@ examples:
|
|
|
16
16
|
|
|
17
17
|
# Doc-Sync — Keep Documentation in Sync with the Codebase
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
`skills/j-doc-sync/` is the **canonical, hand-edited** directory for this skill, per CLAUDE.md's "The Canonical Naming Contract" (the `E50` reopening of 2026-09-09, which promoted `skills/j-doc-sync/` from generated twin to sole canonical form). The `j-` prefix is there for collision safety — a real directory under a distinct name, so a host tool shipping its own same-named built-in command cannot shadow it (Claude Code's native skill resolution is a literal-string, directory-name-based match; see `docs/skill-authoring.md`'s "Invocation Convention").
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
> ⚠️ **`scripts/generate-j-alias.sh` was retired by `E50_S14` and no longer exists — there is nothing to run.** This file was previously generated from a bare `skills/doc-sync/SKILL.md` source; `E50_S15` deleted that directory. This file is now the sole canonical, hand-edited source for this skill — edit it directly.
|
|
22
22
|
|
|
23
23
|
## What this skill does
|
|
24
24
|
|
package/skills/j-dooo/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: j.dooo
|
|
3
|
-
description:
|
|
3
|
+
description: Parallel execution orchestrator. Calls /do to start implementations via sub-agents, then loops back to the board to identify and offer parallelisable tasks until the user selects "Done".
|
|
4
4
|
keywords:
|
|
5
5
|
- dooo
|
|
6
6
|
- parallel
|
|
@@ -8,7 +8,6 @@ keywords:
|
|
|
8
8
|
- multiple tasks
|
|
9
9
|
- orchestrate
|
|
10
10
|
- j-dooo
|
|
11
|
-
- polyfill
|
|
12
11
|
examples:
|
|
13
12
|
- "run all pending tasks in parallel"
|
|
14
13
|
- "execute multiple tasks at once"
|
|
@@ -19,32 +18,24 @@ metadata:
|
|
|
19
18
|
|
|
20
19
|
# Dooo — Parallel Execution Orchestrator
|
|
21
20
|
|
|
22
|
-
|
|
21
|
+
`skills/j-dooo/` is the **canonical, hand-edited** directory for this skill, per CLAUDE.md's "The Canonical Naming Contract" (the `E50` reopening of 2026-09-09, which promoted `skills/j-dooo/` from generated twin to sole canonical form). The `j-` prefix is there for collision safety — a real directory under a distinct name, so a host tool shipping its own same-named built-in command cannot shadow it (Claude Code's native skill resolution is a literal-string, directory-name-based match; see `docs/skill-authoring.md`'s "Invocation Convention").
|
|
23
22
|
|
|
24
|
-
|
|
23
|
+
> ⚠️ **`scripts/generate-j-alias.sh` was retired by `E50_S14` and no longer exists — there is nothing to run.** This file was previously generated from a bare `skills/dooo/SKILL.md` source; `E50_S15` deleted that directory. This file is now the sole canonical, hand-edited source for this skill — edit it directly.
|
|
25
24
|
|
|
26
25
|
## Instructions
|
|
27
26
|
|
|
28
27
|
### 1. Invoke `/do`
|
|
29
28
|
Call the `/do` skill to let the user select and start an implementation. `/do` will launch a background sub-agent to handle the implementation. Once the sub-agent is launched, `/do` returns control here.
|
|
30
29
|
|
|
31
|
-
After `/do` hands back control, mark the story/task that was just started as **
|
|
30
|
+
After `/do` hands back control, mark the story/task that was just started as **In Progress** in its board file (update the `status:` field in the YAML front-matter).
|
|
32
31
|
|
|
33
32
|
### 2. Return to the board — identify parallelisable tasks
|
|
34
33
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
1. **Stories** — read all files from `project/board/stories/`.
|
|
38
|
-
2. **Tasks derived from stories** — read all files from `project/board/tasks/`. A task is considered in-scope if its parent story (`story_id` in the task's front-matter) is listed in `project/todo.md`, even if the task itself is not directly listed there.
|
|
39
|
-
|
|
40
|
-
A story or task is **eligible** to be presented as a parallel candidate if ALL of the following are true:
|
|
41
|
-
- Its status is `Pending` (not `Running`, `In Progress`, `Passed`, etc.)
|
|
42
|
-
- It has no unresolved dependencies (all blocking stories/tasks are at least `Running` or `Passed`)
|
|
43
|
-
- It is directly listed in `project/todo.md`, **OR** its parent story is listed in `project/todo.md`
|
|
34
|
+
Run `scripts/render-ranked-list.sh` from the project root. It scans `project/board/stories/` and `project/board/tasks/` against `project/todo.md` and prints the eligible items as a ranked, 1-indexed `<id> — <title>` list (stories first, then tasks) — this is the same eligibility scan and rendering `/dooo` has always used (status `Pending`, no unresolved dependencies, directly listed in `project/todo.md` or — for tasks — parent story listed), now implemented once in a shared script rather than described here as inline prose (`E63_S01_T01`; see `scripts/render-ranked-list.sh`'s own header for the full rule and its env-var overrides). A sibling command, `/todo --ranked-list`, calls the same script for a non-interactive view of this same list.
|
|
44
35
|
|
|
45
36
|
### 3. Present choices to the user
|
|
46
37
|
|
|
47
|
-
|
|
38
|
+
Relay the script's output as the numbered list (use `ask_user` with `choices`). **Always append "Done" as the last option.**
|
|
48
39
|
|
|
49
40
|
Example:
|
|
50
41
|
```
|
package/skills/j-error/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: j.error
|
|
3
|
-
description:
|
|
3
|
+
description: Guided troubleshooting flow that gathers context about an error — where it occurs, what was attempted, what went wrong, and what was expected.
|
|
4
4
|
keywords:
|
|
5
5
|
- error
|
|
6
6
|
- bug
|
|
@@ -9,7 +9,6 @@ keywords:
|
|
|
9
9
|
- debug
|
|
10
10
|
- broken
|
|
11
11
|
- j-error
|
|
12
|
-
- polyfill
|
|
13
12
|
examples:
|
|
14
13
|
- "I'm getting an error"
|
|
15
14
|
- "help me fix this bug"
|
|
@@ -20,9 +19,9 @@ metadata:
|
|
|
20
19
|
|
|
21
20
|
# Error — Guided Troubleshooting
|
|
22
21
|
|
|
23
|
-
|
|
22
|
+
`skills/j-error/` is the **canonical, hand-edited** directory for this skill, per CLAUDE.md's "The Canonical Naming Contract" (the `E50` reopening of 2026-09-09, which promoted `skills/j-error/` from generated twin to sole canonical form). The `j-` prefix is there for collision safety — a real directory under a distinct name, so a host tool shipping its own same-named built-in command cannot shadow it (Claude Code's native skill resolution is a literal-string, directory-name-based match; see `docs/skill-authoring.md`'s "Invocation Convention").
|
|
24
23
|
|
|
25
|
-
|
|
24
|
+
> ⚠️ **`scripts/generate-j-alias.sh` was retired by `E50_S14` and no longer exists — there is nothing to run.** This file was previously generated from a bare `skills/error/SKILL.md` source; `E50_S15` deleted that directory. This file is now the sole canonical, hand-edited source for this skill — edit it directly.
|
|
26
25
|
|
|
27
26
|
## Instructions
|
|
28
27
|
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: j.evaluate
|
|
3
|
-
description:
|
|
3
|
+
description: Analyzes example files against a target goal and produces a structured evaluation rapport.
|
|
4
4
|
keywords:
|
|
5
5
|
- j-evaluate
|
|
6
|
-
- polyfill
|
|
7
6
|
---
|
|
8
7
|
|
|
9
8
|
# Evaluate
|
|
10
9
|
|
|
11
|
-
|
|
10
|
+
`skills/j-evaluate/` is the **canonical, hand-edited** directory for this skill, per CLAUDE.md's "The Canonical Naming Contract" (the `E50` reopening of 2026-09-09, which promoted `skills/j-evaluate/` from generated twin to sole canonical form). The `j-` prefix is there for collision safety — a real directory under a distinct name, so a host tool shipping its own same-named built-in command cannot shadow it (Claude Code's native skill resolution is a literal-string, directory-name-based match; see `docs/skill-authoring.md`'s "Invocation Convention").
|
|
12
11
|
|
|
13
|
-
|
|
12
|
+
> ⚠️ **`scripts/generate-j-alias.sh` was retired by `E50_S14` and no longer exists — there is nothing to run.** This file was previously generated from a bare `skills/evaluate/SKILL.md` source; `E50_S15` deleted that directory. This file is now the sole canonical, hand-edited source for this skill — edit it directly.
|
|
14
13
|
|
|
15
14
|
## Input
|
|
16
15
|
|