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
|
@@ -9,136 +9,228 @@ from collections.abc import Sequence
|
|
|
9
9
|
from .commands import CommandResult, handle_diagnostics, handle_runtime_command
|
|
10
10
|
from .compat import UnsupportedPythonVersion, ensure_supported_python
|
|
11
11
|
from .paths import resolve_runtime_paths
|
|
12
|
-
from .runtime_helper import render_result, run_helper_command
|
|
13
12
|
|
|
14
13
|
DESCRIPTION = (
|
|
15
14
|
"PrizmKit canonical Python runtime CLI.\n"
|
|
16
|
-
"Runs pipeline, reset, daemon,
|
|
15
|
+
"Runs operation-first pipeline, status, reset, daemon, diagnostics, and helper commands."
|
|
17
16
|
)
|
|
18
17
|
|
|
18
|
+
_FAMILIES = ("feature", "bugfix", "refactor")
|
|
19
|
+
_GLOBAL_OPTIONS_WITH_VALUES = {"--project-root", "--pipeline-root"}
|
|
20
|
+
_LEAF_OPTIONS_WITH_VALUES = {
|
|
21
|
+
"--env",
|
|
22
|
+
"--features",
|
|
23
|
+
"--lines",
|
|
24
|
+
"-n",
|
|
25
|
+
"--max-retries",
|
|
26
|
+
"--max-infra-retries",
|
|
27
|
+
"--resume-phase",
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _set_handler(
|
|
32
|
+
parser: argparse.ArgumentParser,
|
|
33
|
+
group: str,
|
|
34
|
+
action: str,
|
|
35
|
+
target: str | None = None,
|
|
36
|
+
) -> None:
|
|
37
|
+
parser.set_defaults(handler="runtime", group=group, action=action, target=target)
|
|
19
38
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
39
|
+
|
|
40
|
+
def _non_negative_int(value: str) -> int:
|
|
41
|
+
try:
|
|
42
|
+
parsed = int(value)
|
|
43
|
+
except ValueError as exc:
|
|
44
|
+
raise argparse.ArgumentTypeError("must be an integer") from exc
|
|
45
|
+
if parsed < 0:
|
|
46
|
+
raise argparse.ArgumentTypeError("must be non-negative")
|
|
47
|
+
return parsed
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _add_runner_arguments(parser: argparse.ArgumentParser, family: str) -> None:
|
|
51
|
+
parser.add_argument("operand", nargs="?", help="Optional task ID or family plan path.")
|
|
52
|
+
parser.add_argument("second_operand", nargs="?", help="Optional family plan path or task ID.")
|
|
53
|
+
if family == "feature":
|
|
54
|
+
parser.add_argument("--features", help="Feature ID, range, or comma-separated selection.")
|
|
55
|
+
parser.add_argument("--max-retries", type=_non_negative_int)
|
|
56
|
+
parser.add_argument("--max-infra-retries", type=_non_negative_int)
|
|
57
|
+
parser.add_argument("--resume-phase")
|
|
58
|
+
parser.add_argument("--dry-run", action="store_true")
|
|
59
|
+
parser.add_argument("--clean", action="store_true")
|
|
60
|
+
parser.add_argument("--no-reset", action="store_true")
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _add_run_subparsers(
|
|
64
|
+
subparsers: argparse._SubParsersAction[argparse.ArgumentParser],
|
|
65
|
+
) -> None:
|
|
66
|
+
run_parser = subparsers.add_parser("run", help="Run a foreground pipeline family")
|
|
67
|
+
family_subparsers = run_parser.add_subparsers(dest="run_family", required=True)
|
|
68
|
+
for family in _FAMILIES:
|
|
69
|
+
family_parser = family_subparsers.add_parser(family, help=f"Run the {family} pipeline")
|
|
70
|
+
_add_runner_arguments(family_parser, family)
|
|
71
|
+
_set_handler(family_parser, "run", "run", family)
|
|
26
72
|
|
|
27
73
|
|
|
28
|
-
def
|
|
29
|
-
|
|
74
|
+
def _add_status_subparsers(
|
|
75
|
+
subparsers: argparse._SubParsersAction[argparse.ArgumentParser],
|
|
76
|
+
) -> None:
|
|
77
|
+
status_parser = subparsers.add_parser("status", help="Inspect pipeline task state")
|
|
78
|
+
target_subparsers = status_parser.add_subparsers(dest="status_target", required=True)
|
|
79
|
+
for family in _FAMILIES:
|
|
80
|
+
family_parser = target_subparsers.add_parser(family, help=f"Show {family} status")
|
|
81
|
+
_add_runner_arguments(family_parser, family)
|
|
82
|
+
_set_handler(family_parser, "status", "status", family)
|
|
83
|
+
all_parser = target_subparsers.add_parser(
|
|
84
|
+
"all",
|
|
85
|
+
help="Show read-only status for every configured family",
|
|
86
|
+
)
|
|
87
|
+
_set_handler(all_parser, "status", "status", "all")
|
|
30
88
|
|
|
31
89
|
|
|
32
|
-
def
|
|
90
|
+
def _add_reset_subparsers(
|
|
91
|
+
subparsers: argparse._SubParsersAction[argparse.ArgumentParser],
|
|
92
|
+
) -> None:
|
|
93
|
+
reset_parser = subparsers.add_parser("reset", help="Apply one explicit reset mode")
|
|
94
|
+
family_subparsers = reset_parser.add_subparsers(dest="reset_family", required=True)
|
|
95
|
+
for family in _FAMILIES:
|
|
96
|
+
family_parser = family_subparsers.add_parser(family, help=f"Reset {family} task state")
|
|
97
|
+
family_parser.add_argument("operand", nargs="?", help="Task ID, range, or family plan path.")
|
|
98
|
+
family_parser.add_argument("second_operand", nargs="?", help="Optional family plan path.")
|
|
99
|
+
family_parser.add_argument("--state-only", action="store_true")
|
|
100
|
+
family_parser.add_argument("--fresh-checkout", action="store_true")
|
|
101
|
+
family_parser.add_argument("--clean", action="store_true")
|
|
102
|
+
family_parser.add_argument("--preserve-runtime", action="store_true")
|
|
103
|
+
family_parser.add_argument("--all", action="store_true")
|
|
104
|
+
family_parser.add_argument("--auto-skipped", action="store_true")
|
|
105
|
+
family_parser.add_argument("--failed", action="store_true")
|
|
106
|
+
family_parser.add_argument("--stalled", action="store_true")
|
|
107
|
+
_set_handler(family_parser, "reset", "reset", family)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _add_daemon_start_arguments(parser: argparse.ArgumentParser, family: str) -> None:
|
|
111
|
+
parser.add_argument("list_path", nargs="?", help="Optional family plan path.")
|
|
112
|
+
parser.add_argument("--env", help="Quoted KEY=VALUE daemon environment overrides.")
|
|
113
|
+
if family == "feature":
|
|
114
|
+
parser.add_argument("--features", help="Feature ID, range, or comma-separated selection.")
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def _add_daemon_subparsers(
|
|
118
|
+
subparsers: argparse._SubParsersAction[argparse.ArgumentParser],
|
|
119
|
+
) -> None:
|
|
120
|
+
daemon_parser = subparsers.add_parser("daemon", help="Manage background pipeline processes")
|
|
121
|
+
family_subparsers = daemon_parser.add_subparsers(dest="daemon_family", required=True)
|
|
122
|
+
for family in _FAMILIES:
|
|
123
|
+
family_parser = family_subparsers.add_parser(family, help=f"Manage the {family} daemon")
|
|
124
|
+
action_subparsers = family_parser.add_subparsers(dest="daemon_action", required=True)
|
|
125
|
+
for action in ("start", "stop", "status", "logs", "restart"):
|
|
126
|
+
action_parser = action_subparsers.add_parser(action, help=f"{action.title()} the {family} daemon")
|
|
127
|
+
if action in {"start", "restart"}:
|
|
128
|
+
_add_daemon_start_arguments(action_parser, family)
|
|
129
|
+
elif action == "logs":
|
|
130
|
+
action_parser.add_argument("--lines", "-n", type=_non_negative_int, default=50)
|
|
131
|
+
action_parser.add_argument("--follow", "-f", action="store_true")
|
|
132
|
+
_set_handler(action_parser, "daemon", action, family)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def _add_diagnostics_subparsers(
|
|
33
136
|
subparsers: argparse._SubParsersAction[argparse.ArgumentParser],
|
|
34
|
-
group: str,
|
|
35
|
-
actions: Sequence[str],
|
|
36
137
|
) -> None:
|
|
37
|
-
|
|
38
|
-
action_subparsers =
|
|
39
|
-
for action in
|
|
40
|
-
action_parser = action_subparsers.add_parser(action, help=f"
|
|
41
|
-
_add_passthrough_options(action_parser)
|
|
42
|
-
_set_handler(action_parser, group, action)
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
def _add_reset_subparsers(subparsers: argparse._SubParsersAction[argparse.ArgumentParser]) -> None:
|
|
46
|
-
reset_parser = subparsers.add_parser("reset", help="Explicit reset commands")
|
|
47
|
-
reset_subparsers = reset_parser.add_subparsers(dest="reset_target", required=True)
|
|
48
|
-
for target in ("feature", "bugfix", "refactor"):
|
|
49
|
-
target_parser = reset_subparsers.add_parser(target, help=f"Run {target} reset")
|
|
50
|
-
_add_passthrough_options(target_parser)
|
|
51
|
-
_set_handler(target_parser, "reset", "reset", target)
|
|
52
|
-
describe_parser = reset_subparsers.add_parser("describe", help="Describe reset command boundaries")
|
|
53
|
-
_set_handler(describe_parser, "reset", "describe")
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
def _add_daemon_subparsers(subparsers: argparse._SubParsersAction[argparse.ArgumentParser]) -> None:
|
|
57
|
-
daemon_parser = subparsers.add_parser("daemon", help="Daemon lifecycle commands")
|
|
58
|
-
target_subparsers = daemon_parser.add_subparsers(dest="daemon_target", required=True)
|
|
59
|
-
for target in ("feature", "bugfix", "refactor"):
|
|
60
|
-
target_parser = target_subparsers.add_parser(target, help=f"{target} daemon commands")
|
|
61
|
-
action_subparsers = target_parser.add_subparsers(dest="daemon_action", required=True)
|
|
62
|
-
for action in ("start", "stop", "status", "logs", "restart", "describe"):
|
|
63
|
-
action_parser = action_subparsers.add_parser(action, help=f"Run daemon {target} {action}")
|
|
64
|
-
_add_passthrough_options(action_parser)
|
|
65
|
-
_set_handler(action_parser, "daemon", action, target)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
def _add_status_subparsers(subparsers: argparse._SubParsersAction[argparse.ArgumentParser]) -> None:
|
|
69
|
-
status_parser = subparsers.add_parser("status", help="Status commands")
|
|
70
|
-
status_subparsers = status_parser.add_subparsers(dest="status_target", required=True)
|
|
71
|
-
for target in ("feature", "bugfix", "refactor", "all"):
|
|
72
|
-
target_parser = status_subparsers.add_parser(target, help=f"Show {target} status")
|
|
73
|
-
_add_passthrough_options(target_parser)
|
|
74
|
-
_set_handler(target_parser, "status", "status", target)
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
def _add_diagnostics_subparsers(subparsers: argparse._SubParsersAction[argparse.ArgumentParser]) -> None:
|
|
78
|
-
diagnostics_parser = subparsers.add_parser("diagnostics", help="Python runtime diagnostics")
|
|
79
|
-
diagnostics_subparsers = diagnostics_parser.add_subparsers(dest="diagnostics_action", required=True)
|
|
80
|
-
for action in ("paths", "entrypoints", "version"):
|
|
81
|
-
action_parser = diagnostics_subparsers.add_parser(action, help=f"Show {action} diagnostics")
|
|
138
|
+
diagnostics_parser = subparsers.add_parser("diagnostics", help="Inspect Python runtime configuration")
|
|
139
|
+
action_subparsers = diagnostics_parser.add_subparsers(dest="diagnostics_action", required=True)
|
|
140
|
+
for action in ("paths", "entrypoints", "version", "ai-cli"):
|
|
141
|
+
action_parser = action_subparsers.add_parser(action, help=f"Show {action} diagnostics")
|
|
82
142
|
action_parser.set_defaults(handler="diagnostics", action=action)
|
|
83
143
|
|
|
84
144
|
|
|
85
|
-
def _add_helper_subparser(
|
|
86
|
-
|
|
145
|
+
def _add_helper_subparser(
|
|
146
|
+
subparsers: argparse._SubParsersAction[argparse.ArgumentParser],
|
|
147
|
+
) -> None:
|
|
148
|
+
helper_parser = subparsers.add_parser("helper", help="Run low-level cross-platform helper commands")
|
|
149
|
+
helper_parser.add_argument("helper_command", nargs="?", help="Helper command namespace.")
|
|
87
150
|
helper_parser.add_argument(
|
|
88
|
-
"
|
|
151
|
+
"helper_args",
|
|
89
152
|
nargs=argparse.REMAINDER,
|
|
90
153
|
help="Arguments forwarded to prizmkit-runtime-helper.",
|
|
91
154
|
)
|
|
92
|
-
helper_parser
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
_PIPELINE_GROUPS = {"feature", "bugfix", "refactor", "recovery"}
|
|
96
|
-
_GLOBAL_OPTIONS_WITH_VALUES = {"--project-root", "--pipeline-root"}
|
|
155
|
+
_set_handler(helper_parser, "helper", "run")
|
|
97
156
|
|
|
98
157
|
|
|
99
|
-
def
|
|
100
|
-
"""
|
|
158
|
+
def _parser_argv(argv: Sequence[str]) -> list[str]:
|
|
159
|
+
"""Normalize interspersed leaf operands for argparse validation only."""
|
|
101
160
|
tokens = [str(arg) for arg in argv]
|
|
102
|
-
prefix: list[str] = []
|
|
103
161
|
index = 0
|
|
104
162
|
while index < len(tokens):
|
|
105
163
|
token = tokens[index]
|
|
106
164
|
if token in _GLOBAL_OPTIONS_WITH_VALUES:
|
|
107
|
-
|
|
108
|
-
index += 1
|
|
109
|
-
if index < len(tokens):
|
|
110
|
-
prefix.append(tokens[index])
|
|
111
|
-
index += 1
|
|
165
|
+
index += 2
|
|
112
166
|
continue
|
|
113
167
|
if any(token.startswith(f"{option}=") for option in _GLOBAL_OPTIONS_WITH_VALUES):
|
|
114
|
-
prefix.append(token)
|
|
115
168
|
index += 1
|
|
116
169
|
continue
|
|
117
170
|
break
|
|
171
|
+
if index >= len(tokens):
|
|
172
|
+
return tokens
|
|
118
173
|
|
|
174
|
+
group = tokens[index]
|
|
175
|
+
depth = {"run": 2, "status": 2, "reset": 2, "daemon": 3}.get(group)
|
|
176
|
+
if depth is None or len(tokens) <= index + depth:
|
|
177
|
+
return tokens
|
|
178
|
+
|
|
179
|
+
command_end = index + depth
|
|
180
|
+
operands: list[str] = []
|
|
181
|
+
options: list[str] = []
|
|
182
|
+
tail = tokens[command_end:]
|
|
183
|
+
tail_index = 0
|
|
184
|
+
while tail_index < len(tail):
|
|
185
|
+
token = tail[tail_index]
|
|
186
|
+
option_name = token.split("=", 1)[0]
|
|
187
|
+
if token.startswith("-"):
|
|
188
|
+
options.append(token)
|
|
189
|
+
if (
|
|
190
|
+
"=" not in token
|
|
191
|
+
and option_name in _LEAF_OPTIONS_WITH_VALUES
|
|
192
|
+
and tail_index + 1 < len(tail)
|
|
193
|
+
):
|
|
194
|
+
tail_index += 1
|
|
195
|
+
options.append(tail[tail_index])
|
|
196
|
+
else:
|
|
197
|
+
operands.append(token)
|
|
198
|
+
tail_index += 1
|
|
199
|
+
return [*tokens[:command_end], *operands, *options]
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def _runtime_action_args(argv: Sequence[str]) -> tuple[str, ...]:
|
|
203
|
+
"""Return the original validated leaf arguments in their exact order."""
|
|
204
|
+
tokens = [str(arg) for arg in argv]
|
|
205
|
+
index = 0
|
|
206
|
+
while index < len(tokens):
|
|
207
|
+
token = tokens[index]
|
|
208
|
+
if token in _GLOBAL_OPTIONS_WITH_VALUES:
|
|
209
|
+
index += 2
|
|
210
|
+
continue
|
|
211
|
+
if any(token.startswith(f"{option}=") for option in _GLOBAL_OPTIONS_WITH_VALUES):
|
|
212
|
+
index += 1
|
|
213
|
+
continue
|
|
214
|
+
break
|
|
119
215
|
if index >= len(tokens):
|
|
120
|
-
return
|
|
216
|
+
return ()
|
|
121
217
|
|
|
122
218
|
group = tokens[index]
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
passthrough = tuple(tokens[command_end:])
|
|
135
|
-
if group == "diagnostics":
|
|
136
|
-
return tokens, ()
|
|
137
|
-
return prefix, passthrough
|
|
219
|
+
depth = {
|
|
220
|
+
"run": 2,
|
|
221
|
+
"status": 2,
|
|
222
|
+
"reset": 2,
|
|
223
|
+
"daemon": 3,
|
|
224
|
+
"diagnostics": 2,
|
|
225
|
+
"helper": 1,
|
|
226
|
+
}.get(group)
|
|
227
|
+
if depth is None:
|
|
228
|
+
return ()
|
|
229
|
+
return tuple(tokens[index + depth :])
|
|
138
230
|
|
|
139
231
|
|
|
140
232
|
def build_parser() -> argparse.ArgumentParser:
|
|
141
|
-
"""Build the standard-library argparse command tree."""
|
|
233
|
+
"""Build the standard-library operation-first argparse command tree."""
|
|
142
234
|
parser = argparse.ArgumentParser(
|
|
143
235
|
prog="prizmkit-runtime",
|
|
144
236
|
description=DESCRIPTION,
|
|
@@ -154,13 +246,10 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
154
246
|
)
|
|
155
247
|
subparsers = parser.add_subparsers(dest="command_group", required=True)
|
|
156
248
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
_add_action_subparsers(subparsers, "refactor", ("run", "status", "reset", "unskip", "describe"))
|
|
160
|
-
_add_action_subparsers(subparsers, "recovery", ("run", "detect", "describe"))
|
|
249
|
+
_add_run_subparsers(subparsers)
|
|
250
|
+
_add_status_subparsers(subparsers)
|
|
161
251
|
_add_reset_subparsers(subparsers)
|
|
162
252
|
_add_daemon_subparsers(subparsers)
|
|
163
|
-
_add_status_subparsers(subparsers)
|
|
164
253
|
_add_diagnostics_subparsers(subparsers)
|
|
165
254
|
_add_helper_subparser(subparsers)
|
|
166
255
|
return parser
|
|
@@ -174,14 +263,6 @@ def _dispatch(args: argparse.Namespace) -> CommandResult:
|
|
|
174
263
|
paths = _runtime_paths_from_args(args)
|
|
175
264
|
if args.handler == "diagnostics":
|
|
176
265
|
return handle_diagnostics(args.action, paths)
|
|
177
|
-
if args.handler == "helper":
|
|
178
|
-
helper_result = run_helper_command(tuple(getattr(args, "args", ()) or ()))
|
|
179
|
-
return CommandResult(
|
|
180
|
-
helper_result.exit_code,
|
|
181
|
-
"Python runtime helper",
|
|
182
|
-
"Cross-platform prompt runtime helper result.",
|
|
183
|
-
stdout=render_result(helper_result, json_output="--json" in tuple(getattr(args, "args", ()) or ())),
|
|
184
|
-
)
|
|
185
266
|
return handle_runtime_command(
|
|
186
267
|
args.group,
|
|
187
268
|
args.action,
|
|
@@ -192,7 +273,7 @@ def _dispatch(args: argparse.Namespace) -> CommandResult:
|
|
|
192
273
|
|
|
193
274
|
|
|
194
275
|
def main(argv: Sequence[str] | None = None) -> int:
|
|
195
|
-
"""Run the
|
|
276
|
+
"""Run the canonical operation-first runtime CLI."""
|
|
196
277
|
try:
|
|
197
278
|
ensure_supported_python()
|
|
198
279
|
except UnsupportedPythonVersion as exc:
|
|
@@ -201,10 +282,8 @@ def main(argv: Sequence[str] | None = None) -> int:
|
|
|
201
282
|
|
|
202
283
|
parser = build_parser()
|
|
203
284
|
parse_argv = list(sys.argv[1:] if argv is None else argv)
|
|
204
|
-
|
|
205
|
-
args =
|
|
206
|
-
if passthrough_args:
|
|
207
|
-
args.args = tuple(getattr(args, "args", ()) or ()) + passthrough_args
|
|
285
|
+
args = parser.parse_args(_parser_argv(parse_argv))
|
|
286
|
+
args.args = _runtime_action_args(parse_argv)
|
|
208
287
|
result = _dispatch(args)
|
|
209
288
|
if result.stderr:
|
|
210
289
|
print(result.stderr, file=sys.stderr)
|