prizmkit 1.0.91 → 1.0.93

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.91",
3
- "bundledAt": "2026-03-22T16:22:09.148Z",
4
- "bundledFrom": "e2ee289"
2
+ "frameworkVersion": "1.0.93",
3
+ "bundledAt": "2026-03-22T17:12:01.644Z",
4
+ "bundledFrom": "62f12ab"
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
 
@@ -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
 
@@ -744,7 +744,7 @@ sys.exit(1)
744
744
  _source_branch=$(git -C "$_proj_root" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "main")
745
745
  _ORIGINAL_BRANCH="$_source_branch"
746
746
 
747
- local _branch_name="${DEV_BRANCH:-dev/${feature_id}-$(date +%s)}"
747
+ local _branch_name="${DEV_BRANCH:-dev/${feature_id}-$(date +%Y%m%d%H%M)}"
748
748
  if branch_create "$_proj_root" "$_branch_name" "$_source_branch"; then
749
749
  _DEV_BRANCH_NAME="$_branch_name"
750
750
  else
@@ -895,23 +895,13 @@ main() {
895
895
  echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
896
896
  echo ""
897
897
 
898
- # Branch lifecycle: create dev branch for this pipeline run
898
+ # Branch lifecycle: each feature gets its own dev branch (created per-iteration below)
899
899
  local _proj_root
900
900
  _proj_root="$(cd "$SCRIPT_DIR/.." && pwd)"
901
901
  local _source_branch
902
902
  _source_branch=$(git -C "$_proj_root" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "main")
903
903
  _ORIGINAL_BRANCH="$_source_branch"
904
904
 
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
905
  # Main processing loop
916
906
  local session_count=0
917
907
 
@@ -952,16 +942,6 @@ for f in data.get('stuck_features', []):
952
942
  log_success " Total sessions: $session_count"
953
943
  log_success "════════════════════════════════════════════════════"
954
944
  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
945
  break
966
946
  fi
967
947
 
@@ -989,6 +969,16 @@ for f in data.get('stuck_features', []):
989
969
  fi
990
970
  echo -e "${BOLD}────────────────────────────────────────────────────${NC}"
991
971
 
972
+ # Create per-feature dev branch
973
+ local _feature_branch="${DEV_BRANCH:-dev/${feature_id}-$(date +%Y%m%d%H%M)}"
974
+ if branch_create "$_proj_root" "$_feature_branch" "$_ORIGINAL_BRANCH"; then
975
+ _DEV_BRANCH_NAME="$_feature_branch"
976
+ log_info "Dev branch: $_feature_branch"
977
+ else
978
+ log_warn "Failed to create dev branch; running on current branch: $_ORIGINAL_BRANCH"
979
+ _DEV_BRANCH_NAME=""
980
+ fi
981
+
992
982
  # Generate session ID and bootstrap prompt
993
983
  local session_id run_id
994
984
  run_id=$(jq -r '.run_id' "$STATE_DIR/pipeline.json")
@@ -1071,6 +1061,22 @@ os.replace(tmp, target)
1071
1061
  "$bootstrap_prompt" "$session_dir" "$MAX_RETRIES" "$feature_model"
1072
1062
  local session_status="$_SPAWN_RESULT"
1073
1063
 
1064
+ # Merge per-feature dev branch back to original on success
1065
+ if [[ "$session_status" == "success" && -n "$_DEV_BRANCH_NAME" ]]; then
1066
+ if branch_merge "$_proj_root" "$_DEV_BRANCH_NAME" "$_ORIGINAL_BRANCH" "$AUTO_PUSH"; then
1067
+ _DEV_BRANCH_NAME=""
1068
+ else
1069
+ log_warn "Auto-merge failed — dev branch preserved: $_DEV_BRANCH_NAME"
1070
+ log_warn "Merge manually: git checkout $_ORIGINAL_BRANCH && git rebase $_DEV_BRANCH_NAME"
1071
+ _DEV_BRANCH_NAME=""
1072
+ fi
1073
+ elif [[ -n "$_DEV_BRANCH_NAME" ]]; then
1074
+ # Session failed — return to original branch, preserve dev branch for inspection
1075
+ git -C "$_proj_root" checkout "$_ORIGINAL_BRANCH" 2>/dev/null || true
1076
+ log_warn "Session failed — dev branch preserved for inspection: $_DEV_BRANCH_NAME"
1077
+ _DEV_BRANCH_NAME=""
1078
+ fi
1079
+
1074
1080
  session_count=$((session_count + 1))
1075
1081
 
1076
1082
  # 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.91",
2
+ "version": "1.0.93",
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.91",
3
+ "version": "1.0.93",
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": {
package/src/scaffold.js CHANGED
@@ -680,8 +680,9 @@ export async function installPipeline(projectRoot, dryRun, { forceOverwrite = fa
680
680
  /**
681
681
  * 生成 .gitignore
682
682
  */
683
- async function installGitignore(projectRoot, options, dryRun) {
683
+ export async function installGitignore(projectRoot, options, dryRun) {
684
684
  const targetPath = path.join(projectRoot, '.gitignore');
685
+ const MODELS_ENTRY = '.prizmkit/available-models.json';
685
686
 
686
687
  if (dryRun) {
687
688
  console.log(chalk.gray(` [dry-run] .gitignore`));
@@ -689,12 +690,21 @@ async function installGitignore(projectRoot, options, dryRun) {
689
690
  }
690
691
 
691
692
  if (await fs.pathExists(targetPath)) {
692
- // 追加 PrizmKit 相关条目
693
693
  const existing = await fs.readFile(targetPath, 'utf8');
694
+
695
+ // If .prizmkit/ (whole dir) is already ignored, available-models.json is covered
694
696
  if (existing.includes('.prizmkit/')) {
697
+ console.log(chalk.yellow(` ⚠ .gitignore 已包含 .prizmkit/ 条目,跳过`));
698
+ return;
699
+ }
700
+
701
+ // If the specific entry is already present, nothing to do
702
+ if (existing.includes(MODELS_ENTRY)) {
695
703
  console.log(chalk.yellow(` ⚠ .gitignore 已包含 PrizmKit 条目,跳过`));
696
704
  return;
697
705
  }
706
+
707
+ // No PrizmKit entries at all — append full .prizmkit/ block
698
708
  const prizmkitSection = '\n\n# PrizmKit\n.prizmkit/\n';
699
709
  await fs.appendFile(targetPath, prizmkitSection);
700
710
  console.log(chalk.green(` ✓ .gitignore (追加 PrizmKit 条目)`));
package/src/upgrade.js CHANGED
@@ -28,6 +28,7 @@ import {
28
28
  installPrizmkitScripts,
29
29
  installGitHook,
30
30
  installPostMergeHook,
31
+ installGitignore,
31
32
  resolvePipelineFileList,
32
33
  } from './scaffold.js';
33
34
 
@@ -364,6 +365,10 @@ export async function runUpgrade(directory, options = {}) {
364
365
  await installGitHook(projectRoot, dryRun);
365
366
  await installPostMergeHook(projectRoot, dryRun);
366
367
 
368
+ // .gitignore
369
+ console.log(chalk.blue(' Gitignore:'));
370
+ await installGitignore(projectRoot, { pipeline }, dryRun);
371
+
367
372
  // PrizmKit scripts
368
373
  console.log(chalk.blue(' PrizmKit Scripts:'));
369
374
  await installPrizmkitScripts(projectRoot, dryRun);