prizmkit 1.0.100 → 1.0.101

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.100",
3
- "bundledAt": "2026-03-23T15:20:23.258Z",
4
- "bundledFrom": "e0c5380"
2
+ "frameworkVersion": "1.0.101",
3
+ "bundledAt": "2026-03-23T16:44:31.127Z",
4
+ "bundledFrom": "7da7d80"
5
5
  }
@@ -93,6 +93,7 @@ cmd_start() {
93
93
  local feature_list=""
94
94
  local env_overrides=""
95
95
  local mode_override=""
96
+ local features_filter=""
96
97
 
97
98
  # Parse arguments
98
99
  while [[ $# -gt 0 ]]; do
@@ -123,6 +124,15 @@ cmd_start() {
123
124
  esac
124
125
  shift
125
126
  ;;
127
+ --features)
128
+ shift
129
+ if [[ $# -eq 0 ]]; then
130
+ log_error "--features requires a value (e.g. --features F-001,F-003 or --features F-001:F-010)"
131
+ exit 1
132
+ fi
133
+ features_filter="$1"
134
+ shift
135
+ ;;
126
136
  *)
127
137
  feature_list="$1"
128
138
  shift
@@ -199,6 +209,9 @@ cmd_start() {
199
209
  log_info "Launching pipeline..."
200
210
  log_info "Feature list: $feature_list"
201
211
  log_info "Log file: $LOG_FILE"
212
+ if [[ -n "$features_filter" ]]; then
213
+ log_info "Features filter: $features_filter"
214
+ fi
202
215
  if [[ -n "$mode_override" ]]; then
203
216
  log_info "Mode: $mode_override"
204
217
  fi
@@ -212,6 +225,9 @@ cmd_start() {
212
225
  echo "================================================================"
213
226
  echo " Pipeline Daemon Started: $start_time"
214
227
  echo " Feature list: $feature_list"
228
+ if [[ -n "$features_filter" ]]; then
229
+ echo " Features filter: $features_filter"
230
+ fi
215
231
  if [[ -n "$mode_override" ]]; then
216
232
  echo " Mode: $mode_override"
217
233
  fi
@@ -227,11 +243,17 @@ cmd_start() {
227
243
  # is inherited and blocks child claude processes with "nested sessions" error.
228
244
  unset CLAUDECODE 2>/dev/null || true
229
245
 
246
+ # Build features flag
247
+ local features_flag=""
248
+ if [[ -n "$features_filter" ]]; then
249
+ features_flag="--features $features_filter"
250
+ fi
251
+
230
252
  # Launch with nohup + disown for full detachment
231
253
  if [[ -n "$env_cmd" ]]; then
232
- nohup $env_cmd "$RUN_SCRIPT" run "$feature_list" >> "$LOG_FILE" 2>&1 &
254
+ nohup $env_cmd "$RUN_SCRIPT" run "$feature_list" $features_flag >> "$LOG_FILE" 2>&1 &
233
255
  else
234
- nohup "$RUN_SCRIPT" run "$feature_list" >> "$LOG_FILE" 2>&1 &
256
+ nohup "$RUN_SCRIPT" run "$feature_list" $features_flag >> "$LOG_FILE" 2>&1 &
235
257
  fi
236
258
  local pipeline_pid=$!
237
259
  disown "$pipeline_pid" 2>/dev/null || true
@@ -548,20 +570,23 @@ show_help() {
548
570
  Usage: launch-daemon.sh <command> [options]
549
571
 
550
572
  Commands:
551
- start [feature-list.json] [--mode <mode>] [--env "K=V ..."] Start pipeline in background
573
+ start [feature-list.json] [--mode <mode>] [--features <filter>] [--env "K=V ..."] Start pipeline in background
552
574
  stop Gracefully stop pipeline
553
575
  status Check if pipeline is running
554
576
  logs [--lines N] [--follow] View pipeline logs
555
- restart [feature-list.json] [--mode <mode>] [--env "K=V ..."] Stop + start pipeline
577
+ restart [feature-list.json] [--mode <mode>] [--features <filter>] [--env "K=V ..."] Stop + start pipeline
556
578
  help Show this help
557
579
 
558
580
  Options:
559
581
  --mode <lite|standard|full|self-evolve> Override pipeline mode for all features
582
+ --features <filter> Run only specified features (e.g. F-001,F-003 or F-001:F-010)
560
583
  --env "KEY=VAL ..." Set environment variables
561
584
 
562
585
  Examples:
563
586
  ./launch-daemon.sh start # Start with default feature-list.json
564
587
  ./launch-daemon.sh start my-features.json # Start with custom feature list
588
+ ./launch-daemon.sh start --features F-001:F-005 # Run only features F-001 through F-005
589
+ ./launch-daemon.sh start --features F-001,F-003,F-007 # Run specific features
565
590
  ./launch-daemon.sh start --mode self-evolve # Self-evolve mode (framework development)
566
591
  ./launch-daemon.sh start --env "MAX_RETRIES=5 SESSION_TIMEOUT=7200"
567
592
  ./launch-daemon.sh start feature-list.json --mode self-evolve --env "VERBOSE=1"
@@ -783,6 +783,7 @@ print(data.get('reload_needed', False))
783
783
 
784
784
  main() {
785
785
  local feature_list="${1:-feature-list.json}"
786
+ local features_filter="${2:-}"
786
787
 
787
788
  # Resolve to absolute path
788
789
  if [[ ! "$feature_list" = /* ]]; then
@@ -842,6 +843,9 @@ main() {
842
843
  echo -e "${BOLD} Dev-Pipeline Runner Started${NC}"
843
844
  echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
844
845
  log_info "Feature list: $feature_list"
846
+ if [[ -n "$features_filter" ]]; then
847
+ log_info "Features filter: $features_filter"
848
+ fi
845
849
  log_info "Max retries per feature: $MAX_RETRIES"
846
850
  if [[ $SESSION_TIMEOUT -gt 0 ]]; then
847
851
  log_info "Session timeout: ${SESSION_TIMEOUT}s"
@@ -889,11 +893,17 @@ for f in data.get('stuck_features', []):
889
893
 
890
894
  # Find next feature to process
891
895
  local next_feature
896
+ local _get_next_args=(
897
+ --feature-list "$feature_list"
898
+ --state-dir "$STATE_DIR"
899
+ --max-retries "$MAX_RETRIES"
900
+ --action get_next
901
+ )
902
+ if [[ -n "$features_filter" ]]; then
903
+ _get_next_args+=(--features "$features_filter")
904
+ fi
892
905
  next_feature=$(python3 "$SCRIPTS_DIR/update-feature-status.py" \
893
- --feature-list "$feature_list" \
894
- --state-dir "$STATE_DIR" \
895
- --max-retries "$MAX_RETRIES" \
896
- --action get_next 2>/dev/null) || true
906
+ "${_get_next_args[@]}" 2>/dev/null) || true
897
907
 
898
908
  if [[ "$next_feature" == "PIPELINE_COMPLETE" ]]; then
899
909
  echo ""
@@ -1060,13 +1070,18 @@ show_help() {
1060
1070
  echo "Usage: $0 <command> [options]"
1061
1071
  echo ""
1062
1072
  echo "Commands:"
1063
- echo " run [feature-list.json] Run all features sequentially"
1073
+ echo " run [feature-list.json] [--features <filter>] Run features (all or filtered subset)"
1064
1074
  echo " run <feature-id> [options] Run a single feature"
1065
1075
  echo " status [feature-list.json] Show pipeline status"
1066
1076
  echo " test-cli Test AI CLI: show detected CLI, version, and model"
1067
1077
  echo " reset Clear all state and start fresh"
1068
1078
  echo " help Show this help message"
1069
1079
  echo ""
1080
+ echo "Feature Filter (--features):"
1081
+ echo " --features F-001,F-003,F-005 Run only specified features"
1082
+ echo " --features F-001:F-010 Run a range of features (F-001 through F-010)"
1083
+ echo " --features F-001,F-005:F-010 Mixed: individual IDs + ranges"
1084
+ echo ""
1070
1085
  echo "Single Feature Options (run <feature-id>):"
1071
1086
  echo " --dry-run Generate bootstrap prompt only, don't spawn session"
1072
1087
  echo " --resume-phase N Override resume phase (default: auto-detect)"
@@ -1089,6 +1104,8 @@ show_help() {
1089
1104
  echo ""
1090
1105
  echo "Examples:"
1091
1106
  echo " ./run.sh run # Run all features"
1107
+ echo " ./run.sh run --features F-001,F-003,F-005 # Run specific features"
1108
+ echo " ./run.sh run --features F-001:F-010 # Run features F-001 through F-010"
1092
1109
  echo " ./run.sh run F-007 --dry-run # Inspect generated prompt"
1093
1110
  echo " ./run.sh run F-007 --dry-run --mode lite # Test lite mode"
1094
1111
  echo " ./run.sh run F-007 --resume-phase 6 # Skip to implementation"
@@ -1107,7 +1124,27 @@ case "${1:-run}" in
1107
1124
  if [[ "${1:-}" =~ ^[Ff]-[0-9]+ ]]; then
1108
1125
  run_one "$@"
1109
1126
  else
1110
- main "${1:-feature-list.json}"
1127
+ # Parse positional and --features flag
1128
+ local _run_feature_list="feature-list.json"
1129
+ local _run_features_filter=""
1130
+ while [[ $# -gt 0 ]]; do
1131
+ case "$1" in
1132
+ --features)
1133
+ shift
1134
+ if [[ $# -eq 0 ]]; then
1135
+ log_error "--features requires a value (e.g. --features F-001,F-003 or --features F-001:F-010)"
1136
+ exit 1
1137
+ fi
1138
+ _run_features_filter="$1"
1139
+ shift
1140
+ ;;
1141
+ *)
1142
+ _run_feature_list="$1"
1143
+ shift
1144
+ ;;
1145
+ esac
1146
+ done
1147
+ main "$_run_feature_list" "$_run_features_filter"
1111
1148
  fi
1112
1149
  ;;
1113
1150
  status)
@@ -16,7 +16,8 @@ Usage:
16
16
  --feature-list <path> --state-dir <path> \
17
17
  --action <get_next|start|update|status|pause|reset|clean|complete> \
18
18
  [--feature-id <id>] [--session-status <status>] \
19
- [--session-id <id>] [--max-retries <n>]
19
+ [--session-id <id>] [--max-retries <n>] \
20
+ [--features <filter>]
20
21
  """
21
22
 
22
23
  import argparse
@@ -102,9 +103,49 @@ def parse_args():
102
103
  default=None,
103
104
  help="Project root directory. Required for 'clean' action.",
104
105
  )
106
+ parser.add_argument(
107
+ "--features",
108
+ default=None,
109
+ help="Feature filter: comma-separated IDs (F-001,F-003) or range (F-001:F-010), or mixed.",
110
+ )
105
111
  return parser.parse_args()
106
112
 
107
113
 
114
+ def parse_feature_filter(features_str):
115
+ """Parse --features argument into a set of feature IDs.
116
+
117
+ Supported formats:
118
+ F-001,F-003,F-005 -> {"F-001", "F-003", "F-005"}
119
+ F-001:F-010 -> {"F-001", "F-002", ..., "F-010"}
120
+ F-001,F-005:F-010 -> mixed, union of both
121
+
122
+ Returns None if features_str is None/empty (meaning no filter).
123
+ """
124
+ if not features_str:
125
+ return None
126
+
127
+ result = set()
128
+ for part in features_str.split(","):
129
+ part = part.strip()
130
+ if not part:
131
+ continue
132
+ if ":" in part:
133
+ tokens = part.split(":", 1)
134
+ m_start = re.search(r"\d+", tokens[0])
135
+ m_end = re.search(r"\d+", tokens[1])
136
+ if not m_start or not m_end:
137
+ error_out("Invalid range format: {}".format(part))
138
+ start_num = int(m_start.group())
139
+ end_num = int(m_end.group())
140
+ if start_num > end_num:
141
+ start_num, end_num = end_num, start_num
142
+ for i in range(start_num, end_num + 1):
143
+ result.add("F-{:03d}".format(i))
144
+ else:
145
+ result.add(part.upper())
146
+ return result if result else None
147
+
148
+
108
149
  def now_iso():
109
150
  """Return the current UTC time in ISO8601 format."""
110
151
  return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
@@ -285,20 +326,31 @@ def load_session_status(state_dir, feature_id, session_id):
285
326
  # Action: get_next
286
327
  # ---------------------------------------------------------------------------
287
328
 
288
- def action_get_next(feature_list_data, state_dir):
329
+ def action_get_next(feature_list_data, state_dir, feature_filter=None):
289
330
  """Find the next feature to process.
290
331
 
291
332
  Priority logic:
292
333
  1. Skip terminal statuses (completed, failed, skipped)
293
- 2. Check that all dependencies are completed
294
- 3. Prefer in_progress features over pending ones (interrupted session resume)
295
- 4. Among eligible features, pick lowest priority number (highest priority)
334
+ 2. If feature_filter is set, skip features not in the filter
335
+ 3. Check that all dependencies are completed
336
+ 4. Prefer in_progress features over pending ones (interrupted session resume)
337
+ 5. Among eligible features, pick lowest priority number (highest priority)
296
338
  """
297
339
  features = feature_list_data.get("features", [])
298
340
  if not features:
299
341
  print("PIPELINE_COMPLETE")
300
342
  return
301
343
 
344
+ # Apply feature filter: only consider features in the whitelist
345
+ if feature_filter is not None:
346
+ features = [
347
+ f for f in features
348
+ if isinstance(f, dict) and f.get("id") in feature_filter
349
+ ]
350
+ if not features:
351
+ print("PIPELINE_COMPLETE")
352
+ return
353
+
302
354
  # Build a map of feature statuses from state dir
303
355
  status_map = {} # feature_id -> status string
304
356
  status_data_map = {} # feature_id -> full status data
@@ -678,7 +730,7 @@ def _estimate_remaining_time(features, state_dir, counts, feature_list_data=None
678
730
  return remaining_seconds, confidence
679
731
 
680
732
 
681
- def action_status(feature_list_data, state_dir):
733
+ def action_status(feature_list_data, state_dir, feature_filter=None):
682
734
  """Print a formatted overview of all features and their status.
683
735
 
684
736
  Status is read exclusively from feature-list.json (the single source of
@@ -688,6 +740,13 @@ def action_status(feature_list_data, state_dir):
688
740
  features = feature_list_data.get("features", [])
689
741
  app_name = feature_list_data.get("app_name", "Unknown")
690
742
 
743
+ # Apply feature filter
744
+ if feature_filter is not None:
745
+ features = [
746
+ f for f in features
747
+ if isinstance(f, dict) and f.get("id") in feature_filter
748
+ ]
749
+
691
750
  # Gather status info
692
751
  counts = {
693
752
  "completed": 0,
@@ -1080,15 +1139,18 @@ def main():
1080
1139
  if err:
1081
1140
  error_out("Cannot load feature list: {}".format(err))
1082
1141
 
1142
+ # Parse feature filter (used by get_next and status)
1143
+ feature_filter = parse_feature_filter(args.features)
1144
+
1083
1145
  # Dispatch action
1084
1146
  if args.action == "get_next":
1085
- action_get_next(feature_list_data, args.state_dir)
1147
+ action_get_next(feature_list_data, args.state_dir, feature_filter)
1086
1148
  elif args.action == "start":
1087
1149
  action_start(args, args.feature_list, args.state_dir)
1088
1150
  elif args.action == "update":
1089
1151
  action_update(args, args.feature_list, args.state_dir)
1090
1152
  elif args.action == "status":
1091
- action_status(feature_list_data, args.state_dir)
1153
+ action_status(feature_list_data, args.state_dir, feature_filter)
1092
1154
  elif args.action == "reset":
1093
1155
  action_reset(args, args.feature_list, args.state_dir)
1094
1156
  elif args.action == "clean":
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.0.100",
2
+ "version": "1.0.101",
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.",
@@ -28,6 +28,7 @@ Use daemon mode (`launch-daemon.sh`) only when:
28
28
  - "launch pipeline", "start implementing", "run the pipeline", "start auto-development"
29
29
  - "implement next steps", "execute feature list", "start building"
30
30
  - After app-planner completes: "build it", "start developing from the feature list"
31
+ - "run only F-001 to F-005", "run features F-001,F-003", "only build these features"
31
32
 
32
33
  **Check status** -- User says:
33
34
  - "pipeline status", "check pipeline", "how's it going", "progress"
@@ -117,11 +118,20 @@ Detect user intent from their message, then follow the corresponding workflow:
117
118
  ```bash
118
119
  dev-pipeline/run.sh run feature-list.json
119
120
  ```
121
+ If user wants to run only specific features:
122
+ ```bash
123
+ dev-pipeline/run.sh run feature-list.json --features F-001:F-005
124
+ dev-pipeline/run.sh run feature-list.json --features F-001,F-003,F-007
125
+ ```
120
126
 
121
127
  **If option 2 (background)**:
122
128
  ```bash
123
129
  dev-pipeline/launch-daemon.sh start feature-list.json
124
130
  ```
131
+ With feature filter:
132
+ ```bash
133
+ dev-pipeline/launch-daemon.sh start feature-list.json --features F-001:F-005
134
+ ```
125
135
  Note: Pipeline runs fully detached. Survives session closure.
126
136
 
127
137
  **If option 3 (manual)**: Print commands and stop. Do not execute anything.
@@ -251,7 +261,35 @@ dev-pipeline/launch-daemon.sh start feature-list.json --env "SESSION_TIMEOUT=720
251
261
 
252
262
  ---
253
263
 
254
- #### Intent F: Retry Single Feature Node
264
+ #### Intent F: Run Subset of Features
265
+
266
+ When user says "run only F-001 to F-005", "only build features 1 through 5":
267
+
268
+ ```bash
269
+ dev-pipeline/run.sh run feature-list.json --features F-001:F-005
270
+ ```
271
+
272
+ When user says "run F-001, F-003, and F-007", "only build these three features":
273
+
274
+ ```bash
275
+ dev-pipeline/run.sh run feature-list.json --features F-001,F-003,F-007
276
+ ```
277
+
278
+ Mixed format (IDs + ranges):
279
+
280
+ ```bash
281
+ dev-pipeline/run.sh run feature-list.json --features F-001,F-005:F-010
282
+ ```
283
+
284
+ Background daemon with feature filter:
285
+
286
+ ```bash
287
+ dev-pipeline/launch-daemon.sh start feature-list.json --features F-001:F-005
288
+ ```
289
+
290
+ ---
291
+
292
+ #### Intent G: Retry Single Feature Node
255
293
 
256
294
  When user says "retry F-003":
257
295
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prizmkit",
3
- "version": "1.0.100",
3
+ "version": "1.0.101",
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": {