@jenga-ai/agent 1.1.0 → 1.2.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 (91) hide show
  1. package/README.md +7 -3
  2. package/agents/developer.md +82 -2
  3. package/agents/scrum-master.md +140 -21
  4. package/agents/tester.md +90 -8
  5. package/hooks/on_session_end.sh +171 -20
  6. package/package.json +1 -1
  7. package/scripts/check-permission-level.sh +107 -0
  8. package/scripts/check-publicignore-match.sh +122 -0
  9. package/scripts/check-worktree-liveness.sh +193 -0
  10. package/scripts/generate-rapport-manifest.sh +43 -0
  11. package/scripts/idea_manager.sh +47 -0
  12. package/scripts/install-worktree-commit-guard.sh +134 -0
  13. package/scripts/jenga-permission-level-switch.sh +109 -0
  14. package/scripts/smoke-harness.sh +139 -0
  15. package/scripts/validate-board.sh +62 -0
  16. package/scripts/with-lock.sh +158 -0
  17. package/scripts/worktree-remove-guard.sh +204 -0
  18. package/skills/clearify/SKILL.md +52 -0
  19. package/skills/commit/SKILL.md +13 -4
  20. package/skills/distribute/CONFIG_SCHEMA.md +60 -2
  21. package/skills/do/SKILL.md +48 -11
  22. package/skills/doc-sync/SKILL.md +16 -0
  23. package/skills/doc-sync/assets/doc_targets.md +11 -0
  24. package/skills/idea/SKILL.md +56 -0
  25. package/skills/idea/assets/idea_handoff_template.md +26 -0
  26. package/skills/idea/assets/idea_template.md +3 -0
  27. package/skills/init/SKILL.md +100 -7
  28. package/skills/init/assets/directory_structure.txt +1 -0
  29. package/skills/init/assets/workflow_template.json +1 -1
  30. package/skills/init/scripts/apply-project-visibility.sh +176 -0
  31. package/skills/init/scripts/detect-existing-codebase.sh +166 -0
  32. package/skills/init/scripts/init.sh +30 -1
  33. package/skills/jenga/SKILL.md +160 -17
  34. package/skills/jenga/scripts/board-scan.sh +238 -0
  35. package/skills/jenga/scripts/cascade-resolve.sh +297 -0
  36. package/skills/jenga/scripts/render-confirmation.sh +679 -0
  37. package/skills/jenga/scripts/render-picker.sh +439 -0
  38. package/skills/jenga/scripts/resolve-id.sh +367 -0
  39. package/skills/jenga-permission-level/SKILL.md +81 -0
  40. package/skills/proceed/SKILL.md +1 -1
  41. package/skills/publish/SKILL.md +8 -5
  42. package/skills/publish/assets/ci-contract.md +2 -2
  43. package/skills/publish/assets/ownership-matrix.md +1 -1
  44. package/skills/publish/scripts/finalize_changelog.sh +115 -0
  45. package/skills/publish/scripts/generate_release_notes.sh +475 -28
  46. package/skills/publish/scripts/npm_ci_pipeline.sh +44 -6
  47. package/skills/publish/scripts/publish_deploy.sh +38 -8
  48. package/skills/publish/scripts/run_gates.sh +2 -2
  49. package/skills/reconcile/SKILL.md +117 -5
  50. package/skills/reconcile/scripts/detect-unlinked-code.sh +741 -0
  51. package/skills/skillify/assets/init-new/assets/directory_structure.txt +5 -1
  52. package/skills/spinoff/SKILL.md +12 -7
  53. package/skills/todo/SKILL.md +2 -0
  54. package/skills/uncharted/SKILL.md +711 -0
  55. package/skills/uncharted/assets/SEGMENT_PROPOSAL_TEMPLATE.md +129 -0
  56. package/skills/uncharted/assets/UNDERSTANDING_DOC_TEMPLATE.md +160 -0
  57. package/skills/uncharted/scripts/apply-subsystem-cap.sh +573 -0
  58. package/skills/uncharted/scripts/detect-dependencies.sh +732 -0
  59. package/skills/uncharted/scripts/detect-tests.sh +553 -0
  60. package/skills/uncharted/scripts/discover-subsystems.sh +1029 -0
  61. package/skills/uncharted/scripts/enumerate-target.sh +470 -0
  62. package/skills/uncharted/scripts/import-source.sh +517 -0
  63. package/skills/uncharted/scripts/inspect-provenance.sh +573 -0
  64. package/skills/uncharted/scripts/resolve-segment-target.sh +640 -0
  65. package/skills/uncharted/scripts/run-engine.sh +655 -0
  66. package/skills/uncharted/scripts/validate-proposed-items.sh +125 -0
  67. package/skills/uncharted/scripts/write-backfilled-epics.sh +498 -0
  68. package/skills/wtf/SKILL.md +20 -0
  69. package/templates/CHANGELOG_TEMPLATE.md +13 -0
  70. package/templates/PROBLEM_RAPPORT_TEMPLATE.md +4 -1
  71. package/templates/SCRUM_BOARD_SCHEMA.md +157 -10
  72. package/templates/permission-levels/README.md +73 -0
  73. package/templates/permission-levels/level-1-locked.json +71 -0
  74. package/templates/permission-levels/level-2-guarded.json +64 -0
  75. package/templates/permission-levels/level-3-standard.json +62 -0
  76. package/templates/permission-levels/level-4-elevated.json +60 -0
  77. package/templates/permission-levels/level-5-unrestricted.json +58 -0
  78. package/skills/convert/SKILL.md +0 -124
  79. package/skills/convert/convert_cli.py +0 -235
  80. package/skills/convert/tests/sample.csv +0 -4
  81. package/skills/convert/tests/sample.json +0 -5
  82. package/skills/convert/tests/sample.jsonl +0 -3
  83. package/skills/convert/tests/sample.yaml +0 -18
  84. package/skills/convert/tests/sample_obj.csv +0 -2
  85. package/skills/convert/tests/sample_obj.json +0 -9
  86. package/skills/mirror-public/SKILL.md +0 -237
  87. package/skills/mirror-public/assets/config.json +0 -5
  88. package/skills/mirror-public/scripts/mirror.sh +0 -374
  89. package/skills/self-sync/SKILL.md +0 -73
  90. package/skills/self-sync/scripts/run.js +0 -136
  91. package/skills/strategy/SKILL.md +0 -312
