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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Executing command registry for the canonical operation-first runtime."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
@@ -11,18 +11,19 @@ from .paths import RuntimePaths, resolve_runtime_paths
|
|
|
11
11
|
RUNTIME_STATUS = "python-runtime-canonical"
|
|
12
12
|
CANONICAL_RUNTIME_NOTE = "The Python CLI and prizmkit_runtime modules are the canonical runtime."
|
|
13
13
|
PYTHON_CLI = "dev-pipeline/cli.py"
|
|
14
|
+
_FAMILIES = ("feature", "bugfix", "refactor")
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
@dataclass(frozen=True)
|
|
17
18
|
class RuntimeCommand:
|
|
18
|
-
"""
|
|
19
|
+
"""One public CLI command mapped to an executing or diagnostic handler."""
|
|
19
20
|
|
|
20
21
|
group: str
|
|
21
22
|
action: str
|
|
22
23
|
target: str | None
|
|
23
|
-
current_entrypoint: str
|
|
24
|
-
entrypoint_kind: str
|
|
25
|
-
entrypoint_name: str
|
|
24
|
+
current_entrypoint: str
|
|
25
|
+
entrypoint_kind: str = "python-cli"
|
|
26
|
+
entrypoint_name: str = ""
|
|
26
27
|
transition_status: str = RUNTIME_STATUS
|
|
27
28
|
notes: tuple[str, ...] = (CANONICAL_RUNTIME_NOTE,)
|
|
28
29
|
|
|
@@ -54,12 +55,16 @@ class CommandResult:
|
|
|
54
55
|
|
|
55
56
|
def _runtime_invocation(group: str, action: str, target: str | None = None) -> str:
|
|
56
57
|
if group == "daemon" and target is not None:
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
command = f"daemon {target} {action}"
|
|
59
|
+
elif group in {"run", "status", "reset"} and target is not None:
|
|
60
|
+
command = f"{group} {target}"
|
|
61
|
+
elif group == "diagnostics":
|
|
62
|
+
command = f"diagnostics {action}"
|
|
63
|
+
elif group == "helper":
|
|
64
|
+
command = "helper"
|
|
65
|
+
else:
|
|
66
|
+
command = f"{group} {action}"
|
|
67
|
+
return f"python3 {PYTHON_CLI} {command}"
|
|
63
68
|
|
|
64
69
|
|
|
65
70
|
def _command(
|
|
@@ -74,74 +79,24 @@ def _command(
|
|
|
74
79
|
target=target,
|
|
75
80
|
action=action,
|
|
76
81
|
current_entrypoint=_runtime_invocation(group, action, target),
|
|
77
|
-
entrypoint_kind="python-cli",
|
|
78
82
|
entrypoint_name=group if target is None else f"{group}:{target}",
|
|
79
83
|
notes=notes,
|
|
80
84
|
)
|
|
81
85
|
|
|
82
86
|
|
|
83
|
-
def
|
|
84
|
-
|
|
85
|
-
action_matrix = {
|
|
86
|
-
"feature": ("run", "status", "reset", "unskip", "test-cli", "describe"),
|
|
87
|
-
"bugfix": ("run", "status", "reset", "unskip", "describe"),
|
|
88
|
-
"refactor": ("run", "status", "reset", "unskip", "describe"),
|
|
89
|
-
"recovery": ("run", "detect", "describe"),
|
|
90
|
-
}
|
|
91
|
-
for group, actions in action_matrix.items():
|
|
92
|
-
for action in actions:
|
|
93
|
-
commands.append(
|
|
94
|
-
_command(
|
|
95
|
-
group,
|
|
96
|
-
action,
|
|
97
|
-
notes=(
|
|
98
|
-
CANONICAL_RUNTIME_NOTE,
|
|
99
|
-
"Foreground and recovery behavior is implemented in Python runtime modules.",
|
|
100
|
-
),
|
|
101
|
-
)
|
|
102
|
-
)
|
|
103
|
-
return tuple(commands)
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
def _reset_commands() -> tuple[RuntimeCommand, ...]:
|
|
107
|
-
commands = [
|
|
87
|
+
def _run_commands() -> tuple[RuntimeCommand, ...]:
|
|
88
|
+
return tuple(
|
|
108
89
|
_command(
|
|
109
|
-
"
|
|
110
|
-
"
|
|
111
|
-
target=
|
|
90
|
+
"run",
|
|
91
|
+
"run",
|
|
92
|
+
target=family,
|
|
112
93
|
notes=(
|
|
113
94
|
CANONICAL_RUNTIME_NOTE,
|
|
114
|
-
"
|
|
95
|
+
"Foreground pipeline behavior is implemented in Python runtime modules.",
|
|
115
96
|
),
|
|
116
97
|
)
|
|
117
|
-
for
|
|
118
|
-
]
|
|
119
|
-
commands.append(
|
|
120
|
-
_command(
|
|
121
|
-
"reset",
|
|
122
|
-
"describe",
|
|
123
|
-
notes=(CANONICAL_RUNTIME_NOTE, "Lists destructive Python reset commands without running them."),
|
|
124
|
-
)
|
|
98
|
+
for family in _FAMILIES
|
|
125
99
|
)
|
|
126
|
-
return tuple(commands)
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
def _daemon_commands() -> tuple[RuntimeCommand, ...]:
|
|
130
|
-
commands: list[RuntimeCommand] = []
|
|
131
|
-
for target in ("feature", "bugfix", "refactor"):
|
|
132
|
-
for action in ("start", "stop", "status", "logs", "restart", "describe"):
|
|
133
|
-
commands.append(
|
|
134
|
-
_command(
|
|
135
|
-
"daemon",
|
|
136
|
-
action,
|
|
137
|
-
target=target,
|
|
138
|
-
notes=(
|
|
139
|
-
CANONICAL_RUNTIME_NOTE,
|
|
140
|
-
"Daemon lifecycle behavior is implemented by the Python daemon runtime.",
|
|
141
|
-
),
|
|
142
|
-
)
|
|
143
|
-
)
|
|
144
|
-
return tuple(commands)
|
|
145
100
|
|
|
146
101
|
|
|
147
102
|
def _status_commands() -> tuple[RuntimeCommand, ...]:
|
|
@@ -149,44 +104,80 @@ def _status_commands() -> tuple[RuntimeCommand, ...]:
|
|
|
149
104
|
_command(
|
|
150
105
|
"status",
|
|
151
106
|
"status",
|
|
152
|
-
target=
|
|
153
|
-
notes=(CANONICAL_RUNTIME_NOTE, "Status is resolved by the
|
|
107
|
+
target=family,
|
|
108
|
+
notes=(CANONICAL_RUNTIME_NOTE, "Status is resolved by the canonical family status handler."),
|
|
154
109
|
)
|
|
155
|
-
for
|
|
110
|
+
for family in _FAMILIES
|
|
156
111
|
]
|
|
157
112
|
commands.append(
|
|
158
113
|
_command(
|
|
159
114
|
"status",
|
|
160
115
|
"status",
|
|
161
116
|
target="all",
|
|
162
|
-
notes=(CANONICAL_RUNTIME_NOTE, "
|
|
117
|
+
notes=(CANONICAL_RUNTIME_NOTE, "Aggregates configured family status handlers without mutation."),
|
|
163
118
|
)
|
|
164
119
|
)
|
|
165
120
|
return tuple(commands)
|
|
166
121
|
|
|
167
122
|
|
|
123
|
+
def _reset_commands() -> tuple[RuntimeCommand, ...]:
|
|
124
|
+
return tuple(
|
|
125
|
+
_command(
|
|
126
|
+
"reset",
|
|
127
|
+
"reset",
|
|
128
|
+
target=family,
|
|
129
|
+
notes=(
|
|
130
|
+
CANONICAL_RUNTIME_NOTE,
|
|
131
|
+
"Reset requires one explicit mode and never starts execution.",
|
|
132
|
+
),
|
|
133
|
+
)
|
|
134
|
+
for family in _FAMILIES
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def _daemon_commands() -> tuple[RuntimeCommand, ...]:
|
|
139
|
+
return tuple(
|
|
140
|
+
_command(
|
|
141
|
+
"daemon",
|
|
142
|
+
action,
|
|
143
|
+
target=family,
|
|
144
|
+
notes=(
|
|
145
|
+
CANONICAL_RUNTIME_NOTE,
|
|
146
|
+
"Daemon lifecycle behavior is implemented by the Python daemon runtime.",
|
|
147
|
+
),
|
|
148
|
+
)
|
|
149
|
+
for family in _FAMILIES
|
|
150
|
+
for action in ("start", "stop", "status", "logs", "restart")
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
|
|
168
154
|
def _diagnostic_commands() -> tuple[RuntimeCommand, ...]:
|
|
169
155
|
return tuple(
|
|
170
156
|
_command(
|
|
171
157
|
"diagnostics",
|
|
172
158
|
action,
|
|
173
|
-
notes=(CANONICAL_RUNTIME_NOTE, "Diagnostic
|
|
159
|
+
notes=(CANONICAL_RUNTIME_NOTE, "Diagnostic behavior is implemented in the Python runtime."),
|
|
174
160
|
)
|
|
175
|
-
for action in ("paths", "entrypoints", "version")
|
|
161
|
+
for action in ("paths", "entrypoints", "version", "ai-cli")
|
|
176
162
|
)
|
|
177
163
|
|
|
178
164
|
|
|
179
165
|
COMMAND_REGISTRY: tuple[RuntimeCommand, ...] = (
|
|
180
|
-
*
|
|
166
|
+
*_run_commands(),
|
|
167
|
+
*_status_commands(),
|
|
181
168
|
*_reset_commands(),
|
|
182
169
|
*_daemon_commands(),
|
|
183
|
-
*_status_commands(),
|
|
184
170
|
*_diagnostic_commands(),
|
|
171
|
+
_command(
|
|
172
|
+
"helper",
|
|
173
|
+
"run",
|
|
174
|
+
notes=(CANONICAL_RUNTIME_NOTE, "Low-level helper behavior is implemented by runtime_helper.py."),
|
|
175
|
+
),
|
|
185
176
|
)
|
|
186
177
|
|
|
187
178
|
|
|
188
179
|
def list_runtime_commands() -> tuple[RuntimeCommand, ...]:
|
|
189
|
-
"""Return the
|
|
180
|
+
"""Return the public executing/diagnostic command inventory."""
|
|
190
181
|
return COMMAND_REGISTRY
|
|
191
182
|
|
|
192
183
|
|
|
@@ -199,23 +190,6 @@ def find_runtime_command(group: str, action: str, target: str | None = None) ->
|
|
|
199
190
|
raise KeyError(f"Unknown runtime command: group={group}{target_text} action={action}")
|
|
200
191
|
|
|
201
192
|
|
|
202
|
-
def describe_command(command: RuntimeCommand, paths: RuntimePaths | None = None) -> CommandResult:
|
|
203
|
-
"""Describe a Python runtime command contract without running behavior."""
|
|
204
|
-
_ = paths or resolve_runtime_paths()
|
|
205
|
-
details = [
|
|
206
|
-
f"command: {command.group} {command.target or ''} {command.action}".replace(" ", " ").strip(),
|
|
207
|
-
f"runtime status: {command.transition_status}",
|
|
208
|
-
f"current entrypoint: {command.current_entrypoint or PYTHON_CLI}",
|
|
209
|
-
]
|
|
210
|
-
details.extend(f"note: {note}" for note in command.notes)
|
|
211
|
-
return CommandResult(
|
|
212
|
-
exit_code=0,
|
|
213
|
-
title="Python runtime command contract",
|
|
214
|
-
message="This command is available in the canonical PrizmKit Python runtime.",
|
|
215
|
-
details=tuple(details),
|
|
216
|
-
)
|
|
217
|
-
|
|
218
|
-
|
|
219
193
|
def handle_runtime_command(
|
|
220
194
|
group: str,
|
|
221
195
|
action: str,
|
|
@@ -224,33 +198,60 @@ def handle_runtime_command(
|
|
|
224
198
|
paths: RuntimePaths | None = None,
|
|
225
199
|
legacy_args: tuple[str, ...] = (),
|
|
226
200
|
) -> CommandResult:
|
|
227
|
-
"""
|
|
201
|
+
"""Dispatch one registered public runtime command to real behavior."""
|
|
202
|
+
find_runtime_command(group, action, target)
|
|
228
203
|
runtime_paths = paths or resolve_runtime_paths()
|
|
229
|
-
|
|
204
|
+
|
|
205
|
+
if group == "run" and target in _FAMILIES and action == "run":
|
|
230
206
|
from .runners import run_pipeline_command
|
|
231
207
|
|
|
232
|
-
return run_pipeline_command(
|
|
233
|
-
if group == "status" and target in
|
|
208
|
+
return run_pipeline_command(target, "run", legacy_args, runtime_paths)
|
|
209
|
+
if group == "status" and target in _FAMILIES and action == "status":
|
|
234
210
|
from .runners import run_pipeline_command
|
|
235
211
|
|
|
236
|
-
return run_pipeline_command(target,
|
|
237
|
-
if group == "
|
|
238
|
-
|
|
212
|
+
return run_pipeline_command(target, "status", legacy_args, runtime_paths)
|
|
213
|
+
if group == "status" and target == "all" and action == "status":
|
|
214
|
+
if legacy_args:
|
|
215
|
+
return CommandResult(
|
|
216
|
+
2,
|
|
217
|
+
"Python aggregate status",
|
|
218
|
+
"status all does not accept a plan path or family-specific arguments",
|
|
219
|
+
)
|
|
220
|
+
from .runners import run_pipeline_command
|
|
221
|
+
from .status import aggregate_family_status
|
|
239
222
|
|
|
240
|
-
|
|
241
|
-
|
|
223
|
+
aggregate = aggregate_family_status(
|
|
224
|
+
runtime_paths,
|
|
225
|
+
lambda family: run_pipeline_command(family, "status", (), runtime_paths),
|
|
226
|
+
)
|
|
227
|
+
return CommandResult(
|
|
228
|
+
aggregate.exit_code,
|
|
229
|
+
"Python aggregate status",
|
|
230
|
+
"Read-only status for all pipeline families.",
|
|
231
|
+
stdout=aggregate.output,
|
|
232
|
+
)
|
|
233
|
+
if group == "reset" and target in _FAMILIES and action == "reset":
|
|
242
234
|
from .reset import run_reset_command
|
|
243
235
|
|
|
244
236
|
return run_reset_command(target, legacy_args, runtime_paths)
|
|
245
|
-
if group == "daemon" and target in
|
|
237
|
+
if group == "daemon" and target in _FAMILIES and action in {"start", "stop", "status", "logs", "restart"}:
|
|
246
238
|
from .daemon import run_daemon_command
|
|
247
239
|
|
|
248
240
|
try:
|
|
249
241
|
return run_daemon_command(target, action, legacy_args, runtime_paths)
|
|
250
242
|
except ValueError as exc:
|
|
251
243
|
return CommandResult(1, f"Python {target} daemon", str(exc), stdout="", stderr=str(exc))
|
|
252
|
-
|
|
253
|
-
|
|
244
|
+
if group == "helper" and action == "run" and target is None:
|
|
245
|
+
from .runtime_helper import render_result, run_helper_command
|
|
246
|
+
|
|
247
|
+
helper_result = run_helper_command(legacy_args)
|
|
248
|
+
return CommandResult(
|
|
249
|
+
helper_result.exit_code,
|
|
250
|
+
"Python runtime helper",
|
|
251
|
+
"Cross-platform prompt runtime helper result.",
|
|
252
|
+
stdout=render_result(helper_result, json_output="--json" in legacy_args),
|
|
253
|
+
)
|
|
254
|
+
raise RuntimeError(f"Registered command has no handler: {group} {target or ''} {action}".strip())
|
|
254
255
|
|
|
255
256
|
|
|
256
257
|
def diagnostics_paths(paths: RuntimePaths | None = None) -> CommandResult:
|
|
@@ -275,20 +276,27 @@ def diagnostics_paths(paths: RuntimePaths | None = None) -> CommandResult:
|
|
|
275
276
|
|
|
276
277
|
|
|
277
278
|
def diagnostics_entrypoints(paths: RuntimePaths | None = None) -> CommandResult:
|
|
278
|
-
"""Return
|
|
279
|
+
"""Return canonical runtime, command, and utility entrypoints."""
|
|
279
280
|
runtime_paths = paths or resolve_runtime_paths()
|
|
280
281
|
details: list[str] = [
|
|
281
282
|
f"runtime:cli: {runtime_paths.pipeline_root / 'cli.py'}",
|
|
282
283
|
f"runtime:module: {runtime_paths.pipeline_root / 'prizmkit_runtime'}",
|
|
283
284
|
f"runtime:helper-module: {runtime_paths.pipeline_root / 'prizmkit_runtime' / 'runtime_helper.py'}",
|
|
284
285
|
]
|
|
286
|
+
details.extend(
|
|
287
|
+
f"command:{command.group}:{command.target or command.action}: {command.current_entrypoint}"
|
|
288
|
+
for command in COMMAND_REGISTRY
|
|
289
|
+
)
|
|
285
290
|
for name, relative_path in sorted(UTILITY_ENTRYPOINTS.items()):
|
|
286
291
|
invocation = describe_existing_entrypoint("utility", name, paths=runtime_paths)
|
|
287
|
-
details.append(
|
|
292
|
+
details.append(
|
|
293
|
+
f"utility:{name}: "
|
|
294
|
+
f"{invocation.script_path if invocation else runtime_paths.pipeline_root / relative_path}"
|
|
295
|
+
)
|
|
288
296
|
return CommandResult(
|
|
289
297
|
exit_code=0,
|
|
290
298
|
title="Python runtime entrypoint inventory",
|
|
291
|
-
message="Inventory for canonical Python runtime and utility scripts.",
|
|
299
|
+
message="Inventory for canonical Python runtime commands and utility scripts.",
|
|
292
300
|
details=tuple(details),
|
|
293
301
|
)
|
|
294
302
|
|
|
@@ -303,12 +311,39 @@ def diagnostics_version() -> CommandResult:
|
|
|
303
311
|
)
|
|
304
312
|
|
|
305
313
|
|
|
314
|
+
def diagnostics_ai_cli(paths: RuntimePaths | None = None) -> CommandResult:
|
|
315
|
+
"""Report the family-neutral AI CLI resolution used by runtime commands."""
|
|
316
|
+
from .config import load_runtime_config
|
|
317
|
+
|
|
318
|
+
runtime_paths = paths or resolve_runtime_paths()
|
|
319
|
+
config = load_runtime_config(runtime_paths)
|
|
320
|
+
cli = config.ai_client.command or "(not found)"
|
|
321
|
+
details = [
|
|
322
|
+
f"detected_cli: {cli}",
|
|
323
|
+
f"platform: {config.ai_client.platform or 'unresolved'}",
|
|
324
|
+
f"source: {config.ai_client.source}",
|
|
325
|
+
f"runtime_mode: {config.runtime_mode}",
|
|
326
|
+
]
|
|
327
|
+
if config.model:
|
|
328
|
+
details.append(f"model: {config.model}")
|
|
329
|
+
details.extend(f"note: {note}" for note in config.ai_client.notes)
|
|
330
|
+
return CommandResult(
|
|
331
|
+
0 if config.ai_client.command else 1,
|
|
332
|
+
"Python runtime AI CLI diagnostics",
|
|
333
|
+
"AI CLI resolution for the canonical Python runtime.",
|
|
334
|
+
tuple(details),
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
|
|
306
338
|
def handle_diagnostics(action: str, paths: RuntimePaths | None = None) -> CommandResult:
|
|
307
|
-
"""Dispatch diagnostics
|
|
339
|
+
"""Dispatch one registered diagnostics action."""
|
|
340
|
+
find_runtime_command("diagnostics", action)
|
|
308
341
|
if action == "paths":
|
|
309
342
|
return diagnostics_paths(paths)
|
|
310
343
|
if action == "entrypoints":
|
|
311
344
|
return diagnostics_entrypoints(paths)
|
|
312
345
|
if action == "version":
|
|
313
346
|
return diagnostics_version()
|
|
314
|
-
|
|
347
|
+
if action == "ai-cli":
|
|
348
|
+
return diagnostics_ai_cli(paths)
|
|
349
|
+
raise RuntimeError(f"Registered diagnostics action has no handler: {action}")
|
|
@@ -37,7 +37,6 @@ class DaemonStartOptions:
|
|
|
37
37
|
|
|
38
38
|
list_path: Path
|
|
39
39
|
env_overrides: str = ""
|
|
40
|
-
mode: str = ""
|
|
41
40
|
features_filter: str = ""
|
|
42
41
|
help_requested: bool = False
|
|
43
42
|
|
|
@@ -70,7 +69,7 @@ ID_KEY_BY_KIND = {
|
|
|
70
69
|
|
|
71
70
|
PROGRESS_COUNTS_BY_KIND = {
|
|
72
71
|
"feature": ("completed", "in_progress", "failed", "pending", "skipped", "auto_skipped"),
|
|
73
|
-
"bugfix": ("completed", "in_progress", "failed", "pending", "needs_info", "skipped"),
|
|
72
|
+
"bugfix": ("completed", "in_progress", "failed", "pending", "needs_info", "skipped", "auto_skipped"),
|
|
74
73
|
"refactor": ("completed", "in_progress", "failed", "pending", "skipped", "auto_skipped"),
|
|
75
74
|
}
|
|
76
75
|
|
|
@@ -79,8 +78,6 @@ def run_daemon_command(kind: str, action: str, legacy_args: tuple[str, ...], pat
|
|
|
79
78
|
"""Run a daemon lifecycle command for feature, bugfix, or refactor."""
|
|
80
79
|
family = family_for(kind, paths)
|
|
81
80
|
daemon_paths = _daemon_paths(family)
|
|
82
|
-
if action == "describe":
|
|
83
|
-
return CommandResult(0, f"Python {kind} daemon", _help_text(family))
|
|
84
81
|
if action == "start":
|
|
85
82
|
return _start(family, daemon_paths, legacy_args, paths)
|
|
86
83
|
if action == "status":
|
|
@@ -244,23 +241,17 @@ def _logs(family: RunnerFamily, daemon_paths: DaemonPaths, legacy_args: tuple[st
|
|
|
244
241
|
def _parse_start_args(family: RunnerFamily, legacy_args: tuple[str, ...]) -> DaemonStartOptions:
|
|
245
242
|
list_path = family.plan_path
|
|
246
243
|
env_overrides = ""
|
|
247
|
-
mode = ""
|
|
248
244
|
features_filter = ""
|
|
249
245
|
help_requested = False
|
|
250
246
|
positional: list[str] = []
|
|
251
247
|
index = 0
|
|
252
248
|
while index < len(legacy_args):
|
|
253
249
|
arg = legacy_args[index]
|
|
254
|
-
if arg in {"--help", "-h"
|
|
250
|
+
if arg in {"--help", "-h"}:
|
|
255
251
|
help_requested = True
|
|
256
252
|
elif arg == "--env" and index + 1 < len(legacy_args):
|
|
257
253
|
index += 1
|
|
258
254
|
env_overrides = legacy_args[index]
|
|
259
|
-
elif arg == "--mode" and index + 1 < len(legacy_args):
|
|
260
|
-
index += 1
|
|
261
|
-
mode = legacy_args[index]
|
|
262
|
-
if mode not in {"lite", "standard", "full"}:
|
|
263
|
-
raise ValueError(f"Invalid mode: {mode} (must be lite, standard, or full)")
|
|
264
255
|
elif arg == "--features" and index + 1 < len(legacy_args):
|
|
265
256
|
index += 1
|
|
266
257
|
features_filter = legacy_args[index]
|
|
@@ -271,7 +262,7 @@ def _parse_start_args(family: RunnerFamily, legacy_args: tuple[str, ...]) -> Dae
|
|
|
271
262
|
index += 1
|
|
272
263
|
if positional:
|
|
273
264
|
list_path = Path(positional[0]).expanduser()
|
|
274
|
-
return DaemonStartOptions(list_path=list_path, env_overrides=env_overrides,
|
|
265
|
+
return DaemonStartOptions(list_path=list_path, env_overrides=env_overrides, features_filter=features_filter, help_requested=help_requested)
|
|
275
266
|
|
|
276
267
|
|
|
277
268
|
def _parse_log_args(legacy_args: tuple[str, ...]) -> DaemonLogOptions:
|
|
@@ -300,14 +291,12 @@ def _payload_command(family: RunnerFamily, paths, list_path: Path, options: Daem
|
|
|
300
291
|
str(paths.project_root),
|
|
301
292
|
"--pipeline-root",
|
|
302
293
|
str(paths.pipeline_root),
|
|
303
|
-
family.kind,
|
|
304
294
|
"run",
|
|
295
|
+
family.kind,
|
|
305
296
|
str(list_path),
|
|
306
297
|
]
|
|
307
298
|
if family.kind == "feature" and options.features_filter:
|
|
308
299
|
command.extend(["--features", options.features_filter])
|
|
309
|
-
if options.mode:
|
|
310
|
-
command.extend(["--mode", options.mode])
|
|
311
300
|
return command
|
|
312
301
|
|
|
313
302
|
|
|
@@ -318,8 +307,6 @@ def _daemon_env(options: DaemonStartOptions) -> dict[str, str]:
|
|
|
318
307
|
key, value = token.split("=", 1)
|
|
319
308
|
if key:
|
|
320
309
|
env[key] = value
|
|
321
|
-
if options.mode:
|
|
322
|
-
env["PIPELINE_MODE"] = options.mode
|
|
323
310
|
return env
|
|
324
311
|
|
|
325
312
|
|
|
@@ -350,7 +337,6 @@ def _write_meta(family: RunnerFamily, path: Path, pid: int, started_at: str, lis
|
|
|
350
337
|
"started_at": started_at,
|
|
351
338
|
LIST_META_KEY_BY_KIND[family.kind]: str(list_path),
|
|
352
339
|
"env_overrides": options.env_overrides,
|
|
353
|
-
"mode": options.mode,
|
|
354
340
|
"log_file": str(log_file),
|
|
355
341
|
}
|
|
356
342
|
tmp = path.with_suffix(path.suffix + ".tmp")
|
|
@@ -407,8 +393,6 @@ def _write_log_separator(family: RunnerFamily, log_file: Path, list_path: Path,
|
|
|
407
393
|
]
|
|
408
394
|
if options.features_filter:
|
|
409
395
|
lines.append(f" Features filter: {options.features_filter}")
|
|
410
|
-
if options.mode:
|
|
411
|
-
lines.append(f" Mode: {options.mode}")
|
|
412
396
|
if options.env_overrides:
|
|
413
397
|
lines.append(f" Environment: {options.env_overrides}")
|
|
414
398
|
lines.extend(["================================================================", ""])
|
|
@@ -442,7 +442,7 @@ def ensure_linked_worktree(runtime: WorktreeRuntimeContext) -> WorktreeOperation
|
|
|
442
442
|
|
|
443
443
|
|
|
444
444
|
def merge_linked_worktree(runtime: WorktreeRuntimeContext, *, auto_push: bool = False) -> WorktreeOperationResult:
|
|
445
|
-
"""
|
|
445
|
+
"""Fast-forward a committed linked-worktree branch, rebasing only when needed."""
|
|
446
446
|
results: list[GitCommandResult] = []
|
|
447
447
|
clean = run_git_command(
|
|
448
448
|
runtime.worktree_path,
|
|
@@ -459,11 +459,12 @@ def merge_linked_worktree(runtime: WorktreeRuntimeContext, *, auto_push: bool =
|
|
|
459
459
|
if clean.return_code != 0:
|
|
460
460
|
return WorktreeOperationResult(False, "dirty_task_checkout", runtime, tuple(results))
|
|
461
461
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
462
|
+
if not branch_fast_forward_possible(runtime.context.project_root, runtime.context):
|
|
463
|
+
rebase = run_git_command(runtime.worktree_path, ("rebase", runtime.context.base_branch))
|
|
464
|
+
results.append(rebase)
|
|
465
|
+
if rebase.return_code != 0:
|
|
466
|
+
results.append(run_git_command(runtime.worktree_path, ("rebase", "--abort")))
|
|
467
|
+
return WorktreeOperationResult(False, "merge_conflict", runtime, tuple(results))
|
|
467
468
|
|
|
468
469
|
checkout = run_git_command(runtime.context.project_root, ("checkout", runtime.context.base_branch))
|
|
469
470
|
results.append(checkout)
|
|
@@ -581,14 +582,47 @@ def branch_return_plan(context: BranchContext) -> GitCommandPlan:
|
|
|
581
582
|
)
|
|
582
583
|
|
|
583
584
|
|
|
584
|
-
def
|
|
585
|
-
"""
|
|
585
|
+
def branch_fast_forward_possible(project_root: Path, context: BranchContext) -> bool:
|
|
586
|
+
"""Return whether the base branch is an ancestor of the committed task branch."""
|
|
587
|
+
return run_git_command(
|
|
588
|
+
project_root,
|
|
589
|
+
("merge-base", "--is-ancestor", context.base_branch, context.working_branch),
|
|
590
|
+
).return_code == 0
|
|
591
|
+
|
|
592
|
+
|
|
593
|
+
def branch_merge_plan(
|
|
594
|
+
context: BranchContext,
|
|
595
|
+
*,
|
|
596
|
+
auto_push: bool = False,
|
|
597
|
+
rebase: bool = True,
|
|
598
|
+
) -> GitCommandPlan:
|
|
599
|
+
"""Plan a merge that consumes only task-visible committed branch state."""
|
|
586
600
|
commands = [
|
|
587
|
-
_git(
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
601
|
+
_git(
|
|
602
|
+
"status",
|
|
603
|
+
"--porcelain",
|
|
604
|
+
"--untracked-files=normal",
|
|
605
|
+
"--",
|
|
606
|
+
".",
|
|
607
|
+
*HIDDEN_TOOL_WORKTREE_EXCLUDES,
|
|
608
|
+
description="require a clean task checkout",
|
|
609
|
+
),
|
|
591
610
|
]
|
|
611
|
+
if rebase:
|
|
612
|
+
commands.append(
|
|
613
|
+
_git(
|
|
614
|
+
"rebase",
|
|
615
|
+
context.base_branch,
|
|
616
|
+
context.working_branch,
|
|
617
|
+
description="rebase dev onto original",
|
|
618
|
+
)
|
|
619
|
+
)
|
|
620
|
+
commands.extend(
|
|
621
|
+
[
|
|
622
|
+
_git("checkout", context.base_branch, description="checkout original for fast-forward"),
|
|
623
|
+
_git("merge", "--ff-only", context.working_branch, description="fast-forward original"),
|
|
624
|
+
]
|
|
625
|
+
)
|
|
592
626
|
if auto_push:
|
|
593
627
|
commands.append(_git("push", allow_failure=True, description="optional auto-push"))
|
|
594
628
|
commands.append(_git("branch", "-d", context.working_branch, allow_failure=True, description="delete merged dev branch"))
|
|
@@ -596,8 +630,8 @@ def branch_merge_plan(context: BranchContext, *, auto_push: bool = False) -> Git
|
|
|
596
630
|
name="branch_merge",
|
|
597
631
|
commands=tuple(commands),
|
|
598
632
|
notes=(
|
|
599
|
-
"
|
|
600
|
-
"Rebase then fast-forward
|
|
633
|
+
"Task-visible checkout state must be clean; recognized internal/support dirt remains outside merge input.",
|
|
634
|
+
"Rebase only when base ancestry requires it, then fast-forward without pipeline-owned stashes.",
|
|
601
635
|
),
|
|
602
636
|
)
|
|
603
637
|
|
|
@@ -16,7 +16,6 @@ UTILITY_ENTRYPOINTS = {
|
|
|
16
16
|
"detect-stuck": "scripts/detect-stuck.py",
|
|
17
17
|
"generate-bootstrap-prompt": "scripts/generate-bootstrap-prompt.py",
|
|
18
18
|
"generate-bugfix-prompt": "scripts/generate-bugfix-prompt.py",
|
|
19
|
-
"generate-recovery-prompt": "scripts/generate-recovery-prompt.py",
|
|
20
19
|
"generate-refactor-prompt": "scripts/generate-refactor-prompt.py",
|
|
21
20
|
"init-bugfix-pipeline": "scripts/init-bugfix-pipeline.py",
|
|
22
21
|
"init-change-artifact": "scripts/init-change-artifact.py",
|
|
@@ -23,7 +23,6 @@ class RuntimePaths:
|
|
|
23
23
|
feature_state_dir: Path
|
|
24
24
|
bugfix_state_dir: Path
|
|
25
25
|
refactor_state_dir: Path
|
|
26
|
-
recovery_state_dir: Path
|
|
27
26
|
layout: str
|
|
28
27
|
|
|
29
28
|
def path_values(self) -> tuple[Path, ...]:
|
|
@@ -42,7 +41,6 @@ class RuntimePaths:
|
|
|
42
41
|
self.feature_state_dir,
|
|
43
42
|
self.bugfix_state_dir,
|
|
44
43
|
self.refactor_state_dir,
|
|
45
|
-
self.recovery_state_dir,
|
|
46
44
|
)
|
|
47
45
|
|
|
48
46
|
|
|
@@ -105,6 +103,5 @@ def resolve_runtime_paths(
|
|
|
105
103
|
feature_state_dir=state_dir / "features",
|
|
106
104
|
bugfix_state_dir=state_dir / "bugfix",
|
|
107
105
|
refactor_state_dir=state_dir / "refactor",
|
|
108
|
-
recovery_state_dir=state_dir / "recovery",
|
|
109
106
|
layout=layout,
|
|
110
107
|
)
|