prizmkit 1.0.92 → 1.0.94

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.
@@ -1,5 +1,5 @@
1
1
  {
2
- "frameworkVersion": "1.0.92",
3
- "bundledAt": "2026-03-22T16:41:48.152Z",
4
- "bundledFrom": "c189001"
2
+ "frameworkVersion": "1.0.94",
3
+ "bundledAt": "2026-03-23T00:08:19.504Z",
4
+ "bundledFrom": "b1e871c"
5
5
  }
@@ -81,9 +81,10 @@ branch_return() {
81
81
  # Merges dev_branch into original_branch, then optionally pushes.
82
82
  # Steps:
83
83
  # 1. Checkout original_branch
84
- # 2. Merge dev_branch (fast-forward when possible)
85
- # 3. Push to remote if auto_push == "1"
86
- # 4. Delete dev_branch (local only, it's been merged)
84
+ # 2. Rebase dev_branch onto original_branch (handles diverged main)
85
+ # 3. Fast-forward merge original_branch to rebased dev tip
86
+ # 4. Push to remote if auto_push == "1"
87
+ # 5. Delete dev_branch (local only, it's been merged)
87
88
  #
88
89
  # Returns 0 on success, 1 on failure.
89
90
  branch_merge() {
@@ -100,15 +101,28 @@ branch_merge() {
100
101
  git -C "$project_root" add -A 2>/dev/null || true
101
102
  git -C "$project_root" commit --no-verify -m "chore: include pipeline state artifacts" 2>/dev/null || true
102
103
  fi
104
+
105
+ # Step 2: Rebase dev branch onto original to make it fast-forwardable.
106
+ # This handles the case where original_branch has diverged
107
+ # (e.g. commits were made on main while the pipeline was running).
108
+ # "git rebase A B" is equivalent to: git checkout B && git rebase A
109
+ log_info "Merging $dev_branch into $original_branch..."
110
+ if ! git -C "$project_root" rebase "$original_branch" "$dev_branch" 2>&1; then
111
+ log_error "Rebase of $dev_branch onto $original_branch failed — resolve manually:"
112
+ log_error " git rebase --abort # then resolve conflicts and retry"
113
+ git -C "$project_root" rebase --abort 2>/dev/null || true
114
+ git -C "$project_root" checkout "$dev_branch" 2>/dev/null || true
115
+ return 1
116
+ fi
117
+ # After the rebase we are on dev_branch — checkout original for the fast-forward
103
118
  if ! git -C "$project_root" checkout "$original_branch" 2>/dev/null; then
104
119
  log_error "Failed to checkout $original_branch for merge"
105
120
  return 1
106
121
  fi
107
122
 
108
- # Step 2: Merge dev branch (fast-forward only avoids interactive merge commit editor)
109
- log_info "Merging $dev_branch into $original_branch..."
123
+ # Step 3: Fast-forward original_branch to the rebased dev tip
110
124
  if ! git -C "$project_root" merge --ff-only "$dev_branch" 2>&1; then
111
- log_error "Merge failed (non-fast-forward) — resolve manually:"
125
+ log_error "Merge failed after rebase this should not happen, resolve manually:"
112
126
  log_error " git checkout $original_branch && git rebase $dev_branch"
113
127
  git -C "$project_root" checkout "$dev_branch" 2>/dev/null || true
114
128
  return 1
@@ -116,7 +130,7 @@ branch_merge() {
116
130
 
117
131
  log_success "Merged $dev_branch into $original_branch"
118
132
 
119
- # Step 3: Push if AUTO_PUSH enabled
133
+ # Step 4: Push if AUTO_PUSH enabled
120
134
  if [[ "$auto_push" == "1" ]]; then
121
135
  log_info "Pushing $original_branch to remote..."
122
136
  if git -C "$project_root" push 2>/dev/null; then
@@ -126,7 +140,7 @@ branch_merge() {
126
140
  fi
127
141
  fi
128
142
 
129
- # Step 4: Delete merged dev branch
143
+ # Step 5: Delete merged dev branch
130
144
  git -C "$project_root" branch -d "$dev_branch" 2>/dev/null && \
131
145
  log_info "Deleted merged branch: $dev_branch" || true
132
146
 
@@ -328,6 +328,7 @@ if [[ -f "$SESSION_LOG" ]]; then
328
328
  FINAL_SIZE=$(wc -c < "$SESSION_LOG" 2>/dev/null | tr -d ' ')
329
329
  log_info "Session log: $FINAL_LINES lines, $((FINAL_SIZE / 1024))KB"
330
330
  fi
331
+ log_info "exit_code=$EXIT_CODE"
331
332
 
332
333
  # ── Determine session outcome from observable signals ──────────────
333
334
  PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
@@ -337,6 +337,7 @@ if [[ -f "$SESSION_LOG" ]]; then
337
337
  FINAL_SIZE=$(wc -c < "$SESSION_LOG" 2>/dev/null | tr -d ' ')
338
338
  log_info "Session log: $FINAL_LINES lines, $((FINAL_SIZE / 1024))KB"
339
339
  fi
340
+ log_info "exit_code=$EXIT_CODE"
340
341
 
341
342
  # ── Determine session outcome from observable signals ──────────────
342
343
  PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
@@ -163,6 +163,7 @@ spawn_and_wait_session() {
163
163
  local final_lines=$(wc -l < "$session_log" 2>/dev/null | tr -d ' ')
164
164
  log_info "Session log: $final_lines lines, $((final_size / 1024))KB"
165
165
  fi
166
+ log_info "exit_code=$exit_code"
166
167
 
167
168
  # ── Determine session outcome from observable signals ──────────────
168
169
  local session_status
@@ -28,7 +28,7 @@ set -euo pipefail
28
28
  # LOG_RETENTION_DAYS Delete logs older than N days (default: 14)
29
29
  # LOG_MAX_TOTAL_MB Keep total logs under N MB via oldest-first cleanup (default: 1024)
30
30
  # PIPELINE_MODE Override mode for all features: lite|standard|full|self-evolve (used by daemon)
31
- # DEV_BRANCH Custom dev branch name (default: auto-generated dev/pipeline-{run_id})
31
+ # DEV_BRANCH Custom dev branch name (default: auto-generated dev/{feature_id}-YYYYMMDDHHmm)
32
32
  # AUTO_PUSH Auto-push to remote after successful feature (default: 0). Set to 1 to enable.
33
33
  # ============================================================
34
34
 
@@ -183,6 +183,7 @@ spawn_and_wait_session() {
183
183
  local final_lines=$(wc -l < "$session_log" 2>/dev/null | tr -d ' ')
184
184
  log_info "Session log: $final_lines lines, $((final_size / 1024))KB"
185
185
  fi
186
+ log_info "exit_code=$exit_code"
186
187
 
187
188
  # ── Determine session outcome from observable signals ──────────────
188
189
  # No dependency on session-status.json — uses exit code, git commits,
@@ -272,39 +273,6 @@ sys.exit(1)
272
273
  feature_slug=""
273
274
  }
274
275
 
275
- if [[ -n "$feature_slug" ]]; then
276
- local project_root_for_summary
277
- project_root_for_summary="$(cd "$SCRIPT_DIR/.." && pwd)"
278
- local summary_path="$project_root_for_summary/.prizmkit/specs/${feature_slug}/session-summary.json"
279
- mkdir -p "$(dirname "$summary_path")"
280
- local session_start_time
281
- session_start_time=$(python3 -c "
282
- import json, sys, os
283
- p = os.path.join(sys.argv[1], 'current-session.json')
284
- if os.path.isfile(p):
285
- with open(p) as f: print(json.load(f).get('started_at', ''))
286
- else: print('')
287
- " "$STATE_DIR" 2>/dev/null) || session_start_time=""
288
- local exec_tier
289
- exec_tier=$(python3 -c "
290
- import json, sys, os
291
- p = sys.argv[1]
292
- if os.path.isfile(p):
293
- with open(p) as f: print(json.load(f).get('exec_tier', ''))
294
- else: print('')
295
- " "$session_dir/session-status.json" 2>/dev/null) || exec_tier=""
296
- cat > "$summary_path" <<SUMMARY
297
- {
298
- "feature_id": "$feature_id",
299
- "session_id": "$session_id",
300
- "status": "$session_status",
301
- "started_at": "$session_start_time",
302
- "completed_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
303
- "tier": "$exec_tier"
304
- }
305
- SUMMARY
306
- fi
307
-
308
276
  # Validate key artifacts exist after successful session
309
277
  if [[ "$session_status" == "success" && -n "$feature_slug" ]]; then
310
278
  local project_root_for_artifacts
@@ -744,7 +712,7 @@ sys.exit(1)
744
712
  _source_branch=$(git -C "$_proj_root" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "main")
745
713
  _ORIGINAL_BRANCH="$_source_branch"
746
714
 
747
- local _branch_name="${DEV_BRANCH:-dev/${feature_id}-$(date +%s)}"
715
+ local _branch_name="${DEV_BRANCH:-dev/${feature_id}-$(date +%Y%m%d%H%M)}"
748
716
  if branch_create "$_proj_root" "$_branch_name" "$_source_branch"; then
749
717
  _DEV_BRANCH_NAME="$_branch_name"
750
718
  else
@@ -895,23 +863,13 @@ main() {
895
863
  echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
896
864
  echo ""
897
865
 
898
- # Branch lifecycle: create dev branch for this pipeline run
866
+ # Branch lifecycle: each feature gets its own dev branch (created per-iteration below)
899
867
  local _proj_root
900
868
  _proj_root="$(cd "$SCRIPT_DIR/.." && pwd)"
901
869
  local _source_branch
902
870
  _source_branch=$(git -C "$_proj_root" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "main")
903
871
  _ORIGINAL_BRANCH="$_source_branch"
904
872
 
905
- local run_id_for_branch
906
- run_id_for_branch=$(jq -r '.run_id' "$STATE_DIR/pipeline.json" 2>/dev/null || echo "$$")
907
- local _branch_name="${DEV_BRANCH:-dev/pipeline-${run_id_for_branch}}"
908
- if branch_create "$_proj_root" "$_branch_name" "$_source_branch"; then
909
- _DEV_BRANCH_NAME="$_branch_name"
910
- log_info "Dev branch: $_branch_name"
911
- else
912
- log_warn "Failed to create dev branch; running on current branch: $_source_branch"
913
- fi
914
-
915
873
  # Main processing loop
916
874
  local session_count=0
917
875
 
@@ -952,16 +910,6 @@ for f in data.get('stuck_features', []):
952
910
  log_success " Total sessions: $session_count"
953
911
  log_success "════════════════════════════════════════════════════"
954
912
  rm -f "$STATE_DIR/current-session.json"
955
-
956
- # Merge dev branch back to original
957
- if [[ -n "$_DEV_BRANCH_NAME" ]]; then
958
- if branch_merge "$_proj_root" "$_DEV_BRANCH_NAME" "$_ORIGINAL_BRANCH" "$AUTO_PUSH"; then
959
- _DEV_BRANCH_NAME=""
960
- else
961
- log_warn "Auto-merge failed — dev branch preserved: $_DEV_BRANCH_NAME"
962
- log_warn "Merge manually: git checkout $_ORIGINAL_BRANCH && git rebase $_DEV_BRANCH_NAME"
963
- fi
964
- fi
965
913
  break
966
914
  fi
967
915
 
@@ -989,6 +937,16 @@ for f in data.get('stuck_features', []):
989
937
  fi
990
938
  echo -e "${BOLD}────────────────────────────────────────────────────${NC}"
991
939
 
940
+ # Create per-feature dev branch
941
+ local _feature_branch="${DEV_BRANCH:-dev/${feature_id}-$(date +%Y%m%d%H%M)}"
942
+ if branch_create "$_proj_root" "$_feature_branch" "$_ORIGINAL_BRANCH"; then
943
+ _DEV_BRANCH_NAME="$_feature_branch"
944
+ log_info "Dev branch: $_feature_branch"
945
+ else
946
+ log_warn "Failed to create dev branch; running on current branch: $_ORIGINAL_BRANCH"
947
+ _DEV_BRANCH_NAME=""
948
+ fi
949
+
992
950
  # Generate session ID and bootstrap prompt
993
951
  local session_id run_id
994
952
  run_id=$(jq -r '.run_id' "$STATE_DIR/pipeline.json")
@@ -1071,6 +1029,22 @@ os.replace(tmp, target)
1071
1029
  "$bootstrap_prompt" "$session_dir" "$MAX_RETRIES" "$feature_model"
1072
1030
  local session_status="$_SPAWN_RESULT"
1073
1031
 
1032
+ # Merge per-feature dev branch back to original on success
1033
+ if [[ "$session_status" == "success" && -n "$_DEV_BRANCH_NAME" ]]; then
1034
+ if branch_merge "$_proj_root" "$_DEV_BRANCH_NAME" "$_ORIGINAL_BRANCH" "$AUTO_PUSH"; then
1035
+ _DEV_BRANCH_NAME=""
1036
+ else
1037
+ log_warn "Auto-merge failed — dev branch preserved: $_DEV_BRANCH_NAME"
1038
+ log_warn "Merge manually: git checkout $_ORIGINAL_BRANCH && git rebase $_DEV_BRANCH_NAME"
1039
+ _DEV_BRANCH_NAME=""
1040
+ fi
1041
+ elif [[ -n "$_DEV_BRANCH_NAME" ]]; then
1042
+ # Session failed — return to original branch, preserve dev branch for inspection
1043
+ git -C "$_proj_root" checkout "$_ORIGINAL_BRANCH" 2>/dev/null || true
1044
+ log_warn "Session failed — dev branch preserved for inspection: $_DEV_BRANCH_NAME"
1045
+ _DEV_BRANCH_NAME=""
1046
+ fi
1047
+
1074
1048
  session_count=$((session_count + 1))
1075
1049
 
1076
1050
  # Brief pause before next iteration
@@ -195,7 +195,7 @@ def create_state_directory(state_dir, bug_list_path, bugs):
195
195
  bugs_dir = os.path.join(abs_state_dir, "bugs")
196
196
 
197
197
  now = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
198
- run_id = "bugfix-run-" + datetime.now(timezone.utc).strftime("%Y%m%d-%H%M%S")
198
+ run_id = "bugfix-run-" + datetime.now(timezone.utc).strftime("%Y%m%d%H%M")
199
199
 
200
200
  # Create top-level state directory
201
201
  os.makedirs(abs_state_dir, exist_ok=True)
@@ -231,7 +231,7 @@ def create_state_directory(state_dir, feature_list_path, features):
231
231
  features_dir = os.path.join(abs_state_dir, "features")
232
232
 
233
233
  now = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
234
- run_id = "run-" + datetime.now(timezone.utc).strftime("%Y%m%d-%H%M%S")
234
+ run_id = "run-" + datetime.now(timezone.utc).strftime("%Y%m%d%H%M")
235
235
 
236
236
  # Create top-level state directory
237
237
  os.makedirs(abs_state_dir, exist_ok=True)
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.0.92",
2
+ "version": "1.0.94",
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.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prizmkit",
3
- "version": "1.0.92",
3
+ "version": "1.0.94",
4
4
  "description": "Create a new PrizmKit-powered project with clean initialization — no framework dev files, just what you need.",
5
5
  "type": "module",
6
6
  "bin": {