@@ -304,7 +304,7 @@ Before starting:
304
304
  Before invoking the developer, check whether this task was manually scoped by a human operator.
305
305
 
306
306
  1. Read `jenga_assigned` from the resolved task's frontmatter.
307
- 2. If `jenga_assigned` is `true` or the field is absent — proceed to step 5 without any further check.
307
+ 2. If `jenga_assigned` is `true` or the field is absent — proceed to step 4.2 without any further check.
308
308
  3. If `jenga_assigned` is `false`:
309
309
  a. Read `override_justification` from the task's frontmatter.
310
310
  b. If `override_justification` is absent or its value is an empty string, **halt execution** and emit:
@@ -316,21 +316,58 @@ Before invoking the developer, check whether this task was manually scoped by a
316
316
  ```
317
317
  Override acknowledged for <task_id>: <override_justification>
318
318
  ```
319
- Then proceed to step 5.
319
+ Then proceed to step 4.2.
320
320
 
321
321
  ### 4.2. Inline Execution Path (execution_scope: inline)
322
322
 
323
- If the resolved task has `execution_scope: inline` in its frontmatter, execute the task directly in the current session without spawning a developer subagent:
323
+ After resolving the task context (step 4) and passing override validation (step 4.1), read `execution_scope` from the task frontmatter.
324
324
 
