@jenga-ai/agent 1.0.1 → 1.1.1

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 (117) hide show
  1. package/README.md +10 -7
  2. package/agents/developer.md +82 -2
  3. package/agents/scrum-master.md +215 -21
  4. package/agents/tester.md +90 -8
  5. package/hooks/on_session_end.sh +171 -20
  6. package/mcp/router/embedder.js +1 -1
  7. package/mcp/training_runner/index.js +239 -0
  8. package/mcp/training_runner/package-lock.json +1065 -0
  9. package/mcp/training_runner/package.json +15 -0
  10. package/package.json +14 -16
  11. package/scripts/check-permission-level.sh +107 -0
  12. package/scripts/check-publicignore-match.sh +122 -0
  13. package/scripts/check-worktree-liveness.sh +193 -0
  14. package/scripts/generate-rapport-manifest.sh +43 -0
  15. package/scripts/idea_manager.sh +47 -0
  16. package/scripts/install-worktree-commit-guard.sh +134 -0
  17. package/scripts/jenga-permission-level-switch.sh +109 -0
  18. package/scripts/smoke-harness.sh +139 -0
  19. package/scripts/validate-board.sh +62 -0
  20. package/scripts/with-lock.sh +158 -0
  21. package/scripts/worktree-remove-guard.sh +204 -0
  22. package/skills/clearify/SKILL.md +52 -0
  23. package/skills/close-story/SKILL.md +203 -0
  24. package/skills/close-story/scripts/check-story-closeable.sh +195 -0
  25. package/skills/close-story/scripts/compute-scope-divergence.sh +128 -0
  26. package/skills/close-story/scripts/extract-diff-stats.sh +48 -0
  27. package/skills/close-story/scripts/extract-task-diff-stats.sh +97 -0
  28. package/skills/close-story/scripts/update-task-frontmatter.sh +103 -0
  29. package/skills/commit/SKILL.md +30 -3
  30. package/skills/distribute/CONFIG_SCHEMA.md +148 -0
  31. package/skills/distribute/SKILL.md +173 -0
  32. package/skills/distribute/scripts/check-version.sh +74 -0
  33. package/skills/distribute/scripts/commit-version-bump.sh +108 -0
  34. package/skills/distribute/scripts/distribute-changes.sh +381 -0
  35. package/skills/do/SKILL.md +352 -1
  36. package/skills/do/assets/intent-vs-diff-prompt.md +69 -0
  37. package/skills/doc/assets/path-objectives.yaml +13 -0
  38. package/skills/doc-sync/SKILL.md +16 -0
  39. package/skills/doc-sync/assets/doc_targets.md +11 -0
  40. package/skills/idea/SKILL.md +56 -0
  41. package/skills/idea/assets/idea_handoff_template.md +26 -0
  42. package/skills/idea/assets/idea_template.md +3 -0
  43. package/skills/init/SKILL.md +101 -7
  44. package/skills/init/assets/directory_structure.txt +1 -0
  45. package/skills/init/assets/strategy_stub_template.md +38 -0
  46. package/skills/init/assets/workflow_template.json +1 -1
  47. package/skills/init/scripts/apply-project-visibility.sh +176 -0
  48. package/skills/init/scripts/detect-existing-codebase.sh +166 -0
  49. package/skills/init/scripts/init.sh +35 -1
  50. package/skills/jenga/SKILL.md +206 -14
  51. package/skills/jenga/scripts/board-scan.sh +238 -0
  52. package/skills/jenga/scripts/cascade-resolve.sh +297 -0
  53. package/skills/jenga/scripts/render-confirmation.sh +679 -0
  54. package/skills/jenga/scripts/render-picker.sh +439 -0
  55. package/skills/jenga/scripts/resolve-id.sh +367 -0
  56. package/skills/jenga-permission-level/SKILL.md +81 -0
  57. package/skills/proceed/SKILL.md +1 -1
  58. package/skills/publish/SKILL.md +8 -5
  59. package/skills/publish/assets/ci-contract.md +2 -2
  60. package/skills/publish/assets/ownership-matrix.md +1 -1
  61. package/skills/publish/scripts/finalize_changelog.sh +115 -0
  62. package/skills/publish/scripts/generate_release_notes.sh +475 -28
  63. package/skills/publish/scripts/npm_ci_pipeline.sh +44 -6
  64. package/skills/publish/scripts/publish_deploy.sh +38 -8
  65. package/skills/publish/scripts/run_gates.sh +2 -2
  66. package/skills/reconcile/SKILL.md +117 -5
  67. package/skills/reconcile/scripts/detect-unlinked-code.sh +741 -0
  68. package/skills/skillify/assets/init-new/assets/directory_structure.txt +5 -1
  69. package/skills/spinoff/SKILL.md +12 -7
  70. package/skills/todo/SKILL.md +2 -0
  71. package/skills/uncharted/SKILL.md +711 -0
  72. package/skills/uncharted/assets/SEGMENT_PROPOSAL_TEMPLATE.md +129 -0
  73. package/skills/uncharted/assets/UNDERSTANDING_DOC_TEMPLATE.md +160 -0
  74. package/skills/uncharted/scripts/apply-subsystem-cap.sh +573 -0
  75. package/skills/uncharted/scripts/detect-dependencies.sh +732 -0
  76. package/skills/uncharted/scripts/detect-tests.sh +553 -0
  77. package/skills/uncharted/scripts/discover-subsystems.sh +1029 -0
  78. package/skills/uncharted/scripts/enumerate-target.sh +470 -0
  79. package/skills/uncharted/scripts/import-source.sh +517 -0
  80. package/skills/uncharted/scripts/inspect-provenance.sh +573 -0
  81. package/skills/uncharted/scripts/resolve-segment-target.sh +640 -0
  82. package/skills/uncharted/scripts/run-engine.sh +655 -0
  83. package/skills/uncharted/scripts/validate-proposed-items.sh +125 -0
  84. package/skills/uncharted/scripts/write-backfilled-epics.sh +498 -0
  85. package/skills/wtf/SKILL.md +20 -0
  86. package/templates/CHANGELOG_TEMPLATE.md +13 -0
  87. package/templates/PROBLEM_RAPPORT_TEMPLATE.md +4 -1
  88. package/templates/SCRUM_BOARD_SCHEMA.md +206 -10
  89. package/templates/permission-levels/README.md +73 -0
  90. package/templates/permission-levels/level-1-locked.json +71 -0
  91. package/templates/permission-levels/level-2-guarded.json +64 -0
  92. package/templates/permission-levels/level-3-standard.json +62 -0
  93. package/templates/permission-levels/level-4-elevated.json +60 -0
  94. package/templates/permission-levels/level-5-unrestricted.json +58 -0
  95. package/skills/convert/SKILL.md +0 -124
  96. package/skills/convert/convert_cli.py +0 -235
  97. package/skills/convert/tests/sample.csv +0 -4
  98. package/skills/convert/tests/sample.json +0 -5
  99. package/skills/convert/tests/sample.jsonl +0 -3
  100. package/skills/convert/tests/sample.yaml +0 -18
  101. package/skills/convert/tests/sample_obj.csv +0 -2
  102. package/skills/convert/tests/sample_obj.json +0 -9
  103. package/skills/mirror-public/SKILL.md +0 -237
  104. package/skills/mirror-public/assets/config.json +0 -5
  105. package/skills/mirror-public/scripts/mirror.sh +0 -374
  106. package/skills/self-sync/SKILL.md +0 -73
  107. package/skills/self-sync/scripts/run.js +0 -136
  108. package/skills/train/SKILL.md +0 -116
  109. package/skills/train/assets/dashboard-templates/classifiers.html +0 -106
  110. package/skills/train/assets/dashboard-templates/nlp.html +0 -102
  111. package/skills/train/assets/dashboard-templates/transformers.html +0 -98
  112. package/skills/train/assets/results-parsers/__init__.py +0 -9
  113. package/skills/train/assets/results-parsers/classifiers.py +0 -84
  114. package/skills/train/assets/results-parsers/nlp.py +0 -88
  115. package/skills/train/assets/results-parsers/reporter.py +0 -154
  116. package/skills/train/assets/results-parsers/transformers.py +0 -120
  117. package/skills/train/train_cli.py +0 -786
