prizmkit 1.1.8 → 1.1.9
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/adapters/codebuddy/skill-adapter.js +21 -7
- package/bundled/agents/prizm-dev-team-reviewer.md +53 -173
- package/bundled/dev-pipeline/.env.example +45 -0
- package/bundled/dev-pipeline/SCHEMA_ANALYSIS.md +535 -0
- package/bundled/dev-pipeline/assets/feature-list-example.json +0 -1
- package/bundled/dev-pipeline/launch-bugfix-daemon.sh +57 -12
- package/bundled/dev-pipeline/launch-feature-daemon.sh +3 -1
- package/bundled/dev-pipeline/launch-refactor-daemon.sh +57 -12
- package/bundled/dev-pipeline/lib/branch.sh +6 -1
- package/bundled/dev-pipeline/lib/common.sh +71 -0
- package/bundled/dev-pipeline/lib/heartbeat.sh +2 -2
- package/bundled/dev-pipeline/retry-bugfix.sh +60 -23
- package/bundled/dev-pipeline/retry-feature.sh +47 -12
- package/bundled/dev-pipeline/retry-refactor.sh +105 -23
- package/bundled/dev-pipeline/run-bugfix.sh +265 -44
- package/bundled/dev-pipeline/run-feature.sh +35 -1
- package/bundled/dev-pipeline/run-refactor.sh +376 -51
- package/bundled/dev-pipeline/scripts/check-session-status.py +24 -1
- package/bundled/dev-pipeline/scripts/detect-stuck.py +195 -85
- package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +31 -19
- package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +19 -3
- package/bundled/dev-pipeline/scripts/generate-refactor-prompt.py +98 -11
- package/bundled/dev-pipeline/scripts/init-bugfix-pipeline.py +30 -5
- package/bundled/dev-pipeline/scripts/init-pipeline.py +3 -3
- package/bundled/dev-pipeline/scripts/init-refactor-pipeline.py +15 -4
- package/bundled/dev-pipeline/scripts/parse-stream-progress.py +1 -5
- package/bundled/dev-pipeline/scripts/patch-completion-notes.py +191 -0
- package/bundled/dev-pipeline/scripts/update-bug-status.py +159 -14
- package/bundled/dev-pipeline/scripts/update-feature-status.py +79 -37
- package/bundled/dev-pipeline/scripts/update-refactor-status.py +343 -13
- package/bundled/dev-pipeline/templates/agent-prompts/dev-fix.md +1 -1
- package/bundled/dev-pipeline/templates/agent-prompts/reviewer-review.md +7 -11
- package/bundled/dev-pipeline/templates/bootstrap-prompt.md +41 -7
- package/bundled/dev-pipeline/templates/bootstrap-tier1.md +27 -3
- package/bundled/dev-pipeline/templates/bootstrap-tier2.md +43 -19
- package/bundled/dev-pipeline/templates/bootstrap-tier3.md +54 -26
- package/bundled/dev-pipeline/templates/bug-fix-list-schema.json +5 -14
- package/bundled/dev-pipeline/templates/bugfix-bootstrap-prompt.md +36 -25
- package/bundled/dev-pipeline/templates/feature-list-schema.json +23 -11
- package/bundled/dev-pipeline/templates/refactor-bootstrap-prompt.md +270 -0
- package/bundled/dev-pipeline/templates/refactor-list-schema.json +10 -2
- package/bundled/dev-pipeline/templates/sections/context-budget-rules.md +3 -1
- package/bundled/dev-pipeline/templates/sections/critical-paths-agent.md +1 -0
- package/bundled/dev-pipeline/templates/sections/feature-context.md +2 -0
- package/bundled/dev-pipeline/templates/sections/phase-commit-full.md +29 -2
- package/bundled/dev-pipeline/templates/sections/phase-commit.md +22 -0
- package/bundled/dev-pipeline/templates/sections/phase-deploy-verification.md +2 -2
- package/bundled/dev-pipeline/templates/sections/phase-review-agent.md +8 -6
- package/bundled/dev-pipeline/templates/sections/phase-review-full.md +7 -5
- package/bundled/dev-pipeline/templates/sections/phase-specify-plan-full.md +3 -3
- package/bundled/skills/_metadata.json +5 -22
- package/bundled/skills/app-planner/SKILL.md +92 -66
- package/bundled/skills/app-planner/assets/app-design-guide.md +1 -1
- package/bundled/skills/app-planner/references/architecture-decisions.md +1 -1
- package/bundled/skills/app-planner/references/project-brief-guide.md +69 -66
- package/bundled/skills/bug-fix-workflow/SKILL.md +47 -4
- package/bundled/skills/bug-planner/SKILL.md +130 -188
- package/bundled/skills/bug-planner/assets/bug-confirmation-template.md +43 -0
- package/bundled/skills/bug-planner/references/critic-and-verification.md +44 -0
- package/bundled/skills/bug-planner/references/error-recovery.md +73 -0
- package/bundled/skills/bug-planner/references/input-formats.md +53 -0
- package/bundled/skills/bug-planner/references/schema-validation.md +25 -0
- package/bundled/skills/bug-planner/references/severity-rules.md +16 -0
- package/bundled/skills/bug-planner/scripts/validate-bug-list.py +1 -5
- package/bundled/skills/bugfix-pipeline-launcher/SKILL.md +5 -10
- package/bundled/skills/feature-pipeline-launcher/SKILL.md +16 -3
- package/bundled/skills/feature-planner/SKILL.md +33 -122
- package/bundled/skills/feature-planner/assets/evaluation-guide.md +1 -1
- package/bundled/skills/feature-planner/assets/planning-guide.md +21 -5
- package/bundled/skills/feature-planner/references/browser-interaction.md +2 -4
- package/bundled/skills/feature-planner/references/completeness-review.md +57 -0
- package/bundled/skills/feature-planner/references/error-recovery.md +15 -34
- package/bundled/skills/feature-planner/references/incremental-feature-planning.md +1 -1
- package/bundled/skills/feature-planner/references/new-project-planning.md +2 -2
- package/bundled/skills/feature-planner/scripts/validate-and-generate.py +1 -2
- package/bundled/skills/feature-workflow/SKILL.md +3 -4
- package/bundled/skills/prizm-kit/SKILL.md +39 -49
- package/bundled/skills/prizmkit-code-review/SKILL.md +51 -64
- package/bundled/skills/prizmkit-code-review/rules/dimensions.md +85 -0
- package/bundled/skills/prizmkit-code-review/rules/fix-strategy.md +11 -11
- package/bundled/skills/prizmkit-committer/SKILL.md +3 -31
- package/bundled/skills/prizmkit-deploy/SKILL.md +34 -31
- package/bundled/skills/prizmkit-deploy/assets/deploy-template.md +1 -1
- package/bundled/skills/prizmkit-implement/SKILL.md +35 -68
- package/bundled/skills/prizmkit-init/SKILL.md +112 -65
- package/bundled/skills/prizmkit-init/assets/project-brief-template.md +82 -0
- package/bundled/skills/prizmkit-plan/SKILL.md +120 -79
- package/bundled/skills/prizmkit-plan/assets/plan-template.md +28 -18
- package/bundled/skills/prizmkit-plan/assets/spec-template.md +28 -11
- package/bundled/skills/prizmkit-plan/references/clarify-guide.md +3 -3
- package/bundled/skills/prizmkit-plan/references/verification-checklist.md +60 -0
- package/bundled/skills/prizmkit-prizm-docs/SKILL.md +10 -81
- package/bundled/skills/prizmkit-prizm-docs/assets/{PRIZM-SPEC.md → prizm-docs-format.md} +41 -526
- package/bundled/skills/prizmkit-prizm-docs/references/op-init.md +46 -0
- package/bundled/skills/prizmkit-prizm-docs/references/op-rebuild.md +16 -0
- package/bundled/skills/prizmkit-prizm-docs/references/op-status.md +14 -0
- package/bundled/skills/prizmkit-prizm-docs/references/op-update.md +19 -0
- package/bundled/skills/prizmkit-prizm-docs/references/op-validate.md +17 -0
- package/bundled/skills/prizmkit-retrospective/SKILL.md +27 -65
- package/bundled/skills/prizmkit-retrospective/references/knowledge-injection-steps.md +3 -4
- package/bundled/skills/prizmkit-retrospective/references/structural-sync-steps.md +7 -25
- package/bundled/skills/recovery-workflow/SKILL.md +8 -8
- package/bundled/skills/refactor-pipeline-launcher/SKILL.md +17 -9
- package/bundled/skills/refactor-planner/SKILL.md +23 -41
- package/bundled/skills/refactor-workflow/SKILL.md +1 -2
- package/bundled/team/prizm-dev-team.json +1 -1
- package/bundled/{skills/prizm-kit/assets → templates}/project-memory-template.md +1 -1
- package/package.json +1 -1
- package/src/clean.js +0 -1
- package/src/gitignore-template.js +0 -1
- package/src/scaffold.js +10 -3
- package/bundled/dev-pipeline/templates/agent-prompts/reviewer-analyze.md +0 -5
- package/bundled/dev-pipeline/templates/sections/phase-analyze-agent.md +0 -19
- package/bundled/dev-pipeline/templates/sections/phase-analyze-full.md +0 -19
- package/bundled/skills/app-planner/references/project-conventions.md +0 -93
- package/bundled/skills/prizmkit-analyze/SKILL.md +0 -207
- package/bundled/skills/prizmkit-code-review/rules/dimensions-bugfix.md +0 -25
- package/bundled/skills/prizmkit-code-review/rules/dimensions-feature.md +0 -43
- package/bundled/skills/prizmkit-code-review/rules/dimensions-refactor.md +0 -25
- package/bundled/skills/prizmkit-implement/references/deploy-guide-protocol.md +0 -69
- package/bundled/skills/prizmkit-verify/SKILL.md +0 -281
- package/bundled/skills/prizmkit-verify/scripts/verify-light.py +0 -402
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
"""Core state machine for updating refactor status in the refactor pipeline.
|
|
3
3
|
|
|
4
|
-
Handles
|
|
4
|
+
Handles eight actions:
|
|
5
5
|
- get_next: Find the next refactor to process based on dependency order, priority, complexity
|
|
6
|
+
- start: Mark a refactor as in_progress when a session starts
|
|
6
7
|
- update: Update a refactor's status based on session outcome
|
|
7
8
|
- status: Print a formatted overview of all refactors
|
|
8
9
|
- pause: Save pipeline state for graceful shutdown
|
|
9
10
|
- reset: Reset a refactor to pending (status + retry count)
|
|
10
11
|
- clean: Reset + delete session history + delete refactor artifacts
|
|
12
|
+
- unskip: Reset skipped refactors and their downstream dependents back to pending
|
|
11
13
|
|
|
12
14
|
Usage:
|
|
13
15
|
python3 update-refactor-status.py \
|
|
14
16
|
--refactor-list <path> --state-dir <path> \
|
|
15
|
-
--action <get_next|update|status|pause|reset|clean> \
|
|
17
|
+
--action <get_next|start|update|status|pause|reset|clean|unskip> \
|
|
16
18
|
[--refactor-id <id>] [--session-status <status>] \
|
|
17
19
|
[--session-id <id>] [--max-retries <n>]
|
|
18
20
|
"""
|
|
@@ -21,6 +23,7 @@ import argparse
|
|
|
21
23
|
import json
|
|
22
24
|
import os
|
|
23
25
|
import shutil
|
|
26
|
+
import sys
|
|
24
27
|
from datetime import datetime, timezone
|
|
25
28
|
|
|
26
29
|
from utils import (
|
|
@@ -39,10 +42,12 @@ SESSION_STATUS_VALUES = [
|
|
|
39
42
|
"failed",
|
|
40
43
|
"crashed",
|
|
41
44
|
"timed_out",
|
|
45
|
+
"commit_missing",
|
|
46
|
+
"docs_missing",
|
|
42
47
|
"merge_conflict",
|
|
43
48
|
]
|
|
44
49
|
|
|
45
|
-
TERMINAL_STATUSES = {"completed", "failed", "skipped"}
|
|
50
|
+
TERMINAL_STATUSES = {"completed", "failed", "skipped", "auto_skipped"}
|
|
46
51
|
|
|
47
52
|
# Artifact directory names (relative to project root)
|
|
48
53
|
REFACTOR_ARTIFACTS_REL = os.path.join(".prizmkit", "refactor")
|
|
@@ -72,7 +77,7 @@ def parse_args():
|
|
|
72
77
|
parser.add_argument("--state-dir", required=True, help="Path to the state directory (default: .prizmkit/state/refactor)")
|
|
73
78
|
parser.add_argument(
|
|
74
79
|
"--action", required=True,
|
|
75
|
-
choices=["get_next", "update", "status", "pause", "reset", "clean"],
|
|
80
|
+
choices=["get_next", "start", "update", "status", "pause", "reset", "clean", "unskip", "complete"],
|
|
76
81
|
help="Action to perform",
|
|
77
82
|
)
|
|
78
83
|
parser.add_argument("--refactor-id", default=None, help="Refactor ID (required for 'update'/'reset'/'clean' actions)")
|
|
@@ -272,16 +277,23 @@ def action_update(args, refactor_list_path, state_dir):
|
|
|
272
277
|
if err:
|
|
273
278
|
error_out("Failed to update .prizmkit/plans/refactor-list.json: {}".format(err))
|
|
274
279
|
return
|
|
275
|
-
elif session_status
|
|
280
|
+
elif session_status in ("commit_missing", "docs_missing", "merge_conflict"):
|
|
281
|
+
# Degraded outcome: keep artifacts for retry.
|
|
282
|
+
# Write schema-valid status to refactor-list.json ("pending" for retry,
|
|
283
|
+
# "failed" if max retries exceeded). Store the granular degraded reason
|
|
284
|
+
# in status.json only (internal pipeline state, not schema-bound).
|
|
276
285
|
rs["retry_count"] = rs.get("retry_count", 0) + 1
|
|
277
286
|
|
|
278
287
|
if rs["retry_count"] >= max_retries:
|
|
279
288
|
rs["status"] = "failed"
|
|
280
289
|
target_status = "failed"
|
|
281
290
|
else:
|
|
282
|
-
|
|
283
|
-
|
|
291
|
+
# status.json keeps the granular degraded reason for diagnostics
|
|
292
|
+
rs["status"] = session_status
|
|
293
|
+
# refactor-list.json gets schema-valid "pending" (will be retried)
|
|
294
|
+
target_status = "pending"
|
|
284
295
|
|
|
296
|
+
rs["degraded_reason"] = session_status
|
|
285
297
|
rs["resume_from_phase"] = None
|
|
286
298
|
rs["sessions"] = []
|
|
287
299
|
rs["last_session_id"] = None
|
|
@@ -329,6 +341,13 @@ def action_update(args, refactor_list_path, state_dir):
|
|
|
329
341
|
error_out("Failed to save refactor status: {}".format(err))
|
|
330
342
|
return
|
|
331
343
|
|
|
344
|
+
# Auto-skip downstream refactors when this refactor is marked as failed or skipped
|
|
345
|
+
auto_skipped_refactors = []
|
|
346
|
+
if rs["status"] in ("failed", "skipped"):
|
|
347
|
+
auto_skipped_refactors = auto_skip_blocked_refactors(
|
|
348
|
+
refactor_list_path, state_dir, refactor_id
|
|
349
|
+
)
|
|
350
|
+
|
|
332
351
|
summary = {
|
|
333
352
|
"action": "update",
|
|
334
353
|
"refactor_id": refactor_id,
|
|
@@ -338,8 +357,10 @@ def action_update(args, refactor_list_path, state_dir):
|
|
|
338
357
|
"resume_from_phase": rs.get("resume_from_phase"),
|
|
339
358
|
"updated_at": rs["updated_at"],
|
|
340
359
|
}
|
|
341
|
-
if
|
|
342
|
-
summary["
|
|
360
|
+
if auto_skipped_refactors:
|
|
361
|
+
summary["auto_skipped"] = [info["refactor_id"] for info in auto_skipped_refactors]
|
|
362
|
+
if session_status in ("commit_missing", "docs_missing", "merge_conflict"):
|
|
363
|
+
summary["degraded_reason"] = session_status
|
|
343
364
|
summary["restart_policy"] = "finalization_retry"
|
|
344
365
|
elif session_status != "success":
|
|
345
366
|
summary["restart_policy"] = "full_restart"
|
|
@@ -410,6 +431,116 @@ def load_session_status(state_dir, refactor_id, session_id):
|
|
|
410
431
|
return data, None
|
|
411
432
|
|
|
412
433
|
|
|
434
|
+
# ---------------------------------------------------------------------------
|
|
435
|
+
# Auto-skip: cascade failure to blocked downstream refactors
|
|
436
|
+
# ---------------------------------------------------------------------------
|
|
437
|
+
|
|
438
|
+
def auto_skip_blocked_refactors(refactor_list_path, state_dir, failed_refactor_id):
|
|
439
|
+
"""Recursively mark all downstream refactors blocked by a failed refactor as auto_skipped.
|
|
440
|
+
|
|
441
|
+
When a refactor is marked as failed, any refactor whose dependency chain includes
|
|
442
|
+
the failed refactor can never be executed. This function propagates the failure
|
|
443
|
+
by marking those blocked refactors as auto_skipped, allowing the pipeline to
|
|
444
|
+
continue processing unblocked refactors and eventually reach PIPELINE_COMPLETE.
|
|
445
|
+
|
|
446
|
+
Re-reads .prizmkit/plans/refactor-list.json from disk to get the latest state (including the
|
|
447
|
+
just-written failed status from update_refactor_in_list).
|
|
448
|
+
|
|
449
|
+
NOTE: This function performs a read-modify-write on .prizmkit/plans/refactor-list.json without
|
|
450
|
+
file locking. The caller (action_update) also writes to .prizmkit/plans/refactor-list.json
|
|
451
|
+
immediately before calling this. Safe for single-pipeline execution, but if
|
|
452
|
+
multiple pipeline instances share the same .prizmkit/plans/refactor-list.json concurrently,
|
|
453
|
+
a race condition may cause lost writes. Add file locking if parallel pipelines
|
|
454
|
+
are introduced.
|
|
455
|
+
"""
|
|
456
|
+
data, err = load_json_file(refactor_list_path)
|
|
457
|
+
if err:
|
|
458
|
+
return []
|
|
459
|
+
refactors = data.get("refactors", [])
|
|
460
|
+
|
|
461
|
+
# Build current status map
|
|
462
|
+
status_map = {}
|
|
463
|
+
for r in refactors:
|
|
464
|
+
if isinstance(r, dict) and r.get("id"):
|
|
465
|
+
status_map[r["id"]] = r.get("status", "pending")
|
|
466
|
+
|
|
467
|
+
# Collect all refactors to auto-skip (recursive propagation)
|
|
468
|
+
to_skip = set()
|
|
469
|
+
changed = True
|
|
470
|
+
while changed:
|
|
471
|
+
changed = False
|
|
472
|
+
for r in refactors:
|
|
473
|
+
if not isinstance(r, dict):
|
|
474
|
+
continue
|
|
475
|
+
rid = r.get("id")
|
|
476
|
+
if not rid or rid in to_skip:
|
|
477
|
+
continue
|
|
478
|
+
current = status_map.get(rid, "pending")
|
|
479
|
+
if current in TERMINAL_STATUSES:
|
|
480
|
+
continue
|
|
481
|
+
deps = r.get("dependencies", [])
|
|
482
|
+
for dep_id in deps:
|
|
483
|
+
dep_status = status_map.get(dep_id, "pending")
|
|
484
|
+
if dep_status in ("failed", "skipped", "auto_skipped") or dep_id in to_skip:
|
|
485
|
+
to_skip.add(rid)
|
|
486
|
+
status_map[rid] = "auto_skipped"
|
|
487
|
+
changed = True
|
|
488
|
+
break
|
|
489
|
+
|
|
490
|
+
if not to_skip:
|
|
491
|
+
return []
|
|
492
|
+
|
|
493
|
+
# Batch-write to .prizmkit/plans/refactor-list.json
|
|
494
|
+
for r in refactors:
|
|
495
|
+
if isinstance(r, dict) and r.get("id") in to_skip:
|
|
496
|
+
r["status"] = "auto_skipped"
|
|
497
|
+
write_json_file(refactor_list_path, data)
|
|
498
|
+
|
|
499
|
+
# Sync status.json for each auto-skipped refactor
|
|
500
|
+
for rid in to_skip:
|
|
501
|
+
rs = load_refactor_status(state_dir, rid)
|
|
502
|
+
rs["status"] = "auto_skipped"
|
|
503
|
+
rs["updated_at"] = now_iso()
|
|
504
|
+
save_refactor_status(state_dir, rid, rs)
|
|
505
|
+
|
|
506
|
+
# Build blocking reason map for logging
|
|
507
|
+
skipped_info = []
|
|
508
|
+
for r in refactors:
|
|
509
|
+
if not isinstance(r, dict):
|
|
510
|
+
continue
|
|
511
|
+
rid = r.get("id")
|
|
512
|
+
if rid not in to_skip:
|
|
513
|
+
continue
|
|
514
|
+
deps = r.get("dependencies", [])
|
|
515
|
+
blockers = [
|
|
516
|
+
d for d in deps
|
|
517
|
+
if d == failed_refactor_id or d in to_skip
|
|
518
|
+
]
|
|
519
|
+
skipped_info.append({
|
|
520
|
+
"refactor_id": rid,
|
|
521
|
+
"title": r.get("title", ""),
|
|
522
|
+
"blocked_by": blockers,
|
|
523
|
+
})
|
|
524
|
+
|
|
525
|
+
print(
|
|
526
|
+
"[auto-skip] {} refactor(s) auto-skipped due to failed {}:".format(
|
|
527
|
+
len(skipped_info), failed_refactor_id
|
|
528
|
+
),
|
|
529
|
+
file=sys.stderr,
|
|
530
|
+
)
|
|
531
|
+
for info in skipped_info:
|
|
532
|
+
print(
|
|
533
|
+
" {} ({}) — blocked by {}".format(
|
|
534
|
+
info["refactor_id"],
|
|
535
|
+
info["title"],
|
|
536
|
+
", ".join(info["blocked_by"]),
|
|
537
|
+
),
|
|
538
|
+
file=sys.stderr,
|
|
539
|
+
)
|
|
540
|
+
|
|
541
|
+
return skipped_info
|
|
542
|
+
|
|
543
|
+
|
|
413
544
|
# ---------------------------------------------------------------------------
|
|
414
545
|
# Action: status
|
|
415
546
|
# ---------------------------------------------------------------------------
|
|
@@ -445,7 +576,7 @@ def action_status(refactor_list_data, state_dir):
|
|
|
445
576
|
refactors = refactor_list_data.get("refactors", [])
|
|
446
577
|
project_name = refactor_list_data.get("project_name", "Unknown")
|
|
447
578
|
|
|
448
|
-
counts = {"completed": 0, "in_progress": 0, "failed": 0, "pending": 0, "skipped": 0}
|
|
579
|
+
counts = {"completed": 0, "in_progress": 0, "failed": 0, "pending": 0, "skipped": 0, "auto_skipped": 0}
|
|
449
580
|
refactor_lines = []
|
|
450
581
|
|
|
451
582
|
for r in refactors:
|
|
@@ -478,6 +609,8 @@ def action_status(refactor_list_data, state_dir):
|
|
|
478
609
|
icon = COLOR_RED + "[✗]" + COLOR_RESET
|
|
479
610
|
elif rstatus == "skipped":
|
|
480
611
|
icon = COLOR_GRAY + "[—]" + COLOR_RESET
|
|
612
|
+
elif rstatus == "auto_skipped":
|
|
613
|
+
icon = COLOR_GRAY + "[⊘]" + COLOR_RESET
|
|
481
614
|
else:
|
|
482
615
|
icon = COLOR_GRAY + "[ ]" + COLOR_RESET
|
|
483
616
|
|
|
@@ -525,8 +658,8 @@ def action_status(refactor_list_data, state_dir):
|
|
|
525
658
|
summary_line = "Total: {} refactors | Completed: {} | In Progress: {}".format(
|
|
526
659
|
total, completed, counts["in_progress"]
|
|
527
660
|
)
|
|
528
|
-
summary_line2 = "Failed: {} | Pending: {} | Skipped: {}".format(
|
|
529
|
-
counts["failed"], counts["pending"], counts["skipped"]
|
|
661
|
+
summary_line2 = "Failed: {} | Pending: {} | Skipped: {} | Auto-skipped: {}".format(
|
|
662
|
+
counts["failed"], counts["pending"], counts["skipped"], counts["auto_skipped"]
|
|
530
663
|
)
|
|
531
664
|
|
|
532
665
|
inner = BOX_WIDTH - 2
|
|
@@ -685,6 +818,195 @@ def action_pause(state_dir):
|
|
|
685
818
|
print(json.dumps(result, indent=2, ensure_ascii=False))
|
|
686
819
|
|
|
687
820
|
|
|
821
|
+
# ---------------------------------------------------------------------------
|
|
822
|
+
# Action: start
|
|
823
|
+
# ---------------------------------------------------------------------------
|
|
824
|
+
|
|
825
|
+
def action_start(args, refactor_list_path, state_dir):
|
|
826
|
+
"""Mark a refactor as in_progress when a session starts.
|
|
827
|
+
|
|
828
|
+
This keeps refactor-list.json/state status in sync during execution,
|
|
829
|
+
instead of only updating after session end.
|
|
830
|
+
"""
|
|
831
|
+
refactor_id = args.refactor_id
|
|
832
|
+
if not refactor_id:
|
|
833
|
+
error_out("--refactor-id is required for 'start' action")
|
|
834
|
+
return
|
|
835
|
+
|
|
836
|
+
rs = load_refactor_status(state_dir, refactor_id)
|
|
837
|
+
old_status = rs.get("status", "pending")
|
|
838
|
+
|
|
839
|
+
rs["status"] = "in_progress"
|
|
840
|
+
rs["updated_at"] = now_iso()
|
|
841
|
+
|
|
842
|
+
err = save_refactor_status(state_dir, refactor_id, rs)
|
|
843
|
+
if err:
|
|
844
|
+
error_out("Failed to save refactor status: {}".format(err))
|
|
845
|
+
return
|
|
846
|
+
|
|
847
|
+
err = update_refactor_in_list(refactor_list_path, refactor_id, "in_progress")
|
|
848
|
+
if err:
|
|
849
|
+
error_out("Failed to update .prizmkit/plans/refactor-list.json: {}".format(err))
|
|
850
|
+
return
|
|
851
|
+
|
|
852
|
+
result = {
|
|
853
|
+
"action": "start",
|
|
854
|
+
"refactor_id": refactor_id,
|
|
855
|
+
"old_status": old_status,
|
|
856
|
+
"new_status": "in_progress",
|
|
857
|
+
"updated_at": rs["updated_at"],
|
|
858
|
+
}
|
|
859
|
+
print(json.dumps(result, indent=2, ensure_ascii=False))
|
|
860
|
+
|
|
861
|
+
|
|
862
|
+
# ---------------------------------------------------------------------------
|
|
863
|
+
# Action: unskip
|
|
864
|
+
# ---------------------------------------------------------------------------
|
|
865
|
+
|
|
866
|
+
def action_unskip(args, refactor_list_path, state_dir):
|
|
867
|
+
"""Recover skipped/auto_skipped/failed refactors by resetting them and their failed upstream.
|
|
868
|
+
|
|
869
|
+
Two modes:
|
|
870
|
+
- --refactor-id R-001: Reset the specified failed/skipped/auto_skipped refactor + all
|
|
871
|
+
downstream auto_skipped refactors whose dependency chain includes it.
|
|
872
|
+
If the target is auto_skipped, also walk upstream to find and reset the
|
|
873
|
+
failed/skipped ancestor that caused the cascade.
|
|
874
|
+
- No --refactor-id: Reset ALL failed, skipped, and auto_skipped refactors to pending.
|
|
875
|
+
"""
|
|
876
|
+
refactor_id = args.refactor_id
|
|
877
|
+
|
|
878
|
+
data, err = load_json_file(refactor_list_path)
|
|
879
|
+
if err:
|
|
880
|
+
error_out("Cannot load refactor list: {}".format(err))
|
|
881
|
+
return
|
|
882
|
+
refactors = data.get("refactors", [])
|
|
883
|
+
|
|
884
|
+
to_reset = set()
|
|
885
|
+
|
|
886
|
+
if refactor_id:
|
|
887
|
+
# Find the target refactor
|
|
888
|
+
target = None
|
|
889
|
+
for r in refactors:
|
|
890
|
+
if isinstance(r, dict) and r.get("id") == refactor_id:
|
|
891
|
+
target = r
|
|
892
|
+
break
|
|
893
|
+
if not target:
|
|
894
|
+
error_out("Refactor '{}' not found in .prizmkit/plans/refactor-list.json".format(refactor_id))
|
|
895
|
+
return
|
|
896
|
+
if target.get("status") not in ("failed", "skipped", "auto_skipped"):
|
|
897
|
+
error_out(
|
|
898
|
+
"Refactor '{}' has status '{}', expected 'failed', 'skipped', or 'auto_skipped'".format(
|
|
899
|
+
refactor_id, target.get("status", "unknown")
|
|
900
|
+
)
|
|
901
|
+
)
|
|
902
|
+
return
|
|
903
|
+
|
|
904
|
+
# If target is failed or skipped, reset it and find all auto_skipped descendants
|
|
905
|
+
if target.get("status") in ("failed", "skipped"):
|
|
906
|
+
to_reset.add(refactor_id)
|
|
907
|
+
# Find all auto_skipped refactors that depend (transitively) on this one
|
|
908
|
+
changed = True
|
|
909
|
+
while changed:
|
|
910
|
+
changed = False
|
|
911
|
+
for r in refactors:
|
|
912
|
+
if not isinstance(r, dict):
|
|
913
|
+
continue
|
|
914
|
+
rid = r.get("id")
|
|
915
|
+
if not rid or rid in to_reset:
|
|
916
|
+
continue
|
|
917
|
+
if r.get("status") != "auto_skipped":
|
|
918
|
+
continue
|
|
919
|
+
deps = r.get("dependencies", [])
|
|
920
|
+
if any(d in to_reset for d in deps):
|
|
921
|
+
to_reset.add(rid)
|
|
922
|
+
changed = True
|
|
923
|
+
|
|
924
|
+
# If target is auto_skipped, reset it and its failed upstream + siblings
|
|
925
|
+
elif target.get("status") == "auto_skipped":
|
|
926
|
+
to_reset.add(refactor_id)
|
|
927
|
+
# Transitively walk upstream to find ALL failed/auto_skipped ancestors
|
|
928
|
+
# (e.g., R-001 failed → R-002 auto_skipped → R-003 auto_skipped;
|
|
929
|
+
# unskip R-003 must also find and reset R-001)
|
|
930
|
+
upstream_changed = True
|
|
931
|
+
while upstream_changed:
|
|
932
|
+
upstream_changed = False
|
|
933
|
+
for r in refactors:
|
|
934
|
+
if not isinstance(r, dict):
|
|
935
|
+
continue
|
|
936
|
+
rid = r.get("id")
|
|
937
|
+
if not rid or rid not in to_reset:
|
|
938
|
+
continue
|
|
939
|
+
for dep_id in r.get("dependencies", []):
|
|
940
|
+
if dep_id in to_reset:
|
|
941
|
+
continue
|
|
942
|
+
for dep_r in refactors:
|
|
943
|
+
if isinstance(dep_r, dict) and dep_r.get("id") == dep_id:
|
|
944
|
+
if dep_r.get("status") in ("failed", "skipped", "auto_skipped"):
|
|
945
|
+
to_reset.add(dep_id)
|
|
946
|
+
upstream_changed = True
|
|
947
|
+
# Also reset downstream auto_skipped refactors blocked by the same upstreams
|
|
948
|
+
changed = True
|
|
949
|
+
while changed:
|
|
950
|
+
changed = False
|
|
951
|
+
for r in refactors:
|
|
952
|
+
if not isinstance(r, dict):
|
|
953
|
+
continue
|
|
954
|
+
rid = r.get("id")
|
|
955
|
+
if not rid or rid in to_reset:
|
|
956
|
+
continue
|
|
957
|
+
if r.get("status") != "auto_skipped":
|
|
958
|
+
continue
|
|
959
|
+
rdeps = r.get("dependencies", [])
|
|
960
|
+
if any(d in to_reset for d in rdeps):
|
|
961
|
+
to_reset.add(rid)
|
|
962
|
+
changed = True
|
|
963
|
+
else:
|
|
964
|
+
# No refactor-id: reset ALL failed + skipped + auto_skipped
|
|
965
|
+
for r in refactors:
|
|
966
|
+
if isinstance(r, dict) and r.get("id"):
|
|
967
|
+
if r.get("status") in ("failed", "skipped", "auto_skipped"):
|
|
968
|
+
to_reset.add(r["id"])
|
|
969
|
+
|
|
970
|
+
if not to_reset:
|
|
971
|
+
error_out("No refactors to unskip")
|
|
972
|
+
return
|
|
973
|
+
|
|
974
|
+
# Reset all collected refactors in refactor-list.json
|
|
975
|
+
reset_details = []
|
|
976
|
+
for r in refactors:
|
|
977
|
+
if isinstance(r, dict) and r.get("id") in to_reset:
|
|
978
|
+
old_status = r.get("status", "unknown")
|
|
979
|
+
r["status"] = "pending"
|
|
980
|
+
reset_details.append({
|
|
981
|
+
"refactor_id": r["id"],
|
|
982
|
+
"title": r.get("title", ""),
|
|
983
|
+
"old_status": old_status,
|
|
984
|
+
})
|
|
985
|
+
|
|
986
|
+
err = write_json_file(refactor_list_path, data)
|
|
987
|
+
if err:
|
|
988
|
+
error_out("Failed to write .prizmkit/plans/refactor-list.json: {}".format(err))
|
|
989
|
+
return
|
|
990
|
+
|
|
991
|
+
# Reset status.json for each refactor
|
|
992
|
+
for rid in to_reset:
|
|
993
|
+
rs = load_refactor_status(state_dir, rid)
|
|
994
|
+
rs["status"] = "pending"
|
|
995
|
+
rs["retry_count"] = 0
|
|
996
|
+
rs["sessions"] = []
|
|
997
|
+
rs["last_session_id"] = None
|
|
998
|
+
rs["resume_from_phase"] = None
|
|
999
|
+
rs["updated_at"] = now_iso()
|
|
1000
|
+
save_refactor_status(state_dir, rid, rs)
|
|
1001
|
+
|
|
1002
|
+
result = {
|
|
1003
|
+
"action": "unskip",
|
|
1004
|
+
"reset_count": len(to_reset),
|
|
1005
|
+
"refactors": reset_details,
|
|
1006
|
+
}
|
|
1007
|
+
print(json.dumps(result, indent=2, ensure_ascii=False))
|
|
1008
|
+
|
|
1009
|
+
|
|
688
1010
|
# ---------------------------------------------------------------------------
|
|
689
1011
|
# Main
|
|
690
1012
|
# ---------------------------------------------------------------------------
|
|
@@ -697,7 +1019,7 @@ def main():
|
|
|
697
1019
|
error_out("--refactor-id is required for 'update' action")
|
|
698
1020
|
if not args.session_status:
|
|
699
1021
|
error_out("--session-status is required for 'update' action")
|
|
700
|
-
if args.action in ("reset", "clean"):
|
|
1022
|
+
if args.action in ("start", "reset", "clean", "complete"):
|
|
701
1023
|
if not args.refactor_id:
|
|
702
1024
|
error_out("--refactor-id is required for '{}' action".format(args.action))
|
|
703
1025
|
if args.action == "clean":
|
|
@@ -718,8 +1040,16 @@ def main():
|
|
|
718
1040
|
action_reset(args, args.refactor_list, args.state_dir)
|
|
719
1041
|
elif args.action == "clean":
|
|
720
1042
|
action_clean(args, args.refactor_list, args.state_dir)
|
|
1043
|
+
elif args.action == "start":
|
|
1044
|
+
action_start(args, args.refactor_list, args.state_dir)
|
|
721
1045
|
elif args.action == "pause":
|
|
722
1046
|
action_pause(args.state_dir)
|
|
1047
|
+
elif args.action == "unskip":
|
|
1048
|
+
action_unskip(args, args.refactor_list, args.state_dir)
|
|
1049
|
+
elif args.action == "complete":
|
|
1050
|
+
# Shortcut: 'complete' is equivalent to 'update --session-status success'
|
|
1051
|
+
args.session_status = "success"
|
|
1052
|
+
action_update(args, args.refactor_list, args.state_dir)
|
|
723
1053
|
|
|
724
1054
|
|
|
725
1055
|
if __name__ == "__main__":
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"Read {{DEV_SUBAGENT_PATH}}. Fix NEEDS_FIXES issues for feature {{FEATURE_ID}} (slug: {{FEATURE_SLUG}}).
|
|
2
|
-
1. Read `.prizmkit/specs/{{FEATURE_SLUG}}/
|
|
2
|
+
1. Read `.prizmkit/specs/{{FEATURE_SLUG}}/review-report.md` — contains structured Fix Instructions with exact steps.
|
|
3
3
|
2. Follow Fix Instructions in order (respect Depends On / Blocks dependencies). Each FIX-N has: Root Cause, Fix Strategy, Code Guidance, and Verification criteria.
|
|
4
4
|
3. After each fix, run the Verification command listed in that FIX-N to confirm it works.
|
|
5
5
|
4. Run `{{TEST_CMD}}` to verify no regressions.
|
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
"Read {{REVIEWER_SUBAGENT_PATH}}. For feature {{FEATURE_ID}} (slug: {{FEATURE_SLUG}}):
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
3. Run prizmkit-code-review (both phases): Phase 1 diagnostic review (spec compliance, code quality, correctness), then Phase 2 fix strategy formulation for any findings. Read ONLY files listed in Implementation Log for diagnosis; MAY read additional files for impact analysis.
|
|
10
|
-
4. Run the full test suite using `{{TEST_CMD}}` — **ONLY if the Implementation Log does not already confirm all tests passing**. If Implementation Log states tests passed, trust it and skip the re-run. When running tests: `{{TEST_CMD}} 2>&1 | tee /tmp/review-test-out.txt | tail -20`, then grep `/tmp/review-test-out.txt` for details — do NOT re-run the suite multiple times. Write and execute integration tests covering all user stories from spec.md.
|
|
11
|
-
5. Write structured '## Review Notes' to context-snapshot.md with Fix Instructions (Root Cause, Impact, Fix Strategy, Code Guidance, Verification for each finding) and Re-Review Expectations.
|
|
12
|
-
Report verdict: PASS, PASS_WITH_WARNINGS, or NEEDS_FIXES."
|
|
2
|
+
1. Read `.prizmkit/specs/{{FEATURE_SLUG}}/spec.md` (if it exists) for goals and acceptance criteria; if spec.md does not exist, read `.prizmkit/specs/{{FEATURE_SLUG}}/context-snapshot.md` Section 1 instead
|
|
3
|
+
2. Read `.prizmkit/specs/{{FEATURE_SLUG}}/plan.md` for architecture decisions and completed tasks
|
|
4
|
+
3. Read `.prizm-docs/root.prizm` and relevant L1/L2 docs for RULES, PATTERNS, TRAPS
|
|
5
|
+
4. Run /prizmkit-code-review with artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/: Phase 1 diagnostic review across all applicable dimensions, then Phase 2 fix strategy for any findings. Read ONLY files referenced in completed plan.md tasks for diagnosis; MAY read additional files for impact analysis.
|
|
6
|
+
5. Run the full test suite using `{{TEST_CMD}}`. When running tests: `{{TEST_CMD}} 2>&1 | tee /tmp/review-test-out.txt | tail -20`, then grep `/tmp/review-test-out.txt` for details — do NOT re-run the suite multiple times. Write and execute integration tests covering all goals from spec.md.
|
|
7
|
+
6. review-report.md will be written to .prizmkit/specs/{{FEATURE_SLUG}}/ by prizmkit-code-review.
|
|
8
|
+
Report: number of findings found, or 'no findings' if clean."
|
|
@@ -1,10 +1,44 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Dev-Pipeline Fallback Bootstrap Prompt
|
|
2
2
|
|
|
3
|
-
This
|
|
3
|
+
> **Note**: This is an emergency fallback template. Normally, `generate-bootstrap-prompt.py`
|
|
4
|
+
> selects a tier-specific template (`bootstrap-tier1.md`, `bootstrap-tier2.md`, or `bootstrap-tier3.md`).
|
|
5
|
+
> If you are seeing this prompt, the tier-specific templates were not found.
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
- `bootstrap-tier2.md` — Tier 2: Dual Agent (complexity: medium)
|
|
7
|
-
- `bootstrap-tier3.md` — Tier 3: Full Team (complexity: high)
|
|
7
|
+
## Feature Context
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
- **Feature ID**: {{FEATURE_ID}}
|
|
10
|
+
- **Title**: {{FEATURE_TITLE}}
|
|
11
|
+
- **Description**: {{FEATURE_DESCRIPTION}}
|
|
12
|
+
- **Slug**: {{FEATURE_SLUG}}
|
|
13
|
+
|
|
14
|
+
### Acceptance Criteria
|
|
15
|
+
|
|
16
|
+
{{ACCEPTANCE_CRITERIA}}
|
|
17
|
+
|
|
18
|
+
## Instructions
|
|
19
|
+
|
|
20
|
+
You are running in **headless non-interactive mode** — no human is available for input.
|
|
21
|
+
Infer what needs to be done from the feature context above and follow the standard dev loop.
|
|
22
|
+
|
|
23
|
+
### Execution Steps
|
|
24
|
+
|
|
25
|
+
1. **Read context**: Read `.prizm-docs/root.prizm` and relevant L1/L2 docs to understand the codebase.
|
|
26
|
+
|
|
27
|
+
2. **Plan**: Run `/prizmkit-plan` with `artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/` to produce `spec.md` and `plan.md`.
|
|
28
|
+
|
|
29
|
+
3. **Implement**: Run `/prizmkit-implement` with `artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/` to execute the plan using TDD (write tests first, then implement).
|
|
30
|
+
|
|
31
|
+
4. **Test**: Run the project test suite to verify all tests pass with no regressions.
|
|
32
|
+
|
|
33
|
+
5. **Review**: Run `/prizmkit-code-review` with `artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/` to review changes against the spec. If findings exist, fix them and re-review (max 2 rounds).
|
|
34
|
+
|
|
35
|
+
6. **Retrospective**: Run `/prizmkit-retrospective` to sync `.prizm-docs/` with code changes.
|
|
36
|
+
|
|
37
|
+
7. **Commit**: Run `/prizmkit-committer` to commit all changes. Do NOT push.
|
|
38
|
+
|
|
39
|
+
### Critical Rules
|
|
40
|
+
|
|
41
|
+
- Do NOT ask for user input — decide autonomously.
|
|
42
|
+
- Do NOT push to remote — the user will push manually.
|
|
43
|
+
- Write all artifacts to `.prizmkit/specs/{{FEATURE_SLUG}}/`.
|
|
44
|
+
- If a step fails after 3 attempts, write a status report and stop.
|
|
@@ -39,7 +39,9 @@ You are the **session orchestrator**. Implement Feature {{FEATURE_ID}}: "{{FEATU
|
|
|
39
39
|
|
|
40
40
|
## ⚠️ Context Budget Rules (CRITICAL — read before any phase)
|
|
41
41
|
|
|
42
|
-
You are running in headless mode with a FINITE context window. Exceeding it will crash the session and lose all work. Follow these rules strictly:
|
|
42
|
+
You are running in **headless non-interactive mode** with a FINITE context window. Exceeding it will crash the session and lose all work. Follow these rules strictly:
|
|
43
|
+
|
|
44
|
+
0. **NON-INTERACTIVE MODE** — There is NO human on the other end. NEVER ask for user confirmation, NEVER wait for user input, NEVER use interactive prompts (e.g. "Would you like me to…"). If a skill has an interactive step (e.g. offer remediation, ask for approval), skip it and proceed autonomously. Make decisions based on the data available and move forward.
|
|
43
45
|
|
|
44
46
|
1. **context-snapshot.md is your single source of truth** — After Phase 1 builds it, ALWAYS read context-snapshot.md instead of re-reading individual source files
|
|
45
47
|
2. **Never re-read your own writes** — After you create/modify a file, do NOT read it back to verify. Trust your write was correct.
|
|
@@ -232,7 +234,7 @@ You just implemented this feature — you know the project's tech stack and buil
|
|
|
232
234
|
3. **Assess and record** — append to context-snapshot.md:
|
|
233
235
|
- **ALL builds pass** → `## Deploy Verification: PASS` — proceed to commit
|
|
234
236
|
- **Some builds fail with fixable errors** → fix and re-verify (already handled in step 2)
|
|
235
|
-
- **Cannot build locally** (missing system-level deps you cannot install) → Generate
|
|
237
|
+
- **Cannot build locally** (missing system-level deps you cannot install) → Generate `.prizmkit/deploy.md` with:
|
|
236
238
|
```
|
|
237
239
|
# Local Development Setup
|
|
238
240
|
|
|
@@ -248,7 +250,7 @@ You just implemented this feature — you know the project's tech stack and buil
|
|
|
248
250
|
## Verify
|
|
249
251
|
[how to confirm the app is running correctly]
|
|
250
252
|
```
|
|
251
|
-
Record: `## Deploy Verification: PARTIAL — see
|
|
253
|
+
Record: `## Deploy Verification: PARTIAL — see .prizmkit/deploy.md for missing prerequisites`
|
|
252
254
|
|
|
253
255
|
Deploy verification does NOT block the commit, but you MUST attempt it.
|
|
254
256
|
|
|
@@ -289,6 +291,28 @@ Working tree MUST be clean after this step. If any feature-related files remain,
|
|
|
289
291
|
|
|
290
292
|
**Exception**: `session-summary.md` in the artifact directory is a local cross-session artifact generated by `/prizmkit-committer` — it is NOT committed to git. Ignore it in the clean-tree check.
|
|
291
293
|
|
|
294
|
+
**4e.** Write completion summary for downstream dependency context:
|
|
295
|
+
|
|
296
|
+
Write `.prizmkit/specs/{{FEATURE_SLUG}}/completion-summary.json` with the key changes from this session. This file is NOT committed to git — the pipeline runner reads it to propagate context to dependent features.
|
|
297
|
+
|
|
298
|
+
```json
|
|
299
|
+
{
|
|
300
|
+
"completion_notes": [
|
|
301
|
+
"<each item: one key change, API, model, or integration point that downstream features may need>",
|
|
302
|
+
"Example: Added User model (id, email, password_hash, display_name) in prisma/schema.prisma",
|
|
303
|
+
"Example: POST /api/auth/register and POST /api/auth/login endpoints in src/api/auth.ts",
|
|
304
|
+
"Example: Auth middleware in src/middleware/auth.ts — validates JWT on protected routes"
|
|
305
|
+
]
|
|
306
|
+
}
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
Rules for writing completion notes:
|
|
310
|
+
- Focus on **what downstream features need to know**: new APIs, models, exported functions, key file paths
|
|
311
|
+
- Each note should be self-contained and concise (one line, under 120 characters preferred)
|
|
312
|
+
- Include 3-8 notes covering the most important changes
|
|
313
|
+
- Do NOT include test files, config changes, or internal implementation details unless they affect other features
|
|
314
|
+
- If this feature has no downstream dependents, still write the summary (it serves as documentation)
|
|
315
|
+
|
|
292
316
|
## Critical Paths
|
|
293
317
|
|
|
294
318
|
| Resource | Path |
|