325
- 1. Read the task file and load its full content (description, acceptance criteria).
325
+ **Locked-task dispatch guard (defense-in-depth).** Before branching on `execution_scope` below, read `crucial_level` from the task frontmatter (per `templates/SCRUM_BOARD_SCHEMA.md`'s Crucial Flag Fields). If `crucial_level: locked`:
326
+
327
+ - This task MUST be routed through the inline execution path below — no worktree, no developer subagent — regardless of what `execution_scope` currently reads. This guards against a locked task reaching dispatch with a non-`inline` `execution_scope` (a race, a manually edited file, or a task added to a story's `tasks:` list after `skills/jenga/SKILL.md` Phase 0.5's Rule 4 last ran).
328
+ - If `execution_scope` is already `inline`, proceed directly to the inline steps below — no correction needed.
329
+ - If `execution_scope` is anything other than `inline` (absent, `task`, `story`, or `epic`), auto-correct it to `inline` in the task frontmatter now, and record the correction using the **same logged-note convention** as `skills/jenga/SKILL.md` Phase 0.5 Rule 4 (do not invent a second, inconsistent logging mechanism):
330
+ - Append to the task's `override_justification` frontmatter field:
331
+ ```
332
+ override_justification: "/do dispatch guard auto-correction <date>: execution_scope forced from '<previous_value>' to 'inline' because crucial_level: locked."
333
+ ```
334
+ - Then emit (non-fatally — do not halt):
335
+ ```
336
+ AUTO-CORRECTION [<task_id>]: crucial_level=locked requires execution_scope=inline; corrected from "<previous_value>" to "inline".
337
+ ```
338
+ - Then proceed to the inline steps below with the now-corrected `execution_scope: inline`.
339
+ - **Under no circumstance does a `crucial_level: locked` task fall through to step 5** (developer agent invocation / worktree creation) — this applies whether the task was resolved individually or would otherwise have entered the normal per-task worktree-creation flow.
340
+
341
+ **If `execution_scope: inline`** (including tasks corrected above), execute the task directly in the current session without spawning a developer subagent:
342
+
343
+ 1. Read the task file and load its full content (description, acceptance criteria). Do NOT create a worktree. Do NOT spawn a developer subagent.
326
344
  2. Implement the task inline — make the required changes to files directly in the current session.
327
- 3. Commit the changes using the standard commit convention (`task(<task_id>): <short description>`).
328
- 4. Run the **Intent-vs-Diff Check** (see `### 5.1. Intent-vs-Diff Check` below) for this task.
329
- 5. Self-verify the implementation against the acceptance criteria.
330
- 6. Write `status: Passed` and `date_completed: <today>` to the task's frontmatter if verification passes.
331
- 7. Continue to step 6 (documentation verification) and then step 7 (post-completion).
345
+ 3. Run the smoke test harness before committing anything:
346
+ - Run `bash scripts/smoke-harness.sh <changed_file>...`, passing the paths changed in step 2. With no arguments the harness infers them from `git diff --name-only HEAD`. It exits `0` on pass and `1` on failure.
347
+ - If `scripts/smoke-harness.sh` does not exist, log a warning and treat the result as a pass:
348
+ ```
349
+ WARNING [<task_id>]: scripts/smoke-harness.sh not found. Smoke test skipped (stub pass).
350
+ ```
351
+ 4. **If the smoke test exits non-zero**:
352
+ - Write `status: Failed` to the task's frontmatter.
353
+ - Emit:
354
+ ```
355
+ INLINE TASK FAILED [<task_id>]: smoke test returned non-zero exit code. Task marked Failed. Halting.
356
+ ```
357
+ - Do not commit. Do not proceed to the next task.
358
+ 5. **If the smoke test passes**:
359
+ - Commit the changes using the standard commit convention (`task(<task_id>): <short description>`) via `/commit` in inline mode (E32_S04_T03).
360
+ - Run the **Intent-vs-Diff Check** (see `### 5.1. Intent-vs-Diff Check` below) for this task.
361
+ - Self-verify the implementation against the acceptance criteria.
362
+ - Write `status: Passed` and `date_completed: <today>` to the task's frontmatter if verification passes.
363
+ - Remove the task from `project/todo.md`.
364
+ 6. `inline` tasks do not invoke the tester agent — the smoke test and self-verification are the only gates.
365
+ 7. `inline` tasks always have `needs_docs: false` — skip plan and summary documentation for the implemented task.
366
+ 8. Continue to `### 6. Verify documentation`, then `### 7. After successful completion`.
367
+
368
+ If the implementation cannot be completed inline (scope is larger than anticipated), abort and re-route to the normal developer path (step 5) — unless `crucial_level: locked`, in which case do not re-route; re-attempt inline or halt and report, per the locked-task dispatch guard above.
332
369
 
333
- If the implementation cannot be completed inline (scope is larger than anticipated), abort and re-route to the normal developer path (step 5).
370
+ **If `execution_scope` is not `inline`** (or is absent / `task` / `story` / `epic`) **and `crucial_level` is not `locked`**, proceed to step 5 (invoke the developer agent) as normal.
334
371
 
335
372
  ### 5. Invoke the developer agent
336
373
  Pass the following to the developer agent:
@@ -392,7 +429,7 @@ If either file is missing, ask the developer to produce it before continuing.
392
429
  Additionally, if the completed work introduces user-facing changes, update `README.md` and `WARP.md` accordingly.
393
430
 
394
431
  ### 7. After successful completion
395
- - Check for any `_INSTRUCTIONS.md` files in `$(bash scripts/board_resolver.sh)tasks/` whose ID matches the completed task. If found, present them to the user and explain that these actions must be completed before the feature will work correctly.
432
+ - Check for any `_INSTRUCTIONS.md` files in `project/instructions/` whose ID matches the completed task. If found, present them to the user and explain that these actions must be completed before the feature will work correctly.
396
433
  - Invoke the `/commit` skill to commit the work (if not already committed by the developer)
397
434
  - Run `bash scripts/todo_manager.sh remove '<task title>'` to remove the completed task from `project/todo.md`
398
435
  - Run `bash scripts/todo_manager.sh teardown` to delete `project/todo.md` if it is now effectively empty
@@ -87,6 +87,21 @@ For each update target and its resolved sources:
87
87
  - Outdated examples, wrong flag names, stale code snippets.
88
88
  - Incorrect or missing configuration keys/values.
89
89
 
90
+ #### 4a. Cross-reference `.publicignore` for "missing documentation" candidates
91
+
92
+ Every candidate identified above as "missing documentation for new things added in source" ships publicly by default unless this project has adopted `/mirror-public`. Before flagging any such candidate, check whether it's actually private-only:
93
+
94
+ 1. **Check for `.publicignore` at the repo root.** Most projects using this framework will not have one (they haven't adopted `/mirror-public`) — if it's absent, **skip this entire sub-step**. Fall through to flagging every "missing documentation" candidate exactly as `3.` above already would, with no further filtering.
95
+ 2. **If `.publicignore` exists**, for each "missing documentation" candidate, determine its source path (relative to the repo root) and classify it by running:
96
+ ```
97
+ scripts/check-publicignore-match.sh <path> [<path> ...]
98
+ ```
99
+ This reuses `/mirror-public`'s own `mirror.sh` matching logic (`rsync --exclude-from=.publicignore`) — a file this script reports `BLOCKED` is guaranteed to be a file `/mirror-public --dry-run` would also report as "would be blocked", and vice versa for `PUBLIC`. It needs no network access and does not require `/mirror-public` to be configured.
100
+ 3. **`BLOCKED`** → do not flag this candidate as missing documentation. It's private-only and will never ship to the public mirror, so public docs coverage is not applicable.
101
+ 4. **`PUBLIC`** → flag it as usual in step 5's report, and name `README.md` and `project/.wiki/documentation.md` (the confirmed canonical full-reference doc — see `assets/doc_targets.md`) as the target docs to check for coverage of this item.
102
+
103
+ This sub-step only changes what gets flagged as "missing documentation" in step 3's third bullet — it does not affect the other three drift categories (renamed/removed references, outdated examples, incorrect config keys), which are flagged regardless of `.publicignore` since they concern existing documentation content, not public-shipping coverage of new source additions.
104
+
90
105
  ### 5. Report findings before updating
91
106
 
92
107
  Before making any writes, present a concise drift summary per file:
@@ -165,3 +180,4 @@ If minification could not reach the target, note: `⚠️ docs/API.md reduced to
165
180
 
166
181
  - `assets/doc_targets.md` — Editable list of documentation files this skill checks by default.
167
182
  - `assets/default_excludes.txt` — Paths always excluded from source analysis unless overridden.
183
+ - `scripts/check-publicignore-match.sh` (repo root) — Used in step 4a to classify "missing documentation" candidates as `PUBLIC`/`BLOCKED` per `.publicignore`, reusing `/mirror-public`'s exact matching semantics.
@@ -8,7 +8,18 @@ Add one path per line inside the list below. Blank lines and lines starting with
8
8
 
9
9
  <!-- Add your project's documentation files here, one per line -->
10
10
  README.md
11
+ project/.wiki/documentation.md
11
12
  <!-- docs/API.md -->
12
13
  <!-- docs/config.md -->
13
14
  <!-- CHANGELOG.md -->
14
15
  <!-- CONTRIBUTING.md -->
16
+
17
+ <!--
18
+ Note: project/.wiki/documentation.md is the confirmed-canonical full
19
+ skill-reference doc (README.md links to it directly as "Full reference").
20
+ A near-duplicate, project/documentation/documentation.md, has independently
21
+ diverged from this canonical copy — see E28_S03_T01's execution summary for
22
+ the investigation, and story E38_S01 for the planned consolidation. Do not
23
+ add project/documentation/documentation.md here until that consolidation
24
+ lands.
25
+ -->
@@ -0,0 +1,56 @@
1
+ ---
2
+ name: idea
3
+ description: Capture a loosely-defined idea to project/ideas.md — a lightweight, "maybe someday" log with no board or promotion overhead.
4
+ keywords:
5
+ - idea
6
+ - capture idea
7
+ - log idea
8
+ - brain dump
9
+ - maybe someday
10
+ examples:
11
+ - "capture this as an idea"
12
+ - "log this idea for later"
13
+ - "I have a rough idea I want to jot down"
14
+ metadata:
15
+ prefered_agent: scrum-master
16
+ ---
17
+
18
+ # Idea — Lightweight Idea Capture
19
+
20
+ ## Instructions
21
+
22
+ 1. **Ensure `project/ideas.md` exists** — If it doesn't exist, it will be auto-created by `idea_manager.sh` from `skills/idea/assets/idea_template.md` — no manual action needed.
23
+
24
+ 2. **Ask the user about the idea:**
25
+ - What's the idea?
26
+ - Any known context worth noting (why it came up, what it might relate to)?
27
+
28
+ Keep this light — `/idea` is a low-overhead capture, not a structured mission intake like `/todo`.
29
+
30
+ 3. **Add to `project/ideas.md`** by running:
31
+ ```
32
+ bash scripts/idea_manager.sh add '<idea>'
33
+ ```
34
+
35
+ 4. **Ask the user**: "Capture another idea, or done?"
36
+ - If **another** — go back to step 2.
37
+ - If **done** — exit.
38
+
39
+ Unlike `/todo`, `/idea` never offers to execute, refine, or promote the captured idea(s) at the end. There is no `/do`-style follow-up here — `/idea` has no refine or promotion logic of its own.
40
+
41
+ ## For Reference Only — Promotion Convention (not implemented here)
42
+
43
+ `/idea` does not implement any refine or promotion mechanism. This section documents, for reference, how promotion is expected to work elsewhere so future flows stay consistent:
44
+
45
+ - **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`.
46
+ - **Terminal idea states** are marked directly in `project/ideas.md` using the same HTML-comment tag convention `project/todo.md` uses for `RECONCILED`:
47
+ - `PROMOTED` — the idea was picked up via `/brainstorm` and turned into board work.
48
+ - `DISCARDED` — the idea was reviewed and dropped.
49
+
50
+ Example (mirroring `project/todo.md`'s tagging style):
51
+ ```
52
+ Add dark mode toggle to settings page <!-- PROMOTED -->
53
+ Rewrite onboarding copy in a more casual tone <!-- DISCARDED -->
54
+ ```
55
+
56
+ No agent invoked by `/idea` applies these tags or acts on them — that is reserved for a future promotion step (e.g. within `/brainstorm`).
@@ -0,0 +1,26 @@
1
+ # Idea Handoff
2
+
3
+ <!-- PREAMBLE (for /idea): This template was pre-filled by a caller (e.g. /spinoff).
4
+ Skip any questions whose answers are already provided below. Only prompt the user
5
+ for fields that remain empty or marked as a placeholder. -->
6
+
7
+ <!-- Format: <mission title>: <E##_S##> (epic/story ref optional) -->
8
+
9
+ ## Mission Title
10
+ <!-- PLACEHOLDER: short name for this idea, e.g. "Refactor auth middleware" -->
11
+
12
+ ## Goal / Objective
13
+ <!-- PLACEHOLDER: what this idea is trying to achieve -->
14
+
15
+ ## Affected Files or Scope
16
+ <!-- PLACEHOLDER: which files, modules, or areas are involved, e.g. src/auth/, skills/idea/ -->
17
+
18
+ ## Intended Approach
19
+ <!-- PLACEHOLDER: step-by-step or high-level approach to the work -->
20
+
21
+ ## Epic / Story Linkage
22
+ <!-- PLACEHOLDER: known Epic or Story ID this links to, e.g. E02_S03 — or "None" if not linked -->
23
+
24
+ ## Origin
25
+ <!-- PLACEHOLDER: EST id (task/story/epic) in progress when the divergence happened, or "None" -->
26
+ <!-- PLACEHOLDER: one-line summary of what the user was doing at the time -->
@@ -0,0 +1,3 @@
1
+ # Ideas
2
+
3
+ <!-- Format: <idea text> (one line per idea; terminal tags PROMOTED / DISCARDED appended by /brainstorm, not by /idea) -->
@@ -18,14 +18,93 @@ examples:
18
18
 
19
19
  Follow these steps in order. Do not skip steps — the sequence matters.
20
20
 
21
- ### 1–9. Run the scaffold script
21
+ ### 1. Detect existing project state
22
22
 
23
- Execute the init script from the project root:
23
+ Before asking anything or scaffolding anything, classify the target directory
24
+ (the current directory) by running the detection script:
24
25
 
25
26
  ```bash
26
- chmod +x ./scripts/init.sh && ./scripts/init.sh
27
+ skills/init/scripts/detect-existing-codebase.sh .
27
28
  ```
28
29
 
30
+ It prints exactly one verdict on stdout:
31
+
32
+ | Verdict | Meaning | What to do |
33
+ |---|---|---|
34
+ | `empty` | The directory is empty, or contains only `.git`, `.gitignore`, and top-level `README*`/`LICENSE*` boilerplate. | Proceed to step 2 — behaviour here is unchanged from before this detection step existed. |
35
+ | `already-scaffolded` | `project/board/`, `project/PROJECT_SUMMARY.md`, or `project/configs/workflow.json` already exists. | Tell the user this directory already has a Jenga scaffold and **stop** — do not run the scaffold script. Re-running it would silently overwrite `PROJECT_SUMMARY.md` and `workflow.json` with fresh stubs. Point them at `/continue` or `/status` instead. |
36
+ | `existing-codebase` | The directory has real content (source, configs, docs beyond the boilerplate list) and is not already scaffolded. | **Pause. Do not scaffold.** Present the choice below and wait for an answer. |
37
+
38
+ On `existing-codebase`, present this choice verbatim, per the Interaction Pattern in
39
+ `CLAUDE.md` (numbered, free-text last):
40
+
41
+ This directory already contains code that wasn't built through Jenga. How would
42
+ you like to proceed?
43
+ 1. Run /uncharted onboard first, to analyze the existing code and backfill the
44
+ board before scaffolding
45
+ 2. Scaffold fresh anyway, leaving the board empty (the existing code is never
46
+ modified either way — onboard mode and fresh scaffolding are both board-only)
47
+ 3. Abort — don't scaffold, don't run /uncharted
48
+ 4. Other (describe below)
49
+
50
+ - **Option 1** — invoke `/uncharted onboard`. It analyzes the existing code and backfills
51
+ the board; it never modifies, moves, or restructures application code. Once it
52
+ finishes, the directory now has `project/PROJECT_SUMMARY.md` etc., so re-running this
53
+ detection step returns `already-scaffolded` — there is nothing left to scaffold.
54
+ - **Option 2** — continue to step 2 and scaffold fresh. Note in your response that the
55
+ board will start empty despite the directory containing pre-existing code, since the
56
+ user explicitly chose that.
57
+ - **Option 3** — stop here. Do not run the scaffold script and do not invoke `/uncharted`.
58
+ - **Option 4** — handle the free-text response on its own merits.
59
+
60
+ If the run is non-interactive (no user available to answer), default to **option 3
61
+ (abort)**. Unlike the visibility question in step 2, none of these three choices is a
62
+ no-op: running `/uncharted onboard` unattended commits an analysis pass the user never
63
+ asked for, and scaffolding fresh unattended silently discards pre-existing code from the
64
+ board exactly as `/init` did before this step existed. Aborting is the only choice that
65
+ changes nothing on disk, so it is the only safe default.
66
+
67
+ Never treat `existing-codebase` as if it were `empty`, and never skip straight to step 2
68
+ on that verdict without the user (or the non-interactive default) choosing to.
69
+
70
+ ### 2. Ask how JengaAgent's working files should appear
71
+
72
+ Ask the user this question, verbatim, before running any script:
73
+
74
+ How should JengaAgent's own working files (project/ — the scrum board, todo.md,
75
+ queue/, rapports/, and logs/) appear in this project?
76
+ 1. Visible — keep them at `project/`, tracked and visible in directory listings
77
+ 2. Ignored — keep them at `project/` but add them to `.gitignore` so they are never committed
78
+ 3. Not sure — explain the trade-offs and ask me again
79
+
80
+ If the user picks option 3, explain the trade-offs and re-ask. Do not proceed until
81
+ the answer is one of `visible` or `ignored`.
82
+
83
+ If the run is non-interactive (no user available to answer), use the default:
84
+ **`visible`**. It is the only choice that changes nothing on disk, so an unattended
85
+ run can never silently relocate directories or edit `.gitignore`.
86
+
87
+ > A third mode, `hidden` (dot-prefixing `project/` to `.project/`, matching the
88
+ > `.agents/`/`.claude/` convention), was built and then withdrawn before release —
89
+ > testing found it left board resolution and session-end hooks writing to two
90
+ > different trees. It is not offered here. See
91
+ > `skills/distribute/CONFIG_SCHEMA.md` for the root-cause note and the tracked
92
+ > follow-up to reintroduce it once fixed.
93
+
94
+ Carry the chosen value into step 3. Do not apply it yourself — the script owns all
95
+ of the mechanical work.
96
+
97
+ ### 3. Run the scaffold script
98
+
99
+ Execute the init script from the project root, passing the choice from step 2:
100
+
101
+ ```bash
102
+ chmod +x ./scripts/init.sh && ./scripts/init.sh --visibility <visible|ignored>
103
+ ```
104
+
105
+ Omitting `--visibility` falls back to the `JENGA_PROJECT_FILES_VISIBILITY`
106
+ environment variable, then to `visible`.
107
+
29
108
  This script handles all scaffolding in one step:
30
109
  1. Initializes the git repository
31
110
  2. Creates `.gitignore`
@@ -36,10 +115,24 @@ This script handles all scaffolding in one step:
36
115
  7. Creates `project/data/baselines.json`
37
116
  8. Creates `project/logs/events.json`
38
117
  9. Creates `docs/STRATEGY.md` — a strategic brief stub intended for investors, partners, and the product team
39
- 10. Stages and commits all files with the message `init: scaffold project structure and workflow config`
118
+ 10. Creates `CHANGELOG.md` from the shared template — a running log of notable changes, seeded with an `[Unreleased]` section
119
+ 11. 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
120
+ 12. Stages and commits all files with the message `init: scaffold project structure and workflow config`
121
+
122
+ The visibility mode is validated before any scaffolding happens, so an invalid
123
+ value fails fast and leaves nothing behind. It is applied before the commit, so
124
+ the `.gitignore` entry is captured in the initial commit.
125
+
126
+ If the script fails, check that you are in the project root and that git and `jq`
127
+ are available.
40
128
 
41
- If the script fails, check that you are in the project root and that git is available.
129
+ See `skills/distribute/CONFIG_SCHEMA.md` for the full `project_files_visibility`
130
+ field reference.
42
131
 
43
- ### 11. Prompt next step
132
+ ### 4. Prompt next step
44
133
 
45
- Inform the user that setup is complete. Mention that `docs/STRATEGY.md` was created as a strategic brief stub for investors, partners, and the product team — they can fill it in now or return to it later. Suggest running `/pi-plan` to define project goals and epics.
134
+ Inform the user that setup is complete, and state which visibility mode was applied
135
+ and where the working files now live. Mention that `docs/STRATEGY.md` was created as
136
+ a strategic brief stub for investors, partners, and the product team — they can fill
137
+ it in now or return to it later. Suggest running `/pi-plan` to define project goals
138
+ and epics.
@@ -1,6 +1,7 @@
1
1
  project/board/epics
2
2
  project/board/stories
3
3
  project/board/tasks
4
+ project/instructions
4
5
  project/configs
5
6
  project/data
6
7
  project/queue
@@ -12,7 +12,7 @@
12
12
  "scrum_triggers": "project/queue/scrum_triggers.jsonl",
13
13
  "developer_triggers": "project/queue/developer_triggers.jsonl",
14
14
  "tester_triggers": "project/queue/tester_triggers.jsonl",
15
- "session_handoff": "project/queue/.session_handoff.json",
15
+ "session_handoff": "project/queue/handoffs/",
16
16
  "logs": "project/logs",
17
17
  "data": "project/data",
18
18
  "configs": "project/configs",
@@ -0,0 +1,176 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # apply-project-visibility.sh — apply the `project_files_visibility` mode to a project.
4
+ #
5
+ # Usage:
6
+ # apply-project-visibility.sh <mode> [project_root]
7
+ # apply-project-visibility.sh --check-only <mode>
8
+ #
9
+ # Modes:
10
+ # visible Working files stay where they are. No-op on disk beyond the config write.
11
+ # ignored Working files are added to the project's .gitignore — present on disk,
12
+ # never committed.
13
+ #
14
+ # NOTE: A third mode, `hidden` (dot-prefixing project/ -> .project/), was
15
+ # implemented and then withdrawn before release. Testing found it functionally
16
+ # broken: scripts/board_resolver.sh hardcodes project/configs/workflow.json
17
+ # and never locates the rewritten path, and hooks/on_session_end.sh
18
+ # unconditionally recreates a shadow project/ tree on every session end,
19
+ # splitting runtime state across two trees. See
20
+ # project/rapports/problems/E31_S05_T01-hidden-mode-path-resolution-gaps.md
21
+ # for the full findings. Re-introducing `hidden` requires fixing both of
22
+ # those hardcoded paths first — tracked as a follow-up /todo item.
23
+ #
24
+ # Exit codes:
25
+ # 0 Success
26
+ # 1 Bad usage or missing prerequisite
27
+ # 2 Invalid mode (outside the two-value enum)
28
+ # 3 Filesystem apply failure
29
+ # 4 jenga.config.json write failure
30
+
31
+ # Do NOT use set -e globally — each step handles its own errors.
32
+ set -uo pipefail
33
+
34
+ info() { echo "[visibility] $*"; }
35
+ warn() { echo "[visibility] WARNING: $*"; }
36
+ err() { echo "[visibility] ERROR: $*" >&2; }
37
+
38
+ usage() {
39
+ echo "Usage: $(basename "$0") <visible|ignored> [project_root]" >&2
40
+ echo " $(basename "$0") --check-only <visible|ignored>" >&2
41
+ exit 1
42
+ }
43
+
44
+ # Every JengaAgent working file named in E31_S05 — the scrum board, todo.md,
45
+ # queue/, rapports/ and logs/ — nests under this single root, so one entry
46
+ # covers them all. `ignored` consumes this list.
47
+ JENGA_WORKING_PATHS=("project")
48
+
49
+ VALID_MODES="visible ignored"
50
+
51
+ validate_mode() {
52
+ local mode="$1"
53
+ for valid in $VALID_MODES; do
54
+ [ "$mode" = "$valid" ] && return 0
55
+ done
56
+ err "Invalid project_files_visibility value: '${mode}'"
57
+ err "Allowed values are: ${VALID_MODES// /, }"
58
+ exit 2
59
+ }
60
+
61
+ # ---------------------------------------------------------------------------
62
+ # Argument parsing
63
+ # ---------------------------------------------------------------------------
64
+
65
+ CHECK_ONLY=0
66
+ if [ "${1:-}" = "--check-only" ]; then
67
+ CHECK_ONLY=1
68
+ shift
69
+ fi
70
+
71
+ MODE="${1:-}"
72
+ [ -n "$MODE" ] || usage
73
+
74
+ validate_mode "$MODE"
75
+
76
+ if [ "$CHECK_ONLY" -eq 1 ]; then
77
+ info "Mode '$MODE' is valid."
78
+ exit 0
79
+ fi
80
+
81
+ PROJECT_ROOT="${2:-$PWD}"
82
+ if [ ! -d "$PROJECT_ROOT" ]; then
83
+ err "Project root does not exist: $PROJECT_ROOT"
84
+ exit 1
85
+ fi
86
+ cd "$PROJECT_ROOT" || { err "Cannot enter project root: $PROJECT_ROOT"; exit 1; }
87
+
88
+ if ! command -v jq >/dev/null 2>&1; then
89
+ err "jq is required to write jenga.config.json but was not found on PATH."
90
+ exit 1
91
+ fi
92
+
93
+ # ---------------------------------------------------------------------------
94
+ # ignored — append to .gitignore, without ever duplicating an entry
95
+ # ---------------------------------------------------------------------------
96
+
97
+ gitignore_append() {
98
+ local entry="$1"
99
+ local gitignore=".gitignore"
100
+
101
+ if [ -f "$gitignore" ] && grep -qxF -- "$entry" "$gitignore"; then
102
+ info "'$entry' already present in .gitignore — skipping."
103
+ return 0
104
+ fi
105
+
106
+ # Don't glue our entry onto a final line that lacks a newline.
107
+ if [ -s "$gitignore" ] && [ -n "$(tail -c 1 "$gitignore")" ]; then
108
+ printf '\n' >> "$gitignore"
109
+ fi
110
+
111
+ if ! printf '%s\n' "$entry" >> "$gitignore"; then
112
+ err "Failed to append '$entry' to .gitignore"
113
+ exit 3
114
+ fi
115
+ info "Added '$entry' to .gitignore"
116
+ }
117
+
118
+ # ---------------------------------------------------------------------------
119
+ # jenga.config.json — merge the field in, written atomically (temp + mv)
120
+ # ---------------------------------------------------------------------------
121
+
122
+ write_visibility_config() {
123
+ local mode="$1"
124
+ local config="jenga.config.json"
125
+ local tmp="${config}.tmp"
126
+ local existing='{}'
127
+
128
+ # /init normally runs before any /distribute, so the file usually does not
129
+ # exist yet. Merge rather than overwrite so other fields survive.
130
+ if [ -f "$config" ]; then
131
+ if ! jq empty "$config" 2>/dev/null; then
132
+ err "$config exists but contains malformed JSON — refusing to overwrite it."
133
+ exit 4
134
+ fi
135
+ existing="$(cat "$config")"
136
+ fi
137
+
138
+ local content
139
+ content="$(jq --arg v "$mode" '.project_files_visibility = $v' <<< "$existing")"
140
+ if [ -z "$content" ]; then
141
+ err "Failed to construct $config content."
142
+ exit 4
143
+ fi
144
+
145
+ if ! printf '%s\n' "$content" > "$tmp"; then
146
+ err "Failed to write temporary config file: $tmp"
147
+ exit 4
148
+ fi
149
+
150
+ if ! mv "$tmp" "$config"; then
151
+ err "Failed to atomically move $tmp to $config"
152
+ rm -f "$tmp"
153
+ exit 4
154
+ fi
155
+
156
+ info "Wrote project_files_visibility = \"$mode\" to $config"
157
+ }
158
+
159
+ # ---------------------------------------------------------------------------
160
+ # Apply
161
+ # ---------------------------------------------------------------------------
162
+
163
+ case "$MODE" in
164
+ visible)
165
+ info "Mode 'visible' — working files stay in place; nothing to change on disk."
166
+ ;;
167
+ ignored)
168
+ for path in "${JENGA_WORKING_PATHS[@]}"; do
169
+ gitignore_append "${path}/"
170
+ done
171
+ ;;
172
+ esac
173
+
174
+ write_visibility_config "$MODE"
175
+
176
+ info "Applied project_files_visibility '$MODE' to $PROJECT_ROOT"