@jenga-ai/agent 3.5.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.
Files changed (94) hide show
  1. package/README.md +85 -78
  2. package/agents/developer.md +1 -1
  3. package/agents/scrum-master.md +20 -2
  4. package/agents/tester.md +3 -3
  5. package/hooks/on_session_end.sh +5 -5
  6. package/lib/generate-agent-context.js +2 -2
  7. package/lib/generate-copilot-hooks.js +1 -1
  8. package/lib/generate-skill-allow-list.js +37 -3
  9. package/lib/mirror.js +1 -1
  10. package/lib/postinstall-manifest.js +1 -1
  11. package/lib/skill-allow-list.json +2 -2
  12. package/mcp/help/index.js +8 -17
  13. package/mcp/help/scan.js +73 -0
  14. package/package.json +6 -1
  15. package/project/app/api/parsers/knowledge-graph.js +100 -9
  16. package/project/app/api/routes/health.js +36 -0
  17. package/project/app/api/scripts/capture-snapshot.js +9 -6
  18. package/project/app/ui/dist/assets/{index-CdK3Qrep.css → index-BVR_7Owg.css} +1 -1
  19. package/project/app/ui/dist/assets/index-CtU2xLQm.js +104 -0
  20. package/project/app/ui/dist/index.html +2 -2
  21. package/project/app/ui/package.json +4 -0
  22. package/project/app/ui/scripts/build-snapshot-html.cjs +63 -2
  23. package/scripts/acquire-concurrency-slot.sh +1 -1
  24. package/scripts/apply-j-prefix.sh +46 -5
  25. package/scripts/audit-twin-divergence.sh +73 -5
  26. package/scripts/build-pages-site.sh +1 -1
  27. package/scripts/check-public-playbook-steps.sh +158 -52
  28. package/scripts/check-publicignore-match.sh +2 -2
  29. package/scripts/compute-deploy-reconcile.sh +5 -5
  30. package/scripts/delete-bare-skill-dirs.sh +330 -0
  31. package/scripts/generate-legacy-shipped-paths.js +2 -2
  32. package/scripts/idea_manager.sh +258 -3
  33. package/scripts/mark-deployed.sh +2 -2
  34. package/scripts/populate-knowledge-graph.entity-resolution.test.js +254 -0
  35. package/scripts/populate-knowledge-graph.js +213 -5
  36. package/scripts/populate-knowledge-graph.staleness.test.js +130 -0
  37. package/scripts/postinstall.js +1 -1
  38. package/scripts/repoint-skill-refs.sh +539 -0
  39. package/scripts/todo_manager.sh +1 -1
  40. package/scripts/verify-legacy-seed-reconcile.sh +10 -10
  41. package/scripts/verify-postinstall-reconcile.sh +7 -7
  42. package/scripts/write-context-digest.sh +1 -1
  43. package/skills/j-clearify/SKILL.md +2 -2
  44. package/skills/j-close-story/scripts/check-privatized.sh +4 -4
  45. package/skills/j-distribute/CONFIG_SCHEMA.md +82 -5
  46. package/skills/j-do/SKILL.md +101 -17
  47. package/skills/j-doc-sync/SKILL.md +1 -0
  48. package/skills/j-gitignore/SKILL.md +157 -0
  49. package/skills/j-gitignore/assets/jenga-paths.txt +50 -0
  50. package/skills/j-gitignore/scripts/_catalog.sh +105 -0
  51. package/skills/j-gitignore/scripts/audit-gitignore.sh +194 -0
  52. package/skills/j-gitignore/scripts/repair-gitignore.sh +226 -0
  53. package/skills/j-gitignore/scripts/untrack-jenga-files.sh +210 -0
  54. package/skills/j-idea/SKILL.md +78 -6
  55. package/skills/j-idea/assets/idea_template.md +1 -1
  56. package/skills/j-improve/SKILL.md +1 -1
  57. package/skills/j-init/SKILL.md +3 -3
  58. package/skills/j-init/assets/scope-thresholds_template.json +5 -2
  59. package/skills/j-init/scripts/apply-scaffold-visibility.sh +1 -1
  60. package/skills/j-init/scripts/init.sh +4 -4
  61. package/skills/j-playbook/SKILL.md +1 -1
  62. package/skills/j-publish/SKILL.md +1 -1
  63. package/skills/j-publish/adapters/npm-ci.md +6 -1
  64. package/skills/j-publish/adapters/npm.md +1 -1
  65. package/skills/j-publish/scripts/generate_release_notes.sh +1 -1
  66. package/skills/j-publish/scripts/npm_stage_inspect.sh +61 -0
  67. package/skills/j-reconcile/SKILL.md +2 -2
  68. package/skills/j-reconcile/scripts/detect-unlinked-code.sh +11 -11
  69. package/skills/j-redo/SKILL.md +1 -1
  70. package/skills/j-spinoff/SKILL.md +1 -1
  71. package/skills/j-status/SKILL.md +15 -0
  72. package/skills/j-todo/SKILL.md +3 -1
  73. package/skills/j-uncharted/SKILL.md +1 -1
  74. package/skills/j-uncharted/scripts/detect-dependencies.sh +1 -1
  75. package/skills/j-uncharted/scripts/detect-tests.sh +1 -1
  76. package/skills/j-uncharted/scripts/elicitation-state.sh +1 -1
  77. package/skills/j-uncharted/scripts/validate-proposed-items.sh +1 -1
  78. package/skills/j-wtf/SKILL.md +1 -1
  79. package/skills/jenga/SKILL.md +43 -9
  80. package/skills/jenga/playbooks/board-hygiene.json +32 -0
  81. package/skills/jenga/playbooks/schema.json +73 -6
  82. package/skills/jenga/playbooks/understand-then-commit.json +19 -0
  83. package/skills/jenga/scripts/load-nl-catalog.sh +1 -1
  84. package/skills/jenga/scripts/load-playbooks.sh +1 -1
  85. package/skills/jenga/scripts/match-playbook.sh +1 -1
  86. package/templates/SCRUM_BOARD_SCHEMA.md +14 -1
  87. package/templates/SKILL_TEMPLATE.md +12 -0
  88. package/templates/permission-levels/level-4-elevated.json +1 -1
  89. package/templates/permission-levels/level-5-unrestricted.json +1 -1
  90. package/templates/playbook-types.json +34 -6
  91. package/project/app/ui/dist/assets/index-7fj-vllY.js +0 -104
  92. package/scripts/generate-j-alias.sh +0 -333
  93. package/skills/j-dev-done/SKILL.md +0 -53
  94. 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
