@jenga-ai/agent 1.3.0 → 2.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 +97 -92
- package/agents/developer.md +9 -8
- package/agents/scrum-master.md +57 -23
- package/agents/tester.md +51 -5
- package/hooks/on_session_end.sh +13 -1
- package/lib/generate-agent-context.js +18 -1
- package/lib/generate-copilot-instructions.js +18 -1
- package/lib/generate-skill-allow-list.js +191 -0
- package/lib/skill-allow-list.json +43 -0
- package/package.json +18 -4
- package/scripts/apply-j-prefix.sh +230 -0
- package/scripts/consume-context-digest.sh +103 -0
- package/scripts/postinstall.js +25 -0
- package/scripts/sweep-stale-context-digests.sh +132 -0
- package/scripts/validate-board.sh +5 -0
- package/scripts/write-context-digest.sh +230 -0
- package/skills/brainstorm/SKILL.md +1 -1
- package/skills/btw/SKILL.md +1 -1
- package/skills/clearify/SKILL.md +1 -1
- package/skills/close-story/SKILL.md +78 -6
- package/skills/close-story/scripts/check-privatized.sh +345 -0
- package/skills/commit/SKILL.md +1 -1
- package/skills/continue/SKILL.md +1 -1
- package/skills/deep-dive/SKILL.md +1 -1
- package/skills/dev-done/SKILL.md +1 -1
- package/skills/distribute/SKILL.md +1 -1
- package/skills/do/SKILL.md +100 -10
- package/skills/doc/README.md +155 -0
- package/skills/doc/SKILL.md +43 -13
- package/skills/doc/authoring-notes.md +72 -0
- package/skills/doc/scripts/resolve_last_update.py +149 -0
- package/skills/doc-sync/SKILL.md +1 -1
- package/skills/dooo/SKILL.md +1 -1
- package/skills/error/SKILL.md +1 -1
- package/skills/evaluate/SKILL.md +1 -1
- package/skills/examplify/SKILL.md +1 -1
- package/skills/help/SKILL.md +1 -1
- package/skills/idea/SKILL.md +1 -1
- package/skills/improve/SKILL.md +1 -1
- package/skills/init/SKILL.md +1 -1
- package/skills/init/assets/scope-thresholds_template.json +3 -3
- package/skills/j-init/SKILL.md +168 -0
- package/skills/j-init/assets/.gitignore_template +15 -0
- package/skills/j-init/assets/PROJECT_SUMMARY_template.md +13 -0
- package/skills/j-init/assets/directory_structure.txt +14 -0
- package/skills/j-init/assets/scope-thresholds_template.json +7 -0
- package/skills/j-init/assets/strategy_stub_template.md +38 -0
- package/skills/j-init/assets/test-config_template.json +4 -0
- package/skills/j-init/assets/workflow_template.json +30 -0
- package/skills/j-init/scripts/apply-project-visibility.sh +176 -0
- package/skills/j-init/scripts/detect-existing-codebase.sh +166 -0
- package/skills/j-init/scripts/init.sh +116 -0
- package/skills/jbp/SKILL.md +1 -1
- package/skills/jenga/SKILL.md +1 -1
- package/skills/jenga/scripts/render-confirmation.sh +55 -18
- package/skills/jenga-permission-level/SKILL.md +1 -1
- package/skills/lgtm/SKILL.md +1 -1
- package/skills/pi-plan/SKILL.md +1 -1
- package/skills/proceed/SKILL.md +1 -1
- package/skills/publish/SKILL.md +1 -1
- package/skills/publish/adapters/npm-ci.md +26 -4
- package/skills/publish/scripts/npm_ci_pipeline.sh +21 -1
- package/skills/reconcile/SKILL.md +1 -1
- package/skills/reconcile-origin/SKILL.md +1 -1
- package/skills/redo/SKILL.md +1 -1
- package/skills/skillify/SKILL.md +1 -1
- package/skills/spinoff/SKILL.md +1 -1
- package/skills/status/SKILL.md +1 -1
- package/skills/todo/SKILL.md +40 -3
- package/skills/todo/scripts/add_trivial_task.sh +216 -0
- package/skills/todo/scripts/update_story_tasks.py +87 -0
- package/skills/uncharted/SKILL.md +1 -1
- package/skills/wtf/SKILL.md +1 -1
- package/templates/SCRUM_BOARD_SCHEMA.md +33 -2
- package/templates/agent-context.md.tpl +32 -9
- package/templates/copilot-instructions.md.tpl +25 -8
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
5
|
+
ASSETS_DIR="$SCRIPT_DIR/../assets"
|
|
6
|
+
VISIBILITY_SCRIPT="$SCRIPT_DIR/apply-project-visibility.sh"
|
|
7
|
+
|
|
8
|
+
# ─── Resolve the package root that owns templates/ and lib/ ──────────────────
|
|
9
|
+
# postinstall.js mirrors only skills/ and agents/ into .claude/ and .agents/ —
|
|
10
|
+
# templates/ and lib/ are never copied there, so a script running from a
|
|
11
|
+
# mirrored copy (.claude/skills/init/scripts/ or .agents/skills/init/scripts/)
|
|
12
|
+
# cannot reach its siblings via a fixed ../../../ climb the way it can in this
|
|
13
|
+
# monorepo checkout, where init.sh actually lives at skills/init/scripts/ with
|
|
14
|
+
# templates/ and lib/ three levels up. Consumers instead have them inside the
|
|
15
|
+
# installed npm package.
|
|
16
|
+
if [[ -d "$SCRIPT_DIR/../../../templates" ]]; then
|
|
17
|
+
PKG_ROOT="$SCRIPT_DIR/../../.."
|
|
18
|
+
elif [[ -d "$PWD/node_modules/@jenga-ai/agent/templates" ]]; then
|
|
19
|
+
PKG_ROOT="$PWD/node_modules/@jenga-ai/agent"
|
|
20
|
+
else
|
|
21
|
+
echo "Error: could not locate the jenga-agent package root (templates/ not found via monorepo checkout or node_modules/@jenga-ai/agent)." >&2
|
|
22
|
+
exit 1
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
# ─── 0. Resolve project_files_visibility ─────────────────────────────────────
|
|
26
|
+
# Defaults to `visible` — the only value that touches nothing on disk — so an
|
|
27
|
+
# unattended run can never silently relocate directories or edit .gitignore.
|
|
28
|
+
VISIBILITY="${JENGA_PROJECT_FILES_VISIBILITY:-visible}"
|
|
29
|
+
|
|
30
|
+
while [[ $# -gt 0 ]]; do
|
|
31
|
+
case "$1" in
|
|
32
|
+
--visibility) VISIBILITY="${2:-}"; shift 2 ;;
|
|
33
|
+
--visibility=*) VISIBILITY="${1#*=}"; shift ;;
|
|
34
|
+
*) echo "Unknown argument: $1" >&2
|
|
35
|
+
echo "Usage: $(basename "$0") [--visibility <visible|ignored>]" >&2
|
|
36
|
+
exit 1 ;;
|
|
37
|
+
esac
|
|
38
|
+
done
|
|
39
|
+
|
|
40
|
+
# Validate before scaffolding so a typo cannot leave a half-initialised project.
|
|
41
|
+
bash "$VISIBILITY_SCRIPT" --check-only "$VISIBILITY"
|
|
42
|
+
|
|
43
|
+
# ─── 1. Initialize git repository ────────────────────────────────────────────
|
|
44
|
+
echo "→ Initializing git repository..."
|
|
45
|
+
git init
|
|
46
|
+
|
|
47
|
+
# ─── 2. Create .gitignore ─────────────────────────────────────────────────────
|
|
48
|
+
echo "→ Copying .gitignore from template..."
|
|
49
|
+
cp "$ASSETS_DIR/.gitignore_template" .gitignore
|
|
50
|
+
|
|
51
|
+
# ─── 3. Scaffold directory structure ──────────────────────────────────────────
|
|
52
|
+
echo "→ Scaffolding directory structure..."
|
|
53
|
+
while IFS= read -r dir || [[ -n "$dir" ]]; do
|
|
54
|
+
[[ -z "$dir" || "$dir" == \#* ]] && continue
|
|
55
|
+
mkdir -p "$dir"
|
|
56
|
+
done < "$ASSETS_DIR/directory_structure.txt"
|
|
57
|
+
|
|
58
|
+
# ─── 4. Create project/PROJECT_SUMMARY.md ────────────────────────────────────
|
|
59
|
+
echo "→ Copying PROJECT_SUMMARY.md from template..."
|
|
60
|
+
cp "$ASSETS_DIR/PROJECT_SUMMARY_template.md" project/PROJECT_SUMMARY.md
|
|
61
|
+
|
|
62
|
+
# ─── 5. Create project/configs/workflow.json ─────────────────────────────────
|
|
63
|
+
echo "→ Copying workflow.json from template..."
|
|
64
|
+
cp "$ASSETS_DIR/workflow_template.json" project/configs/workflow.json
|
|
65
|
+
|
|
66
|
+
# ─── 6. Create project/configs/test-config.json stub ─────────────────────────
|
|
67
|
+
echo "→ Copying test-config.json from template..."
|
|
68
|
+
cp "$ASSETS_DIR/test-config_template.json" project/configs/test-config.json
|
|
69
|
+
|
|
70
|
+
# ─── 6.5. Create project/configs/scope-thresholds.json ───────────────────────
|
|
71
|
+
# Consumed by skills/jenga (Phase 0) and skills/do (Step 0); both halt if it's
|
|
72
|
+
# missing, so it must exist immediately after scaffold.
|
|
73
|
+
echo "→ Copying scope-thresholds.json from template..."
|
|
74
|
+
cp "$ASSETS_DIR/scope-thresholds_template.json" project/configs/scope-thresholds.json
|
|
75
|
+
|
|
76
|
+
# ─── 7. Create project/data/baselines.json ───────────────────────────────────
|
|
77
|
+
echo "→ Creating baselines.json..."
|
|
78
|
+
echo '{}' > project/data/baselines.json
|
|
79
|
+
|
|
80
|
+
# ─── 8. Create project/logs/events.json ──────────────────────────────────────
|
|
81
|
+
echo "→ Creating events.json..."
|
|
82
|
+
echo '[]' > project/logs/events.json
|
|
83
|
+
|
|
84
|
+
# ─── 9. Create docs/STRATEGY.md ──────────────────────────────────────────────
|
|
85
|
+
echo "→ Creating docs/STRATEGY.md (strategic brief for investors, partners, and the product team)..."
|
|
86
|
+
mkdir -p docs
|
|
87
|
+
cp "$ASSETS_DIR/strategy_stub_template.md" docs/STRATEGY.md
|
|
88
|
+
|
|
89
|
+
# ─── 10. Create CHANGELOG.md ──────────────────────────────────────────────────
|
|
90
|
+
echo "→ Creating CHANGELOG.md from template..."
|
|
91
|
+
cp "$PKG_ROOT/templates/CHANGELOG_TEMPLATE.md" CHANGELOG.md
|
|
92
|
+
|
|
93
|
+
# ─── 11. Apply project_files_visibility ──────────────────────────────────────
|
|
94
|
+
# Runs before the commit so the .gitignore entry (ignored) is captured in the
|
|
95
|
+
# initial commit.
|
|
96
|
+
echo "→ Applying project files visibility ($VISIBILITY)..."
|
|
97
|
+
bash "$VISIBILITY_SCRIPT" "$VISIBILITY" "$PWD"
|
|
98
|
+
|
|
99
|
+
# ─── 12. Generate CLAUDE.md / AGENTS.md ──────────────────────────────────────
|
|
100
|
+
# Unconditional — never gated on agentTarget (E41_S04). Applies the J-
|
|
101
|
+
# collision rule and idempotent managed-block updates; see
|
|
102
|
+
# lib/generate-agent-context.js (shared with the published `jenga init` CLI).
|
|
103
|
+
echo "→ Generating CLAUDE.md / AGENTS.md..."
|
|
104
|
+
if command -v node >/dev/null 2>&1; then
|
|
105
|
+
node "$PKG_ROOT/lib/generate-agent-context.js" "$PWD"
|
|
106
|
+
else
|
|
107
|
+
echo " Warning: node not found — skipped CLAUDE.md/AGENTS.md generation." >&2
|
|
108
|
+
fi
|
|
109
|
+
|
|
110
|
+
# ─── 13. Initial commit ──────────────────────────────────────────────────────
|
|
111
|
+
echo "→ Staging and committing scaffolded files..."
|
|
112
|
+
git add -A
|
|
113
|
+
git commit -m "init: scaffold project structure and workflow config"
|
|
114
|
+
|
|
115
|
+
echo ""
|
|
116
|
+
echo "✓ Project scaffold complete."
|
package/skills/jbp/SKILL.md
CHANGED
package/skills/jenga/SKILL.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: jenga
|
|
2
|
+
name: j:jenga
|
|
3
3
|
description: Interactive-by-default board orchestrator with a fully automated escape hatch. Bare `/jenga` renders a picker and confirmation tree before scoping the run; `/jenga <ids>` resolves an explicit fuzzy-ID scope and confirms it; `/jenga *` reproduces the original zero-prompt behavior — decomposing any unbroken Epics into Stories, any unbroken Stories into Tasks, queuing all unqueued Tasks into todo.md, then executing every eligible item with no user prompts — until the board is fully started.
|
|
4
4
|
keywords:
|
|
5
5
|
- jenga
|
|
@@ -97,12 +97,18 @@
|
|
|
97
97
|
# ENTIRE turn is rejected as an error turn (state left untouched) — there
|
|
98
98
|
# is no partial application of the valid numbers in a mixed-validity reply.
|
|
99
99
|
#
|
|
100
|
-
# Toggling
|
|
101
|
-
#
|
|
102
|
-
#
|
|
103
|
-
#
|
|
104
|
-
#
|
|
105
|
-
#
|
|
100
|
+
# Toggling CASCADES downward (E45_S02_T03): checking or unchecking a
|
|
101
|
+
# story applies the same resulting state to all of its tasks; checking or
|
|
102
|
+
# unchecking an epic applies the same resulting state to all of its
|
|
103
|
+
# stories and their tasks. This is a deliberate, explicit reversal of the
|
|
104
|
+
# original non-cascading design (see this story's 2026-08-27 close-out) —
|
|
105
|
+
# the user hit a real case where unchecking a parent epic left its child
|
|
106
|
+
# story/tasks checked, requiring a manual follow-up uncheck command.
|
|
107
|
+
# Cascade is STRICTLY DOWNWARD (parent -> descendants) only: checking a
|
|
108
|
+
# leaf task does NOT imply its ancestors should also be checked, so a
|
|
109
|
+
# checked child under an unchecked parent is a valid (if visually
|
|
110
|
+
# inconsistent) state. Toggling a leaf task (no children) behaves exactly
|
|
111
|
+
# as it always has — no descendants to cascade into.
|
|
106
112
|
#
|
|
107
113
|
# ---------------------------------------------------------------------------
|
|
108
114
|
# OUTPUT CONTRACT (deliberately NOT uniform JSON — see rationale below)
|
|
@@ -165,8 +171,15 @@
|
|
|
165
171
|
# STATE FILE
|
|
166
172
|
# ---------------------------------------------------------------------------
|
|
167
173
|
# Created under `mktemp -t jenga-confirm-XXXXXX.json`. Stores:
|
|
168
|
-
# - `numbering`: displayed number -> {item, level, checked} —
|
|
169
|
-
#
|
|
174
|
+
# - `numbering`: displayed number -> {item, level, checked, children} —
|
|
175
|
+
# `children` is a fixed list of the item's direct descendant numbers
|
|
176
|
+
# (a story's task numbers; an epic's story numbers), computed once at
|
|
177
|
+
# build time so continue-mode can cascade a toggle without
|
|
178
|
+
# re-deriving parent/child relationships from `item_id`/`epic_id`/
|
|
179
|
+
# `story_id` at toggle time. `children` is always `[]` for a leaf
|
|
180
|
+
# task. The only fields that mutate across turns are `checked` values
|
|
181
|
+
# (potentially many at once, via cascade — see TOGGLE COMMAND GRAMMAR
|
|
182
|
+
# above).
|
|
170
183
|
# - `layout`: the fixed print order (item lines + header markers),
|
|
171
184
|
# computed once at start. Continue mode never recomputes tree shape —
|
|
172
185
|
# it only re-renders from `layout` + the live `checked` flags in
|
|
@@ -305,15 +318,17 @@ def pluralize_task(n):
|
|
|
305
318
|
return f"{n} task{'' if n == 1 else 's'}"
|
|
306
319
|
|
|
307
320
|
|
|
308
|
-
def add_item(item, level, indent):
|
|
321
|
+
def add_item(item, level, indent, parent_number=None):
|
|
309
322
|
global counter
|
|
310
323
|
n = str(counter)
|
|
311
324
|
counter += 1
|
|
312
325
|
suffix = ""
|
|
313
326
|
if item.get("id") in undecomposed_ids:
|
|
314
327
|
suffix = " [needs decomposition -- no children on the board yet]"
|
|
315
|
-
numbering[n] = {"item": item, "level": level, "checked": True}
|
|
328
|
+
numbering[n] = {"item": item, "level": level, "checked": True, "children": []}
|
|
316
329
|
layout.append({"kind": "item", "number": n, "level": level, "indent": indent, "suffix": suffix})
|
|
330
|
+
if parent_number is not None:
|
|
331
|
+
numbering[parent_number]["children"].append(n)
|
|
317
332
|
return n
|
|
318
333
|
|
|
319
334
|
|
|
@@ -328,7 +343,7 @@ def append_suffix(extra):
|
|
|
328
343
|
|
|
329
344
|
|
|
330
345
|
for e in epics:
|
|
331
|
-
add_item(e, "epic", INDENT["epic"])
|
|
346
|
+
e_num = add_item(e, "epic", INDENT["epic"])
|
|
332
347
|
child_stories = stories_by_epic.get(e["id"], [])
|
|
333
348
|
story_count = len(child_stories)
|
|
334
349
|
task_count = sum(len(tasks_by_story.get(s["id"], [])) for s in child_stories)
|
|
@@ -340,23 +355,23 @@ for e in epics:
|
|
|
340
355
|
append_suffix(", ".join(parts))
|
|
341
356
|
|
|
342
357
|
for s in child_stories:
|
|
343
|
-
add_item(s, "story", INDENT["story"])
|
|
358
|
+
s_num = add_item(s, "story", INDENT["story"], parent_number=e_num)
|
|
344
359
|
child_tasks = tasks_by_story.get(s["id"], [])
|
|
345
360
|
if child_tasks:
|
|
346
361
|
append_suffix(pluralize_task(len(child_tasks)))
|
|
347
362
|
for t in child_tasks:
|
|
348
|
-
add_item(t, "task", INDENT["task"])
|
|
363
|
+
add_item(t, "task", INDENT["task"], parent_number=s_num)
|
|
349
364
|
|
|
350
365
|
if orphan_stories:
|
|
351
366
|
layout.append({"kind": "header", "text": ""})
|
|
352
367
|
layout.append({"kind": "header", "text": "-- Directly Selected Stories (no epic in this selection) --"})
|
|
353
368
|
for s in orphan_stories:
|
|
354
|
-
add_item(s, "story", INDENT["story"])
|
|
369
|
+
s_num = add_item(s, "story", INDENT["story"])
|
|
355
370
|
child_tasks = tasks_by_story.get(s["id"], [])
|
|
356
371
|
if child_tasks:
|
|
357
372
|
append_suffix(pluralize_task(len(child_tasks)))
|
|
358
373
|
for t in child_tasks:
|
|
359
|
-
add_item(t, "task", INDENT["task"])
|
|
374
|
+
add_item(t, "task", INDENT["task"], parent_number=s_num)
|
|
360
375
|
|
|
361
376
|
if orphan_tasks:
|
|
362
377
|
layout.append({"kind": "header", "text": ""})
|
|
@@ -644,18 +659,40 @@ if invalid:
|
|
|
644
659
|
print(f"STATE_FILE: {state_file_path}", file=sys.stderr)
|
|
645
660
|
sys.exit(1)
|
|
646
661
|
|
|
662
|
+
def apply_cascade(num, value):
|
|
663
|
+
"""Set `num`'s checked state to `value`, then recurse into every
|
|
664
|
+
number in its `children` list (a story's tasks; an epic's stories,
|
|
665
|
+
which recurse further into their own tasks). Strictly downward —
|
|
666
|
+
never touches a parent. A leaf task has an empty `children` list, so
|
|
667
|
+
this degenerates to exactly the old single-flag assignment for the
|
|
668
|
+
non-cascading base case."""
|
|
669
|
+
numbering[num]["checked"] = value
|
|
670
|
+
for child in numbering[num].get("children", []):
|
|
671
|
+
apply_cascade(child, value)
|
|
672
|
+
|
|
673
|
+
|
|
647
674
|
# All-or-nothing application, de-duplicated (first-seen wins on dupes).
|
|
675
|
+
# Resulting values are computed from PRE-mutation state in a first pass,
|
|
676
|
+
# then applied (with cascade) in a second pass -- this avoids a
|
|
677
|
+
# parent-then-child (or child-then-parent) double-toggle artifact when a
|
|
678
|
+
# single reply lists both a parent and one of its own descendants, e.g.
|
|
679
|
+
# bare-number toggle "5,6" where 6 is a child of 5.
|
|
648
680
|
seen = set()
|
|
681
|
+
pending = []
|
|
649
682
|
for tok in valid_tokens:
|
|
650
683
|
if tok in seen:
|
|
651
684
|
continue
|
|
652
685
|
seen.add(tok)
|
|
653
686
|
if action == "check":
|
|
654
|
-
|
|
687
|
+
value = True
|
|
655
688
|
elif action == "uncheck":
|
|
656
|
-
|
|
689
|
+
value = False
|
|
657
690
|
else:
|
|
658
|
-
|
|
691
|
+
value = not numbering[tok]["checked"]
|
|
692
|
+
pending.append((tok, value))
|
|
693
|
+
|
|
694
|
+
for tok, value in pending:
|
|
695
|
+
apply_cascade(tok, value)
|
|
659
696
|
|
|
660
697
|
state["numbering"] = numbering
|
|
661
698
|
with open(state_file_path, "w", encoding="utf-8") as f:
|
package/skills/lgtm/SKILL.md
CHANGED
package/skills/pi-plan/SKILL.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: pi-plan
|
|
2
|
+
name: j:pi-plan
|
|
3
3
|
description: Define or expand project Epics in PROJECT_SUMMARY.md. Use this at the start of a project to establish its foundation, AND whenever the user wants to add major new features, plan a significant new area of work, or make epic-level changes to an existing project. Trigger whenever you hear things like "new feature area", "big change", "new epic", "expand the project", "add a major capability", or "plan a new phase" — even mid-project.
|
|
4
4
|
keywords:
|
|
5
5
|
- epic
|
package/skills/proceed/SKILL.md
CHANGED
package/skills/publish/SKILL.md
CHANGED
|
@@ -99,11 +99,33 @@ Run the adapter phases in this exact order:
|
|
|
99
99
|
```yaml
|
|
100
100
|
permissions:
|
|
101
101
|
id-token: write
|
|
102
|
-
contents:
|
|
102
|
+
contents: write
|
|
103
103
|
```
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
(`contents: write` — bumped from `read` — is required so the `publish` and
|
|
105
|
+
`stage` jobs can push the tags described below; this is the CI's own token
|
|
106
|
+
gaining write access to tag *its own* repository, nothing else, and no new
|
|
107
|
+
secret or credential is introduced) and runs `npm publish --provenance` to
|
|
108
|
+
attach a build provenance attestation to the published package. In
|
|
109
|
+
`--dry-run` mode, print the rendered YAML to stdout and exit 0 without
|
|
110
|
+
writing any file.
|
|
111
|
+
|
|
112
|
+
Each job also gains a final step, gated on `if: success()` so a failed
|
|
113
|
+
publish/stage never creates or moves a tag:
|
|
114
|
+
- **`publish` job — "Tag prod release and remove stage tag":** reads the
|
|
115
|
+
version from `package.json`, tags the checked-out commit `v<version>`
|
|
116
|
+
(no force — this tag is immutable; a genuine collision fails loudly
|
|
117
|
+
rather than silently moving a prod tag), pushes it, then best-effort
|
|
118
|
+
deletes the corresponding `v<version>-stage` tag both locally and on the
|
|
119
|
+
remote (tolerating its absence, e.g. a prod publish that skipped
|
|
120
|
+
staging).
|
|
121
|
+
- **`stage` job — "Tag stage release":** reads the version the same way
|
|
122
|
+
and tags the checked-out commit `v<version>-stage` — a **mutable**
|
|
123
|
+
pointer, force-created (`git tag -f`) and force-pushed, so re-staging the
|
|
124
|
+
same version moves the tag rather than failing.
|
|
125
|
+
|
|
126
|
+
Both new steps configure a `github-actions[bot]` git identity
|
|
127
|
+
(`user.name`/`user.email`) before tagging, since no prior step in the
|
|
128
|
+
workflow sets one.
|
|
107
129
|
|
|
108
130
|
3. **`commit-workflow`** — write the generated YAML to `<workflow_path>`
|
|
109
131
|
(creating the `.github/workflows/` directory if needed) and commit it with:
|
|
@@ -172,7 +172,7 @@ on:
|
|
|
172
172
|
|
|
173
173
|
permissions:
|
|
174
174
|
id-token: write
|
|
175
|
-
contents:
|
|
175
|
+
contents: write
|
|
176
176
|
|
|
177
177
|
jobs:
|
|
178
178
|
publish:
|
|
@@ -194,6 +194,17 @@ jobs:
|
|
|
194
194
|
- name: Publish to npm
|
|
195
195
|
run: npm publish --provenance --access ${NPM_ACCESS} --tag ${DIST_TAG}
|
|
196
196
|
|
|
197
|
+
- name: Tag prod release and remove stage tag
|
|
198
|
+
if: success()
|
|
199
|
+
run: |
|
|
200
|
+
git config user.name "github-actions[bot]"
|
|
201
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
202
|
+
VERSION="\$(node -p "require('./package.json').version")"
|
|
203
|
+
git tag "v\${VERSION}"
|
|
204
|
+
git push origin "v\${VERSION}"
|
|
205
|
+
git tag -d "v\${VERSION}-stage" 2>/dev/null || true
|
|
206
|
+
git push origin ":refs/tags/v\${VERSION}-stage" 2>/dev/null || true
|
|
207
|
+
|
|
197
208
|
stage:
|
|
198
209
|
if: \${{ github.event.inputs.mode == 'stage' }}
|
|
199
210
|
runs-on: ubuntu-latest
|
|
@@ -212,6 +223,15 @@ jobs:
|
|
|
212
223
|
|
|
213
224
|
- name: Stage to npm
|
|
214
225
|
run: npm stage publish --provenance --access ${NPM_ACCESS} --tag ${DIST_TAG}
|
|
226
|
+
|
|
227
|
+
- name: Tag stage release
|
|
228
|
+
if: success()
|
|
229
|
+
run: |
|
|
230
|
+
git config user.name "github-actions[bot]"
|
|
231
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
232
|
+
VERSION="\$(node -p "require('./package.json').version")"
|
|
233
|
+
git tag -f "v\${VERSION}-stage"
|
|
234
|
+
git push origin "v\${VERSION}-stage" --force
|
|
215
235
|
EOF
|
|
216
236
|
)"
|
|
217
237
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: reconcile
|
|
2
|
+
name: j:reconcile
|
|
3
3
|
description: Reconcile the scrum board with actual implementation state. Cross-checks every task's board status against git history and worktrees, merges orphaned worktree branches, demotes unimplemented "Done" items, promotes secretly-implemented items, flags code with no board provenance and offers /uncharted segment for it, and cleans stale entries from todo.md. Use when the board feels out of sync, after a big merge session, when tasks were completed outside the normal workflow, or when todo.md has grown stale. Trigger on phrases like "sync the board", "clean up the board", "reconcile", "board is out of date", "todo is stale", or "check what's really done".
|
|
4
4
|
metadata:
|
|
5
5
|
prefered_agent: scrum-master
|
package/skills/redo/SKILL.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: redo
|
|
2
|
+
name: j:redo
|
|
3
3
|
description: Redo parts or entire previous implementations identified by a commit SHA or an Epic/Story number (e.g. E01, E02_S03). Expects an identifier and a description of what to redo and why. Use when the user wants to revisit, rework, or rewrite previously completed work, including updating all affected documentation.
|
|
4
4
|
keywords:
|
|
5
5
|
- redo
|
package/skills/skillify/SKILL.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: skillify
|
|
2
|
+
name: j:skillify
|
|
3
3
|
description: Refactor one or more existing skills into a cleaner, more maintainable structure — extracting hardcoded content into asset files, offloading deterministic steps into scripts, and reorganizing the skill body to reflect the leaner result. Use this whenever the user wants to clean up, improve, or restructure an existing skill, mentions that a skill has hardcoded content that could be templated, or asks to "skillify", "refactor", or "tidy up" a skill. Trigger even if the user just pastes a skill and says something like "can we make this better?".
|
|
4
4
|
---
|
|
5
5
|
|
package/skills/spinoff/SKILL.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: spinoff
|
|
2
|
+
name: j:spinoff
|
|
3
3
|
description: Capture a diverging topic mid-conversation. Collects context and a mandatory origin, optionally runs /brainstorm for prerequisites, saves an /idea entry, and returns focus to the primary thread.
|
|
4
4
|
keywords:
|
|
5
5
|
- spinoff
|
package/skills/status/SKILL.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: status
|
|
2
|
+
name: j:status
|
|
3
3
|
description: Print a human-readable summary of the entire scrum board — all epics, stories, and tasks with their statuses — plus any open rapports and unprocessed queue triggers. Use when you want a quick overview of project state without reading raw files.
|
|
4
4
|
keywords:
|
|
5
5
|
- status
|
package/skills/todo/SKILL.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: todo
|
|
2
|
+
name: j:todo
|
|
3
3
|
description: Add missions to the project todo list (project/todo.md), optionally linking them to epics and stories. Loops until the user is done, then optionally executes the list.
|
|
4
4
|
keywords:
|
|
5
5
|
- todo
|
|
@@ -16,6 +16,16 @@ metadata:
|
|
|
16
16
|
|
|
17
17
|
# Todo — Add Missions to the Todo List
|
|
18
18
|
|
|
19
|
+
## `--trivial` Flag
|
|
20
|
+
|
|
21
|
+
**Syntax:** `/todo --trivial <description>` — optionally combined with the same `: <Epic no.>_<Story no.>` linkage syntax normal `/todo` entries use, e.g. `/todo --trivial Fix typo in error message: E12_S03`.
|
|
22
|
+
|
|
23
|
+
When `--trivial` is present, the mission is written as a **fully-formed task board file immediately** (not just a raw `todo.md` line deferred to `/do`'s own breakdown pass) with `execution_scope: inline` forced unconditionally — no threshold computation is consulted for the scope value itself. See step 4.5 below for the mechanics.
|
|
24
|
+
|
|
25
|
+
**Human-only override.** `--trivial` is invoked by a human typing `/todo --trivial ...` — it is never applied by the scrum-master to itself during autonomous story/epic breakdown elsewhere (e.g. `/jenga`'s Phase 0.5, or `/do`'s own scrum-master decomposition step in `skills/do/SKILL.md` step 3). Those paths keep using the normal heuristic-only `execution_scope` assignment documented in `agents/scrum-master.md`'s Execution Scope Assignment section, unmodified by this flag.
|
|
26
|
+
|
|
27
|
+
**Fallback on failure is out of scope here.** If a `--trivial`-forced inline run fails the smoke-harness or shows scope creep at dispatch time, `/do`'s own `--trivial` handling (a separate task, E32_S14_T02) is responsible for falling back to the full `task` pipeline — this skill only ever writes the initial forced-inline task.
|
|
28
|
+
|
|
19
29
|
## Instructions
|
|
20
30
|
|
|
21
31
|
1. **Ensure `project/todo.md` exists** — If it doesn't exist, it will be auto-created by `todo_manager.sh` — no manual action needed.
|
|
@@ -24,6 +34,7 @@ metadata:
|
|
|
24
34
|
- Where do you want to do this?
|
|
25
35
|
- What would you like to do?
|
|
26
36
|
- What is the goal?
|
|
37
|
+
- (If `--trivial` was passed, these answers still apply — `--trivial` changes how the mission is written to the board in step 4.5, not what's asked here.)
|
|
27
38
|
|
|
28
39
|
3. **Classify the mission** — Check if it fits into:
|
|
29
40
|
- An existing story
|
|
@@ -31,18 +42,44 @@ metadata:
|
|
|
31
42
|
- A new story inside a new Epic
|
|
32
43
|
- None of the above
|
|
33
44
|
|
|
45
|
+
**`--trivial` requires an existing (or, in this same step, newly-created) story to attach to.** It forces the scope of a single task, not a container — if the mission has no story yet, create it now via step 4 below exactly as normal, then continue to step 4.5. `--trivial` cannot be used for "None of the above."
|
|
46
|
+
|
|
34
47
|
4. **Update project documentation** — Add the mission to the appropriate files under `project/board/epics/` and `project/board/stories/` if applicable.
|
|
35
48
|
- If the mission involves implementing or modifying a skill, apply the **Skill Implementation Principle — Scripts Over Inline Logic** (see `CLAUDE.md` / `AGENTS.md`): note in the story/task's acceptance criteria that deterministic, repeatable steps must be offloaded to scripts under `skills/<name>/scripts/` (or `scripts/`) rather than encoded as inline agent instructions in `SKILL.md`.
|
|
36
49
|
- If the user indicates the mission is high-risk, or explicitly asks to flag it, set an elevated caution tier directly on the story or task frontmatter: `crucial_level` (one of `advisory`, `gated`, `locked` — see `templates/SCRUM_BOARD_SCHEMA.md` for valid values and their meaning), `crucial_set_by: user`, and `crucial_note` capturing the user's stated reason. This user-initiated flag is written immediately — it does not require the confirm-before-write gate, which applies only to scrum-master-*proposed* caution tiers (a separate, heuristic-driven path).
|
|
37
50
|
|
|
38
|
-
5. **
|
|
51
|
+
4.5. **If `--trivial` was passed, create the task now** (skip step 5 — this step writes the todo.md entry itself):
|
|
52
|
+
|
|
53
|
+
a. **Estimate the change**, using the same judgment `agents/scrum-master.md`'s Execution Scope Assignment heuristic applies: how many files will this mission likely touch, and roughly how many lines. This is a reasoning step, not a script step — do not guess wildly, but a rough, honest estimate is sufficient.
|
|
54
|
+
|
|
55
|
+
b. **Determine `computed_tier`** — what `execution_scope` the normal heuristic would have assigned to this estimate, purely for the audit trail (it is never written as the actual `execution_scope`, which is always forced to `inline`):
|
|
56
|
+
- Read `inline_max_files`, `inline_max_lines`, and `story_max_files` from `project/configs/scope-thresholds.json` at run time — never hardcode these numbers here.
|
|
57
|
+
- Apply `agents/scrum-master.md`'s `inline` / `story` / `task` heuristics (file count vs. `inline_max_files`, line estimate vs. `inline_max_lines`, contention and cross-cutting checks for `story`) to the estimate from (a). The result is `computed_tier` — one of `inline`, `task`, or `story` (never `epic` — the heuristic never autonomously computes `epic`).
|
|
58
|
+
|
|
59
|
+
c. **Run the helper script**, which handles everything mechanical — next task-ID assignment, writing the task board file with `execution_scope: inline` forced, registering the new task ID into the parent story's `tasks:` frontmatter list, and adding the `project/todo.md` entry using the full task ID (so `/do` routes straight into its Inline Execution Path with no redundant breakdown pass):
|
|
60
|
+
```
|
|
61
|
+
bash skills/todo/scripts/add_trivial_task.sh \
|
|
62
|
+
--story <E##_S##> \
|
|
63
|
+
--title "<mission title>" \
|
|
64
|
+
--description "<mission description>" \
|
|
65
|
+
--criteria "<criterion 1>|<criterion 2>|..." \
|
|
66
|
+
--computed-tier <inline|task|story> \
|
|
67
|
+
--est-files <N> \
|
|
68
|
+
--est-lines <M> \
|
|
69
|
+
[--prerequisites "<text>"]
|
|
70
|
+
```
|
|
71
|
+
The script writes `scope_rationale` in the form `"forced inline via --trivial; computed scope would have been '<computed_tier>' — estimated <N> files, ~<M> lines"` and sets `jenga_assigned: false` with a matching `override_justification`, so `/do` step 4.1's existing override-validation logs the override on dispatch — no separate acknowledgement step needed here.
|
|
72
|
+
On success the script prints the new task ID to stdout; on failure (e.g. the story doesn't exist yet, or `--computed-tier` is invalid) it exits non-zero with an explanatory message on stderr — surface that to the user rather than retrying blindly.
|
|
73
|
+
d. Continue to step 6 (skip step 5 — the script already added the `todo.md` entry).
|
|
74
|
+
|
|
75
|
+
5. **Add to `project/todo.md`** by running (skip this step if step 4.5 already ran):
|
|
39
76
|
```
|
|
40
77
|
bash scripts/todo_manager.sh add '<mission title>: <Epic no.>_<Story no.>'
|
|
41
78
|
```
|
|
42
79
|
The epic and story reference is only required if the mission is assigned to one.
|
|
43
80
|
|
|
44
81
|
6. **Ask the user**: "Add another todo" or "Done"?
|
|
45
|
-
- If **add another** — go back to step 2.
|
|
82
|
+
- If **add another** — go back to step 2. (`--trivial` applies only to the mission it was passed with — it does not carry over to the next mission unless the user says `--trivial` again.)
|
|
46
83
|
- If **done** — ask if they want to execute the todo list.
|
|
47
84
|
- If **yes** — invoke the `/do` skill.
|
|
48
85
|
- If **no** — exit.
|