@jenga-ai/agent 3.5.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +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 +79 -8
- 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 +5 -1
- package/project/app/api/lib/resolve-project-root.js +1 -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/package.json +4 -0
- package/project/app/ui/dist/assets/index-BADc5mmH.css +1 -0
- package/project/app/ui/dist/assets/index-C3oiuli_.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 +35 -5
- package/scripts/apply-j-prefix.sh +46 -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 +329 -0
- package/scripts/generate-legacy-shipped-paths.js +2 -2
- package/scripts/idea_manager.sh +273 -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/release-concurrency-slot.sh +34 -4
- package/scripts/render-ranked-list.sh +270 -0
- package/scripts/repoint-dead-bare-path-prose.py +81 -0
- package/scripts/repoint-skill-refs.sh +539 -0
- package/scripts/rewrite-stale-skill-preambles.py +188 -0
- package/scripts/strip-polyfill-frontmatter.py +166 -0
- package/scripts/todo_manager.sh +16 -1
- package/scripts/validate-typed-object.sh +750 -0
- 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-brainstorm/SKILL.md +3 -4
- package/skills/j-btw/SKILL.md +3 -4
- package/skills/j-clearify/SKILL.md +5 -6
- package/skills/j-close-story/SKILL.md +11 -12
- package/skills/j-close-story/scripts/check-privatized.sh +4 -4
- package/skills/j-close-story/scripts/check-story-closeable.sh +11 -4
- package/skills/j-commit/SKILL.md +3 -4
- package/skills/j-continue/SKILL.md +5 -6
- package/skills/j-deep-dive/SKILL.md +3 -4
- package/skills/j-distribute/CONFIG_SCHEMA.md +82 -5
- package/skills/j-distribute/SKILL.md +3 -4
- package/skills/j-do/SKILL.md +100 -18
- package/skills/j-doc/SKILL.md +3 -4
- package/skills/j-doc-sync/SKILL.md +4 -4
- package/skills/j-dooo/SKILL.md +6 -15
- package/skills/j-error/SKILL.md +3 -4
- package/skills/j-evaluate/SKILL.md +3 -4
- package/skills/j-examplify/SKILL.md +3 -4
- 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-help/SKILL.md +3 -4
- package/skills/j-idea/SKILL.md +80 -9
- package/skills/j-idea/assets/idea_template.md +1 -1
- package/skills/j-improve/SKILL.md +4 -5
- package/skills/j-init/SKILL.md +23 -14
- package/skills/j-init/assets/scope-thresholds_template.json +5 -2
- package/skills/j-init/scripts/apply-scaffold-visibility.sh +9 -7
- package/skills/j-init/scripts/init.sh +4 -4
- package/skills/j-jbp/SKILL.md +3 -4
- package/skills/j-lgtm/SKILL.md +3 -4
- package/skills/j-pi-plan/SKILL.md +3 -4
- package/skills/j-playbook/SKILL.md +1 -1
- package/skills/j-proceed/SKILL.md +3 -4
- package/skills/j-publish/SKILL.md +4 -5
- 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-publish/scripts/run_gates.sh +1 -1
- package/skills/j-reconcile/SKILL.md +40 -7
- package/skills/j-reconcile/assets/report_format.md +11 -0
- package/skills/j-reconcile/scripts/detect-unlinked-code.sh +13 -13
- package/skills/j-reconcile-origin/SKILL.md +3 -4
- package/skills/j-redo/SKILL.md +4 -5
- package/skills/j-skillify/SKILL.md +3 -4
- package/skills/j-spinoff/SKILL.md +4 -5
- package/skills/j-status/SKILL.md +18 -4
- package/skills/j-todo/SKILL.md +44 -5
- package/skills/j-todo/scripts/argument-is-not-ranked-list.sh +92 -0
- package/skills/j-todo/scripts/argument-is-ranked-list.sh +78 -0
- package/skills/j-uncharted/SKILL.md +252 -13
- package/skills/j-uncharted/scripts/detect-dependencies.sh +80 -22
- package/skills/j-uncharted/scripts/detect-tests.sh +1 -1
- package/skills/j-uncharted/scripts/diff-since-baseline.sh +600 -0
- package/skills/j-uncharted/scripts/elicitation-state.sh +1 -1
- package/skills/j-uncharted/scripts/find-scan-baseline.sh +545 -0
- package/skills/j-uncharted/scripts/run-engine.sh +36 -2
- package/skills/j-uncharted/scripts/validate-proposed-items.sh +1 -1
- package/skills/j-uncharted/scripts/write-scan-record.sh +361 -0
- package/skills/j-wtf/SKILL.md +4 -5
- package/skills/jenga/SKILL.md +106 -11
- 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.js +5 -2
- package/skills/jenga/scripts/load-nl-catalog.sh +1 -1
- package/skills/jenga/scripts/load-playbooks.sh +290 -5
- package/skills/jenga/scripts/match-playbook.sh +4 -4
- package/skills/jenga/scripts/run-playbook-step.sh +267 -1
- package/templates/SCRUM_BOARD_SCHEMA.md +14 -1
- package/templates/SKILL_TEMPLATE.md +12 -0
- package/templates/permission-levels/level-1-locked.json +1 -1
- package/templates/permission-levels/level-2-guarded.json +1 -1
- package/templates/permission-levels/level-3-standard.json +1 -1
- package/templates/permission-levels/level-4-elevated.json +2 -2
- package/templates/permission-levels/level-5-unrestricted.json +2 -2
- package/templates/playbook-types.json +40 -6
- package/project/app/ui/dist/assets/index-7fj-vllY.js +0 -104
- package/project/app/ui/dist/assets/index-CdK3Qrep.css +0 -1
- package/scripts/audit-twin-divergence.sh +0 -625
- 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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: j.examplify
|
|
3
|
-
description:
|
|
3
|
+
description: Explains concepts, features, use cases, and patterns based on provided context — a description, scenario, code snippet, or file. Use when the user wants to understand what something is, how it works, when to use it, or wants a concrete example.
|
|
4
4
|
keywords:
|
|
5
5
|
- examplify
|
|
6
6
|
- explain
|
|
@@ -8,7 +8,6 @@ keywords:
|
|
|
8
8
|
- how does
|
|
9
9
|
- understand
|
|
10
10
|
- j-examplify
|
|
11
|
-
- polyfill
|
|
12
11
|
examples:
|
|
13
12
|
- "explain how this works"
|
|
14
13
|
- "give me an example of X"
|
|
@@ -17,9 +16,9 @@ examples:
|
|
|
17
16
|
|
|
18
17
|
# Concept Explainer
|
|
19
18
|
|
|
20
|
-
|
|
19
|
+
`skills/j-examplify/` is the **canonical, hand-edited** directory for this skill, per CLAUDE.md's "The Canonical Naming Contract" (the `E50` reopening of 2026-09-09, which promoted `skills/j-examplify/` from generated twin to sole canonical form). The `j-` prefix is there for collision safety — a real directory under a distinct name, so a host tool shipping its own same-named built-in command cannot shadow it (Claude Code's native skill resolution is a literal-string, directory-name-based match; see `docs/skill-authoring.md`'s "Invocation Convention").
|
|
21
20
|
|
|
22
|
-
|
|
21
|
+
> ⚠️ **`scripts/generate-j-alias.sh` was retired by `E50_S14` and no longer exists — there is nothing to run.** This file was previously generated from a bare `skills/examplify/SKILL.md` source; `E50_S15` deleted that directory. This file is now the sole canonical, hand-edited source for this skill — edit it directly.
|
|
23
22
|
|
|
24
23
|
## Instructions
|
|
25
24
|
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: j.gitignore
|
|
3
|
+
description: Retroactively repair an already-scaffolded project's Jenga gitignore state — strips the stray heredoc `EOF` line left by pre-fix /init scaffolds, adds or removes the Jenga-owned path entries via a managed block, and untracks those paths from git (and from origin) while leaving every file on disk.
|
|
4
|
+
keywords:
|
|
5
|
+
- gitignore
|
|
6
|
+
- fix gitignore
|
|
7
|
+
- untrack jenga files
|
|
8
|
+
- remove from origin
|
|
9
|
+
- stray EOF
|
|
10
|
+
- jenga files committed
|
|
11
|
+
- stop tracking scaffold
|
|
12
|
+
examples:
|
|
13
|
+
- "jenga files keep getting committed"
|
|
14
|
+
- "remove .claude and .agents from the repo but keep them locally"
|
|
15
|
+
- "my .gitignore has a stray EOF line"
|
|
16
|
+
- "untrack the jenga scaffold from origin"
|
|
17
|
+
- "j.gitignore"
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
# j.gitignore
|
|
21
|
+
|
|
22
|
+
Repairs the Jenga-related git state of a project that was **already scaffolded**. `/init` does this
|
|
23
|
+
correctly for new projects; this skill is the retroactive path for projects created before the fix,
|
|
24
|
+
or projects whose ignore rules have drifted.
|
|
25
|
+
|
|
26
|
+
## When to use this
|
|
27
|
+
|
|
28
|
+
- `.gitignore` contains a stray `EOF` line (the signature of the botched `cat > .gitignore <<EOF` in
|
|
29
|
+
pre-fix `/init` scaffolds).
|
|
30
|
+
- `.claude/`, `.agents/`, `jenga.config.json`, `.jenga-version` etc. are being committed even though
|
|
31
|
+
you expected Jenga to ignore them.
|
|
32
|
+
- You want the Jenga scaffold gone from the remote, but still working locally.
|
|
33
|
+
- You want to **reverse** any of the above and commit the scaffold deliberately.
|
|
34
|
+
|
|
35
|
+
## Why /init cannot do this
|
|
36
|
+
|
|
37
|
+
`skills/j-init/SKILL.md` hard-stops on `already-scaffolded`, and for good reason: `init.sh` does an
|
|
38
|
+
unconditional `cp "$ASSETS_DIR/.gitignore_template" .gitignore`, which would clobber the project's
|
|
39
|
+
existing `.gitignore`, and later steps overwrite `PROJECT_SUMMARY.md`, `workflow.json` and
|
|
40
|
+
`test-config.json` with fresh stubs. The upstream fixes (`E31_S07_T02`/`T03`, `E42_S06_T01`) repaired
|
|
41
|
+
the **template**, which is forward-only. Nothing repairs a project already on disk. That is this
|
|
42
|
+
skill's entire reason to exist.
|
|
43
|
+
|
|
44
|
+
`apply-project-visibility.sh` and `apply-scaffold-visibility.sh` remain the **init-time** path and are
|
|
45
|
+
not replaced. They only ever append `project/`, `.claude/` and `.agents/` as loose lines — they do not
|
|
46
|
+
remove a stray `EOF`, do not cover the file-level paths, and cannot untrack anything.
|
|
47
|
+
|
|
48
|
+
## Scripts
|
|
49
|
+
|
|
50
|
+
All three ship without the executable bit — invoke via `bash`. All are bash 3.2 compatible (macOS).
|
|
51
|
+
|
|
52
|
+
| Script | Role |
|
|
53
|
+
|---|---|
|
|
54
|
+
| `scripts/audit-gitignore.sh` | Read-only. Reports stray terminators, per-path entry/ignored/tracked state, and what is present on origin. Exit `10` means findings, `0` means clean. |
|
|
55
|
+
| `scripts/repair-gitignore.sh` | Strips stray `EOF` lines, then adds (`ignored`) or removes (`visible`) the entries inside a managed block. Atomic write, verified after. |
|
|
56
|
+
| `scripts/untrack-jenga-files.sh` | `git rm -r --cached` — stops tracking, never deletes from disk. Optional `--commit`, opt-in `--push`. |
|
|
57
|
+
| `assets/jenga-paths.txt` | The single catalog of Jenga-owned paths, tiered. All three scripts read it. |
|
|
58
|
+
|
|
59
|
+
## Path tiers
|
|
60
|
+
|
|
61
|
+
`--tiers` selects what to act on. Default is `scaffold` — the safe set.
|
|
62
|
+
|
|
63
|
+
| Tier | Contents | Default |
|
|
64
|
+
|---|---|---|
|
|
65
|
+
| `scaffold` | `.claude/`, `.agents/`, `.jenga/`, `.jenga-version`, `jenga.config.json`, `.github/hooks/jenga.json`, `J-CLAUDE.md`, `J-AGENTS.md` — entirely Jenga-owned, regenerated by postinstall/`/distribute`. | ✅ on |
|
|
66
|
+
| `hybrid` | `CLAUDE.md`, `AGENTS.md`, `.github/copilot-instructions.md` — Jenga writes a *managed block* and preserves your content around it. Ignoring these hides **your** prose too. | opt-in |
|
|
67
|
+
| `board` | `project/` — governed by `project_files_visibility`. Teams sharing a board want it tracked. | opt-in |
|
|
68
|
+
| `optional` | `.copilot/` — not generated by any current Jenga version. Defensive only. | opt-in |
|
|
69
|
+
|
|
70
|
+
## Procedure
|
|
71
|
+
|
|
72
|
+
### 1. Audit
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
bash <skill>/scripts/audit-gitignore.sh . --tiers scaffold
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Present the three summary counts to the user. If `AUDIT_RESULT=clean`, say so and stop — there is
|
|
79
|
+
nothing to repair.
|
|
80
|
+
|
|
81
|
+
### 2. Confirm scope
|
|
82
|
+
|
|
83
|
+
The audit's per-path table shows what is tracked. Before changing anything, ask:
|
|
84
|
+
|
|
85
|
+
Which Jenga paths should this project ignore?
|
|
86
|
+
1. Scaffold only — .claude/, .agents/, jenga.config.json, .jenga-version, hook + J- files (recommended)
|
|
87
|
+
2. Scaffold + the board (project/) — adds your scrum board, todo.md, queue, rapports, logs
|
|
88
|
+
3. Scaffold + CLAUDE.md / AGENTS.md / copilot-instructions.md — note these may contain your own prose
|
|
89
|
+
4. Everything, including the defensive .copilot/ entry
|
|
90
|
+
5. Other (describe below)
|
|
91
|
+
|
|
92
|
+
Two warnings to surface if they are in scope:
|
|
93
|
+
|
|
94
|
+
- **`jenga.config.json`** holds `project_files_visibility` and `scaffold_visibility`. Ignoring it
|
|
95
|
+
means a fresh clone loses those settings and the next `/init`-style run re-prompts for them.
|
|
96
|
+
- **`hybrid` tier** files contain user-authored content outside Jenga's managed block. Ignoring them
|
|
97
|
+
removes that content from the repo too.
|
|
98
|
+
|
|
99
|
+
### 3. Repair the .gitignore
|
|
100
|
+
|
|
101
|
+
Always dry-run first and show the diff:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
bash <skill>/scripts/repair-gitignore.sh ignored . --tiers <tiers> --dry-run
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Then apply without `--dry-run`. This step is purely local and reversible (`visible` mode removes the
|
|
108
|
+
block again), so it does not need separate confirmation beyond the scope choice in step 2.
|
|
109
|
+
|
|
110
|
+
If the user genuinely wants to ignore a file literally named `EOF`, pass `--keep-eof`.
|
|
111
|
+
|
|
112
|
+
### 4. Untrack
|
|
113
|
+
|
|
114
|
+
`.gitignore` has no effect on files git already tracks, so step 3 alone changes nothing for anything
|
|
115
|
+
already committed. Dry-run first:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
bash <skill>/scripts/untrack-jenga-files.sh . --tiers <tiers> --dry-run
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Then choose how far to go:
|
|
122
|
+
|
|
123
|
+
The .gitignore is fixed. How far should I take the untracking?
|
|
124
|
+
1. Stage the removals only — I review `git status` and commit myself
|
|
125
|
+
2. Stage and commit locally — nothing reaches the remote until I push
|
|
126
|
+
3. Stage, commit, and push — removes them from origin's branch tip
|
|
127
|
+
4. Stop here — just the .gitignore change
|
|
128
|
+
5. Other (describe below)
|
|
129
|
+
|
|
130
|
+
Map to `--commit` / `--commit --push` accordingly. **Never pass `--push` without the user explicitly
|
|
131
|
+
choosing option 3** — it is the only outward-facing step and cannot be undone by re-running the skill.
|
|
132
|
+
|
|
133
|
+
### 5. Report
|
|
134
|
+
|
|
135
|
+
Re-run the audit to confirm `AUDIT_RESULT=clean`, then state plainly what changed, and always
|
|
136
|
+
include the history caveat below.
|
|
137
|
+
|
|
138
|
+
## What this does NOT do
|
|
139
|
+
|
|
140
|
+
- **It does not rewrite history.** `--push` removes the paths from the branch *tip*. Every earlier
|
|
141
|
+
commit still contains them, and the blobs stay reachable. A fresh clone is clean; `git log` is not.
|
|
142
|
+
- **It is not a secret scrubber.** If a `.env` or credential was committed, treat it as compromised,
|
|
143
|
+
rotate it, and use `git-filter-repo` separately. Say this out loud if the audit shows anything
|
|
144
|
+
credential-shaped.
|
|
145
|
+
- **It never deletes from disk.** Every removal is `git rm --cached`, and the script re-verifies each
|
|
146
|
+
path is still present before reporting success.
|
|
147
|
+
|
|
148
|
+
## Edge cases
|
|
149
|
+
|
|
150
|
+
| Situation | Behavior |
|
|
151
|
+
|---|---|
|
|
152
|
+
| No `.gitignore` at the root | `ignored` creates one; `visible` exits 0 as a no-op. |
|
|
153
|
+
| No git repo | All three exit 1 with a clear message — this skill needs git. |
|
|
154
|
+
| No upstream branch | Audit says nothing was ever pushed. `--push` refuses rather than guessing a remote; the commit is already safe locally. |
|
|
155
|
+
| Unrelated staged changes | `untrack-jenga-files.sh` refuses (exit 4) so it cannot sweep your work into its commit. A staged `.gitignore` alone is allowed through and folded in, since it is the companion change. |
|
|
156
|
+
| Unterminated managed block | `repair-gitignore.sh` refuses to write (exit 3) rather than risk eating the rest of the file. |
|
|
157
|
+
| Path tracked but absent from disk | Reported as a warning; nothing was lost, git simply tracked something the working tree did not have. |
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# skills/j-gitignore/assets/jenga-paths.txt
|
|
2
|
+
#
|
|
3
|
+
# The canonical catalog of Jenga-owned paths a consuming project may end up
|
|
4
|
+
# with on disk. Consumed by audit-gitignore.sh, repair-gitignore.sh and
|
|
5
|
+
# untrack-jenga-files.sh — all three read this one file, so the path surface
|
|
6
|
+
# is defined in exactly one place.
|
|
7
|
+
#
|
|
8
|
+
# Format: <tier>TAB<path>TAB<description>
|
|
9
|
+
# Blank lines and lines starting with '#' are ignored.
|
|
10
|
+
#
|
|
11
|
+
# Trailing '/' marks a directory entry and is preserved verbatim into
|
|
12
|
+
# .gitignore (git treats 'foo/' as directory-only, which is what we want).
|
|
13
|
+
#
|
|
14
|
+
# ─── Tiers ───────────────────────────────────────────────────────────────────
|
|
15
|
+
#
|
|
16
|
+
# scaffold Entirely Jenga-owned. Regenerated wholesale by `npm postinstall`
|
|
17
|
+
# or `/distribute`, so nothing of yours is ever lost by ignoring
|
|
18
|
+
# them. Safe default.
|
|
19
|
+
#
|
|
20
|
+
# hybrid A Jenga-managed block inside a file that ALSO holds your own
|
|
21
|
+
# content. lib/generate-agent-context.js and
|
|
22
|
+
# lib/generate-copilot-instructions.js both replace only their
|
|
23
|
+
# managed block and preserve everything outside it. Ignoring these
|
|
24
|
+
# therefore also hides YOUR prose from the repo. Opt-in, never
|
|
25
|
+
# applied without the user saying so.
|
|
26
|
+
#
|
|
27
|
+
# board The project/ working tree (scrum board, todo.md, queue/,
|
|
28
|
+
# rapports/, logs/). Governed by jenga.config.json's
|
|
29
|
+
# `project_files_visibility`. Teams that share a board want this
|
|
30
|
+
# tracked; solo users usually do not. Opt-in.
|
|
31
|
+
#
|
|
32
|
+
# optional Defensive entries for paths no current Jenga version generates.
|
|
33
|
+
# Costs nothing to ignore, guards against a future or third-party
|
|
34
|
+
# agent surface appearing. Opt-in.
|
|
35
|
+
#
|
|
36
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
37
|
+
|
|
38
|
+
scaffold .claude/ Claude Code skill/agent mirror — rewritten by every postinstall and /distribute run (scripts/postinstall.js targetRoots). Contains .jenga-postinstall-manifest.json.
|
|
39
|
+
scaffold .agents/ Copilot/Codex skill/agent mirror — the second of postinstall.js's two targetRoots. Contains .jenga-postinstall-manifest.json.
|
|
40
|
+
scaffold .jenga/ `jenga` CLI state directory. lib/commands/init.js already appends this entry itself; listed here so the audit reports it consistently.
|
|
41
|
+
scaffold .jenga-version Installed-version stamp written at consumer root by scripts/postinstall.js.
|
|
42
|
+
scaffold jenga.config.json Jenga project config (project_files_visibility, scaffold_visibility). SEE THE WARNING IN SKILL.md — ignoring this means a fresh clone loses your visibility settings.
|
|
43
|
+
scaffold .github/hooks/jenga.json Copilot CLI hook wiring. "Entirely Jenga-owned output" per scripts/postinstall.js — no user content, unlike copilot-instructions.md.
|
|
44
|
+
scaffold J-CLAUDE.md Collision-case copy written only when you already had your own CLAUDE.md. A J- file can only ever have been created by Jenga.
|
|
45
|
+
scaffold J-AGENTS.md Collision-case copy written only when you already had your own AGENTS.md. Jenga-created by definition.
|
|
46
|
+
hybrid CLAUDE.md Jenga writes a managed block here and preserves content outside it. May contain your own instructions.
|
|
47
|
+
hybrid AGENTS.md Same managed-block treatment as CLAUDE.md, for Codex and generic AGENTS.md consumers.
|
|
48
|
+
hybrid .github/copilot-instructions.md Managed-block bootstrap. postinstall.js explicitly notes this one is NOT entirely Jenga-owned.
|
|
49
|
+
board project/ The whole Jenga working tree. Mirrors what apply-project-visibility.sh's JENGA_WORKING_PATHS appends at init time.
|
|
50
|
+
optional .copilot/ Not generated by any current Jenga version (grepped across lib/, scripts/, skills/). Defensive only.
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# -----------------------------------------------------------------------------
|
|
3
|
+
# skills/j-gitignore/scripts/_catalog.sh
|
|
4
|
+
#
|
|
5
|
+
# Shared helpers for the j-gitignore scripts. Sourced, never run directly:
|
|
6
|
+
#
|
|
7
|
+
# source "$(dirname "${BASH_SOURCE[0]}")/_catalog.sh"
|
|
8
|
+
#
|
|
9
|
+
# Provides:
|
|
10
|
+
# CATALOG_FILE absolute path to assets/jenga-paths.txt
|
|
11
|
+
# MANAGED_BEGIN/_END the managed-block markers
|
|
12
|
+
# load_catalog <tiers> populates CATALOG_PATHS/_TIERS/_DESCS arrays
|
|
13
|
+
# validate_tiers <csv> rejects an unknown tier name
|
|
14
|
+
# resolve_root <dir> cd's to a project root, verifying it is a git repo
|
|
15
|
+
#
|
|
16
|
+
# The leading underscore marks this as internal to the skill — it is not an
|
|
17
|
+
# entry point and takes no arguments of its own.
|
|
18
|
+
# -----------------------------------------------------------------------------
|
|
19
|
+
|
|
20
|
+
# Deliberately no `set -e` — callers handle their own errors, matching the
|
|
21
|
+
# convention in skills/j-init/scripts/apply-scaffold-visibility.sh.
|
|
22
|
+
set -uo pipefail
|
|
23
|
+
|
|
24
|
+
_CATALOG_LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
25
|
+
CATALOG_FILE="${_CATALOG_LIB_DIR}/../assets/jenga-paths.txt"
|
|
26
|
+
|
|
27
|
+
MANAGED_BEGIN="# >>> jenga:gitignore >>>"
|
|
28
|
+
MANAGED_END="# <<< jenga:gitignore <<<"
|
|
29
|
+
|
|
30
|
+
VALID_TIERS="scaffold hybrid board optional"
|
|
31
|
+
|
|
32
|
+
# Populated by load_catalog.
|
|
33
|
+
CATALOG_PATHS=()
|
|
34
|
+
CATALOG_TIERS=()
|
|
35
|
+
CATALOG_DESCS=()
|
|
36
|
+
|
|
37
|
+
validate_tiers() {
|
|
38
|
+
local csv="$1" tier valid found
|
|
39
|
+
[ -n "$csv" ] || { echo "ERROR: --tiers was given an empty value." >&2; return 2; }
|
|
40
|
+
# Split on commas into an array FIRST, then restore IFS. Setting IFS=',' for
|
|
41
|
+
# the duration of both loops would stop the space-separated $VALID_TIERS from
|
|
42
|
+
# splitting, making every tier look invalid.
|
|
43
|
+
local -a requested=()
|
|
44
|
+
local old_ifs="$IFS"
|
|
45
|
+
IFS=','; read -r -a requested <<< "$csv"; IFS="$old_ifs"
|
|
46
|
+
for tier in "${requested[@]}"; do
|
|
47
|
+
found=0
|
|
48
|
+
for valid in $VALID_TIERS; do
|
|
49
|
+
[ "$tier" = "$valid" ] && found=1 && break
|
|
50
|
+
done
|
|
51
|
+
if [ "$found" -eq 0 ]; then
|
|
52
|
+
echo "ERROR: Unknown tier '${tier}'. Valid tiers: ${VALID_TIERS// /, }" >&2
|
|
53
|
+
return 2
|
|
54
|
+
fi
|
|
55
|
+
done
|
|
56
|
+
return 0
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
# load_catalog <comma-separated-tiers>
|
|
60
|
+
# Reads CATALOG_FILE, keeping only rows whose tier is in the requested set.
|
|
61
|
+
load_catalog() {
|
|
62
|
+
local want="$1"
|
|
63
|
+
CATALOG_PATHS=(); CATALOG_TIERS=(); CATALOG_DESCS=()
|
|
64
|
+
|
|
65
|
+
if [ ! -f "$CATALOG_FILE" ]; then
|
|
66
|
+
echo "ERROR: Path catalog not found: $CATALOG_FILE" >&2
|
|
67
|
+
return 1
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
local tier path desc
|
|
71
|
+
while IFS=$'\t' read -r tier path desc || [ -n "${tier:-}" ]; do
|
|
72
|
+
[ -z "${tier// /}" ] && continue
|
|
73
|
+
case "$tier" in \#*) continue ;; esac
|
|
74
|
+
[ -n "${path:-}" ] || continue
|
|
75
|
+
case ",${want}," in
|
|
76
|
+
*",${tier},"*)
|
|
77
|
+
CATALOG_PATHS+=("$path")
|
|
78
|
+
CATALOG_TIERS+=("$tier")
|
|
79
|
+
CATALOG_DESCS+=("${desc:-}")
|
|
80
|
+
;;
|
|
81
|
+
esac
|
|
82
|
+
done < "$CATALOG_FILE"
|
|
83
|
+
|
|
84
|
+
if [ "${#CATALOG_PATHS[@]}" -eq 0 ]; then
|
|
85
|
+
echo "ERROR: No catalog entries matched tiers '${want}'." >&2
|
|
86
|
+
return 1
|
|
87
|
+
fi
|
|
88
|
+
return 0
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
# resolve_root <dir> — cd into it and confirm it is the root of a git work tree.
|
|
92
|
+
resolve_root() {
|
|
93
|
+
local root="$1"
|
|
94
|
+
if [ ! -d "$root" ]; then
|
|
95
|
+
echo "ERROR: Project root does not exist: $root" >&2
|
|
96
|
+
return 1
|
|
97
|
+
fi
|
|
98
|
+
cd "$root" || { echo "ERROR: Cannot enter project root: $root" >&2; return 1; }
|
|
99
|
+
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
100
|
+
echo "ERROR: Not a git repository: $root" >&2
|
|
101
|
+
echo " This skill repairs a project's tracked/ignored state, so it needs git." >&2
|
|
102
|
+
return 1
|
|
103
|
+
fi
|
|
104
|
+
return 0
|
|
105
|
+
}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# -----------------------------------------------------------------------------
|
|
3
|
+
# skills/j-gitignore/scripts/audit-gitignore.sh
|
|
4
|
+
#
|
|
5
|
+
# Read-only. Reports the Jenga-related git state of an already-scaffolded
|
|
6
|
+
# project. Changes nothing — this is the "check" half of the skill, safe to run
|
|
7
|
+
# anywhere, any number of times.
|
|
8
|
+
#
|
|
9
|
+
# Reports three independent things per catalog path:
|
|
10
|
+
#
|
|
11
|
+
# entry Is the exact entry literally present in .gitignore?
|
|
12
|
+
# ignored Does git actually ignore the path (`git check-ignore`)? This can
|
|
13
|
+
# be true via a broader rule even when `entry` is no — and is
|
|
14
|
+
# ALWAYS reported as "no" for a tracked path, because .gitignore
|
|
15
|
+
# has no effect on a file git already tracks. That divergence is
|
|
16
|
+
# the single most common cause of "I ignored it and it still keeps
|
|
17
|
+
# getting committed".
|
|
18
|
+
# tracked Does git currently track anything under the path?
|
|
19
|
+
#
|
|
20
|
+
# Plus the stray-heredoc-terminator check: a bare `EOF` line left behind by the
|
|
21
|
+
# botched `cat > .gitignore <<EOF` in pre-fix /init scaffolds (fixed for NEW
|
|
22
|
+
# projects by E31_S07_T02/T03 and E42_S06_T01, which replaced the heredoc with
|
|
23
|
+
# a `cp` from assets/.gitignore_template — forward-only, so already-scaffolded
|
|
24
|
+
# projects still carry the damage).
|
|
25
|
+
#
|
|
26
|
+
# Invoked via `bash`, not executed directly — ships without the executable bit,
|
|
27
|
+
# same convention as skills/j-cloud-connect/scripts/install-rclone.sh.
|
|
28
|
+
#
|
|
29
|
+
# Usage:
|
|
30
|
+
# audit-gitignore.sh [project_root] [--tiers scaffold,hybrid,board,optional]
|
|
31
|
+
#
|
|
32
|
+
# Exit codes:
|
|
33
|
+
# 0 Audit ran; nothing to fix
|
|
34
|
+
# 1 Bad usage or missing prerequisite (not a git repo, catalog missing)
|
|
35
|
+
# 2 Invalid tier name
|
|
36
|
+
# 10 Audit ran; findings exist (stray terminators, missing entries, or
|
|
37
|
+
# tracked paths). Not an error — this is the signal to run the repair.
|
|
38
|
+
# -----------------------------------------------------------------------------
|
|
39
|
+
|
|
40
|
+
set -uo pipefail
|
|
41
|
+
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/_catalog.sh"
|
|
42
|
+
|
|
43
|
+
PROJECT_ROOT=""
|
|
44
|
+
TIERS="scaffold"
|
|
45
|
+
|
|
46
|
+
while [ $# -gt 0 ]; do
|
|
47
|
+
case "$1" in
|
|
48
|
+
--tiers) TIERS="${2:-}"; shift 2 ;;
|
|
49
|
+
--tiers=*) TIERS="${1#*=}"; shift ;;
|
|
50
|
+
-h|--help)
|
|
51
|
+
echo "Usage: $(basename "$0") [project_root] [--tiers scaffold,hybrid,board,optional]"
|
|
52
|
+
exit 0 ;;
|
|
53
|
+
-*)
|
|
54
|
+
echo "ERROR: Unknown option: $1" >&2
|
|
55
|
+
echo "Usage: $(basename "$0") [project_root] [--tiers <csv>]" >&2
|
|
56
|
+
exit 1 ;;
|
|
57
|
+
*)
|
|
58
|
+
if [ -n "$PROJECT_ROOT" ]; then
|
|
59
|
+
echo "ERROR: More than one project root given: '$PROJECT_ROOT' and '$1'" >&2
|
|
60
|
+
exit 1
|
|
61
|
+
fi
|
|
62
|
+
PROJECT_ROOT="$1"; shift ;;
|
|
63
|
+
esac
|
|
64
|
+
done
|
|
65
|
+
|
|
66
|
+
PROJECT_ROOT="${PROJECT_ROOT:-$PWD}"
|
|
67
|
+
validate_tiers "$TIERS" || exit 2
|
|
68
|
+
resolve_root "$PROJECT_ROOT" || exit 1
|
|
69
|
+
load_catalog "$TIERS" || exit 1
|
|
70
|
+
|
|
71
|
+
GITIGNORE=".gitignore"
|
|
72
|
+
FINDINGS=0
|
|
73
|
+
|
|
74
|
+
echo "═══════════════════════════════════════════════════════════════════════"
|
|
75
|
+
echo " Jenga gitignore audit — $(pwd)"
|
|
76
|
+
echo " Tiers: ${TIERS}"
|
|
77
|
+
echo "═══════════════════════════════════════════════════════════════════════"
|
|
78
|
+
echo
|
|
79
|
+
|
|
80
|
+
# ─── 1. Stray heredoc terminators ───────────────────────────────────────────
|
|
81
|
+
echo "── 1. Stray heredoc terminators ───────────────────────────────────────"
|
|
82
|
+
STRAY_COUNT=0
|
|
83
|
+
if [ ! -f "$GITIGNORE" ]; then
|
|
84
|
+
echo " No .gitignore at this root — nothing to check."
|
|
85
|
+
else
|
|
86
|
+
# A line that is exactly EOF (tolerating trailing whitespace). Reported with
|
|
87
|
+
# line numbers so a human can eyeball it before anything is removed.
|
|
88
|
+
while IFS= read -r hit; do
|
|
89
|
+
[ -z "$hit" ] && continue
|
|
90
|
+
echo " ✗ line ${hit%%:*}: stray '${hit#*:}' terminator"
|
|
91
|
+
STRAY_COUNT=$((STRAY_COUNT + 1))
|
|
92
|
+
done < <(grep -nE '^[[:space:]]*EOF[[:space:]]*$' "$GITIGNORE" 2>/dev/null)
|
|
93
|
+
|
|
94
|
+
if [ "$STRAY_COUNT" -eq 0 ]; then
|
|
95
|
+
echo " ✓ Clean — no stray terminator lines."
|
|
96
|
+
else
|
|
97
|
+
echo
|
|
98
|
+
echo " → ${STRAY_COUNT} stray line(s). repair-gitignore.sh removes these."
|
|
99
|
+
FINDINGS=$((FINDINGS + STRAY_COUNT))
|
|
100
|
+
fi
|
|
101
|
+
fi
|
|
102
|
+
echo
|
|
103
|
+
|
|
104
|
+
# ─── 2. Managed block ────────────────────────────────────────────────────────
|
|
105
|
+
echo "── 2. Managed block ───────────────────────────────────────────────────"
|
|
106
|
+
if [ -f "$GITIGNORE" ] && grep -qxF -- "$MANAGED_BEGIN" "$GITIGNORE"; then
|
|
107
|
+
echo " ✓ Present — this project has been through repair-gitignore.sh before."
|
|
108
|
+
else
|
|
109
|
+
echo " · Absent — entries (if any) are loose, e.g. appended by /init's"
|
|
110
|
+
echo " apply-project-visibility.sh / apply-scaffold-visibility.sh."
|
|
111
|
+
fi
|
|
112
|
+
echo
|
|
113
|
+
|
|
114
|
+
# ─── 3. Per-path state ───────────────────────────────────────────────────────
|
|
115
|
+
echo "── 3. Per-path state ──────────────────────────────────────────────────"
|
|
116
|
+
printf " %-34s %-7s %-8s %-8s %s\n" "PATH" "ENTRY" "IGNORED" "TRACKED" "TIER"
|
|
117
|
+
printf " %-34s %-7s %-8s %-8s %s\n" "----" "-----" "-------" "-------" "----"
|
|
118
|
+
|
|
119
|
+
MISSING_ENTRIES=0
|
|
120
|
+
TRACKED_PATHS=()
|
|
121
|
+
|
|
122
|
+
for i in "${!CATALOG_PATHS[@]}"; do
|
|
123
|
+
path="${CATALOG_PATHS[$i]}"
|
|
124
|
+
tier="${CATALOG_TIERS[$i]}"
|
|
125
|
+
|
|
126
|
+
entry="no"
|
|
127
|
+
if [ -f "$GITIGNORE" ] && grep -qxF -- "$path" "$GITIGNORE"; then
|
|
128
|
+
entry="yes"
|
|
129
|
+
fi
|
|
130
|
+
|
|
131
|
+
# check-ignore works on paths that do not exist on disk, so a not-yet-created
|
|
132
|
+
# scaffold dir is still evaluated against the rules.
|
|
133
|
+
ignored="no"
|
|
134
|
+
if git check-ignore -q -- "$path" 2>/dev/null; then
|
|
135
|
+
ignored="yes"
|
|
136
|
+
fi
|
|
137
|
+
|
|
138
|
+
tracked="no"
|
|
139
|
+
if [ -n "$(git ls-files -- "$path" 2>/dev/null | head -n 1)" ]; then
|
|
140
|
+
tracked="yes"
|
|
141
|
+
TRACKED_PATHS+=("$path")
|
|
142
|
+
fi
|
|
143
|
+
|
|
144
|
+
flag=""
|
|
145
|
+
if [ "$entry" = "no" ]; then flag=" ← no entry"; MISSING_ENTRIES=$((MISSING_ENTRIES + 1)); fi
|
|
146
|
+
if [ "$tracked" = "yes" ]; then flag="${flag} ← TRACKED"; fi
|
|
147
|
+
|
|
148
|
+
printf " %-34s %-7s %-8s %-8s %s%s\n" "$path" "$entry" "$ignored" "$tracked" "$tier" "$flag"
|
|
149
|
+
done
|
|
150
|
+
echo
|
|
151
|
+
|
|
152
|
+
# ─── 4. Origin state ─────────────────────────────────────────────────────────
|
|
153
|
+
echo "── 4. Origin ──────────────────────────────────────────────────────────"
|
|
154
|
+
BRANCH="$(git rev-parse --abbrev-ref HEAD 2>/dev/null)"
|
|
155
|
+
UPSTREAM="$(git rev-parse --abbrev-ref --symbolic-full-name '@{u}' 2>/dev/null)"
|
|
156
|
+
|
|
157
|
+
if [ -z "$UPSTREAM" ]; then
|
|
158
|
+
echo " · Branch '${BRANCH}' has no upstream — nothing has been pushed from it."
|
|
159
|
+
echo " Untracking here only ever affects local history."
|
|
160
|
+
else
|
|
161
|
+
echo " Upstream: ${UPSTREAM}"
|
|
162
|
+
ON_ORIGIN=0
|
|
163
|
+
for path in "${TRACKED_PATHS[@]:-}"; do
|
|
164
|
+
[ -z "$path" ] && continue
|
|
165
|
+
if [ -n "$(git ls-tree -r --name-only "$UPSTREAM" -- "$path" 2>/dev/null | head -n 1)" ]; then
|
|
166
|
+
echo " ✗ ${path} — present on ${UPSTREAM}"
|
|
167
|
+
ON_ORIGIN=$((ON_ORIGIN + 1))
|
|
168
|
+
fi
|
|
169
|
+
done
|
|
170
|
+
if [ "$ON_ORIGIN" -eq 0 ]; then
|
|
171
|
+
echo " ✓ No catalog path is present on ${UPSTREAM}."
|
|
172
|
+
else
|
|
173
|
+
echo
|
|
174
|
+
echo " → ${ON_ORIGIN} path(s) live on the remote. untrack-jenga-files.sh"
|
|
175
|
+
echo " --commit --push removes them from the branch TIP. It does NOT"
|
|
176
|
+
echo " rewrite history — earlier commits still contain them."
|
|
177
|
+
fi
|
|
178
|
+
fi
|
|
179
|
+
echo
|
|
180
|
+
|
|
181
|
+
# ─── Summary ─────────────────────────────────────────────────────────────────
|
|
182
|
+
FINDINGS=$((FINDINGS + MISSING_ENTRIES + ${#TRACKED_PATHS[@]}))
|
|
183
|
+
echo "═══════════════════════════════════════════════════════════════════════"
|
|
184
|
+
echo " Stray terminators : ${STRAY_COUNT}"
|
|
185
|
+
echo " Missing entries : ${MISSING_ENTRIES}"
|
|
186
|
+
echo " Tracked paths : ${#TRACKED_PATHS[@]}"
|
|
187
|
+
echo "═══════════════════════════════════════════════════════════════════════"
|
|
188
|
+
|
|
189
|
+
if [ "$FINDINGS" -gt 0 ]; then
|
|
190
|
+
echo "AUDIT_RESULT=findings"
|
|
191
|
+
exit 10
|
|
192
|
+
fi
|
|
193
|
+
echo "AUDIT_RESULT=clean"
|
|
194
|
+
exit 0
|