prizmkit 1.0.99 → 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.
- package/bundled/VERSION.json +3 -3
- package/bundled/dev-pipeline/launch-daemon.sh +29 -4
- package/bundled/dev-pipeline/run.sh +43 -6
- package/bundled/dev-pipeline/scripts/update-feature-status.py +70 -8
- package/bundled/skills/_metadata.json +1 -1
- package/bundled/skills/dev-pipeline-launcher/SKILL.md +39 -1
- package/bundled/skills/prizmkit-init/SKILL.md +3 -3
- package/bundled/skills/prizmkit-prizm-docs/SKILL.md +1 -1
- package/bundled/skills/prizmkit-prizm-docs/assets/PRIZM-SPEC.md +8 -8
- package/package.json +1 -1
package/bundled/VERSION.json
CHANGED
|
@@ -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
|
-
|
|
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]
|
|
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
|
-
|
|
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.
|
|
294
|
-
3.
|
|
295
|
-
4.
|
|
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":
|
|
@@ -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:
|
|
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
|
|
|
@@ -43,10 +43,10 @@ BROWNFIELD WORKFLOW (existing project):
|
|
|
43
43
|
**Step 1: Project Scanning**
|
|
44
44
|
1. Detect tech stack from build files (`package.json`, `requirements.txt`, `go.mod`, `pom.xml`, `Cargo.toml`, etc.)
|
|
45
45
|
2. Map directory structure using a TWO-TIER model — flat structures lose the nesting relationships that AI needs to navigate the codebase:
|
|
46
|
-
- TOP-LEVEL modules: directories directly under project root that contain source files or sub-directories with source files (e.g. `
|
|
47
|
-
- SUB-MODULES: directories INSIDE a top-level module (e.g. `
|
|
46
|
+
- TOP-LEVEL modules: directories directly under project root that contain source files or sub-directories with source files (e.g. `src/`, `internal/`, `lib/`)
|
|
47
|
+
- SUB-MODULES: directories INSIDE a top-level module (e.g. `src/routes/`, `src/models/`)
|
|
48
48
|
- A sub-module maps to `.prizm-docs/<M>/<S>.prizm`, never to `.prizm-docs/<S>.prizm` — flattening would create ambiguous paths when two modules have identically-named sub-modules
|
|
49
|
-
- Exclude: `.git/`, `node_modules/`, `vendor/`, `build/`, `dist/`, `__pycache__/`, `.claude/`, `.codebuddy/`, `.prizmkit/`, `.prizm-docs/`
|
|
49
|
+
- Exclude: `.git/`, `node_modules/`, `vendor/`, `build/`, `dist/`, `__pycache__/`, `target/`, `bin/`, `.claude/`, `.codebuddy/`, `.prizmkit/`, `.prizm-docs/`, `dev-pipeline/`
|
|
50
50
|
3. Identify entry points by language convention
|
|
51
51
|
4. Catalog dependencies (external packages)
|
|
52
52
|
5. Count source files per directory
|
|
@@ -48,7 +48,7 @@ STEPS:
|
|
|
48
48
|
- TOP-LEVEL modules: directories directly under project root (or under src/ for src-based layouts) that contain 3+ source files OR contain sub-directories with 3+ source files. These go into MODULE_INDEX.
|
|
49
49
|
- SUB-MODULES: directories INSIDE a top-level module that contain 3+ source files. Listed in the parent L1 doc's SUBDIRS section only.
|
|
50
50
|
- HIERARCHY RULE: directory X inside top-level module M maps to .prizm-docs/<M>/<X>.prizm, never to .prizm-docs/<X>.prizm.
|
|
51
|
-
- Exclude
|
|
51
|
+
- Exclude .git/, node_modules/, vendor/, build/, dist/, __pycache__/, target/, bin/, .claude/, .codebuddy/, .prizmkit/, .prizm-docs/, dev-pipeline/. If top-level module count > 30, ask user for include/exclude patterns.
|
|
52
52
|
3. Create .prizm-docs/ directory structure mirroring the source tree exactly. For each top-level module M that has sub-modules, create the subdirectory .prizm-docs/<M>/.
|
|
53
53
|
4. Generate root.prizm (L0) with PROJECT, LANG, FRAMEWORK, BUILD, TEST, ENTRY, MODULE_INDEX listing only top-level modules with arrow pointers to .prizm-docs/<M>.prizm (sub-modules stay out of MODULE_INDEX to keep L0 compact and within the 4KB limit), RULES extracted from CODEBUDDY.md/CLAUDE.md/README/linter configs, and PATTERNS. Set PRIZM_VERSION: 2, UPDATED: today's date. Max 4KB.
|
|
54
54
|
5. Generate L1 .prizm files for ALL modules (top-level and sub-modules), each at its correct mirrored path:
|
|
@@ -479,19 +479,19 @@ STEPS:
|
|
|
479
479
|
a. IDENTIFY TOP-LEVEL modules: directories directly under project root (or directly under src/ for src-based layouts) that either:
|
|
480
480
|
- Contain 3+ source files of the primary language, OR
|
|
481
481
|
- Contain sub-directories that each have 3+ source files
|
|
482
|
-
RESULT: top_modules = [
|
|
482
|
+
RESULT: top_modules = [src, internal, app, lib, ...]
|
|
483
483
|
|
|
484
484
|
b. IDENTIFY SUB-MODULES: for each top-level module M, find directories INSIDE M that contain 3+ source files
|
|
485
485
|
RESULT: sub_modules[M] = [scripts, lib, templates, ...] (relative names, not full paths)
|
|
486
486
|
|
|
487
487
|
c. HIERARCHY RULE: if directory X lives inside top-level module M, X is a sub-module of M — NOT a separate top-level module.
|
|
488
|
-
WRONG:
|
|
489
|
-
CORRECT:
|
|
488
|
+
WRONG: src/routes/ treated as top-level module -> .prizm-docs/routes.prizm
|
|
489
|
+
CORRECT: src/routes/ is a sub-module of src -> .prizm-docs/src/routes.prizm
|
|
490
490
|
|
|
491
491
|
d. MODULE_INDEX in root.prizm lists ONLY top-level modules from step 2a.
|
|
492
492
|
Sub-modules appear in their parent's L1 doc SUBDIRS section, not in MODULE_INDEX.
|
|
493
493
|
|
|
494
|
-
- EXCLUDE:
|
|
494
|
+
- EXCLUDE: .git/, node_modules/, vendor/, build/, dist/, __pycache__/, target/, bin/, .claude/, .codebuddy/, .prizmkit/, .prizm-docs/, dev-pipeline/
|
|
495
495
|
IF top-level module count > 30: ASK user for include/exclude patterns
|
|
496
496
|
|
|
497
497
|
3. CREATE_DIRECTORY_STRUCTURE:
|
|
@@ -499,10 +499,10 @@ STEPS:
|
|
|
499
499
|
For each top-level module M that has sub-modules: create .prizm-docs/<M>/ directory
|
|
500
500
|
RULE: .prizm-docs/ directory tree must mirror the source directory tree exactly
|
|
501
501
|
EXAMPLE:
|
|
502
|
-
source:
|
|
503
|
-
source:
|
|
504
|
-
source:
|
|
505
|
-
NEVER create .prizm-docs/
|
|
502
|
+
source: src/routes/ -> prizm: .prizm-docs/src/routes.prizm
|
|
503
|
+
source: src/models/ -> prizm: .prizm-docs/src/models.prizm
|
|
504
|
+
source: src/ -> prizm: .prizm-docs/src.prizm
|
|
505
|
+
NEVER create .prizm-docs/routes.prizm for a directory that lives at src/routes/
|
|
506
506
|
|
|
507
507
|
4. GENERATE_ROOT (L0):
|
|
508
508
|
Fill: PROJECT, LANG, FRAMEWORK, BUILD, TEST, ENTRY from step 1
|