@@ -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`
@@ -35,10 +114,25 @@ This script handles all scaffolding in one step:
35
114
  6. Creates `project/configs/test-config.json` stub
36
115
  7. Creates `project/data/baselines.json`
37
116
  8. Creates `project/logs/events.json`
38
- 9. Stages and commits all files with the message `init: scaffold project structure and workflow config`
117
+ 9. Creates `docs/STRATEGY.md` — a strategic brief stub intended for investors, partners, and the product team
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.
39
128
 
40
- 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.
41
131
 
42
- ### 10. Prompt next step
132
+ ### 4. Prompt next step
43
133
 
44
- Inform the user that setup is complete and 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
@@ -0,0 +1,38 @@
1
+ # Strategy
2
+
3
+ <!-- This document is intended for investors, strategic partners, and senior stakeholders.
4
+ Write in clear, confident language that conveys conviction and focus.
5
+ Avoid jargon. Prioritise substance over length. -->
6
+
7
+ ## Vision
8
+
9
+ <!-- Describe the long-term direction of this project over a 3–5 year horizon.
10
+ What change do you want to see in the world, and what role does this project play in bringing it about?
11
+ A strong vision statement is specific, ambitious, and grounded — it should be possible to hold yourself accountable to it. -->
12
+
13
+ ## Value Proposition
14
+
15
+ <!-- Articulate what makes this project uniquely valuable and to whom.
16
+ Answer: Why does this exist? Why now? Why this team?
17
+ Focus on the distinct advantage or insight that underpins the project — not features, but the underlying value delivered. -->
18
+
19
+ ## Scope
20
+
21
+ ### In Scope
22
+
23
+ <!-- List the capabilities, domains, or problem spaces this project actively addresses.
24
+ Be specific enough that a new stakeholder can quickly understand the boundaries of the work.
25
+ Use bullet points for readability. -->
26
+
27
+ ### Out of Scope
28
+
29
+ <!-- List what this project explicitly does not cover.
30
+ Revenue model, pricing strategy, and competitive analysis are intentionally excluded from this document —
31
+ they belong in separate artefacts and are out of scope here.
32
+ Use this section to prevent scope creep and set clear expectations with stakeholders. -->
33
+
34
+ ## Target Audience
35
+
36
+ <!-- Describe who this project is built for.
37
+ Include both the end users (who experiences the product) and the stakeholders (who evaluates or funds it).
38
+ Be specific: a well-defined audience sharpens every other section of this document. -->
@@ -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"
@@ -0,0 +1,166 @@
1
+ #!/usr/bin/env bash
2
+ # ---------------------------------------------------------------------------
3
+ # skills/init/scripts/detect-existing-codebase.sh
4
+ #
5
+ # Deterministic front half of the /init "detect existing project state" step.
6
+ # /init currently always scaffolds as though the target directory were empty.
7
+ # That is wrong whenever a directory already carries a Jenga scaffold, or
8
+ # already carries substantial application code that predates Jenga entirely
9
+ # -- in the second case, scaffolding fresh produces an empty board and a stub
10
+ # PROJECT_SUMMARY.md that actively misrepresent the project.
11
+ #
12
+ # This script answers exactly one question -- "what kind of directory is
13
+ # this?" -- and nothing else. It never scaffolds, never prompts, never runs
14
+ # /uncharted, and never modifies anything on disk. Deciding what to DO with
15
+ # the verdict is agent judgement and lives in skills/init/SKILL.md.
16
+ #
17
+ # ---------------------------------------------------------------------------
18
+ # VERDICTS -- exactly one is printed on stdout, nothing else
19
+ # ---------------------------------------------------------------------------
20
+ # empty The target is empty, or contains only boilerplate
21
+ # that does not count as "there is a project here":
22
+ # .git (the directory itself, pruned entirely -- not
23
+ # merely excluded by name), .gitignore, and top-level
24
+ # README*/LICENSE*/LICENCE* files (case-insensitive),
25
+ # plus anything git itself reports as ignored. A repo
26
+ # containing only a README is empty for this purpose.
27
+ # already-scaffolded The target already carries a Jenga scaffold: any one
28
+ # of project/board/, project/PROJECT_SUMMARY.md, or
29
+ # project/configs/workflow.json is present. Checked
30
+ # BEFORE the emptiness scan, so a scaffolded project
31
+ # that also happens to look sparse is never misreported
32
+ # as "empty".
33
+ # existing-codebase The target has real content (source files, configs,
34
+ # docs beyond the boilerplate list above, etc.) and is
35
+ # not already Jenga-scaffolded. This is the case /init
36
+ # currently mishandles: scaffolding fresh here silently
37
+ # discards the fact that pre-existing code exists.
38
+ #
39
+ # ---------------------------------------------------------------------------
40
+ # NOTES ON GITIGNORE HANDLING
41
+ # ---------------------------------------------------------------------------
42
+ # /init runs this check BEFORE `git init` in the fresh-scaffold path, so the
43
+ # target directory is very often not a git work tree yet. Gitignore-based
44
+ # filtering is therefore best-effort: it only runs when the target already
45
+ # has a `.git` directory AND `git` is on PATH. A standalone `.gitignore` file
46
+ # with no repository behind it still counts as boilerplate via the name-based
47
+ # exclusion below -- it just cannot hide any OTHER file, because there is no
48
+ # git to ask "is this ignored".
49
+ #
50
+ # README/LICENSE exclusion applies to TOP-LEVEL entries only. A directory
51
+ # whose only content is a buried `docs/README.md` two levels down is real
52
+ # structure, not boilerplate, and must not be reported as empty.
53
+ #
54
+ # ---------------------------------------------------------------------------
55
+ # Usage
56
+ # ---------------------------------------------------------------------------
57
+ # detect-existing-codebase.sh [target-dir]
58
+ #
59
+ # target-dir Directory to classify. Default: current directory.
60
+ #
61
+ # Options:
62
+ # -h, --help Show this help and exit 0.
63
+ #
64
+ # Exit codes:
65
+ # 0 A verdict was printed on stdout.
66
+ # 1 Usage error (unknown option, more than one positional argument).
67
+ # 2 target-dir does not exist or is not a directory.
68
+ #
69
+ # Requires: bash, find. git is used opportunistically for gitignore
70
+ # filtering when the target is already a git work tree; its absence never
71
+ # causes a failure.
72
+ # ---------------------------------------------------------------------------
73
+
74
+ set -euo pipefail
75
+
76
+ SELF="$(basename "$0")"
77
+
78
+ usage() {
79
+ sed -n '/^# Usage$/,/^# Requires:/p' "$0" | sed -e 's/^# \{0,1\}//' -e '/^-\{10,\}$/d'
80
+ }
81
+
82
+ die_usage() {
83
+ printf '%s: error: %s\n' "$SELF" "$*" >&2
84
+ echo >&2
85
+ usage >&2
86
+ exit 1
87
+ }
88
+
89
+ TARGET_DIR="."
90
+ HAVE_TARGET=0
91
+
92
+ while [ "$#" -gt 0 ]; do
93
+ case "$1" in
94
+ -h|--help) usage; exit 0 ;;
95
+ --)
96
+ shift
97
+ [ "$#" -le 1 ] || die_usage "at most one target directory is allowed"
98
+ if [ "$#" -eq 1 ]; then TARGET_DIR="$1"; HAVE_TARGET=1; fi
99
+ shift $#
100
+ ;;
101
+ -*)
102
+ die_usage "unknown option \"$1\"" ;;
103
+ *)
104
+ [ "$HAVE_TARGET" -eq 0 ] || die_usage "at most one target directory is allowed (got \"$TARGET_DIR\" and \"$1\")"
105
+ TARGET_DIR="$1"; HAVE_TARGET=1; shift ;;
106
+ esac
107
+ done
108
+
109
+ [ -d "$TARGET_DIR" ] || { printf '%s: error: not a directory: %s\n' "$SELF" "$TARGET_DIR" >&2; exit 2; }
110
+
111
+ TARGET_DIR="$(cd -- "$TARGET_DIR" && pwd -P)"
112
+
113
+ # --- already-scaffolded: checked first, independent of emptiness -----------
114
+ if [ -d "$TARGET_DIR/project/board" ] \
115
+ || [ -f "$TARGET_DIR/project/PROJECT_SUMMARY.md" ] \
116
+ || [ -f "$TARGET_DIR/project/configs/workflow.json" ]; then
117
+ echo "already-scaffolded"
118
+ exit 0
119
+ fi
120
+
121
+ # --- enumerate candidate files, pruning .git entirely -----------------------
122
+ ALL_FILES=$(mktemp "${TMPDIR:-/tmp}/detect-existing-codebase.XXXXXX")
123
+ IGNORED_FILES=$(mktemp "${TMPDIR:-/tmp}/detect-existing-codebase-ignored.XXXXXX")
124
+ cleanup() { rm -f "$ALL_FILES" "$IGNORED_FILES"; }
125
+ trap cleanup EXIT
126
+
127
+ find "$TARGET_DIR" -path "$TARGET_DIR/.git" -prune -o -type f -print > "$ALL_FILES"
128
+
129
+ # --- best-effort gitignore filtering ----------------------------------------
130
+ : > "$IGNORED_FILES"
131
+ if [ -d "$TARGET_DIR/.git" ] && command -v git >/dev/null 2>&1; then
132
+ git -C "$TARGET_DIR" check-ignore --stdin < "$ALL_FILES" > "$IGNORED_FILES" 2>/dev/null || true
133
+ fi
134
+
135
+ # --- classify each candidate -------------------------------------------------
136
+ SOURCE_FOUND=0
137
+ while IFS= read -r f; do
138
+ [ -n "$f" ] || continue
139
+
140
+ if [ -s "$IGNORED_FILES" ] && grep -Fxq -- "$f" "$IGNORED_FILES"; then
141
+ continue
142
+ fi
143
+
144
+ rel="${f#"$TARGET_DIR"/}"
145
+ base="$(basename -- "$f")"
146
+ dir_rel="$(dirname -- "$rel")"
147
+
148
+ if [ "$dir_rel" = "." ]; then
149
+ if [ "$base" = ".gitignore" ]; then
150
+ continue
151
+ fi
152
+ base_upper="$(printf '%s' "$base" | tr '[:lower:]' '[:upper:]')"
153
+ case "$base_upper" in
154
+ README*|LICENSE*|LICENCE*) continue ;;
155
+ esac
156
+ fi
157
+
158
+ SOURCE_FOUND=1
159
+ break
160
+ done < "$ALL_FILES"
161
+
162
+ if [ "$SOURCE_FOUND" -eq 1 ]; then
163
+ echo "existing-codebase"
164
+ else
165
+ echo "empty"
166
+ fi
@@ -3,6 +3,25 @@ set -euo pipefail
3
3
 
4
4
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
5
  ASSETS_DIR="$SCRIPT_DIR/../assets"
6
+ VISIBILITY_SCRIPT="$SCRIPT_DIR/apply-project-visibility.sh"
7
+
8
+ # ─── 0. Resolve project_files_visibility ─────────────────────────────────────
9
+ # Defaults to `visible` — the only value that touches nothing on disk — so an
10
+ # unattended run can never silently relocate directories or edit .gitignore.
11
+ VISIBILITY="${JENGA_PROJECT_FILES_VISIBILITY:-visible}"
12
+
13
+ while [[ $# -gt 0 ]]; do
14
+ case "$1" in
15
+ --visibility) VISIBILITY="${2:-}"; shift 2 ;;
16
+ --visibility=*) VISIBILITY="${1#*=}"; shift ;;
17
+ *) echo "Unknown argument: $1" >&2
18
+ echo "Usage: $(basename "$0") [--visibility <visible|ignored>]" >&2
19
+ exit 1 ;;
20
+ esac
21
+ done
22
+
23
+ # Validate before scaffolding so a typo cannot leave a half-initialised project.
24
+ bash "$VISIBILITY_SCRIPT" --check-only "$VISIBILITY"
6
25
 
7
26
  # ─── 1. Initialize git repository ────────────────────────────────────────────
8
27
  echo "→ Initializing git repository..."
@@ -39,7 +58,22 @@ echo '{}' > project/data/baselines.json
39
58
  echo "→ Creating events.json..."
40
59
  echo '[]' > project/logs/events.json
41
60
 
42
- # ─── 9. Initial commit ───────────────────────────────────────────────────────
61
+ # ─── 9. Create docs/STRATEGY.md ──────────────────────────────────────────────
62
+ echo "→ Creating docs/STRATEGY.md (strategic brief for investors, partners, and the product team)..."
63
+ mkdir -p docs
64
+ cp "$ASSETS_DIR/strategy_stub_template.md" docs/STRATEGY.md
65
+
66
+ # ─── 10. Create CHANGELOG.md ──────────────────────────────────────────────────
67
+ echo "→ Creating CHANGELOG.md from template..."
68
+ cp "$SCRIPT_DIR/../../../templates/CHANGELOG_TEMPLATE.md" CHANGELOG.md
69
+
70
+ # ─── 11. Apply project_files_visibility ──────────────────────────────────────
71
+ # Runs before the commit so the .gitignore entry (ignored) is captured in the
72
+ # initial commit.
73
+ echo "→ Applying project files visibility ($VISIBILITY)..."
74
+ bash "$VISIBILITY_SCRIPT" "$VISIBILITY" "$PWD"
75
+
76
+ # ─── 12. Initial commit ──────────────────────────────────────────────────────
43
77
  echo "→ Staging and committing scaffolded files..."
44
78
  git add -A
45
79
  git commit -m "init: scaffold project structure and workflow config"