@@ -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
- - `DISCARDED` — the idea was reviewed and dropped.
55
+ - `REJECTED` — the idea was reviewed and dropped.
56
56
 
57
- Example (mirroring `project/todo.md`'s tagging style):
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
- Add dark mode toggle to settings page <!-- PROMOTED -->
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
- No agent invoked by `/idea` applies these tags or acts on them — that is reserved for a future promotion step (e.g. within `/brainstorm`).
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.
@@ -1,3 +1,3 @@
1
1
  # Ideas
2
2
 
3
- <!-- Format: <idea text> (one line per idea; terminal tags PROMOTED / DISCARDED appended by /brainstorm, not by /idea) -->
3
+ <!-- Format: <idea text> (one line per idea; terminal tags PROMOTED / REJECTED appended by /brainstorm, not by /idea) -->
@@ -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
 
@@ -101,7 +101,7 @@ 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
107
  Carry the chosen value into step 4. Do not apply it yourself — the script owns all
@@ -116,7 +116,7 @@ framework scaffold (skill and agent definitions), which is a separate tree with
116
116
  separate lifecycle — it gets overwritten wholesale by every `/distribute` run or npm
117
117
  upgrade, unlike `project/`. Kept as its own flag (`scaffold_visibility`) rather than
118
118
  folded into `project_files_visibility`'s enum; see
119
- `skills/distribute/CONFIG_SCHEMA.md`'s "Scaffold visibility" section for the full
119
+ `skills/j-distribute/CONFIG_SCHEMA.md`'s "Scaffold visibility" section for the full
120
120
  rationale.
121
121
 
122
122
  Ask the user this question, verbatim, before running any script:
@@ -195,7 +195,7 @@ run) by the time `/init` runs `git add -A`.
195
195
  If the script fails, check that you are in the project root and that git and `jq`
