prizmkit 1.0.12 → 1.0.13

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.12",
3
- "bundledAt": "2026-03-12T18:05:27.841Z",
4
- "bundledFrom": "051c0a3"
2
+ "frameworkVersion": "1.0.13",
3
+ "bundledAt": "2026-03-13T01:34:34.833Z",
4
+ "bundledFrom": "cca8058"
5
5
  }
@@ -299,6 +299,18 @@ else
299
299
  SESSION_STATUS="crashed"
300
300
  fi
301
301
 
302
+ if [[ "$SESSION_STATUS" == "success" ]]; then
303
+ PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
304
+ if git -C "$PROJECT_ROOT" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
305
+ DIRTY_FILES=$(git -C "$PROJECT_ROOT" status --porcelain 2>/dev/null || true)
306
+ if [[ -n "$DIRTY_FILES" ]]; then
307
+ log_error "Session reported success but git working tree is not clean."
308
+ echo "$DIRTY_FILES" | sed 's/^/ - /'
309
+ SESSION_STATUS="failed"
310
+ fi
311
+ fi
312
+ fi
313
+
302
314
  # Update bug status
303
315
  python3 "$SCRIPTS_DIR/update-bug-status.py" \
304
316
  --bug-list "$BUG_LIST" \
@@ -300,6 +300,18 @@ else
300
300
  SESSION_STATUS="crashed"
301
301
  fi
302
302
 
303
+ if [[ "$SESSION_STATUS" == "success" ]]; then
304
+ PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
305
+ if git -C "$PROJECT_ROOT" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
306
+ DIRTY_FILES=$(git -C "$PROJECT_ROOT" status --porcelain 2>/dev/null || true)
307
+ if [[ -n "$DIRTY_FILES" ]]; then
308
+ log_error "Session reported success but git working tree is not clean."
309
+ echo "$DIRTY_FILES" | sed 's/^/ - /'
310
+ SESSION_STATUS="failed"
311
+ fi
312
+ fi
313
+ fi
314
+
303
315
  # Update feature status
304
316
  python3 "$SCRIPTS_DIR/update-feature-status.py" \
305
317
  --feature-list "$FEATURE_LIST" \
