prizmkit 1.1.154 → 1.1.156
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 +21 -27
- package/bundled/dev-pipeline/prizmkit_runtime/checkpoint_state.py +341 -15
- package/bundled/dev-pipeline/prizmkit_runtime/cli.py +0 -3
- package/bundled/dev-pipeline/prizmkit_runtime/daemon.py +1 -15
- package/bundled/dev-pipeline/prizmkit_runtime/gitops.py +48 -14
- package/bundled/dev-pipeline/prizmkit_runtime/runner_classification.py +50 -2
- package/bundled/dev-pipeline/prizmkit_runtime/runner_models.py +0 -9
- package/bundled/dev-pipeline/prizmkit_runtime/runner_prompts.py +3 -3
- package/bundled/dev-pipeline/prizmkit_runtime/runners.py +120 -22
- package/bundled/dev-pipeline/prizmkit_runtime/runtime_commit.py +482 -0
- 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/prompt_framework.py +36 -41
- package/bundled/dev-pipeline/scripts/update-bug-status.py +1 -4
- package/bundled/dev-pipeline/scripts/update-checkpoint.py +61 -13
- package/bundled/dev-pipeline/scripts/update-feature-status.py +1 -4
- package/bundled/dev-pipeline/scripts/update-refactor-status.py +1 -4
- 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/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_checkpoint_state.py +469 -18
- package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +262 -175
- 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 +168 -18
- package/bundled/dev-pipeline/tests/test_recovery_workflow.py +111 -0
- package/bundled/dev-pipeline/tests/test_reset_preserve.py +0 -2
- package/bundled/dev-pipeline/tests/test_runtime_commit.py +608 -0
- package/bundled/dev-pipeline/tests/test_unified_cli.py +167 -25
- 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/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 +75 -11
- package/bundled/skills/prizmkit-prizm-docs/assets/prizm-docs-format.md +191 -56
- package/bundled/skills/prizmkit-prizm-docs/references/op-init.md +18 -18
- package/bundled/skills/prizmkit-prizm-docs/references/op-rebuild.md +14 -8
- package/bundled/skills/prizmkit-prizm-docs/references/op-status.md +12 -5
- package/bundled/skills/prizmkit-prizm-docs/references/op-update.md +23 -12
- package/bundled/skills/prizmkit-prizm-docs/references/op-validate.md +13 -9
- package/bundled/skills/prizmkit-retrospective/SKILL.md +94 -97
- package/bundled/skills/prizmkit-retrospective/references/knowledge-injection-steps.md +79 -37
- package/bundled/skills/prizmkit-retrospective/references/retrospective-result-schema.json +138 -0
- package/bundled/skills/prizmkit-retrospective/references/structural-sync-steps.md +111 -54
- 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 +2 -1
- package/bundled/skills/recovery-workflow/references/detection.md +4 -3
- package/bundled/skills/recovery-workflow/scripts/detect-recovery-state.py +15 -5
- package/bundled/templates/hooks/validate-prizm-docs.py +124 -12
- package/package.json +1 -1
- package/src/scaffold.js +33 -22
- 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
|
@@ -6,15 +6,19 @@ import copy
|
|
|
6
6
|
import json
|
|
7
7
|
import re
|
|
8
8
|
from dataclasses import dataclass, field
|
|
9
|
-
from pathlib import Path
|
|
9
|
+
from pathlib import Path, PurePosixPath
|
|
10
10
|
from typing import Any, Mapping
|
|
11
11
|
|
|
12
|
-
from .test_result import
|
|
12
|
+
from .test_result import (
|
|
13
|
+
valid_legacy_test_artifact_pair,
|
|
14
|
+
valid_test_artifact_pair,
|
|
15
|
+
)
|
|
13
16
|
|
|
14
17
|
VALID_CHECKPOINT_STATUSES = {"pending", "in_progress", "completed", "skipped", "failed"}
|
|
15
18
|
TERMINAL_STEP_STATUSES = {"completed", "skipped"}
|
|
16
19
|
STEP_ID_PATTERN = re.compile(r"^S[0-9]+$")
|
|
17
20
|
MAX_OUTER_REPAIR_ROUNDS = 3
|
|
21
|
+
_COMMIT_HASH_PATTERN = re.compile(r"^[0-9a-fA-F]{40,64}$")
|
|
18
22
|
|
|
19
23
|
REVIEW_RESULTS = {"REVIEW_PASS", "REVIEW_NEEDS_FIXES"}
|
|
20
24
|
TEST_RESULTS = {"TEST_PASS", "TEST_NEEDS_FIXES", "TEST_BLOCKED"}
|
|
@@ -32,6 +36,8 @@ VALID_STAGE_RESULTS = (
|
|
|
32
36
|
)
|
|
33
37
|
STAGE_RESULT_OWNERS = {
|
|
34
38
|
"prizmkit-plan": PLAN_RESULTS,
|
|
39
|
+
"context-snapshot-and-plan": PLAN_RESULTS,
|
|
40
|
+
"bug-diagnosis-and-plan": PLAN_RESULTS,
|
|
35
41
|
"prizmkit-implement": IMPLEMENT_RESULTS,
|
|
36
42
|
"prizmkit-code-review": REVIEW_RESULTS,
|
|
37
43
|
"prizmkit-test": TEST_RESULTS,
|
|
@@ -49,6 +55,15 @@ WORKFLOW_STAGE_SKILLS = {
|
|
|
49
55
|
SKILL_WORKFLOW_STAGES = {
|
|
50
56
|
skill: stage for stage, skill in WORKFLOW_STAGE_SKILLS.items()
|
|
51
57
|
}
|
|
58
|
+
SKILL_WORKFLOW_STAGES.update({
|
|
59
|
+
"context-snapshot-and-plan": "plan",
|
|
60
|
+
"bug-diagnosis-and-plan": "plan",
|
|
61
|
+
})
|
|
62
|
+
FAMILY_PLAN_SKILLS = {
|
|
63
|
+
"feature-pipeline": "context-snapshot-and-plan",
|
|
64
|
+
"bugfix-pipeline": "bug-diagnosis-and-plan",
|
|
65
|
+
"refactor-pipeline": "prizmkit-plan",
|
|
66
|
+
}
|
|
52
67
|
VALID_TERMINAL_STATUSES = {"WORKFLOW_COMPLETED", "WORKFLOW_BLOCKED"}
|
|
53
68
|
VALID_REPAIR_SCOPES = {
|
|
54
69
|
"production",
|
|
@@ -63,7 +78,7 @@ SEMANTIC_STATE_KEYS = {
|
|
|
63
78
|
"bugfix-pipeline": "bugfix_state",
|
|
64
79
|
"refactor-pipeline": "refactor_state",
|
|
65
80
|
}
|
|
66
|
-
|
|
81
|
+
LEGACY_FAMILY_REQUIRED_STAGES = {
|
|
67
82
|
"feature-pipeline": (
|
|
68
83
|
"prizmkit-implement",
|
|
69
84
|
"prizmkit-code-review",
|
|
@@ -91,6 +106,34 @@ FAMILY_REQUIRED_STAGES = {
|
|
|
91
106
|
),
|
|
92
107
|
}
|
|
93
108
|
|
|
109
|
+
FAMILY_REQUIRED_STAGES = {
|
|
110
|
+
"feature-pipeline": (
|
|
111
|
+
"prizmkit-implement",
|
|
112
|
+
"prizmkit-code-review",
|
|
113
|
+
"prizmkit-test",
|
|
114
|
+
"completion-summary",
|
|
115
|
+
"prizmkit-retrospective",
|
|
116
|
+
"prizmkit-committer",
|
|
117
|
+
),
|
|
118
|
+
"bugfix-pipeline": (
|
|
119
|
+
"prizmkit-implement",
|
|
120
|
+
"prizmkit-code-review",
|
|
121
|
+
"prizmkit-test",
|
|
122
|
+
"bug-report",
|
|
123
|
+
"prizmkit-retrospective",
|
|
124
|
+
"prizmkit-committer",
|
|
125
|
+
),
|
|
126
|
+
"refactor-pipeline": (
|
|
127
|
+
"prizmkit-implement",
|
|
128
|
+
"prizmkit-code-review",
|
|
129
|
+
"prizmkit-test",
|
|
130
|
+
"refactor-report",
|
|
131
|
+
"completion-summary",
|
|
132
|
+
"prizmkit-retrospective",
|
|
133
|
+
"prizmkit-committer",
|
|
134
|
+
),
|
|
135
|
+
}
|
|
136
|
+
|
|
94
137
|
|
|
95
138
|
@dataclass(frozen=True)
|
|
96
139
|
class CheckpointStep:
|
|
@@ -128,10 +171,13 @@ class SemanticCheckpoint:
|
|
|
128
171
|
repair_round: int = 0
|
|
129
172
|
blocked_reason: str | None = None
|
|
130
173
|
terminal_status: str | None = None
|
|
174
|
+
runtime_base_head: str = ""
|
|
175
|
+
runtime_commit_hash: str = ""
|
|
131
176
|
sequence_valid: bool = False
|
|
132
177
|
test_result_valid: bool = False
|
|
133
178
|
artifacts_valid: bool = False
|
|
134
179
|
completion_ready: bool = False
|
|
180
|
+
commit_ready: bool = False
|
|
135
181
|
complete: bool = False
|
|
136
182
|
blocked: bool = False
|
|
137
183
|
error_code: str = ""
|
|
@@ -147,6 +193,9 @@ class SemanticCheckpoint:
|
|
|
147
193
|
"repair_round": self.repair_round,
|
|
148
194
|
"blocked_reason": self.blocked_reason,
|
|
149
195
|
"terminal_status": self.terminal_status,
|
|
196
|
+
"runtime_base_head": self.runtime_base_head,
|
|
197
|
+
"runtime_commit_hash": self.runtime_commit_hash,
|
|
198
|
+
"commit_ready": self.commit_ready,
|
|
150
199
|
}
|
|
151
200
|
|
|
152
201
|
|
|
@@ -200,6 +249,11 @@ class CheckpointState:
|
|
|
200
249
|
"""Return whether this checkpoint authoritatively proves task completion."""
|
|
201
250
|
return self.valid and self.semantic.complete
|
|
202
251
|
|
|
252
|
+
@property
|
|
253
|
+
def semantic_commit_ready(self) -> bool:
|
|
254
|
+
"""Return whether the runtime may execute the prepared local commit."""
|
|
255
|
+
return self.valid and self.semantic.commit_ready
|
|
256
|
+
|
|
203
257
|
@property
|
|
204
258
|
def semantic_blocked(self) -> bool:
|
|
205
259
|
"""Return whether this checkpoint has a deterministic blocked terminal state."""
|
|
@@ -591,8 +645,21 @@ def _derive_semantic_state(
|
|
|
591
645
|
return _semantic_error(workflow_type, current_step, "invalid_semantic_state", f"{state_key} must be an object")
|
|
592
646
|
|
|
593
647
|
required = FAMILY_REQUIRED_STAGES.get(workflow_type)
|
|
594
|
-
|
|
648
|
+
canonical_sequence_error = (
|
|
649
|
+
_required_sequence_error(steps, required)
|
|
650
|
+
if required else "unsupported workflow family"
|
|
651
|
+
)
|
|
652
|
+
if not canonical_sequence_error:
|
|
653
|
+
canonical_sequence_error = _configured_verification_sequence_error(steps)
|
|
654
|
+
legacy_required = LEGACY_FAMILY_REQUIRED_STAGES.get(workflow_type)
|
|
655
|
+
legacy_sequence_valid = bool(
|
|
656
|
+
canonical_sequence_error
|
|
657
|
+
and legacy_required
|
|
658
|
+
and not _required_sequence_error(steps, legacy_required)
|
|
659
|
+
)
|
|
660
|
+
sequence_error = "" if legacy_sequence_valid else canonical_sequence_error
|
|
595
661
|
sequence_valid = not sequence_error
|
|
662
|
+
canonical_sequence_valid = not canonical_sequence_error
|
|
596
663
|
|
|
597
664
|
repair_round = raw_state.get("repair_round", 0)
|
|
598
665
|
if isinstance(repair_round, bool) or not isinstance(repair_round, int) or not 0 <= repair_round <= MAX_OUTER_REPAIR_ROUNDS:
|
|
@@ -629,6 +696,20 @@ def _derive_semantic_state(
|
|
|
629
696
|
terminal_status = raw_state.get("terminal_status")
|
|
630
697
|
if terminal_status is not None and terminal_status not in VALID_TERMINAL_STATUSES:
|
|
631
698
|
return _semantic_error(workflow_type, current_step, "invalid_terminal_status", "terminal_status is not recognized")
|
|
699
|
+
runtime_base_head = str(raw_state.get("runtime_base_head") or "").strip()
|
|
700
|
+
runtime_commit_hash = str(raw_state.get("runtime_commit_hash") or "").strip()
|
|
701
|
+
runtime_receipt_valid = bool(
|
|
702
|
+
_COMMIT_HASH_PATTERN.fullmatch(runtime_base_head)
|
|
703
|
+
and _COMMIT_HASH_PATTERN.fullmatch(runtime_commit_hash)
|
|
704
|
+
and runtime_base_head.lower() != runtime_commit_hash.lower()
|
|
705
|
+
)
|
|
706
|
+
if (runtime_base_head or runtime_commit_hash) and not runtime_receipt_valid:
|
|
707
|
+
return _semantic_error(
|
|
708
|
+
workflow_type,
|
|
709
|
+
current_step,
|
|
710
|
+
"invalid_runtime_commit_receipt",
|
|
711
|
+
"Runtime commit receipt requires distinct valid base and commit hashes",
|
|
712
|
+
)
|
|
632
713
|
blocked_reason = raw_state.get("blocked_reason")
|
|
633
714
|
if blocked_reason is not None and (not isinstance(blocked_reason, str) or not blocked_reason.strip()):
|
|
634
715
|
return _semantic_error(workflow_type, current_step, "invalid_blocked_reason", "blocked_reason must be a non-empty string")
|
|
@@ -651,6 +732,25 @@ def _derive_semantic_state(
|
|
|
651
732
|
|
|
652
733
|
review_step = _single_step(steps, "prizmkit-code-review")
|
|
653
734
|
test_step = _single_step(steps, "prizmkit-test")
|
|
735
|
+
plan_step = _single_step(steps, FAMILY_PLAN_SKILLS.get(workflow_type, ""))
|
|
736
|
+
implement_step = _single_step(steps, "prizmkit-implement")
|
|
737
|
+
plan_valid = bool(
|
|
738
|
+
plan_step
|
|
739
|
+
and implement_step
|
|
740
|
+
and plan_step.index < implement_step.index
|
|
741
|
+
and plan_step.status == "completed"
|
|
742
|
+
and plan_step.stage_result == "PLAN_READY"
|
|
743
|
+
)
|
|
744
|
+
configured_manual_valid = all(
|
|
745
|
+
step.status == "completed"
|
|
746
|
+
for step in steps
|
|
747
|
+
if step.skill == "manual-verification"
|
|
748
|
+
)
|
|
749
|
+
implementation_valid = bool(
|
|
750
|
+
implement_step
|
|
751
|
+
and implement_step.status == "completed"
|
|
752
|
+
and implement_step.stage_result == "IMPLEMENTED"
|
|
753
|
+
)
|
|
654
754
|
review_valid = bool(
|
|
655
755
|
review_step
|
|
656
756
|
and review_step.status == "completed"
|
|
@@ -661,18 +761,65 @@ def _derive_semantic_state(
|
|
|
661
761
|
and test_step.status == "completed"
|
|
662
762
|
and test_step.stage_result == "TEST_PASS"
|
|
663
763
|
)
|
|
664
|
-
|
|
764
|
+
effective_required = legacy_required if legacy_sequence_valid else required
|
|
765
|
+
all_required_completed = bool(effective_required) and all(
|
|
665
766
|
(step := _single_step(steps, skill)) is not None and step.status == "completed"
|
|
666
|
-
for skill in
|
|
767
|
+
for skill in effective_required
|
|
667
768
|
)
|
|
668
769
|
artifacts_valid = all(
|
|
669
770
|
_required_step_artifacts_valid(step, checkpoint_path, project_root)
|
|
670
771
|
for step in steps
|
|
671
772
|
if step.status == "completed"
|
|
672
773
|
)
|
|
774
|
+
completion_artifacts_valid = artifacts_valid or (
|
|
775
|
+
legacy_sequence_valid
|
|
776
|
+
and all(
|
|
777
|
+
_required_step_artifacts_valid(
|
|
778
|
+
step,
|
|
779
|
+
checkpoint_path,
|
|
780
|
+
project_root,
|
|
781
|
+
allow_legacy_test=True,
|
|
782
|
+
)
|
|
783
|
+
for step in steps
|
|
784
|
+
if step.status == "completed"
|
|
785
|
+
)
|
|
786
|
+
)
|
|
787
|
+
retrospective_step = _single_step(steps, "prizmkit-retrospective")
|
|
788
|
+
retrospective_valid = bool(
|
|
789
|
+
retrospective_step
|
|
790
|
+
and retrospective_step.status == "completed"
|
|
791
|
+
and retrospective_step.stage_result == "RETRO_COMPLETE"
|
|
792
|
+
)
|
|
793
|
+
committer_step = _single_step(steps, "prizmkit-committer")
|
|
794
|
+
committed_valid = bool(
|
|
795
|
+
committer_step
|
|
796
|
+
and committer_step.status == "completed"
|
|
797
|
+
and committer_step.stage_result == "COMMITTED"
|
|
798
|
+
)
|
|
799
|
+
precommit_required = tuple(
|
|
800
|
+
skill for skill in (required or ()) if skill != "prizmkit-committer"
|
|
801
|
+
)
|
|
802
|
+
all_precommit_completed = bool(precommit_required) and all(
|
|
803
|
+
(step := _single_step(steps, skill)) is not None and step.status == "completed"
|
|
804
|
+
for skill in precommit_required
|
|
805
|
+
)
|
|
806
|
+
commit_request_valid = bool(
|
|
807
|
+
committer_step
|
|
808
|
+
and committer_step.status == "in_progress"
|
|
809
|
+
and committer_step.stage_result == "COMMIT_PENDING"
|
|
810
|
+
and _required_step_artifacts_valid(committer_step, checkpoint_path, project_root)
|
|
811
|
+
)
|
|
812
|
+
commit_ready = (
|
|
813
|
+
canonical_sequence_valid and plan_valid and configured_manual_valid
|
|
814
|
+
and all_precommit_completed and implementation_valid and review_valid
|
|
815
|
+
and test_result_valid and retrospective_valid and artifacts_valid
|
|
816
|
+
and commit_request_valid and terminal_status is None
|
|
817
|
+
)
|
|
673
818
|
completion_ready = (
|
|
674
|
-
sequence_valid and all_required_completed and
|
|
675
|
-
and test_result_valid and
|
|
819
|
+
sequence_valid and all_required_completed and implementation_valid
|
|
820
|
+
and review_valid and test_result_valid and retrospective_valid
|
|
821
|
+
and committed_valid and completion_artifacts_valid
|
|
822
|
+
and (legacy_sequence_valid or runtime_receipt_valid)
|
|
676
823
|
)
|
|
677
824
|
blocked = terminal_status == "WORKFLOW_BLOCKED" and bool(blocked_reason)
|
|
678
825
|
complete = completion_ready and terminal_status == "WORKFLOW_COMPLETED" and not blocked
|
|
@@ -719,10 +866,13 @@ def _derive_semantic_state(
|
|
|
719
866
|
repair_round=repair_round,
|
|
720
867
|
blocked_reason=blocked_reason,
|
|
721
868
|
terminal_status=terminal_status,
|
|
869
|
+
runtime_base_head=runtime_base_head,
|
|
870
|
+
runtime_commit_hash=runtime_commit_hash,
|
|
722
871
|
sequence_valid=sequence_valid,
|
|
723
872
|
test_result_valid=test_result_valid,
|
|
724
|
-
artifacts_valid=
|
|
873
|
+
artifacts_valid=completion_artifacts_valid,
|
|
725
874
|
completion_ready=completion_ready,
|
|
875
|
+
commit_ready=commit_ready,
|
|
726
876
|
complete=complete,
|
|
727
877
|
blocked=blocked,
|
|
728
878
|
error_code=error_code,
|
|
@@ -747,16 +897,34 @@ def _required_sequence_error(
|
|
|
747
897
|
return ""
|
|
748
898
|
|
|
749
899
|
|
|
900
|
+
def _configured_verification_sequence_error(
|
|
901
|
+
steps: tuple[CheckpointStep, ...],
|
|
902
|
+
) -> str:
|
|
903
|
+
"""Require configured Browser/Manual checks between Review and Test."""
|
|
904
|
+
review = _single_step(steps, "prizmkit-code-review")
|
|
905
|
+
test = _single_step(steps, "prizmkit-test")
|
|
906
|
+
if review is None or test is None:
|
|
907
|
+
return ""
|
|
908
|
+
for skill in ("browser-verification", "manual-verification"):
|
|
909
|
+
matches = [step for step in steps if step.skill == skill]
|
|
910
|
+
if len(matches) > 1:
|
|
911
|
+
return f"Expected at most one configured stage {skill}"
|
|
912
|
+
if matches and not (review.index < matches[0].index < test.index):
|
|
913
|
+
return f"Configured stage {skill} must run after review and before test"
|
|
914
|
+
return ""
|
|
915
|
+
|
|
916
|
+
|
|
750
917
|
def _single_step(steps: tuple[CheckpointStep, ...], skill: str) -> CheckpointStep | None:
|
|
751
918
|
matches = [step for step in steps if step.skill == skill]
|
|
752
919
|
return matches[0] if len(matches) == 1 else None
|
|
753
920
|
|
|
754
921
|
|
|
755
|
-
|
|
756
922
|
def _required_step_artifacts_valid(
|
|
757
923
|
step: CheckpointStep,
|
|
758
924
|
checkpoint_path: Path | None,
|
|
759
925
|
project_root: Path | None,
|
|
926
|
+
*,
|
|
927
|
+
allow_legacy_test: bool = False,
|
|
760
928
|
) -> bool:
|
|
761
929
|
"""Validate declared artifacts, including semantic test terminal output."""
|
|
762
930
|
if step.skill == "prizmkit-test":
|
|
@@ -769,11 +937,38 @@ def _required_step_artifacts_valid(
|
|
|
769
937
|
result_path = (root / results[0]).resolve()
|
|
770
938
|
if not _is_within_root(report_path, root) or not _is_within_root(result_path, root):
|
|
771
939
|
return False
|
|
772
|
-
|
|
940
|
+
validator = (
|
|
941
|
+
valid_legacy_test_artifact_pair
|
|
942
|
+
if allow_legacy_test
|
|
943
|
+
else valid_test_artifact_pair
|
|
944
|
+
)
|
|
945
|
+
return validator(
|
|
773
946
|
report_path,
|
|
774
947
|
result_path,
|
|
775
948
|
required_result="TEST_PASS",
|
|
776
949
|
)
|
|
950
|
+
if step.skill == "prizmkit-code-review":
|
|
951
|
+
return _valid_review_artifact(step, checkpoint_path, project_root)
|
|
952
|
+
if step.skill == "prizmkit-retrospective":
|
|
953
|
+
return _valid_retrospective_artifact(step, checkpoint_path, project_root)
|
|
954
|
+
if (
|
|
955
|
+
step.skill == "prizmkit-committer"
|
|
956
|
+
and step.status == "completed"
|
|
957
|
+
and step.stage_result == "COMMITTED"
|
|
958
|
+
):
|
|
959
|
+
requests = tuple(
|
|
960
|
+
artifact
|
|
961
|
+
for artifact in step.required_artifacts
|
|
962
|
+
if artifact.endswith("/runtime-commit-request.json")
|
|
963
|
+
)
|
|
964
|
+
if not step.required_artifacts:
|
|
965
|
+
return True
|
|
966
|
+
if len(requests) != 1:
|
|
967
|
+
return False
|
|
968
|
+
durable = tuple(
|
|
969
|
+
artifact for artifact in step.required_artifacts if artifact not in requests
|
|
970
|
+
)
|
|
971
|
+
return _required_artifact_paths_exist(durable, checkpoint_path, project_root)
|
|
777
972
|
return _required_artifacts_exist(step, checkpoint_path, project_root)
|
|
778
973
|
|
|
779
974
|
|
|
@@ -782,23 +977,154 @@ def _required_artifacts_exist(
|
|
|
782
977
|
checkpoint_path: Path | None,
|
|
783
978
|
project_root: Path | None,
|
|
784
979
|
) -> bool:
|
|
785
|
-
|
|
980
|
+
return _required_artifact_paths_exist(
|
|
981
|
+
step.required_artifacts,
|
|
982
|
+
checkpoint_path,
|
|
983
|
+
project_root,
|
|
984
|
+
)
|
|
985
|
+
|
|
986
|
+
|
|
987
|
+
def _required_artifact_paths_exist(
|
|
988
|
+
artifacts: tuple[str, ...],
|
|
989
|
+
checkpoint_path: Path | None,
|
|
990
|
+
project_root: Path | None,
|
|
991
|
+
) -> bool:
|
|
992
|
+
if not artifacts:
|
|
786
993
|
return True
|
|
787
994
|
import glob
|
|
788
995
|
|
|
789
996
|
root = (project_root or _infer_project_root(checkpoint_path)).resolve()
|
|
790
|
-
for artifact in
|
|
997
|
+
for artifact in artifacts:
|
|
791
998
|
candidate = (root / artifact).resolve()
|
|
792
999
|
if not _is_within_root(candidate, root):
|
|
793
1000
|
return False
|
|
794
1001
|
if glob.has_magic(str(candidate)):
|
|
795
1002
|
if not glob.glob(str(candidate)):
|
|
796
1003
|
return False
|
|
797
|
-
|
|
798
|
-
|
|
1004
|
+
else:
|
|
1005
|
+
try:
|
|
1006
|
+
if not candidate.exists():
|
|
1007
|
+
return False
|
|
1008
|
+
if candidate.is_file() and candidate.stat().st_size == 0:
|
|
1009
|
+
return False
|
|
1010
|
+
except OSError:
|
|
1011
|
+
return False
|
|
799
1012
|
return True
|
|
800
1013
|
|
|
801
1014
|
|
|
1015
|
+
def _valid_review_artifact(
|
|
1016
|
+
step: CheckpointStep,
|
|
1017
|
+
checkpoint_path: Path | None,
|
|
1018
|
+
project_root: Path | None,
|
|
1019
|
+
) -> bool:
|
|
1020
|
+
reports = [item for item in step.required_artifacts if item.endswith("/review-report.md")]
|
|
1021
|
+
if not reports:
|
|
1022
|
+
return _required_artifacts_exist(step, checkpoint_path, project_root)
|
|
1023
|
+
if len(reports) != 1 or not _required_artifacts_exist(step, checkpoint_path, project_root):
|
|
1024
|
+
return False
|
|
1025
|
+
root = (project_root or _infer_project_root(checkpoint_path)).resolve()
|
|
1026
|
+
report = (root / reports[0]).resolve()
|
|
1027
|
+
if not _is_within_root(report, root):
|
|
1028
|
+
return False
|
|
1029
|
+
try:
|
|
1030
|
+
text = report.read_text(encoding="utf-8")
|
|
1031
|
+
except (OSError, UnicodeError):
|
|
1032
|
+
return False
|
|
1033
|
+
final_sections = re.findall(
|
|
1034
|
+
r"(?ms)^## Final Result\s*$\n(?P<body>.*?)(?=^## |\Z)",
|
|
1035
|
+
text,
|
|
1036
|
+
)
|
|
1037
|
+
if len(final_sections) != 1:
|
|
1038
|
+
return False
|
|
1039
|
+
verdicts = re.findall(r"(?m)^- Verdict:\s*(PASS|NEEDS_FIXES)\s*$", final_sections[0])
|
|
1040
|
+
return verdicts == ["PASS"]
|
|
1041
|
+
|
|
1042
|
+
|
|
1043
|
+
def _valid_retrospective_artifact(
|
|
1044
|
+
step: CheckpointStep,
|
|
1045
|
+
checkpoint_path: Path | None,
|
|
1046
|
+
project_root: Path | None,
|
|
1047
|
+
) -> bool:
|
|
1048
|
+
results = [
|
|
1049
|
+
item for item in step.required_artifacts
|
|
1050
|
+
if item.endswith("/retrospective-result.json")
|
|
1051
|
+
]
|
|
1052
|
+
if not results:
|
|
1053
|
+
return _required_artifacts_exist(step, checkpoint_path, project_root)
|
|
1054
|
+
if len(results) != 1 or not _required_artifacts_exist(step, checkpoint_path, project_root):
|
|
1055
|
+
return False
|
|
1056
|
+
root = (project_root or _infer_project_root(checkpoint_path)).resolve()
|
|
1057
|
+
result_path = (root / results[0]).resolve()
|
|
1058
|
+
if not _is_within_root(result_path, root):
|
|
1059
|
+
return False
|
|
1060
|
+
try:
|
|
1061
|
+
value = json.loads(result_path.read_text(encoding="utf-8"))
|
|
1062
|
+
except (OSError, UnicodeError, json.JSONDecodeError):
|
|
1063
|
+
return False
|
|
1064
|
+
expected_keys = {
|
|
1065
|
+
"schema_version",
|
|
1066
|
+
"outcome",
|
|
1067
|
+
"result",
|
|
1068
|
+
"reason",
|
|
1069
|
+
"change_paths",
|
|
1070
|
+
"documentation_paths",
|
|
1071
|
+
"validation",
|
|
1072
|
+
}
|
|
1073
|
+
return bool(
|
|
1074
|
+
isinstance(value, dict)
|
|
1075
|
+
and set(value) == expected_keys
|
|
1076
|
+
and value.get("schema_version") == 1
|
|
1077
|
+
and value.get("outcome") == "RETRO_COMPLETE"
|
|
1078
|
+
and value.get("result") in {"DOCS_UPDATED", "NO_DOC_CHANGE"}
|
|
1079
|
+
and isinstance(value.get("reason"), str)
|
|
1080
|
+
and value["reason"].strip()
|
|
1081
|
+
and isinstance(value.get("change_paths"), list)
|
|
1082
|
+
and all(_valid_retrospective_change_path(path) for path in value["change_paths"])
|
|
1083
|
+
and isinstance(value.get("documentation_paths"), list)
|
|
1084
|
+
and all(
|
|
1085
|
+
_valid_retrospective_documentation_path(path)
|
|
1086
|
+
for path in value["documentation_paths"]
|
|
1087
|
+
)
|
|
1088
|
+
and isinstance(value.get("validation"), list)
|
|
1089
|
+
and all(isinstance(item, str) and item.strip() for item in value["validation"])
|
|
1090
|
+
and (
|
|
1091
|
+
value.get("result") != "DOCS_UPDATED"
|
|
1092
|
+
or (
|
|
1093
|
+
bool(value["documentation_paths"])
|
|
1094
|
+
and bool(value["validation"])
|
|
1095
|
+
)
|
|
1096
|
+
)
|
|
1097
|
+
)
|
|
1098
|
+
|
|
1099
|
+
|
|
1100
|
+
def _valid_retrospective_documentation_path(value: object) -> bool:
|
|
1101
|
+
if not isinstance(value, str) or not value.strip() or "\\" in value:
|
|
1102
|
+
return False
|
|
1103
|
+
raw_parts = value.split("/")
|
|
1104
|
+
if any(part in {"", ".", ".."} for part in raw_parts):
|
|
1105
|
+
return False
|
|
1106
|
+
path = PurePosixPath(value)
|
|
1107
|
+
return bool(
|
|
1108
|
+
not path.is_absolute()
|
|
1109
|
+
and len(raw_parts) >= 3
|
|
1110
|
+
and raw_parts[:2] == [".prizmkit", "prizm-docs"]
|
|
1111
|
+
and path.suffix == ".prizm"
|
|
1112
|
+
)
|
|
1113
|
+
|
|
1114
|
+
|
|
1115
|
+
def _valid_retrospective_change_path(value: object) -> bool:
|
|
1116
|
+
if not isinstance(value, str) or not value.strip() or "\\" in value:
|
|
1117
|
+
return False
|
|
1118
|
+
raw_parts = value.split("/")
|
|
1119
|
+
if any(part in {"", ".", ".."} for part in raw_parts):
|
|
1120
|
+
return False
|
|
1121
|
+
path = PurePosixPath(value)
|
|
1122
|
+
return bool(
|
|
1123
|
+
not path.is_absolute()
|
|
1124
|
+
and raw_parts[0] != ".prizmkit"
|
|
1125
|
+
)
|
|
1126
|
+
|
|
1127
|
+
|
|
802
1128
|
def _is_within_root(path: Path, root: Path) -> bool:
|
|
803
1129
|
try:
|
|
804
1130
|
path.relative_to(root)
|
|
@@ -24,7 +24,6 @@ _LEAF_OPTIONS_WITH_VALUES = {
|
|
|
24
24
|
"-n",
|
|
25
25
|
"--max-retries",
|
|
26
26
|
"--max-infra-retries",
|
|
27
|
-
"--mode",
|
|
28
27
|
"--resume-phase",
|
|
29
28
|
}
|
|
30
29
|
|
|
@@ -55,7 +54,6 @@ def _add_runner_arguments(parser: argparse.ArgumentParser, family: str) -> None:
|
|
|
55
54
|
parser.add_argument("--features", help="Feature ID, range, or comma-separated selection.")
|
|
56
55
|
parser.add_argument("--max-retries", type=_non_negative_int)
|
|
57
56
|
parser.add_argument("--max-infra-retries", type=_non_negative_int)
|
|
58
|
-
parser.add_argument("--mode")
|
|
59
57
|
parser.add_argument("--resume-phase")
|
|
60
58
|
parser.add_argument("--dry-run", action="store_true")
|
|
61
59
|
parser.add_argument("--clean", action="store_true")
|
|
@@ -112,7 +110,6 @@ def _add_reset_subparsers(
|
|
|
112
110
|
def _add_daemon_start_arguments(parser: argparse.ArgumentParser, family: str) -> None:
|
|
113
111
|
parser.add_argument("list_path", nargs="?", help="Optional family plan path.")
|
|
114
112
|
parser.add_argument("--env", help="Quoted KEY=VALUE daemon environment overrides.")
|
|
115
|
-
parser.add_argument("--mode", choices=("lite", "standard", "full"))
|
|
116
113
|
if family == "feature":
|
|
117
114
|
parser.add_argument("--features", help="Feature ID, range, or comma-separated selection.")
|
|
118
115
|
|
|
@@ -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
|
|
|
@@ -242,7 +241,6 @@ def _logs(family: RunnerFamily, daemon_paths: DaemonPaths, legacy_args: tuple[st
|
|
|
242
241
|
def _parse_start_args(family: RunnerFamily, legacy_args: tuple[str, ...]) -> DaemonStartOptions:
|
|
243
242
|
list_path = family.plan_path
|
|
244
243
|
env_overrides = ""
|
|
245
|
-
mode = ""
|
|
246
244
|
features_filter = ""
|
|
247
245
|
help_requested = False
|
|
248
246
|
positional: list[str] = []
|
|
@@ -254,11 +252,6 @@ def _parse_start_args(family: RunnerFamily, legacy_args: tuple[str, ...]) -> Dae
|
|
|
254
252
|
elif arg == "--env" and index + 1 < len(legacy_args):
|
|
255
253
|
index += 1
|
|
256
254
|
env_overrides = legacy_args[index]
|
|
257
|
-
elif arg == "--mode" and index + 1 < len(legacy_args):
|
|
258
|
-
index += 1
|
|
259
|
-
mode = legacy_args[index]
|
|
260
|
-
if mode not in {"lite", "standard", "full"}:
|
|
261
|
-
raise ValueError(f"Invalid mode: {mode} (must be lite, standard, or full)")
|
|
262
255
|
elif arg == "--features" and index + 1 < len(legacy_args):
|
|
263
256
|
index += 1
|
|
264
257
|
features_filter = legacy_args[index]
|
|
@@ -269,7 +262,7 @@ def _parse_start_args(family: RunnerFamily, legacy_args: tuple[str, ...]) -> Dae
|
|
|
269
262
|
index += 1
|
|
270
263
|
if positional:
|
|
271
264
|
list_path = Path(positional[0]).expanduser()
|
|
272
|
-
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)
|
|
273
266
|
|
|
274
267
|
|
|
275
268
|
def _parse_log_args(legacy_args: tuple[str, ...]) -> DaemonLogOptions:
|
|
@@ -304,8 +297,6 @@ def _payload_command(family: RunnerFamily, paths, list_path: Path, options: Daem
|
|
|
304
297
|
]
|
|
305
298
|
if family.kind == "feature" and options.features_filter:
|
|
306
299
|
command.extend(["--features", options.features_filter])
|
|
307
|
-
if options.mode:
|
|
308
|
-
command.extend(["--mode", options.mode])
|
|
309
300
|
return command
|
|
310
301
|
|
|
311
302
|
|
|
@@ -316,8 +307,6 @@ def _daemon_env(options: DaemonStartOptions) -> dict[str, str]:
|
|
|
316
307
|
key, value = token.split("=", 1)
|
|
317
308
|
if key:
|
|
318
309
|
env[key] = value
|
|
319
|
-
if options.mode:
|
|
320
|
-
env["PIPELINE_MODE"] = options.mode
|
|
321
310
|
return env
|
|
322
311
|
|
|
323
312
|
|
|
@@ -348,7 +337,6 @@ def _write_meta(family: RunnerFamily, path: Path, pid: int, started_at: str, lis
|
|
|
348
337
|
"started_at": started_at,
|
|
349
338
|
LIST_META_KEY_BY_KIND[family.kind]: str(list_path),
|
|
350
339
|
"env_overrides": options.env_overrides,
|
|
351
|
-
"mode": options.mode,
|
|
352
340
|
"log_file": str(log_file),
|
|
353
341
|
}
|
|
354
342
|
tmp = path.with_suffix(path.suffix + ".tmp")
|
|
@@ -405,8 +393,6 @@ def _write_log_separator(family: RunnerFamily, log_file: Path, list_path: Path,
|
|
|
405
393
|
]
|
|
406
394
|
if options.features_filter:
|
|
407
395
|
lines.append(f" Features filter: {options.features_filter}")
|
|
408
|
-
if options.mode:
|
|
409
|
-
lines.append(f" Mode: {options.mode}")
|
|
410
396
|
if options.env_overrides:
|
|
411
397
|
lines.append(f" Environment: {options.env_overrides}")
|
|
412
398
|
lines.extend(["================================================================", ""])
|