@jenga-ai/agent 3.4.0 → 3.6.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 +37 -3
- 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 +6 -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/ui/dist/assets/{index-CdK3Qrep.css → index-BVR_7Owg.css} +1 -1
- package/project/app/ui/dist/assets/index-CtU2xLQm.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 +1 -1
- package/scripts/apply-j-prefix.sh +46 -5
- package/scripts/audit-twin-divergence.sh +73 -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 +330 -0
- package/scripts/generate-legacy-shipped-paths.js +2 -2
- package/scripts/idea_manager.sh +258 -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/repoint-skill-refs.sh +539 -0
- package/scripts/todo_manager.sh +1 -1
- 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-clearify/SKILL.md +2 -2
- package/skills/j-close-story/scripts/check-privatized.sh +4 -4
- package/skills/j-distribute/CONFIG_SCHEMA.md +82 -5
- package/skills/j-do/SKILL.md +101 -17
- package/skills/j-doc-sync/SKILL.md +1 -0
- 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-idea/SKILL.md +78 -6
- package/skills/j-idea/assets/idea_template.md +1 -1
- package/skills/j-improve/SKILL.md +1 -1
- package/skills/j-init/SKILL.md +53 -14
- package/skills/j-init/assets/.gitignore_template +1 -2
- package/skills/j-init/assets/scope-thresholds_template.json +5 -2
- package/skills/j-init/scripts/apply-scaffold-visibility.sh +192 -0
- package/skills/j-init/scripts/init.sh +22 -8
- package/skills/j-playbook/SKILL.md +1 -1
- package/skills/j-publish/SKILL.md +1 -1
- 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-reconcile/SKILL.md +2 -2
- package/skills/j-reconcile/scripts/detect-unlinked-code.sh +11 -11
- package/skills/j-redo/SKILL.md +1 -1
- package/skills/j-skillify/assets/init-new/assets/.gitignore_template +1 -2
- package/skills/j-spinoff/SKILL.md +1 -1
- package/skills/j-status/SKILL.md +15 -0
- package/skills/j-todo/SKILL.md +3 -1
- package/skills/j-uncharted/SKILL.md +55 -8
- package/skills/j-uncharted/assets/NODE_QUESTION_TEMPLATE.md +69 -0
- package/skills/j-uncharted/scripts/detect-dependencies.sh +1 -1
- package/skills/j-uncharted/scripts/detect-tests.sh +1 -1
- package/skills/j-uncharted/scripts/elicitation-state.sh +46 -8
- package/skills/j-uncharted/scripts/validate-proposed-items.sh +1 -1
- package/skills/j-wtf/SKILL.md +1 -1
- package/skills/jenga/SKILL.md +43 -9
- 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.sh +1 -1
- package/skills/jenga/scripts/load-playbooks.sh +23 -11
- package/skills/jenga/scripts/match-playbook.sh +1 -1
- package/templates/SCRUM_BOARD_SCHEMA.md +14 -1
- package/templates/SKILL_TEMPLATE.md +12 -0
- package/templates/permission-levels/level-4-elevated.json +1 -1
- package/templates/permission-levels/level-5-unrestricted.json +1 -1
- package/templates/playbook-types.json +34 -6
- package/project/app/ui/dist/assets/index-7fj-vllY.js +0 -104
- 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
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# -----------------------------------------------------------------------------
|
|
3
|
+
# skills/j-gitignore/scripts/untrack-jenga-files.sh
|
|
4
|
+
#
|
|
5
|
+
# Removes Jenga-owned paths from git WITHOUT removing them from disk —
|
|
6
|
+
# `git rm -r --cached`, never a plain `git rm`. The files stay exactly where
|
|
7
|
+
# they are; git simply stops tracking them, and the .gitignore entries written
|
|
8
|
+
# by repair-gitignore.sh then keep them from coming back.
|
|
9
|
+
#
|
|
10
|
+
# Run repair-gitignore.sh FIRST. .gitignore has no effect on an already-tracked
|
|
11
|
+
# file, so untracking without the entries in place just means the next
|
|
12
|
+
# `git add -A` re-adds everything.
|
|
13
|
+
#
|
|
14
|
+
# ─── What "removed from origin" does and does not mean ──────────────────────
|
|
15
|
+
# With --commit --push, these paths disappear from the branch TIP on the
|
|
16
|
+
# remote: clone it fresh and they are gone. Earlier commits are UNTOUCHED —
|
|
17
|
+
# the blobs remain reachable in history, so this is not a secret-scrubbing
|
|
18
|
+
# tool. If something sensitive was committed, treat it as compromised, rotate
|
|
19
|
+
# it, and use a history-rewriting tool (git-filter-repo) separately.
|
|
20
|
+
#
|
|
21
|
+
# Invoked via `bash`, not executed directly.
|
|
22
|
+
#
|
|
23
|
+
# Usage:
|
|
24
|
+
# untrack-jenga-files.sh [project_root]
|
|
25
|
+
# [--tiers scaffold,hybrid,board,optional]
|
|
26
|
+
# [--dry-run] [--commit] [--push]
|
|
27
|
+
# [--allow-dirty-index]
|
|
28
|
+
#
|
|
29
|
+
# Options:
|
|
30
|
+
# --dry-run List what would be untracked; touch nothing.
|
|
31
|
+
# --commit Commit the removals. Without it, changes are left
|
|
32
|
+
# staged for you to inspect and commit yourself.
|
|
33
|
+
# --push Push to the branch's upstream. Requires --commit.
|
|
34
|
+
# Never implied — this is the only outward-facing step.
|
|
35
|
+
# --allow-dirty-index Proceed even if unrelated changes are already staged.
|
|
36
|
+
# Off by default so this can never sweep your staged
|
|
37
|
+
# work into its commit.
|
|
38
|
+
#
|
|
39
|
+
# Exit codes:
|
|
40
|
+
# 0 Success (including "nothing tracked — nothing to do")
|
|
41
|
+
# 1 Bad usage or missing prerequisite
|
|
42
|
+
# 2 Invalid tier
|
|
43
|
+
# 3 git operation failed
|
|
44
|
+
# 4 Refused: index already dirty, or --push without --commit
|
|
45
|
+
# -----------------------------------------------------------------------------
|
|
46
|
+
|
|
47
|
+
set -uo pipefail
|
|
48
|
+
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/_catalog.sh"
|
|
49
|
+
|
|
50
|
+
info() { echo "[untrack] $*"; }
|
|
51
|
+
warn() { echo "[untrack] WARNING: $*"; }
|
|
52
|
+
err() { echo "[untrack] ERROR: $*" >&2; }
|
|
53
|
+
|
|
54
|
+
PROJECT_ROOT=""
|
|
55
|
+
TIERS="scaffold"
|
|
56
|
+
DRY_RUN=0
|
|
57
|
+
DO_COMMIT=0
|
|
58
|
+
DO_PUSH=0
|
|
59
|
+
ALLOW_DIRTY=0
|
|
60
|
+
|
|
61
|
+
while [ $# -gt 0 ]; do
|
|
62
|
+
case "$1" in
|
|
63
|
+
--tiers) TIERS="${2:-}"; shift 2 ;;
|
|
64
|
+
--tiers=*) TIERS="${1#*=}"; shift ;;
|
|
65
|
+
--dry-run) DRY_RUN=1; shift ;;
|
|
66
|
+
--commit) DO_COMMIT=1; shift ;;
|
|
67
|
+
--push) DO_PUSH=1; shift ;;
|
|
68
|
+
--allow-dirty-index) ALLOW_DIRTY=1; shift ;;
|
|
69
|
+
-h|--help)
|
|
70
|
+
echo "Usage: $(basename "$0") [project_root] [--tiers <csv>] [--dry-run] [--commit] [--push] [--allow-dirty-index]"
|
|
71
|
+
exit 0 ;;
|
|
72
|
+
-*) err "Unknown option: $1"; exit 1 ;;
|
|
73
|
+
*)
|
|
74
|
+
if [ -n "$PROJECT_ROOT" ]; then err "More than one project root given."; exit 1; fi
|
|
75
|
+
PROJECT_ROOT="$1"; shift ;;
|
|
76
|
+
esac
|
|
77
|
+
done
|
|
78
|
+
|
|
79
|
+
if [ "$DO_PUSH" -eq 1 ] && [ "$DO_COMMIT" -eq 0 ]; then
|
|
80
|
+
err "--push requires --commit. There would be nothing to push."
|
|
81
|
+
exit 4
|
|
82
|
+
fi
|
|
83
|
+
|
|
84
|
+
PROJECT_ROOT="${PROJECT_ROOT:-$PWD}"
|
|
85
|
+
validate_tiers "$TIERS" || exit 2
|
|
86
|
+
resolve_root "$PROJECT_ROOT" || exit 1
|
|
87
|
+
load_catalog "$TIERS" || exit 1
|
|
88
|
+
|
|
89
|
+
# ─── Refuse to run on a dirty index ─────────────────────────────────────────
|
|
90
|
+
# .gitignore is the one staged path that is never "unrelated": it is the
|
|
91
|
+
# companion change repair-gitignore.sh just made, and untracking without it is
|
|
92
|
+
# pointless. Staged alone, it is allowed through and folded into this commit.
|
|
93
|
+
# Anything else staged is refused.
|
|
94
|
+
if [ "$ALLOW_DIRTY" -eq 0 ] && [ "$DRY_RUN" -eq 0 ]; then
|
|
95
|
+
if ! git diff --cached --quiet 2>/dev/null; then
|
|
96
|
+
staged="$(git diff --cached --name-only)"
|
|
97
|
+
if [ "$staged" = ".gitignore" ]; then
|
|
98
|
+
info "Staged .gitignore detected — folding the ignore-rule change into this commit."
|
|
99
|
+
else
|
|
100
|
+
err "The index already has staged changes:"
|
|
101
|
+
printf '%s\n' "$staged" | sed 's/^/ /' >&2
|
|
102
|
+
err "Refusing to run — a --commit here would sweep them into this commit."
|
|
103
|
+
err "Commit or unstage them first, or pass --allow-dirty-index if you"
|
|
104
|
+
err "genuinely want them included."
|
|
105
|
+
exit 4
|
|
106
|
+
fi
|
|
107
|
+
fi
|
|
108
|
+
fi
|
|
109
|
+
|
|
110
|
+
# ─── Find what is actually tracked ──────────────────────────────────────────
|
|
111
|
+
TRACKED_PATHS=()
|
|
112
|
+
TOTAL_FILES=0
|
|
113
|
+
for i in "${!CATALOG_PATHS[@]}"; do
|
|
114
|
+
path="${CATALOG_PATHS[$i]}"
|
|
115
|
+
count="$(git ls-files -- "$path" 2>/dev/null | wc -l | tr -d ' ')"
|
|
116
|
+
if [ "${count:-0}" -gt 0 ]; then
|
|
117
|
+
TRACKED_PATHS+=("$path")
|
|
118
|
+
TOTAL_FILES=$((TOTAL_FILES + count))
|
|
119
|
+
printf ' %-36s %s tracked file(s)\n' "$path" "$count"
|
|
120
|
+
fi
|
|
121
|
+
done
|
|
122
|
+
|
|
123
|
+
if [ "${#TRACKED_PATHS[@]}" -eq 0 ]; then
|
|
124
|
+
info "No catalog path (tiers: ${TIERS}) is tracked — nothing to untrack."
|
|
125
|
+
exit 0
|
|
126
|
+
fi
|
|
127
|
+
|
|
128
|
+
echo
|
|
129
|
+
info "${#TRACKED_PATHS[@]} path(s), ${TOTAL_FILES} file(s) would stop being tracked."
|
|
130
|
+
info "All of them remain on disk — this uses 'git rm -r --cached'."
|
|
131
|
+
|
|
132
|
+
if [ "$DRY_RUN" -eq 1 ]; then
|
|
133
|
+
info "--dry-run — nothing changed."
|
|
134
|
+
exit 0
|
|
135
|
+
fi
|
|
136
|
+
|
|
137
|
+
# ─── Untrack ────────────────────────────────────────────────────────────────
|
|
138
|
+
for path in "${TRACKED_PATHS[@]}"; do
|
|
139
|
+
if ! git rm -r --cached --quiet -- "$path"; then
|
|
140
|
+
err "git rm --cached failed for '${path}'. The index may be partially staged;"
|
|
141
|
+
err "inspect with 'git status' and 'git reset' to back out."
|
|
142
|
+
exit 3
|
|
143
|
+
fi
|
|
144
|
+
info "Untracked: ${path}"
|
|
145
|
+
done
|
|
146
|
+
|
|
147
|
+
# Verify nothing was deleted from disk before reporting success.
|
|
148
|
+
MISSING=0
|
|
149
|
+
for path in "${TRACKED_PATHS[@]}"; do
|
|
150
|
+
probe="${path%/}"
|
|
151
|
+
if [ ! -e "$probe" ]; then
|
|
152
|
+
warn "'${probe}' is not on disk. It was already absent before this ran"
|
|
153
|
+
warn "(git tracked it, the working tree did not), so nothing was lost here."
|
|
154
|
+
MISSING=$((MISSING + 1))
|
|
155
|
+
fi
|
|
156
|
+
done
|
|
157
|
+
[ "$MISSING" -eq 0 ] && info "Verified: every untracked path is still present on disk."
|
|
158
|
+
|
|
159
|
+
if [ "$DO_COMMIT" -eq 0 ]; then
|
|
160
|
+
echo
|
|
161
|
+
info "Changes are STAGED but not committed. Review with:"
|
|
162
|
+
info " git status"
|
|
163
|
+
info " git diff --cached --stat"
|
|
164
|
+
info "Then commit yourself, or re-run with --commit."
|
|
165
|
+
exit 0
|
|
166
|
+
fi
|
|
167
|
+
|
|
168
|
+
# ─── Commit ─────────────────────────────────────────────────────────────────
|
|
169
|
+
COMMIT_MSG="chore(jenga): untrack Jenga-owned files, keep them on disk
|
|
170
|
+
|
|
171
|
+
Removes the Jenga scaffold from version control via 'git rm --cached' and
|
|
172
|
+
relies on the j.gitignore managed block to keep it out. Files are untouched
|
|
173
|
+
on disk. Tiers: ${TIERS}.
|
|
174
|
+
|
|
175
|
+
Note: this changes the branch tip only — earlier commits still contain these
|
|
176
|
+
paths."
|
|
177
|
+
|
|
178
|
+
if ! git commit -q -m "$COMMIT_MSG"; then
|
|
179
|
+
err "git commit failed. Your removals are still staged."
|
|
180
|
+
exit 3
|
|
181
|
+
fi
|
|
182
|
+
info "Committed: $(git rev-parse --short HEAD)"
|
|
183
|
+
|
|
184
|
+
if [ "$DO_PUSH" -eq 0 ]; then
|
|
185
|
+
echo
|
|
186
|
+
info "Not pushed. The remote still has these files until you push."
|
|
187
|
+
exit 0
|
|
188
|
+
fi
|
|
189
|
+
|
|
190
|
+
# ─── Push ───────────────────────────────────────────────────────────────────
|
|
191
|
+
BRANCH="$(git rev-parse --abbrev-ref HEAD)"
|
|
192
|
+
UPSTREAM="$(git rev-parse --abbrev-ref --symbolic-full-name '@{u}' 2>/dev/null)"
|
|
193
|
+
|
|
194
|
+
if [ -z "$UPSTREAM" ]; then
|
|
195
|
+
err "Branch '${BRANCH}' has no upstream — refusing to guess a remote."
|
|
196
|
+
err "Set one, then push yourself: git push -u origin ${BRANCH}"
|
|
197
|
+
err "The commit itself succeeded and is safe on your local branch."
|
|
198
|
+
exit 3
|
|
199
|
+
fi
|
|
200
|
+
|
|
201
|
+
info "Pushing ${BRANCH} → ${UPSTREAM} ..."
|
|
202
|
+
if ! git push; then
|
|
203
|
+
err "Push failed — most likely the branch is behind its upstream."
|
|
204
|
+
err "Reconcile (git pull --rebase) and push yourself. The commit is safe locally."
|
|
205
|
+
exit 3
|
|
206
|
+
fi
|
|
207
|
+
|
|
208
|
+
info "Pushed. These paths are gone from ${UPSTREAM}'s tip."
|
|
209
|
+
info "They REMAIN in earlier commits — this did not rewrite history."
|
|
210
|
+
exit 0
|
package/skills/j-idea/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: j.idea
|
|
3
|
-
description: Polyfill alias of the idea skill under a collision-safe directory name. Identical behavior to /idea — Capture a loosely-defined idea to project/ideas.md — a lightweight, "maybe someday" log with no board or promotion overhead. Use when the bare /idea form is shadowed by another tool's own built-in command of the same name.
|
|
3
|
+
description: Polyfill alias of the idea skill under a collision-safe directory name. Identical behavior to /idea — DEPRECATED - use the prefixed 'j-idea' skill instead. Capture a loosely-defined idea to project/ideas.md — a lightweight, "maybe someday" log with no board or promotion overhead. Use when the bare /idea form is shadowed by another tool's own built-in command of the same name.
|
|
4
4
|
keywords:
|
|
5
5
|
- idea
|
|
6
6
|
- capture idea
|
|
@@ -52,12 +52,84 @@ This file is generated/synced by `scripts/generate-j-alias.sh idea` from `skills
|
|
|
52
52
|
- **Promoting an idea** means re-running `/brainstorm` on it, which routes onward to `/btw` or `/todo` as normal. That routing behavior already exists and is out of scope for `/idea`.
|
|
53
53
|
- **Terminal idea states** are marked directly in `project/ideas.md` using the same HTML-comment tag convention `project/todo.md` uses for `RECONCILED`:
|
|
54
54
|
- `PROMOTED` — the idea was picked up via `/brainstorm` and turned into board work.
|
|
55
|
-
- `
|
|
55
|
+
- `REJECTED` — the idea was reviewed and dropped.
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
### Embedded Board ID
|
|
58
|
+
|
|
59
|
+
`PROMOTED`/`REJECTED` tags support an embedded board ID, so the idea→board-item link is
|
|
60
|
+
machine-readable directly from the tag itself, without needing a separate lookup:
|
|
61
|
+
|
|
62
|
+
- `<!-- PROMOTED: E##_S##[_T##] -->` — the `_T##` task suffix is optional; use whichever level
|
|
63
|
+
the idea was actually promoted into (an epic, a story, or a specific task).
|
|
64
|
+
- `<!-- REJECTED -->` — stays bare, with no embedded ID. A rejection has no resulting board
|
|
65
|
+
item to point at.
|
|
66
|
+
|
|
67
|
+
Example (mirroring `project/todo.md`'s tagging style):
|
|
68
|
+
```
|
|
69
|
+
Add dark mode toggle to settings page <!-- PROMOTED: E12_S03 -->
|
|
70
|
+
Add a settings-page keyboard shortcut cheat sheet <!-- PROMOTED: E12_S03_T02 -->
|
|
71
|
+
Rewrite onboarding copy in a more casual tone <!-- REJECTED -->
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Source-Rapport Link Convention
|
|
75
|
+
|
|
76
|
+
Some ideas originate from a rapport rather than being manually captured via `/idea` — e.g. when
|
|
77
|
+
scrum-master's `rapport_review` step (E35_S03) detects a distinct idea surfaced inside a
|
|
78
|
+
problem rapport and, on user confirmation, appends it to `project/ideas.md` the same way
|
|
79
|
+
`/idea` does. When that happens, the entry's source rapport is recorded with a second inline
|
|
80
|
+
HTML comment on the same line:
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
<!-- rapport: <path/to/rapport.md> -->
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Rules:
|
|
87
|
+
- Written at capture time, alongside the idea text, by whichever flow is adding the entry
|
|
88
|
+
(scrum-master's rapport-derived capture path; `/idea`'s own manual capture never has a source
|
|
89
|
+
rapport and omits this comment entirely).
|
|
90
|
+
- Left in place through promotion/rejection — the `rapport:` comment and the terminal
|
|
91
|
+
`PROMOTED`/`REJECTED` comment coexist on the same line, e.g.:
|
|
58
92
|
```
|
|
59
|
-
|
|
60
|
-
Rewrite onboarding copy in a more casual tone <!-- DISCARDED -->
|
|
93
|
+
Extract shared retry logic into a utility <!-- rapport: project/rapports/problems/E40_S02_T01-segment-remarks.md --> <!-- PROMOTED: E61_S01 -->
|
|
61
94
|
```
|
|
95
|
+
- Consumed by the outcome-record mechanism at promotion/rejection time: if a `rapport:` comment
|
|
96
|
+
is present on the line, that rapport is updated with the decision (and `[SPIKE]`-prefixed in
|
|
97
|
+
its title/header if not already, per `templates/SCRUM_BOARD_SCHEMA.md`'s `[SPIKE]` section);
|
|
98
|
+
if absent (a manually-captured `/idea` entry with no source rapport), a
|
|
99
|
+
`project/documentation/plans/<slug>_PROMOTED.md` or `_REJECTED.md` file is created instead.
|
|
100
|
+
- Verified compatible with `scripts/idea_manager.sh`'s `real_entries()` filtering: that function
|
|
101
|
+
only strips lines whose first non-whitespace characters are `<!--`; a trailing inline comment
|
|
102
|
+
on an otherwise real entry line is untouched and the line still counts as a real entry.
|
|
103
|
+
|
|
104
|
+
No agent invoked by `/idea` applies terminal (`PROMOTED`/`REJECTED`) tags or acts on them — that
|
|
105
|
+
is reserved for the promotion step (e.g. within `/brainstorm`) and, for rapport-sourced ideas,
|
|
106
|
+
scrum-master's rapport-review flow.
|
|
107
|
+
|
|
108
|
+
### Outcome-Record Mechanism (`idea_manager.sh`) — E35_S03_T03
|
|
109
|
+
|
|
110
|
+
`scripts/idea_manager.sh` implements the tagging and outcome-record behavior described above, via
|
|
111
|
+
four additional subcommands beyond `add`/`list`:
|
|
112
|
+
|
|
113
|
+
- `tag "<idea-text>" <PROMOTED:E##_S##[_T##]|REJECTED>` — writes the terminal tag onto the
|
|
114
|
+
`project/ideas.md` line matching `<idea-text>` (an exact/literal match; errors if zero or more
|
|
115
|
+
than one line matches, and errors if the line is already tagged).
|
|
116
|
+
- `get-id "<idea-text>"` — prints the embedded board ID from that line's `PROMOTED` tag (errors
|
|
117
|
+
if the line has no `PROMOTED` tag).
|
|
118
|
+
- `get-rapport "<idea-text>"` — prints the `rapport:` path recorded on that line, or nothing
|
|
119
|
+
(exit 0) if the line has no source-rapport comment.
|
|
120
|
+
- `resolve "<idea-text>" <promoted|rejected> [board_id]` — the full outcome-record mechanism in
|
|
121
|
+
one call: tags the line (as `tag` does), then either updates the idea's source rapport or, if
|
|
122
|
+
none is recorded, creates the `project/documentation/plans/` fallback file:
|
|
123
|
+
- **Source rapport present:** the rapport's `# Rapport: ...` title line is prefixed
|
|
124
|
+
`[SPIKE] ` if not already, and an `## Idea Outcome Record` section (decision, date, resulting
|
|
125
|
+
board ID if promoted, and the idea text) is appended to the rapport file.
|
|
126
|
+
- **No source rapport:** `project/documentation/plans/<slug>_PROMOTED.md` or `_REJECTED.md` is
|
|
127
|
+
created (idea text slugified, lowercased, capped at 60 characters), containing the same
|
|
128
|
+
decision/date/board-ID/idea-text content.
|
|
129
|
+
|
|
130
|
+
`board_id` is required for `promoted` (validated to start with `E<digits>`) and must be omitted
|
|
131
|
+
for `rejected` (a rejection has no resulting board item).
|
|
62
132
|
|
|
63
|
-
|
|
133
|
+
This is the mechanism itself, not the trigger — nothing currently calls `resolve` automatically.
|
|
134
|
+
A future promotion step (e.g. within `/brainstorm`'s routing, or scrum-master acting on a
|
|
135
|
+
rapport-sourced idea) is expected to invoke it once that trigger exists.
|
|
@@ -50,7 +50,7 @@ Assess whether you have enough context to evaluate current behavior against the
|
|
|
50
50
|
Invoke the `/examplify` skill. Specify clearly what you want it to find out — e.g. which code paths are exercised, what inputs/outputs look like, or what edge cases exist.
|
|
51
51
|
|
|
52
52
|
### 5. Run `/evaluate`
|
|
53
|
-
Copy `.agents/skills/evaluate/assets/evaluation_invokation_template.yml` and fill in:
|
|
53
|
+
Copy `.agents/skills/j-evaluate/assets/evaluation_invokation_template.yml` and fill in:
|
|
54
54
|
- `paths`: path(s) to the relevant example files
|
|
55
55
|
- `goal`: the confirmed target goal
|
|
56
56
|
|
package/skills/j-init/SKILL.md
CHANGED
|
@@ -101,13 +101,44 @@ run can never silently relocate directories or edit `.gitignore`.
|
|
|
101
101
|
> `.agents/`/`.claude/` convention), was built and then withdrawn before release —
|
|
102
102
|
> testing found it left board resolution and session-end hooks writing to two
|
|
103
103
|
> different trees. It is not offered here. See
|
|
104
|
-
> `skills/distribute/CONFIG_SCHEMA.md` for the root-cause note and the tracked
|
|
104
|
+
> `skills/j-distribute/CONFIG_SCHEMA.md` for the root-cause note and the tracked
|
|
105
105
|
> follow-up to reintroduce it once fixed.
|
|
106
106
|
|
|
107
|
-
Carry the chosen value into step
|
|
107
|
+
Carry the chosen value into step 4. Do not apply it yourself — the script owns all
|
|
108
108
|
of the mechanical work.
|
|
109
109
|
|
|
110
|
-
### 3.
|
|
110
|
+
### 3. Ask whether the distributed scaffold should be committed
|
|
111
|
+
|
|
112
|
+
This is a **distinct** question from step 2 — `project_files_visibility` (step 2)
|
|
113
|
+
covers only the `project/` working tree (the scrum board, `todo.md`, `queue/`,
|
|
114
|
+
`rapports/`, `logs/`). It has no effect on `.claude/`/`.agents/`, the distributed
|
|
115
|
+
framework scaffold (skill and agent definitions), which is a separate tree with a
|
|
116
|
+
separate lifecycle — it gets overwritten wholesale by every `/distribute` run or npm
|
|
117
|
+
upgrade, unlike `project/`. Kept as its own flag (`scaffold_visibility`) rather than
|
|
118
|
+
folded into `project_files_visibility`'s enum; see
|
|
119
|
+
`skills/j-distribute/CONFIG_SCHEMA.md`'s "Scaffold visibility" section for the full
|
|
120
|
+
rationale.
|
|
121
|
+
|
|
122
|
+
Ask the user this question, verbatim, before running any script:
|
|
123
|
+
|
|
124
|
+
Should the distributed .claude/.agents Jenga AI framework scaffold (skills, agent
|
|
125
|
+
definitions — implementation detail, not your own code) be committed into this
|
|
126
|
+
project's git history?
|
|
127
|
+
1. Yes, commit it — keep it tracked and visible, exactly like today
|
|
128
|
+
2. No, keep it on disk but add it to .gitignore so it's never committed
|
|
129
|
+
3. Not sure — explain the trade-offs and ask me again
|
|
130
|
+
|
|
131
|
+
If the user picks option 3, explain the trade-offs and re-ask. Do not proceed until
|
|
132
|
+
the answer maps to one of `visible` (option 1) or `ignored` (option 2).
|
|
133
|
+
|
|
134
|
+
If the run is non-interactive (no user available to answer), use the default:
|
|
135
|
+
**`visible`**. It is the only choice that changes nothing on disk, so an unattended
|
|
136
|
+
run reproduces exactly today's behavior — the scaffold is still committed by default.
|
|
137
|
+
|
|
138
|
+
Carry the chosen value into step 4 as well. Do not apply it yourself — the script
|
|
139
|
+
owns all of the mechanical work.
|
|
140
|
+
|
|
141
|
+
### 4. Run the scaffold script
|
|
111
142
|
|
|
112
143
|
`init.sh` is not guaranteed to live at a single fixed path: in a project that
|
|
113
144
|
installed Jenga via npm, it was mirrored to `.claude/skills/j-init/scripts/`
|
|
@@ -117,7 +148,7 @@ source checkout, where it lives at the bare `skills/j-init/scripts/` path
|
|
|
117
148
|
instead. This step runs before `CLAUDE.md`/`AGENTS.md` exist, so it cannot
|
|
118
149
|
rely on either file's routing instructions to resolve the path — it must
|
|
119
150
|
locate its own script directly. Execute the init script from the project
|
|
120
|
-
root, passing the
|
|
151
|
+
root, passing the choices from steps 2 and 3:
|
|
121
152
|
|
|
122
153
|
```bash
|
|
123
154
|
INIT_SCRIPT=""
|
|
@@ -128,11 +159,14 @@ if [[ -z "$INIT_SCRIPT" ]]; then
|
|
|
128
159
|
echo "Error: could not locate init.sh under .claude/skills/, .agents/skills/, or skills/" >&2
|
|
129
160
|
exit 1
|
|
130
161
|
fi
|
|
131
|
-
chmod +x "$INIT_SCRIPT" && "$INIT_SCRIPT" --visibility <visible|ignored>
|
|
162
|
+
chmod +x "$INIT_SCRIPT" && "$INIT_SCRIPT" --visibility <visible|ignored> --scaffold-visibility <visible|ignored>
|
|
132
163
|
```
|
|
133
164
|
|
|
134
165
|
Omitting `--visibility` falls back to the `JENGA_PROJECT_FILES_VISIBILITY`
|
|
135
|
-
environment variable, then to `visible`.
|
|
166
|
+
environment variable, then to `visible`. Omitting `--scaffold-visibility` falls
|
|
167
|
+
back to the `JENGA_SCAFFOLD_VISIBILITY` environment variable, then to `visible`
|
|
168
|
+
— the same default-preserving fallback chain, applied independently to the
|
|
169
|
+
distributed-scaffold question from step 3.
|
|
136
170
|
|
|
137
171
|
This script handles all scaffolding in one step:
|
|
138
172
|
1. Initializes the git repository
|
|
@@ -148,22 +182,27 @@ This script handles all scaffolding in one step:
|
|
|
148
182
|
11. Creates `docs/STRATEGY.md` — a strategic brief stub intended for investors, partners, and the product team
|
|
149
183
|
12. Creates `CHANGELOG.md` from the shared template — a running log of notable changes, seeded with an `[Unreleased]` section
|
|
150
184
|
13. Applies the chosen visibility mode via `scripts/apply-project-visibility.sh`, which records it as `project_files_visibility` in `jenga.config.json` and performs any `.gitignore` change
|
|
151
|
-
14.
|
|
185
|
+
14. Applies the chosen scaffold visibility mode via `scripts/apply-scaffold-visibility.sh`, which records it as `scaffold_visibility` in `jenga.config.json` and, when `ignored`, adds `.claude/` and `.agents/` to `.gitignore`
|
|
186
|
+
15. Stages and commits all files with the message `init: scaffold project structure and workflow config`
|
|
152
187
|
|
|
153
|
-
|
|
154
|
-
value fails fast and leaves nothing behind.
|
|
155
|
-
|
|
188
|
+
Both visibility modes are validated before any scaffolding happens, so an invalid
|
|
189
|
+
value fails fast and leaves nothing behind. Both are applied before the commit, so
|
|
190
|
+
any resulting `.gitignore` entries are captured in the initial commit — this is what
|
|
191
|
+
lets `scaffold_visibility: ignored` keep `.claude/`/`.agents/` out of the commit even
|
|
192
|
+
though they may already exist on disk (from npm postinstall or a prior `/distribute`
|
|
193
|
+
run) by the time `/init` runs `git add -A`.
|
|
156
194
|
|
|
157
195
|
If the script fails, check that you are in the project root and that git and `jq`
|
|
158
196
|
are available.
|
|
159
197
|
|
|
160
|
-
See `skills/distribute/CONFIG_SCHEMA.md` for the full `project_files_visibility`
|
|
161
|
-
field reference.
|
|
198
|
+
See `skills/j-distribute/CONFIG_SCHEMA.md` for the full `project_files_visibility` and
|
|
199
|
+
`scaffold_visibility` field reference.
|
|
162
200
|
|
|
163
|
-
###
|
|
201
|
+
### 5. Prompt next step
|
|
164
202
|
|
|
165
203
|
Inform the user that setup is complete, and state which visibility mode was applied
|
|
166
|
-
|
|
204
|
+
for both `project_files_visibility` and `scaffold_visibility`, and where the working
|
|
205
|
+
files and scaffold now live. Mention that `docs/STRATEGY.md` was created as
|
|
167
206
|
a strategic brief stub for investors, partners, and the product team — they can fill
|
|
168
207
|
it in now or return to it later. Suggest running `/pi-plan` to define project goals
|
|
169
208
|
and epics.
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
"threshold_version":
|
|
2
|
+
"threshold_version": 3,
|
|
3
3
|
"inline_max_files": 3,
|
|
4
4
|
"inline_max_lines": 75,
|
|
5
5
|
"story_max_files": 5,
|
|
6
|
-
"bundle_lock_ttl_minutes": 30
|
|
6
|
+
"bundle_lock_ttl_minutes": 30,
|
|
7
|
+
"max_concurrent_developers": 3,
|
|
8
|
+
"max_concurrent_testers": 3,
|
|
9
|
+
"slot_ttl_minutes": 45
|
|
7
10
|
}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# apply-scaffold-visibility.sh — apply the `scaffold_visibility` mode to a project.
|
|
4
|
+
#
|
|
5
|
+
# This is a DISTINCT flag from `project_files_visibility` (see
|
|
6
|
+
# apply-project-visibility.sh). `project_files_visibility` covers the
|
|
7
|
+
# project/ working tree (scrum board, todo.md, queue/, rapports/, logs/) —
|
|
8
|
+
# E31_S05's own Background section scopes it to that tree only. This script
|
|
9
|
+
# instead covers the *distributed framework scaffold* — `.claude/` and
|
|
10
|
+
# `.agents/` — which is a different tree with a different lifecycle (it is
|
|
11
|
+
# overwritten wholesale by every `/distribute` run or npm upgrade; project/
|
|
12
|
+
# is not). Filed as new, adjacent scope under E31_S07 rather than folded
|
|
13
|
+
# silently into project_files_visibility's existing enum. See
|
|
14
|
+
# skills/j-distribute/CONFIG_SCHEMA.md's "Scaffold visibility" section for the
|
|
15
|
+
# full rationale.
|
|
16
|
+
#
|
|
17
|
+
# This is skills/j-init/'s own copy of skills/init/scripts/apply-scaffold-visibility.sh
|
|
18
|
+
# (E31_S07_T03) — skills/j-init/ is a separate, hand-maintained directory, not
|
|
19
|
+
# auto-synced with skills/init/ (scripts/generate-j-alias.sh explicitly excludes
|
|
20
|
+
# this pair), and is the copy that actually ships to public-GitHub-mirror and
|
|
21
|
+
# npm-package consumers. Keep this file's logic in lockstep with skills/init/'s
|
|
22
|
+
# copy — any behavioral change made there should be mirrored here.
|
|
23
|
+
#
|
|
24
|
+
# Usage:
|
|
25
|
+
# apply-scaffold-visibility.sh <mode> [project_root]
|
|
26
|
+
# apply-scaffold-visibility.sh --check-only <mode>
|
|
27
|
+
#
|
|
28
|
+
# Modes:
|
|
29
|
+
# visible Scaffold directories stay where they are. No-op on disk beyond
|
|
30
|
+
# the config write. This is the default — matches the behavior
|
|
31
|
+
# of every /init run before this flag existed.
|
|
32
|
+
# ignored .claude/ and .agents/ are added to the project's .gitignore —
|
|
33
|
+
# present on disk (whenever npm postinstall or /distribute
|
|
34
|
+
# places them, whether that happens before or after this runs),
|
|
35
|
+
# never committed. Entries are written unconditionally, the same
|
|
36
|
+
# way apply-project-visibility.sh gitignores project/ whether or
|
|
37
|
+
# not it exists yet, so a scaffold created by a later
|
|
38
|
+
# /distribute run is covered too, not just one already on disk.
|
|
39
|
+
#
|
|
40
|
+
# Exit codes:
|
|
41
|
+
# 0 Success
|
|
42
|
+
# 1 Bad usage or missing prerequisite
|
|
43
|
+
# 2 Invalid mode (outside the two-value enum)
|
|
44
|
+
# 3 Filesystem apply failure
|
|
45
|
+
# 4 jenga.config.json write failure
|
|
46
|
+
|
|
47
|
+
# Do NOT use set -e globally — each step handles its own errors.
|
|
48
|
+
set -uo pipefail
|
|
49
|
+
|
|
50
|
+
info() { echo "[scaffold-visibility] $*"; }
|
|
51
|
+
warn() { echo "[scaffold-visibility] WARNING: $*"; }
|
|
52
|
+
err() { echo "[scaffold-visibility] ERROR: $*" >&2; }
|
|
53
|
+
|
|
54
|
+
usage() {
|
|
55
|
+
echo "Usage: $(basename "$0") <visible|ignored> [project_root]" >&2
|
|
56
|
+
echo " $(basename "$0") --check-only <visible|ignored>" >&2
|
|
57
|
+
exit 1
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
# The distributed framework scaffold — mirrored copies of skills/agents for
|
|
61
|
+
# Claude Code and Copilot/other agents. Distinct from JENGA_WORKING_PATHS in
|
|
62
|
+
# apply-project-visibility.sh, which covers project/ only.
|
|
63
|
+
JENGA_SCAFFOLD_PATHS=(".claude" ".agents")
|
|
64
|
+
|
|
65
|
+
VALID_MODES="visible ignored"
|
|
66
|
+
|
|
67
|
+
validate_mode() {
|
|
68
|
+
local mode="$1"
|
|
69
|
+
for valid in $VALID_MODES; do
|
|
70
|
+
[ "$mode" = "$valid" ] && return 0
|
|
71
|
+
done
|
|
72
|
+
err "Invalid scaffold_visibility value: '${mode}'"
|
|
73
|
+
err "Allowed values are: ${VALID_MODES// /, }"
|
|
74
|
+
exit 2
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
# ---------------------------------------------------------------------------
|
|
78
|
+
# Argument parsing
|
|
79
|
+
# ---------------------------------------------------------------------------
|
|
80
|
+
|
|
81
|
+
CHECK_ONLY=0
|
|
82
|
+
if [ "${1:-}" = "--check-only" ]; then
|
|
83
|
+
CHECK_ONLY=1
|
|
84
|
+
shift
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
MODE="${1:-}"
|
|
88
|
+
[ -n "$MODE" ] || usage
|
|
89
|
+
|
|
90
|
+
validate_mode "$MODE"
|
|
91
|
+
|
|
92
|
+
if [ "$CHECK_ONLY" -eq 1 ]; then
|
|
93
|
+
info "Mode '$MODE' is valid."
|
|
94
|
+
exit 0
|
|
95
|
+
fi
|
|
96
|
+
|
|
97
|
+
PROJECT_ROOT="${2:-$PWD}"
|
|
98
|
+
if [ ! -d "$PROJECT_ROOT" ]; then
|
|
99
|
+
err "Project root does not exist: $PROJECT_ROOT"
|
|
100
|
+
exit 1
|
|
101
|
+
fi
|
|
102
|
+
cd "$PROJECT_ROOT" || { err "Cannot enter project root: $PROJECT_ROOT"; exit 1; }
|
|
103
|
+
|
|
104
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
105
|
+
err "jq is required to write jenga.config.json but was not found on PATH."
|
|
106
|
+
exit 1
|
|
107
|
+
fi
|
|
108
|
+
|
|
109
|
+
# ---------------------------------------------------------------------------
|
|
110
|
+
# ignored — append to .gitignore, without ever duplicating an entry
|
|
111
|
+
# ---------------------------------------------------------------------------
|
|
112
|
+
|
|
113
|
+
gitignore_append() {
|
|
114
|
+
local entry="$1"
|
|
115
|
+
local gitignore=".gitignore"
|
|
116
|
+
|
|
117
|
+
if [ -f "$gitignore" ] && grep -qxF -- "$entry" "$gitignore"; then
|
|
118
|
+
info "'$entry' already present in .gitignore — skipping."
|
|
119
|
+
return 0
|
|
120
|
+
fi
|
|
121
|
+
|
|
122
|
+
# Don't glue our entry onto a final line that lacks a newline.
|
|
123
|
+
if [ -s "$gitignore" ] && [ -n "$(tail -c 1 "$gitignore")" ]; then
|
|
124
|
+
printf '\n' >> "$gitignore"
|
|
125
|
+
fi
|
|
126
|
+
|
|
127
|
+
if ! printf '%s\n' "$entry" >> "$gitignore"; then
|
|
128
|
+
err "Failed to append '$entry' to .gitignore"
|
|
129
|
+
exit 3
|
|
130
|
+
fi
|
|
131
|
+
info "Added '$entry' to .gitignore"
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
# ---------------------------------------------------------------------------
|
|
135
|
+
# jenga.config.json — merge the field in, written atomically (temp + mv)
|
|
136
|
+
# ---------------------------------------------------------------------------
|
|
137
|
+
|
|
138
|
+
write_scaffold_config() {
|
|
139
|
+
local mode="$1"
|
|
140
|
+
local config="jenga.config.json"
|
|
141
|
+
local tmp="${config}.tmp"
|
|
142
|
+
local existing='{}'
|
|
143
|
+
|
|
144
|
+
# /init normally runs before any /distribute, so the file usually does not
|
|
145
|
+
# exist yet. Merge rather than overwrite so other fields survive.
|
|
146
|
+
if [ -f "$config" ]; then
|
|
147
|
+
if ! jq empty "$config" 2>/dev/null; then
|
|
148
|
+
err "$config exists but contains malformed JSON — refusing to overwrite it."
|
|
149
|
+
exit 4
|
|
150
|
+
fi
|
|
151
|
+
existing="$(cat "$config")"
|
|
152
|
+
fi
|
|
153
|
+
|
|
154
|
+
local content
|
|
155
|
+
content="$(jq --arg v "$mode" '.scaffold_visibility = $v' <<< "$existing")"
|
|
156
|
+
if [ -z "$content" ]; then
|
|
157
|
+
err "Failed to construct $config content."
|
|
158
|
+
exit 4
|
|
159
|
+
fi
|
|
160
|
+
|
|
161
|
+
if ! printf '%s\n' "$content" > "$tmp"; then
|
|
162
|
+
err "Failed to write temporary config file: $tmp"
|
|
163
|
+
exit 4
|
|
164
|
+
fi
|
|
165
|
+
|
|
166
|
+
if ! mv "$tmp" "$config"; then
|
|
167
|
+
err "Failed to atomically move $tmp to $config"
|
|
168
|
+
rm -f "$tmp"
|
|
169
|
+
exit 4
|
|
170
|
+
fi
|
|
171
|
+
|
|
172
|
+
info "Wrote scaffold_visibility = \"$mode\" to $config"
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
# ---------------------------------------------------------------------------
|
|
176
|
+
# Apply
|
|
177
|
+
# ---------------------------------------------------------------------------
|
|
178
|
+
|
|
179
|
+
case "$MODE" in
|
|
180
|
+
visible)
|
|
181
|
+
info "Mode 'visible' — scaffold directories stay in place; nothing to change on disk."
|
|
182
|
+
;;
|
|
183
|
+
ignored)
|
|
184
|
+
for path in "${JENGA_SCAFFOLD_PATHS[@]}"; do
|
|
185
|
+
gitignore_append "${path}/"
|
|
186
|
+
done
|
|
187
|
+
;;
|
|
188
|
+
esac
|
|
189
|
+
|
|
190
|
+
write_scaffold_config "$MODE"
|
|
191
|
+
|
|
192
|
+
info "Applied scaffold_visibility '$MODE' to $PROJECT_ROOT"
|