196
196
  are available.
197
197
 
198
- See `skills/distribute/CONFIG_SCHEMA.md` for the full `project_files_visibility` and
198
+ See `skills/j-distribute/CONFIG_SCHEMA.md` for the full `project_files_visibility` and
199
199
  `scaffold_visibility` field reference.
200
200
 
201
201
  ### 5. Prompt next step
@@ -1,7 +1,10 @@
1
1
  {
2
- "threshold_version": 2,
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
  }
@@ -11,7 +11,7 @@
11
11
  # overwritten wholesale by every `/distribute` run or npm upgrade; project/
12
12
  # is not). Filed as new, adjacent scope under E31_S07 rather than folded
13
13
  # silently into project_files_visibility's existing enum. See
14
- # skills/distribute/CONFIG_SCHEMA.md's "Scaffold visibility" section for the
14
+ # skills/j-distribute/CONFIG_SCHEMA.md's "Scaffold visibility" section for the
15
15
  # full rationale.
16
16
  #
17
17
  # This is skills/j-init/'s own copy of skills/init/scripts/apply-scaffold-visibility.sh
@@ -30,7 +30,7 @@ fi
30
30
  # queue/, rapports/, logs/). scaffold_visibility is a distinct, independent
31
31
  # flag (E31_S07_T01, ported here in E31_S07_T03) covering the distributed
32
32
  # .claude/.agents framework scaffold — kept separate per
33
- # skills/distribute/CONFIG_SCHEMA.md's "Scaffold visibility" section, rather
33
+ # skills/j-distribute/CONFIG_SCHEMA.md's "Scaffold visibility" section, rather
34
34
  # than folded into project_files_visibility's existing enum.
35
35
  VISIBILITY="${JENGA_PROJECT_FILES_VISIBILITY:-visible}"
36
36
  SCAFFOLD_VISIBILITY="${JENGA_SCAFFOLD_VISIBILITY:-visible}"
@@ -79,7 +79,7 @@ echo "→ Copying test-config.json from template..."
79
79
  cp "$ASSETS_DIR/test-config_template.json" project/configs/test-config.json
80
80
 
81
81
  # ─── 6.5. Create project/configs/scope-thresholds.json ───────────────────────
82
- # Consumed by skills/jenga (Phase 0) and skills/do (Step 0); both halt if it's
82
+ # Consumed by skills/jenga (Phase 0) and skills/j-do (Step 0); both halt if it's
83
83
  # missing, so it must exist immediately after scaffold.
84
84
  echo "→ Copying scope-thresholds.json from template..."
85
85
  cp "$ASSETS_DIR/scope-thresholds_template.json" project/configs/scope-thresholds.json
@@ -93,7 +93,7 @@ echo "→ Creating events.json..."
93
93
  echo '[]' > project/logs/events.json
94
94
 
95
95
  # ─── 8.5. Create project/knowledge-graph/{STUB_SCHEMA.md,graph.json} ─────────
96
- # Consumed by skills/uncharted's conversational elicitation flow (`onboard`,
96
+ # Consumed by skills/j-uncharted's conversational elicitation flow (`onboard`,
97
97
  # `segment --mode investigate`), which writes coarse graph nodes/edges to
98
98
  # graph.json per the stub schema — both must exist before that flow's first
99
99
  # write, per templates/KNOWLEDGE_GRAPH_STUB_SCHEMA_TEMPLATE.md's own header
@@ -138,4 +138,4 @@ git add -A
138
138
  git commit -m "init: scaffold project structure and workflow config"
139
139
 
140
140
  echo ""
141
- echo "✓ Project scaffold complete."
141
+ echo "✓ Project scaffold complete."
@@ -8,7 +8,7 @@ keywords:
8
8
  - execute playbook
9
9
  examples:
10
10
  - "j.playbook brainstorm-to-mirror"
11
- - "run the understand-then-ship playbook"
11
+ - "run the understand-then-commit playbook"
12
12
  - "invoke playbook by id"
