prizmkit 1.0.9 → 1.0.11

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.9",
3
- "bundledAt": "2026-03-11T17:48:07.887Z",
4
- "bundledFrom": "41d8286"
2
+ "frameworkVersion": "1.0.11",
3
+ "bundledAt": "2026-03-12T14:05:37.316Z",
4
+ "bundledFrom": "6a1f70b"
5
5
  }
@@ -166,8 +166,18 @@ detect_stream_json_support() {
166
166
  local cli_cmd="$1"
167
167
  USE_STREAM_JSON="false"
168
168
 
169
- # Try to detect support via --help output
170
- if "$cli_cmd" --help 2>&1 | grep -q "stream-json" 2>/dev/null; then
169
+ # CodeBuddy (cbc) always supports stream-json
170
+ if [[ "$cli_cmd" == "cbc" ]]; then
171
+ USE_STREAM_JSON="true"
172
+ return 0
173
+ fi
174
+
175
+ # For other CLIs, try to detect support via --help output
176
+ # Use explicit file descriptor to avoid issues in background processes
177
+ local help_output
178
+ help_output=$("$cli_cmd" --help 2>&1) || true
179
+
180
+ if echo "$help_output" | grep -q "stream-json"; then
171
181
  USE_STREAM_JSON="true"
172
182
  fi
173
183
  }
@@ -202,6 +202,13 @@ if [[ "$USE_STREAM_JSON" == "true" ]]; then
202
202
  STREAM_JSON_FLAG="--output-format stream-json"
203
203
  fi
204
204
 
205
+ # Mark feature as in-progress before spawning session
206
+ python3 "$SCRIPTS_DIR/update-feature-status.py" \
207
+ --feature-list "$FEATURE_LIST" \
208
+ --state-dir "$STATE_DIR" \
209
+ --feature-id "$FEATURE_ID" \
210
+ --action start >/dev/null 2>&1 || true
211
+
205
212
  # Spawn AI CLI session
206
213
  case "$CLI_CMD" in
207
214
  *claude*)
@@ -516,6 +516,13 @@ sys.exit(1)
516
516
  return 0
517
517
  fi
518
518
 
519
+ # Mark feature as in-progress before spawning session
520
+ python3 "$SCRIPTS_DIR/update-feature-status.py" \
521
+ --feature-list "$feature_list" \
522
+ --state-dir "$STATE_DIR" \
523
+ --feature-id "$feature_id" \
524
+ --action start >/dev/null 2>&1 || true
525
+
519
526
  # Spawn AI CLI Session
520
527
  echo ""
521
528
  echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
@@ -729,6 +736,13 @@ with open(os.path.join(state_dir, 'current-session.json'), 'w') as f:
729
736
  json.dump(data, f, indent=2)
730
737
  " "$feature_id" "$session_id" "$STATE_DIR"
731
738
 
739
+ # Mark feature as in-progress before spawning session
740
+ python3 "$SCRIPTS_DIR/update-feature-status.py" \
741
+ --feature-list "$feature_list" \
742
+ --state-dir "$STATE_DIR" \
743
+ --feature-id "$feature_id" \
744
+ --action start >/dev/null 2>&1 || true
745
+
732
746
  # Spawn session and wait
733
747
  log_info "Spawning AI CLI session: $session_id"
734
748
  _SPAWN_RESULT=""
@@ -428,6 +428,7 @@ def build_replacements(args, feature, features, global_context, script_dir):
428
428
  "{{RUN_ID}}": args.run_id,
429
429
  "{{SESSION_ID}}": args.session_id,
430
430
  "{{FEATURE_ID}}": args.feature_id,
431
+ "{{FEATURE_LIST_PATH}}": os.path.abspath(args.feature_list),
431
432
  "{{FEATURE_TITLE}}": feature.get("title", ""),
432
433
  "{{RETRY_COUNT}}": str(args.retry_count),
433
434
  "{{MAX_RETRIES}}": str(DEFAULT_MAX_RETRIES),
@@ -1,8 +1,9 @@
1
1
  #!/usr/bin/env python3
2
2
  """Core state machine for updating feature status in the dev-pipeline.
3
3
 
4
- Handles seven actions:
4
+ Handles eight actions:
5
5
  - get_next: Find the next feature to process based on priority and dependencies
6
+ - start: Mark a feature as in_progress when a session starts
6
7
  - update: Update a feature's status based on session outcome
7
8
  - status: Print a formatted overview of all features
8
9
  - pause: Save pipeline state for graceful shutdown
@@ -13,7 +14,7 @@ Handles seven actions:
13
14
  Usage:
14
15
  python3 update-feature-status.py \
15
16
  --feature-list <path> --state-dir <path> \
16
- --action <get_next|update|status|pause|reset|clean|complete> \
17
+ --action <get_next|start|update|status|pause|reset|clean|complete> \
17
18
  [--feature-id <id>] [--session-status <status>] \
18
19
  [--session-id <id>] [--max-retries <n>]
19
20
  """
