aw-spec-cli 0.1.2 → 0.1.4

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 (77) hide show
  1. package/README.md +291 -0
  2. package/assets/docs/ModularMonolith/ModularMonolith.Reference.pack.txt +25248 -0
  3. package/assets/docs/ModularMonolith/ModularMonolith.pack.txt +5726 -0
  4. package/assets/docs/ModularMonolith/pack-foundation.ps1 +145 -0
  5. package/assets/docs/ModularMonolith/pack-foundation.sh +196 -0
  6. package/assets/docs/ModularMonolith/pack-reference-foundation.ps1 +157 -0
  7. package/assets/docs/ModularMonolith/pack-reference-foundation.sh +209 -0
  8. package/assets/docs/ModularMonolith/unpack-foundation.ps1 +126 -0
  9. package/assets/docs/ModularMonolith/unpack-foundation.sh +217 -0
  10. package/assets/docs/ModularMonolith/unpack-reference-foundation.ps1 +129 -0
  11. package/assets/docs/ModularMonolith/unpack-reference-foundation.sh +218 -0
  12. package/assets/docs/UI.Visualization/PACKAGING.md +191 -0
  13. package/assets/docs/UI.Visualization/UI.Visualization.Reference.pack.txt +11768 -0
  14. package/assets/docs/UI.Visualization/UI.Visualization.pack.txt +11214 -0
  15. package/assets/docs/UI.Visualization/pack-foundation.ps1 +165 -0
  16. package/assets/docs/UI.Visualization/pack-foundation.sh +206 -0
  17. package/assets/docs/UI.Visualization/pack-reference-foundation.ps1 +159 -0
  18. package/assets/docs/UI.Visualization/pack-reference-foundation.sh +205 -0
  19. package/assets/docs/UI.Visualization/unpack-foundation.ps1 +126 -0
  20. package/assets/docs/UI.Visualization/unpack-foundation.sh +217 -0
  21. package/assets/docs/UI.Visualization/unpack-reference-foundation.ps1 +129 -0
  22. package/assets/docs/UI.Visualization/unpack-reference-foundation.sh +218 -0
  23. package/assets/docs/VerticalSlice/VerticalSlice.Reference.pack.txt +19318 -0
  24. package/assets/docs/VerticalSlice/pack-reference-foundation.ps1 +157 -0
  25. package/assets/docs/VerticalSlice/pack-reference-foundation.sh +209 -0
  26. package/assets/docs/VerticalSlice/unpack-reference-foundation.ps1 +129 -0
  27. package/assets/docs/VerticalSlice/unpack-reference-foundation.sh +218 -0
  28. package/assets/docs/components/Email/README.md +7 -0
  29. package/assets/docs/components/Email/ReferenceEndpoints/SendEmailEndpoint.cs +84 -0
  30. package/assets/docs/components/Email/integration.md +57 -17
  31. package/assets/docs/components/Jobs/integration.md +29 -15
  32. package/assets/docs/components/QrGenerator/README.md +7 -0
  33. package/assets/docs/components/QrGenerator/ReferenceEndpoints/GenerateQrEndpoint.cs +57 -0
  34. package/assets/docs/components/QrGenerator/integration.md +51 -6
  35. package/assets/docs/components/README.md +19 -2
  36. package/assets/docs/domainspecs/UIVisualization/chart-bubble.md +70 -0
  37. package/assets/docs/domainspecs/UIVisualization/chart-dimred.md +58 -0
  38. package/assets/docs/domainspecs/UIVisualization/chart-heatmap.md +62 -0
  39. package/assets/docs/domainspecs/UIVisualization/chart-network.md +69 -0
  40. package/assets/docs/domainspecs/UIVisualization/chart-parallel.md +75 -0
  41. package/assets/docs/domainspecs/UIVisualization/chart-scurve.md +66 -0
  42. package/assets/docs/domainspecs/UIVisualization/chart-survival.md +69 -0
  43. package/assets/docs/domainspecs/UIVisualization/chart-trellis.md +68 -0
  44. package/assets/docs/domainspecs/UIVisualization/chart-violin.md +61 -0
  45. package/assets/docs/domainspecs/UIVisualization/chart-volcano.md +63 -0
  46. package/assets/docs/domainspecs/UIVisualization/charting-standards.domain.md +80 -0
  47. package/assets/docs/domainspecs/UIVisualization/clean-architecture.domain.md +87 -0
  48. package/assets/docs/domainspecs/UIVisualization/coding-standards.domain.md +47 -0
  49. package/assets/docs/domainspecs/UIVisualization/comandrulemap.md +130 -0
  50. package/assets/docs/domainspecs/UIVisualization/component-contracts.domain.md +67 -0
  51. package/assets/docs/domainspecs/UIVisualization/data-source.domain.md +68 -0
  52. package/assets/docs/domainspecs/UIVisualization/domain-requirements.md +110 -0
  53. package/assets/docs/domainspecs/UIVisualization/folder-structure.domain.md +55 -0
  54. package/assets/docs/domainspecs/UIVisualization/state-management.domain.md +67 -0
  55. package/assets/docs/domainspecs/UIVisualization/testing.domain.md +52 -0
  56. package/assets/docs/domainspecs/UIVisualization/ui-viz-terms.md +39 -0
  57. package/assets/docs/domainspecs/healthcare/comandrulemap.md +47 -0
  58. package/assets/docs/domainspecs/pharma/comandrulemap.md +50 -0
  59. package/dist/commands/init.d.ts.map +1 -1
  60. package/dist/commands/init.js +54 -7
  61. package/dist/commands/init.js.map +1 -1
  62. package/dist/commands/update.d.ts +3 -0
  63. package/dist/commands/update.d.ts.map +1 -0
  64. package/dist/commands/update.js +142 -0
  65. package/dist/commands/update.js.map +1 -0
  66. package/dist/index.js +2 -0
  67. package/dist/index.js.map +1 -1
  68. package/dist/utils/manifest.d.ts +31 -0
  69. package/dist/utils/manifest.d.ts.map +1 -0
  70. package/dist/utils/manifest.js +91 -0
  71. package/dist/utils/manifest.js.map +1 -0
  72. package/dist/utils/update-engine.d.ts +52 -0
  73. package/dist/utils/update-engine.d.ts.map +1 -0
  74. package/dist/utils/update-engine.js +203 -0
  75. package/dist/utils/update-engine.js.map +1 -0
  76. package/package.json +5 -2
  77. package/assets/docs/requirement-spec.txt +0 -15
