@jenga-ai/agent 3.1.0 → 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/lib/skill-allow-list.json +1 -1
- package/package.json +1 -1
- package/scripts/build-pages-site.sh +268 -0
- package/skills/j-uncharted/scripts/elicitation-state.sh +15 -1
- package/skills/jenga/SKILL.md +39 -7
- package/skills/jenga/playbooks/brainstorm-to-mirror.json +22 -0
- package/skills/jenga/playbooks/schema.json +42 -0
- package/skills/jenga/scripts/detect-nl-intent.sh +179 -0
- package/skills/jenga/scripts/load-nl-catalog.js +206 -0
- package/skills/jenga/scripts/load-nl-catalog.sh +65 -0
- package/skills/jenga/scripts/load-playbooks.sh +194 -0
- package/skills/jenga/scripts/match-playbook.sh +262 -0
- package/skills/jenga/scripts/render-playbook-confirmation.sh +363 -0
- package/skills/jenga/scripts/run-playbook-step.sh +273 -0
package/README.md
CHANGED
|
@@ -40,7 +40,7 @@ Jenga AI solves each of these with structure: persistent engineering context mai
|
|
|
40
40
|
- **Isolated git worktrees per task** — the Developer never works directly on your main branch
|
|
41
41
|
- **Works with any AI coding agent or AI-native IDE** — Claude Code, GitHub Copilot, and Codex CLI are all supported today
|
|
42
42
|
|
|
43
|
-
> 📖 **Full reference:** [project/.wiki/documentation.md](project/.wiki/documentation.md)
|
|
43
|
+
> 📖 **Full reference:** [Docs site](https://samwelmunga.github.io/jenga-npm/reference.html) · **Intro Guide:** [Docs site](https://samwelmunga.github.io/jenga-npm/getting-started.html) — mirrored at [project/.wiki/documentation.md](project/.wiki/documentation.md) / [intro-guide.md](project/.wiki/intro-guide.md)
|
|
44
44
|
|
|
45
45
|
### "Isn't this just an LLM grading another LLM?"
|
|
46
46
|
|
|
@@ -215,7 +215,7 @@ Skills live in `.agents/skills/<name>/SKILL.md`. Invoke with `j.<name>` in your
|
|
|
215
215
|
| `j.do` | Execute tasks from the scrum board, drives the Developer agent through the full loop |
|
|
216
216
|
| `j.status` | Print a full scrum board overview — epics, stories, tasks, rapports, queue depth |
|
|
217
217
|
|
|
218
|
-
> 📖 **Full skill list** (planning, review, committing & maintenance commands): [project/.wiki/documentation.md](project/.wiki/documentation.md#skills)
|
|
218
|
+
> 📖 **Full skill list** (planning, review, committing & maintenance commands): [Docs site](https://samwelmunga.github.io/jenga-npm/skills.html) — mirrored at [project/.wiki/documentation.md#skills](project/.wiki/documentation.md#skills)
|
|
219
219
|
|
|
220
220
|
---
|
|
221
221
|
|
|
@@ -232,4 +232,4 @@ Skills live in `.agents/skills/<name>/SKILL.md`. Invoke with `j.<name>` in your
|
|
|
232
232
|
- You're doing a quick one-off script or single-session experiment
|
|
233
233
|
- Your project has no meaningful test surface
|
|
234
234
|
|
|
235
|
-
📖 **Full reference:** [project/.wiki/documentation.md](project/.wiki/documentation.md)
|
|
235
|
+
📖 **Full reference:** [Docs site](https://samwelmunga.github.io/jenga-npm/reference.html) — mirrored at [project/.wiki/documentation.md](project/.wiki/documentation.md)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jenga-ai/agent",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.1",
|
|
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": {
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# scripts/build-pages-site.sh
|
|
3
|
+
#
|
|
4
|
+
# Deterministically (re)generates the wiki-derived pages of the GitHub Pages
|
|
5
|
+
# documentation site (docs/*.md) from the existing wiki mirror under
|
|
6
|
+
# project/.wiki/. This is the sync mechanism behind E41_S13_T01's
|
|
7
|
+
# source-of-truth decision ("restructure from the wiki, keep both in sync"):
|
|
8
|
+
# project/.wiki/ stays the canonical, doc-sync-maintained content; this
|
|
9
|
+
# script is the deterministic transform from that content into the
|
|
10
|
+
# multi-page, navigable Pages site.
|
|
11
|
+
#
|
|
12
|
+
# WHEN TO RE-RUN: after `j.doc-sync` (or any manual edit) updates
|
|
13
|
+
# project/.wiki/documentation.md, project/.wiki/intro-guide.md, or
|
|
14
|
+
# project/.wiki/concepts/*.md, re-run this script to refresh the Pages site
|
|
15
|
+
# so it doesn't silently drift from the wiki the way README.md and the wiki
|
|
16
|
+
# itself have drifted from each other before (see skills/doc-sync/SKILL.md
|
|
17
|
+
# for the doc-sync side of this convention).
|
|
18
|
+
#
|
|
19
|
+
# WHAT THIS SCRIPT DOES NOT TOUCH:
|
|
20
|
+
# - docs/_config.yml, docs/index.md — hand-authored site structure/config,
|
|
21
|
+
# not derived from wiki content. Edit these directly if the page set or
|
|
22
|
+
# nav changes.
|
|
23
|
+
# - docs/README.md — maintainer-facing decision record, not a rendered
|
|
24
|
+
# Jekyll page and not wiki-derived content.
|
|
25
|
+
#
|
|
26
|
+
# WHAT THIS SCRIPT REGENERATES (always overwritten, never hand-edit these):
|
|
27
|
+
# - docs/getting-started.md <- project/.wiki/intro-guide.md
|
|
28
|
+
# - docs/concepts.md <- project/.wiki/concepts/*.md (concatenated)
|
|
29
|
+
# - docs/skills.md <- project/.wiki/documentation.md "## Skills"
|
|
30
|
+
# - docs/agents.md <- project/.wiki/documentation.md "## Agents"
|
|
31
|
+
# - docs/hooks.md <- project/.wiki/documentation.md "## Hooks"
|
|
32
|
+
# - docs/mcp-tools.md <- project/.wiki/documentation.md "## MCP Tools"
|
|
33
|
+
# - docs/reference.md <- project/.wiki/documentation.md
|
|
34
|
+
# "## Directory Structure" +
|
|
35
|
+
# "## Agent Communication Contract"
|
|
36
|
+
# (plus a short hand-authored index blurb
|
|
37
|
+
# linking to skills/agents/hooks/mcp-tools)
|
|
38
|
+
#
|
|
39
|
+
# KNOWN LIMITATION: this is a structural transform, not a fact-checker. It
|
|
40
|
+
# ports project/.wiki/documentation.md's content as-is, including whatever
|
|
41
|
+
# is currently stale in that file (e.g. it documents ~30 skills under the
|
|
42
|
+
# old bare `/<name>` invocation form and does not yet list every skill in
|
|
43
|
+
# skills/, including the `j-<name>` twins — a pre-existing wiki staleness
|
|
44
|
+
# gap, not something introduced by this script). Fixing the wiki's own
|
|
45
|
+
# staleness is doc-sync's job, not this script's — this script only keeps
|
|
46
|
+
# the Pages site faithful to whatever the wiki currently says.
|
|
47
|
+
#
|
|
48
|
+
# HEADING-STABILITY ASSUMPTION: section extraction below is keyed to exact
|
|
49
|
+
# top-level ("## ") heading text in documentation.md (Agents, Skills, MCP
|
|
50
|
+
# Tools, Hooks, Directory Structure, Agent Communication Contract). If any
|
|
51
|
+
# of those headings are renamed, update the `case` statement in
|
|
52
|
+
# extract_sections() to match.
|
|
53
|
+
#
|
|
54
|
+
# Usage: scripts/build-pages-site.sh
|
|
55
|
+
# Safe to re-run any number of times — every run fully overwrites its
|
|
56
|
+
# output files from the current wiki content (no partial/incremental state).
|
|
57
|
+
|
|
58
|
+
set -euo pipefail
|
|
59
|
+
|
|
60
|
+
# shellcheck source=lib/resolve-project-dir.sh disable=SC1091
|
|
61
|
+
source "$(git rev-parse --show-toplevel)/lib/resolve-project-dir.sh"
|
|
62
|
+
|
|
63
|
+
REPO_ROOT="$JENGA_PROJECT_DIR"
|
|
64
|
+
WIKI_DIR="$REPO_ROOT/project/.wiki"
|
|
65
|
+
DOCS_DIR="$REPO_ROOT/docs"
|
|
66
|
+
DOC_MD="$WIKI_DIR/documentation.md"
|
|
67
|
+
INTRO_MD="$WIKI_DIR/intro-guide.md"
|
|
68
|
+
CONCEPTS_DIR="$WIKI_DIR/concepts"
|
|
69
|
+
|
|
70
|
+
for f in "$DOC_MD" "$INTRO_MD"; do
|
|
71
|
+
if [ ! -f "$f" ]; then
|
|
72
|
+
echo "build-pages-site.sh: required source file not found: $f" >&2
|
|
73
|
+
exit 1
|
|
74
|
+
fi
|
|
75
|
+
done
|
|
76
|
+
if [ ! -d "$CONCEPTS_DIR" ]; then
|
|
77
|
+
echo "build-pages-site.sh: required source directory not found: $CONCEPTS_DIR" >&2
|
|
78
|
+
exit 1
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
WORK="$(mktemp -d)"
|
|
82
|
+
trap 'rm -rf "$WORK"' EXIT
|
|
83
|
+
|
|
84
|
+
# --- 1. Split documentation.md into per-section scratch files -------------
|
|
85
|
+
# A line can only belong to one target section at a time; the generic
|
|
86
|
+
# "any other ## heading" rule resets `section` to "" so unrelated top-level
|
|
87
|
+
# sections (e.g. "## Table of Contents") are dropped rather than bleeding
|
|
88
|
+
# into whichever named section preceded them.
|
|
89
|
+
awk -v work="$WORK" '
|
|
90
|
+
/^## Agents$/ { section = "agents"; next }
|
|
91
|
+
/^## Skills$/ { section = "skills"; next }
|
|
92
|
+
/^## MCP Tools$/ { section = "mcp-tools"; next }
|
|
93
|
+
/^## Hooks$/ { section = "hooks"; next }
|
|
94
|
+
/^## Directory Structure$/ { section = "directory-structure"; next }
|
|
95
|
+
/^## Agent Communication Contract$/ { section = "contract"; next }
|
|
96
|
+
/^## / { section = "" }
|
|
97
|
+
{
|
|
98
|
+
if (section != "") {
|
|
99
|
+
print >> (work "/section-" section ".md")
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
' "$DOC_MD"
|
|
103
|
+
|
|
104
|
+
for s in agents skills mcp-tools hooks directory-structure contract; do
|
|
105
|
+
[ -f "$WORK/section-$s.md" ] || touch "$WORK/section-$s.md"
|
|
106
|
+
done
|
|
107
|
+
|
|
108
|
+
write_page() {
|
|
109
|
+
# write_page <output-path> <title> <permalink> <body-file>
|
|
110
|
+
local out="$1" title="$2" permalink="$3" body="$4"
|
|
111
|
+
{
|
|
112
|
+
printf -- '---\n'
|
|
113
|
+
printf 'layout: page\n'
|
|
114
|
+
printf 'title: %s\n' "$title"
|
|
115
|
+
printf 'permalink: %s\n' "$permalink"
|
|
116
|
+
printf -- '---\n\n'
|
|
117
|
+
cat "$body"
|
|
118
|
+
} > "$out"
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
# --- 2. docs/agents.md, docs/hooks.md, docs/mcp-tools.md -------------------
|
|
122
|
+
# Straight ports — no internal markdown links were found in these sections
|
|
123
|
+
# of documentation.md, so no link rewriting is needed beyond the front
|
|
124
|
+
# matter wrapper.
|
|
125
|
+
write_page "$DOCS_DIR/agents.md" "Agents" "/agents.html" "$WORK/section-agents.md"
|
|
126
|
+
write_page "$DOCS_DIR/hooks.md" "Hooks" "/hooks.html" "$WORK/section-hooks.md"
|
|
127
|
+
write_page "$DOCS_DIR/mcp-tools.md" "MCP Tools" "/mcp-tools.html" "$WORK/section-mcp-tools.md"
|
|
128
|
+
|
|
129
|
+
# --- 3. docs/skills.md ------------------------------------------------------
|
|
130
|
+
# Single reference page (matches the story's own suggested top-level
|
|
131
|
+
# category list: Getting Started / Concepts / Skills reference / Agents /
|
|
132
|
+
# Hooks / MCP Tools — "Skills reference" is one page, not one page per
|
|
133
|
+
# skill). Category (### ) and per-skill (#### ) structure is preserved
|
|
134
|
+
# as-is from the source.
|
|
135
|
+
write_page "$DOCS_DIR/skills.md" "Skills Reference" "/skills.html" "$WORK/section-skills.md"
|
|
136
|
+
|
|
137
|
+
# --- 4. docs/reference.md ---------------------------------------------------
|
|
138
|
+
# Combines the two remaining documentation.md sections (Directory Structure,
|
|
139
|
+
# Agent Communication Contract) behind a short hand-authored index blurb
|
|
140
|
+
# that links out to the pages built above — this replaces documentation.md's
|
|
141
|
+
# original role as the single "full reference" entry point, now that its
|
|
142
|
+
# content is split across multiple pages.
|
|
143
|
+
{
|
|
144
|
+
cat <<'EOF'
|
|
145
|
+
## Full Reference Index
|
|
146
|
+
|
|
147
|
+
This page is the entry point into the full reference material, split across
|
|
148
|
+
several pages so nothing requires scrolling through one giant file:
|
|
149
|
+
|
|
150
|
+
- **[Skills Reference](./skills.md)** — every skill, grouped by Setup &
|
|
151
|
+
Planning, Execution, Status & Review, and Committing & Maintenance.
|
|
152
|
+
- **[Agents](./agents.md)** — Scrum Master, Developer, Tester: roles,
|
|
153
|
+
ownership, and responsibilities.
|
|
154
|
+
- **[Hooks](./hooks.md)** — session lifecycle hooks and what they run.
|
|
155
|
+
- **[MCP Tools](./mcp-tools.md)** — Model Context Protocol tools available
|
|
156
|
+
in a Claude Code session.
|
|
157
|
+
|
|
158
|
+
The rest of this page covers the repo's directory structure and the
|
|
159
|
+
inter-agent communication contract (the typed "sender object" every agent
|
|
160
|
+
call carries).
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
EOF
|
|
165
|
+
cat "$WORK/section-directory-structure.md"
|
|
166
|
+
printf '\n---\n\n'
|
|
167
|
+
cat "$WORK/section-contract.md"
|
|
168
|
+
} > "$WORK/reference-body.md"
|
|
169
|
+
write_page "$DOCS_DIR/reference.md" "Reference" "/reference.html" "$WORK/reference-body.md"
|
|
170
|
+
|
|
171
|
+
# --- 5. docs/getting-started.md ---------------------------------------------
|
|
172
|
+
# Port of intro-guide.md verbatim (drop the leading H1 — front matter
|
|
173
|
+
# supplies the page title instead), with its two links into the
|
|
174
|
+
# now-restructured reference/concepts pages rewritten.
|
|
175
|
+
tail -n +2 "$INTRO_MD" > "$WORK/intro-body.md"
|
|
176
|
+
# NOTE on delimiter choice: sed's `s<delim>pattern<delim>replacement<delim>`
|
|
177
|
+
# breaks if the replacement text itself contains the delimiter character.
|
|
178
|
+
# Several replacements below contain a literal "#" (anchor fragments), so
|
|
179
|
+
# "#" cannot be used as the delimiter here — "|" is used instead, since
|
|
180
|
+
# none of these paths/anchors contain a literal "|".
|
|
181
|
+
sed -i.bak \
|
|
182
|
+
-e 's|\[documentation\.md\](\./documentation\.md)|[reference.md](./reference.md)|g' \
|
|
183
|
+
-e 's|(\./concepts/role-separation\.md)|(./concepts.md#role-separation)|g' \
|
|
184
|
+
-e 's|(\./concepts/board-hierarchy\.md)|(./concepts.md#board-hierarchy)|g' \
|
|
185
|
+
-e 's|(\./concepts/session-continuity\.md)|(./concepts.md#session-continuity)|g' \
|
|
186
|
+
-e 's|(\./concepts/first-feature\.md)|(./concepts.md#your-first-feature)|g' \
|
|
187
|
+
-e 's|(\./concepts/multi-session-work\.md)|(./concepts.md#working-across-sessions)|g' \
|
|
188
|
+
-e 's|(\./concepts/mid-flow-capture\.md)|(./concepts.md#capturing-mid-flow-ideas)|g' \
|
|
189
|
+
-e 's|(\./concepts/parallel-tasks\.md)|(./concepts.md#parallel-tasks)|g' \
|
|
190
|
+
"$WORK/intro-body.md"
|
|
191
|
+
rm -f "$WORK/intro-body.md.bak"
|
|
192
|
+
write_page "$DOCS_DIR/getting-started.md" "Getting Started" "/getting-started.html" "$WORK/intro-body.md"
|
|
193
|
+
|
|
194
|
+
# --- 6. docs/concepts.md -----------------------------------------------------
|
|
195
|
+
# Concatenates all 7 project/.wiki/concepts/*.md files into one page:
|
|
196
|
+
# - each file's H1 becomes an H2 section heading (slug listed below must
|
|
197
|
+
# stay in sync with each file's actual title text — GitHub Pages/kramdown
|
|
198
|
+
# slugifies headings to lowercase-hyphenated automatically)
|
|
199
|
+
# - all other headings are demoted one level (## -> ###, ### -> ####)
|
|
200
|
+
# - sibling/parent links are rewritten to point within the merged page
|
|
201
|
+
# and at the sibling getting-started.md / reference.md pages
|
|
202
|
+
#
|
|
203
|
+
{
|
|
204
|
+
cat <<'EOF'
|
|
205
|
+
## Concepts
|
|
206
|
+
|
|
207
|
+
The ideas behind Jenga AI's structure, and the how-tos for using it day to
|
|
208
|
+
day. Jump to any section:
|
|
209
|
+
|
|
210
|
+
- [Role Separation](#role-separation)
|
|
211
|
+
- [Board Hierarchy](#board-hierarchy)
|
|
212
|
+
- [Session Continuity](#session-continuity)
|
|
213
|
+
- [Your First Feature](#your-first-feature)
|
|
214
|
+
- [Working Across Sessions](#working-across-sessions)
|
|
215
|
+
- [Capturing Mid-Flow Ideas](#capturing-mid-flow-ideas)
|
|
216
|
+
- [Parallel Tasks](#parallel-tasks)
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
EOF
|
|
221
|
+
} > "$WORK/concepts-body.md"
|
|
222
|
+
|
|
223
|
+
append_concept() {
|
|
224
|
+
# append_concept <filename-stem> <section-title>
|
|
225
|
+
local stem="$1"
|
|
226
|
+
local title="$2"
|
|
227
|
+
local src="$CONCEPTS_DIR/$stem.md"
|
|
228
|
+
{
|
|
229
|
+
printf '## %s\n\n' "$title"
|
|
230
|
+
# NOTE on delimiter choice: same reasoning as the getting-started block
|
|
231
|
+
# above — replacements here contain a literal "#" anchor character, so
|
|
232
|
+
# "|" is used as the sed delimiter instead of "#".
|
|
233
|
+
#
|
|
234
|
+
# NOTE on heading demotion: a naive two-pass "## -> ###" then
|
|
235
|
+
# "### -> ####" sed would double-demote lines that were originally
|
|
236
|
+
# "## " (they'd match the first rule, becoming "### ", and then ALSO
|
|
237
|
+
# match the second rule on the same pass, becoming "#### " — wrong).
|
|
238
|
+
# The single extended-regex rule below captures the existing run of
|
|
239
|
+
# 2-3 "#" characters and prepends exactly one more, so each line is
|
|
240
|
+
# demoted exactly once regardless of its original level.
|
|
241
|
+
tail -n +2 "$src" \
|
|
242
|
+
| sed \
|
|
243
|
+
-e 's|\[documentation\.md\](\.\./documentation\.md)|[reference.md](./reference.md)|g' \
|
|
244
|
+
-e 's|(\.\./intro-guide\.md)|(./getting-started.md)|g' \
|
|
245
|
+
-e 's|(\.\./documentation\.md)|(./reference.md)|g' \
|
|
246
|
+
-e 's|(\./role-separation\.md)|(#role-separation)|g' \
|
|
247
|
+
-e 's|(\./board-hierarchy\.md)|(#board-hierarchy)|g' \
|
|
248
|
+
-e 's|(\./session-continuity\.md)|(#session-continuity)|g' \
|
|
249
|
+
-e 's|(\./first-feature\.md)|(#your-first-feature)|g' \
|
|
250
|
+
-e 's|(\./multi-session-work\.md)|(#working-across-sessions)|g' \
|
|
251
|
+
-e 's|(\./mid-flow-capture\.md)|(#capturing-mid-flow-ideas)|g' \
|
|
252
|
+
-e 's|(\./parallel-tasks\.md)|(#parallel-tasks)|g' \
|
|
253
|
+
| sed -E 's/^(#{2,3}) /#\1 /'
|
|
254
|
+
printf '\n---\n\n'
|
|
255
|
+
} >> "$WORK/concepts-body.md"
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
append_concept "role-separation" "Role Separation"
|
|
259
|
+
append_concept "board-hierarchy" "Board Hierarchy"
|
|
260
|
+
append_concept "session-continuity" "Session Continuity"
|
|
261
|
+
append_concept "first-feature" "Your First Feature"
|
|
262
|
+
append_concept "multi-session-work" "Working Across Sessions"
|
|
263
|
+
append_concept "mid-flow-capture" "Capturing Mid-Flow Ideas"
|
|
264
|
+
append_concept "parallel-tasks" "Parallel Tasks"
|
|
265
|
+
|
|
266
|
+
write_page "$DOCS_DIR/concepts.md" "Concepts" "/concepts.html" "$WORK/concepts-body.md"
|
|
267
|
+
|
|
268
|
+
echo "build-pages-site.sh: regenerated docs/{getting-started,concepts,skills,agents,hooks,mcp-tools,reference}.md from project/.wiki/*"
|
|
@@ -151,7 +151,21 @@ if [ -z "$REPO_ROOT" ]; then
|
|
|
151
151
|
exit 2
|
|
152
152
|
fi
|
|
153
153
|
|
|
154
|
-
|
|
154
|
+
# ─── Resolve with-lock.sh's package root ──────────────────────────────────
|
|
155
|
+
# postinstall.js mirrors only skills/ and agents/ into a consumer's .claude/
|
|
156
|
+
# and .agents/ — scripts/ (which owns with-lock.sh) is never copied there, so
|
|
157
|
+
# this script — itself shipped under skills/j-uncharted/scripts/ and mirrored
|
|
158
|
+
# alongside it — cannot assume "$REPO_ROOT/scripts/with-lock.sh" exists.
|
|
159
|
+
# Mirrors skills/init/scripts/init.sh's PKG_ROOT fallback: prefer a monorepo
|
|
160
|
+
# checkout's sibling scripts/ dir, else fall back to the installed npm
|
|
161
|
+
# package under node_modules/@jenga-ai/agent.
|
|
162
|
+
if [ -f "$SCRIPT_DIR/../../../scripts/with-lock.sh" ]; then
|
|
163
|
+
WITH_LOCK="$SCRIPT_DIR/../../../scripts/with-lock.sh"
|
|
164
|
+
elif [ -f "$REPO_ROOT/node_modules/@jenga-ai/agent/scripts/with-lock.sh" ]; then
|
|
165
|
+
WITH_LOCK="$REPO_ROOT/node_modules/@jenga-ai/agent/scripts/with-lock.sh"
|
|
166
|
+
else
|
|
167
|
+
WITH_LOCK="$REPO_ROOT/scripts/with-lock.sh"
|
|
168
|
+
fi
|
|
155
169
|
STATE_DIR="$REPO_ROOT/project/queue/elicitation-state"
|
|
156
170
|
DEFAULT_CAP=5
|
|
157
171
|
|
package/skills/jenga/SKILL.md
CHANGED
|
@@ -132,13 +132,15 @@ If all applicable rules pass (or the task is a legacy task), proceed to the next
|
|
|
132
132
|
|
|
133
133
|
### Phase 0.75 — Entry Mode Resolution
|
|
134
134
|
|
|
135
|
-
This phase determines **how `/jenga` was invoked** and, for two of the
|
|
135
|
+
This phase determines **how `/jenga` was invoked** and, for two of the four entry modes, produces a **scoped set** — a confirmed list of board IDs (epics/stories/tasks) that Phases 1-4 must restrict themselves to. All board scanning, ID parsing, cascade expansion, and rendering used by this phase already live in `skills/jenga/scripts/` per this repo's "Scripts Over Inline Logic" principle — this phase never re-implements any of that logic inline. The executing agent's job here is limited to: invoking the right script with the right arguments, relaying its STDOUT verbatim to the user when the contract calls for that, capturing the `STATE_FILE:` line from STDERR for the next turn, and forwarding the user's raw reply back into the next invocation unmodified.
|
|
136
136
|
|
|
137
137
|
**Determine the invocation form** from the raw argument (if any) passed to `/jenga`:
|
|
138
138
|
|
|
139
139
|
- No argument at all → **bare branch**.
|
|
140
140
|
- The argument is the literal string `*` → **wildcard branch**.
|
|
141
|
-
- Any other non-empty argument →
|
|
141
|
+
- Any other non-empty argument → invoke `skills/jenga/scripts/detect-nl-intent.sh "<raw argument>"` (E53_S01_T01) and branch on its `classification` field:
|
|
142
|
+
- `all_resolved` or `mixed` → **scoped branch** (below) — this is the same branch as before; only its internal mechanics changed (see below).
|
|
143
|
+
- `nl_intent` → **natural-language branch** (below) — new for E53_S01, no new sigil or entry point, purely a new outcome of this same argument-shape detection.
|
|
142
144
|
|
|
143
145
|
#### Wildcard branch (`/jenga *`)
|
|
144
146
|
|
|
@@ -154,10 +156,35 @@ Skip both the picker and the confirmation step entirely. There is no scoped set
|
|
|
154
156
|
|
|
155
157
|
#### Scoped branch (`/jenga <ids>`)
|
|
156
158
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
159
|
+
This branch is entered when `detect-nl-intent.sh` (invoked above) classifies the argument as `all_resolved` or `mixed` — the picker is skipped entirely in this branch. `detect-nl-intent.sh` has already invoked `resolve-id.sh` internally and reduced its per-segment output to one of these two shapes; `skills/jenga/SKILL.md` never parses `resolve-id.sh`'s raw array itself (see `detect-nl-intent.sh`'s own header comment for the full classification contract, E53_S01_T01).
|
|
160
|
+
|
|
161
|
+
1. On `all_resolved`, take the `resolved_ids` (or `resolved_ids_csv`) field directly from `detect-nl-intent.sh`'s output and continue to the shared confirmation step below.
|
|
162
|
+
2. On `mixed`, halt this phase (do not proceed to confirmation or Phase 1) and report each entry in `detect-nl-intent.sh`'s `rejected` array — its `input` and `reason` — to the user verbatim; a partial or ambiguous ID is never guessed. The user must re-invoke `/jenga <ids>` with corrected input.
|
|
163
|
+
|
|
164
|
+
#### Natural-language branch (`/jenga <free-form text>`)
|
|
165
|
+
|
|
166
|
+
This branch is entered when `detect-nl-intent.sh` classifies the argument as `nl_intent` — every comma-delimited segment failed the ID grammar, so the raw argument is treated as natural-language intent rather than a malformed ID list. This is purely a new *outcome* of the same argument-shape detection above — no new sigil, trigger prefix, or separate entry point is introduced.
|
|
167
|
+
|
|
168
|
+
1. **Load the catalog** — invoke `skills/jenga/scripts/load-nl-catalog.sh` with no arguments (E53_S01_T02). Its stdout is the full skill catalog (`name`/`description`/`keywords`/`examples`/`prefered_agent` per skill), sourced exclusively from `lib/generate-skill-allow-list.js`'s generated inventory — see the script's own header for the full contract. Never re-derive this catalog by re-scanning `skills/` inline.
|
|
169
|
+
2. **Match** — run `skills/route/SKILL.md`'s **Step 2 — Match the Prompt to a Skill** (the three-pass keyword → example-similarity → description match, including its tie-break and no-match handling) against this catalog, treating `detect-nl-intent.sh`'s `raw_argument` field as the prompt. Reuse that section's matching logic by reference — do not re-author its prose here.
|
|
170
|
+
3. **Confident single match** — report the routing decision using `skills/route/SKILL.md`'s **Step 7 — Report Routing Decision** format (substitute `/jenga` for `/route` as the invoking command named in the report), then invoke the matched skill exactly as `skills/route/SKILL.md`'s **Step 6 — Invoke the Matched Skill** already does: load `agents/<prefered_agent>.md` when the matched skill specifies `metadata.prefered_agent`, otherwise execute the skill instructions directly. The matched skill's own execution takes over from here — do not continue into this `/jenga` invocation's Phase 1.
|
|
171
|
+
4. **No match, or an ambiguous multi-way tie (single-skill match)** — before surfacing `/route`'s generic disambiguation options, attempt a **playbook fallback** (E53_S02): invoke `skills/jenga/scripts/match-playbook.sh "<raw_argument>"`. This step only ever runs when step 3 above did NOT already commit to a confident single-skill match — a confident single-skill match always wins outright and this playbook fallback is never even invoked in that case. Branch on `match-playbook.sh`'s `classification` field:
|
|
172
|
+
- `playbook_match` → continue to **step 5 (Playbook proposal and execution)** below.
|
|
173
|
+
- `ambiguous` or `no_match` → continue to **step 6 (Fall through to `/route`'s disambiguation)** below — the exact behavior this branch already had before E53_S02, unchanged.
|
|
174
|
+
5. **Playbook proposal and execution** — entered only on a `playbook_match` result from step 4. A proposed playbook is an ordered chain of skills (e.g. the canonical `brainstorm -> j.todo -> j.do -> j.dev-done -> j.mirror-public` chain defined in `skills/jenga/playbooks/brainstorm-to-mirror.json`) that must be confirmed, editable, and confirmable per `CLAUDE.md`'s Interaction Pattern before any step executes — the same confirm-before-execute posture `/jenga` already applies to the bare/scoped branches via `render-confirmation.sh`.
|
|
175
|
+
a. **Render and confirm the chain** — invoke `skills/jenga/scripts/render-playbook-confirmation.sh "<playbook_id>" "<name>" "<comma-separated steps>"` (start mode, using `match-playbook.sh`'s `playbook_id`/`name`/`steps` fields verbatim). Relay STDOUT (the numbered chain + instructions) to the user verbatim. Capture the `STATE_FILE:` path from STDERR.
|
|
176
|
+
b. Wait for the user's chat reply, then invoke `skills/jenga/scripts/render-playbook-confirmation.sh <state_file> "<raw_reply>"` (continue mode).
|
|
177
|
+
- **Toggle or error turn** (plain text on STDOUT, state file retained) — relay verbatim and return to step 5b for another reply. This loops exactly as the existing bare/scoped confirmation flow's own toggle/error turns already do.
|
|
178
|
+
- **Cancellation** — relay the cancellation acknowledgement and halt the entire `/jenga` invocation immediately, with no step executed — identical posture to the existing picker/confirmation cancellation edge cases already documented for the bare/scoped branches (see "## Edge Cases" below).
|
|
179
|
+
- **Confirmed** (JSON object on STDOUT, state file removed) — take the confirmed `steps` array (checked-only, in original playbook order) and continue to step 5c.
|
|
180
|
+
c. **Initialize the sequential runner** — invoke `skills/jenga/scripts/run-playbook-step.sh init "<playbook_id>" "<name>" "<comma-separated confirmed steps>"`. Its `step_ready` result names the first step to invoke.
|
|
181
|
+
d. **Execute steps in a loop** — for the step named by the runner's most recent `step_ready` result:
|
|
182
|
+
i. Invoke that step exactly as `skills/route/SKILL.md`'s **Step 6 — Invoke the Matched Skill** already does for a single matched skill: load `agents/<prefered_agent>.md` when that step's own `SKILL.md` specifies `metadata.prefered_agent`, otherwise execute its instructions directly.
|
|
183
|
+
ii. After that step's execution concludes, call `skills/jenga/scripts/run-playbook-step.sh advance <state_file> passed` (the step completed successfully) or `... advance <state_file> failed "<short failure note>"` (the step failed).
|
|
184
|
+
iii. On a `step_ready` result, repeat step 5d for the newly-named step.
|
|
185
|
+
iv. On a `complete` result, report the full list of completed steps to the user and stop — the playbook run is finished; do not continue into this `/jenga` invocation's Phase 1.
|
|
186
|
+
v. On a `halted` result, **immediately stop executing any further steps** — no silent skip-ahead. Report `failed_step`, `failed_note`, `completed` (steps that already finished), and `never_run` (steps that never got a chance to run) to the user verbatim from the halt report. Do not continue into this `/jenga` invocation's Phase 1.
|
|
187
|
+
6. **Fall through to `/route`'s disambiguation** — entered when step 4 found no playbook match (`ambiguous` or `no_match`). Surface the same disambiguation options `skills/route/SKILL.md`'s **Step 2** already defines for these cases (browse `/help`, create a new skill via `/btw`, or proceed with the raw prompt) by reference to that section — do not re-copy its prose. Halt this `/jenga` invocation once the user picks an option; none of Phase 0.75's remaining steps or Phases 1-4 run for this branch.
|
|
161
188
|
|
|
162
189
|
#### Shared confirmation step (bare and scoped branches only)
|
|
163
190
|
|
|
@@ -255,6 +282,11 @@ When no eligible candidates remain in Phase 4, exit and output:
|
|
|
255
282
|
- **Bundle `/do` call failure** — treated as a skip for the entire bundle; mark all bundled tasks' status back to `Pending` and continue Phase 4 with remaining non-bundled candidates.
|
|
256
283
|
- **Picker cancelled (bare branch)** — the entire `/jenga` run halts immediately after relaying the cancellation acknowledgement; no phase past 0.75 runs, and nothing on the board is modified.
|
|
257
284
|
- **Confirmation cancelled (bare or scoped branch)** — same as picker cancellation: the entire `/jenga` run halts immediately; no scoped set is produced and no later phase runs.
|
|
258
|
-
- **`
|
|
285
|
+
- **`detect-nl-intent.sh` classifies the argument as `mixed` (scoped branch)** — the whole invocation halts at Phase 0.75 with each rejected segment's `input`/`reason` reported verbatim, per `detect-nl-intent.sh`'s own classification contract (E53_S01_T01); no partial scope is assembled from the segments that did resolve, and no fallback guess is made for the rejected ones. The user must re-invoke `/jenga <ids>` with corrected input.
|
|
286
|
+
- **`detect-nl-intent.sh` classifies the argument as `nl_intent`, no confident single-skill match, and `match-playbook.sh` (E53_S02) also finds no playbook match** — the natural-language branch's step 4 attempts the playbook fallback first (see the Natural-language branch's step 4/6), and only THEN surfaces `skills/route/SKILL.md`'s Step 2 no-match disambiguation options (browse `/help`, create a new skill via `/btw`, proceed with the raw prompt) instead of guessing; no phase past 0.75 runs until the user picks one.
|
|
287
|
+
- **`detect-nl-intent.sh` classifies the argument as `nl_intent`, no confident single-skill match, and `match-playbook.sh` returns an ambiguous multi-way tie between playbooks** — treated the same as the no-playbook-match case above: falls through to `skills/route/SKILL.md`'s Step 2 tie-break prompt (top candidates + a "neither, describe what you need" option) instead of guessing; no phase past 0.75 runs until the user picks one. (`match-playbook.sh`'s own `ambiguous` result — a tie between playbooks — is intentionally not given its own separate disambiguation UI; it is treated identically to `no_match` and routed to the same `/route` Step 2 fallback prose, which already has its own tie-break handling.)
|
|
288
|
+
- **`match-playbook.sh` returns `playbook_match` and the user confirms the full chain, and every step succeeds** — the Natural-language branch's step 5d reports the full `completed` steps list to the user and stops; `/jenga`'s own Phase 1 never runs for this invocation (execution was already fully handled by the playbook's own steps, e.g. `j.do`/`j.dev-done`).
|
|
289
|
+
- **`match-playbook.sh` returns `playbook_match` but the user cancels at the chain confirmation step (step 5b)** — identical posture to the existing picker/confirmation cancellation cases above: the entire `/jenga` run halts immediately after relaying the cancellation acknowledgement, with NO step of the chain executed; nothing on the board is modified by this invocation.
|
|
290
|
+
- **`match-playbook.sh` returns `playbook_match`, the user confirms, and a step mid-chain fails** — the Natural-language branch's step 5d(v) halts immediately on `run-playbook-step.sh`'s `halted` result: no step after the failed one runs (no silent skip-ahead), and the user is shown exactly which steps already completed, which step failed (with its note), and which steps never ran.
|
|
259
291
|
- **`/jenga *` (wildcard branch)** — never produces a scoped set; Phases 1-4 run fully unrestricted over the entire board, identical to `/jenga`'s behavior before Phase 0.75 existed.
|
|
260
292
|
- **Stale out-of-scope story queued in `todo.md` from an earlier run (scoped run only)** — Phase 3.5's scoped-set guard skips it entirely (not considered for bundling), so it cannot be dispatched via a bundle `/do <E##_S##>` call that would otherwise bypass Phase 4's own scoped-set exclusion; it remains untouched in `todo.md` until a future run's scope includes it.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "brainstorm-to-mirror",
|
|
3
|
+
"name": "Idea to Public Release",
|
|
4
|
+
"description": "Takes a rough idea all the way from planning through implementation, committing, and a public mirror release -- the canonical end-to-end Jenga workflow chain.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"idea to release",
|
|
7
|
+
"plan and ship",
|
|
8
|
+
"idea to done",
|
|
9
|
+
"full workflow",
|
|
10
|
+
"end to end",
|
|
11
|
+
"plan build ship",
|
|
12
|
+
"idea to production"
|
|
13
|
+
],
|
|
14
|
+
"examples": [
|
|
15
|
+
"I have an idea, help me plan it, build it, and ship it",
|
|
16
|
+
"take this feature from idea to committed and published",
|
|
17
|
+
"let's go from a rough idea all the way to a public release",
|
|
18
|
+
"plan this out, implement it, commit it, and push it to the public mirror",
|
|
19
|
+
"walk this through the whole pipeline from brainstorm to release"
|
|
20
|
+
],
|
|
21
|
+
"steps": ["brainstorm", "todo", "do", "dev-done", "mirror-public"]
|
|
22
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://jenga.local/schemas/jenga-playbook.schema.json",
|
|
4
|
+
"title": "Jenga Multi-Skill Playbook",
|
|
5
|
+
"description": "Schema for a single multi-skill playbook definition consumed by skills/jenga/scripts/load-playbooks.sh (E53_S02_T01). A playbook is a dedicated, versionable data file describing an ORDERED chain of skills that /jenga's natural-language branch may propose (as an editable, confirmable numbered list -- see skills/jenga/scripts/render-playbook-confirmation.sh, E53_S02_T03) when free-text intent spans more than one skill and does not cleanly resolve to a single one via skills/route/SKILL.md's Step 2 matching. This file itself (schema.json) is never treated as a playbook -- load-playbooks.sh explicitly excludes it by filename when scanning skills/jenga/playbooks/*.json.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["id", "name", "description", "keywords", "examples", "steps"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"id": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"description": "Stable, unique, kebab-case identifier for this playbook (e.g. \"brainstorm-to-mirror\"). Must equal the filename's basename without the .json extension -- load-playbooks.sh validates this so a playbook's id can never silently drift from its file location.",
|
|
13
|
+
"pattern": "^[a-z0-9]+(-[a-z0-9]+)*$"
|
|
14
|
+
},
|
|
15
|
+
"name": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"description": "Short human-readable display name shown to the user in the confirmation prompt and in routing/report output, e.g. \"Idea to Public Release\"."
|
|
18
|
+
},
|
|
19
|
+
"description": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"description": "One-sentence explanation of what this playbook accomplishes end-to-end, used as the lowest-priority match signal (description match, same as skills/route/SKILL.md's Step 2 Pass 3) when keywords/examples don't produce a confident match."
|
|
22
|
+
},
|
|
23
|
+
"keywords": {
|
|
24
|
+
"type": "array",
|
|
25
|
+
"description": "Short phrases (1-3 words) for verbatim, case-insensitive keyword matching against the raw natural-language prompt -- the highest-priority match signal (Pass 1), mirroring skills/route/SKILL.md's Step 2 Pass 1 semantics exactly, but scoped to this playbook's catalog rather than the single-skill catalog.",
|
|
26
|
+
"items": { "type": "string" },
|
|
27
|
+
"minItems": 1
|
|
28
|
+
},
|
|
29
|
+
"examples": {
|
|
30
|
+
"type": "array",
|
|
31
|
+
"description": "Natural-language example prompts a user might type that should resolve to this playbook. Used for the semantic similarity match (Pass 2), mirroring skills/route/SKILL.md's Step 2 Pass 2 semantics. At least one example must plausibly span the full breadth of this playbook's steps (not just its first step) so it is distinguishable from a plain single-skill match.",
|
|
32
|
+
"items": { "type": "string" },
|
|
33
|
+
"minItems": 1
|
|
34
|
+
},
|
|
35
|
+
"steps": {
|
|
36
|
+
"type": "array",
|
|
37
|
+
"description": "Ordered list of bare skill names (the directory name under skills/<name>/SKILL.md, e.g. \"brainstorm\", not \"j.brainstorm\" or \"/brainstorm\") that make up this playbook's chain, in the exact execution order. Each entry MUST resolve to an existing skills/<name>/SKILL.md at load time -- load-playbooks.sh skips (with a stderr warning) any playbook referencing a nonexistent skill rather than silently including a broken chain in the catalog.",
|
|
38
|
+
"items": { "type": "string" },
|
|
39
|
+
"minItems": 2
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|