prizmkit 1.1.40 → 1.1.41

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 (27) hide show
  1. package/bundled/VERSION.json +3 -3
  2. package/bundled/dev-pipeline/SCHEMA_ANALYSIS.md +1 -1
  3. package/bundled/dev-pipeline/run-bugfix.sh +74 -0
  4. package/bundled/dev-pipeline/run-feature.sh +74 -0
  5. package/bundled/dev-pipeline/run-refactor.sh +74 -0
  6. package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +0 -6
  7. package/bundled/dev-pipeline/templates/bootstrap-tier1.md +0 -23
  8. package/bundled/dev-pipeline/templates/bootstrap-tier2.md +0 -23
  9. package/bundled/dev-pipeline/templates/bootstrap-tier3.md +0 -23
  10. package/bundled/dev-pipeline/tests/test-deploy-safety.sh +223 -0
  11. package/bundled/skills/_metadata.json +3 -3
  12. package/bundled/skills/app-planner/SKILL.md +0 -3
  13. package/bundled/skills/bugfix-pipeline-launcher/SKILL.md +8 -2
  14. package/bundled/skills/feature-pipeline-launcher/SKILL.md +8 -2
  15. package/bundled/skills/prizmkit-committer/SKILL.md +0 -1
  16. package/bundled/skills/prizmkit-deploy/SKILL.md +491 -209
  17. package/bundled/skills/prizmkit-deploy/references/cloud-platform-deploy.md +93 -0
  18. package/bundled/skills/prizmkit-deploy/references/deploy-config-schema.md +147 -0
  19. package/bundled/skills/prizmkit-deploy/references/deploy-history-schema.md +62 -0
  20. package/bundled/skills/prizmkit-deploy/references/docker-deploy.md +31 -0
  21. package/bundled/skills/prizmkit-deploy/references/nginx-blue-green.md +59 -0
  22. package/bundled/skills/prizmkit-init/SKILL.md +0 -2
  23. package/bundled/skills/prizmkit-plan/SKILL.md +0 -3
  24. package/bundled/skills/refactor-pipeline-launcher/SKILL.md +8 -2
  25. package/package.json +1 -1
  26. package/bundled/dev-pipeline/templates/sections/phase-deploy-verification.md +0 -31
  27. package/bundled/skills/prizmkit-deploy/assets/deploy-template.md +0 -187
@@ -1,5 +1,5 @@
1
1
  {
2
- "frameworkVersion": "1.1.40",
3
- "bundledAt": "2026-04-20T14:02:15.471Z",
4
- "bundledFrom": "a703bde"
2
+ "frameworkVersion": "1.1.41",
3
+ "bundledAt": "2026-04-30T09:49:08.976Z",
4
+ "bundledFrom": "13a2ce9"
5
5
  }
@@ -325,7 +325,7 @@ pending, in_progress, completed, failed, skipped
325
325
  | `failure-log-check.md` | Failure log diagnostics |
326
326
  | `context-budget-rules.md` | Context window guardrails |
327
327
  | `phase-browser-verification.md` | Playwright UI verification |
328
- | `phase-deploy-verification.md` | Local deployment check |
328
+ | `phase-deploy-verification.md` | [DEPRECATED] Local deployment check (template removed) |
329
329
  | `ac-verification-checklist.md` | Acceptance criteria verification |
330
330
  | `feature-context.md` | Feature brief context |
331
331
  | `phase-specify-plan-full.md` | Full spec + plan workflow |
@@ -50,6 +50,7 @@ MODEL=${MODEL:-""}
50
50
  DEV_BRANCH=${DEV_BRANCH:-""}
51
51
  AUTO_PUSH=${AUTO_PUSH:-0}
52
52
  STOP_ON_FAILURE=${STOP_ON_FAILURE:-0}
53
+ ENABLE_DEPLOY=${ENABLE_DEPLOY:-0}
53
54
 
54
55
  # Source shared common helpers (CLI/platform detection + logs + deps)
55
56
  source "$SCRIPT_DIR/lib/common.sh"
