prizmkit 1.1.159 → 1.1.161
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/codebuddy/settings-adapter.js +76 -25
- package/bundled/dev-pipeline/prizmkit_runtime/gitops.py +9 -2
- package/bundled/dev-pipeline/prizmkit_runtime/heartbeat.py +9 -6
- package/bundled/dev-pipeline/prizmkit_runtime/runtime_commit.py +155 -93
- package/bundled/dev-pipeline/templates/bootstrap-prompt.md +1 -1
- package/bundled/dev-pipeline/templates/bootstrap-tier3.md +2 -2
- package/bundled/dev-pipeline/templates/bugfix-bootstrap-prompt.md +1 -1
- package/bundled/dev-pipeline/templates/refactor-bootstrap-prompt.md +1 -1
- package/bundled/dev-pipeline/templates/sections/runtime-commit-handoff.md +9 -15
- package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +9 -5
- package/bundled/dev-pipeline/tests/test_generate_bugfix_prompt.py +4 -2
- package/bundled/dev-pipeline/tests/test_generate_refactor_prompt.py +4 -2
- package/bundled/dev-pipeline/tests/test_runtime_commit.py +228 -69
- package/bundled/dev-pipeline/tests/test_unified_cli.py +182 -10
- package/bundled/rules/prizm/prizm-commit-workflow.md +14 -7
- package/bundled/rules/prizm/prizm-documentation.md +24 -65
- package/bundled/rules/prizm/prizm-progressive-loading.md +9 -8
- package/bundled/skills/_metadata.json +1 -1
- package/bundled/skills/prizmkit-code-review/SKILL.md +5 -5
- package/bundled/skills/prizmkit-code-review/references/independent-code-review.md +4 -5
- package/bundled/skills/prizmkit-code-review/references/review-report-template.md +4 -6
- package/bundled/skills/prizmkit-code-review/scripts/render_review_report.py +1 -4
- package/bundled/skills/prizmkit-committer/SKILL.md +50 -59
- package/bundled/skills/prizmkit-deploy/SKILL.md +172 -198
- package/bundled/skills/prizmkit-deploy/references/capability-contract.md +137 -0
- package/bundled/skills/prizmkit-deploy/references/deploy-record-schema.json +1053 -0
- package/bundled/skills/prizmkit-deploy/references/deployment-declaration-schema.json +291 -0
- package/bundled/skills/prizmkit-deploy/references/legacy-migration.md +90 -0
- package/bundled/skills/prizmkit-deploy/references/policy-and-execution.md +170 -0
- package/bundled/skills/prizmkit-deploy/references/real-resource-test-policy.md +73 -0
- package/bundled/skills/prizmkit-deploy/references/verification-and-recovery.md +164 -0
- package/bundled/skills/prizmkit-deploy/scripts/validate-deploy-artifact.py +371 -0
- package/bundled/skills/prizmkit-implement/SKILL.md +2 -2
- package/bundled/skills/prizmkit-init/SKILL.md +17 -17
- package/bundled/skills/prizmkit-init/references/update-supplement.md +5 -5
- package/bundled/skills/prizmkit-prizm-docs/SKILL.md +17 -11
- package/bundled/skills/prizmkit-prizm-docs/assets/prizm-docs-format.md +95 -155
- package/bundled/skills/prizmkit-prizm-docs/references/op-init.md +6 -5
- package/bundled/skills/prizmkit-prizm-docs/references/op-rebuild.md +4 -2
- package/bundled/skills/prizmkit-prizm-docs/references/op-status.md +9 -10
- package/bundled/skills/prizmkit-prizm-docs/references/op-update.md +6 -5
- package/bundled/skills/prizmkit-prizm-docs/references/op-validate.md +13 -12
- package/bundled/skills/prizmkit-retrospective/SKILL.md +3 -3
- package/bundled/skills/prizmkit-test/SKILL.md +28 -15
- package/bundled/skills/prizmkit-test/references/boundary-contract-and-test-double-guidance.md +8 -4
- package/bundled/skills/prizmkit-test/references/independent-test-review.md +7 -3
- package/bundled/skills/prizmkit-test/references/test-coverage-model.md +34 -11
- package/bundled/skills/prizmkit-test/references/test-report-template.md +33 -11
- package/bundled/skills/prizmkit-workflow/SKILL.md +4 -8
- package/bundled/skills/prizmkit-workflow/references/workflow-state-protocol.md +10 -9
- package/bundled/templates/hooks/commit-intent-status.py +9 -41
- package/bundled/templates/hooks/commit-intent.json +3 -3
- package/bundled/templates/hooks/diff-prizm-docs.py +3 -1
- package/bundled/templates/hooks/prizm-pre-commit.py +32 -6
- package/bundled/templates/hooks/run-python-hook.cjs +44 -0
- package/bundled/templates/hooks/validate-prizm-docs.py +399 -173
- package/bundled/templates/project-memory-template.md +19 -19
- package/package.json +1 -1
- package/src/clean.js +6 -7
- package/src/gitignore-template.js +8 -12
- package/src/scaffold.js +125 -71
- package/bundled/skills/prizmkit-deploy/assets/deploy-document-template.md +0 -89
- package/bundled/skills/prizmkit-deploy/references/ci-cd-workflows.md +0 -145
- package/bundled/skills/prizmkit-deploy/references/cloud-platform-deploy.md +0 -109
- package/bundled/skills/prizmkit-deploy/references/data-safety-examples.md +0 -120
- package/bundled/skills/prizmkit-deploy/references/database-setup.md +0 -65
- package/bundled/skills/prizmkit-deploy/references/deploy-config-schema.md +0 -150
- package/bundled/skills/prizmkit-deploy/references/deploy-history-schema.md +0 -78
- package/bundled/skills/prizmkit-deploy/references/deploy-metadata-schema.json +0 -49
- package/bundled/skills/prizmkit-deploy/references/deployment-modes.md +0 -50
- package/bundled/skills/prizmkit-deploy/references/direct-upload.md +0 -26
- package/bundled/skills/prizmkit-deploy/references/dns-setup.md +0 -42
- package/bundled/skills/prizmkit-deploy/references/docker-deploy.md +0 -31
- package/bundled/skills/prizmkit-deploy/references/firewall-setup.md +0 -37
- package/bundled/skills/prizmkit-deploy/references/live-validation-notes.md +0 -21
- package/bundled/skills/prizmkit-deploy/references/nginx-blue-green.md +0 -59
- package/bundled/skills/prizmkit-deploy/references/pending-input-schema.json +0 -164
- package/bundled/skills/prizmkit-deploy/references/ssh-adapter-flow.md +0 -221
- package/bundled/skills/prizmkit-deploy/references/ssh-bootstrap-flow.md +0 -49
- package/bundled/skills/prizmkit-deploy/references/ssh-execution-flow.md +0 -41
- package/bundled/skills/prizmkit-deploy/references/ssh-takeover.md +0 -20
- package/bundled/skills/prizmkit-deploy/references/ssl-setup.md +0 -56
|
@@ -5,31 +5,25 @@ The Python runtime, not the AI session, executes the pipeline's local Git commit
|
|
|
5
5
|
After Code Review, all configured verification, `TEST_PASS`, family reports/summaries, and retrospective have completed:
|
|
6
6
|
|
|
7
7
|
1. As the session orchestrator, validate every required stage artifact and result first. Atomic Skills do not perform this sequencing check.
|
|
8
|
-
2.
|
|
8
|
+
2. Re-inventory the complete final Git-visible workspace: staged, unstaged, added, deleted, renamed, copied, and non-ignored untracked content. Confirm Code Review and Test authority covers every behavior-affecting change, including correct work that predated this session or lives in framework, generated, instruction, lock, or host-support paths. If production behavior changed after those gates, re-enter them before commit preparation.
|
|
9
|
+
3. Invoke `/prizmkit-committer` with the same artifact root, exact readiness evidence, and request path:
|
|
9
10
|
|
|
10
11
|
```text
|
|
11
|
-
/prizmkit-committer operation=prepare-runtime-commit artifact_dir={{ARTIFACT_DIR}} evidence_paths=<exact validated artifact paths>
|
|
12
|
+
/prizmkit-committer operation=prepare-runtime-commit artifact_dir={{ARTIFACT_DIR}} evidence_paths=<exact validated artifact paths> request_path={{ARTIFACT_DIR}}/runtime-commit-request.json
|
|
12
13
|
```
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
- all `.prizmkit/**` paths are PrizmKit-internal and stay outside the task commit, including config, plans, Prizm docs, lifecycle Artifacts, Runtime files, and state;
|
|
16
|
-
- `AGENTS.md`, `skills-lock.json`, installed platform directories, and local platform settings are support data and stay outside the task commit;
|
|
17
|
-
- project-specific transient data must already be covered by Git ignore rules;
|
|
18
|
-
- every other Git-visible path must be justified task output and included exactly, otherwise the handoff blocks.
|
|
19
|
-
|
|
20
|
-
It then rejects sensitive/unrelated/unknown paths, generates one Conventional Commit message, and writes this request without staging or committing:
|
|
15
|
+
4. The committer validates the complete final workspace without a caller-supplied path manifest or provenance classification. Ignored paths remain local and never block or require force-add. Merge conflicts, Secrets, sensitive local content, known incorrect or incoherent changes, unverifiable content, and stale readiness evidence still block. It generates one truthful Conventional Commit message and writes this request without staging or committing:
|
|
21
16
|
|
|
22
17
|
```json
|
|
23
18
|
{
|
|
24
|
-
"schema_version":
|
|
19
|
+
"schema_version": 2,
|
|
25
20
|
"artifact_dir": "{{ARTIFACT_DIR}}",
|
|
26
21
|
"base_head": "<current HEAD commit hash>",
|
|
27
|
-
"commit_message": "<type>(<scope>): <description>"
|
|
28
|
-
"intended_paths": ["<exact project-relative changed path>"]
|
|
22
|
+
"commit_message": "<type>(<scope>): <description>"
|
|
29
23
|
}
|
|
30
24
|
```
|
|
31
25
|
|
|
32
|
-
|
|
33
|
-
|
|
26
|
+
5. Require the stage-local result `COMMIT_REQUEST_READY`. Then this injected session—not the Skill—marks `prizmkit-committer` `in_progress` with `stage_result=COMMIT_PENDING` through the checkpoint helper. Do not mark it completed or write `COMMITTED`.
|
|
27
|
+
6. Stop normal work after the valid request and checkpoint handoff exist. Do not run `git add`, `git commit`, `git commit --amend`, merge, push, or create additional task files.
|
|
34
28
|
|
|
35
|
-
The
|
|
29
|
+
The Runtime validates the pathless schema, base, complete non-ignored workspace, sensitive path safeguards, merge state, and causal bookkeeping boundary. It stages the complete workspace, omitting only the exact active request/checkpoint whose final receipt cannot truthfully precede the commit; verifies a non-empty commit with the expected parent and message; records its Git receipt; and only then finalizes `COMMITTED` and performs configured integration. A malformed, stale, unsafe, incomplete, or contradictory handoff blocks without deleting user data.
|
|
@@ -1381,6 +1381,9 @@ class TestHeadlessPromptCleanupF033:
|
|
|
1381
1381
|
assert artifact in prompt
|
|
1382
1382
|
assert "Atomic Skills write only their stage-owned artifacts and domain results" in prompt
|
|
1383
1383
|
assert "COMMIT_REQUEST_READY" in prompt
|
|
1384
|
+
assert '"schema_version": 2' in prompt
|
|
1385
|
+
assert '"intended_paths"' not in prompt
|
|
1386
|
+
assert "complete final Git-visible workspace" in prompt
|
|
1384
1387
|
assert "workflow_state_path" not in prompt
|
|
1385
1388
|
assert "outcome=RETRO_COMPLETE" in prompt
|
|
1386
1389
|
assert "Never recreate the testing-local repair loop" in prompt
|
|
@@ -1554,11 +1557,12 @@ class TestFeatureBootstrapShellExtraction:
|
|
|
1554
1557
|
assert "text search . --pattern \"123-prompt-cleanup\" --json" in tier3
|
|
1555
1558
|
assert "text count .prizmkit/specs/123-prompt-cleanup/plan.md --pattern \"- [ ]\"" in tier3
|
|
1556
1559
|
assert "/prizmkit-committer operation=prepare-runtime-commit" in tier3
|
|
1557
|
-
assert "Require
|
|
1558
|
-
assert "The Python runtime
|
|
1559
|
-
assert "
|
|
1560
|
-
assert "
|
|
1561
|
-
assert "
|
|
1560
|
+
assert "Require a schema-v2 pathless request and `COMMIT_REQUEST_READY`" in tier3
|
|
1561
|
+
assert "The Python runtime re-enumerates and commits the complete non-ignored workspace" in tier3
|
|
1562
|
+
assert "validate the complete Git-visible workspace" in tier3
|
|
1563
|
+
assert "Code Review and Test authority must cover every behavior-affecting visible change" in tier3
|
|
1564
|
+
assert "Ignored paths remain naturally absent" in tier3
|
|
1565
|
+
assert "Never force-add or change/interpret project ignore policy" in tier3
|
|
1562
1566
|
assert "git add" not in tier3
|
|
1563
1567
|
assert "git commit" not in tier3
|
|
1564
1568
|
|
|
@@ -596,8 +596,10 @@ class TestBugfixCheckpointGeneration:
|
|
|
596
596
|
assert "operation=prepare-runtime-commit" in prompt
|
|
597
597
|
assert "NEVER ask for user confirmation" in prompt
|
|
598
598
|
assert "The Python runtime, not the AI session, executes" in prompt
|
|
599
|
-
assert "
|
|
600
|
-
assert "
|
|
599
|
+
assert "complete final Git-visible workspace" in prompt
|
|
600
|
+
assert '"schema_version": 2' in prompt
|
|
601
|
+
assert '"intended_paths"' not in prompt
|
|
602
|
+
assert "Ignored paths remain local" in prompt
|
|
601
603
|
assert "push_authorized\": true" not in prompt
|
|
602
604
|
assert ".prizmkit/bugfix/B-001/" in prompt
|
|
603
605
|
assert "write the session status" not in prompt.lower()
|
|
@@ -435,8 +435,10 @@ class TestRefactorCheckpointGeneration:
|
|
|
435
435
|
assert "local_commit_authorized" not in prompt
|
|
436
436
|
assert "operation=prepare-runtime-commit" in prompt
|
|
437
437
|
assert "The Python runtime, not the AI session, executes" in prompt
|
|
438
|
-
assert "
|
|
439
|
-
assert "
|
|
438
|
+
assert "complete final Git-visible workspace" in prompt
|
|
439
|
+
assert '"schema_version": 2' in prompt
|
|
440
|
+
assert '"intended_paths"' not in prompt
|
|
441
|
+
assert "Ignored paths remain local" in prompt
|
|
440
442
|
assert "automatic push" not in prompt.lower()
|
|
441
443
|
assert "push_authorized\": true" not in prompt
|
|
442
444
|
assert "write the session status" not in prompt.lower()
|
|
@@ -171,16 +171,15 @@ def _write_commit_ready_checkpoint(root: Path) -> tuple[Path, Path]:
|
|
|
171
171
|
return artifact_dir, checkpoint_path
|
|
172
172
|
|
|
173
173
|
|
|
174
|
-
def _write_request(root: Path, artifact_dir: Path, base_head: str
|
|
174
|
+
def _write_request(root: Path, artifact_dir: Path, base_head: str) -> Path:
|
|
175
175
|
request_path = artifact_dir / "runtime-commit-request.json"
|
|
176
176
|
request_path.write_text(
|
|
177
177
|
json.dumps(
|
|
178
178
|
{
|
|
179
|
-
"schema_version":
|
|
179
|
+
"schema_version": 2,
|
|
180
180
|
"artifact_dir": artifact_dir.relative_to(root).as_posix(),
|
|
181
181
|
"base_head": base_head,
|
|
182
182
|
"commit_message": "fix(runtime): finalize prepared task",
|
|
183
|
-
"intended_paths": paths,
|
|
184
183
|
}
|
|
185
184
|
),
|
|
186
185
|
encoding="utf-8",
|
|
@@ -188,7 +187,7 @@ def _write_request(root: Path, artifact_dir: Path, base_head: str, paths: list[s
|
|
|
188
187
|
return request_path
|
|
189
188
|
|
|
190
189
|
|
|
191
|
-
def
|
|
190
|
+
def test_runtime_commit_executes_complete_workspace_and_finalizes_only_checkpoint(tmp_path):
|
|
192
191
|
base_head = _init_repo(tmp_path)
|
|
193
192
|
artifact_dir, checkpoint_path = _write_commit_ready_checkpoint(tmp_path)
|
|
194
193
|
caller_state = tmp_path / ".prizmkit" / "state" / "workflows" / "caller.json"
|
|
@@ -196,7 +195,7 @@ def test_runtime_commit_executes_exact_request_and_finalizes_only_checkpoint(tmp
|
|
|
196
195
|
caller_state.write_text('{"owner":"external-coordinator"}\n', encoding="utf-8")
|
|
197
196
|
expected_caller_state = caller_state.read_bytes()
|
|
198
197
|
(tmp_path / "tracked.txt").write_text("after\n", encoding="utf-8")
|
|
199
|
-
_write_request(tmp_path, artifact_dir, base_head
|
|
198
|
+
_write_request(tmp_path, artifact_dir, base_head)
|
|
200
199
|
|
|
201
200
|
result = finalize_runtime_commit(
|
|
202
201
|
tmp_path,
|
|
@@ -229,18 +228,18 @@ def test_runtime_commit_executes_exact_request_and_finalizes_only_checkpoint(tmp
|
|
|
229
228
|
".prizmkit/prizm-docs/src/counter.prizm",
|
|
230
229
|
],
|
|
231
230
|
)
|
|
232
|
-
def
|
|
231
|
+
def test_runtime_commit_includes_tracked_prizmkit_path_from_workspace(tmp_path, durable_path):
|
|
233
232
|
_init_repo(tmp_path)
|
|
234
233
|
durable = tmp_path / durable_path
|
|
235
234
|
durable.parent.mkdir(parents=True, exist_ok=True)
|
|
236
235
|
durable.write_text("before\n", encoding="utf-8")
|
|
237
236
|
_git(tmp_path, "add", "-f", durable_path)
|
|
238
|
-
_git(tmp_path, "commit", "-m", "track
|
|
237
|
+
_git(tmp_path, "commit", "-m", "track project-selected PrizmKit data")
|
|
239
238
|
base_head = _git(tmp_path, "rev-parse", "HEAD")
|
|
240
239
|
artifact_dir, checkpoint_path = _write_commit_ready_checkpoint(tmp_path)
|
|
241
240
|
(tmp_path / "tracked.txt").write_text("after\n", encoding="utf-8")
|
|
242
241
|
durable.write_text("after\n", encoding="utf-8")
|
|
243
|
-
_write_request(tmp_path, artifact_dir, base_head
|
|
242
|
+
_write_request(tmp_path, artifact_dir, base_head)
|
|
244
243
|
|
|
245
244
|
result = finalize_runtime_commit(
|
|
246
245
|
tmp_path,
|
|
@@ -249,24 +248,19 @@ def test_runtime_commit_excludes_tracked_prizmkit_internal_paths(tmp_path, durab
|
|
|
249
248
|
)
|
|
250
249
|
|
|
251
250
|
assert result.status == "committed", result
|
|
252
|
-
|
|
251
|
+
changed = set(_git(
|
|
253
252
|
tmp_path,
|
|
254
253
|
"diff-tree",
|
|
255
254
|
"--no-commit-id",
|
|
256
255
|
"--name-only",
|
|
257
256
|
"-r",
|
|
258
257
|
"HEAD",
|
|
259
|
-
)
|
|
258
|
+
).splitlines())
|
|
259
|
+
assert changed == {"tracked.txt", durable_path}
|
|
260
260
|
assert durable.read_text(encoding="utf-8") == "after\n"
|
|
261
|
-
assert durable_path in _git(
|
|
262
|
-
tmp_path,
|
|
263
|
-
"status",
|
|
264
|
-
"--short",
|
|
265
|
-
"--untracked-files=all",
|
|
266
|
-
)
|
|
267
261
|
|
|
268
262
|
|
|
269
|
-
def
|
|
263
|
+
def test_runtime_commit_includes_valid_host_support_paths_from_workspace(tmp_path):
|
|
270
264
|
base_head = _init_repo(tmp_path)
|
|
271
265
|
artifact_dir, checkpoint_path = _write_commit_ready_checkpoint(tmp_path)
|
|
272
266
|
(tmp_path / "tracked.txt").write_text("after\n", encoding="utf-8")
|
|
@@ -274,7 +268,7 @@ def test_runtime_commit_ignores_runner_support_paths_but_leaves_them_unmodified(
|
|
|
274
268
|
codex_config = tmp_path / ".codex" / "config.toml"
|
|
275
269
|
codex_config.parent.mkdir()
|
|
276
270
|
codex_config.write_text("[project]\ntrusted = true\n", encoding="utf-8")
|
|
277
|
-
_write_request(tmp_path, artifact_dir, base_head
|
|
271
|
+
_write_request(tmp_path, artifact_dir, base_head)
|
|
278
272
|
|
|
279
273
|
result = finalize_runtime_commit(
|
|
280
274
|
tmp_path,
|
|
@@ -283,11 +277,11 @@ def test_runtime_commit_ignores_runner_support_paths_but_leaves_them_unmodified(
|
|
|
283
277
|
)
|
|
284
278
|
|
|
285
279
|
assert result.status == "committed"
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
assert
|
|
280
|
+
changed = set(
|
|
281
|
+
_git(tmp_path, "diff-tree", "--no-commit-id", "--name-only", "-r", "HEAD").splitlines()
|
|
282
|
+
)
|
|
283
|
+
assert changed == {"tracked.txt", "AGENTS.md", ".codex/config.toml"}
|
|
284
|
+
assert _git(tmp_path, "status", "--porcelain") == ""
|
|
291
285
|
|
|
292
286
|
|
|
293
287
|
def test_runtime_commit_allows_task_path_adjacent_to_internal_namespace(tmp_path):
|
|
@@ -296,7 +290,7 @@ def test_runtime_commit_allows_task_path_adjacent_to_internal_namespace(tmp_path
|
|
|
296
290
|
adjacent_path = tmp_path / ".prizmkitx" / "task.txt"
|
|
297
291
|
adjacent_path.parent.mkdir()
|
|
298
292
|
adjacent_path.write_text("task-owned\n", encoding="utf-8")
|
|
299
|
-
_write_request(tmp_path, artifact_dir, base_head
|
|
293
|
+
_write_request(tmp_path, artifact_dir, base_head)
|
|
300
294
|
|
|
301
295
|
result = finalize_runtime_commit(
|
|
302
296
|
tmp_path,
|
|
@@ -320,7 +314,7 @@ def test_runtime_commit_ignores_project_gitignored_transient_data(tmp_path):
|
|
|
320
314
|
transient = tmp_path / "tmp" / "tool-cache.json"
|
|
321
315
|
transient.parent.mkdir()
|
|
322
316
|
transient.write_text('{"cache":true}\n', encoding="utf-8")
|
|
323
|
-
_write_request(tmp_path, artifact_dir, base_head
|
|
317
|
+
_write_request(tmp_path, artifact_dir, base_head)
|
|
324
318
|
|
|
325
319
|
result = finalize_runtime_commit(
|
|
326
320
|
tmp_path,
|
|
@@ -333,12 +327,12 @@ def test_runtime_commit_ignores_project_gitignored_transient_data(tmp_path):
|
|
|
333
327
|
assert transient.read_text(encoding="utf-8") == '{"cache":true}\n'
|
|
334
328
|
|
|
335
329
|
|
|
336
|
-
def
|
|
330
|
+
def test_runtime_commit_includes_preexisting_git_visible_change_without_manifest(tmp_path):
|
|
337
331
|
base_head = _init_repo(tmp_path)
|
|
338
332
|
artifact_dir, checkpoint_path = _write_commit_ready_checkpoint(tmp_path)
|
|
339
333
|
(tmp_path / "tracked.txt").write_text("after\n", encoding="utf-8")
|
|
340
|
-
(tmp_path / "
|
|
341
|
-
_write_request(tmp_path, artifact_dir, base_head
|
|
334
|
+
(tmp_path / "preexisting.txt").write_text("validated existing work\n", encoding="utf-8")
|
|
335
|
+
_write_request(tmp_path, artifact_dir, base_head)
|
|
342
336
|
|
|
343
337
|
result = finalize_runtime_commit(
|
|
344
338
|
tmp_path,
|
|
@@ -346,16 +340,18 @@ def test_runtime_commit_rejects_unlisted_git_visible_change(tmp_path):
|
|
|
346
340
|
checkpoint_path=checkpoint_path,
|
|
347
341
|
)
|
|
348
342
|
|
|
349
|
-
assert result.status == "
|
|
350
|
-
|
|
351
|
-
|
|
343
|
+
assert result.status == "committed"
|
|
344
|
+
changed = set(
|
|
345
|
+
_git(tmp_path, "diff-tree", "--no-commit-id", "--name-only", "-r", "HEAD").splitlines()
|
|
346
|
+
)
|
|
347
|
+
assert changed == {"tracked.txt", "preexisting.txt"}
|
|
352
348
|
|
|
353
349
|
|
|
354
350
|
def test_runtime_commit_recovers_commit_created_before_state_finalization(tmp_path):
|
|
355
351
|
base_head = _init_repo(tmp_path)
|
|
356
352
|
artifact_dir, checkpoint_path = _write_commit_ready_checkpoint(tmp_path)
|
|
357
353
|
(tmp_path / "tracked.txt").write_text("after\n", encoding="utf-8")
|
|
358
|
-
_write_request(tmp_path, artifact_dir, base_head
|
|
354
|
+
_write_request(tmp_path, artifact_dir, base_head)
|
|
359
355
|
_git(tmp_path, "add", "tracked.txt")
|
|
360
356
|
_git(tmp_path, "commit", "-m", "fix(runtime): finalize prepared task")
|
|
361
357
|
committed_head = _git(tmp_path, "rev-parse", "HEAD")
|
|
@@ -372,15 +368,38 @@ def test_runtime_commit_recovers_commit_created_before_state_finalization(tmp_pa
|
|
|
372
368
|
assert _git(tmp_path, "rev-list", "--count", f"{base_head}..HEAD") == "1"
|
|
373
369
|
|
|
374
370
|
|
|
371
|
+
def test_runtime_commit_rejects_recovery_commit_containing_causal_bookkeeping(tmp_path):
|
|
372
|
+
base_head = _init_repo(tmp_path)
|
|
373
|
+
artifact_dir, checkpoint_path = _write_commit_ready_checkpoint(tmp_path)
|
|
374
|
+
(tmp_path / "tracked.txt").write_text("after\n", encoding="utf-8")
|
|
375
|
+
request_path = _write_request(tmp_path, artifact_dir, base_head)
|
|
376
|
+
_git(
|
|
377
|
+
tmp_path,
|
|
378
|
+
"add",
|
|
379
|
+
"-f",
|
|
380
|
+
"tracked.txt",
|
|
381
|
+
checkpoint_path.relative_to(tmp_path).as_posix(),
|
|
382
|
+
request_path.relative_to(tmp_path).as_posix(),
|
|
383
|
+
)
|
|
384
|
+
_git(tmp_path, "commit", "-m", "fix(runtime): finalize prepared task")
|
|
385
|
+
|
|
386
|
+
result = finalize_runtime_commit(
|
|
387
|
+
tmp_path,
|
|
388
|
+
artifact_dir=artifact_dir,
|
|
389
|
+
checkpoint_path=checkpoint_path,
|
|
390
|
+
)
|
|
391
|
+
|
|
392
|
+
assert result.status == "failed"
|
|
393
|
+
assert result.reason == "base_head_mismatch"
|
|
394
|
+
|
|
395
|
+
|
|
375
396
|
def test_runtime_commit_recovers_after_checkpoint_finalization_failure(tmp_path, monkeypatch):
|
|
376
397
|
import prizmkit_runtime.runtime_commit as runtime_commit
|
|
377
398
|
|
|
378
399
|
base_head = _init_repo(tmp_path)
|
|
379
400
|
artifact_dir, checkpoint_path = _write_commit_ready_checkpoint(tmp_path)
|
|
380
401
|
(tmp_path / "tracked.txt").write_text("after\n", encoding="utf-8")
|
|
381
|
-
request_path = _write_request(
|
|
382
|
-
tmp_path, artifact_dir, base_head, ["tracked.txt"]
|
|
383
|
-
)
|
|
402
|
+
request_path = _write_request(tmp_path, artifact_dir, base_head)
|
|
384
403
|
|
|
385
404
|
original_finalize = runtime_commit._finalize_checkpoint
|
|
386
405
|
monkeypatch.setattr(
|
|
@@ -417,9 +436,7 @@ def test_runtime_commit_recovers_cleanup_after_completed_checkpoint(tmp_path, mo
|
|
|
417
436
|
base_head = _init_repo(tmp_path)
|
|
418
437
|
artifact_dir, checkpoint_path = _write_commit_ready_checkpoint(tmp_path)
|
|
419
438
|
(tmp_path / "tracked.txt").write_text("after\n", encoding="utf-8")
|
|
420
|
-
request_path = _write_request(
|
|
421
|
-
tmp_path, artifact_dir, base_head, ["tracked.txt"]
|
|
422
|
-
)
|
|
439
|
+
request_path = _write_request(tmp_path, artifact_dir, base_head)
|
|
423
440
|
|
|
424
441
|
original_unlink = Path.unlink
|
|
425
442
|
|
|
@@ -462,7 +479,7 @@ def test_runtime_commit_disables_repository_hooks(tmp_path):
|
|
|
462
479
|
)
|
|
463
480
|
hook.chmod(0o755)
|
|
464
481
|
(tmp_path / "tracked.txt").write_text("after\n", encoding="utf-8")
|
|
465
|
-
_write_request(tmp_path, artifact_dir, base_head
|
|
482
|
+
_write_request(tmp_path, artifact_dir, base_head)
|
|
466
483
|
|
|
467
484
|
result = finalize_runtime_commit(
|
|
468
485
|
tmp_path,
|
|
@@ -484,12 +501,7 @@ def test_runtime_commit_handles_rename_as_exact_delete_and_add(tmp_path):
|
|
|
484
501
|
base_head = _git(tmp_path, "rev-parse", "HEAD")
|
|
485
502
|
artifact_dir, checkpoint_path = _write_commit_ready_checkpoint(tmp_path)
|
|
486
503
|
old_path.rename(tmp_path / "new-name.txt")
|
|
487
|
-
_write_request(
|
|
488
|
-
tmp_path,
|
|
489
|
-
artifact_dir,
|
|
490
|
-
base_head,
|
|
491
|
-
["old-name.txt", "new-name.txt"],
|
|
492
|
-
)
|
|
504
|
+
_write_request(tmp_path, artifact_dir, base_head)
|
|
493
505
|
|
|
494
506
|
result = finalize_runtime_commit(
|
|
495
507
|
tmp_path,
|
|
@@ -513,28 +525,95 @@ def test_runtime_commit_handles_rename_as_exact_delete_and_add(tmp_path):
|
|
|
513
525
|
@pytest.mark.parametrize(
|
|
514
526
|
"unsafe_path",
|
|
515
527
|
[
|
|
516
|
-
"../escape.txt",
|
|
517
|
-
".git/config",
|
|
518
528
|
".env",
|
|
519
|
-
"
|
|
520
|
-
"
|
|
521
|
-
".
|
|
522
|
-
".
|
|
523
|
-
".prizmkit/config.json",
|
|
524
|
-
".prizmkit/prizm-docs/src/counter.prizm",
|
|
525
|
-
".prizmkit/state/runtime.json",
|
|
526
|
-
".prizmkit/dev-pipeline/cli.py",
|
|
527
|
-
".prizmkit/scripts/helper.py",
|
|
528
|
-
".prizmkit/manifest.json",
|
|
529
|
-
".prizmkit/specs/001-runtime-commit/workflow-checkpoint.json",
|
|
530
|
-
".prizmkit/specs/001-runtime-commit/runtime-commit-request.json",
|
|
529
|
+
"credentials.json",
|
|
530
|
+
"secrets.json",
|
|
531
|
+
"private.pem",
|
|
532
|
+
".codex/settings.local.json",
|
|
531
533
|
],
|
|
532
534
|
)
|
|
533
|
-
def
|
|
535
|
+
def test_runtime_commit_rejects_sensitive_git_visible_workspace_path(tmp_path, unsafe_path):
|
|
536
|
+
base_head = _init_repo(tmp_path)
|
|
537
|
+
artifact_dir, checkpoint_path = _write_commit_ready_checkpoint(tmp_path)
|
|
538
|
+
unsafe = tmp_path / unsafe_path
|
|
539
|
+
unsafe.parent.mkdir(parents=True, exist_ok=True)
|
|
540
|
+
unsafe.write_text("sensitive\n", encoding="utf-8")
|
|
541
|
+
_write_request(tmp_path, artifact_dir, base_head)
|
|
542
|
+
|
|
543
|
+
result = finalize_runtime_commit(
|
|
544
|
+
tmp_path,
|
|
545
|
+
artifact_dir=artifact_dir,
|
|
546
|
+
checkpoint_path=checkpoint_path,
|
|
547
|
+
)
|
|
548
|
+
|
|
549
|
+
assert result.status == "failed"
|
|
550
|
+
assert result.reason == "sensitive_workspace_path"
|
|
551
|
+
assert _git(tmp_path, "rev-parse", "HEAD") == base_head
|
|
552
|
+
|
|
553
|
+
|
|
554
|
+
def test_runtime_commit_rejects_empty_workspace(tmp_path):
|
|
555
|
+
base_head = _init_repo(tmp_path)
|
|
556
|
+
artifact_dir, checkpoint_path = _write_commit_ready_checkpoint(tmp_path)
|
|
557
|
+
_write_request(tmp_path, artifact_dir, base_head)
|
|
558
|
+
|
|
559
|
+
result = finalize_runtime_commit(
|
|
560
|
+
tmp_path,
|
|
561
|
+
artifact_dir=artifact_dir,
|
|
562
|
+
checkpoint_path=checkpoint_path,
|
|
563
|
+
)
|
|
564
|
+
|
|
565
|
+
assert result.status == "failed"
|
|
566
|
+
assert result.reason == "empty_workspace_change"
|
|
567
|
+
assert _git(tmp_path, "rev-parse", "HEAD") == base_head
|
|
568
|
+
|
|
569
|
+
|
|
570
|
+
def test_runtime_commit_rejects_unresolved_merge_state(tmp_path):
|
|
571
|
+
_init_repo(tmp_path)
|
|
572
|
+
initial_branch = _git(tmp_path, "branch", "--show-current")
|
|
573
|
+
_git(tmp_path, "checkout", "-b", "other")
|
|
574
|
+
(tmp_path / "tracked.txt").write_text("other\n", encoding="utf-8")
|
|
575
|
+
_git(tmp_path, "add", "tracked.txt")
|
|
576
|
+
_git(tmp_path, "commit", "-m", "other change")
|
|
577
|
+
_git(tmp_path, "checkout", initial_branch)
|
|
578
|
+
(tmp_path / "tracked.txt").write_text("master\n", encoding="utf-8")
|
|
579
|
+
_git(tmp_path, "add", "tracked.txt")
|
|
580
|
+
_git(tmp_path, "commit", "-m", "master change")
|
|
581
|
+
base_head = _git(tmp_path, "rev-parse", "HEAD")
|
|
582
|
+
merged = subprocess.run(
|
|
583
|
+
["git", "merge", "other"],
|
|
584
|
+
cwd=tmp_path,
|
|
585
|
+
stdout=subprocess.PIPE,
|
|
586
|
+
stderr=subprocess.PIPE,
|
|
587
|
+
text=True,
|
|
588
|
+
check=False,
|
|
589
|
+
)
|
|
590
|
+
assert merged.returncode != 0
|
|
591
|
+
artifact_dir, checkpoint_path = _write_commit_ready_checkpoint(tmp_path)
|
|
592
|
+
_write_request(tmp_path, artifact_dir, base_head)
|
|
593
|
+
|
|
594
|
+
result = finalize_runtime_commit(
|
|
595
|
+
tmp_path,
|
|
596
|
+
artifact_dir=artifact_dir,
|
|
597
|
+
checkpoint_path=checkpoint_path,
|
|
598
|
+
)
|
|
599
|
+
|
|
600
|
+
assert result.status == "failed"
|
|
601
|
+
assert result.reason == "unresolved_merge_state"
|
|
602
|
+
assert _git(tmp_path, "rev-parse", "HEAD") == base_head
|
|
603
|
+
|
|
604
|
+
|
|
605
|
+
def test_runtime_commit_rejects_already_staged_runtime_bookkeeping(tmp_path):
|
|
534
606
|
base_head = _init_repo(tmp_path)
|
|
535
607
|
artifact_dir, checkpoint_path = _write_commit_ready_checkpoint(tmp_path)
|
|
536
608
|
(tmp_path / "tracked.txt").write_text("after\n", encoding="utf-8")
|
|
537
|
-
_write_request(tmp_path, artifact_dir, base_head
|
|
609
|
+
request_path = _write_request(tmp_path, artifact_dir, base_head)
|
|
610
|
+
_git(
|
|
611
|
+
tmp_path,
|
|
612
|
+
"add",
|
|
613
|
+
"-f",
|
|
614
|
+
checkpoint_path.relative_to(tmp_path).as_posix(),
|
|
615
|
+
request_path.relative_to(tmp_path).as_posix(),
|
|
616
|
+
)
|
|
538
617
|
|
|
539
618
|
result = finalize_runtime_commit(
|
|
540
619
|
tmp_path,
|
|
@@ -543,17 +622,99 @@ def test_runtime_commit_rejects_unsafe_intended_paths(tmp_path, unsafe_path):
|
|
|
543
622
|
)
|
|
544
623
|
|
|
545
624
|
assert result.status == "failed"
|
|
546
|
-
assert result.reason == "
|
|
625
|
+
assert result.reason == "runtime_bookkeeping_staged"
|
|
547
626
|
assert _git(tmp_path, "rev-parse", "HEAD") == base_head
|
|
548
627
|
|
|
549
628
|
|
|
550
|
-
def
|
|
629
|
+
def test_runtime_commit_rejects_schema_v1_path_manifest(tmp_path):
|
|
551
630
|
base_head = _init_repo(tmp_path)
|
|
552
631
|
artifact_dir, checkpoint_path = _write_commit_ready_checkpoint(tmp_path)
|
|
553
632
|
(tmp_path / "tracked.txt").write_text("after\n", encoding="utf-8")
|
|
554
|
-
request_path = _write_request(
|
|
555
|
-
|
|
633
|
+
request_path = _write_request(tmp_path, artifact_dir, base_head)
|
|
634
|
+
request = json.loads(request_path.read_text(encoding="utf-8"))
|
|
635
|
+
request["schema_version"] = 1
|
|
636
|
+
request["intended_paths"] = ["tracked.txt"]
|
|
637
|
+
request_path.write_text(json.dumps(request), encoding="utf-8")
|
|
638
|
+
|
|
639
|
+
result = finalize_runtime_commit(
|
|
640
|
+
tmp_path,
|
|
641
|
+
artifact_dir=artifact_dir,
|
|
642
|
+
checkpoint_path=checkpoint_path,
|
|
643
|
+
)
|
|
644
|
+
|
|
645
|
+
assert result.status == "failed"
|
|
646
|
+
assert result.reason == "commit_request_invalid_schema"
|
|
647
|
+
assert _git(tmp_path, "rev-parse", "HEAD") == base_head
|
|
648
|
+
|
|
649
|
+
|
|
650
|
+
def test_runtime_commit_includes_already_staged_and_unstaged_workspace(tmp_path):
|
|
651
|
+
_init_repo(tmp_path)
|
|
652
|
+
support = tmp_path / "AGENTS.md"
|
|
653
|
+
support.write_text("before\n", encoding="utf-8")
|
|
654
|
+
_git(tmp_path, "add", "AGENTS.md")
|
|
655
|
+
_git(tmp_path, "commit", "-m", "track support")
|
|
656
|
+
base_head = _git(tmp_path, "rev-parse", "HEAD")
|
|
657
|
+
artifact_dir, checkpoint_path = _write_commit_ready_checkpoint(tmp_path)
|
|
658
|
+
(tmp_path / "tracked.txt").write_text("after\n", encoding="utf-8")
|
|
659
|
+
support.write_text("after\n", encoding="utf-8")
|
|
660
|
+
_git(tmp_path, "add", "AGENTS.md")
|
|
661
|
+
_write_request(tmp_path, artifact_dir, base_head)
|
|
662
|
+
|
|
663
|
+
result = finalize_runtime_commit(
|
|
664
|
+
tmp_path,
|
|
665
|
+
artifact_dir=artifact_dir,
|
|
666
|
+
checkpoint_path=checkpoint_path,
|
|
556
667
|
)
|
|
668
|
+
|
|
669
|
+
assert result.status == "committed"
|
|
670
|
+
changed = set(
|
|
671
|
+
_git(tmp_path, "diff-tree", "--no-commit-id", "--name-only", "-r", "HEAD").splitlines()
|
|
672
|
+
)
|
|
673
|
+
assert changed == {"AGENTS.md", "tracked.txt"}
|
|
674
|
+
|
|
675
|
+
|
|
676
|
+
def test_runtime_commit_keeps_tracked_post_commit_bookkeeping_out_of_snapshot(tmp_path):
|
|
677
|
+
from prizmkit_runtime.gitops import HIDDEN_TOOL_WORKTREE_EXCLUDES
|
|
678
|
+
|
|
679
|
+
initial_head = _init_repo(tmp_path)
|
|
680
|
+
artifact_dir, checkpoint_path = _write_commit_ready_checkpoint(tmp_path)
|
|
681
|
+
request_path = _write_request(tmp_path, artifact_dir, initial_head)
|
|
682
|
+
checkpoint_rel = checkpoint_path.relative_to(tmp_path).as_posix()
|
|
683
|
+
request_rel = request_path.relative_to(tmp_path).as_posix()
|
|
684
|
+
_git(tmp_path, "add", "-f", checkpoint_rel, request_rel)
|
|
685
|
+
_git(tmp_path, "commit", "-m", "track runtime bookkeeping by project policy")
|
|
686
|
+
base_head = _git(tmp_path, "rev-parse", "HEAD")
|
|
687
|
+
_write_request(tmp_path, artifact_dir, base_head)
|
|
688
|
+
(tmp_path / "tracked.txt").write_text("after\n", encoding="utf-8")
|
|
689
|
+
|
|
690
|
+
result = finalize_runtime_commit(
|
|
691
|
+
tmp_path,
|
|
692
|
+
artifact_dir=artifact_dir,
|
|
693
|
+
checkpoint_path=checkpoint_path,
|
|
694
|
+
)
|
|
695
|
+
|
|
696
|
+
assert result.status == "committed", result
|
|
697
|
+
assert _git(tmp_path, "diff-tree", "--no-commit-id", "--name-only", "-r", "HEAD") == "tracked.txt"
|
|
698
|
+
assert checkpoint_rel not in _git(tmp_path, "diff-tree", "--no-commit-id", "--name-only", "-r", "HEAD")
|
|
699
|
+
visible = _git(
|
|
700
|
+
tmp_path,
|
|
701
|
+
"status",
|
|
702
|
+
"--porcelain",
|
|
703
|
+
"--",
|
|
704
|
+
".",
|
|
705
|
+
*HIDDEN_TOOL_WORKTREE_EXCLUDES,
|
|
706
|
+
)
|
|
707
|
+
assert visible == ""
|
|
708
|
+
raw_status = _git(tmp_path, "status", "--porcelain", "--", checkpoint_rel, request_rel)
|
|
709
|
+
assert checkpoint_rel in raw_status
|
|
710
|
+
assert request_rel in raw_status
|
|
711
|
+
|
|
712
|
+
|
|
713
|
+
def test_runtime_commit_rejects_caller_orchestration_fields(tmp_path):
|
|
714
|
+
base_head = _init_repo(tmp_path)
|
|
715
|
+
artifact_dir, checkpoint_path = _write_commit_ready_checkpoint(tmp_path)
|
|
716
|
+
(tmp_path / "tracked.txt").write_text("after\n", encoding="utf-8")
|
|
717
|
+
request_path = _write_request(tmp_path, artifact_dir, base_head)
|
|
557
718
|
request = json.loads(request_path.read_text(encoding="utf-8"))
|
|
558
719
|
request["caller_state_path"] = ".runtime/caller-state.json"
|
|
559
720
|
request_path.write_text(json.dumps(request), encoding="utf-8")
|
|
@@ -573,9 +734,7 @@ def test_runtime_commit_rejects_ai_supplied_premature_runtime_hash(tmp_path):
|
|
|
573
734
|
base_head = _init_repo(tmp_path)
|
|
574
735
|
artifact_dir, checkpoint_path = _write_commit_ready_checkpoint(tmp_path)
|
|
575
736
|
(tmp_path / "tracked.txt").write_text("after\n", encoding="utf-8")
|
|
576
|
-
request_path = _write_request(
|
|
577
|
-
tmp_path, artifact_dir, base_head, ["tracked.txt"]
|
|
578
|
-
)
|
|
737
|
+
request_path = _write_request(tmp_path, artifact_dir, base_head)
|
|
579
738
|
request = json.loads(request_path.read_text(encoding="utf-8"))
|
|
580
739
|
request["runtime_commit_hash"] = "a" * 40
|
|
581
740
|
request_path.write_text(json.dumps(request), encoding="utf-8")
|
|
@@ -595,7 +754,7 @@ def test_runtime_commit_rejects_stale_base_head(tmp_path):
|
|
|
595
754
|
base_head = _init_repo(tmp_path)
|
|
596
755
|
artifact_dir, checkpoint_path = _write_commit_ready_checkpoint(tmp_path)
|
|
597
756
|
(tmp_path / "tracked.txt").write_text("after\n", encoding="utf-8")
|
|
598
|
-
_write_request(tmp_path, artifact_dir, "a" * 40
|
|
757
|
+
_write_request(tmp_path, artifact_dir, "a" * 40)
|
|
599
758
|
|
|
600
759
|
result = finalize_runtime_commit(
|
|
601
760
|
tmp_path,
|