@@ -0,0 +1,218 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # unpack-reference-foundation.sh — bash/macOS port of unpack-reference-foundation.ps1
4
+ #
5
+ # SYNOPSIS
6
+ # Unpack an AW-Spec reference pack file into a target project, renaming the
7
+ # sentinel app name to the caller's app name.
8
+ #
9
+ # DESCRIPTION
10
+ # Reads --pack-file (produced by pack-reference-foundation.sh/.ps1), takes the sentinel
11
+ # from its header (override with --sentinel), derives four case forms of the target app
12
+ # name, and writes every file block to --out-dir with the sentinel rewritten in both file
13
+ # CONTENTS and file/dir PATHS. Text blocks are rewritten and written as UTF-8; base64
14
+ # blocks are decoded as-is. Refuses to overwrite existing files unless --force.
15
+ #
16
+ # EXAMPLE
17
+ # ./unpack-reference-foundation.sh \
18
+ # --pack-file ./VerticalSlice.Reference.pack.txt \
19
+ # --target-app-name AppWeaver.Pharma \
20
+ # --out-dir ../../
21
+ #
22
+ set -euo pipefail
23
+
24
+ # ------------------------------------------------------------------ defaults ---
25
+ PACK_FILE=''
26
+ TARGET_APP_NAME=''
27
+ OUT_DIR='.'
28
+ SENTINEL=''
29
+ FORCE=0
30
+ DRYRUN=0
31
+
32
+ usage() {
33
+ cat >&2 <<'EOF'
34
+ Usage: unpack-reference-foundation.sh --pack-file <file> --target-app-name <name>
35
+ [--out-dir <dir>] [--sentinel <name>]
36
+ [--force] [--dry-run]
37
+
38
+ -p, --pack-file <file> Reference pack file to unpack (required)
39
+ -t, --target-app-name <name> New app name to rename the sentinel into (required)
40
+ -o, --out-dir <dir> Output root (default: .)
41
+ --sentinel <name> Override the sentinel from the pack header
42
+ --force Overwrite files that already exist
43
+ --dry-run List what would be written, write nothing
44
+ -h, --help Show this help
45
+
46
+ Positional fallback: unpack-reference-foundation.sh <pack-file> <target-app-name> [out-dir]
47
+ EOF
48
+ }
49
+
50
+ # -------------------------------------------------------------- arg parsing ---
51
+ while [ $# -gt 0 ]; do
52
+ case "$1" in
53
+ -p|--pack-file) PACK_FILE="${2:?--pack-file needs a value}"; shift 2 ;;
54
+ -t|--target-app-name) TARGET_APP_NAME="${2:?--target-app-name needs a value}"; shift 2 ;;
55
+ -o|--out-dir) OUT_DIR="${2:?--out-dir needs a value}"; shift 2 ;;
56
+ --sentinel) SENTINEL="${2:?--sentinel needs a value}"; shift 2 ;;
57
+ --force) FORCE=1; shift ;;
58
+ --dry-run) DRYRUN=1; shift ;;
59
+ -h|--help) usage; exit 0 ;;
60
+ --) shift; break ;;
61
+ -*) echo "Error: unknown option: $1" >&2; usage; exit 2 ;;
62
+ *)
63
+ if [ -z "$PACK_FILE" ]; then PACK_FILE="$1"
64
+ elif [ -z "$TARGET_APP_NAME" ]; then TARGET_APP_NAME="$1"
65
+ else OUT_DIR="$1"
66
+ fi
67
+ shift ;;
68
+ esac
69
+ done
70
+
71
+ [ -n "$PACK_FILE" ] || { echo "Error: --pack-file is required." >&2; usage; exit 2; }
72
+ [ -n "$TARGET_APP_NAME" ] || { echo "Error: --target-app-name is required." >&2; usage; exit 2; }
73
+ [ -f "$PACK_FILE" ] || { echo "Error: pack file not found: $PACK_FILE" >&2; exit 1; }
74
+
75
+ case "$TARGET_APP_NAME" in
76
+ *[!A-Za-z0-9._-]*)
77
+ echo "Error: --target-app-name may contain only letters, digits, '.', '_' or '-': $TARGET_APP_NAME" >&2
78
+ exit 2 ;;
79
+ esac
80
+
81
+ # ------------------------------------------------ sentinel from header --------
82
+ if [ -z "$SENTINEL" ]; then
83
+ SENTINEL="$(LC_ALL=C sed -n 's/^#[[:space:]]*sentinel:[[:space:]]*\(.*[^[:space:]]\)[[:space:]]*$/\1/p' "$PACK_FILE" | head -n1)"
84
+ fi
85
+ [ -n "$SENTINEL" ] || { echo "Error: Sentinel not found in pack header; supply it with --sentinel." >&2; exit 1; }
86
+
87
+ # ------------------------------------------------ derive case forms -----------
88
+ to_lower() { printf '%s' "$1" | LC_ALL=C tr '[:upper:]' '[:lower:]'; }
89
+
90
+ S_DOT="$SENTINEL"; T_DOT="$TARGET_APP_NAME"
91
+ S_UND="${SENTINEL//./_}"; T_UND="${TARGET_APP_NAME//./_}"
92
+ s_low="$(to_lower "$SENTINEL")"; t_low="$(to_lower "$TARGET_APP_NAME")"
93
+ S_HYP="${s_low//./-}"; T_HYP="${t_low//./-}"
94
+ S_LDOT="$s_low"; T_LDOT="$t_low"
95
+
96
+ FROM=(); TO=()
97
+ add_form() {
98
+ local from="$1" to="$2" e
99
+ [ -n "$from" ] || return 0
100
+ [ "$from" = "$to" ] && return 0
101
+ if [ "${#FROM[@]}" -gt 0 ]; then
102
+ for e in "${FROM[@]}"; do [ "$e" = "$from" ] && return 0; done
103
+ fi
104
+ FROM+=("$from"); TO+=("$to")
105
+ }
106
+ add_form "$S_DOT" "$T_DOT"
107
+ add_form "$S_UND" "$T_UND"
108
+ add_form "$S_HYP" "$T_HYP"
109
+ add_form "$S_LDOT" "$T_LDOT"
110
+
111
+ # Sort indices by FROM length descending
112
+ ORDER=()
113
+ {
114
+ local_n="${#FROM[@]}"
115
+ used=(); for ((k = 0; k < local_n; k++)); do used[$k]=0; done
116
+ for ((pass = 0; pass < local_n; pass++)); do
117
+ best=-1; bestlen=-1
118
+ for ((j = 0; j < local_n; j++)); do
119
+ if [ "${used[$j]}" -eq 0 ] && [ "${#FROM[$j]}" -gt "$bestlen" ]; then
120
+ bestlen="${#FROM[$j]}"; best="$j"
121
+ fi
122
+ done
123
+ used[$best]=1; ORDER+=("$best")
124
+ done
125
+ }
126
+
127
+ REPL_OUT=''
128
+ apply_repl() {
129
+ local text="$1" idx from to
130
+ if [ "${#ORDER[@]}" -gt 0 ]; then
131
+ for idx in "${ORDER[@]}"; do
132
+ from="${FROM[$idx]}"; to="${TO[$idx]}"
133
+ text="${text//"$from"/$to}"
134
+ done
135
+ fi
136
+ REPL_OUT="$text"
137
+ }
138
+
139
+ # ------------------------------------------------ output root ----------------
140
+ [ -d "$OUT_DIR" ] || mkdir -p "$OUT_DIR"
141
+ OUT_ROOT="$(cd "$OUT_DIR" && pwd -P)"
142
+
143
+ # ------------------------------------------------ base64 decoder (portable) --
144
+ B64D=()
145
+ if printf 'aGk=' | base64 -d >/dev/null 2>&1; then B64D=(base64 -d)
146
+ elif printf 'aGk=' | base64 -D >/dev/null 2>&1; then B64D=(base64 -D)
147
+ elif printf 'aGk=' | base64 --decode >/dev/null 2>&1; then B64D=(base64 --decode)
148
+ else B64D=(openssl base64 -d -A)
149
+ fi
150
+
151
+ # ------------------------------------------------ parse file blocks ----------
152
+ rels=(); encs=(); contents=()
153
+ in_block=0; cur_rel=''; cur_enc=''; cur_content=''; first_line=1
154
+ file_re='^<<<FILE path="([^"]+)"( encoding="([^"]+)")?>>>[[:space:]]*$'
155
+
156
+ while IFS= read -r line || [ -n "$line" ]; do
157
+ line="${line%$'\r'}"
158
+ if [ "$in_block" -eq 0 ]; then
159
+ if [[ "$line" =~ $file_re ]]; then
160
+ cur_rel="${BASH_REMATCH[1]}"
161
+ cur_enc="${BASH_REMATCH[3]:-}"
162
+ in_block=1; first_line=1; cur_content=''
163
+ fi
164
+ else
165
+ if [ "$line" = '<<<ENDFILE>>>' ]; then
166
+ rels+=("$cur_rel"); encs+=("$cur_enc"); contents+=("$cur_content")
167
+ in_block=0
168
+ elif [ "$first_line" -eq 1 ]; then
169
+ cur_content="$line"; first_line=0
170
+ else
171
+ cur_content="$cur_content"$'\n'"$line"
172
+ fi
173
+ fi
174
+ done < "$PACK_FILE"
175
+
176
+ [ "${#rels[@]}" -gt 0 ] || { echo "Error: No <<<FILE>>> blocks found in pack: $PACK_FILE" >&2; exit 1; }
177
+
178
+ # ------------------------------------------------ resolve destinations -------
179
+ dests=()
180
+ for ((i = 0; i < ${#rels[@]}; i++)); do
181
+ apply_repl "${rels[$i]}"
182
+ dests+=("$OUT_ROOT/$REPL_OUT")
183
+ done
184
+
185
+ # ------------------------------------------------ conflict guard -------------
186
+ if [ "$FORCE" -eq 0 ] && [ "$DRYRUN" -eq 0 ]; then
187
+ conflicts=()
188
+ for d in "${dests[@]}"; do [ -e "$d" ] && conflicts+=("$d"); done
189
+ if [ "${#conflicts[@]}" -gt 0 ]; then
190
+ echo "Error: Refusing to overwrite existing files (re-run with --force):" >&2
191
+ printf ' %s\n' "${conflicts[@]}" >&2
192
+ exit 1
193
+ fi
194
+ fi
195
+
196
+ # ------------------------------------------------ write ----------------------
197
+ written=0
198
+ for ((i = 0; i < ${#rels[@]}; i++)); do
199
+ rel="${rels[$i]}"; enc="${encs[$i]}"; dest="${dests[$i]}"
200
+ if [ "$DRYRUN" -eq 1 ]; then
201
+ echo "WOULD WRITE $rel -> $dest"
202
+ continue
203
+ fi
204
+ mkdir -p "$(dirname "$dest")"
205
+ if [ "$enc" = 'base64' ]; then
206
+ printf '%s' "${contents[$i]}" | tr -d '[:space:]' | "${B64D[@]}" > "$dest"
207
+ else
208
+ apply_repl "${contents[$i]}"
209
+ printf '%s' "$REPL_OUT" > "$dest"
210
+ fi
211
+ written=$((written + 1))
212
+ done
213
+
214
+ if [ "$DRYRUN" -eq 1 ]; then
215
+ echo "DryRun: ${#rels[@]} file(s) would be written to $OUT_ROOT (sentinel '$SENTINEL' -> '$TARGET_APP_NAME')."
216
+ else
217
+ echo "Unpacked $written file(s) to $OUT_ROOT (sentinel '$SENTINEL' -> '$TARGET_APP_NAME')."
218
+ fi
@@ -0,0 +1,191 @@
1
+ # UI.Visualization — Foundation Packaging Rules
2
+
3
+ > **Why this exists.** This packaging model replaces reconstruction with a
4
+ > **byte-for-byte bundle of the real, verified Next.js template**.
5
+ >
6
+ > You author the UI foundation **once** (a Next.js app that actually builds and runs),
7
+ > pack it into a single text file, and the scaffolder **unpacks + renames** it.
8
+ > No regeneration, no drift — the same guarantee that `VerticalSlice` provides for the backend.
9
+
10
+ ---
11
+
12
+ ## The single artifact
13
+
14
+ ```
15
+ docs/UI.Visualization/
16
+ ├── UI.Visualization.pack.txt ← THE BUNDLE: every source file in one text file
17
+ ├── PACKAGING.md ← this file
18
+ ├── pack-foundation.ps1 ← produces the pack from the template folder (Windows)
19
+ ├── pack-foundation.sh ← produces the pack from the template folder (macOS/Linux)
20
+ ├── pack-reference-foundation.ps1 ← produces a reference/sample pack
21
+ ├── pack-reference-foundation.sh
22
+ ├── unpack-foundation.ps1 ← extracts + renames into a target app (used by skill)
23
+ ├── unpack-foundation.sh
24
+ ├── unpack-reference-foundation.ps1
25
+ └── unpack-reference-foundation.sh
26
+ ```
27
+
28
+ The source template lives at:
29
+
30
+ ```
31
+ templates/UI.Visualization/
32
+ ```
33
+
34
+ ---
35
+
36
+ ## The sentinel convention
37
+
38
+ The template is authored under the sentinel app name:
39
+
40
+ ```
41
+ UI.Visualization
42
+ ```
43
+
44
+ The scaffolder rewrites the sentinel in **four case forms** (ordinal, case-sensitive, longest-first),
45
+ applied to **file contents and to file/folder paths**:
46
+
47
+ | Form | Sentinel | Example target (`PharmaViz`) | Where it appears |
48
+ |--------------|--------------------------------|---------------------------------|-------------------------------------------|
49
+ | dotted | `UI.Visualization` | `PharmaViz` | `package.json` name (dotted form), README |
50
+ | underscored | `UI_Visualization` | `PharmaViz` | any underscored identifiers |
51
+ | lower-hyphen | `ui-visualization` | `pharmaviz` | npm package name, Docker image tag |
52
+ | lower-dot | `ui.visualization` | `pharmaviz` | any lowercased identifiers |
53
+
54
+ ### What does NOT get renamed
55
+
56
+ - `AppWeaver.*` framework package references in `package.json` (there are none in this UI template — all deps are third-party).
57
+ - The generic sample pages (`/heatmap`, `/bubble`, etc.) — these are example content the caller replaces with their own pages.
58
+
59
+ ---
60
+
61
+ ## How to author the template (do this once per change)
62
+
63
+ 1. Work in `templates/UI.Visualization/`.
64
+
65
+ 2. Use `UI.Visualization` as the sentinel wherever the app name belongs:
66
+ - `package.json` → `"name": "ui-visualization"` (lower-hyphen form)
67
+ - `README.md` → title
68
+ - `src/app/layout.tsx` → `<title>UI.Visualization</title>` and metadata
69
+ - Any other branding strings
70
+
71
+ 3. Verify the template builds and runs clean:
72
+ ```bash
73
+ cd templates/UI.Visualization
74
+ npm install
75
+ npm run build # must exit 0, no TypeScript errors
76
+ npm run dev # browse to http://localhost:3000, all 10 chart pages render
77
+ ```
78
+
79
+ 4. Fix every error here, in the real template, where the compiler tells you exactly what's wrong.
80
+
81
+ ---
82
+
83
+ ## How to build the bundle
84
+
85
+ From `docs/UI.Visualization/`:
86
+
87
+ **macOS / Linux:**
88
+ ```bash
89
+ ./pack-foundation.sh \
90
+ --source-dir ../../../../templates/UI.Visualization \
91
+ --out-file ./UI.Visualization.pack.txt
92
+ ```
93
+
94
+ **Windows (PowerShell):**
95
+ ```powershell
96
+ ./pack-foundation.ps1 `
97
+ -SourceDir ../../../../templates/UI.Visualization `
98
+ -OutFile ./UI.Visualization.pack.txt
99
+ ```
100
+
101
+ The packer:
102
+ - Walks the template, **excluding** build/IDE and JS output artifacts:
103
+ - dirs: `node_modules .next .turbo dist out coverage .cache bin obj .vs .git logs`
104
+ - files: `*.tsbuildinfo next-env.d.ts *.log .env.* *.pem *.key secrets.json`
105
+ - **Fails closed on detected secrets** — scans file contents for credential markers and refuses to pack unless `--allow-secrets` / `-AllowSecrets` is passed.
106
+ - Stores text files **verbatim** and binary files (e.g. `.xlsx`) **base64-encoded**.
107
+ - Writes a header containing `foundation`, `sentinel`, file count, format version, and the replacement contract.
108
+ - **Warns** if the sentinel token appears in zero files.
109
+
110
+ Re-run it whenever the template changes; commit the regenerated `UI.Visualization.pack.txt`.
111
+
112
+ ---
113
+
114
+ ## How to build the reference pack
115
+
116
+ The reference pack is used by `/aw-spec-addcomponent` and `/aw-spec-implement` unpack workflows
117
+ when a feature reference example exists under `templates/features/`.
118
+
119
+ ```bash
120
+ ./pack-reference-foundation.sh \
121
+ --source-dir ../../../../templates/features/UIVisualization.SimpleSample \
122
+ --out-file ./UI.Visualization.Reference.pack.txt
123
+ ```
124
+
125
+ *(Create the `SimpleSample` folder when you have a working feature example to bundle.)*
126
+
127
+ ---
128
+
129
+ ## Pack file format (`aw-spec-pack/v1`)
130
+
131
+ Same format as `VerticalSlice.pack.txt`:
132
+
133
+ ```
134
+ # AW-SPEC FOUNDATION PACK
135
+ # foundation: UI.Visualization
136
+ # sentinel: UI.Visualization
137
+ # generated: 2026-06-26T10:00:00.0000000Z
138
+ # files: 32
139
+ # format: aw-spec-pack/v1
140
+ # --- replacement contract ... ---
141
+ # ============================================================
142
+
143
+ <<<FILE path="package.json">>>
144
+ ...verbatim file content...
145
+ <<<ENDFILE>>>
146
+ <<<FILE path="src/app/layout.tsx">>>
147
+ ...
148
+ <<<ENDFILE>>>
149
+ <<<FILE path="public/sample-data.xlsx" encoding="base64">>>
150
+ AAABAAE...
151
+ <<<ENDFILE>>>
152
+ ```
153
+
154
+ ---
155
+
156
+ ## How scaffolding consumes the bundle
157
+
158
+ `/aw-spec-foundation UI.Visualization <AppName> [OutputDir]`
159
+ runs `unpack-foundation.sh` (or `.ps1`), which reads the sentinel from the pack header,
160
+ derives the four target case forms, and writes the renamed files to the output directory.
161
+
162
+ ```bash
163
+ # macOS / Linux
164
+ ./unpack-foundation.sh \
165
+ --pack-file ./UI.Visualization.pack.txt \
166
+ --target-app-name PharmaViz \
167
+ --out-dir ~/projects/
168
+
169
+ # Windows
170
+ ./unpack-foundation.ps1 `
171
+ -PackFile ./UI.Visualization.pack.txt `
172
+ -TargetAppName PharmaViz `
173
+ -OutDir ~/projects/
174
+ ```
175
+
176
+ After unpacking:
177
+ ```bash
178
+ cd ~/projects/PharmaViz # or wherever OutDir puts it
179
+ npm install
180
+ npm run dev # → http://localhost:3000
181
+ ```
182
+
183
+ ---
184
+
185
+ ## Maintenance checklist
186
+
187
+ - [ ] Template builds clean (`npm run build`, no TypeScript errors).
188
+ - [ ] Sentinel `UI.Visualization` appears in `package.json`, `README.md`, `layout.tsx`.
189
+ - [ ] No `node_modules/`, `.next/`, or generated files committed into the pack.
190
+ - [ ] `pack-foundation.sh` reported a non-zero sentinel hit count.
191
+ - [ ] `UI.Visualization.pack.txt` regenerated and committed after any change.