prizmkit 1.1.1 → 1.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.
- package/bundled/VERSION.json +3 -3
- package/bundled/adapters/claude/agent-adapter.js +18 -0
- package/bundled/adapters/claude/command-adapter.js +1 -27
- package/bundled/agents/prizm-dev-team-critic.md +2 -0
- package/bundled/agents/prizm-dev-team-dev.md +2 -0
- package/bundled/agents/prizm-dev-team-reviewer.md +2 -0
- package/bundled/dev-pipeline/README.md +63 -63
- package/bundled/dev-pipeline/assets/feature-list-example.json +1 -1
- package/bundled/dev-pipeline/assets/prizm-dev-team-integration.md +1 -1
- package/bundled/dev-pipeline/{launch-daemon.sh → launch-feature-daemon.sh} +33 -33
- package/bundled/dev-pipeline/launch-refactor-daemon.sh +454 -0
- package/bundled/dev-pipeline/lib/branch.sh +1 -1
- package/bundled/dev-pipeline/reset-feature.sh +3 -3
- package/bundled/dev-pipeline/reset-refactor.sh +312 -0
- package/bundled/dev-pipeline/{retry-bug.sh → retry-bugfix.sh} +47 -59
- package/bundled/dev-pipeline/retry-feature.sh +41 -54
- package/bundled/dev-pipeline/retry-refactor.sh +358 -0
- package/bundled/dev-pipeline/run-bugfix.sh +41 -0
- package/bundled/dev-pipeline/{run.sh → run-feature.sh} +64 -31
- package/bundled/dev-pipeline/run-refactor.sh +787 -0
- package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +398 -10
- package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +124 -0
- package/bundled/dev-pipeline/scripts/generate-refactor-prompt.py +419 -0
- package/bundled/dev-pipeline/scripts/init-refactor-pipeline.py +393 -0
- package/bundled/dev-pipeline/scripts/update-refactor-status.py +726 -0
- package/bundled/dev-pipeline/templates/agent-prompts/critic-code-challenge.md +13 -0
- package/bundled/dev-pipeline/templates/agent-prompts/critic-plan-challenge.md +7 -0
- package/bundled/dev-pipeline/templates/agent-prompts/dev-fix.md +7 -0
- package/bundled/dev-pipeline/templates/agent-prompts/dev-implement.md +27 -0
- package/bundled/dev-pipeline/templates/agent-prompts/dev-resume.md +5 -0
- package/bundled/dev-pipeline/templates/agent-prompts/reviewer-analyze.md +5 -0
- package/bundled/dev-pipeline/templates/agent-prompts/reviewer-review.md +12 -0
- package/bundled/dev-pipeline/templates/bootstrap-tier1.md +33 -2
- package/bundled/dev-pipeline/templates/bootstrap-tier2.md +13 -9
- package/bundled/dev-pipeline/templates/bootstrap-tier3.md +16 -12
- package/bundled/dev-pipeline/templates/bugfix-bootstrap-prompt.md +22 -4
- package/bundled/dev-pipeline/templates/feature-list-schema.json +1 -1
- package/bundled/dev-pipeline/templates/refactor-list-schema.json +159 -0
- package/bundled/dev-pipeline/templates/sections/ac-verification-checklist.md +13 -0
- package/bundled/dev-pipeline/templates/sections/checkpoint-system.md +36 -0
- package/bundled/dev-pipeline/templates/sections/failure-log-check.md +2 -1
- package/bundled/dev-pipeline/templates/sections/feature-context.md +1 -1
- package/bundled/dev-pipeline/templates/sections/phase-analyze-agent.md +11 -7
- package/bundled/dev-pipeline/templates/sections/phase-analyze-full.md +11 -7
- package/bundled/dev-pipeline/templates/sections/phase-browser-verification.md +5 -1
- package/bundled/dev-pipeline/templates/sections/phase-commit-full.md +3 -0
- package/bundled/dev-pipeline/templates/sections/phase-commit.md +3 -0
- package/bundled/dev-pipeline/templates/sections/phase-context-snapshot-agent-suffix.md +3 -0
- package/bundled/dev-pipeline/templates/sections/phase-context-snapshot-lite-suffix.md +3 -0
- package/bundled/dev-pipeline/templates/sections/phase-critic-code.md +11 -10
- package/bundled/dev-pipeline/templates/sections/phase-critic-plan-full.md +12 -10
- package/bundled/dev-pipeline/templates/sections/phase-critic-plan.md +11 -9
- package/bundled/dev-pipeline/templates/sections/phase-deploy-verification.md +3 -0
- package/bundled/dev-pipeline/templates/sections/phase-implement-agent.md +10 -10
- package/bundled/dev-pipeline/templates/sections/phase-implement-full.md +12 -16
- package/bundled/dev-pipeline/templates/sections/phase-implement-lite.md +3 -0
- package/bundled/dev-pipeline/templates/sections/phase-plan-agent.md +3 -0
- package/bundled/dev-pipeline/templates/sections/phase-plan-lite.md +3 -0
- package/bundled/dev-pipeline/templates/sections/phase-review-agent.md +11 -13
- package/bundled/dev-pipeline/templates/sections/phase-review-full.md +12 -20
- package/bundled/dev-pipeline/templates/sections/phase-specify-plan-full.md +3 -0
- package/bundled/dev-pipeline/templates/sections/phase0-init.md +3 -0
- package/bundled/dev-pipeline/templates/sections/phase0-test-baseline.md +3 -0
- package/bundled/dev-pipeline/templates/sections/resume-header.md +4 -1
- package/bundled/dev-pipeline/templates/sections/test-failure-recovery.md +75 -0
- package/bundled/rules/prizm/prizm-commit-workflow.md +1 -0
- package/bundled/rules/prizm/prizm-documentation.md +15 -15
- package/bundled/rules/prizm/prizm-progressive-loading.md +2 -1
- package/bundled/skills/_metadata.json +33 -6
- package/bundled/skills/app-planner/SKILL.md +105 -320
- package/bundled/skills/app-planner/assets/app-design-guide.md +101 -0
- package/bundled/skills/app-planner/references/frontend-design-guide.md +1 -1
- package/bundled/skills/app-planner/references/project-brief-guide.md +49 -80
- package/bundled/skills/bug-fix-workflow/SKILL.md +2 -2
- package/bundled/skills/bug-planner/SKILL.md +68 -5
- package/bundled/skills/bug-planner/scripts/validate-bug-list.py +3 -2
- package/bundled/skills/bugfix-pipeline-launcher/SKILL.md +19 -5
- package/bundled/skills/{dev-pipeline-launcher → feature-pipeline-launcher}/SKILL.md +32 -32
- package/bundled/skills/feature-planner/SKILL.md +337 -0
- package/bundled/skills/{app-planner → feature-planner}/assets/evaluation-guide.md +4 -4
- package/bundled/skills/{app-planner → feature-planner}/assets/planning-guide.md +3 -171
- package/bundled/skills/{app-planner → feature-planner}/references/browser-interaction.md +6 -5
- package/bundled/skills/feature-planner/references/decomposition-patterns.md +75 -0
- package/bundled/skills/{app-planner → feature-planner}/references/error-recovery.md +8 -8
- package/bundled/skills/{app-planner → feature-planner}/references/incremental-feature-planning.md +1 -1
- package/bundled/skills/{app-planner/references/new-app-planning.md → feature-planner/references/new-project-planning.md} +1 -1
- package/bundled/skills/{app-planner → feature-planner}/scripts/validate-and-generate.py +4 -4
- package/bundled/skills/feature-workflow/SKILL.md +23 -23
- package/bundled/skills/prizm-kit/SKILL.md +1 -3
- package/bundled/skills/prizm-kit/assets/project-memory-template.md +4 -2
- package/bundled/skills/prizmkit-analyze/SKILL.md +2 -5
- package/bundled/skills/prizmkit-code-review/SKILL.md +2 -2
- package/bundled/skills/prizmkit-committer/SKILL.md +32 -8
- package/bundled/skills/prizmkit-deploy/SKILL.md +1 -5
- package/bundled/skills/prizmkit-implement/SKILL.md +5 -51
- package/bundled/skills/prizmkit-init/SKILL.md +7 -78
- package/bundled/skills/prizmkit-plan/SKILL.md +1 -12
- package/bundled/skills/prizmkit-prizm-docs/SKILL.md +13 -28
- package/bundled/skills/prizmkit-prizm-docs/assets/PRIZM-SPEC.md +52 -1
- package/bundled/skills/prizmkit-retrospective/SKILL.md +12 -117
- package/bundled/skills/recovery-workflow/SKILL.md +168 -316
- package/bundled/skills/recovery-workflow/evals/evals.json +29 -13
- package/bundled/skills/recovery-workflow/scripts/detect-recovery-state.py +232 -274
- package/bundled/skills/refactor-pipeline-launcher/SKILL.md +352 -0
- package/bundled/skills/refactor-planner/SKILL.md +436 -0
- package/bundled/skills/refactor-planner/assets/planning-guide.md +292 -0
- package/bundled/skills/refactor-planner/references/behavior-preservation.md +301 -0
- package/bundled/skills/refactor-planner/references/refactor-scoping-guide.md +221 -0
- package/bundled/skills/refactor-planner/scripts/validate-and-generate-refactor.py +786 -0
- package/bundled/skills/refactor-workflow/SKILL.md +299 -319
- package/bundled/team/prizm-dev-team.json +1 -1
- package/package.json +1 -1
- package/src/clean.js +3 -3
- package/src/scaffold.js +6 -6
- package/bundled/skills/prizmkit-plan/assets/spec-template.md +0 -56
- package/bundled/skills/prizmkit-plan/references/clarify-guide.md +0 -67
- package/src/config.js +0 -504
- package/src/prompts.js +0 -210
- /package/bundled/skills/{dev-pipeline-launcher → feature-pipeline-launcher}/scripts/preflight-check.py +0 -0
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# ============================================================
|
|
5
|
+
# dev-pipeline/retry-refactor.sh - Retry a single failed refactor
|
|
6
|
+
#
|
|
7
|
+
# Runs exactly ONE AI CLI session for the specified refactor, then exits.
|
|
8
|
+
# Use this to manually retry a failed refactor without restarting
|
|
9
|
+
# the full refactor pipeline.
|
|
10
|
+
#
|
|
11
|
+
# Usage:
|
|
12
|
+
# ./retry-refactor.sh <refactor-id> [refactor-list.json]
|
|
13
|
+
#
|
|
14
|
+
# Examples:
|
|
15
|
+
# ./retry-refactor.sh R-001
|
|
16
|
+
# ./retry-refactor.sh R-001 refactor-list.json
|
|
17
|
+
# SESSION_TIMEOUT=3600 ./retry-refactor.sh R-001
|
|
18
|
+
# ============================================================
|
|
19
|
+
|
|
20
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
21
|
+
STATE_DIR="$SCRIPT_DIR/refactor-state"
|
|
22
|
+
SCRIPTS_DIR="$SCRIPT_DIR/scripts"
|
|
23
|
+
|
|
24
|
+
SESSION_TIMEOUT=${SESSION_TIMEOUT:-0}
|
|
25
|
+
HEARTBEAT_INTERVAL=${HEARTBEAT_INTERVAL:-30}
|
|
26
|
+
|
|
27
|
+
# Source shared common helpers (CLI/platform detection + logs + deps)
|
|
28
|
+
source "$SCRIPT_DIR/lib/common.sh"
|
|
29
|
+
prizm_detect_cli_and_platform
|
|
30
|
+
|
|
31
|
+
# Source shared heartbeat library
|
|
32
|
+
source "$SCRIPT_DIR/lib/heartbeat.sh"
|
|
33
|
+
|
|
34
|
+
# Detect stream-json support
|
|
35
|
+
detect_stream_json_support "$CLI_CMD"
|
|
36
|
+
|
|
37
|
+
# ============================================================
|
|
38
|
+
# Args
|
|
39
|
+
# ============================================================
|
|
40
|
+
|
|
41
|
+
if [[ $# -lt 1 ]]; then
|
|
42
|
+
echo "Usage: $0 <refactor-id> [refactor-list.json]"
|
|
43
|
+
echo ""
|
|
44
|
+
echo " refactor-id Refactor to retry (e.g. R-001)"
|
|
45
|
+
echo " refactor-list.json Path to refactor list (default: refactor-list.json)"
|
|
46
|
+
echo ""
|
|
47
|
+
echo "Environment Variables:"
|
|
48
|
+
echo " SESSION_TIMEOUT Timeout in seconds (default: 0 = no limit)"
|
|
49
|
+
echo " HEARTBEAT_INTERVAL Heartbeat interval in seconds (default: 30)"
|
|
50
|
+
exit 1
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
REFACTOR_ID="$1"
|
|
54
|
+
REFACTOR_LIST="${2:-refactor-list.json}"
|
|
55
|
+
|
|
56
|
+
if [[ ! "$REFACTOR_LIST" = /* ]]; then
|
|
57
|
+
REFACTOR_LIST="$(pwd)/$REFACTOR_LIST"
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
# ============================================================
|
|
61
|
+
# Validation
|
|
62
|
+
# ============================================================
|
|
63
|
+
|
|
64
|
+
if [[ ! -f "$REFACTOR_LIST" ]]; then
|
|
65
|
+
log_error "Refactor list not found: $REFACTOR_LIST"
|
|
66
|
+
exit 1
|
|
67
|
+
fi
|
|
68
|
+
|
|
69
|
+
if ! command -v jq &>/dev/null; then
|
|
70
|
+
log_error "jq is required. Install with: brew install jq"
|
|
71
|
+
exit 1
|
|
72
|
+
fi
|
|
73
|
+
|
|
74
|
+
# Initialize state if needed
|
|
75
|
+
if [[ ! -f "$STATE_DIR/pipeline.json" ]]; then
|
|
76
|
+
log_info "Initializing refactor pipeline state..."
|
|
77
|
+
python3 "$SCRIPTS_DIR/init-refactor-pipeline.py" \
|
|
78
|
+
--refactor-list "$REFACTOR_LIST" \
|
|
79
|
+
--state-dir "$STATE_DIR" >/dev/null 2>&1 || {
|
|
80
|
+
log_error "Failed to initialize refactor pipeline state"
|
|
81
|
+
exit 1
|
|
82
|
+
}
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
# Verify refactor exists
|
|
86
|
+
REFACTOR_TITLE=$(python3 -c "
|
|
87
|
+
import json, sys
|
|
88
|
+
with open('$REFACTOR_LIST') as f:
|
|
89
|
+
data = json.load(f)
|
|
90
|
+
for item in data.get('refactors', []):
|
|
91
|
+
if item.get('id') == '$REFACTOR_ID':
|
|
92
|
+
print(item.get('title', ''))
|
|
93
|
+
sys.exit(0)
|
|
94
|
+
sys.exit(1)
|
|
95
|
+
" 2>/dev/null) || {
|
|
96
|
+
log_error "Refactor $REFACTOR_ID not found in $REFACTOR_LIST"
|
|
97
|
+
exit 1
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
REFACTOR_COMPLEXITY=$(python3 -c "
|
|
101
|
+
import json, sys
|
|
102
|
+
with open('$REFACTOR_LIST') as f:
|
|
103
|
+
data = json.load(f)
|
|
104
|
+
for item in data.get('refactors', []):
|
|
105
|
+
if item.get('id') == '$REFACTOR_ID':
|
|
106
|
+
print(item.get('complexity', 'medium'))
|
|
107
|
+
sys.exit(0)
|
|
108
|
+
sys.exit(1)
|
|
109
|
+
" 2>/dev/null) || REFACTOR_COMPLEXITY="medium"
|
|
110
|
+
|
|
111
|
+
# ============================================================
|
|
112
|
+
# Clean refactor artifacts + reset status for a full restart
|
|
113
|
+
# ============================================================
|
|
114
|
+
|
|
115
|
+
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
116
|
+
ORIGINAL_BRANCH=$(git -C "$PROJECT_ROOT" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "main")
|
|
117
|
+
|
|
118
|
+
log_info "Cleaning $REFACTOR_ID artifacts for full restart..."
|
|
119
|
+
python3 "$SCRIPTS_DIR/update-refactor-status.py" \
|
|
120
|
+
--refactor-list "$REFACTOR_LIST" \
|
|
121
|
+
--state-dir "$STATE_DIR" \
|
|
122
|
+
--refactor-id "$REFACTOR_ID" \
|
|
123
|
+
--project-root "$PROJECT_ROOT" \
|
|
124
|
+
--action clean >/dev/null 2>&1 || {
|
|
125
|
+
log_warn "Failed to clean refactor artifacts (continuing with fresh session only)"
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
# ============================================================
|
|
129
|
+
# Generate bootstrap prompt
|
|
130
|
+
# ============================================================
|
|
131
|
+
|
|
132
|
+
RUN_ID=$(jq -r '.run_id' "$STATE_DIR/pipeline.json")
|
|
133
|
+
SESSION_ID="${REFACTOR_ID}-$(date +%Y%m%d%H%M%S)"
|
|
134
|
+
SESSION_DIR="$STATE_DIR/refactors/$REFACTOR_ID/sessions/$SESSION_ID"
|
|
135
|
+
mkdir -p "$SESSION_DIR/logs"
|
|
136
|
+
|
|
137
|
+
BOOTSTRAP_PROMPT="$SESSION_DIR/bootstrap-prompt.md"
|
|
138
|
+
|
|
139
|
+
log_info "Generating refactor bootstrap prompt..."
|
|
140
|
+
python3 "$SCRIPTS_DIR/generate-refactor-prompt.py" \
|
|
141
|
+
--refactor-list "$REFACTOR_LIST" \
|
|
142
|
+
--refactor-id "$REFACTOR_ID" \
|
|
143
|
+
--session-id "$SESSION_ID" \
|
|
144
|
+
--run-id "$RUN_ID" \
|
|
145
|
+
--retry-count 0 \
|
|
146
|
+
--resume-phase "null" \
|
|
147
|
+
--state-dir "$STATE_DIR" \
|
|
148
|
+
--output "$BOOTSTRAP_PROMPT" >/dev/null 2>&1
|
|
149
|
+
|
|
150
|
+
# ============================================================
|
|
151
|
+
# Run single AI CLI session
|
|
152
|
+
# ============================================================
|
|
153
|
+
|
|
154
|
+
echo ""
|
|
155
|
+
echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
|
|
156
|
+
echo -e "${BOLD} Retry Refactor: $REFACTOR_ID — $REFACTOR_TITLE${NC}"
|
|
157
|
+
echo -e "${BOLD} Complexity: $REFACTOR_COMPLEXITY${NC}"
|
|
158
|
+
echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
|
|
159
|
+
log_info "CLI: $CLI_CMD (platform: $PLATFORM)"
|
|
160
|
+
if [[ -n "${MODEL:-}" ]]; then
|
|
161
|
+
log_info "Model: $MODEL"
|
|
162
|
+
else
|
|
163
|
+
log_info "Model: (CLI default)"
|
|
164
|
+
fi
|
|
165
|
+
if [[ $SESSION_TIMEOUT -gt 0 ]]; then
|
|
166
|
+
log_info "Session timeout: ${SESSION_TIMEOUT}s"
|
|
167
|
+
else
|
|
168
|
+
log_info "Session timeout: none"
|
|
169
|
+
fi
|
|
170
|
+
log_info "Prompt: $BOOTSTRAP_PROMPT"
|
|
171
|
+
log_info "Log: $SESSION_DIR/logs/session.log"
|
|
172
|
+
echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
|
|
173
|
+
echo ""
|
|
174
|
+
|
|
175
|
+
SESSION_LOG="$SESSION_DIR/logs/session.log"
|
|
176
|
+
PROGRESS_JSON="$SESSION_DIR/logs/progress.json"
|
|
177
|
+
|
|
178
|
+
# Build stream-json flag
|
|
179
|
+
STREAM_JSON_FLAG=""
|
|
180
|
+
if [[ "$USE_STREAM_JSON" == "true" ]]; then
|
|
181
|
+
STREAM_JSON_FLAG="--output-format stream-json"
|
|
182
|
+
fi
|
|
183
|
+
|
|
184
|
+
# claude-internal requires --verbose when using stream-json with -p/--print
|
|
185
|
+
VERBOSE_FLAG=""
|
|
186
|
+
if [[ "$USE_STREAM_JSON" == "true" ]]; then
|
|
187
|
+
VERBOSE_FLAG="--verbose"
|
|
188
|
+
fi
|
|
189
|
+
|
|
190
|
+
# Spawn AI CLI session
|
|
191
|
+
MODEL_FLAG=""
|
|
192
|
+
if [[ -n "${MODEL:-}" ]]; then
|
|
193
|
+
MODEL_FLAG="--model $MODEL"
|
|
194
|
+
fi
|
|
195
|
+
|
|
196
|
+
unset CLAUDECODE 2>/dev/null || true
|
|
197
|
+
|
|
198
|
+
case "$CLI_CMD" in
|
|
199
|
+
*claude*)
|
|
200
|
+
# Claude Code: prompt via -p argument, --dangerously-skip-permissions for auto-accept
|
|
201
|
+
"$CLI_CMD" \
|
|
202
|
+
-p "$(cat "$BOOTSTRAP_PROMPT")" \
|
|
203
|
+
--dangerously-skip-permissions \
|
|
204
|
+
$VERBOSE_FLAG \
|
|
205
|
+
$STREAM_JSON_FLAG \
|
|
206
|
+
$MODEL_FLAG \
|
|
207
|
+
> "$SESSION_LOG" 2>&1 &
|
|
208
|
+
;;
|
|
209
|
+
*)
|
|
210
|
+
# CodeBuddy (cbc) and others: prompt via stdin
|
|
211
|
+
"$CLI_CMD" \
|
|
212
|
+
--print \
|
|
213
|
+
-y \
|
|
214
|
+
$STREAM_JSON_FLAG \
|
|
215
|
+
$MODEL_FLAG \
|
|
216
|
+
< "$BOOTSTRAP_PROMPT" \
|
|
217
|
+
> "$SESSION_LOG" 2>&1 &
|
|
218
|
+
;;
|
|
219
|
+
esac
|
|
220
|
+
CLI_PID=$!
|
|
221
|
+
|
|
222
|
+
# Start progress parser (no-op if stream-json not supported)
|
|
223
|
+
start_progress_parser "$SESSION_LOG" "$PROGRESS_JSON" "$SCRIPTS_DIR"
|
|
224
|
+
PARSER_PID="${_PARSER_PID:-}"
|
|
225
|
+
|
|
226
|
+
# Timeout watchdog
|
|
227
|
+
WATCHER_PID=""
|
|
228
|
+
if [[ $SESSION_TIMEOUT -gt 0 ]]; then
|
|
229
|
+
( sleep "$SESSION_TIMEOUT" && kill -TERM "$CLI_PID" 2>/dev/null ) &
|
|
230
|
+
WATCHER_PID=$!
|
|
231
|
+
fi
|
|
232
|
+
|
|
233
|
+
# Heartbeat
|
|
234
|
+
start_heartbeat "$CLI_PID" "$SESSION_LOG" "$PROGRESS_JSON" "$HEARTBEAT_INTERVAL"
|
|
235
|
+
HEARTBEAT_PID="${_HEARTBEAT_PID:-}"
|
|
236
|
+
|
|
237
|
+
# Ctrl+C cleanup
|
|
238
|
+
cleanup() {
|
|
239
|
+
echo ""
|
|
240
|
+
log_warn "Interrupted. Killing session..."
|
|
241
|
+
kill "$CLI_PID" 2>/dev/null || true
|
|
242
|
+
[[ -n "$WATCHER_PID" ]] && kill "$WATCHER_PID" 2>/dev/null || true
|
|
243
|
+
stop_heartbeat "$HEARTBEAT_PID"
|
|
244
|
+
stop_progress_parser "$PARSER_PID"
|
|
245
|
+
wait "$CLI_PID" 2>/dev/null || true
|
|
246
|
+
[[ -n "$WATCHER_PID" ]] && wait "$WATCHER_PID" 2>/dev/null || true
|
|
247
|
+
log_info "Session log: $SESSION_LOG"
|
|
248
|
+
exit 130
|
|
249
|
+
}
|
|
250
|
+
trap cleanup SIGINT SIGTERM
|
|
251
|
+
|
|
252
|
+
# Wait
|
|
253
|
+
EXIT_CODE=0
|
|
254
|
+
if wait "$CLI_PID" 2>/dev/null; then
|
|
255
|
+
EXIT_CODE=0
|
|
256
|
+
else
|
|
257
|
+
EXIT_CODE=$?
|
|
258
|
+
fi
|
|
259
|
+
|
|
260
|
+
# Cleanup background processes
|
|
261
|
+
[[ -n "$WATCHER_PID" ]] && kill "$WATCHER_PID" 2>/dev/null || true
|
|
262
|
+
stop_heartbeat "$HEARTBEAT_PID"
|
|
263
|
+
stop_progress_parser "$PARSER_PID"
|
|
264
|
+
[[ -n "$WATCHER_PID" ]] && wait "$WATCHER_PID" 2>/dev/null || true
|
|
265
|
+
|
|
266
|
+
[[ $EXIT_CODE -eq 143 ]] && EXIT_CODE=124
|
|
267
|
+
|
|
268
|
+
# ============================================================
|
|
269
|
+
# Check result
|
|
270
|
+
# ============================================================
|
|
271
|
+
|
|
272
|
+
echo ""
|
|
273
|
+
if [[ -f "$SESSION_LOG" ]]; then
|
|
274
|
+
FINAL_LINES=$(wc -l < "$SESSION_LOG" 2>/dev/null | tr -d ' ')
|
|
275
|
+
FINAL_SIZE=$(wc -c < "$SESSION_LOG" 2>/dev/null | tr -d ' ')
|
|
276
|
+
log_info "Session log: $FINAL_LINES lines, $((FINAL_SIZE / 1024))KB"
|
|
277
|
+
fi
|
|
278
|
+
log_info "exit_code=$EXIT_CODE"
|
|
279
|
+
|
|
280
|
+
# ── Determine session outcome from observable signals ──────────────
|
|
281
|
+
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
282
|
+
DEFAULT_BRANCH="$ORIGINAL_BRANCH"
|
|
283
|
+
|
|
284
|
+
if [[ $EXIT_CODE -eq 124 ]]; then
|
|
285
|
+
log_warn "Session timed out after ${SESSION_TIMEOUT}s"
|
|
286
|
+
SESSION_STATUS="timed_out"
|
|
287
|
+
elif [[ $EXIT_CODE -ne 0 ]]; then
|
|
288
|
+
log_warn "Session exited with code $EXIT_CODE"
|
|
289
|
+
SESSION_STATUS="crashed"
|
|
290
|
+
else
|
|
291
|
+
# Exit code 0 — check if the session produced commits
|
|
292
|
+
HAS_COMMITS=""
|
|
293
|
+
if git -C "$PROJECT_ROOT" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
294
|
+
HAS_COMMITS=$(git -C "$PROJECT_ROOT" log "${DEFAULT_BRANCH}..HEAD" --oneline 2>/dev/null | head -1)
|
|
295
|
+
fi
|
|
296
|
+
|
|
297
|
+
if [[ -n "$HAS_COMMITS" ]]; then
|
|
298
|
+
SESSION_STATUS="success"
|
|
299
|
+
else
|
|
300
|
+
UNCOMMITTED=$(git -C "$PROJECT_ROOT" status --porcelain 2>/dev/null | head -1 || true)
|
|
301
|
+
if [[ -n "$UNCOMMITTED" ]]; then
|
|
302
|
+
log_warn "Session exited cleanly but produced no commits (uncommitted changes found) — auto-committing..."
|
|
303
|
+
git -C "$PROJECT_ROOT" add -A 2>/dev/null || true
|
|
304
|
+
if git -C "$PROJECT_ROOT" commit --no-verify -m "chore($REFACTOR_ID): auto-commit session work" 2>/dev/null; then
|
|
305
|
+
log_info "Auto-commit succeeded"
|
|
306
|
+
SESSION_STATUS="success"
|
|
307
|
+
else
|
|
308
|
+
log_warn "Auto-commit failed — no changes to commit"
|
|
309
|
+
SESSION_STATUS="crashed"
|
|
310
|
+
fi
|
|
311
|
+
else
|
|
312
|
+
log_warn "Session exited cleanly but produced no commits and no changes"
|
|
313
|
+
SESSION_STATUS="crashed"
|
|
314
|
+
fi
|
|
315
|
+
fi
|
|
316
|
+
fi
|
|
317
|
+
|
|
318
|
+
# ── Post-success validation ──────────────────────────────────────────
|
|
319
|
+
if [[ "$SESSION_STATUS" == "success" ]]; then
|
|
320
|
+
if git -C "$PROJECT_ROOT" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
321
|
+
DIRTY_FILES=$(git -C "$PROJECT_ROOT" status --porcelain 2>/dev/null || true)
|
|
322
|
+
if [[ -n "$DIRTY_FILES" ]]; then
|
|
323
|
+
log_info "Auto-committing remaining session artifacts..."
|
|
324
|
+
git -C "$PROJECT_ROOT" add -A 2>/dev/null || true
|
|
325
|
+
git -C "$PROJECT_ROOT" commit --no-verify --amend --no-edit -a 2>/dev/null \
|
|
326
|
+
|| git -C "$PROJECT_ROOT" commit --no-verify -m "chore($REFACTOR_ID): include remaining session artifacts" 2>/dev/null \
|
|
327
|
+
|| true
|
|
328
|
+
fi
|
|
329
|
+
fi
|
|
330
|
+
fi
|
|
331
|
+
|
|
332
|
+
# Update refactor status
|
|
333
|
+
python3 "$SCRIPTS_DIR/update-refactor-status.py" \
|
|
334
|
+
--refactor-list "$REFACTOR_LIST" \
|
|
335
|
+
--state-dir "$STATE_DIR" \
|
|
336
|
+
--refactor-id "$REFACTOR_ID" \
|
|
337
|
+
--session-status "$SESSION_STATUS" \
|
|
338
|
+
--session-id "$SESSION_ID" \
|
|
339
|
+
--max-retries 999 \
|
|
340
|
+
--action update >/dev/null 2>&1 || true
|
|
341
|
+
|
|
342
|
+
# Commit refactor-list.json status update (pipeline management commit)
|
|
343
|
+
if ! git -C "$PROJECT_ROOT" diff --quiet "$REFACTOR_LIST" 2>/dev/null; then
|
|
344
|
+
git -C "$PROJECT_ROOT" add "$REFACTOR_LIST"
|
|
345
|
+
git -C "$PROJECT_ROOT" commit --no-verify -m "chore($REFACTOR_ID): update refactor status" 2>/dev/null || true
|
|
346
|
+
fi
|
|
347
|
+
|
|
348
|
+
echo ""
|
|
349
|
+
if [[ "$SESSION_STATUS" == "success" ]]; then
|
|
350
|
+
log_success "════════════════════════════════════════════════════"
|
|
351
|
+
log_success " $REFACTOR_ID completed successfully!"
|
|
352
|
+
log_success "════════════════════════════════════════════════════"
|
|
353
|
+
else
|
|
354
|
+
log_error "════════════════════════════════════════════════════"
|
|
355
|
+
log_error " $REFACTOR_ID result: $SESSION_STATUS"
|
|
356
|
+
log_error " Review log: $SESSION_LOG"
|
|
357
|
+
log_error "════════════════════════════════════════════════════"
|
|
358
|
+
fi
|
|
@@ -224,6 +224,41 @@ spawn_and_wait_session() {
|
|
|
224
224
|
|
|
225
225
|
log_info "Session result: $session_status"
|
|
226
226
|
|
|
227
|
+
# Validate checkpoint completeness after successful session
|
|
228
|
+
if [[ "$session_status" == "success" ]]; then
|
|
229
|
+
local _ckpt_root
|
|
230
|
+
_ckpt_root="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
231
|
+
local checkpoint_file="$_ckpt_root/.prizmkit/bugfix/${bug_id}/workflow-checkpoint.json"
|
|
232
|
+
if [[ -f "$checkpoint_file" ]]; then
|
|
233
|
+
local checkpoint_result
|
|
234
|
+
checkpoint_result=$(python3 -c "
|
|
235
|
+
import json, sys
|
|
236
|
+
try:
|
|
237
|
+
with open(sys.argv[1]) as f:
|
|
238
|
+
data = json.load(f)
|
|
239
|
+
except json.JSONDecodeError as e:
|
|
240
|
+
print('CORRUPTED: {}'.format(e))
|
|
241
|
+
sys.exit(2)
|
|
242
|
+
incomplete = [s for s in data['steps'] if s['status'] not in ('completed', 'skipped')]
|
|
243
|
+
if incomplete:
|
|
244
|
+
for s in incomplete:
|
|
245
|
+
print('INCOMPLETE: {} {} = {}'.format(s['id'], s['skill'], s['status']))
|
|
246
|
+
sys.exit(1)
|
|
247
|
+
print('ALL_COMPLETE')
|
|
248
|
+
sys.exit(0)
|
|
249
|
+
" "$checkpoint_file" 2>&1)
|
|
250
|
+
local check_exit=$?
|
|
251
|
+
if [[ $check_exit -eq 2 ]]; then
|
|
252
|
+
log_warn "CHECKPOINT_CORRUPTED: workflow-checkpoint.json is not valid JSON"
|
|
253
|
+
elif [[ $check_exit -eq 1 ]]; then
|
|
254
|
+
log_warn "CHECKPOINT_INCOMPLETE: Not all workflow steps completed:"
|
|
255
|
+
echo "$checkpoint_result" | while read -r line; do log_warn " $line"; done
|
|
256
|
+
else
|
|
257
|
+
log_info "CHECKPOINT: All workflow steps completed"
|
|
258
|
+
fi
|
|
259
|
+
fi
|
|
260
|
+
fi
|
|
261
|
+
|
|
227
262
|
# Subagent detection
|
|
228
263
|
prizm_detect_subagents "$session_log"
|
|
229
264
|
|
|
@@ -237,6 +272,12 @@ spawn_and_wait_session() {
|
|
|
237
272
|
--max-retries "$max_retries" \
|
|
238
273
|
--action update >/dev/null 2>&1 || true
|
|
239
274
|
|
|
275
|
+
# Commit bug-fix-list.json status update (pipeline management commit)
|
|
276
|
+
if ! git -C "$project_root" diff --quiet "$bug_list" 2>/dev/null; then
|
|
277
|
+
git -C "$project_root" add "$bug_list"
|
|
278
|
+
git -C "$project_root" commit --no-verify -m "chore($bug_id): update bug status" 2>/dev/null || true
|
|
279
|
+
fi
|
|
280
|
+
|
|
240
281
|
_SPAWN_RESULT="$session_status"
|
|
241
282
|
}
|
|
242
283
|
|
|
@@ -2,17 +2,17 @@
|
|
|
2
2
|
set -euo pipefail
|
|
3
3
|
|
|
4
4
|
# ============================================================
|
|
5
|
-
# dev-pipeline/run.sh - Autonomous Dev Pipeline Runner
|
|
5
|
+
# dev-pipeline/run-feature.sh - Autonomous Dev Pipeline Runner
|
|
6
6
|
#
|
|
7
7
|
# Drives the prizm-dev-team multi-agent team through iterative
|
|
8
8
|
# AI CLI sessions (CodeBuddy or Claude Code) to build a complete app
|
|
9
9
|
# from a feature list.
|
|
10
10
|
#
|
|
11
11
|
# Usage:
|
|
12
|
-
# ./run.sh run [feature-list.json] Run all features
|
|
13
|
-
# ./run.sh run <feature-id> [options] Run a single feature
|
|
14
|
-
# ./run.sh status [feature-list.json] Show pipeline status
|
|
15
|
-
# ./run.sh reset Clear all state
|
|
12
|
+
# ./run-feature.sh run [feature-list.json] Run all features
|
|
13
|
+
# ./run-feature.sh run <feature-id> [options] Run a single feature
|
|
14
|
+
# ./run-feature.sh status [feature-list.json] Show pipeline status
|
|
15
|
+
# ./run-feature.sh reset Clear all state
|
|
16
16
|
#
|
|
17
17
|
# Environment Variables:
|
|
18
18
|
# MAX_RETRIES Max retries per feature (default: 3)
|
|
@@ -116,7 +116,7 @@ spawn_and_wait_session() {
|
|
|
116
116
|
fi
|
|
117
117
|
|
|
118
118
|
# Unset CLAUDECODE to prevent "nested session" error when launched from
|
|
119
|
-
# within an existing Claude Code session (e.g. via launch-daemon.sh).
|
|
119
|
+
# within an existing Claude Code session (e.g. via launch-feature-daemon.sh).
|
|
120
120
|
unset CLAUDECODE 2>/dev/null || true
|
|
121
121
|
|
|
122
122
|
case "$CLI_CMD" in
|
|
@@ -287,6 +287,39 @@ sys.exit(1)
|
|
|
287
287
|
if [[ ! -f "$plan_file" ]]; then
|
|
288
288
|
log_warn "ARTIFACT_MISSING: plan.md not found at $plan_file"
|
|
289
289
|
fi
|
|
290
|
+
|
|
291
|
+
# Validate checkpoint completeness
|
|
292
|
+
local checkpoint_file="$project_root_for_artifacts/.prizmkit/specs/${feature_slug}/workflow-checkpoint.json"
|
|
293
|
+
if [[ -f "$checkpoint_file" ]]; then
|
|
294
|
+
local checkpoint_result
|
|
295
|
+
checkpoint_result=$(python3 -c "
|
|
296
|
+
import json, sys
|
|
297
|
+
try:
|
|
298
|
+
with open(sys.argv[1]) as f:
|
|
299
|
+
data = json.load(f)
|
|
300
|
+
except json.JSONDecodeError as e:
|
|
301
|
+
print('CORRUPTED: {}'.format(e))
|
|
302
|
+
sys.exit(2)
|
|
303
|
+
incomplete = [s for s in data['steps'] if s['status'] not in ('completed', 'skipped')]
|
|
304
|
+
if incomplete:
|
|
305
|
+
for s in incomplete:
|
|
306
|
+
print('INCOMPLETE: {} {} = {}'.format(s['id'], s['skill'], s['status']))
|
|
307
|
+
sys.exit(1)
|
|
308
|
+
print('ALL_COMPLETE')
|
|
309
|
+
sys.exit(0)
|
|
310
|
+
" "$checkpoint_file" 2>&1)
|
|
311
|
+
local check_exit=$?
|
|
312
|
+
if [[ $check_exit -eq 2 ]]; then
|
|
313
|
+
log_warn "CHECKPOINT_CORRUPTED: workflow-checkpoint.json is not valid JSON"
|
|
314
|
+
elif [[ $check_exit -eq 1 ]]; then
|
|
315
|
+
log_warn "CHECKPOINT_INCOMPLETE: Not all workflow steps completed:"
|
|
316
|
+
echo "$checkpoint_result" | while read -r line; do log_warn " $line"; done
|
|
317
|
+
else
|
|
318
|
+
log_info "CHECKPOINT: All workflow steps completed"
|
|
319
|
+
fi
|
|
320
|
+
else
|
|
321
|
+
log_info "CHECKPOINT: No workflow-checkpoint.json found (checkpoint system not active)"
|
|
322
|
+
fi
|
|
290
323
|
fi
|
|
291
324
|
|
|
292
325
|
# Check if session produced a failure-log for future retries
|
|
@@ -316,8 +349,8 @@ sys.exit(1)
|
|
|
316
349
|
}
|
|
317
350
|
|
|
318
351
|
# Commit feature status update (pipeline management commit)
|
|
319
|
-
if ! git -C "$project_root" diff --quiet
|
|
320
|
-
git -C "$project_root" add
|
|
352
|
+
if ! git -C "$project_root" diff --quiet "$feature_list" 2>/dev/null; then
|
|
353
|
+
git -C "$project_root" add "$feature_list"
|
|
321
354
|
git -C "$project_root" commit --no-verify -m "chore($feature_id): update feature status" 2>/dev/null || true
|
|
322
355
|
fi
|
|
323
356
|
|
|
@@ -349,7 +382,7 @@ cleanup() {
|
|
|
349
382
|
--action pause 2>/dev/null || true
|
|
350
383
|
fi
|
|
351
384
|
|
|
352
|
-
log_info "Pipeline paused. Run './run.sh run' to resume."
|
|
385
|
+
log_info "Pipeline paused. Run './run-feature.sh run' to resume."
|
|
353
386
|
exit 130
|
|
354
387
|
}
|
|
355
388
|
trap cleanup SIGINT SIGTERM
|
|
@@ -809,8 +842,8 @@ main() {
|
|
|
809
842
|
# Validate feature list exists
|
|
810
843
|
if [[ ! -f "$feature_list" ]]; then
|
|
811
844
|
log_error "Feature list not found: $feature_list"
|
|
812
|
-
log_info "Create a feature list first using the
|
|
813
|
-
log_info "or provide a path: ./run.sh run <path-to-feature-list.json>"
|
|
845
|
+
log_info "Create a feature list first using the feature-planner skill,"
|
|
846
|
+
log_info "or provide a path: ./run-feature.sh run <path-to-feature-list.json>"
|
|
814
847
|
exit 1
|
|
815
848
|
fi
|
|
816
849
|
|
|
@@ -956,8 +989,8 @@ print(count)
|
|
|
956
989
|
if [[ "$auto_skipped_count" -gt 0 ]]; then
|
|
957
990
|
echo ""
|
|
958
991
|
log_warn "$auto_skipped_count feature(s) were auto-skipped due to failed dependencies."
|
|
959
|
-
log_warn "Run './run.sh status' to see details."
|
|
960
|
-
log_warn "Run './run.sh unskip' to reset and retry them."
|
|
992
|
+
log_warn "Run './run-feature.sh status' to see details."
|
|
993
|
+
log_warn "Run './run-feature.sh unskip' to reset and retry them."
|
|
961
994
|
fi
|
|
962
995
|
|
|
963
996
|
break
|
|
@@ -965,7 +998,7 @@ print(count)
|
|
|
965
998
|
|
|
966
999
|
if [[ "$next_feature" == "PIPELINE_BLOCKED" ]]; then
|
|
967
1000
|
log_warn "All remaining features are blocked by dependencies or failed."
|
|
968
|
-
log_warn "Run './run.sh status' to see details."
|
|
1001
|
+
log_warn "Run './run-feature.sh status' to see details."
|
|
969
1002
|
log_warn "Waiting 60s before re-checking... (Ctrl+C to stop)"
|
|
970
1003
|
sleep 60
|
|
971
1004
|
continue
|
|
@@ -1027,12 +1060,12 @@ print(count)
|
|
|
1027
1060
|
--output "$bootstrap_prompt"
|
|
1028
1061
|
)
|
|
1029
1062
|
|
|
1030
|
-
# Support PIPELINE_MODE env var (set by launch-daemon.sh --mode)
|
|
1063
|
+
# Support PIPELINE_MODE env var (set by launch-feature-daemon.sh --mode)
|
|
1031
1064
|
if [[ -n "${PIPELINE_MODE:-}" ]]; then
|
|
1032
1065
|
main_prompt_args+=(--mode "$PIPELINE_MODE")
|
|
1033
1066
|
fi
|
|
1034
1067
|
|
|
1035
|
-
# Support ENABLE_CRITIC env var (set by launch-daemon.sh --critic)
|
|
1068
|
+
# Support ENABLE_CRITIC env var (set by launch-feature-daemon.sh --critic)
|
|
1036
1069
|
if [[ "${ENABLE_CRITIC:-}" == "true" || "${ENABLE_CRITIC:-}" == "1" ]]; then
|
|
1037
1070
|
main_prompt_args+=(--critic "true")
|
|
1038
1071
|
elif [[ "${ENABLE_CRITIC:-}" == "false" || "${ENABLE_CRITIC:-}" == "0" ]]; then
|
|
@@ -1154,18 +1187,18 @@ show_help() {
|
|
|
1154
1187
|
echo " ENABLE_CRITIC Enable critic review for all features: true|false"
|
|
1155
1188
|
echo ""
|
|
1156
1189
|
echo "Examples:"
|
|
1157
|
-
echo " ./run.sh run # Run all features"
|
|
1158
|
-
echo " ./run.sh run --features F-001,F-003,F-005 # Run specific features"
|
|
1159
|
-
echo " ./run.sh run --features F-001:F-010 # Run features F-001 through F-010"
|
|
1160
|
-
echo " ./run.sh run F-007 --dry-run # Inspect generated prompt"
|
|
1161
|
-
echo " ./run.sh run F-007 --dry-run --mode lite # Test lite mode"
|
|
1162
|
-
echo " ./run.sh run F-007 --resume-phase 6 # Skip to implementation"
|
|
1163
|
-
echo " ./run.sh run F-007 --mode full --timeout 3600 # Full mode, 1h timeout"
|
|
1164
|
-
echo " ./run.sh run F-007 --clean --mode standard # Clean + run standard"
|
|
1165
|
-
echo " ./run.sh status # Show pipeline status"
|
|
1166
|
-
echo " MAX_RETRIES=5 SESSION_TIMEOUT=7200 ./run.sh run # Custom config"
|
|
1167
|
-
echo " MODEL=claude-sonnet-4.6 ./run.sh run # Use Sonnet model"
|
|
1168
|
-
echo " MODEL=claude-haiku-4.5 ./run.sh test-cli # Test with Haiku"
|
|
1190
|
+
echo " ./run-feature.sh run # Run all features"
|
|
1191
|
+
echo " ./run-feature.sh run --features F-001,F-003,F-005 # Run specific features"
|
|
1192
|
+
echo " ./run-feature.sh run --features F-001:F-010 # Run features F-001 through F-010"
|
|
1193
|
+
echo " ./run-feature.sh run F-007 --dry-run # Inspect generated prompt"
|
|
1194
|
+
echo " ./run-feature.sh run F-007 --dry-run --mode lite # Test lite mode"
|
|
1195
|
+
echo " ./run-feature.sh run F-007 --resume-phase 6 # Skip to implementation"
|
|
1196
|
+
echo " ./run-feature.sh run F-007 --mode full --timeout 3600 # Full mode, 1h timeout"
|
|
1197
|
+
echo " ./run-feature.sh run F-007 --clean --mode standard # Clean + run standard"
|
|
1198
|
+
echo " ./run-feature.sh status # Show pipeline status"
|
|
1199
|
+
echo " MAX_RETRIES=5 SESSION_TIMEOUT=7200 ./run-feature.sh run # Custom config"
|
|
1200
|
+
echo " MODEL=claude-sonnet-4.6 ./run-feature.sh run # Use Sonnet model"
|
|
1201
|
+
echo " MODEL=claude-haiku-4.5 ./run-feature.sh test-cli # Test with Haiku"
|
|
1169
1202
|
}
|
|
1170
1203
|
|
|
1171
1204
|
case "${1:-run}" in
|
|
@@ -1201,7 +1234,7 @@ case "${1:-run}" in
|
|
|
1201
1234
|
status)
|
|
1202
1235
|
check_dependencies
|
|
1203
1236
|
if [[ ! -f "$STATE_DIR/pipeline.json" ]]; then
|
|
1204
|
-
log_error "No pipeline state found. Run './run.sh run' first."
|
|
1237
|
+
log_error "No pipeline state found. Run './run-feature.sh run' first."
|
|
1205
1238
|
exit 1
|
|
1206
1239
|
fi
|
|
1207
1240
|
python3 "$SCRIPTS_DIR/update-feature-status.py" \
|
|
@@ -1270,12 +1303,12 @@ case "${1:-run}" in
|
|
|
1270
1303
|
reset)
|
|
1271
1304
|
log_warn "Resetting pipeline state..."
|
|
1272
1305
|
rm -rf "$STATE_DIR"
|
|
1273
|
-
log_success "State cleared. Run './run.sh run' to start fresh."
|
|
1306
|
+
log_success "State cleared. Run './run-feature.sh run' to start fresh."
|
|
1274
1307
|
;;
|
|
1275
1308
|
unskip)
|
|
1276
1309
|
check_dependencies
|
|
1277
1310
|
if [[ ! -f "$STATE_DIR/pipeline.json" ]]; then
|
|
1278
|
-
log_error "No pipeline state found. Run './run.sh run' first."
|
|
1311
|
+
log_error "No pipeline state found. Run './run-feature.sh run' first."
|
|
1279
1312
|
exit 1
|
|
1280
1313
|
fi
|
|
1281
1314
|
_unskip_feature_list="feature-list.json"
|