prizmkit 1.1.114 → 1.1.115
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/.env.example +0 -1
- package/bundled/dev-pipeline/README.md +4 -6
- package/bundled/dev-pipeline/SCHEMA_ANALYSIS.md +40 -518
- package/bundled/dev-pipeline/assets/prizm-dev-team-integration.md +27 -99
- package/bundled/dev-pipeline/prizmkit_runtime/checkpoint_state.py +283 -0
- package/bundled/dev-pipeline/prizmkit_runtime/daemon.py +3 -13
- package/bundled/dev-pipeline/prizmkit_runtime/heartbeat.py +0 -1
- package/bundled/dev-pipeline/prizmkit_runtime/runner_classification.py +25 -31
- package/bundled/dev-pipeline/prizmkit_runtime/runner_models.py +0 -8
- package/bundled/dev-pipeline/prizmkit_runtime/runner_prompts.py +0 -3
- package/bundled/dev-pipeline/prizmkit_runtime/runners.py +13 -7
- package/bundled/dev-pipeline/prizmkit_runtime/sessions.py +13 -1
- package/bundled/dev-pipeline/scripts/continuation.py +8 -40
- package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +76 -261
- package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +16 -35
- package/bundled/dev-pipeline/scripts/generate-refactor-prompt.py +15 -34
- package/bundled/dev-pipeline/scripts/init-bugfix-pipeline.py +6 -0
- package/bundled/dev-pipeline/scripts/init-pipeline.py +6 -0
- package/bundled/dev-pipeline/scripts/init-refactor-pipeline.py +6 -0
- package/bundled/dev-pipeline/scripts/parse-stream-progress.py +1 -1
- package/bundled/dev-pipeline/scripts/prompt_framework.py +114 -63
- package/bundled/dev-pipeline/scripts/update-bug-status.py +3 -7
- package/bundled/dev-pipeline/scripts/update-checkpoint.py +54 -22
- package/bundled/dev-pipeline/scripts/update-feature-status.py +3 -7
- package/bundled/dev-pipeline/scripts/update-refactor-status.py +3 -7
- package/bundled/dev-pipeline/scripts/utils.py +6 -37
- package/bundled/dev-pipeline/templates/bootstrap-prompt.md +1 -1
- package/bundled/dev-pipeline/templates/bootstrap-tier1.md +1 -1
- package/bundled/dev-pipeline/templates/bootstrap-tier2.md +9 -91
- package/bundled/dev-pipeline/templates/bootstrap-tier3.md +9 -66
- package/bundled/dev-pipeline/templates/bug-fix-list-schema.json +10 -16
- package/bundled/dev-pipeline/templates/feature-list-schema.json +32 -17
- package/bundled/dev-pipeline/templates/refactor-bootstrap-prompt.md +0 -16
- package/bundled/dev-pipeline/templates/refactor-list-schema.json +10 -16
- package/bundled/dev-pipeline/templates/sections/bugfix-session-context.md +1 -1
- package/bundled/dev-pipeline/templates/sections/context-budget-rules.md +1 -1
- package/bundled/dev-pipeline/templates/sections/critical-paths-agent.md +0 -1
- package/bundled/dev-pipeline/templates/sections/critical-paths-full.md +0 -1
- package/bundled/dev-pipeline/templates/sections/phase-implement-agent.md +1 -1
- package/bundled/dev-pipeline/templates/sections/phase-implement-full.md +1 -1
- package/bundled/dev-pipeline/templates/sections/refactor-session-context.md +1 -1
- package/bundled/dev-pipeline/tests/conftest.py +1 -0
- package/bundled/dev-pipeline/tests/test_checkpoint_state.py +164 -0
- package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +48 -76
- package/bundled/dev-pipeline/tests/test_generate_bugfix_prompt.py +25 -3
- package/bundled/dev-pipeline/tests/test_generate_refactor_prompt.py +25 -5
- package/bundled/dev-pipeline/tests/test_python_runner_parity.py +128 -10
- package/bundled/dev-pipeline/tests/test_unified_cli.py +40 -9
- package/bundled/skills/_metadata.json +1 -1
- package/bundled/skills/bug-planner/SKILL.md +5 -4
- package/bundled/skills/bug-planner/references/verification.md +29 -0
- package/bundled/skills/bug-planner/scripts/validate-bug-list.py +8 -0
- package/bundled/skills/bugfix-pipeline-launcher/SKILL.md +2 -2
- package/bundled/skills/bugfix-pipeline-launcher/references/configuration.md +1 -6
- package/bundled/skills/feature-pipeline-launcher/SKILL.md +6 -12
- package/bundled/skills/feature-pipeline-launcher/references/configuration.md +0 -1
- package/bundled/skills/feature-planner/SKILL.md +13 -12
- package/bundled/skills/feature-planner/assets/planning-guide.md +2 -2
- package/bundled/skills/feature-planner/scripts/validate-and-generate.py +8 -11
- package/bundled/skills/prizmkit-plan/SKILL.md +15 -1
- package/bundled/skills/prizmkit-plan/references/review-plan-spec-loop.md +101 -0
- package/bundled/skills/refactor-pipeline-launcher/SKILL.md +5 -5
- package/bundled/skills/refactor-pipeline-launcher/references/configuration.md +2 -7
- package/bundled/skills/refactor-planner/SKILL.md +10 -8
- package/bundled/skills/refactor-planner/scripts/validate-and-generate-refactor.py +9 -0
- package/bundled/team/prizm-dev-team.json +2 -9
- package/package.json +1 -1
- package/bundled/agents/prizm-dev-team-critic.md +0 -179
- package/bundled/dev-pipeline/templates/agent-prompts/critic-plan-challenge.md +0 -8
- package/bundled/dev-pipeline/templates/sections/bugfix-phase-critic.md +0 -22
- package/bundled/dev-pipeline/templates/sections/phase-critic-plan-full.md +0 -61
- package/bundled/dev-pipeline/templates/sections/phase-critic-plan.md +0 -38
- package/bundled/dev-pipeline/templates/sections/refactor-phase-critic.md +0 -22
- package/bundled/skills/bug-planner/references/critic-and-verification.md +0 -44
|
@@ -29,7 +29,7 @@ import sys
|
|
|
29
29
|
|
|
30
30
|
from utils import enrich_global_context, helper_replacements, load_json_file, resolve_prompt_platform, setup_logging
|
|
31
31
|
from continuation import add_continuation_args, append_continuation_handoff, is_continuation
|
|
32
|
-
from prompt_framework import browser_enabled_from_item, detect_dev_server_port
|
|
32
|
+
from prompt_framework import browser_enabled_from_item, checkpoint_group, checkpoint_skip, checkpoint_step, detect_dev_server_port, generate_checkpoint_from_sections, merge_checkpoint_state as merge_shared_checkpoint_state
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
DEFAULT_MAX_RETRIES = 3
|
|
@@ -103,12 +103,6 @@ def parse_args():
|
|
|
103
103
|
default=None,
|
|
104
104
|
help="Override pipeline mode (default: auto-detect from complexity)",
|
|
105
105
|
)
|
|
106
|
-
parser.add_argument(
|
|
107
|
-
"--critic",
|
|
108
|
-
choices=["true", "false"],
|
|
109
|
-
default=None,
|
|
110
|
-
help="Override critic enablement (default: read from feature field)",
|
|
111
|
-
)
|
|
112
106
|
parser.add_argument(
|
|
113
107
|
"--extract-baselines",
|
|
114
108
|
action="store_true",
|
|
@@ -520,12 +514,11 @@ def process_conditional_blocks(content, resume_phase):
|
|
|
520
514
|
return content
|
|
521
515
|
|
|
522
516
|
|
|
523
|
-
def process_mode_blocks(content, pipeline_mode, init_done,
|
|
517
|
+
def process_mode_blocks(content, pipeline_mode, init_done,
|
|
524
518
|
browser_interaction=False, browser_tool="auto"):
|
|
525
|
-
"""Process pipeline mode, init,
|
|
519
|
+
"""Process pipeline mode, init, and browser conditional blocks.
|
|
526
520
|
|
|
527
521
|
Keeps the block matching the current mode, removes the others.
|
|
528
|
-
Handles {{IF_CRITIC_ENABLED}} / {{END_IF_CRITIC_ENABLED}} blocks.
|
|
529
522
|
Handles {{IF_BROWSER_INTERACTION}} / {{END_IF_BROWSER_INTERACTION}} blocks.
|
|
530
523
|
Handles {{IF_BROWSER_TOOL_PLAYWRIGHT}} / {{IF_BROWSER_TOOL_OPENCLI}} /
|
|
531
524
|
{{IF_BROWSER_TOOL_AUTO}} blocks (nested inside browser interaction block).
|
|
@@ -564,20 +557,6 @@ def process_mode_blocks(content, pipeline_mode, init_done, critic_enabled=False,
|
|
|
564
557
|
"", content, flags=re.DOTALL,
|
|
565
558
|
)
|
|
566
559
|
|
|
567
|
-
# Critic blocks
|
|
568
|
-
critic_open = "{{IF_CRITIC_ENABLED}}"
|
|
569
|
-
critic_close = "{{END_IF_CRITIC_ENABLED}}"
|
|
570
|
-
if critic_enabled:
|
|
571
|
-
# Keep content, remove tags
|
|
572
|
-
content = content.replace(critic_open + "\n", "")
|
|
573
|
-
content = content.replace(critic_open, "")
|
|
574
|
-
content = content.replace(critic_close + "\n", "")
|
|
575
|
-
content = content.replace(critic_close, "")
|
|
576
|
-
else:
|
|
577
|
-
# Remove entire CRITIC blocks
|
|
578
|
-
pattern = re.escape(critic_open) + r".*?" + re.escape(critic_close) + r"\n?"
|
|
579
|
-
content = re.sub(pattern, "", content, flags=re.DOTALL)
|
|
580
|
-
|
|
581
560
|
# Browser interaction blocks
|
|
582
561
|
browser_open = "{{IF_BROWSER_INTERACTION}}"
|
|
583
562
|
browser_close = "{{END_IF_BROWSER_INTERACTION}}"
|
|
@@ -672,36 +651,41 @@ def determine_pipeline_mode(complexity):
|
|
|
672
651
|
# prizmkit skill name. This ensures each section has a distinct key so
|
|
673
652
|
# merge_checkpoint_state() never collides.
|
|
674
653
|
SECTION_TO_SKILL = {
|
|
675
|
-
"phase0-init": (
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
"phase-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
654
|
+
"phase0-init": checkpoint_step(
|
|
655
|
+
"prizmkit-init", "Project Bootstrap",
|
|
656
|
+
[".prizmkit/prizm-docs/root.prizm", ".prizmkit/config.json"],
|
|
657
|
+
),
|
|
658
|
+
"phase0-test-baseline": checkpoint_skip(),
|
|
659
|
+
"phase-context-snapshot": checkpoint_step(
|
|
660
|
+
"context-snapshot", "Build Context Snapshot",
|
|
661
|
+
[".prizmkit/specs/{slug}/context-snapshot.md"],
|
|
662
|
+
),
|
|
663
|
+
"phase-specify-plan": checkpoint_step(
|
|
664
|
+
"context-snapshot-and-plan", "Specify & Plan",
|
|
665
|
+
[".prizmkit/specs/{slug}/context-snapshot.md",
|
|
666
|
+
".prizmkit/specs/{slug}/plan.md"],
|
|
667
|
+
),
|
|
668
|
+
"phase-plan": checkpoint_step(
|
|
669
|
+
"prizmkit-plan", "Plan & Tasks",
|
|
670
|
+
[".prizmkit/specs/{slug}/plan.md"],
|
|
671
|
+
),
|
|
672
|
+
"phase-implement": checkpoint_step("prizmkit-implement", "Implement + Test", []),
|
|
673
|
+
"phase-prizmkit-test": checkpoint_step(
|
|
688
674
|
"prizmkit-test", "Scoped Feature Test Gate",
|
|
689
675
|
[".prizmkit/specs/{slug}/test-report-path.txt",
|
|
690
676
|
".prizmkit/test/*/test-report.md"],
|
|
691
677
|
),
|
|
692
|
-
"phase-review": ("prizmkit-code-review", "Code Review", []),
|
|
693
|
-
"phase-browser": ("browser-verification", "Browser Verification", []),
|
|
694
|
-
"phase-commit":
|
|
678
|
+
"phase-review": checkpoint_step("prizmkit-code-review", "Code Review", []),
|
|
679
|
+
"phase-browser": checkpoint_step("browser-verification", "Browser Verification", []),
|
|
680
|
+
"phase-commit": checkpoint_group([
|
|
681
|
+
("prizmkit-retrospective", "Retrospective", []),
|
|
682
|
+
("prizmkit-committer", "Commit", []),
|
|
683
|
+
("completion-summary", "Completion Summary",
|
|
684
|
+
[".prizmkit/specs/{slug}/completion-summary.json"]),
|
|
685
|
+
]),
|
|
695
686
|
}
|
|
696
687
|
|
|
697
|
-
|
|
698
|
-
# artifacts; only real files/globs belong in required_artifacts.
|
|
699
|
-
_COMMIT_STEPS = [
|
|
700
|
-
("prizmkit-retrospective", "Retrospective", []),
|
|
701
|
-
("prizmkit-committer", "Commit", []),
|
|
702
|
-
("completion-summary", "Completion Summary",
|
|
703
|
-
[".prizmkit/specs/{slug}/completion-summary.json"]),
|
|
704
|
-
]
|
|
688
|
+
_COMMIT_STEPS = []
|
|
705
689
|
|
|
706
690
|
|
|
707
691
|
def _resolve_artifacts(artifact_templates, slug):
|
|
@@ -1152,132 +1136,30 @@ def _completed_step_artifacts_valid(project_root, skill_key, artifacts):
|
|
|
1152
1136
|
def generate_checkpoint_definition(sections, pipeline_mode, workflow_type,
|
|
1153
1137
|
item_id, item_slug, session_id,
|
|
1154
1138
|
init_done=False):
|
|
1155
|
-
"""Derive checkpoint step definitions from
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
pipeline_mode
|
|
1160
|
-
workflow_type
|
|
1161
|
-
item_id
|
|
1162
|
-
item_slug
|
|
1163
|
-
session_id
|
|
1164
|
-
init_done
|
|
1165
|
-
|
|
1166
|
-
Returns:
|
|
1167
|
-
dict suitable for writing as workflow-checkpoint.json
|
|
1168
|
-
"""
|
|
1169
|
-
steps = []
|
|
1170
|
-
step_counter = 1
|
|
1171
|
-
prev_step_id = None
|
|
1172
|
-
|
|
1173
|
-
for section_name, _content in sections:
|
|
1174
|
-
if section_name not in SECTION_TO_SKILL:
|
|
1175
|
-
continue
|
|
1176
|
-
|
|
1177
|
-
mapping = SECTION_TO_SKILL[section_name]
|
|
1178
|
-
|
|
1179
|
-
if mapping is None:
|
|
1180
|
-
# phase-commit -> split into retrospective + committer
|
|
1181
|
-
for skill, name, artifacts in _COMMIT_STEPS:
|
|
1182
|
-
step_id = "S{:02d}".format(step_counter)
|
|
1183
|
-
steps.append({
|
|
1184
|
-
"id": step_id,
|
|
1185
|
-
"skill": skill,
|
|
1186
|
-
"name": name,
|
|
1187
|
-
"status": "pending",
|
|
1188
|
-
"required_artifacts": _resolve_artifacts(artifacts, item_slug),
|
|
1189
|
-
"depends_on": prev_step_id,
|
|
1190
|
-
})
|
|
1191
|
-
prev_step_id = step_id
|
|
1192
|
-
step_counter += 1
|
|
1193
|
-
continue
|
|
1194
|
-
|
|
1195
|
-
skill, name, artifacts = mapping
|
|
1196
|
-
step_id = "S{:02d}".format(step_counter)
|
|
1197
|
-
|
|
1198
|
-
status = "pending"
|
|
1199
|
-
if init_done and section_name in ("phase0-init", "phase0-test-baseline"):
|
|
1200
|
-
status = "skipped"
|
|
1201
|
-
|
|
1202
|
-
steps.append({
|
|
1203
|
-
"id": step_id,
|
|
1204
|
-
"skill": skill,
|
|
1205
|
-
"name": name,
|
|
1206
|
-
"status": status,
|
|
1207
|
-
"required_artifacts": _resolve_artifacts(artifacts, item_slug),
|
|
1208
|
-
"depends_on": prev_step_id,
|
|
1209
|
-
})
|
|
1210
|
-
|
|
1211
|
-
prev_step_id = step_id
|
|
1212
|
-
step_counter += 1
|
|
1213
|
-
|
|
1214
|
-
return {
|
|
1215
|
-
"version": 1,
|
|
1216
|
-
"workflow_type": workflow_type,
|
|
1217
|
-
"pipeline_mode": pipeline_mode,
|
|
1218
|
-
"item_id": item_id,
|
|
1219
|
-
"item_slug": item_slug,
|
|
1220
|
-
"session_id": session_id,
|
|
1221
|
-
"steps": steps,
|
|
1222
|
-
}
|
|
1139
|
+
"""Derive checkpoint step definitions from explicit section contracts."""
|
|
1140
|
+
return generate_checkpoint_from_sections(
|
|
1141
|
+
sections,
|
|
1142
|
+
SECTION_TO_SKILL,
|
|
1143
|
+
pipeline_mode,
|
|
1144
|
+
workflow_type,
|
|
1145
|
+
item_id,
|
|
1146
|
+
item_slug,
|
|
1147
|
+
session_id,
|
|
1148
|
+
init_done=init_done,
|
|
1149
|
+
)
|
|
1223
1150
|
|
|
1224
1151
|
|
|
1225
1152
|
def merge_checkpoint_state(existing, fresh, project_root):
|
|
1226
|
-
"""Merge existing checkpoint state into a freshly generated definition.
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
"""
|
|
1237
|
-
existing_status = {}
|
|
1238
|
-
existing_artifacts = {}
|
|
1239
|
-
fresh_artifacts = {step["skill"]: step.get("required_artifacts", [])
|
|
1240
|
-
for step in fresh.get("steps", [])}
|
|
1241
|
-
for step in existing.get("steps", []):
|
|
1242
|
-
existing_status[step["skill"]] = step["status"]
|
|
1243
|
-
existing_artifacts[step["skill"]] = step.get("required_artifacts", [])
|
|
1244
|
-
|
|
1245
|
-
# Determine which completed steps have valid artifacts. Prefer the freshly
|
|
1246
|
-
# generated artifact contract so newly added gates invalidate older
|
|
1247
|
-
# checkpoint entries that only satisfied a weaker contract.
|
|
1248
|
-
valid_completed = set()
|
|
1249
|
-
for skill_key, status in existing_status.items():
|
|
1250
|
-
if status == "completed":
|
|
1251
|
-
artifacts = fresh_artifacts.get(
|
|
1252
|
-
skill_key, existing_artifacts.get(skill_key, [])
|
|
1253
|
-
)
|
|
1254
|
-
if _completed_step_artifacts_valid(project_root,
|
|
1255
|
-
skill_key,
|
|
1256
|
-
artifacts):
|
|
1257
|
-
valid_completed.add(skill_key)
|
|
1258
|
-
else:
|
|
1259
|
-
LOGGER.warning(
|
|
1260
|
-
"Step '%s' was completed but artifacts missing — "
|
|
1261
|
-
"resetting to pending", skill_key
|
|
1262
|
-
)
|
|
1263
|
-
elif status == "skipped":
|
|
1264
|
-
valid_completed.add(skill_key)
|
|
1265
|
-
|
|
1266
|
-
# Apply to fresh steps; break chain on first non-valid step
|
|
1267
|
-
chain_broken = False
|
|
1268
|
-
for step in fresh["steps"]:
|
|
1269
|
-
if chain_broken:
|
|
1270
|
-
step["status"] = "pending"
|
|
1271
|
-
continue
|
|
1272
|
-
|
|
1273
|
-
prev = existing_status.get(step["skill"])
|
|
1274
|
-
if step["skill"] in valid_completed:
|
|
1275
|
-
step["status"] = prev # completed or skipped
|
|
1276
|
-
else:
|
|
1277
|
-
chain_broken = True
|
|
1278
|
-
step["status"] = "pending"
|
|
1279
|
-
|
|
1280
|
-
return fresh
|
|
1153
|
+
"""Merge existing checkpoint state into a freshly generated definition."""
|
|
1154
|
+
return merge_shared_checkpoint_state(
|
|
1155
|
+
existing,
|
|
1156
|
+
fresh,
|
|
1157
|
+
project_root,
|
|
1158
|
+
validator=lambda skill_key, artifacts: _completed_step_artifacts_valid(
|
|
1159
|
+
project_root, skill_key, artifacts,
|
|
1160
|
+
),
|
|
1161
|
+
logger=LOGGER,
|
|
1162
|
+
)
|
|
1281
1163
|
|
|
1282
1164
|
|
|
1283
1165
|
# ============================================================
|
|
@@ -1297,18 +1179,15 @@ def load_section(sections_dir, name):
|
|
|
1297
1179
|
return f.read()
|
|
1298
1180
|
|
|
1299
1181
|
|
|
1300
|
-
ACTIVE_AGENT_PROMPTS = {
|
|
1301
|
-
"critic-plan-challenge.md": "{{AGENT_PROMPT_CRITIC_PLAN_CHALLENGE}}",
|
|
1302
|
-
}
|
|
1182
|
+
ACTIVE_AGENT_PROMPTS = {}
|
|
1303
1183
|
|
|
1304
1184
|
|
|
1305
1185
|
def load_active_agent_prompts(templates_dir):
|
|
1306
1186
|
"""Load explicit active agent prompt templates.
|
|
1307
1187
|
|
|
1308
|
-
Retired Dev implementation
|
|
1309
|
-
loaded; feature implementation and accepted review fixes
|
|
1310
|
-
the main orchestrator
|
|
1311
|
-
read-only Reviewer handoffs.
|
|
1188
|
+
Retired Dev implementation, review-fix, and plan-challenge prompts are
|
|
1189
|
+
intentionally not loaded; feature implementation and accepted review fixes
|
|
1190
|
+
are performed by the main orchestrator and reviewer gate.
|
|
1312
1191
|
"""
|
|
1313
1192
|
agent_prompts_dir = os.path.join(templates_dir, "agent-prompts")
|
|
1314
1193
|
if not os.path.isdir(agent_prompts_dir):
|
|
@@ -1341,26 +1220,24 @@ def _tier_header(pipeline_mode):
|
|
|
1341
1220
|
),
|
|
1342
1221
|
"standard": (
|
|
1343
1222
|
"# Dev-Pipeline Session Bootstrap — Tier 2 "
|
|
1344
|
-
"(Orchestrator +
|
|
1345
|
-
"**Tier 2 — Orchestrator +
|
|
1346
|
-
"context + planning + implementation directly.
|
|
1347
|
-
"
|
|
1348
|
-
"orchestrator implements directly (P0-6).\n",
|
|
1223
|
+
"(Orchestrator + Reviewer)\n",
|
|
1224
|
+
"**Tier 2 — Orchestrator + Reviewer**: You handle "
|
|
1225
|
+
"context + planning + implementation directly. Reviewer reviews. "
|
|
1226
|
+
"No Dev subagent — orchestrator implements directly (P0-6).\n",
|
|
1349
1227
|
),
|
|
1350
1228
|
"full": (
|
|
1351
1229
|
"# Dev-Pipeline Session Bootstrap — Tier 3 "
|
|
1352
|
-
"(Orchestrator +
|
|
1353
|
-
"**Tier 3 — Orchestrator +
|
|
1230
|
+
"(Orchestrator + Reviewer)\n",
|
|
1231
|
+
"**Tier 3 — Orchestrator + Reviewer**: For complex "
|
|
1354
1232
|
"features, the main orchestrator handles context, planning, "
|
|
1355
|
-
"and implementation directly.
|
|
1356
|
-
"
|
|
1357
|
-
"implementation subagent is spawned.\n",
|
|
1233
|
+
"and implementation directly. Reviewer reviews, and no top-level "
|
|
1234
|
+
"Dev implementation subagent is spawned.\n",
|
|
1358
1235
|
),
|
|
1359
1236
|
}
|
|
1360
1237
|
return headers.get(pipeline_mode, headers["lite"])
|
|
1361
1238
|
|
|
1362
1239
|
|
|
1363
|
-
def _tier_reminders(pipeline_mode
|
|
1240
|
+
def _tier_reminders(pipeline_mode):
|
|
1364
1241
|
"""Return tier-specific reminder text."""
|
|
1365
1242
|
common = [
|
|
1366
1243
|
"- MANDATORY skills: `/prizmkit-retrospective`, `/prizmkit-committer` "
|
|
@@ -1384,9 +1261,8 @@ def _tier_reminders(pipeline_mode, critic_enabled=False):
|
|
|
1384
1261
|
]
|
|
1385
1262
|
elif pipeline_mode == "standard":
|
|
1386
1263
|
specific = [
|
|
1387
|
-
"- Tier 2: orchestrator builds context+plan,
|
|
1388
|
-
"
|
|
1389
|
-
"subagent), Reviewer reviews — see P0-6",
|
|
1264
|
+
"- Tier 2: orchestrator builds context+plan, implements directly "
|
|
1265
|
+
"(no Dev subagent), and Reviewer reviews — see P0-6",
|
|
1390
1266
|
"- context-snapshot.md is append-only: orchestrator writes "
|
|
1391
1267
|
"Sections 1-4 + Implementation Log, Reviewer appends Review Notes",
|
|
1392
1268
|
"- Gate checks enforce Implementation Log (with Gate Evidence) "
|
|
@@ -1399,8 +1275,7 @@ def _tier_reminders(pipeline_mode, critic_enabled=False):
|
|
|
1399
1275
|
else: # full
|
|
1400
1276
|
specific = [
|
|
1401
1277
|
"- Tier 3: full orchestration — orchestrator implements "
|
|
1402
|
-
"directly (no top-level Dev subagent),
|
|
1403
|
-
"plan, Reviewer reviews",
|
|
1278
|
+
"directly (no top-level Dev subagent), and Reviewer reviews",
|
|
1404
1279
|
"- context-snapshot.md is append-only: orchestrator writes "
|
|
1405
1280
|
"Sections 1-4 + Implementation Log, Reviewer appends "
|
|
1406
1281
|
"Review Notes",
|
|
@@ -1417,8 +1292,7 @@ def _tier_reminders(pipeline_mode, critic_enabled=False):
|
|
|
1417
1292
|
|
|
1418
1293
|
|
|
1419
1294
|
def assemble_sections(pipeline_mode, sections_dir, init_done, is_resume,
|
|
1420
|
-
|
|
1421
|
-
browser_tool="auto"):
|
|
1295
|
+
browser_enabled, retry_count=0, browser_tool="auto"):
|
|
1422
1296
|
"""Assemble prompt sections based on tier and conditions.
|
|
1423
1297
|
|
|
1424
1298
|
Uses Python code for conditional logic instead of regex-based
|
|
@@ -1535,16 +1409,6 @@ def assemble_sections(pipeline_mode, sections_dir, init_done, is_resume,
|
|
|
1535
1409
|
load_section(sections_dir,
|
|
1536
1410
|
"phase-plan-agent.md")))
|
|
1537
1411
|
|
|
1538
|
-
# --- Critic: Plan Challenge (only if critic enabled) ---
|
|
1539
|
-
if critic_enabled:
|
|
1540
|
-
if pipeline_mode == "full":
|
|
1541
|
-
sections.append(("phase-critic-plan",
|
|
1542
|
-
load_section(sections_dir,
|
|
1543
|
-
"phase-critic-plan-full.md")))
|
|
1544
|
-
else:
|
|
1545
|
-
sections.append(("phase-critic-plan",
|
|
1546
|
-
load_section(sections_dir,
|
|
1547
|
-
"phase-critic-plan.md")))
|
|
1548
1412
|
|
|
1549
1413
|
# --- Implement (tier-dependent) ---
|
|
1550
1414
|
if pipeline_mode == "lite":
|
|
@@ -1626,7 +1490,7 @@ def assemble_sections(pipeline_mode, sections_dir, init_done, is_resume,
|
|
|
1626
1490
|
|
|
1627
1491
|
# --- Reminders ---
|
|
1628
1492
|
sections.append(("reminders",
|
|
1629
|
-
_tier_reminders(pipeline_mode
|
|
1493
|
+
_tier_reminders(pipeline_mode)))
|
|
1630
1494
|
|
|
1631
1495
|
return sections
|
|
1632
1496
|
|
|
@@ -1639,10 +1503,8 @@ def render_from_sections(sections, replacements):
|
|
|
1639
1503
|
"""
|
|
1640
1504
|
content = "\n".join(text for _, text in sections)
|
|
1641
1505
|
|
|
1642
|
-
# Replace all placeholders — run twice to handle active
|
|
1643
|
-
#
|
|
1644
|
-
# injects prompt content (for example, Critic plan challenge text); second
|
|
1645
|
-
# pass replaces inner feature/session variables.
|
|
1506
|
+
# Replace all placeholders — run twice to handle active prompt fragments
|
|
1507
|
+
# that may contain their own {{PLACEHOLDER}} variables.
|
|
1646
1508
|
for _pass in range(2):
|
|
1647
1509
|
for placeholder, value in replacements.items():
|
|
1648
1510
|
content = content.replace(placeholder, value)
|
|
@@ -1746,9 +1608,6 @@ def build_replacements(args, feature, features, global_context, script_dir):
|
|
|
1746
1608
|
reviewer_subagent = os.path.join(
|
|
1747
1609
|
agents_dir, f"prizm-dev-team-reviewer{agent_ext}",
|
|
1748
1610
|
)
|
|
1749
|
-
critic_subagent = os.path.join(
|
|
1750
|
-
agents_dir, f"prizm-dev-team-critic{agent_ext}",
|
|
1751
|
-
)
|
|
1752
1611
|
|
|
1753
1612
|
# Verify agent files actually exist — missing files cause confusing
|
|
1754
1613
|
# errors when the AI session tries to read them later.
|
|
@@ -1802,40 +1661,6 @@ def build_replacements(args, feature, features, global_context, script_dir):
|
|
|
1802
1661
|
if effective_resume == "null" and artifacts["all_complete"]:
|
|
1803
1662
|
effective_resume = "6"
|
|
1804
1663
|
|
|
1805
|
-
# Determine critic enablement (priority: CLI > env > feature field > default)
|
|
1806
|
-
critic_env = os.environ.get("ENABLE_CRITIC", "").lower()
|
|
1807
|
-
if args.critic is not None:
|
|
1808
|
-
critic_enabled = args.critic == "true"
|
|
1809
|
-
elif critic_env in ("true", "1"):
|
|
1810
|
-
critic_enabled = True
|
|
1811
|
-
elif critic_env in ("false", "0"):
|
|
1812
|
-
critic_enabled = False
|
|
1813
|
-
else:
|
|
1814
|
-
critic_enabled = bool(feature.get("critic", False))
|
|
1815
|
-
|
|
1816
|
-
# Determine critic count (from feature field, default 1)
|
|
1817
|
-
# Multi-critic voting (3) must be explicitly set by the user in .prizmkit/plans/feature-list.json
|
|
1818
|
-
critic_count = feature.get("critic_count", 1)
|
|
1819
|
-
|
|
1820
|
-
# Guard: if critic enabled but agent file missing, force disable and warn
|
|
1821
|
-
if critic_enabled and not os.path.isfile(critic_subagent):
|
|
1822
|
-
LOGGER.warning(
|
|
1823
|
-
"Critic enabled but agent file not found: %s. "
|
|
1824
|
-
"Critic phases will be SKIPPED. "
|
|
1825
|
-
"Run `npx prizmkit install` to install agent definitions.",
|
|
1826
|
-
critic_subagent,
|
|
1827
|
-
)
|
|
1828
|
-
critic_enabled = False
|
|
1829
|
-
|
|
1830
|
-
# Guard: if critic enabled but tier doesn't support it (lite), warn and disable
|
|
1831
|
-
if critic_enabled and pipeline_mode == "lite":
|
|
1832
|
-
LOGGER.warning(
|
|
1833
|
-
"Critic enabled for feature %s but pipeline_mode='lite' (tier1) "
|
|
1834
|
-
"does not support critic phases. Critic will be SKIPPED. "
|
|
1835
|
-
"Use estimated_complexity='high' or pass --mode standard/full.",
|
|
1836
|
-
args.feature_id,
|
|
1837
|
-
)
|
|
1838
|
-
critic_enabled = False
|
|
1839
1664
|
|
|
1840
1665
|
# Browser verification defaults to a mandatory attempt. It is disabled only
|
|
1841
1666
|
# by BROWSER_VERIFY=false or browser_interaction.enabled=false.
|
|
@@ -1888,7 +1713,6 @@ def build_replacements(args, feature, features, global_context, script_dir):
|
|
|
1888
1713
|
"{{TEAM_CONFIG_PATH}}": team_config_path,
|
|
1889
1714
|
"{{DEV_SUBAGENT_PATH}}": dev_subagent,
|
|
1890
1715
|
"{{REVIEWER_SUBAGENT_PATH}}": reviewer_subagent,
|
|
1891
|
-
"{{CRITIC_SUBAGENT_PATH}}": critic_subagent,
|
|
1892
1716
|
"{{INIT_SCRIPT_PATH}}": init_script_path,
|
|
1893
1717
|
"{{SESSION_STATUS_PATH}}": session_status_abs,
|
|
1894
1718
|
"{{PROJECT_ROOT}}": project_root,
|
|
@@ -1899,8 +1723,6 @@ def build_replacements(args, feature, features, global_context, script_dir):
|
|
|
1899
1723
|
),
|
|
1900
1724
|
"{{PIPELINE_MODE}}": pipeline_mode,
|
|
1901
1725
|
"{{COMPLEXITY}}": complexity,
|
|
1902
|
-
"{{CRITIC_ENABLED}}": "true" if critic_enabled else "false",
|
|
1903
|
-
"{{CRITIC_COUNT}}": str(critic_count),
|
|
1904
1726
|
"{{INIT_DONE}}": "true" if init_done else "false",
|
|
1905
1727
|
"{{HAS_SPEC}}": "true" if artifacts["has_spec"] else "false",
|
|
1906
1728
|
"{{HAS_PLAN}}": "true" if artifacts["has_plan"] else "false",
|
|
@@ -1932,11 +1754,10 @@ def render_template(template_content, replacements, resume_phase,
|
|
|
1932
1754
|
# Step 1: Process fresh_start/resume conditional blocks
|
|
1933
1755
|
content = process_conditional_blocks(template_content, resume_phase)
|
|
1934
1756
|
|
|
1935
|
-
# Step 2: Process mode, init,
|
|
1757
|
+
# Step 2: Process mode, init, and browser conditional blocks
|
|
1936
1758
|
pipeline_mode = replacements.get("{{PIPELINE_MODE}}", "standard")
|
|
1937
1759
|
init_done = replacements.get("{{INIT_DONE}}", "false") == "true"
|
|
1938
|
-
|
|
1939
|
-
content = process_mode_blocks(content, pipeline_mode, init_done, critic_enabled,
|
|
1760
|
+
content = process_mode_blocks(content, pipeline_mode, init_done,
|
|
1940
1761
|
browser_enabled, browser_tool)
|
|
1941
1762
|
|
|
1942
1763
|
# Step 3: Replace all {{PLACEHOLDER}} variables (two passes for nested
|
|
@@ -2012,8 +1833,6 @@ def main():
|
|
|
2012
1833
|
pipeline_mode = replacements.get("{{PIPELINE_MODE}}", "lite")
|
|
2013
1834
|
init_done = replacements.get("{{INIT_DONE}}", "false") == "true"
|
|
2014
1835
|
is_resume = effective_resume != "null"
|
|
2015
|
-
critic_enabled = replacements.get("{{CRITIC_ENABLED}}", "false") == "true"
|
|
2016
|
-
|
|
2017
1836
|
# ── Choose rendering path ──────────────────────────────────────────
|
|
2018
1837
|
use_sections = os.path.isdir(sections_dir) and not args.template
|
|
2019
1838
|
|
|
@@ -2023,7 +1842,7 @@ def main():
|
|
|
2023
1842
|
try:
|
|
2024
1843
|
sections = assemble_sections(
|
|
2025
1844
|
pipeline_mode, sections_dir, init_done, is_resume,
|
|
2026
|
-
|
|
1845
|
+
browser_enabled,
|
|
2027
1846
|
retry_count=int(args.retry_count),
|
|
2028
1847
|
browser_tool=browser_tool,
|
|
2029
1848
|
)
|
|
@@ -2140,16 +1959,12 @@ def main():
|
|
|
2140
1959
|
feature_model = feature.get("model", "")
|
|
2141
1960
|
mode_agent_counts = {"lite": 1, "standard": 3, "full": 3}
|
|
2142
1961
|
agent_count = mode_agent_counts.get(pipeline_mode, 1)
|
|
2143
|
-
critic_count_val = int(replacements.get("{{CRITIC_COUNT}}", "1"))
|
|
2144
|
-
if critic_enabled:
|
|
2145
|
-
agent_count += critic_count_val
|
|
2146
1962
|
output = {
|
|
2147
1963
|
"success": True,
|
|
2148
1964
|
"output_path": os.path.abspath(args.output),
|
|
2149
1965
|
"model": feature_model,
|
|
2150
1966
|
"pipeline_mode": pipeline_mode,
|
|
2151
1967
|
"agent_count": agent_count,
|
|
2152
|
-
"critic_enabled": "true" if critic_enabled else "false",
|
|
2153
1968
|
"render_mode": "sections" if use_sections else "legacy",
|
|
2154
1969
|
"validation_warnings": len(warnings),
|
|
2155
1970
|
"validation_errors": len(errors),
|