@@ -63,13 +64,13 @@ def parse_args():
63
64
  parser.add_argument(
64
65
  "--action",
65
66
  required=True,
66
- choices=["get_next", "update", "status", "pause", "reset", "clean", "complete"],
67
+ choices=["get_next", "start", "update", "status", "pause", "reset", "clean", "complete"],
67
68
  help="Action to perform",
68
69
  )
69
70
  parser.add_argument(
70
71
  "--feature-id",
71
72
  default=None,
72
- help="Feature ID (required for 'update' action)",
73
+ help="Feature ID (required for start/reset/clean/complete/update actions)",
73
74
  )
74
75
  parser.add_argument(
75
76
  "--session-status",
@@ -767,6 +768,47 @@ def action_status(feature_list_data, state_dir):
767
768
  print("╚" + "═" * BOX_WIDTH + "╝")
768
769
 
769
770
 
771
+ # ---------------------------------------------------------------------------
772
+ # Action: start
773
+ # ---------------------------------------------------------------------------
774
+
775
+ def action_start(args, feature_list_path, state_dir):
776
+ """Mark a feature as in_progress at session start.
777
+
778
+ This keeps feature-list.json/state status in sync during execution,
779
+ instead of only updating after session end.
780
+ """
781
+ feature_id = args.feature_id
782
+ if not feature_id:
783
+ error_out("--feature-id is required for 'start' action")
784
+ return
785
+
786
+ fs = load_feature_status(state_dir, feature_id)
787
+ old_status = fs.get("status", "pending")
788
+
789
+ fs["status"] = "in_progress"
790
+ fs["updated_at"] = now_iso()
791
+
792
+ err = save_feature_status(state_dir, feature_id, fs)
793
+ if err:
794
+ error_out("Failed to save feature status: {}".format(err))
795
+ return
796
+
797
+ err = update_feature_in_list(feature_list_path, feature_id, "in_progress")
798
+ if err:
799
+ error_out("Failed to update feature-list.json: {}".format(err))
800
+ return
801
+
802
+ result = {
803
+ "action": "start",
804
+ "feature_id": feature_id,
805
+ "old_status": old_status,
806
+ "new_status": "in_progress",
807
+ "updated_at": fs["updated_at"],
808
+ }
809
+ print(json.dumps(result, indent=2, ensure_ascii=False))
810
+
811
+
770
812
  # ---------------------------------------------------------------------------
771
813
  # Action: reset
772
814
  # ---------------------------------------------------------------------------
@@ -964,7 +1006,7 @@ def main():
964
1006
  error_out("--feature-id is required for 'update' action")
965
1007
  if not args.session_status:
966
1008
  error_out("--session-status is required for 'update' action")
967
- if args.action in ("reset", "clean", "complete"):
1009
+ if args.action in ("start", "reset", "clean", "complete"):
968
1010
  if not args.feature_id:
969
1011
  error_out("--feature-id is required for '{}' action".format(args.action))
970
1012
  if args.action == "clean":
@@ -981,6 +1023,8 @@ def main():
981
1023
  # Dispatch action
982
1024
  if args.action == "get_next":
983
1025
  action_get_next(feature_list_data, args.state_dir)
1026
+ elif args.action == "start":
1027
+ action_start(args, args.feature_list, args.state_dir)
984
1028
  elif args.action == "update":
985
1029
  action_update(args, args.feature_list, args.state_dir)
986
1030
  elif args.action == "status":
@@ -191,7 +191,17 @@ This is a **resume** from Phase {{RESUME_PHASE}}. After completing the team setu
191
191
 
192
192
  **7a.** Run `prizmkit.summarize` (invoke the prizmkit-summarize skill) → archive to REGISTRY.md
193
193
 
194
- **7b.** Run `prizmkit.committer` (invoke the prizmkit-committer skill) `feat({{FEATURE_ID}}): {{FEATURE_TITLE}}`, do NOT push
194
+ **7b.** BEFORE commit, mark current feature as completed in feature-list:
195
+ ```bash
196
+ python3 {{VALIDATOR_SCRIPTS_DIR}}/update-feature-status.py \
197
+ --feature-list "{{FEATURE_LIST_PATH}}" \
198
+ --state-dir "{{PROJECT_ROOT}}/dev-pipeline/state" \
199
+ --feature-id "{{FEATURE_ID}}" \
200
+ --session-id "{{SESSION_ID}}" \
201
+ --action complete
202
+ ```
203
+
204
+ **7c.** Run `prizmkit.committer` (invoke the prizmkit-committer skill) → `feat({{FEATURE_ID}}): {{FEATURE_TITLE}}`, do NOT push
195
205
 
196
206
  ### Step 3: Report Session Status
197
207
 
@@ -248,6 +258,7 @@ TeamDelete
248
258
  | Reviewer Agent Def | {{REVIEWER_SUBAGENT_PATH}} |
249
259
  | Session Status Output | {{SESSION_STATUS_PATH}} |
250
260
  | Project Root | {{PROJECT_ROOT}} |
261
+ | Feature List Path | {{FEATURE_LIST_PATH}} |
251
262
 
252
263
  ## Reminders
253
264
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prizmkit",
3
- "version": "1.0.9",
3
+ "version": "1.0.11",
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": {