13
13
  ---
14
14
 
@@ -265,7 +265,7 @@ Release-note rules:
265
265
  - **`--output <path>`:** writes a standalone, disposable draft to that path instead (the pre-E36 behavior) — `CHANGELOG.md` is not touched in this mode.
266
266
  - If no prior ledger-backed tag exists, a `--output` draft includes `> First release — full history included`; the standing `CHANGELOG.md` merge mode has no equivalent banner (it just merges full history into `[Unreleased]` like any other run).
267
267
  - Scrum-board enrichment is best-effort only; missing or unreadable board data never fails the command.
268
- - **`.publicignore` filtering:** when a repo-root `.publicignore` exists (the blocklist `/mirror-public` also reads), a candidate commit — or a completed task's associated commit(s), matched via the `task(E##_S##_T##):` commit-message convention — is dropped entirely when every changed file it touches is covered by that blocklist. A commit touching a mix of blocked and unblocked files is still logged normally; only full coverage excludes an entry. This exists because `CHANGELOG.md` itself is not blocklisted and ships to the public mirror, so an unfiltered entry referencing a private-only path (e.g. `project/board/`) would leak. Absent `.publicignore`, this is a strict no-op — unchanged from pre-E36_S02_T02 behavior. Matching reuses `skills/mirror-public/scripts/mirror.sh`'s `rsync --exclude-from` evaluation rather than a separate glob implementation, so a path classified "blocked" by `/mirror-public --dry-run` is classified "blocked" here too.
268
+ - **`.publicignore` filtering:** when a repo-root `.publicignore` exists (the blocklist `/mirror-public` also reads), a candidate commit — or a completed task's associated commit(s), matched via the `task(E##_S##_T##):` commit-message convention — is dropped entirely when every changed file it touches is covered by that blocklist. A commit touching a mix of blocked and unblocked files is still logged normally; only full coverage excludes an entry. This exists because `CHANGELOG.md` itself is not blocklisted and ships to the public mirror, so an unfiltered entry referencing a private-only path (e.g. `project/board/`) would leak. Absent `.publicignore`, this is a strict no-op — unchanged from pre-E36_S02_T02 behavior. Matching reuses `skills/j-mirror-public/scripts/mirror.sh`'s `rsync --exclude-from` evaluation rather than a separate glob implementation, so a path classified "blocked" by `/mirror-public --dry-run` is classified "blocked" here too.
269
269
 
270
270
  ## Ledger & Tagging
271
271
 
@@ -239,7 +239,12 @@ automated and human halves of the flow:
239
239
  relies on the automated CI-staged test result) and then
240
240
  `bash skills/j-publish/scripts/npm_stage_inspect.sh approve <stage-id> --otp <otp>`
241
241
  from their own machine. `reject` (same script) is available to either
242
- side to discard a staged candidate.
242
+ side to discard a staged candidate. On success, `approve` also generates
243
+ release notes into `CHANGELOG.md`'s `[Unreleased]` section and finalizes
244
+ it with the approved version — the same behavior described in
245
+ `adapters/npm.md`'s Staged Publishing section, shared by both target
246
+ types since it lives in `npm_stage_inspect.sh` itself, not in either
247
+ target-type-specific pipeline (E22_S09_T08).
243
248
  - **Stage-id capture reads the CI run's own log, not a local `npm stage