@@ -955,6 +956,79 @@ main() {
955
956
  log_success " Total subagent calls: $total_subagent_calls"
956
957
  log_success "════════════════════════════════════════════════════"
957
958
 
959
+ # ── Deploy session (only if ENABLE_DEPLOY=1 and all bugs fixed) ──
960
+ if [[ "$ENABLE_DEPLOY" == "1" ]]; then
961
+ local incomplete_count
962
+ incomplete_count=$({ python3 -c "
963
+ import json, sys
964
+ with open(sys.argv[1]) as f:
965
+ data = json.load(f)
966
+ bad = [b for b in data.get('bugs', [])
967
+ if b.get('status') not in ('completed', 'skipped', 'needs_info')]
968
+ for b in bad:
969
+ print(f\" {b['id']}: {b.get('status', 'unknown')} — {b.get('title', '')}\")
970
+ print(len(bad))
971
+ " "$bug_list" 2>/dev/null || echo "0"; } | tee /dev/stderr | tail -1)
972
+
973
+ if [[ "$incomplete_count" -gt 0 ]]; then
974
+ echo ""
975
+ log_warn "DEPLOY BLOCKED: $incomplete_count bug(s) not fixed successfully."
976
+ log_warn "Fix failed bugs and re-run, or manually run /prizmkit-deploy."
977
+ else
978
+ echo ""
979
+ log_info "All bugs fixed — starting deploy session..."
980
+ log_info "ENABLE_DEPLOY=1"
981
+
982
+ local deploy_session_id="deploy-$(date +%Y%m%d%H%M%S)"
983
+ local deploy_session_dir="$STATE_DIR/deploy/$deploy_session_id"
984
+ mkdir -p "$deploy_session_dir/logs"
985
+
986
+ local deploy_prompt="$deploy_session_dir/bootstrap-prompt.md"
987
+ local _deploy_branch _deploy_commit
988
+ _deploy_branch=$(git -C "$_proj_root" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
989
+ _deploy_commit=$(git -C "$_proj_root" rev-parse --short HEAD 2>/dev/null || echo "unknown")
990
+ cat > "$deploy_prompt" << DEPLOY_PROMPT_EOF
991
+ ## Deploy
992
+
993
+ All bugs have been fixed successfully.
994
+
995
+ - Branch: $_deploy_branch
996
+ - Commit: $_deploy_commit
997
+
998
+ Run /prizmkit-deploy to deploy the project. Read .prizmkit/deploy/deploy.config.json
999
+ for deployment configuration. If no deploy config exists, guide the user through
1000
+ setting one up before deploying.
1001
+ DEPLOY_PROMPT_EOF
1002
+
1003
+ log_info "Deploy prompt: $deploy_prompt"
1004
+ log_info "Deploy log: $deploy_session_dir/logs/session.log"
1005
+
1006
+ case "$CLI_CMD" in
1007
+ *claude*)
1008
+ "$CLI_CMD" \
1009
+ -p "$(cat "$deploy_prompt")" \
1010
+ --dangerously-skip-permissions \
1011
+ > "$deploy_session_dir/logs/session.log" 2>&1
1012
+ ;;
1013
+ *)
1014
+ "$CLI_CMD" \
1015
+ --print \
1016
+ -y \
1017
+ < "$deploy_prompt" \
1018
+ > "$deploy_session_dir/logs/session.log" 2>&1
1019
+ ;;
1020
+ esac
1021
+ local deploy_exit=$?
1022
+
1023
+ if [[ $deploy_exit -eq 0 ]]; then
1024
+ log_success "Deploy session completed (exit 0)"
1025
+ else
1026
+ log_warn "Deploy session exited with code $deploy_exit"
1027
+ log_warn "Review log: $deploy_session_dir/logs/session.log"
1028
+ fi
1029
+ fi
1030
+ fi
1031
+
958
1032
  break
959
1033
  fi
960
1034
 
@@ -53,6 +53,7 @@ MODEL=${MODEL:-""}
53
53
  DEV_BRANCH=${DEV_BRANCH:-""}
54
54
  AUTO_PUSH=${AUTO_PUSH:-0}
55
55
  STOP_ON_FAILURE=${STOP_ON_FAILURE:-0}
56
+ ENABLE_DEPLOY=${ENABLE_DEPLOY:-0}
56
57
 
57
58
  # Source shared common helpers (CLI/platform detection + logs + deps)
58
59
  source "$SCRIPT_DIR/lib/common.sh"
@@ -1186,6 +1187,79 @@ print(count)
1186
1187
  log_warn "Run './run-feature.sh unskip' to reset and retry them."
1187
1188
  fi
1188
1189
 
1190
+ # ── Deploy session (only if ENABLE_DEPLOY=1 and all features completed) ──
1191
+ if [[ "$ENABLE_DEPLOY" == "1" ]]; then
1192
+ local incomplete_count
1193
+ incomplete_count=$({ python3 -c "
1194
+ import json, sys
1195
+ with open(sys.argv[1]) as f:
1196
+ data = json.load(f)
1197
+ bad = [f for f in data.get('features', [])
1198
+ if f.get('status') not in ('completed', 'skipped')]
1199
+ for f in bad:
1200
+ print(f\" {f['id']}: {f.get('status', 'unknown')} — {f.get('title', '')}\")
1201
+ print(len(bad))
1202
+ " "$feature_list" 2>/dev/null || echo "0"; } | tee /dev/stderr | tail -1)
1203
+
1204
+ if [[ "$incomplete_count" -gt 0 ]]; then
1205
+ echo ""
1206
+ log_warn "DEPLOY BLOCKED: $incomplete_count task(s) not completed successfully."
1207
+ log_warn "Fix failed tasks and re-run, or manually run /prizmkit-deploy."
1208
+ else
1209
+ echo ""
1210
+ log_info "All tasks completed — starting deploy session..."
1211
+ log_info "ENABLE_DEPLOY=1"
1212
+
1213
+ local deploy_session_id="deploy-$(date +%Y%m%d%H%M%S)"
1214
+ local deploy_session_dir="$STATE_DIR/deploy/$deploy_session_id"
1215
+ mkdir -p "$deploy_session_dir/logs"
1216
+
1217
+ local deploy_prompt="$deploy_session_dir/bootstrap-prompt.md"
1218
+ local _deploy_branch _deploy_commit
1219
+ _deploy_branch=$(git -C "$_proj_root" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
1220
+ _deploy_commit=$(git -C "$_proj_root" rev-parse --short HEAD 2>/dev/null || echo "unknown")
1221
+ cat > "$deploy_prompt" << DEPLOY_PROMPT_EOF
1222
+ ## Deploy
1223
+
1224
+ All features in the pipeline completed successfully.
1225
+
1226
+ - Branch: $_deploy_branch
1227
+ - Commit: $_deploy_commit
1228
+
1229
+ Run /prizmkit-deploy to deploy the project. Read .prizmkit/deploy/deploy.config.json
1230
+ for deployment configuration. If no deploy config exists, guide the user through
1231
+ setting one up before deploying.
1232
+ DEPLOY_PROMPT_EOF
1233
+
1234
+ log_info "Deploy prompt: $deploy_prompt"
1235
+ log_info "Deploy log: $deploy_session_dir/logs/session.log"
1236
+
1237
+ case "$CLI_CMD" in
1238
+ *claude*)
1239
+ "$CLI_CMD" \
1240
+ -p "$(cat "$deploy_prompt")" \
1241
+ --dangerously-skip-permissions \
1242
+ > "$deploy_session_dir/logs/session.log" 2>&1
1243
+ ;;
1244
+ *)
1245
+ "$CLI_CMD" \
1246
+ --print \
1247
+ -y \
1248
+ < "$deploy_prompt" \
1249
+ > "$deploy_session_dir/logs/session.log" 2>&1
1250
+ ;;
1251
+ esac
1252
+ local deploy_exit=$?
1253
+
1254
+ if [[ $deploy_exit -eq 0 ]]; then
1255
+ log_success "Deploy session completed (exit 0)"
1256
+ else
1257
+ log_warn "Deploy session exited with code $deploy_exit"
1258
+ log_warn "Review log: $deploy_session_dir/logs/session.log"
1259
+ fi
1260
+ fi
1261
+ fi
1262
+
1189
1263
  break
1190
1264
  fi
1191
1265
 
@@ -52,6 +52,7 @@ DEV_BRANCH=${DEV_BRANCH:-""}
52
52
  AUTO_PUSH=${AUTO_PUSH:-0}
53
53
  STOP_ON_FAILURE=${STOP_ON_FAILURE:-0}
54
54
  STRICT_BEHAVIOR_CHECK=${STRICT_BEHAVIOR_CHECK:-1}
55
+ ENABLE_DEPLOY=${ENABLE_DEPLOY:-0}
55
56
 
56
57
  # Source shared common helpers (CLI/platform detection + logs + deps)
57
58
  source "$SCRIPT_DIR/lib/common.sh"
@@ -990,6 +991,79 @@ main() {
990
991
  log_success " Total subagent calls: $total_subagent_calls"
991
992
  log_success "════════════════════════════════════════════════════"
992
993
 
994
+ # ── Deploy session (only if ENABLE_DEPLOY=1 and all refactors completed) ──
995
+ if [[ "$ENABLE_DEPLOY" == "1" ]]; then
996
+ local incomplete_count
997
+ incomplete_count=$({ python3 -c "
998
+ import json, sys
999
+ with open(sys.argv[1]) as f:
1000
+ data = json.load(f)
1001
+ bad = [r for r in data.get('refactors', [])
1002
+ if r.get('status') not in ('completed', 'skipped')]
1003
+ for r in bad:
1004
+ print(f\" {r['id']}: {r.get('status', 'unknown')} — {r.get('title', '')}\")
1005
+ print(len(bad))
1006
+ " "$refactor_list" 2>/dev/null || echo "0"; } | tee /dev/stderr | tail -1)
1007
+
1008
+ if [[ "$incomplete_count" -gt 0 ]]; then
1009
+ echo ""
1010
+ log_warn "DEPLOY BLOCKED: $incomplete_count refactor(s) not completed successfully."
1011
+ log_warn "Fix failed refactors and re-run, or manually run /prizmkit-deploy."
1012
+ else
1013
+ echo ""
1014
+ log_info "All refactors completed — starting deploy session..."
1015
+ log_info "ENABLE_DEPLOY=1"
1016
+
1017
+ local deploy_session_id="deploy-$(date +%Y%m%d%H%M%S)"
1018
+ local deploy_session_dir="$STATE_DIR/deploy/$deploy_session_id"
1019
+ mkdir -p "$deploy_session_dir/logs"
1020
+
1021
+ local deploy_prompt="$deploy_session_dir/bootstrap-prompt.md"
1022
+ local _deploy_branch _deploy_commit
1023
+ _deploy_branch=$(git -C "$_proj_root" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
1024
+ _deploy_commit=$(git -C "$_proj_root" rev-parse --short HEAD 2>/dev/null || echo "unknown")
1025
+ cat > "$deploy_prompt" << DEPLOY_PROMPT_EOF
1026
+ ## Deploy
1027
+
1028
+ All refactor tasks have been completed successfully.
1029
+
1030
+ - Branch: $_deploy_branch
1031
+ - Commit: $_deploy_commit
1032
+
1033
+ Run /prizmkit-deploy to deploy the project. Read .prizmkit/deploy/deploy.config.json
1034
+ for deployment configuration. If no deploy config exists, guide the user through
1035
+ setting one up before deploying.
1036
+ DEPLOY_PROMPT_EOF
1037
+
1038
+ log_info "Deploy prompt: $deploy_prompt"
1039
+ log_info "Deploy log: $deploy_session_dir/logs/session.log"
1040
+
1041
+ case "$CLI_CMD" in
1042
+ *claude*)
1043
+ "$CLI_CMD" \
1044
+ -p "$(cat "$deploy_prompt")" \
1045
+ --dangerously-skip-permissions \
1046
+ > "$deploy_session_dir/logs/session.log" 2>&1
1047
+ ;;
1048
+ *)
1049
+ "$CLI_CMD" \
1050
+ --print \
1051
+ -y \
1052
+ < "$deploy_prompt" \
1053
+ > "$deploy_session_dir/logs/session.log" 2>&1
1054
+ ;;
1055
+ esac
1056
+ local deploy_exit=$?
1057
+
1058
+ if [[ $deploy_exit -eq 0 ]]; then
1059
+ log_success "Deploy session completed (exit 0)"
1060
+ else
1061
+ log_warn "Deploy session exited with code $deploy_exit"
1062
+ log_warn "Review log: $deploy_session_dir/logs/session.log"
1063
+ fi
1064
+ fi
1065
+ fi
1066
+
993
1067
  break
994
1068
  fi
995
1069
 
@@ -625,7 +625,6 @@ SECTION_TO_SKILL = {
625
625
  "phase-implement": ("prizmkit-implement", "Implement + Test", []),
626
626
  "phase-review": ("prizmkit-code-review", "Code Review", []),
627
627
  "phase-browser": ("browser-verification", "Browser Verification", []),
628
- "phase-deploy": ("deploy-verification", "Deploy Verification", []),
629
628
  "phase-commit": None, # special: split into retrospective + committer
630
629
  }
631
630
 
@@ -1072,11 +1071,6 @@ def assemble_sections(pipeline_mode, sections_dir, init_done, is_resume,
1072
1071
  load_section(sections_dir,
1073
1072
  browser_section_file)))
1074
1073
 
1075
- # --- Deploy Verification ---
1076
- sections.append(("phase-deploy",
1077
- load_section(sections_dir,
1078
- "phase-deploy-verification.md")))
1079
-
1080
1074
  # --- Commit (tier-dependent) ---
1081
1075
  if pipeline_mode == "full":
1082
1076
  sections.append(("phase-commit",
@@ -342,29 +342,6 @@ Append results to `context-snapshot.md`:
342
342
  If verification fails, log the failure details but continue to commit. Failures do NOT block the commit, but you MUST attempt verification and MUST clean up the dev server.
343
343
  {{END_IF_BROWSER_INTERACTION}}
344
344
 
345
- ### Phase 3.8: Local Deploy Verification
346
-
347
- You just implemented this feature — you know the project's tech stack and build tools.
348
-
349
- 1. **Build**: Run the project's build/compile commands. If a required tool is missing, install it first.
350
- 2. **Fix**: If build fails with code errors (type errors, missing imports, config issues), fix them (max 2 rounds), then re-verify.
351
- 3. **Assess and record** — append to context-snapshot.md:
352
- - **ALL builds pass** → `## Deploy Verification: PASS` — proceed to commit
353
- - **Some builds fail with fixable errors** → fix and re-verify (already handled in step 2)
354
- - **Cannot build locally** (missing system-level deps you cannot install) → Record: `## Deploy Verification: PARTIAL — missing system deps (see below)`
355
-
356
- Deploy verification does NOT block the commit, but you MUST attempt it.
357
-
358
- **Step 4 — Smoke test** (only if build passed and project can be started):
359
- 1. Start the project locally (e.g., `make dev`, `npm start`, `go run .`, etc.)
360
- 2. Verify basic functionality: hit key endpoints, check health routes, confirm the UI loads
361
- 3. Stop the server process you started — do NOT leave it running
362
- 4. Record smoke test results in `## Deploy Verification` section
363
-
364
- If the project cannot be started locally (e.g., requires external services, databases, credentials), skip the smoke test and note why.
365
-
366
- **Deploy documentation update** — Run `/prizmkit-deploy` ONLY if this feature introduced new infrastructure or deployment-affecting changes (new database, cache, message queue, new env vars, new build steps, changed ports/protocols). If none apply, skip `/prizmkit-deploy`.
367
-
368
345
  ### Phase 4: Architecture Sync & Commit (SINGLE COMMIT)
369
346
 
370
347
  **4a.** Run `/prizmkit-retrospective` — maintains `.prizm-docs/` (architecture index):
@@ -435,29 +435,6 @@ Append results to `context-snapshot.md`:
435
435
  If verification fails, log the failure details but continue to commit. Failures do NOT block the commit, but you MUST attempt verification and MUST clean up the dev server.
436
436
  {{END_IF_BROWSER_INTERACTION}}
437
437
 
438
- ### Phase 5.8: Local Deploy Verification
439
-
440
- You just implemented this feature — you know the project's tech stack and build tools.
441
-
442
- 1. **Build**: Run the project's build/compile commands. If a required tool is missing, install it first.
443
- 2. **Fix**: If build fails with code errors (type errors, missing imports, config issues), fix them (max 2 rounds), then re-verify.
444
- 3. **Assess and record** — append to context-snapshot.md:
445
- - **ALL builds pass** → `## Deploy Verification: PASS` — proceed to commit
446
- - **Some builds fail with fixable errors** → fix and re-verify (already handled in step 2)
447
- - **Cannot build locally** (missing system-level deps you cannot install) → Record: `## Deploy Verification: PARTIAL — missing system deps (see below)`
448
-
449
- Deploy verification does NOT block the commit, but you MUST attempt it.
450
-
451
- **Step 4 — Smoke test** (only if build passed and project can be started):
452
- 1. Start the project locally (e.g., `make dev`, `npm start`, `go run .`, etc.)
453
- 2. Verify basic functionality: hit key endpoints, check health routes, confirm the UI loads
454
- 3. Stop the server process you started — do NOT leave it running
455
- 4. Record smoke test results in `## Deploy Verification` section
456
-
457
- If the project cannot be started locally (e.g., requires external services, databases, credentials), skip the smoke test and note why.
458
-
459
- **Deploy documentation update** — Run `/prizmkit-deploy` ONLY if this feature introduced new infrastructure or deployment-affecting changes (new database, cache, message queue, new env vars, new build steps, changed ports/protocols). If none apply, skip `/prizmkit-deploy`.
460
-
461
438
  ### Phase 6: Architecture Sync & Commit (SINGLE COMMIT)
462
439
 
463
440
  **6a.** Run `/prizmkit-retrospective` — maintains `.prizm-docs/` (architecture index):
@@ -500,29 +500,6 @@ Append results to `context-snapshot.md`:
500
500
  If verification fails, log the failure details but continue to commit. Failures do NOT block the commit, but you MUST attempt verification and MUST clean up the dev server.
501
501
  {{END_IF_BROWSER_INTERACTION}}
502
502
 
503
- ### Phase 5.8: Local Deploy Verification
504
-
505
- You just implemented this feature — you know the project's tech stack and build tools.
506
-
507
- 1. **Build**: Run the project's build/compile commands. If a required tool is missing, install it first.
508
- 2. **Fix**: If build fails with code errors (type errors, missing imports, config issues), fix them (max 2 rounds), then re-verify.
509
- 3. **Assess and record** — append to context-snapshot.md:
510
- - **ALL builds pass** → `## Deploy Verification: PASS` — proceed to commit
511
- - **Some builds fail with fixable errors** → fix and re-verify (already handled in step 2)
512
- - **Cannot build locally** (missing system-level deps you cannot install) → Record: `## Deploy Verification: PARTIAL — missing system deps (see below)`
513
-
514
- Deploy verification does NOT block the commit, but you MUST attempt it.
515
-
516
- **Step 4 — Smoke test** (only if build passed and project can be started):
517
- 1. Start the project locally (e.g., `make dev`, `npm start`, `go run .`, etc.)
518
- 2. Verify basic functionality: hit key endpoints, check health routes, confirm the UI loads
519
- 3. Stop the server process you started — do NOT leave it running
520
- 4. Record smoke test results in `## Deploy Verification` section
521
-
522
- If the project cannot be started locally (e.g., requires external services, databases, credentials), skip the smoke test and note why.
523
-
524
- **Deploy documentation update** — Run `/prizmkit-deploy` ONLY if this feature introduced new infrastructure or deployment-affecting changes (new database, cache, message queue, new env vars, new build steps, changed ports/protocols). If none apply, skip `/prizmkit-deploy`.
525
-
526
503
  ### Phase 6: Retrospective & Commit (SINGLE COMMIT) — DO NOT SKIP
527
504
 
528
505
  **Bug Fix Documentation Policy**:
@@ -0,0 +1,223 @@
1
+ #!/usr/bin/env bash
2
+ # Test deploy safety check logic across different task status scenarios
3
+ # Run: bash dev-pipeline/tests/test-deploy-safety.sh
4
+ set -euo pipefail
5
+
6
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
7
+ REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
8
+
9
+ RED='\033[0;31m'
10
+ GREEN='\033[0;32m'
11
+ YELLOW='\033[1;33m'
12
+ NC='\033[0m'
13
+
14
+ PASS=0
15
+ FAIL=0
16
+ TOTAL=0
17
+
18
+ pass() { echo -e " ${GREEN}PASS${NC} $1"; PASS=$((PASS + 1)); TOTAL=$((TOTAL + 1)); }
19
+ fail() { echo -e " ${RED}FAIL${NC} $1 — $2"; FAIL=$((FAIL + 1)); TOTAL=$((TOTAL + 1)); }
20
+
21
+ echo "================================="
22
+ echo " Deploy Safety Check Tests"
23
+ echo "================================="
24
+ echo ""
25
+
26
+ # --- Test 1: All tasks completed -> deploy should proceed ---
27
+ echo "[Test 1] All 'completed': incomplete_count should be 0"
28
+ cat > /tmp/test-deploy-all-completed.json << 'JSON'
29
+ {"features": [{"id": "F-A", "status": "completed"}, {"id": "F-B", "status": "completed"}]}
30
+ JSON
31
+ count=$(python3 -c "
32
+ import json
33
+ with open('/tmp/test-deploy-all-completed.json') as f:
34
+ data = json.load(f)
35
+ bad = [f for f in data.get('features', [])
36
+ if f.get('status') not in ('completed', 'skipped')]
37
+ print(len(bad))
38
+ ")
39
+ if [[ "$count" == "0" ]]; then
40
+ pass "incomplete_count=0, deploy proceeds"
41
+ else
42
+ fail "incomplete_count=$count, expected 0"
43
+ fi
44
+
45
+ # --- Test 2: One failed, one completed -> deploy blocked ---
46
+ echo "[Test 2] Mixed 'completed' + 'failed': incomplete_count should be 1"
47
+ cat > /tmp/test-deploy-mixed.json << 'JSON'
48
+ {"features": [{"id": "F-A", "status": "completed"}, {"id": "F-B", "status": "failed"}]}
49
+ JSON
50
+ count=$(python3 -c "
51
+ import json
52
+ with open('/tmp/test-deploy-mixed.json') as f:
53
+ data = json.load(f)
54
+ bad = [f for f in data.get('features', [])
55
+ if f.get('status') not in ('completed', 'skipped')]
56
+ print(len(bad))
57
+ ")
58
+ if [[ "$count" == "1" ]]; then
59
+ pass "incomplete_count=1, deploy blocked"
60
+ else
61
+ fail "incomplete_count=$count, expected 1"
62
+ fi
63
+
64
+ # --- Test 3: All skipped -> deploy proceeds (skipped is non-blocking) ---
65
+ echo "[Test 3] All 'skipped': incomplete_count should be 0"
66
+ cat > /tmp/test-deploy-all-skipped.json << 'JSON'
67
+ {"features": [{"id": "F-A", "status": "skipped"}, {"id": "F-B", "status": "skipped"}]}
68
+ JSON
69
+ count=$(python3 -c "
70
+ import json
71
+ with open('/tmp/test-deploy-all-skipped.json') as f:
72
+ data = json.load(f)
73
+ bad = [f for f in data.get('features', [])
74
+ if f.get('status') not in ('completed', 'skipped')]
75
+ print(len(bad))
76
+ ")
77
+ if [[ "$count" == "0" ]]; then
78
+ pass "incomplete_count=0, deploy proceeds (skipped is non-blocking)"
79
+ else
80
+ fail "incomplete_count=$count, expected 0"
81
+ fi
82
+
83
+ # --- Test 4: Timed-out status -> deploy blocked ---
84
+ echo "[Test 4] 'timed_out' status: incomplete_count should be 1"
85
+ cat > /tmp/test-deploy-timeout.json << 'JSON'
86
+ {"features": [{"id": "F-A", "status": "completed"}, {"id": "F-B", "status": "timed_out"}]}
87
+ JSON
88
+ count=$(python3 -c "
89
+ import json
90
+ with open('/tmp/test-deploy-timeout.json') as f:
91
+ data = json.load(f)
92
+ bad = [f for f in data.get('features', [])
93
+ if f.get('status') not in ('completed', 'skipped')]
94
+ print(len(bad))
95
+ ")
96
+ if [[ "$count" == "1" ]]; then
97
+ pass "incomplete_count=1, deploy blocked"
98
+ else
99
+ fail "incomplete_count=$count, expected 1"
100
+ fi
101
+
102
+ # --- Test 5: tee /dev/stderr | tail -1 pattern extracts only count ---
103
+ echo "[Test 5] Multi-line output extraction: only last line (integer) captured"
104
+ cat > /tmp/test-deploy-tee.json << 'JSON'
105
+ {"features": [{"id": "F-001", "status": "failed", "title": "Broken feature"}, {"id": "F-002", "status": "crashed", "title": "Also broken"}]}
106
+ JSON
107
+ result=$({ python3 -c "
108
+ import json
109
+ with open('/tmp/test-deploy-tee.json') as f:
110
+ data = json.load(f)
111
+ bad = [f for f in data.get('features', [])
112
+ if f.get('status') not in ('completed', 'skipped')]
113
+ for f in bad:
114
+ print(f\" {f['id']}: {f.get('status', 'unknown')} — {f.get('title', '')}\")
115
+ print(len(bad))
116
+ " /tmp/test-deploy-tee.json 2>/dev/null || echo "0"; } | tail -1)
117
+ if [[ "$result" =~ ^[0-9]+$ ]]; then
118
+ pass "extracted count is integer: $result"
119
+ else
120
+ fail "extracted count is not a clean integer: '$result'"
121
+ fi
122
+
123
+ # --- Test 6: Empty feature list -> deploy proceeds ---
124
+ echo "[Test 6] Empty list: incomplete_count should be 0"
125
+ cat > /tmp/test-deploy-empty.json << 'JSON'
126
+ {"features": []}
127
+ JSON
128
+ count=$(python3 -c "
129
+ import json
130
+ with open('/tmp/test-deploy-empty.json') as f:
131
+ data = json.load(f)
132
+ bad = [f for f in data.get('features', [])
133
+ if f.get('status') not in ('completed', 'skipped')]
134
+ print(len(bad))
135
+ ")
136
+ if [[ "$count" == "0" ]]; then
137
+ pass "incomplete_count=0, deploy proceeds"
138
+ else
139
+ fail "incomplete_count=$count, expected 0"
140
+ fi
141
+
142
+ # --- Test 7: Bugfix variant with needs_info (non-blocking) ---
143
+ echo "[Test 7] Bugfix: 'needs_info' should NOT block deploy"
144
+ cat > /tmp/test-deploy-bugfix.json << 'JSON'
145
+ {"bugs": [{"id": "B-001", "status": "completed"}, {"id": "B-002", "status": "needs_info"}]}
146
+ JSON
147
+ count=$(python3 -c "
148
+ import json
149
+ with open('/tmp/test-deploy-bugfix.json') as f:
150
+ data = json.load(f)
151
+ bad = [b for b in data.get('bugs', [])
152
+ if b.get('status') not in ('completed', 'skipped', 'needs_info')]
153
+ print(len(bad))
154
+ ")
155
+ if [[ "$count" == "0" ]]; then
156
+ pass "incomplete_count=0, deploy proceeds (needs_info non-blocking)"
157
+ else
158
+ fail "incomplete_count=$count, expected 0"
159
+ fi
160
+
161
+ # --- Test 8: Refactor variant ---
162
+ echo "[Test 8] Refactor: completed + skipped -> deploy proceeds"
163
+ cat > /tmp/test-deploy-refactor.json << 'JSON'
164
+ {"refactors": [{"id": "R-001", "status": "completed"}, {"id": "R-002", "status": "skipped"}]}
165
+ JSON
166
+ count=$(python3 -c "
167
+ import json
168
+ with open('/tmp/test-deploy-refactor.json') as f:
169
+ data = json.load(f)
170
+ bad = [r for r in data.get('refactors', [])
171
+ if r.get('status') not in ('completed', 'skipped')]
172
+ print(len(bad))
173
+ ")
174
+ if [[ "$count" == "0" ]]; then
175
+ pass "incomplete_count=0, deploy proceeds"
176
+ else
177
+ fail "incomplete_count=$count, expected 0"
178
+ fi
179
+
180
+ # --- Test 9: Real feature-list.json ---
181
+ echo "[Test 9] Real feature-list.json: both completed -> deploy proceeds"
182
+ if [[ -f "$REPO_ROOT/.prizmkit/plans/feature-list.json" ]]; then
183
+ count=$(python3 -c "
184
+ import json
185
+ with open('$REPO_ROOT/.prizmkit/plans/feature-list.json') as f:
186
+ data = json.load(f)
187
+ bad = [f for f in data.get('features', [])
188
+ if f.get('status') not in ('completed', 'skipped')]
189
+ print(len(bad))
190
+ ")
191
+ if [[ "$count" == "0" ]]; then
192
+ pass "real list: incomplete_count=0"
193
+ else
194
+ fail "real list: incomplete_count=$count, expected 0"
195
+ fi
196
+ else
197
+ echo " ${YELLOW}SKIP${NC} No real feature-list.json found"
198
+ fi
199
+
200
+ # --- Test 10: ENABLE_DEPLOY=0 skips the entire block ---
201
+ echo "[Test 10] ENABLE_DEPLOY=0: deploy block should be skipped entirely"
202
+ ENABLE_DEPLOY=0
203
+ executed=false
204
+ if [[ "$ENABLE_DEPLOY" == "1" ]]; then
205
+ executed=true
206
+ fi
207
+ if [[ "$executed" == "false" ]]; then
208
+ pass "ENABLE_DEPLOY=0: deploy block skipped"
209
+ else
210
+ fail "ENABLE_DEPLOY=0: deploy block should NOT execute"
211
+ fi
212
+
213
+ # --- Cleanup ---
214
+ rm -f /tmp/test-deploy-*.json
215
+
216
+ echo ""
217
+ echo "================================="
218
+ echo " Results: $PASS passed, $FAIL failed ($TOTAL total)"
219
+ echo "================================="
220
+
221
+ if [[ $FAIL -gt 0 ]]; then
222
+ exit 1
223
+ fi
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.1.40",
2
+ "version": "1.1.41",
3
3
  "skills": {
4
4
  "prizm-kit": {
5
5
  "description": "Full-lifecycle dev toolkit. Covers spec-driven development, Prizm context docs, code quality, debugging, deployment, and knowledge management.",
@@ -58,10 +58,10 @@
58
58
  "hasScripts": false
59
59
  },
60
60
  "prizmkit-deploy": {
61
- "description": "Generate or update deployment documentation (.prizmkit/deploy.md) by scanning project state and deploy strategy. On-demand skill.",
61
+ "description": "Universal deployment gateway: auto-discovers project type and target, routes to SSH automation (PM2 + Nginx + blue/green), guided cloud/Docker deployment, or documentation fallback. Also operates existing deployments (status/logs/restart/rollback).",
62
62
  "tier": "1",
63
63
  "category": "prizmkit-skill",
64
- "hasAssets": true,
64
+ "hasAssets": false,
65
65
  "hasScripts": false
66
66
  },
67
67
  "feature-workflow": {
@@ -37,7 +37,6 @@ If you believe the task is better suited for a different workflow, you MUST:
37
37
  1. `.prizmkit/plans/project-brief.md` (`.prizmkit/plans/` — accumulated project context brief)
38
38
  2. Project conventions and architecture decisions appended to `CLAUDE.md` / `CODEBUDDY.md` (with user consent)
39
39
  3. Infrastructure configuration (database conventions + deployment config) appended to `CLAUDE.md` / `CODEBUDDY.md` `### Infrastructure` section
40
- 4. `.prizmkit/deploy.md` — deployment documentation (created or updated with infrastructure config)
41
40
 
42
41
  **After planning is complete**, you MUST:
43
42
  1. Present the summary of captured project-level context (vision, conventions, architecture decisions, project brief)
@@ -199,7 +198,6 @@ Do NOT use this skill when:
199
198
  #### Deployment Credentials Reference
200
199
  - [platform]: [token/auth method description]
201
200
  ```
202
- - Update `.prizmkit/deploy.md` if it exists — append deployment details to relevant sections (Prerequisites, Production Deployment, Environment Variables). If it does not exist, create it from the `prizmkit-deploy` template with known information filled in.
203
201
  - Items still marked "Skip — decide later" remain as `<!-- [topic]: deferred -->` in CLAUDE.md for `prizmkit-deploy` to pick up later.
204
202
 
205
203
  4. **Project brief accumulation** — throughout all interactive phases:
@@ -443,7 +441,6 @@ After all checkpoints pass, present a summary and end the session:
443
441
  - Infrastructure config → `CLAUDE.md` / `CODEBUDDY.md` `### Infrastructure` (database conventions + deployment config)
444
442
  - Tech stack → `.prizmkit/config.json`
445
443
  - Architecture decisions (if any) → `CLAUDE.md` / `CODEBUDDY.md` `### Architecture Decisions`
446
- - Deployment docs → `.prizmkit/deploy.md` (if created/updated)
447
444
  - Project brief → `.prizmkit/plans/project-brief.md`
448
445
 
449
446
  2. **Suggest possible next steps** (as text, NOT auto-invoked):