prizmkit 1.1.153 → 1.1.155
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/codex/skill-adapter.js +1 -1
- package/bundled/adapters/pi/skill-adapter.js +2 -1
- package/bundled/dev-pipeline/.env.example +2 -6
- package/bundled/dev-pipeline/README.md +120 -113
- package/bundled/dev-pipeline/assets/skill-subagent-integration.md +1 -1
- package/bundled/dev-pipeline/prizmkit_runtime/checkpoint_state.py +355 -15
- package/bundled/dev-pipeline/prizmkit_runtime/cli.py +189 -110
- package/bundled/dev-pipeline/prizmkit_runtime/commands.py +146 -111
- package/bundled/dev-pipeline/prizmkit_runtime/daemon.py +4 -20
- package/bundled/dev-pipeline/prizmkit_runtime/gitops.py +48 -14
- package/bundled/dev-pipeline/prizmkit_runtime/interoperability.py +0 -1
- package/bundled/dev-pipeline/prizmkit_runtime/paths.py +0 -3
- package/bundled/dev-pipeline/prizmkit_runtime/reset.py +122 -15
- package/bundled/dev-pipeline/prizmkit_runtime/reset_preserve.py +1 -1
- package/bundled/dev-pipeline/prizmkit_runtime/runner_classification.py +50 -2
- package/bundled/dev-pipeline/prizmkit_runtime/runner_models.py +1 -10
- package/bundled/dev-pipeline/prizmkit_runtime/runner_prompts.py +3 -3
- package/bundled/dev-pipeline/prizmkit_runtime/runners.py +139 -74
- package/bundled/dev-pipeline/prizmkit_runtime/runtime_commit.py +482 -0
- package/bundled/dev-pipeline/prizmkit_runtime/status.py +106 -1
- package/bundled/dev-pipeline/prizmkit_runtime/test_result.py +64 -11
- package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +145 -367
- package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +91 -62
- package/bundled/dev-pipeline/scripts/generate-refactor-prompt.py +105 -69
- package/bundled/dev-pipeline/scripts/init-bugfix-pipeline.py +2 -2
- package/bundled/dev-pipeline/scripts/prompt_framework.py +36 -41
- package/bundled/dev-pipeline/scripts/update-bug-status.py +197 -71
- package/bundled/dev-pipeline/scripts/update-checkpoint.py +77 -16
- package/bundled/dev-pipeline/scripts/update-feature-status.py +46 -121
- package/bundled/dev-pipeline/scripts/update-refactor-status.py +46 -123
- package/bundled/dev-pipeline/scripts/utils.py +119 -0
- package/bundled/dev-pipeline/templates/bootstrap-prompt.md +22 -27
- package/bundled/dev-pipeline/templates/bootstrap-tier3.md +71 -104
- package/bundled/dev-pipeline/templates/bug-fix-list-schema.json +3 -2
- package/bundled/dev-pipeline/templates/bugfix-bootstrap-prompt.md +59 -111
- package/bundled/dev-pipeline/templates/refactor-bootstrap-prompt.md +37 -72
- package/bundled/dev-pipeline/templates/sections/artifact-manifest.md +39 -0
- package/bundled/dev-pipeline/templates/sections/bugfix-critical-paths.md +3 -1
- package/bundled/dev-pipeline/templates/sections/bugfix-phase-commit-report.md +8 -25
- package/bundled/dev-pipeline/templates/sections/bugfix-phase-diagnose-plan.md +3 -3
- package/bundled/dev-pipeline/templates/sections/bugfix-phase-implement.md +2 -2
- package/bundled/dev-pipeline/templates/sections/bugfix-phase-review.md +3 -3
- package/bundled/dev-pipeline/templates/sections/bugfix-phase-test.md +2 -2
- package/bundled/dev-pipeline/templates/sections/bugfix-reminders.md +4 -4
- package/bundled/dev-pipeline/templates/sections/bugfix-session-context.md +0 -1
- package/bundled/dev-pipeline/templates/sections/checkpoint-system.md +7 -4
- package/bundled/dev-pipeline/templates/sections/context-budget-rules.md +14 -27
- package/bundled/dev-pipeline/templates/sections/feature-completion-summary.md +20 -0
- package/bundled/dev-pipeline/templates/sections/phase-commit-full.md +8 -71
- package/bundled/dev-pipeline/templates/sections/phase-implement-full.md +7 -7
- package/bundled/dev-pipeline/templates/sections/phase-prizmkit-test.md +3 -3
- package/bundled/dev-pipeline/templates/sections/phase-review-full.md +4 -4
- package/bundled/dev-pipeline/templates/sections/phase-specify-plan-full.md +5 -17
- package/bundled/dev-pipeline/templates/sections/refactor-critical-paths.md +3 -1
- package/bundled/dev-pipeline/templates/sections/refactor-phase-commit-report.md +10 -23
- package/bundled/dev-pipeline/templates/sections/refactor-phase-implement.md +2 -2
- package/bundled/dev-pipeline/templates/sections/refactor-phase-plan.md +2 -2
- package/bundled/dev-pipeline/templates/sections/refactor-phase-review.md +3 -3
- package/bundled/dev-pipeline/templates/sections/refactor-phase-test.md +2 -2
- package/bundled/dev-pipeline/templates/sections/refactor-reminders.md +7 -7
- package/bundled/dev-pipeline/templates/sections/refactor-session-context.md +0 -1
- package/bundled/dev-pipeline/templates/sections/retrospective.md +12 -0
- package/bundled/dev-pipeline/templates/sections/runtime-commit-handoff.md +35 -0
- package/bundled/dev-pipeline/templates/session-status-schema.json +45 -62
- package/bundled/dev-pipeline/tests/test_auto_skip.py +111 -32
- package/bundled/dev-pipeline/tests/test_checkpoint_state.py +617 -30
- package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +262 -194
- package/bundled/dev-pipeline/tests/test_generate_bugfix_prompt.py +62 -23
- package/bundled/dev-pipeline/tests/test_generate_refactor_prompt.py +76 -28
- package/bundled/dev-pipeline/tests/test_python_runner_parity.py +281 -206
- package/bundled/dev-pipeline/tests/test_recovery_workflow.py +322 -0
- package/bundled/dev-pipeline/tests/test_reset_modes.py +935 -0
- package/bundled/dev-pipeline/tests/test_reset_preserve.py +5 -7
- package/bundled/dev-pipeline/tests/test_runtime_commit.py +608 -0
- package/bundled/dev-pipeline/tests/test_unified_cli.py +617 -188
- package/bundled/skills/_metadata.json +9 -9
- package/bundled/skills/app-planner/SKILL.md +3 -3
- package/bundled/skills/app-planner/references/generated-plan-review.md +2 -1
- package/bundled/skills/app-planner/references/rules/backend/derivation-rules.md +56 -64
- package/bundled/skills/app-planner/references/rules/backend/fixed-rules.md +85 -240
- package/bundled/skills/app-planner/references/rules/backend/question-bank.md +25 -25
- package/bundled/skills/app-planner/references/rules/backend/question-manifest.json +16 -7
- package/bundled/skills/app-planner/references/rules/backend/template.md +74 -92
- package/bundled/skills/app-planner/references/rules/database/derivation-rules.md +93 -93
- package/bundled/skills/app-planner/references/rules/database/fixed-rules.md +66 -173
- package/bundled/skills/app-planner/references/rules/database/question-bank.md +31 -26
- package/bundled/skills/app-planner/references/rules/database/question-manifest.json +13 -4
- package/bundled/skills/app-planner/references/rules/database/template.md +76 -98
- package/bundled/skills/app-planner/references/rules/frontend/derivation-rules.md +68 -95
- package/bundled/skills/app-planner/references/rules/frontend/fixed-rules.md +93 -166
- package/bundled/skills/app-planner/references/rules/frontend/question-bank.md +46 -36
- package/bundled/skills/app-planner/references/rules/frontend/question-manifest.json +11 -2
- package/bundled/skills/app-planner/references/rules/frontend/template.md +79 -257
- package/bundled/skills/app-planner/references/rules/mobile/derivation-rules.md +91 -99
- package/bundled/skills/app-planner/references/rules/mobile/fixed-rules.md +73 -246
- package/bundled/skills/app-planner/references/rules/mobile/question-bank.md +17 -17
- package/bundled/skills/app-planner/references/rules/mobile/question-manifest.json +17 -2
- package/bundled/skills/app-planner/references/rules/mobile/template.md +73 -85
- package/bundled/skills/app-planner/references/rules-configuration.md +133 -65
- package/bundled/skills/app-planner/scripts/validate-rules-configuration.py +291 -0
- package/bundled/skills/bug-planner/references/schema-validation.md +1 -1
- package/bundled/skills/bug-planner/scripts/validate-bug-list.py +1 -1
- package/bundled/skills/bugfix-pipeline-launcher/SKILL.md +21 -13
- package/bundled/skills/feature-pipeline-launcher/SKILL.md +22 -14
- package/bundled/skills/prizmkit/SKILL.md +17 -18
- package/bundled/skills/prizmkit/references/workflow-state-protocol.md +22 -18
- package/bundled/skills/prizmkit-code-review/SKILL.md +22 -58
- package/bundled/skills/prizmkit-code-review/references/independent-code-review.md +6 -6
- package/bundled/skills/prizmkit-code-review/references/review-report-template.md +2 -2
- package/bundled/skills/prizmkit-committer/SKILL.md +82 -132
- package/bundled/skills/prizmkit-deploy/SKILL.md +27 -11
- package/bundled/skills/prizmkit-deploy/assets/deploy-document-template.md +89 -0
- package/bundled/skills/prizmkit-deploy/references/ci-cd-workflows.md +44 -14
- package/bundled/skills/prizmkit-deploy/references/cloud-platform-deploy.md +19 -3
- package/bundled/skills/prizmkit-deploy/references/database-setup.md +22 -12
- package/bundled/skills/prizmkit-deploy/references/deploy-config-schema.md +3 -1
- package/bundled/skills/prizmkit-deploy/references/deploy-history-schema.md +22 -6
- package/bundled/skills/prizmkit-deploy/references/deploy-metadata-schema.json +49 -0
- package/bundled/skills/prizmkit-deploy/references/live-validation-notes.md +1 -1
- package/bundled/skills/prizmkit-deploy/references/pending-input-schema.json +164 -0
- package/bundled/skills/prizmkit-deploy/references/ssh-adapter-flow.md +9 -8
- package/bundled/skills/prizmkit-deploy/references/ssh-execution-flow.md +6 -6
- package/bundled/skills/prizmkit-implement/SKILL.md +30 -66
- package/bundled/skills/prizmkit-implement/references/implementation-subagent-procedure.md +4 -4
- package/bundled/skills/prizmkit-init/SKILL.md +4 -0
- package/bundled/skills/prizmkit-plan/SKILL.md +21 -64
- package/bundled/skills/prizmkit-plan/references/artifact-identity.md +38 -0
- package/bundled/skills/prizmkit-plan/references/independent-plan-review.md +4 -4
- package/bundled/skills/prizmkit-plan/references/review-plan-spec-loop.md +5 -5
- package/bundled/skills/prizmkit-prizm-docs/SKILL.md +11 -1
- package/bundled/skills/prizmkit-retrospective/SKILL.md +63 -77
- package/bundled/skills/prizmkit-retrospective/references/knowledge-injection-steps.md +3 -3
- package/bundled/skills/prizmkit-retrospective/references/retrospective-result-schema.json +138 -0
- package/bundled/skills/prizmkit-retrospective/references/structural-sync-steps.md +17 -23
- package/bundled/skills/prizmkit-test/SKILL.md +64 -51
- package/bundled/skills/prizmkit-test/references/boundary-contract-and-test-double-guidance.md +206 -0
- package/bundled/skills/prizmkit-test/references/independent-test-review.md +17 -9
- package/bundled/skills/prizmkit-test/references/test-coverage-model.md +45 -21
- package/bundled/skills/prizmkit-test/references/test-report-template.md +20 -13
- package/bundled/skills/prizmkit-workflow/SKILL.md +35 -37
- package/bundled/skills/prizmkit-workflow/references/artifact-identity.md +34 -0
- package/bundled/skills/prizmkit-workflow/references/workflow-state-protocol.md +22 -18
- package/bundled/skills/recovery-workflow/SKILL.md +9 -6
- package/bundled/skills/recovery-workflow/evals/evals.json +2 -2
- package/bundled/skills/recovery-workflow/references/detection.md +7 -6
- package/bundled/skills/recovery-workflow/scripts/detect-recovery-state.py +16 -6
- package/bundled/skills/refactor-pipeline-launcher/SKILL.md +21 -13
- package/bundled/templates/project-memory-template.md +19 -11
- package/package.json +1 -1
- package/src/scaffold.js +33 -22
- package/bundled/dev-pipeline/prizmkit_runtime/runner_recovery.py +0 -228
- package/bundled/dev-pipeline/scripts/generate-recovery-prompt.py +0 -767
- package/bundled/dev-pipeline/templates/sections/bugfix-artifacts.md +0 -16
- package/bundled/dev-pipeline/templates/sections/bugfix-session-status.md +0 -31
- package/bundled/dev-pipeline/templates/sections/critical-paths-agent.md +0 -7
- package/bundled/dev-pipeline/templates/sections/critical-paths-lite.md +0 -7
- package/bundled/dev-pipeline/templates/sections/directory-convention-agent.md +0 -9
- package/bundled/dev-pipeline/templates/sections/directory-convention-lite.md +0 -6
- package/bundled/dev-pipeline/templates/sections/headless-commit-authorization.md +0 -15
- package/bundled/dev-pipeline/templates/sections/phase-commit.md +0 -61
- package/bundled/dev-pipeline/templates/sections/phase-context-snapshot-agent-suffix.md +0 -24
- package/bundled/dev-pipeline/templates/sections/phase-context-snapshot-lite-suffix.md +0 -12
- package/bundled/dev-pipeline/templates/sections/phase-implement-agent.md +0 -44
- package/bundled/dev-pipeline/templates/sections/phase-implement-lite.md +0 -25
- package/bundled/dev-pipeline/templates/sections/phase-plan-agent.md +0 -20
- package/bundled/dev-pipeline/templates/sections/phase-plan-lite.md +0 -20
- package/bundled/dev-pipeline/templates/sections/phase-review-agent.md +0 -20
- package/bundled/dev-pipeline/templates/sections/refactor-artifacts.md +0 -17
- package/bundled/dev-pipeline/templates/sections/refactor-session-status.md +0 -28
- package/bundled/dev-pipeline/templates/sections/test-failure-recovery-agent.md +0 -52
- package/bundled/dev-pipeline/templates/sections/test-failure-recovery-lite.md +0 -52
- package/bundled/skills/prizmkit-code-review/references/workflow-state-protocol.md +0 -174
- package/bundled/skills/prizmkit-committer/references/workflow-state-protocol.md +0 -174
- package/bundled/skills/prizmkit-implement/references/workflow-state-protocol.md +0 -174
- package/bundled/skills/prizmkit-plan/references/workflow-state-protocol.md +0 -174
- package/bundled/skills/prizmkit-retrospective/references/workflow-state-protocol.md +0 -174
- package/bundled/skills/prizmkit-test/references/external-contract-mock-guidance.md +0 -119
|
@@ -38,8 +38,11 @@ class ResetOptions:
|
|
|
38
38
|
item_id: str = ""
|
|
39
39
|
item_range: tuple[str, str] | None = None
|
|
40
40
|
filter_mode: str = ""
|
|
41
|
+
state_only: bool = False
|
|
42
|
+
fresh_checkout: bool = False
|
|
41
43
|
clean: bool = False
|
|
42
44
|
preserve_runtime: bool = False
|
|
45
|
+
all_items: bool = False
|
|
43
46
|
help_requested: bool = False
|
|
44
47
|
unknown_args: tuple[str, ...] = ()
|
|
45
48
|
|
|
@@ -112,7 +115,7 @@ def run_reset_command(kind: str, legacy_args: tuple[str, ...], paths) -> Command
|
|
|
112
115
|
list_path = _resolve_list_path(options.list_path, paths.project_root)
|
|
113
116
|
if not list_path.is_file():
|
|
114
117
|
return CommandResult(1, f"Python {kind} reset", f"{kind} list not found: {list_path}")
|
|
115
|
-
if
|
|
118
|
+
if (options.fresh_checkout or options.clean) and not (family.state_dir / "pipeline.json").is_file():
|
|
116
119
|
return CommandResult(1, f"Python {kind} reset", f"No pipeline state found. Run the {kind} pipeline first to initialize.")
|
|
117
120
|
|
|
118
121
|
options = ResetOptions(
|
|
@@ -120,8 +123,11 @@ def run_reset_command(kind: str, legacy_args: tuple[str, ...], paths) -> Command
|
|
|
120
123
|
item_id=options.item_id,
|
|
121
124
|
item_range=options.item_range,
|
|
122
125
|
filter_mode=options.filter_mode,
|
|
126
|
+
state_only=options.state_only,
|
|
127
|
+
fresh_checkout=options.fresh_checkout,
|
|
123
128
|
clean=options.clean,
|
|
124
129
|
preserve_runtime=options.preserve_runtime,
|
|
130
|
+
all_items=options.all_items,
|
|
125
131
|
help_requested=options.help_requested,
|
|
126
132
|
unknown_args=options.unknown_args,
|
|
127
133
|
)
|
|
@@ -140,6 +146,16 @@ def run_reset_command(kind: str, legacy_args: tuple[str, ...], paths) -> Command
|
|
|
140
146
|
text,
|
|
141
147
|
stdout=text,
|
|
142
148
|
)
|
|
149
|
+
if options.state_only:
|
|
150
|
+
state_result = _run_state_only_updater(family, options, paths.project_root)
|
|
151
|
+
text = state_result.stdout.strip() or state_result.stderr.strip() or "State-only reset failed"
|
|
152
|
+
ok = state_result.returncode == 0 and _json_without_error(state_result.stdout)
|
|
153
|
+
return CommandResult(
|
|
154
|
+
0 if ok else 1,
|
|
155
|
+
f"Python {kind} reset --state-only",
|
|
156
|
+
text,
|
|
157
|
+
stdout=text,
|
|
158
|
+
)
|
|
143
159
|
|
|
144
160
|
try:
|
|
145
161
|
items = _resolve_items(family, options)
|
|
@@ -174,8 +190,11 @@ def _parse_reset_args(family: RunnerFamily, legacy_args: Sequence[str]) -> Reset
|
|
|
174
190
|
item_id = ""
|
|
175
191
|
item_range: tuple[str, str] | None = None
|
|
176
192
|
filter_mode = ""
|
|
193
|
+
state_only = False
|
|
194
|
+
fresh_checkout = False
|
|
177
195
|
clean = False
|
|
178
196
|
preserve_runtime = False
|
|
197
|
+
all_items = False
|
|
179
198
|
help_requested = False
|
|
180
199
|
unknown: list[str] = []
|
|
181
200
|
positional: list[str] = []
|
|
@@ -183,16 +202,22 @@ def _parse_reset_args(family: RunnerFamily, legacy_args: Sequence[str]) -> Reset
|
|
|
183
202
|
index = 0
|
|
184
203
|
while index < len(args):
|
|
185
204
|
arg = args[index]
|
|
186
|
-
if arg in {"--help", "-h"
|
|
205
|
+
if arg in {"--help", "-h"}:
|
|
187
206
|
help_requested = True
|
|
207
|
+
elif arg == "--state-only":
|
|
208
|
+
state_only = True
|
|
209
|
+
elif arg == "--fresh-checkout":
|
|
210
|
+
fresh_checkout = True
|
|
188
211
|
elif arg == "--clean":
|
|
189
212
|
clean = True
|
|
190
213
|
elif arg == "--preserve-runtime":
|
|
191
214
|
preserve_runtime = True
|
|
215
|
+
elif arg == "--all":
|
|
216
|
+
all_items = True
|
|
192
217
|
elif arg == "--run":
|
|
193
218
|
raise ValueError(
|
|
194
219
|
"Reset no longer accepts --run. Run reset first, then execute "
|
|
195
|
-
f"`{family.kind}
|
|
220
|
+
f"`run {family.kind}` as a separate command."
|
|
196
221
|
)
|
|
197
222
|
elif arg in FILTER_FLAGS:
|
|
198
223
|
next_filter = FILTER_FLAGS[arg]
|
|
@@ -208,9 +233,15 @@ def _parse_reset_args(family: RunnerFamily, legacy_args: Sequence[str]) -> Reset
|
|
|
208
233
|
|
|
209
234
|
for value in positional:
|
|
210
235
|
if _looks_like_range(value, family.id_prefix):
|
|
211
|
-
item_range
|
|
212
|
-
|
|
213
|
-
|
|
236
|
+
if item_range is None and not item_id:
|
|
237
|
+
item_range = _normalize_range(value, family.id_prefix)
|
|
238
|
+
else:
|
|
239
|
+
unknown.append(value)
|
|
240
|
+
elif _looks_like_item_id(value, family.id_prefix):
|
|
241
|
+
if not item_id and item_range is None:
|
|
242
|
+
item_id = _normalize_item_id(value, family.id_prefix)
|
|
243
|
+
else:
|
|
244
|
+
unknown.append(value)
|
|
214
245
|
elif list_path == family.plan_path:
|
|
215
246
|
list_path = Path(value).expanduser()
|
|
216
247
|
else:
|
|
@@ -221,8 +252,11 @@ def _parse_reset_args(family: RunnerFamily, legacy_args: Sequence[str]) -> Reset
|
|
|
221
252
|
item_id=item_id,
|
|
222
253
|
item_range=item_range,
|
|
223
254
|
filter_mode=filter_mode,
|
|
255
|
+
state_only=state_only,
|
|
256
|
+
fresh_checkout=fresh_checkout,
|
|
224
257
|
clean=clean,
|
|
225
258
|
preserve_runtime=preserve_runtime,
|
|
259
|
+
all_items=all_items,
|
|
226
260
|
help_requested=help_requested,
|
|
227
261
|
unknown_args=tuple(unknown),
|
|
228
262
|
)
|
|
@@ -231,14 +265,51 @@ def _parse_reset_args(family: RunnerFamily, legacy_args: Sequence[str]) -> Reset
|
|
|
231
265
|
def _reset_option_error(family: RunnerFamily, options: ResetOptions) -> str:
|
|
232
266
|
if options.unknown_args:
|
|
233
267
|
return "Unsupported reset arguments: " + " ".join(options.unknown_args)
|
|
234
|
-
|
|
268
|
+
|
|
269
|
+
selected_modes = [
|
|
270
|
+
name
|
|
271
|
+
for name, enabled in (
|
|
272
|
+
("--state-only", options.state_only),
|
|
273
|
+
("--fresh-checkout", options.fresh_checkout),
|
|
274
|
+
("--clean", options.clean),
|
|
275
|
+
("--preserve-runtime", options.preserve_runtime),
|
|
276
|
+
)
|
|
277
|
+
if enabled
|
|
278
|
+
]
|
|
279
|
+
if len(selected_modes) != 1:
|
|
280
|
+
return (
|
|
281
|
+
"Exactly one reset mode is required: --state-only, --fresh-checkout, "
|
|
282
|
+
"--clean, or --preserve-runtime.\n" + _help_text(family)
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
selectors = sum(
|
|
286
|
+
bool(value)
|
|
287
|
+
for value in (
|
|
288
|
+
options.item_id,
|
|
289
|
+
options.item_range,
|
|
290
|
+
options.filter_mode,
|
|
291
|
+
options.all_items,
|
|
292
|
+
)
|
|
293
|
+
)
|
|
294
|
+
if options.state_only:
|
|
295
|
+
if options.item_range or options.filter_mode:
|
|
296
|
+
return "--state-only accepts only one item ID or explicit --all; ranges and status filters are unsupported."
|
|
297
|
+
if selectors != 1 or not (options.item_id or options.all_items):
|
|
298
|
+
return "--state-only requires exactly one item ID or explicit --all."
|
|
299
|
+
return ""
|
|
300
|
+
|
|
301
|
+
if options.fresh_checkout or options.clean:
|
|
302
|
+
if options.all_items:
|
|
303
|
+
return "--all is supported only with --state-only."
|
|
304
|
+
if selectors != 1:
|
|
305
|
+
mode = "--clean" if options.clean else "--fresh-checkout"
|
|
306
|
+
return f"{mode} requires exactly one item ID, range, or supported status filter."
|
|
235
307
|
return ""
|
|
308
|
+
|
|
236
309
|
if options.filter_mode != "failed":
|
|
237
310
|
return "--preserve-runtime requires --failed and cannot be used with another reset filter."
|
|
238
|
-
if options.
|
|
239
|
-
return "--preserve-runtime and
|
|
240
|
-
if options.item_id or options.item_range:
|
|
241
|
-
return "--preserve-runtime is a whole-list failed-chain reset and cannot target an ID or range."
|
|
311
|
+
if options.item_id or options.item_range or options.all_items:
|
|
312
|
+
return "--preserve-runtime is a whole-list failed-chain reset and cannot target an ID, range, or --all."
|
|
242
313
|
return ""
|
|
243
314
|
|
|
244
315
|
|
|
@@ -282,6 +353,8 @@ def _resolve_items(family: RunnerFamily, options: ResetOptions) -> tuple[ResetIt
|
|
|
282
353
|
for item_id in ids:
|
|
283
354
|
item = by_id.get(item_id)
|
|
284
355
|
if not isinstance(item, dict):
|
|
356
|
+
if options.item_id:
|
|
357
|
+
raise ValueError(f"{FAMILY_LABELS[family.kind].title()} '{item_id}' not found in {options.list_path}")
|
|
285
358
|
continue
|
|
286
359
|
title = str(item.get(TITLE_FIELD_BY_KIND[family.kind]) or "")
|
|
287
360
|
resolved.append(ResetItem(item_id=item_id, title=title, slug=_slug_for_item(family, item_id, title), status=str(item.get("status") or "unknown")))
|
|
@@ -339,6 +412,8 @@ def _reset_one(family: RunnerFamily, item: ResetItem, options: ResetOptions, pro
|
|
|
339
412
|
except RuntimeError as exc:
|
|
340
413
|
lines.append(f"ERROR: Reset {item.item_id} checkout identity failed: {exc}")
|
|
341
414
|
return False
|
|
415
|
+
if options.fresh_checkout:
|
|
416
|
+
lines.append(f"Fresh-checkout boundary published for {item.item_id}")
|
|
342
417
|
lines.append(f"{item.item_id} {action} complete: status -> pending, retry count -> 0")
|
|
343
418
|
return True
|
|
344
419
|
error = _error_text(result.stdout) or result.stderr.strip() or "unknown"
|
|
@@ -346,6 +421,33 @@ def _reset_one(family: RunnerFamily, item: ResetItem, options: ResetOptions, pro
|
|
|
346
421
|
return False
|
|
347
422
|
|
|
348
423
|
|
|
424
|
+
def _run_state_only_updater(
|
|
425
|
+
family: RunnerFamily,
|
|
426
|
+
options: ResetOptions,
|
|
427
|
+
project_root: Path,
|
|
428
|
+
) -> subprocess.CompletedProcess[str]:
|
|
429
|
+
command = [
|
|
430
|
+
sys.executable,
|
|
431
|
+
str(family.updater_script),
|
|
432
|
+
family.list_arg,
|
|
433
|
+
str(options.list_path),
|
|
434
|
+
"--state-dir",
|
|
435
|
+
str(family.state_dir),
|
|
436
|
+
"--action",
|
|
437
|
+
"reset_state",
|
|
438
|
+
]
|
|
439
|
+
if options.item_id:
|
|
440
|
+
command.extend([family.item_id_arg, options.item_id])
|
|
441
|
+
return subprocess.run(
|
|
442
|
+
command,
|
|
443
|
+
cwd=str(project_root),
|
|
444
|
+
stdout=subprocess.PIPE,
|
|
445
|
+
stderr=subprocess.PIPE,
|
|
446
|
+
text=True,
|
|
447
|
+
check=False,
|
|
448
|
+
)
|
|
449
|
+
|
|
450
|
+
|
|
349
451
|
def _run_updater(family: RunnerFamily, action: str, options: ResetOptions, item: ResetItem, project_root: Path) -> subprocess.CompletedProcess[str]:
|
|
350
452
|
command = [
|
|
351
453
|
sys.executable,
|
|
@@ -455,9 +557,14 @@ def _numeric_suffix(value: str, prefix: str) -> int:
|
|
|
455
557
|
def _help_text(family: RunnerFamily) -> str:
|
|
456
558
|
label = FAMILY_LABELS[family.kind]
|
|
457
559
|
return (
|
|
458
|
-
f"Usage: prizmkit-runtime reset {family.kind} <{label}-id
|
|
459
|
-
"
|
|
560
|
+
f"Usage: prizmkit-runtime reset {family.kind} <{label}-id> --state-only [list-path]\n"
|
|
561
|
+
f" prizmkit-runtime reset {family.kind} --state-only --all [list-path]\n"
|
|
562
|
+
f" prizmkit-runtime reset {family.kind} <{label}-id|range> --fresh-checkout [list-path]\n"
|
|
563
|
+
f" prizmkit-runtime reset {family.kind} <--auto-skipped|--failed|--stalled> --fresh-checkout [list-path]\n"
|
|
564
|
+
f" prizmkit-runtime reset {family.kind} <{label}-id|range> --clean [list-path]\n"
|
|
565
|
+
f" prizmkit-runtime reset {family.kind} <--auto-skipped|--failed|--stalled> --clean [list-path]\n"
|
|
460
566
|
f" prizmkit-runtime reset {family.kind} --failed --preserve-runtime [list-path]\n"
|
|
461
|
-
"
|
|
462
|
-
"
|
|
567
|
+
"Exactly one reset mode is required. State-only preserves checkout, Git, checkpoints, and artifacts; "
|
|
568
|
+
"fresh-checkout publishes a new checkout boundary; clean is destructive; preserve-runtime is whole-list failed recovery.\n"
|
|
569
|
+
"Reset never accepts --run; execute the matching run <family> command separately."
|
|
463
570
|
)
|
|
@@ -126,7 +126,7 @@ class PreserveRuntimeResetResult:
|
|
|
126
126
|
"Existing sessions, checkpoints, artifacts, branches, worktrees, and task work were not deleted.",
|
|
127
127
|
"Reset did not start a runner. Run separately:",
|
|
128
128
|
"python3 ./.prizmkit/dev-pipeline/cli.py "
|
|
129
|
-
f"{family.kind}
|
|
129
|
+
f"run {family.kind} {shlex.quote(str(list_path))}",
|
|
130
130
|
)
|
|
131
131
|
)
|
|
132
132
|
return tuple(lines)
|
|
@@ -65,6 +65,17 @@ def classify_session(
|
|
|
65
65
|
progress_fingerprint=fingerprint,
|
|
66
66
|
checkpoint_state=checkpoint.semantic_snapshot,
|
|
67
67
|
)
|
|
68
|
+
if (
|
|
69
|
+
checkpoint is not None
|
|
70
|
+
and checkpoint.semantic_complete
|
|
71
|
+
and not _runtime_commit_receipt_matches(project_root, checkpoint)
|
|
72
|
+
):
|
|
73
|
+
return SessionClassification(
|
|
74
|
+
"commit_missing",
|
|
75
|
+
reason="runtime_commit_receipt_mismatch",
|
|
76
|
+
progress_fingerprint=fingerprint,
|
|
77
|
+
checkpoint_state=checkpoint.semantic_snapshot,
|
|
78
|
+
)
|
|
68
79
|
if _is_terminal_success(result) and checkpoint is not None and checkpoint.semantic_complete:
|
|
69
80
|
return SessionClassification(
|
|
70
81
|
"success",
|
|
@@ -172,6 +183,25 @@ def _is_terminal_success(result: AISessionResult) -> bool:
|
|
|
172
183
|
)
|
|
173
184
|
|
|
174
185
|
|
|
186
|
+
def _runtime_commit_receipt_matches(
|
|
187
|
+
project_root: Path,
|
|
188
|
+
checkpoint: CheckpointState,
|
|
189
|
+
) -> bool:
|
|
190
|
+
"""Verify canonical Runtime receipt identity against the current Git HEAD."""
|
|
191
|
+
commit_hash = checkpoint.semantic.runtime_commit_hash
|
|
192
|
+
base_head = checkpoint.semantic.runtime_base_head
|
|
193
|
+
if not commit_hash and not base_head:
|
|
194
|
+
return True
|
|
195
|
+
head = run_git_command(project_root, ("rev-parse", "HEAD"))
|
|
196
|
+
parent = run_git_command(project_root, ("rev-parse", f"{commit_hash}^"))
|
|
197
|
+
return bool(
|
|
198
|
+
head.return_code == 0
|
|
199
|
+
and parent.return_code == 0
|
|
200
|
+
and head.stdout.strip().lower() == commit_hash.lower()
|
|
201
|
+
and parent.stdout.strip().lower() == base_head.lower()
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
|
|
175
205
|
def _has_late_runtime_error_after_completion(
|
|
176
206
|
result: AISessionResult,
|
|
177
207
|
checkpoint: CheckpointState | None,
|
|
@@ -201,9 +231,27 @@ def has_branch_completion_evidence(
|
|
|
201
231
|
working_branch: str,
|
|
202
232
|
artifact_path: Path | None,
|
|
203
233
|
) -> bool:
|
|
204
|
-
"""
|
|
205
|
-
if not base_branch or not working_branch or
|
|
234
|
+
"""Require semantic completion and matching Runtime receipt on the task branch."""
|
|
235
|
+
if not base_branch or not working_branch or artifact_path is None:
|
|
236
|
+
return False
|
|
237
|
+
checkpoint_path = artifact_path / "workflow-checkpoint.json"
|
|
238
|
+
if not checkpoint_path.is_file():
|
|
239
|
+
return False
|
|
240
|
+
checkpoint = load_checkpoint_state(checkpoint_path, project_root=project_root)
|
|
241
|
+
if not checkpoint.semantic_complete:
|
|
206
242
|
return False
|
|
243
|
+
commit_hash = checkpoint.semantic.runtime_commit_hash
|
|
244
|
+
base_head = checkpoint.semantic.runtime_base_head
|
|
245
|
+
if commit_hash or base_head:
|
|
246
|
+
branch_head = run_git_command(project_root, ("rev-parse", working_branch))
|
|
247
|
+
parent = run_git_command(project_root, ("rev-parse", f"{commit_hash}^"))
|
|
248
|
+
if not (
|
|
249
|
+
branch_head.return_code == 0
|
|
250
|
+
and parent.return_code == 0
|
|
251
|
+
and branch_head.stdout.strip().lower() == commit_hash.lower()
|
|
252
|
+
and parent.stdout.strip().lower() == base_head.lower()
|
|
253
|
+
):
|
|
254
|
+
return False
|
|
207
255
|
return _has_commit_range(project_root, base_branch, working_branch)
|
|
208
256
|
|
|
209
257
|
|
|
@@ -79,7 +79,6 @@ class RunnerInvocation:
|
|
|
79
79
|
item_filter: str = ""
|
|
80
80
|
max_retries: int | None = None
|
|
81
81
|
max_infra_retries: int = 3
|
|
82
|
-
mode: str | None = None
|
|
83
82
|
dry_run: bool = False
|
|
84
83
|
clean: bool = False
|
|
85
84
|
no_reset: bool = False
|
|
@@ -95,7 +94,6 @@ class PromptGenerationResult:
|
|
|
95
94
|
|
|
96
95
|
output_path: Path
|
|
97
96
|
model: str = ""
|
|
98
|
-
pipeline_mode: str = ""
|
|
99
97
|
checkpoint_path: Path | None = None
|
|
100
98
|
artifact_path: Path | None = None
|
|
101
99
|
raw: Mapping[str, object] = field(default_factory=dict)
|
|
@@ -273,7 +271,6 @@ def parse_invocation(
|
|
|
273
271
|
item_filter = ""
|
|
274
272
|
max_retries: int | None = None
|
|
275
273
|
max_infra_retries = 3
|
|
276
|
-
mode: str | None = None
|
|
277
274
|
dry_run = False
|
|
278
275
|
clean = False
|
|
279
276
|
no_reset = False
|
|
@@ -285,7 +282,7 @@ def parse_invocation(
|
|
|
285
282
|
index = 0
|
|
286
283
|
while index < len(args):
|
|
287
284
|
arg = args[index]
|
|
288
|
-
if arg in {"--help", "-h"
|
|
285
|
+
if arg in {"--help", "-h"}:
|
|
289
286
|
help_requested = True
|
|
290
287
|
elif arg == "--dry-run":
|
|
291
288
|
dry_run = True
|
|
@@ -308,11 +305,6 @@ def parse_invocation(
|
|
|
308
305
|
max_infra_retries = _safe_int(args[index], 3)
|
|
309
306
|
elif arg.startswith("--max-infra-retries="):
|
|
310
307
|
max_infra_retries = _safe_int(arg.split("=", 1)[1], 3)
|
|
311
|
-
elif arg == "--mode" and index + 1 < len(args):
|
|
312
|
-
index += 1
|
|
313
|
-
mode = args[index]
|
|
314
|
-
elif arg.startswith("--mode="):
|
|
315
|
-
mode = arg.split("=", 1)[1]
|
|
316
308
|
elif arg == "--resume-phase" and index + 1 < len(args):
|
|
317
309
|
index += 1
|
|
318
310
|
resume_phase = args[index]
|
|
@@ -339,7 +331,6 @@ def parse_invocation(
|
|
|
339
331
|
item_filter=item_filter,
|
|
340
332
|
max_retries=max_retries,
|
|
341
333
|
max_infra_retries=max_infra_retries,
|
|
342
|
-
mode=mode,
|
|
343
334
|
dry_run=dry_run,
|
|
344
335
|
clean=clean,
|
|
345
336
|
no_reset=no_reset,
|
|
@@ -22,6 +22,7 @@ def generate_prompt(
|
|
|
22
22
|
project_root: Path,
|
|
23
23
|
execution_root: Path | None = None,
|
|
24
24
|
continuation: dict[str, object] | None = None,
|
|
25
|
+
preview: bool = False,
|
|
25
26
|
) -> PromptGenerationResult:
|
|
26
27
|
"""Run the existing prompt generator and return its structured JSON result."""
|
|
27
28
|
visible_root = execution_root or project_root
|
|
@@ -47,8 +48,8 @@ def generate_prompt(
|
|
|
47
48
|
"--output",
|
|
48
49
|
str(session_paths.prompt_path),
|
|
49
50
|
]
|
|
50
|
-
if
|
|
51
|
-
command.
|
|
51
|
+
if preview:
|
|
52
|
+
command.append("--no-checkpoint-write")
|
|
52
53
|
if continuation:
|
|
53
54
|
command.extend(["--continuation-mode", "ai_error"])
|
|
54
55
|
for flag, key in (
|
|
@@ -95,7 +96,6 @@ def generate_prompt(
|
|
|
95
96
|
return PromptGenerationResult(
|
|
96
97
|
output_path=output_path,
|
|
97
98
|
model=str(data.get("model") or ""),
|
|
98
|
-
pipeline_mode=str(data.get("pipeline_mode") or ""),
|
|
99
99
|
checkpoint_path=Path(str(checkpoint)) if checkpoint else None,
|
|
100
100
|
artifact_path=_artifact_path(family, visible_root, item_id, data),
|
|
101
101
|
raw=data,
|