244
249
  list` call.** Because the actual `npm stage publish --provenance` call
245
250
  runs inside the dispatched Actions run, the local `npm_stage_pipeline.sh`
@@ -119,7 +119,7 @@ becomes visible on the registry. See `skills/j-publish/SKILL.md`'s
119
119
 
120
120
  - `bash skills/j-publish/scripts/npm_stage_pipeline.sh <target> <path-to-publish.json> [--dry-run] [--non-interactive] [--otp <otp>]` runs validate → gates → pack → stage → capture → ledger and writes a `staged` ledger entry.
121
121
  - `bash skills/j-publish/scripts/npm_stage_inspect.sh test <stage-id>` installs the staged tarball into an isolated scratch directory and smoke-tests it, writing a `stage_tested` ledger entry.
122
- - `bash skills/j-publish/scripts/npm_stage_inspect.sh approve <stage-id>` requires an npm 2FA one-time password and refuses without a passing `test` on record unless `--force <reason>` is given.
122
+ - `bash skills/j-publish/scripts/npm_stage_inspect.sh approve <stage-id>` requires an npm 2FA one-time password and refuses without a passing `test` on record unless `--force <reason>` is given. On a successful `npm stage approve`, it also generates release notes into `CHANGELOG.md`'s `[Unreleased]` section and finalizes that section with the approved version — the same `generate_release_notes.sh` + `finalize_changelog.sh` pair `/publish deploy` runs, reused rather than duplicated (E22_S09_T08). `--dry-run` skips this (it exits before the real approve call runs at all); a failed `npm stage approve` skips it too (no changelog write on a failed approve); `--force` still runs it — `--force` only bypasses the passing-test requirement, not the changelog step.
123
123
  - `bash skills/j-publish/scripts/npm_stage_inspect.sh reject <stage-id>` discards the staged version.
124
124
 
125
125
  Same registry-existence precondition as a normal `npm` publish: staged
@@ -76,7 +76,7 @@ git rev-parse --verify "$TO_REF" >/dev/null 2>&1 || {
76
76
  # Absence of .publicignore is a strict no-op — PI_ACTIVE stays 0 and every
77
77
  # _pi_* helper below fails open immediately.
78
78
  #
79
- # Matching semantics are borrowed from skills/mirror-public/scripts/mirror.sh
79
+ # Matching semantics are borrowed from skills/j-mirror-public/scripts/mirror.sh
80
80
  # rather than reimplemented: that script's compute_ship_list asks rsync
81
81
  # itself "what would transfer past --exclude-from=.publicignore?" and that
82
82
  # is the single source of truth /mirror-public --dry-run reports as
@@ -86,6 +86,8 @@ fi
86
86
  source "${SCRIPT_DIR}/publish_common.sh"
87
87
 
88
88
  WRITE_LEDGER_SCRIPT="${SCRIPT_DIR}/write_ledger_entry.sh"
89
+ GENERATE_RELEASE_NOTES_SCRIPT="${SCRIPT_DIR}/generate_release_notes.sh"
90
+ FINALIZE_CHANGELOG_SCRIPT="${SCRIPT_DIR}/finalize_changelog.sh"
89
91
 
90
92
  # ---------------------------------------------------------------------------
91
93
  # OTP tracing guard — MUST run at the top level, before `main "$@"` is ever
@@ -397,6 +399,53 @@ _write_stage_tested_ledger() {
397
399
  "${cmd[@]}" || log_warn "failed to write 'stage_tested' ledger entry for stage ${stage_id} (result: ${result})"
398
400
  }
399
401
 
402
+ # _finalize_stage_changelog <target_name> <config_path> <package_version>
403
+ #
404
+ # `approve`'s equivalent of publish_deploy.sh's generate_release_notes() +
405
+ # finalize_changelog() pair (E22_S09_T08) — reused verbatim, not
406
+ # reimplemented. Only ever called AFTER a real `npm stage approve` call has
407
+ # already succeeded, so a failure here never masks (nor is masked by) the
408
+ # approve result itself; the caller decides how to report it.
409
+ #
410
+ # Mirrors publish_deploy.sh's resolve_last_tag(): resolves the last publish
411
+ # tag from the ledger via publish_resolve_last_publish_tag, never a
412
+ # hardcoded/guessed tag. Passes --from-tag only when a tag was actually
413
+ # resolved, and passes the config path positional only when one is
414
+ # resolved -- generate_release_notes.sh treats an omitted config the same
415
+ # way it treats an unresolved one internally (falls back to its own
416
+ # defaults via publish_resolve_history_file "").
417
+ #
418
+ # Uses the already-resolved package_version (from the stage's own `npm
419
+ # stage view` output) for finalize_changelog.sh, per the task's acceptance
420
+ # criteria -- never a re-derived version.
421
+ _finalize_stage_changelog() {
422
+ local target_name="$1" config_path="$2" package_version="$3"
423
+ local history_file last_tag
424
+ local -a notes_cmd=(bash "${GENERATE_RELEASE_NOTES_SCRIPT}" --target "${target_name}")
425
+
426
+ history_file="$(publish_resolve_history_file "${config_path}")"
427
+ last_tag="$(publish_resolve_last_publish_tag "${history_file}" HEAD 2>/dev/null || true)"
428
+ [[ -n "${last_tag}" ]] && notes_cmd+=(--from-tag "${last_tag}")
429
+ [[ -n "${config_path}" ]] && notes_cmd+=("${config_path}")
430
+
431
+ if ! "${notes_cmd[@]}"; then
432
+ log_warn "failed to generate release notes for stage approve (target: ${target_name})"
433
+ return 1
434
+ fi
435
+
436
+ if [[ -z "${package_version}" ]]; then
437
+ log_warn "no package version resolved from stage view — skipping CHANGELOG.md finalization"
438
+ return 1
439
+ fi
440
+
441
+ if ! bash "${FINALIZE_CHANGELOG_SCRIPT}" "${package_version}" "${REPO_ROOT}/CHANGELOG.md"; then
442
+ log_warn "failed to finalize CHANGELOG.md for stage approve (version: ${package_version})"
443
+ return 1
444
+ fi
445
+
446
+ return 0
447
+ }
448
+
400
449
  # ---------------------------------------------------------------------------
