Skip to content

Commit ed84c12

Browse files
committed
instantiate.sh: empty-safe expansion for INIT_AGENT_ARGS (fixes #9)
The `--agent=none` path tripped `set -u` on bash 3.2 (macOS default) because `"${INIT_AGENT_ARGS[@]}"` raises "unbound variable" when the array is empty. init-wiki.sh never ran and the script exited non-zero. Switch both call sites to the portable empty-safe form `${ARR[@]+"${ARR[@]}"}"`, which expands with full per-element quoting when set and to nothing when empty, on bash 3.2 / 4 / 5. Adds a regression smoke test `instantiate-agent-none` that bootstraps the template with `--agent=none` and asserts the wiki is created and no agent overlay is installed. The macOS CI matrix actually runs bash 3.2, so this test would have caught the original bug. Also clears the workaround note from the existing `template-bootstrap` patch.sh now that `--agent=none` is exercised explicitly. Local harness: 72 pass, 0 fail (64 baseline + 8 new). Co-authored-by: Priscila Saboia Moreira <pmoreira@nd.edu>
1 parent b86c9e4 commit ed84c12

5 files changed

Lines changed: 99 additions & 6 deletions

File tree

scripts/instantiate.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -282,9 +282,9 @@ else
282282
fi
283283
fi
284284

285-
"$REPO_ROOT/wiki/init-wiki.sh" --github "${INIT_AGENT_ARGS[@]}"
285+
"$REPO_ROOT/wiki/init-wiki.sh" --github ${INIT_AGENT_ARGS[@]+"${INIT_AGENT_ARGS[@]}"}
286286
else
287-
"$REPO_ROOT/wiki/init-wiki.sh" "${INIT_AGENT_ARGS[@]}"
287+
"$REPO_ROOT/wiki/init-wiki.sh" ${INIT_AGENT_ARGS[@]+"${INIT_AGENT_ARGS[@]}"}
288288
fi
289289
fi
290290

scripts/test-mvp/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Currently one category. The harness auto-discovers any new categories under
1616
| Test | Assertions | What it checks |
1717
|---|---|---|
1818
| `template-bootstrap` | 14 | Clones the real template, runs `instantiate.sh`, asserts: bash syntax of all shipping scripts, CLAUDE.md generated with substituted placeholders, wiki sub-repo created, namespaced nav files present, `init-wiki.sh` is idempotent |
19+
| `instantiate-agent-none` | 8 | Regression for issue #9: runs `instantiate.sh --agent=none`, asserts bootstrap completes, CLAUDE.md is written, `init-wiki.sh` runs, and no `.claude/` or `.cursor/` overlay is copied |
1920

2021
## Usage
2122

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#!/usr/bin/env bash
2+
# Assertions for the --agent=none regression smoke test (issue #9).
3+
#
4+
# Before the fix, instantiate.sh exited non-zero with
5+
# "INIT_AGENT_ARGS[@]: unbound variable"
6+
# on bash 3.2 and init-wiki.sh never ran. After the fix, the script
7+
# completes and produces CLAUDE.md + the wiki sub-repo.
8+
9+
T="$SANDBOX/template-none"
10+
11+
if [ ! -d "$T" ]; then
12+
skip "instantiate-agent-none assertions" "template not cloned (offline + no MVP_TEMPLATE_LOCAL)"
13+
return 0 2>/dev/null || true
14+
fi
15+
16+
# Bootstrap exit + CLAUDE.md substitution
17+
assert "instantiate.sh --agent=none produced CLAUDE.md" \
18+
"[ -f '$T/CLAUDE.md' ]"
19+
assert_contains "CLAUDE.md has project name substituted" \
20+
"$T/CLAUDE.md" "Agent None Project"
21+
assert "CLAUDE.md has no {{PROJECT_NAME}} leak" \
22+
"! grep -q '{{PROJECT_NAME}}' '$T/CLAUDE.md'"
23+
24+
# init-wiki.sh must have run (the regression killed it before it could fire)
25+
REPO_NAME=$(basename "$T")
26+
WIKI_SUB="$T/wiki/${REPO_NAME}.wiki"
27+
28+
assert "wiki sub-repo created at wiki/${REPO_NAME}.wiki/ (init-wiki.sh ran)" \
29+
"[ -d '$WIKI_SUB/.git' ]"
30+
assert "Home_${REPO_NAME}.md exists" \
31+
"[ -f '$WIKI_SUB/Home_${REPO_NAME}.md' ]"
32+
assert "SCHEMA_${REPO_NAME}.md exists" \
33+
"[ -f '$WIKI_SUB/SCHEMA_${REPO_NAME}.md' ]"
34+
35+
# --agent=none means no agent-overlay files should have been copied into
36+
# the project root. The template ships agent overlays under wiki/agents/
37+
# but instantiate.sh should NOT have created .claude/ or .cursor/ when
38+
# --agent=none.
39+
assert "no .claude/ overlay copied when --agent=none" \
40+
"[ ! -d '$T/.claude' ]"
41+
assert "no .cursor/ overlay copied when --agent=none" \
42+
"[ ! -d '$T/.cursor' ]"
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#!/usr/bin/env bash
2+
# Smoke test: instantiate with --agent=none.
3+
#
4+
# Regression coverage for issue #9: instantiate.sh tripped `set -u` on
5+
# bash 3.2 (macOS default) when INIT_AGENT_ARGS expanded empty for
6+
# --agent=none, killing the bootstrap before init-wiki.sh could run.
7+
#
8+
# This test exercises the no-overlay path end-to-end so the bug cannot
9+
# return silently. Runs against the macOS matrix where bash 3.2 actually
10+
# reproduces the original failure.
11+
#
12+
# Inputs: SANDBOX env var. lib/template.sh's clone_template.
13+
# Effects: $SANDBOX/template-none/ contains a derivative bootstrapped
14+
# without any agent overlay.
15+
#
16+
# Idempotent.
17+
18+
set -euo pipefail
19+
20+
HARNESS_LIB="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../../lib" && pwd)"
21+
# shellcheck source=../../../lib/template.sh
22+
source "$HARNESS_LIB/template.sh"
23+
24+
T="$SANDBOX/template-none"
25+
26+
if [ -d "$T" ]; then
27+
echo " Template-none already cloned at $T (idempotent re-run)."
28+
elif clone_template "$T"; then
29+
echo " Cloned template to $T."
30+
else
31+
echo " WARN: could not clone template (no network and no MVP_TEMPLATE_LOCAL)." >&2
32+
exit 0
33+
fi
34+
35+
if [ -f "$T/scripts/instantiate.sh" ]; then
36+
(
37+
cd "$T"
38+
if [ ! -f CLAUDE.md ]; then
39+
bash scripts/instantiate.sh "Agent None Project" \
40+
--agent=none \
41+
--description="Regression test for issue #9 (set -u + empty array)." \
42+
>/tmp/instantiate-none.log 2>&1 || {
43+
echo " WARN: instantiate.sh --agent=none failed; assertions will surface the cause." >&2
44+
cat /tmp/instantiate-none.log | sed 's/^/ /' >&2
45+
}
46+
fi
47+
)
48+
fi
49+
50+
echo " Smoke instantiate-agent-none patch applied: template at $T."

scripts/test-mvp/tests/smoke/template-bootstrap/patch.sh

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ if [ -f "$T/scripts/instantiate.sh" ]; then
4545
cd "$T"
4646
# Only run instantiate if it hasn't already been run (CLAUDE.md absent)
4747
if [ ! -f CLAUDE.md ]; then
48-
# Use --agent=claude-code (the documented default). Note: the
49-
# template currently has a 'set -u' bug with empty INIT_AGENT_ARGS
50-
# when --agent=none is used; this should be filed upstream.
51-
# Using claude-code sidesteps the bug for our smoke test.
48+
# Use --agent=claude-code (the documented default) to exercise
49+
# the claude-code overlay. The --agent=none path is covered
50+
# separately by the instantiate-agent-none smoke test (issue #9
51+
# regression).
5252
bash scripts/instantiate.sh "Smoke Test Project" \
5353
--agent=claude-code \
5454
--description="Bootstrapping the template inside the harness sandbox." \

0 commit comments

Comments
 (0)