@@ -180,6 +180,20 @@ spawn_and_wait_session() {
180
180
  session_status="crashed"
181
181
  fi
182
182
 
183
+ if [[ "$session_status" == "success" ]]; then
184
+ local project_root
185
+ project_root="$(cd "$SCRIPT_DIR/.." && pwd)"
186
+ if git -C "$project_root" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
187
+ local dirty_files=""
188
+ dirty_files=$(git -C "$project_root" status --porcelain 2>/dev/null || true)
189
+ if [[ -n "$dirty_files" ]]; then
190
+ log_error "Session reported success but git working tree is not clean."
191
+ echo "$dirty_files" | sed 's/^/ - /'
192
+ session_status="failed"
193
+ fi
194
+ fi
195
+ fi
196
+
183
197
  log_info "Session result: $session_status"
184
198
 
185
199
  # Update bug status
@@ -199,6 +199,20 @@ spawn_and_wait_session() {
199
199
  session_status="crashed"
200
200
  fi
201
201
 
202
+ if [[ "$session_status" == "success" ]]; then
203
+ local project_root
204
+ project_root="$(cd "$SCRIPT_DIR/.." && pwd)"
205
+ if git -C "$project_root" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
206
+ local dirty_files=""
207
+ dirty_files=$(git -C "$project_root" status --porcelain 2>/dev/null || true)
208
+ if [[ -n "$dirty_files" ]]; then
209
+ log_error "Session reported success but git working tree is not clean."
210
+ echo "$dirty_files" | sed 's/^/ - /'
211
+ session_status="failed"
212
+ fi
213
+ fi
214
+ fi
215
+
202
216
  log_info "Session result: $session_status"
203
217
 
204
218
  # Update feature status
@@ -401,6 +401,29 @@ def action_update(args, feature_list_path, state_dir):
401
401
  fs = load_feature_status(state_dir, feature_id)
402
402
 
403
403
  if session_status == "success":
404
+ # No-op guard: if this exact successful session was already recorded,
405
+ # avoid rewriting state files again (prevents post-commit dirty changes).
406
+ existing_sessions = fs.get("sessions", [])
407
+ already_completed = fs.get("status") == "completed" and fs.get("resume_from_phase") is None
408
+ same_session_already_recorded = (
409
+ session_id
410
+ and session_id in existing_sessions
411
+ and fs.get("last_session_id") == session_id
412
+ )
413
+ if already_completed and (same_session_already_recorded or not session_id):
414
+ summary = {
415
+ "action": "update",
416
+ "feature_id": feature_id,
417
+ "session_status": session_status,
418
+ "new_status": fs.get("status", "completed"),
419
+ "retry_count": fs.get("retry_count", 0),
420
+ "resume_from_phase": fs.get("resume_from_phase"),
421
+ "updated_at": fs.get("updated_at"),
422
+ "no_op": True,
423
+ }
424
+ print(json.dumps(summary, indent=2, ensure_ascii=False))
425
+ return
426
+
404
427
  fs["status"] = "completed"
405
428
  fs["resume_from_phase"] = None
406
429
  err = update_feature_in_list(feature_list_path, feature_id, "completed")
@@ -122,6 +122,7 @@ Key decisions: [list]
122
122
  --feature-id "{{FEATURE_ID}}" --session-id "{{SESSION_ID}}" --action complete
123
123
  ```
124
124
  - Run `prizmkit.committer` → `feat({{FEATURE_ID}}): {{FEATURE_TITLE}}`, do NOT push
125
+ - MANDATORY: commit must be done via `prizmkit.committer` skill. Do NOT run manual `git add`/`git commit` as a substitute.
125
126
 
126
127
  ---
127
128
 
@@ -154,6 +155,23 @@ Write to: `{{SESSION_STATUS_PATH}}`
154
155
  }
155
156
  ```
156
157
 
158
+ ### Step 3.1: Final Clean Check (before exit)
159
+
160
+ After writing `session-status.json`, verify repository is clean:
161
+
162
+ ```bash
163
+ git status --short
164
+ ```
165
+
166
+ If any files remain, include them in the last commit:
167
+
168
+ ```bash
169
+ git add -A
170
+ git commit --amend --no-edit
171
+ ```
172
+
173
+ Re-check `git status --short` and ensure it is empty before exiting.
174
+
157
175
  ## Critical Paths
158
176
 
159
177
  | Resource | Path |
@@ -168,4 +186,5 @@ Write to: `{{SESSION_STATUS_PATH}}`
168
186
  - Tier 1: you do everything — no subagents, no TeamCreate
169
187
  - Build context-snapshot.md FIRST; use it throughout instead of re-reading files
170
188
  - ALWAYS write session-status.json before exiting
171
- - `prizmkit.committer` is mandatory — do NOT skip the commit phase
189
+ - `prizmkit.committer` is mandatory — do NOT skip the commit phase, and do NOT replace it with manual git commit commands
190
+ - Before exiting, `git status --short` must be empty
@@ -148,6 +148,7 @@ Wait for Reviewer to return.
148
148
  --feature-id "{{FEATURE_ID}}" --session-id "{{SESSION_ID}}" --action complete
149
149
  ```
150
150
  - Run `prizmkit.committer` → `feat({{FEATURE_ID}}): {{FEATURE_TITLE}}`, do NOT push
151
+ - MANDATORY: commit must be done via `prizmkit.committer` skill. Do NOT run manual `git add`/`git commit` as a substitute.
151
152
 
152
153
  ---
153
154
 
@@ -180,6 +181,23 @@ Write to: `{{SESSION_STATUS_PATH}}`
180
181
  }
181
182
  ```
182
183
 
184
+ ### Step 3.1: Final Clean Check (before exit)
185
+
186
+ After writing `session-status.json`, verify repository is clean:
187
+
188
+ ```bash
189
+ git status --short
190
+ ```
191
+
192
+ If any files remain, include them in the last commit:
193
+
194
+ ```bash
195
+ git add -A
196
+ git commit --amend --no-edit
197
+ ```
198
+
199
+ Re-check `git status --short` and ensure it is empty before exiting.
200
+
183
201
  ## Critical Paths
184
202
 
185
203
  | Resource | Path |
@@ -197,5 +215,6 @@ Write to: `{{SESSION_STATUS_PATH}}`
197
215
  - Build context-snapshot.md FIRST; all subagents read it instead of re-reading source files
198
216
  - Do NOT use `run_in_background=true` when spawning subagents
199
217
  - ALWAYS write session-status.json before exiting
200
- - `prizmkit.committer` is mandatory
218
+ - `prizmkit.committer` is mandatory, and must not be replaced with manual git commit commands
219
+ - Before exiting, `git status --short` must be empty
201
220
  - On timeout: check snapshot → model:lite → remaining steps only → max 2 retries → orchestrator fallback
@@ -255,6 +255,8 @@ python3 {{VALIDATOR_SCRIPTS_DIR}}/update-feature-status.py \
255
255
 
256
256
  **7d.** Run `prizmkit.committer` → `feat({{FEATURE_ID}}): {{FEATURE_TITLE}}`, do NOT push
257
257
 
258
+ **7e.** MANDATORY: commit must be done via `prizmkit.committer` skill. Do NOT run manual `git add`/`git commit` as a substitute.
259
+
258
260
  ---
259
261
 
260
262
  ## Step 3: Write Session Status
@@ -287,6 +289,23 @@ Write to: `{{SESSION_STATUS_PATH}}`
287
289
  }
288
290
  ```
289
291
 
292
+ ### Step 3.1: Final Clean Check (before exit)
293
+
294
+ After writing `session-status.json`, verify repository is clean:
295
+
296
+ ```bash
297
+ git status --short
298
+ ```
299
+
300
+ If any files remain, include them in the last commit:
301
+
302
+ ```bash
303
+ git add -A
304
+ git commit --amend --no-edit
305
+ ```
306
+
307
+ Re-check `git status --short` and ensure it is empty before exiting.
308
+
290
309
  ## Step 4: Team Cleanup
291
310
 
292
311
  No team cleanup needed — agents were spawned directly without TeamCreate.
@@ -311,4 +330,6 @@ No team cleanup needed — agents were spawned directly without TeamCreate.
311
330
  - context-snapshot.md is the team knowledge base: PM writes it once, all agents read it
312
331
  - Do NOT use `run_in_background=true` when spawning agents
313
332
  - ALWAYS write session-status.json before exiting
333
+ - Commit phase must use `prizmkit.committer`; do NOT replace with manual git commit commands
334
+ - Before exiting, `git status --short` must be empty
314
335
  - On timeout: check snapshot → model:lite → remaining steps only → max 2 retries → orchestrator fallback
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prizmkit",
3
- "version": "1.0.12",
3
+ "version": "1.0.13",
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": {