401
450
  # list [<package-spec>] [--config <path>] [--dry-run] [--json]
402
451
  # ---------------------------------------------------------------------------
@@ -772,6 +821,18 @@ cmd_approve() {
772
821
  exit "${EXIT_OP_FAILED}"
773
822
  fi
774
823
 
824
+ # Generate release notes into CHANGELOG.md's [Unreleased] section and
825
+ # stamp it with the approved version — mirroring publish_deploy.sh's own
826
+ # generate_release_notes() + finalize_changelog() pair (E22_S09_T08).
827
+ # Only reached after a confirmed successful `npm stage approve` above, so
828
+ # a failed approve never gets a changelog write, and --force only ever
829
+ # affects the test-interlock check earlier in this function — this step
830
+ # runs identically on both the normal and --force paths, no divergent
831
+ # logic. Never reached at all under --dry-run, which already exited
832
+ # earlier, before the real approve call.
833
+ _finalize_stage_changelog "${target_name}" "${config_path}" "${package_version}" \
834
+ || log_warn "stage ${stage_id} was approved, but CHANGELOG.md was not updated — see warnings above"
835
+
775
836
  local -a ledger_cmd=(bash "${WRITE_LEDGER_SCRIPT}" "${target_name}" "${target_type}" approved "" --stage-id "${stage_id}")
776
837
  [[ -n "${config_path}" ]] && ledger_cmd+=(--config "${config_path}")
777
838
  [[ -n "${package_version}" ]] && ledger_cmd+=(--version "${package_version}")
@@ -3,7 +3,7 @@ name: j.reconcile
3
3
  description: Polyfill alias of the reconcile skill under a collision-safe directory name. Identical behavior to /reconcile — 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". Use when the bare /reconcile form is shadowed by another tool's own built-in command of the same name.
4
4
  metadata:
5
5
  prefered_agent: scrum-master
6
- output_types: text
6
+ output_types: id_list
7
7
  keywords:
8
8
  - j-reconcile
9
9
  - polyfill
@@ -200,7 +200,7 @@ older conventions still present in this repo's history (`E04_S01: ...` and
200
200
  `feat(train): implement E01_S05 - ...`).
201
201
 
202
202
  The script reuses the board-linkage check from
203
- `skills/uncharted/scripts/resolve-segment-target.sh` through its batch interface. Do not
203
+ `skills/j-uncharted/scripts/resolve-segment-target.sh` through its batch interface. Do not
204
204
  re-derive linkage yourself, and do not substitute a `grep` over `project/board/` if the script
205
205
  fails — a second answer to "is this path on the board" is what that reuse exists to prevent.
206
206
  If the script exits non-zero, report the failure in the reconcile report and continue to phase 6.