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
|
@@ -46,7 +46,7 @@ Accept:
|
|
|
46
46
|
|
|
47
47
|
- `description`: the natural-language formal requirement;
|
|
48
48
|
- `artifact_dir`: optional explicit requirement artifact root;
|
|
49
|
-
- `execution_mode`: `interactive
|
|
49
|
+
- `execution_mode`: `interactive`; external headless automation must invoke atomic stages directly and use its Python runtime for commit execution;
|
|
50
50
|
- `resume`: optional workflow state path or requirement slug for recovery.
|
|
51
51
|
|
|
52
52
|
If `description` is missing and no resumable workflow is supplied, ask for the requirement before invoking `prizmkit-plan`. External automation must invoke atomic stages directly with its own execution checkpoint rather than nesting this composite workflow.
|
|
@@ -57,11 +57,11 @@ If `description` is missing and no resumable workflow is supplied, ask for the r
|
|
|
57
57
|
|
|
58
58
|
Invoke `/prizmkit-plan` with the requirement and any explicit `artifact_dir`. Do not write a second plan in this orchestrator.
|
|
59
59
|
|
|
60
|
-
If initialization context is missing,
|
|
60
|
+
If initialization context is missing, let `prizmkit-plan` use its source fallback. Initialization is not a hidden lifecycle stage.
|
|
61
61
|
|
|
62
62
|
### 2. Preserve Requirement Identity
|
|
63
63
|
|
|
64
|
-
Once `prizmkit-plan` resolves an `artifact_dir`, capture it and pass the exact same value to every later stage. The artifact root is generic and is not restricted to one directory family:
|
|
64
|
+
Once `prizmkit-plan` resolves an `artifact_dir`, capture it and pass the exact same value to every later stage. Read `${SKILL_DIR}/references/artifact-identity.md` before deriving or opening workflow state. The artifact root is generic and is not restricted to one directory family:
|
|
65
65
|
|
|
66
66
|
```text
|
|
67
67
|
.prizmkit/specs/<requirement-slug>/
|
|
@@ -69,35 +69,38 @@ Once `prizmkit-plan` resolves an `artifact_dir`, capture it and pass the exact s
|
|
|
69
69
|
.prizmkit/refactor/<refactor-id>/
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
-
Never select a different most-recent plan when resuming or handing off.
|
|
72
|
+
Never select a different most-recent plan when resuming or handing off. Derive the workflow state path from the exact artifact-directory basename, validate its safe identity, and fail closed if an existing state path belongs to another artifact:
|
|
73
73
|
|
|
74
74
|
```text
|
|
75
|
-
.prizmkit/state/workflows/<requirement-
|
|
75
|
+
.prizmkit/state/workflows/<requirement-identity>.json
|
|
76
76
|
```
|
|
77
77
|
|
|
78
|
-
Read `${SKILL_DIR}/references/workflow-state-protocol.md` for the shared state contract. This workflow state remains distinct from any external host execution checkpoint. The target project controls whether generated `.prizmkit/` files are committed, ignored, or shared; do not modify its Git policy.
|
|
78
|
+
Read `${SKILL_DIR}/references/artifact-identity.md` for path/collision rules and `${SKILL_DIR}/references/workflow-state-protocol.md` for the shared state content contract. This workflow state remains distinct from any external host execution checkpoint. The target project controls whether generated `.prizmkit/` files are committed, ignored, or shared; do not modify its Git policy.
|
|
79
79
|
|
|
80
80
|
### 3. Advance Only on Truthful Success
|
|
81
81
|
|
|
82
82
|
After each atomic stage:
|
|
83
83
|
|
|
84
|
-
1. Read the stage
|
|
85
|
-
2. Validate
|
|
86
|
-
3.
|
|
87
|
-
4.
|
|
88
|
-
5.
|
|
89
|
-
6.
|
|
84
|
+
1. Read the stage-local result and stage-owned artifacts.
|
|
85
|
+
2. Validate those artifacts independently.
|
|
86
|
+
3. Map the domain result to this composite's lifecycle status and update workflow state itself.
|
|
87
|
+
4. Preserve the same `artifact_dir`.
|
|
88
|
+
5. Continue only on the permitted success result.
|
|
89
|
+
6. Supply explicit stage-local inputs to the next invocation; atomic Skills never read this composite's state or choose routing.
|
|
90
|
+
7. If the host cannot invoke another Skill automatically, stop with one deterministic next invocation and caller-owned state path.
|
|
90
91
|
|
|
91
92
|
Expected transitions:
|
|
92
93
|
|
|
93
94
|
| Stage | Required success | Next stage |
|
|
94
95
|
|---|---|---|
|
|
95
|
-
| `prizmkit-plan` | `
|
|
96
|
-
| `prizmkit-implement` | `
|
|
97
|
-
| `prizmkit-code-review` | `
|
|
98
|
-
| `prizmkit-test` | `
|
|
99
|
-
| `prizmkit-retrospective` | `
|
|
100
|
-
| `prizmkit-committer` | explicit interactive confirmation
|
|
96
|
+
| `prizmkit-plan` | `PLAN_READY` plus valid `spec.md`/`plan.md` | `prizmkit-implement` |
|
|
97
|
+
| `prizmkit-implement` | `IMPLEMENTED` plus completed task markers | `prizmkit-code-review` |
|
|
98
|
+
| `prizmkit-code-review` | `PASS` plus valid `review-report.md` | `prizmkit-test` |
|
|
99
|
+
| `prizmkit-test` | `TEST_PASS` plus consistent report/result pair | `prizmkit-retrospective` |
|
|
100
|
+
| `prizmkit-retrospective` | `RETRO_COMPLETE` plus an artifact whose `outcome` and `result` agree | `prizmkit-committer` |
|
|
101
|
+
| `prizmkit-committer` | `COMMITTED` after explicit interactive confirmation | end |
|
|
102
|
+
|
|
103
|
+
Before invoking `prizmkit-retrospective`, derive the exact changed project paths outside `.prizmkit/` and pass them as `change_paths` with a concise `change_summary`. Do not ask that atomic Skill to infer scope from this composite's state or earlier artifacts.
|
|
101
104
|
|
|
102
105
|
`TEST_NOT_APPLICABLE` is not a valid lifecycle success. Lightweight changes must execute deterministic verification and return `TEST_PASS`.
|
|
103
106
|
|
|
@@ -106,16 +109,16 @@ Expected transitions:
|
|
|
106
109
|
The composite must not:
|
|
107
110
|
|
|
108
111
|
- reinterpret a plan as implementation;
|
|
109
|
-
- repair production code
|
|
112
|
+
- repair production code itself instead of invoking the appropriate atomic stage with explicit repair input;
|
|
110
113
|
- claim tests passed without a consistent `test-report.md` and terminal `test-result.json`;
|
|
111
114
|
- reinterpret testing-domain results as runtime/session outcomes;
|
|
112
115
|
- perform retrospective documentation changes itself;
|
|
113
|
-
- stage or commit before `prizmkit-committer`
|
|
116
|
+
- stage or commit before `prizmkit-committer` completes the interactive preview and confirmation boundary;
|
|
114
117
|
- invoke `prizmkit-deploy` as a hidden seventh stage.
|
|
115
118
|
|
|
116
119
|
## Failure and Repair Routing
|
|
117
120
|
|
|
118
|
-
Use
|
|
121
|
+
Use caller-owned workflow state and authoritative stage artifacts to determine routing. Atomic Skills never own this decision.
|
|
119
122
|
|
|
120
123
|
### Review Failure
|
|
121
124
|
|
|
@@ -136,15 +139,16 @@ The Main-Agent review skill owns its internal review repairs and its internal te
|
|
|
136
139
|
```text
|
|
137
140
|
TEST_NEEDS_FIXES
|
|
138
141
|
→ preserve test-report.md and test-result.json
|
|
139
|
-
→
|
|
140
|
-
→
|
|
142
|
+
→ when the outer repair budget remains, supply the exact correction to prizmkit-implement
|
|
143
|
+
→ require fresh prizmkit-code-review and prizmkit-test results
|
|
144
|
+
→ otherwise stop with WORKFLOW_BLOCKED
|
|
141
145
|
|
|
142
146
|
TEST_BLOCKED
|
|
143
147
|
→ preserve test-report.md and test-result.json
|
|
144
148
|
→ stop with the unresolved truth, input, safety, environment, or reliability blocker
|
|
145
149
|
```
|
|
146
150
|
|
|
147
|
-
The composite
|
|
151
|
+
The composite's bounded outer repair policy owns that fresh invocation route; it does not recreate the testing-local repair loop. It must never treat either non-pass result as an AI CLI crash.
|
|
148
152
|
|
|
149
153
|
### Environment Block
|
|
150
154
|
|
|
@@ -159,7 +163,7 @@ TEST_BLOCKED
|
|
|
159
163
|
→ stop with a deterministic prizmkit-test resume entry
|
|
160
164
|
```
|
|
161
165
|
|
|
162
|
-
|
|
166
|
+
An external headless runtime may perform its own bounded environment recovery when invoking atomic stages. It does not invoke this interactive composite workflow or silently turn a blocked result into success.
|
|
163
167
|
|
|
164
168
|
### Repair Limit
|
|
165
169
|
|
|
@@ -179,19 +183,13 @@ When the limit is reached:
|
|
|
179
183
|
|
|
180
184
|
The internal `prizmkit-code-review` limit of ten completed review rounds remains separate and does not increment `repair_round`.
|
|
181
185
|
|
|
182
|
-
## Commit
|
|
183
|
-
|
|
184
|
-
The composite may automatically reach `/prizmkit-committer`, but it must not silently create a Git commit.
|
|
186
|
+
## Interactive Commit Boundary
|
|
185
187
|
|
|
186
|
-
|
|
188
|
+
The composite reaches `/prizmkit-committer operation=interactive-commit` but must not silently create a Git commit.
|
|
187
189
|
|
|
188
|
-
|
|
189
|
-
2. inspect the final workspace;
|
|
190
|
-
3. present intended files, diff summary, sensitive-file warnings, and the proposed Conventional Commit message;
|
|
191
|
-
4. wait for explicit user confirmation from the current user;
|
|
192
|
-
5. create and verify the local commit only after confirmation.
|
|
190
|
+
The composite must validate all prior stage artifacts, derive exact non-`.prizmkit/` change paths for the retrospective input, and validate its result. It then invokes the committer with the same `artifact_dir`, exact `evidence_paths`, caller-state paths in `excluded_paths`, and `operation=interactive-commit`. The committer inspects the supplied final change, presents the exact commit, waits for confirmation, and creates it only after approval.
|
|
193
191
|
|
|
194
|
-
|
|
192
|
+
External headless orchestration supplies explicit evidence to `operation=prepare-runtime-commit`, maps `COMMIT_REQUEST_READY` to its own pending state, and lets Python Runtime validate and execute the request. Remote publication remains separate.
|
|
195
193
|
|
|
196
194
|
## Automatic Handoff and Manual Fallback
|
|
197
195
|
|
|
@@ -206,7 +204,7 @@ When it does not:
|
|
|
206
204
|
```text
|
|
207
205
|
Next stage: /prizmkit-<skill>
|
|
208
206
|
artifact_dir: <same resolved artifact_dir>
|
|
209
|
-
workflow_state: .prizmkit/state/workflows/<requirement-
|
|
207
|
+
workflow_state: .prizmkit/state/workflows/<requirement-identity>.json
|
|
210
208
|
```
|
|
211
209
|
|
|
212
210
|
The user can invoke that one atomic skill and this composite can resume with `resume` later.
|
|
@@ -242,7 +240,7 @@ push: not performed automatically
|
|
|
242
240
|
next_action: invoke /prizmkit-deploy separately if deployment is needed
|
|
243
241
|
```
|
|
244
242
|
|
|
245
|
-
If the user declines interactive commit confirmation,
|
|
243
|
+
If the user declines interactive commit confirmation, preserve the committer stage as pending or in progress without a workflow `stage_result`, report the atomic operation result `COMMIT_DECLINED`, and provide the exact `/prizmkit-committer operation=interactive-commit` resume entry. `COMMIT_PENDING` is reserved for a validated Runtime commit request and must not represent an interactive decline.
|
|
246
244
|
|
|
247
245
|
If blocked, report:
|
|
248
246
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Interactive Workflow Artifact Identity
|
|
2
|
+
|
|
3
|
+
The interactive workflow derives state identity from the exact caller/planning artifact directory; it never generates a second slug.
|
|
4
|
+
|
|
5
|
+
## Derivation
|
|
6
|
+
|
|
7
|
+
1. Resolve `artifact_dir` as a project-relative path inside the active checkout.
|
|
8
|
+
2. Take its final path component unchanged as `<requirement-identity>`.
|
|
9
|
+
3. Require 1-96 Unicode code points and at most 200 UTF-8 bytes, containing only letters, decimal digits, ASCII hyphens, or ASCII underscores, with a letter or digit at both ends. Reject control characters, separators, `.`/`..`, symlink escape, and empty identity. The byte limit leaves portable filename space for the `.json` suffix.
|
|
10
|
+
4. Use exactly:
|
|
11
|
+
|
|
12
|
+
```text
|
|
13
|
+
.prizmkit/state/workflows/<requirement-identity>.json
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Examples:
|
|
17
|
+
|
|
18
|
+
```text
|
|
19
|
+
.prizmkit/specs/070-skill-generated-artifact-contracts/
|
|
20
|
+
→ .prizmkit/state/workflows/070-skill-generated-artifact-contracts.json
|
|
21
|
+
|
|
22
|
+
.prizmkit/bugfix/B-001/
|
|
23
|
+
→ .prizmkit/state/workflows/B-001.json
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Collision and Resume Safety
|
|
27
|
+
|
|
28
|
+
- Store the exact normalized project-relative `artifact_dir` in state.
|
|
29
|
+
- Before creating state, if the target file already exists, read it and require its `artifact_dir` to equal the active artifact directory exactly.
|
|
30
|
+
- A state file naming collision with a different artifact directory is blocking. Do not overwrite, merge, suffix, or silently select a recent state; require the caller to resolve the conflicting record explicitly.
|
|
31
|
+
- When `resume` supplies a state path, require it to equal the derived path, remain under `.prizmkit/state/workflows/`, and point to the exact artifact directory recorded inside it.
|
|
32
|
+
- Continue using the same state path and artifact directory for every stage and repair round.
|
|
33
|
+
|
|
34
|
+
External checkpoints use their own identity and are never derived from or merged into this path.
|
|
@@ -4,11 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
## Location and Identity
|
|
6
6
|
|
|
7
|
+
Derive the path through `${SKILL_DIR}/references/artifact-identity.md`:
|
|
8
|
+
|
|
7
9
|
```text
|
|
8
|
-
.prizmkit/state/workflows/<requirement-
|
|
10
|
+
.prizmkit/state/workflows/<requirement-identity>.json
|
|
9
11
|
```
|
|
10
12
|
|
|
11
|
-
The active `artifact_dir` is preserved exactly across every stage:
|
|
13
|
+
The identity is the validated artifact-directory basename. An existing state file for a different `artifact_dir` is a blocking collision and is never overwritten or suffixed automatically. The active `artifact_dir` is preserved exactly across every stage:
|
|
12
14
|
|
|
13
15
|
```text
|
|
14
16
|
.prizmkit/specs/<requirement-slug>/
|
|
@@ -31,7 +33,7 @@ The state file is an index, not the authority for stage completion:
|
|
|
31
33
|
| Terminal testing result | `{artifact_dir}/test-result.json` |
|
|
32
34
|
| Retrospective completion | `{artifact_dir}/retrospective-result.json` |
|
|
33
35
|
| Durable architecture knowledge | `.prizmkit/prizm-docs/` |
|
|
34
|
-
| Local commit | Git history and
|
|
36
|
+
| Local commit | Git history and runtime- or user-verified commit identity |
|
|
35
37
|
| Current stage, orchestrator, and resume entry | Workflow state |
|
|
36
38
|
| External orchestration progress | External host checkpoint |
|
|
37
39
|
|
|
@@ -64,7 +66,7 @@ Every consumer compares workflow state with the skill-owned artifacts and curren
|
|
|
64
66
|
| `orchestrator` | Semantic coordinator identifier, or null for direct stage use. |
|
|
65
67
|
| `stage` | Stage that most recently wrote state. |
|
|
66
68
|
| `status` | Lifecycle status: `pending`, `in_progress`, `completed`, `failed`, or `skipped`. |
|
|
67
|
-
| `stage_result` |
|
|
69
|
+
| `stage_result` | Coordinator-recorded lifecycle result mapped from a validated atomic result and its required artifacts, such as `PLAN_READY`, `IMPLEMENTED`, `REVIEW_PASS`, `REVIEW_NEEDS_FIXES`, `TEST_*`, `RETRO_COMPLETE`, or `COMMITTED`. |
|
|
68
70
|
| `completed_stages` | Ordered stages completed for this requirement. |
|
|
69
71
|
| `repair_scope` | Optional caller-owned routing scope. The test skill reports high-risk repairs through `test-result.json` instead of scheduling another stage. |
|
|
70
72
|
| `repair_round` | Optional outer cross-stage repair round, from 0 through 3. It is not a test-internal repair counter. |
|
|
@@ -97,10 +99,10 @@ review-report NEEDS_FIXES → status=failed, stage_result=REVIEW_NEED
|
|
|
97
99
|
test-result TEST_PASS → status=completed, stage_result=TEST_PASS
|
|
98
100
|
test-result TEST_NEEDS_FIXES → status=failed, stage_result=TEST_NEEDS_FIXES
|
|
99
101
|
test-result TEST_BLOCKED → status=failed, stage_result=TEST_BLOCKED
|
|
100
|
-
retrospective DOCS_UPDATED
|
|
101
|
-
retrospective NO_DOC_CHANGE
|
|
102
|
-
retrospective
|
|
103
|
-
commit
|
|
102
|
+
retrospective outcome=RETRO_COMPLETE, result=DOCS_UPDATED → status=completed, stage_result=RETRO_COMPLETE
|
|
103
|
+
retrospective outcome=RETRO_COMPLETE, result=NO_DOC_CHANGE → status=completed, stage_result=RETRO_COMPLETE
|
|
104
|
+
retrospective outcome=RETRO_BLOCKED → status=failed, stage_result=RETRO_BLOCKED
|
|
105
|
+
runtime commit preparation → status=in_progress, stage_result=COMMIT_PENDING
|
|
104
106
|
local commit confirmed → status=completed, stage_result=COMMITTED
|
|
105
107
|
commit blocked → status=failed, stage_result=COMMIT_BLOCKED
|
|
106
108
|
```
|
|
@@ -115,8 +117,8 @@ commit blocked → status=failed, stage_result=COMMIT_BLOC
|
|
|
115
117
|
|
|
116
118
|
```text
|
|
117
119
|
TEST_NEEDS_FIXES
|
|
118
|
-
→ known correction
|
|
119
|
-
→ caller decides whether and how to arrange another
|
|
120
|
+
→ a known correction remains
|
|
121
|
+
→ caller decides whether and how to arrange another invocation
|
|
120
122
|
|
|
121
123
|
TEST_BLOCKED
|
|
122
124
|
→ truth, input, safe environment, or reliable execution prevents a verdict
|
|
@@ -132,30 +134,32 @@ Any outer repair or continuation policy is independently owned by the caller and
|
|
|
132
134
|
|
|
133
135
|
1. An atomic stage performs only its own stage, writes its truthful result and artifact paths, and returns control.
|
|
134
136
|
2. When `orchestrator` is non-null, only that orchestrator invokes the next skill.
|
|
135
|
-
3. Direct
|
|
137
|
+
3. Direct atomic use returns only its local result and artifacts; it does not report or select another invocation.
|
|
136
138
|
4. Every handoff preserves the same `artifact_dir`.
|
|
137
139
|
5. External automation invokes atomic stages directly and does not nest the composite workflow.
|
|
138
140
|
6. Workflow state never replaces or absorbs an external host checkpoint.
|
|
139
141
|
|
|
140
|
-
## Commit
|
|
142
|
+
## Commit Execution Ownership
|
|
141
143
|
|
|
142
144
|
Interactive execution:
|
|
143
145
|
|
|
144
146
|
```text
|
|
145
147
|
committer previews intended files and message
|
|
146
148
|
→ waits for explicit current-user confirmation
|
|
147
|
-
→ creates the local commit
|
|
149
|
+
→ stages, creates, and verifies the local commit
|
|
148
150
|
```
|
|
149
151
|
|
|
150
|
-
|
|
152
|
+
Pipeline execution:
|
|
151
153
|
|
|
152
154
|
```text
|
|
153
|
-
|
|
154
|
-
→ committer
|
|
155
|
+
external coordinator validates its required gates and supplies exact readiness evidence
|
|
156
|
+
→ committer validates only that evidence and writes an exact runtime-commit-request.json
|
|
157
|
+
→ external coordinator maps COMMIT_REQUEST_READY to its checkpoint's in_progress/COMMIT_PENDING state
|
|
158
|
+
→ Python runtime validates the request, commits, verifies Git, and writes checkpoint completed/COMMITTED
|
|
155
159
|
→ remote publication remains separate
|
|
156
160
|
```
|
|
157
161
|
|
|
158
|
-
|
|
162
|
+
The preparation request is data for runtime validation, not prompt-level authorization. The committer must not stage, commit, or predeclare COMMITTED in pipeline preparation mode.
|
|
159
163
|
|
|
160
164
|
## Recovery
|
|
161
165
|
|
|
@@ -171,4 +175,4 @@ When state is missing, stale, or inconsistent:
|
|
|
171
175
|
8. Reconstruct the latest safe predecessor and report the reconstruction.
|
|
172
176
|
9. Continue only from the first incomplete or invalid stage.
|
|
173
177
|
|
|
174
|
-
Stale state never bypasses review, testing, retrospective, commit
|
|
178
|
+
Stale state never bypasses review, testing, retrospective, commit preparation/execution, or external checkpoint enforcement.
|
|
@@ -42,7 +42,8 @@ The detector reads only active checkout records:
|
|
|
42
42
|
|
|
43
43
|
A candidate is resumable only when:
|
|
44
44
|
- `state` is `active`;
|
|
45
|
-
- `
|
|
45
|
+
- `task_type` equals the checkout directory family;
|
|
46
|
+
- `task_id` is explicitly recorded, matches the exact `F-NNN`, `B-NNN`, or `R-NNN` family form, and equals its parent state-directory name;
|
|
46
47
|
- `active_dev_branch` is present; and
|
|
47
48
|
- the recorded local branch still exists.
|
|
48
49
|
|
|
@@ -13,9 +13,10 @@ Recovery uses the runtime's durable task checkout identity rather than reconstru
|
|
|
13
13
|
A record is resumable only when:
|
|
14
14
|
|
|
15
15
|
1. `state` equals `active`.
|
|
16
|
-
2. `
|
|
17
|
-
3. `
|
|
18
|
-
4. `
|
|
16
|
+
2. `task_type` equals the checkout directory family.
|
|
17
|
+
3. `task_id` is explicitly present, matches the exact `F-NNN`, `B-NNN`, or `R-NNN` family form, and equals its parent state-directory name.
|
|
18
|
+
4. `active_dev_branch` is non-empty.
|
|
19
|
+
5. `refs/heads/<active_dev_branch>` exists locally.
|
|
19
20
|
|
|
20
21
|
Ignore records whose state is `completed` or `reset`. Also ignore session logs, plan lists, artifact directories, and checkpoint files when no active checkout record exists. Those files may remain after completed or historical work and are not evidence of an interrupted task.
|
|
21
22
|
|
|
@@ -5,6 +5,7 @@ from __future__ import annotations
|
|
|
5
5
|
|
|
6
6
|
import argparse
|
|
7
7
|
import json
|
|
8
|
+
import re
|
|
8
9
|
import subprocess
|
|
9
10
|
from pathlib import Path
|
|
10
11
|
|
|
@@ -14,19 +15,19 @@ FAMILIES = (
|
|
|
14
15
|
"name": "feature",
|
|
15
16
|
"state_dir": "features",
|
|
16
17
|
"plan_path": ".prizmkit/plans/feature-list.json",
|
|
17
|
-
"
|
|
18
|
+
"id_pattern": r"^F-\d{3}$",
|
|
18
19
|
},
|
|
19
20
|
{
|
|
20
21
|
"name": "bugfix",
|
|
21
22
|
"state_dir": "bugfix",
|
|
22
23
|
"plan_path": ".prizmkit/plans/bug-fix-list.json",
|
|
23
|
-
"
|
|
24
|
+
"id_pattern": r"^B-\d{3}$",
|
|
24
25
|
},
|
|
25
26
|
{
|
|
26
27
|
"name": "refactor",
|
|
27
28
|
"state_dir": "refactor",
|
|
28
29
|
"plan_path": ".prizmkit/plans/refactor-list.json",
|
|
29
|
-
"
|
|
30
|
+
"id_pattern": r"^R-\d{3}$",
|
|
30
31
|
},
|
|
31
32
|
)
|
|
32
33
|
|
|
@@ -83,9 +84,18 @@ def detect_candidates(project_root: Path) -> list[dict[str, object]]:
|
|
|
83
84
|
data = load_json(checkout_path)
|
|
84
85
|
if not data or str(data.get("state") or "") != "active":
|
|
85
86
|
continue
|
|
86
|
-
|
|
87
|
+
raw_task_id = data.get("task_id")
|
|
88
|
+
if not isinstance(raw_task_id, str):
|
|
89
|
+
continue
|
|
90
|
+
task_id = raw_task_id.strip()
|
|
87
91
|
branch = str(data.get("active_dev_branch") or "").strip()
|
|
88
|
-
if
|
|
92
|
+
if (
|
|
93
|
+
task_id != raw_task_id
|
|
94
|
+
or data.get("task_type") != family["name"]
|
|
95
|
+
or checkout_path.parent.name != task_id
|
|
96
|
+
or re.fullmatch(family["id_pattern"], task_id) is None
|
|
97
|
+
or not branch_exists(project_root, branch)
|
|
98
|
+
):
|
|
89
99
|
continue
|
|
90
100
|
candidates.append(
|
|
91
101
|
{
|
|
@@ -6,6 +6,8 @@ from __future__ import annotations
|
|
|
6
6
|
import re
|
|
7
7
|
import subprocess
|
|
8
8
|
import sys
|
|
9
|
+
from dataclasses import dataclass
|
|
10
|
+
from functools import cmp_to_key
|
|
9
11
|
from pathlib import Path, PurePosixPath
|
|
10
12
|
|
|
11
13
|
DOCS_ROOT = Path(".prizmkit/prizm-docs")
|
|
@@ -124,24 +126,129 @@ def read_check_content(file_path: str, mode: str) -> tuple[bytes, str] | None:
|
|
|
124
126
|
return raw, raw.decode("utf-8", errors="replace")
|
|
125
127
|
|
|
126
128
|
|
|
129
|
+
@dataclass(frozen=True)
|
|
130
|
+
class CapacityDiagnostic:
|
|
131
|
+
file_path: str
|
|
132
|
+
level: str
|
|
133
|
+
size: int
|
|
134
|
+
limit: int
|
|
135
|
+
band: str
|
|
136
|
+
target_low: int
|
|
137
|
+
target_high: int
|
|
138
|
+
actions: str
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def is_root_doc(file_path: str) -> bool:
|
|
142
|
+
return PurePosixPath(file_path) == PurePosixPath(ROOT_PRIZM.as_posix())
|
|
143
|
+
|
|
144
|
+
|
|
127
145
|
def is_l1_doc(file_path: str) -> bool:
|
|
128
146
|
parent = PurePosixPath(file_path).parent.as_posix()
|
|
129
147
|
return parent == DOCS_ROOT.as_posix()
|
|
130
148
|
|
|
131
149
|
|
|
132
150
|
def size_limit(file_path: str) -> tuple[int, str, str]:
|
|
133
|
-
if file_path
|
|
134
|
-
return
|
|
151
|
+
if is_root_doc(file_path):
|
|
152
|
+
return (
|
|
153
|
+
4096,
|
|
154
|
+
"L0",
|
|
155
|
+
"trim: lower-priority global wording; "
|
|
156
|
+
"deduplicate: repeated RULES or module summaries; "
|
|
157
|
+
"move-to-child: module detail into an L1 document; "
|
|
158
|
+
"semantic-split: broad module groups into focused L1 documents",
|
|
159
|
+
)
|
|
135
160
|
if is_l1_doc(file_path):
|
|
136
|
-
return
|
|
137
|
-
|
|
161
|
+
return (
|
|
162
|
+
4096,
|
|
163
|
+
"L1",
|
|
164
|
+
"trim: low-value module summaries; "
|
|
165
|
+
"deduplicate: repeated interfaces, rules, or traps; "
|
|
166
|
+
"move-to-child: implementation detail into an L2 document; "
|
|
167
|
+
"semantic-split: distinct submodules into focused L2 documents",
|
|
168
|
+
)
|
|
169
|
+
return (
|
|
170
|
+
5120,
|
|
171
|
+
"L2",
|
|
172
|
+
"trim: stale or derivable detail; "
|
|
173
|
+
"deduplicate: repeated implementation notes; "
|
|
174
|
+
"move-to-child: one coherent detail set into a focused child document; "
|
|
175
|
+
"semantic-split: unrelated responsibilities into focused L2 documents",
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def ceil_percent(limit: int, percent: int) -> int:
|
|
180
|
+
return (limit * percent + 99) // 100
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def capacity_band(size: int, limit: int) -> str:
|
|
184
|
+
if size > limit:
|
|
185
|
+
return "error"
|
|
186
|
+
if size * 100 >= limit * 90:
|
|
187
|
+
return "strong-warning"
|
|
188
|
+
if size * 100 >= limit * 80:
|
|
189
|
+
return "warning"
|
|
190
|
+
return "normal"
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def capacity_diagnostic(file_path: str, size: int) -> CapacityDiagnostic | None:
|
|
194
|
+
limit, level, actions = size_limit(file_path)
|
|
195
|
+
band = capacity_band(size, limit)
|
|
196
|
+
if band == "normal":
|
|
197
|
+
return None
|
|
198
|
+
return CapacityDiagnostic(
|
|
199
|
+
file_path=file_path,
|
|
200
|
+
level=level,
|
|
201
|
+
size=size,
|
|
202
|
+
limit=limit,
|
|
203
|
+
band=band,
|
|
204
|
+
target_low=ceil_percent(limit, 80),
|
|
205
|
+
target_high=ceil_percent(limit, 90) - 1,
|
|
206
|
+
actions=actions,
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def compare_capacity(left: CapacityDiagnostic, right: CapacityDiagnostic) -> int:
|
|
211
|
+
left_ratio = left.size * right.limit
|
|
212
|
+
right_ratio = right.size * left.limit
|
|
213
|
+
if left_ratio > right_ratio:
|
|
214
|
+
return -1
|
|
215
|
+
if left_ratio < right_ratio:
|
|
216
|
+
return 1
|
|
217
|
+
if left.file_path < right.file_path:
|
|
218
|
+
return -1
|
|
219
|
+
if left.file_path > right.file_path:
|
|
220
|
+
return 1
|
|
221
|
+
return 0
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def utilization_percent(size: int, limit: int) -> str:
|
|
225
|
+
hundredths = (size * 10000) // limit
|
|
226
|
+
return f"{hundredths // 100}.{hundredths % 100:02d}%"
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def emit_capacity(diagnostic: CapacityDiagnostic) -> None:
|
|
230
|
+
severity = {
|
|
231
|
+
"warning": "WARNING",
|
|
232
|
+
"strong-warning": "STRONG WARNING",
|
|
233
|
+
"error": "ERROR",
|
|
234
|
+
}[diagnostic.band]
|
|
235
|
+
print(
|
|
236
|
+
f"{severity}: {diagnostic.file_path} capacity "
|
|
237
|
+
f"level={diagnostic.level} bytes={diagnostic.size}B limit={diagnostic.limit}B "
|
|
238
|
+
f"utilization={diagnostic.size}/{diagnostic.limit} "
|
|
239
|
+
f"({utilization_percent(diagnostic.size, diagnostic.limit)}) "
|
|
240
|
+
f"band={diagnostic.band} "
|
|
241
|
+
f"target={diagnostic.target_low}-{diagnostic.target_high}B (80% to <90%) "
|
|
242
|
+
f"actions={diagnostic.actions}",
|
|
243
|
+
file=sys.stderr,
|
|
244
|
+
)
|
|
138
245
|
|
|
139
246
|
|
|
140
247
|
def contains_root_field(text: str, field: str) -> bool:
|
|
141
248
|
return re.search(rf"^{re.escape(field)}:", text, re.MULTILINE) is not None
|
|
142
249
|
|
|
143
250
|
|
|
144
|
-
def validate_file(file_path: str, raw: bytes, text: str) -> int:
|
|
251
|
+
def validate_file(file_path: str, raw: bytes, text: str) -> tuple[int, CapacityDiagnostic | None]:
|
|
145
252
|
errors = 0
|
|
146
253
|
|
|
147
254
|
if re.search(r"^#{1,6} ", text, re.MULTILINE):
|
|
@@ -195,13 +302,11 @@ def validate_file(file_path: str, raw: bytes, text: str) -> int:
|
|
|
195
302
|
emit_error(file_path, "contains branch names. Describe durable product/domain context instead.")
|
|
196
303
|
errors += 1
|
|
197
304
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
if size > limit:
|
|
201
|
-
emit_error(file_path, f"exceeds {level} limit ({size}B > {limit}B). {hint}")
|
|
305
|
+
diagnostic = capacity_diagnostic(file_path, len(raw))
|
|
306
|
+
if diagnostic is not None and diagnostic.band == "error":
|
|
202
307
|
errors += 1
|
|
203
308
|
|
|
204
|
-
if file_path
|
|
309
|
+
if is_root_doc(file_path):
|
|
205
310
|
for field in ["PRIZM_VERSION", "PROJECT", "LANG", "RULES"]:
|
|
206
311
|
if not contains_root_field(text, field):
|
|
207
312
|
emit_error(file_path, f"missing required field {field}:")
|
|
@@ -210,7 +315,7 @@ def validate_file(file_path: str, raw: bytes, text: str) -> int:
|
|
|
210
315
|
emit_error(file_path, "missing required field MODULE_INDEX: or MODULE_GROUPS:")
|
|
211
316
|
errors += 1
|
|
212
317
|
|
|
213
|
-
return errors
|
|
318
|
+
return errors, diagnostic
|
|
214
319
|
|
|
215
320
|
|
|
216
321
|
def main(argv: list[str]) -> int:
|
|
@@ -223,12 +328,19 @@ def main(argv: list[str]) -> int:
|
|
|
223
328
|
return 0
|
|
224
329
|
|
|
225
330
|
errors = 0
|
|
331
|
+
capacity_entries: list[CapacityDiagnostic] = []
|
|
226
332
|
for file_path in collect_files(mode):
|
|
227
333
|
content = read_check_content(file_path, mode)
|
|
228
334
|
if content is None:
|
|
229
335
|
continue
|
|
230
336
|
raw, text = content
|
|
231
|
-
|
|
337
|
+
file_errors, diagnostic = validate_file(file_path, raw, text)
|
|
338
|
+
errors += file_errors
|
|
339
|
+
if diagnostic is not None:
|
|
340
|
+
capacity_entries.append(diagnostic)
|
|
341
|
+
|
|
342
|
+
for diagnostic in sorted(capacity_entries, key=cmp_to_key(compare_capacity)):
|
|
343
|
+
emit_capacity(diagnostic)
|
|
232
344
|
|
|
233
345
|
if errors > 0:
|
|
234
346
|
print(f"PrizmKit: {errors} format error(s) in .prizm files. Fix before committing.", file=sys.stderr)
|