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.
- package/bundled/VERSION.json +3 -3
- package/bundled/dev-pipeline/SCHEMA_ANALYSIS.md +1 -1
- package/bundled/dev-pipeline/run-bugfix.sh +74 -0
- package/bundled/dev-pipeline/run-feature.sh +74 -0
- package/bundled/dev-pipeline/run-refactor.sh +74 -0
- package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +0 -6
- package/bundled/dev-pipeline/templates/bootstrap-tier1.md +0 -23
- package/bundled/dev-pipeline/templates/bootstrap-tier2.md +0 -23
- package/bundled/dev-pipeline/templates/bootstrap-tier3.md +0 -23
- package/bundled/dev-pipeline/tests/test-deploy-safety.sh +223 -0
- package/bundled/skills/_metadata.json +3 -3
- package/bundled/skills/app-planner/SKILL.md +0 -3
- package/bundled/skills/bugfix-pipeline-launcher/SKILL.md +8 -2
- package/bundled/skills/feature-pipeline-launcher/SKILL.md +8 -2
- package/bundled/skills/prizmkit-committer/SKILL.md +0 -1
- package/bundled/skills/prizmkit-deploy/SKILL.md +491 -209
- package/bundled/skills/prizmkit-deploy/references/cloud-platform-deploy.md +93 -0
- package/bundled/skills/prizmkit-deploy/references/deploy-config-schema.md +147 -0
- package/bundled/skills/prizmkit-deploy/references/deploy-history-schema.md +62 -0
- package/bundled/skills/prizmkit-deploy/references/docker-deploy.md +31 -0
- package/bundled/skills/prizmkit-deploy/references/nginx-blue-green.md +59 -0
- package/bundled/skills/prizmkit-init/SKILL.md +0 -2
- package/bundled/skills/prizmkit-plan/SKILL.md +0 -3
- package/bundled/skills/refactor-pipeline-launcher/SKILL.md +8 -2
- package/package.json +1 -1
- package/bundled/dev-pipeline/templates/sections/phase-deploy-verification.md +0 -31
- package/bundled/skills/prizmkit-deploy/assets/deploy-template.md +0 -187
package/bundled/VERSION.json
CHANGED
|
@@ -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.
|
|
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": "
|
|
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":
|
|
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):
|