@jenga-ai/agent 3.2.0 → 3.5.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 +52 -12
- package/agents/developer.md +16 -1
- package/agents/scrum-master.md +1 -0
- package/bin/jenga.js +10 -0
- package/lib/commands/dashboard.js +92 -0
- package/lib/skill-allow-list.json +6 -2
- package/package.json +21 -2
- package/project/app/api/lib/resolve-project-root.js +120 -0
- package/project/app/api/package.json +16 -0
- package/project/app/api/parsers/architecture.js +72 -0
- package/project/app/api/parsers/board.js +141 -0
- package/project/app/api/parsers/documentation.js +125 -0
- package/project/app/api/parsers/git-log.js +52 -0
- package/project/app/api/parsers/ideas.js +62 -0
- package/project/app/api/parsers/knowledge-graph.js +73 -0
- package/project/app/api/parsers/lib/markdown-dir-reader.js +163 -0
- package/project/app/api/parsers/rapports.js +148 -0
- package/project/app/api/parsers/todo.js +179 -0
- package/project/app/api/response.js +47 -0
- package/project/app/api/routes/architecture.js +23 -0
- package/project/app/api/routes/board.js +46 -0
- package/project/app/api/routes/documentation.js +24 -0
- package/project/app/api/routes/health.js +25 -0
- package/project/app/api/routes/history.js +55 -0
- package/project/app/api/routes/rapports.js +24 -0
- package/project/app/api/scripts/capture-snapshot.js +294 -0
- package/project/app/api/server.js +112 -0
- package/project/app/api/types.js +40 -0
- package/project/app/package.json +21 -0
- package/project/app/ui/dist/assets/index-7fj-vllY.js +104 -0
- package/project/app/ui/dist/assets/index-CdK3Qrep.css +1 -0
- package/project/app/ui/dist/index.html +13 -0
- package/project/app/ui/package.json +23 -0
- package/project/app/ui/scripts/build-snapshot-html.cjs +214 -0
- package/project/app/ui/scripts/dashboard-open.cjs +88 -0
- package/project/app/ui/scripts/dashboard-start.cjs +87 -0
- package/scripts/acquire-concurrency-slot.sh +220 -0
- package/scripts/compute-deploy-reconcile.sh +439 -0
- package/scripts/jenga-permission-level-switch.sh +19 -3
- package/scripts/mark-deployed.sh +532 -0
- package/scripts/populate-knowledge-graph.js +429 -0
- package/scripts/release-concurrency-slot.sh +129 -0
- package/scripts/validate-board.sh +60 -2
- package/scripts/verify-consumer-install.sh +470 -0
- package/skills/j-cloud-connect/SKILL.md +95 -0
- package/skills/j-cloud-connect/scripts/configure-backend.sh +267 -0
- package/skills/j-cloud-connect/scripts/install-rclone.sh +153 -0
- package/skills/j-dashboard/SKILL.md +144 -0
- package/skills/j-dashboard/scripts/launch.sh +121 -0
- package/skills/j-dashboard/scripts/resolve-app-dir.sh +164 -0
- package/skills/j-dashboard/scripts/snapshot.sh +267 -0
- package/skills/j-dashboard-share/SKILL.md +96 -0
- package/skills/j-dashboard-share/scripts/upload-snapshot.sh +173 -0
- package/skills/j-init/SKILL.md +52 -13
- package/skills/j-init/assets/.gitignore_template +1 -2
- package/skills/j-init/scripts/apply-scaffold-visibility.sh +192 -0
- package/skills/j-init/scripts/init.sh +19 -5
- package/skills/j-playbook/SKILL.md +12 -0
- package/skills/j-playbook-new/SKILL.md +155 -0
- package/skills/j-playbook-new/scripts/playbook-new.sh +332 -0
- package/skills/j-publish/scripts/npm_ci_pipeline.sh +6 -0
- package/skills/j-skillify/assets/init-new/assets/.gitignore_template +1 -2
- package/skills/j-uncharted/SKILL.md +54 -7
- package/skills/j-uncharted/assets/NODE_QUESTION_TEMPLATE.md +69 -0
- package/skills/j-uncharted/scripts/elicitation-state.sh +45 -7
- package/skills/jenga/scripts/load-nl-catalog.js +22 -6
- package/skills/jenga/scripts/load-playbooks.sh +146 -35
- package/templates/SCRUM_BOARD_SCHEMA.md +18 -6
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# -----------------------------------------------------------------------------
|
|
3
|
+
# skills/j-dashboard-share/scripts/upload-snapshot.sh
|
|
4
|
+
#
|
|
5
|
+
# Uploads a local dashboard snapshot HTML file (as produced by j-dashboard's
|
|
6
|
+
# `scripts/snapshot.sh`) to a configured rclone remote via `rclone copyto`, at
|
|
7
|
+
# a templated, Drive-side (remote-side) destination path:
|
|
8
|
+
#
|
|
9
|
+
# JengaAI/<repo-directory-name>/<datetime>-board-snapshot.html
|
|
10
|
+
#
|
|
11
|
+
# - <repo-directory-name> is the basename of the repository root, derived
|
|
12
|
+
# via `basename "$(git rev-parse --show-toplevel)"` — never hardcoded to
|
|
13
|
+
# any specific project.
|
|
14
|
+
# - <datetime> is the actual UTC run time, formatted `%Y%m%dT%H%M%SZ`
|
|
15
|
+
# (compact ISO 8601-ish, sortable, filesystem/URL-safe).
|
|
16
|
+
#
|
|
17
|
+
# This destination path is entirely independent of the LOCAL snapshot
|
|
18
|
+
# filename (whatever `snapshot.sh --out` wrote it as) — this script only
|
|
19
|
+
# reads the local file's bytes and uploads them under its own remote-side
|
|
20
|
+
# name.
|
|
21
|
+
#
|
|
22
|
+
# Before attempting any upload, this script verifies the target rclone
|
|
23
|
+
# remote is actually configured (present in `rclone listremotes`). If it is
|
|
24
|
+
# not, this script does NOT attempt the upload and does NOT let rclone
|
|
25
|
+
# surface its own raw error — it dies with an actionable message pointing
|
|
26
|
+
# the user at `j.cloud-connect` (E60_S01) to configure a remote first.
|
|
27
|
+
#
|
|
28
|
+
# HARD SCOPE BOUNDARY: this script uploads ONLY. It never invokes
|
|
29
|
+
# `rclone link` or any other link-creating/sharing subcommand, anywhere in
|
|
30
|
+
# its logic — that is a deliberate, separate, manual action reserved for the
|
|
31
|
+
# user (see E47_S05's story decision). Do not add one.
|
|
32
|
+
#
|
|
33
|
+
# This script does not create or wire up the `j-dashboard-share` skill
|
|
34
|
+
# itself (SKILL.md) — that is a separate task (E47_S05_T02). It assumes a
|
|
35
|
+
# remote has already been configured via `j.cloud-connect`
|
|
36
|
+
# (skills/j-cloud-connect/scripts/{install-rclone.sh,configure-backend.sh},
|
|
37
|
+
# E60_S01) and that `rclone` is already on PATH.
|
|
38
|
+
#
|
|
39
|
+
# Invoked via `bash`, not executed directly: this script intentionally ships
|
|
40
|
+
# without the executable bit, matching the convention already documented in
|
|
41
|
+
# skills/j-cloud-connect/scripts/install-rclone.sh and
|
|
42
|
+
# skills/j-dashboard/scripts/resolve-app-dir.sh. Whatever wires this into the
|
|
43
|
+
# j-dashboard-share skill (E47_S05_T02) should invoke it as
|
|
44
|
+
# `bash skills/j-dashboard-share/scripts/upload-snapshot.sh`.
|
|
45
|
+
#
|
|
46
|
+
# Usage:
|
|
47
|
+
# upload-snapshot.sh --file <local-snapshot-path> --remote <remote-name>
|
|
48
|
+
#
|
|
49
|
+
# --file <path> Path to the local snapshot HTML file to upload (e.g.
|
|
50
|
+
# the output of `j.dashboard --snapshot`). Must exist
|
|
51
|
+
# and be non-empty.
|
|
52
|
+
# --remote <name> Name of an already-configured rclone remote (without a
|
|
53
|
+
# trailing colon), e.g. `gdrive`. Checked against
|
|
54
|
+
# `rclone listremotes` before any upload is attempted.
|
|
55
|
+
#
|
|
56
|
+
# Exit codes:
|
|
57
|
+
# 0 Upload succeeded. The full remote destination path is printed on
|
|
58
|
+
# stdout as the last line.
|
|
59
|
+
# 1 Any failure: bad arguments, missing/empty local file, `rclone` not on
|
|
60
|
+
# PATH, not inside a git repository, the target remote is not
|
|
61
|
+
# configured (points the user at `j.cloud-connect`), or `rclone copyto`
|
|
62
|
+
# itself failed. A human-readable reason is always printed to stderr.
|
|
63
|
+
# -----------------------------------------------------------------------------
|
|
64
|
+
|
|
65
|
+
set -euo pipefail
|
|
66
|
+
|
|
67
|
+
usage() {
|
|
68
|
+
cat <<'EOF'
|
|
69
|
+
Usage: upload-snapshot.sh --file <local-snapshot-path> --remote <remote-name>
|
|
70
|
+
|
|
71
|
+
Uploads a local dashboard snapshot HTML file to a configured rclone remote
|
|
72
|
+
via `rclone copyto`, at the templated destination path:
|
|
73
|
+
|
|
74
|
+
JengaAI/<repo-directory-name>/<datetime>-board-snapshot.html
|
|
75
|
+
|
|
76
|
+
--file <path> Path to the local snapshot HTML file to upload. Must
|
|
77
|
+
exist and be non-empty.
|
|
78
|
+
--remote <name> Name of an already-configured rclone remote (no
|
|
79
|
+
trailing colon). If not configured, this script tells
|
|
80
|
+
you to run j.cloud-connect instead of attempting the
|
|
81
|
+
upload.
|
|
82
|
+
|
|
83
|
+
Upload only — never runs `rclone link` or any other sharing/link-creating
|
|
84
|
+
command.
|
|
85
|
+
EOF
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
die() {
|
|
89
|
+
echo "Error: $*" >&2
|
|
90
|
+
exit 1
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
# -----------------------------------------------------------------------------
|
|
94
|
+
# Argument parsing.
|
|
95
|
+
# -----------------------------------------------------------------------------
|
|
96
|
+
|
|
97
|
+
LOCAL_FILE=""
|
|
98
|
+
REMOTE_NAME=""
|
|
99
|
+
|
|
100
|
+
while [ "$#" -gt 0 ]; do
|
|
101
|
+
case "$1" in
|
|
102
|
+
-h|--help)
|
|
103
|
+
usage
|
|
104
|
+
exit 0
|
|
105
|
+
;;
|
|
106
|
+
--file)
|
|
107
|
+
[ "$#" -ge 2 ] || die "--file requires a value"
|
|
108
|
+
LOCAL_FILE="$2"
|
|
109
|
+
shift 2
|
|
110
|
+
;;
|
|
111
|
+
--remote)
|
|
112
|
+
[ "$#" -ge 2 ] || die "--remote requires a value"
|
|
113
|
+
REMOTE_NAME="$2"
|
|
114
|
+
shift 2
|
|
115
|
+
;;
|
|
116
|
+
*)
|
|
117
|
+
usage >&2
|
|
118
|
+
die "unknown argument: $1"
|
|
119
|
+
;;
|
|
120
|
+
esac
|
|
121
|
+
done
|
|
122
|
+
|
|
123
|
+
[ -n "$LOCAL_FILE" ] || { usage >&2; die "--file is required"; }
|
|
124
|
+
[ -n "$REMOTE_NAME" ] || { usage >&2; die "--remote is required"; }
|
|
125
|
+
|
|
126
|
+
# -----------------------------------------------------------------------------
|
|
127
|
+
# Preflight — local file, rclone availability, git repository.
|
|
128
|
+
# -----------------------------------------------------------------------------
|
|
129
|
+
|
|
130
|
+
[ -f "$LOCAL_FILE" ] || die "local snapshot file not found: $LOCAL_FILE"
|
|
131
|
+
[ -s "$LOCAL_FILE" ] || die "local snapshot file is empty: $LOCAL_FILE"
|
|
132
|
+
|
|
133
|
+
command -v rclone >/dev/null 2>&1 || die "rclone is not on PATH. Install it first (see skills/j-cloud-connect/scripts/install-rclone.sh) and re-run."
|
|
134
|
+
|
|
135
|
+
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null)" || die "not inside a git repository — cannot derive <repo-directory-name> for the destination path. Run this script from within the project's repository."
|
|
136
|
+
REPO_DIR_NAME="$(basename "$REPO_ROOT")"
|
|
137
|
+
|
|
138
|
+
# -----------------------------------------------------------------------------
|
|
139
|
+
# Step 1 — Verify the target remote is actually configured BEFORE attempting
|
|
140
|
+
# any upload. Never let a raw rclone error surface for "remote not
|
|
141
|
+
# configured" — point the user at j.cloud-connect instead.
|
|
142
|
+
# -----------------------------------------------------------------------------
|
|
143
|
+
|
|
144
|
+
REMOTES_OUTPUT="$(rclone listremotes 2>&1)" || die "'rclone listremotes' failed: $REMOTES_OUTPUT"
|
|
145
|
+
|
|
146
|
+
if ! printf '%s\n' "$REMOTES_OUTPUT" | grep -Fxq "${REMOTE_NAME}:"; then
|
|
147
|
+
die "remote '$REMOTE_NAME' is not configured in rclone. Run j.cloud-connect first to set it up, then re-run this upload."
|
|
148
|
+
fi
|
|
149
|
+
|
|
150
|
+
# -----------------------------------------------------------------------------
|
|
151
|
+
# Step 2 — Build the templated destination path.
|
|
152
|
+
# -----------------------------------------------------------------------------
|
|
153
|
+
|
|
154
|
+
DATETIME="$(date -u +%Y%m%dT%H%M%SZ)"
|
|
155
|
+
DEST_RELATIVE_PATH="JengaAI/${REPO_DIR_NAME}/${DATETIME}-board-snapshot.html"
|
|
156
|
+
DEST="${REMOTE_NAME}:${DEST_RELATIVE_PATH}"
|
|
157
|
+
|
|
158
|
+
# -----------------------------------------------------------------------------
|
|
159
|
+
# Step 3 — Upload. stdio inherited (no capture/reformatting), matching this
|
|
160
|
+
# repo's j-cloud-connect script conventions. Upload only: this script never
|
|
161
|
+
# calls `rclone link` or any other sharing/link-creating command.
|
|
162
|
+
# -----------------------------------------------------------------------------
|
|
163
|
+
|
|
164
|
+
echo "Uploading '$LOCAL_FILE' to '$DEST'..."
|
|
165
|
+
|
|
166
|
+
COPY_EXIT=0
|
|
167
|
+
rclone copyto "$LOCAL_FILE" "$DEST" || COPY_EXIT=$?
|
|
168
|
+
if [ "$COPY_EXIT" -ne 0 ]; then
|
|
169
|
+
die "'rclone copyto $LOCAL_FILE $DEST' exited with status $COPY_EXIT. Upload did not succeed — see rclone's output above for the reason."
|
|
170
|
+
fi
|
|
171
|
+
|
|
172
|
+
echo "Upload succeeded."
|
|
173
|
+
echo "$DEST"
|
package/skills/j-init/SKILL.md
CHANGED
|
@@ -104,10 +104,41 @@ run can never silently relocate directories or edit `.gitignore`.
|
|
|
104
104
|
> `skills/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/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/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.
|
|
@@ -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/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"
|
|
@@ -4,6 +4,7 @@ set -euo pipefail
|
|
|
4
4
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
5
5
|
ASSETS_DIR="$SCRIPT_DIR/../assets"
|
|
6
6
|
VISIBILITY_SCRIPT="$SCRIPT_DIR/apply-project-visibility.sh"
|
|
7
|
+
SCAFFOLD_VISIBILITY_SCRIPT="$SCRIPT_DIR/apply-scaffold-visibility.sh"
|
|
7
8
|
|
|
8
9
|
# ─── Resolve the package root that owns templates/ and lib/ ──────────────────
|
|
9
10
|
# postinstall.js mirrors only skills/ and agents/ into .claude/ and .agents/ —
|
|
@@ -22,23 +23,33 @@ else
|
|
|
22
23
|
exit 1
|
|
23
24
|
fi
|
|
24
25
|
|
|
25
|
-
# ─── 0. Resolve project_files_visibility
|
|
26
|
+
# ─── 0. Resolve project_files_visibility and scaffold_visibility ─────────────
|
|
26
27
|
# Defaults to `visible` — the only value that touches nothing on disk — so an
|
|
27
28
|
# unattended run can never silently relocate directories or edit .gitignore.
|
|
29
|
+
# project_files_visibility covers the project/ working tree (board, todo.md,
|
|
30
|
+
# queue/, rapports/, logs/). scaffold_visibility is a distinct, independent
|
|
31
|
+
# flag (E31_S07_T01, ported here in E31_S07_T03) covering the distributed
|
|
32
|
+
# .claude/.agents framework scaffold — kept separate per
|
|
33
|
+
# skills/distribute/CONFIG_SCHEMA.md's "Scaffold visibility" section, rather
|
|
34
|
+
# than folded into project_files_visibility's existing enum.
|
|
28
35
|
VISIBILITY="${JENGA_PROJECT_FILES_VISIBILITY:-visible}"
|
|
36
|
+
SCAFFOLD_VISIBILITY="${JENGA_SCAFFOLD_VISIBILITY:-visible}"
|
|
29
37
|
|
|
30
38
|
while [[ $# -gt 0 ]]; do
|
|
31
39
|
case "$1" in
|
|
32
40
|
--visibility) VISIBILITY="${2:-}"; shift 2 ;;
|
|
33
41
|
--visibility=*) VISIBILITY="${1#*=}"; shift ;;
|
|
42
|
+
--scaffold-visibility) SCAFFOLD_VISIBILITY="${2:-}"; shift 2 ;;
|
|
43
|
+
--scaffold-visibility=*) SCAFFOLD_VISIBILITY="${1#*=}"; shift ;;
|
|
34
44
|
*) echo "Unknown argument: $1" >&2
|
|
35
|
-
echo "Usage: $(basename "$0") [--visibility <visible|ignored>]" >&2
|
|
45
|
+
echo "Usage: $(basename "$0") [--visibility <visible|ignored>] [--scaffold-visibility <visible|ignored>]" >&2
|
|
36
46
|
exit 1 ;;
|
|
37
47
|
esac
|
|
38
48
|
done
|
|
39
49
|
|
|
40
50
|
# Validate before scaffolding so a typo cannot leave a half-initialised project.
|
|
41
51
|
bash "$VISIBILITY_SCRIPT" --check-only "$VISIBILITY"
|
|
52
|
+
bash "$SCAFFOLD_VISIBILITY_SCRIPT" --check-only "$SCAFFOLD_VISIBILITY"
|
|
42
53
|
|
|
43
54
|
# ─── 1. Initialize git repository ────────────────────────────────────────────
|
|
44
55
|
echo "→ Initializing git repository..."
|
|
@@ -101,11 +112,14 @@ cp "$ASSETS_DIR/strategy_stub_template.md" docs/STRATEGY.md
|
|
|
101
112
|
echo "→ Creating CHANGELOG.md from template..."
|
|
102
113
|
cp "$PKG_ROOT/templates/CHANGELOG_TEMPLATE.md" CHANGELOG.md
|
|
103
114
|
|
|
104
|
-
# ─── 11. Apply project_files_visibility
|
|
105
|
-
#
|
|
106
|
-
# initial commit
|
|
115
|
+
# ─── 11. Apply project_files_visibility and scaffold_visibility ─────────────
|
|
116
|
+
# Both run before the commit so any resulting .gitignore entries (ignored)
|
|
117
|
+
# are captured in the initial commit rather than left for the user to notice
|
|
118
|
+
# after the fact.
|
|
107
119
|
echo "→ Applying project files visibility ($VISIBILITY)..."
|
|
108
120
|
bash "$VISIBILITY_SCRIPT" "$VISIBILITY" "$PWD"
|
|
121
|
+
echo "→ Applying scaffold visibility ($SCAFFOLD_VISIBILITY)..."
|
|
122
|
+
bash "$SCAFFOLD_VISIBILITY_SCRIPT" "$SCAFFOLD_VISIBILITY" "$PWD"
|
|
109
123
|
|
|
110
124
|
# ─── 12. Generate CLAUDE.md / AGENTS.md ──────────────────────────────────────
|
|
111
125
|
# Unconditional — never gated on agentTarget (E41_S04). Applies the J-
|
|
@@ -32,6 +32,18 @@ this skill is id resolution (step 1 below).
|
|
|
32
32
|
|
|
33
33
|
## Instructions
|
|
34
34
|
|
|
35
|
+
0. **Bare invocation — no id given.** If this skill was invoked with no argument at all, do not
|
|
36
|
+
proceed to step 1. Instead:
|
|
37
|
+
a. Invoke `skills/jenga/scripts/load-playbooks.sh` with no arguments (its existing full-catalog
|
|
38
|
+
mode — the same call step 1's `"not_found"` branch already uses for its "did you mean"
|
|
39
|
+
nudge; no new script is introduced for this).
|
|
40
|
+
b. Render the returned JSON array as a Markdown table with columns `Id`, `Name`, `Source`, and
|
|
41
|
+
`Steps`. For the `Source` column, render `Built-in` for a `source` field of `"builtin"` and
|
|
42
|
+
`Project` for `"project"`. For the `Steps` column, render each entry in that playbook's
|
|
43
|
+
`steps` array joined by `->`: a bare string step renders as itself; a StepObject step
|
|
44
|
+
renders its `skill` or `playbook` field value (whichever is present).
|
|
45
|
+
c. Halt this invocation after rendering the table — do not proceed to step 1.
|
|
46
|
+
|
|
35
47
|
1. **Resolve the id** — invoke `skills/jenga/scripts/load-playbooks.sh lookup "<id>"`
|
|
36
48
|
(`E53_S06_T02`), where `<id>` is this skill's argument. Branch on the returned `status` field:
|
|
37
49
|
|