prizmkit 1.1.159 → 1.1.160

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.
Files changed (77) hide show
  1. package/bundled/VERSION.json +3 -3
  2. package/bundled/adapters/codebuddy/settings-adapter.js +76 -25
  3. package/bundled/dev-pipeline/prizmkit_runtime/gitops.py +9 -2
  4. package/bundled/dev-pipeline/prizmkit_runtime/runtime_commit.py +42 -15
  5. package/bundled/dev-pipeline/templates/bootstrap-prompt.md +1 -1
  6. package/bundled/dev-pipeline/templates/bootstrap-tier3.md +1 -1
  7. package/bundled/dev-pipeline/templates/sections/runtime-commit-handoff.md +6 -6
  8. package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +4 -3
  9. package/bundled/dev-pipeline/tests/test_generate_bugfix_prompt.py +2 -2
  10. package/bundled/dev-pipeline/tests/test_generate_refactor_prompt.py +2 -2
  11. package/bundled/dev-pipeline/tests/test_runtime_commit.py +68 -13
  12. package/bundled/dev-pipeline/tests/test_unified_cli.py +10 -6
  13. package/bundled/rules/prizm/prizm-commit-workflow.md +7 -7
  14. package/bundled/rules/prizm/prizm-documentation.md +24 -65
  15. package/bundled/rules/prizm/prizm-progressive-loading.md +9 -8
  16. package/bundled/skills/_metadata.json +1 -1
  17. package/bundled/skills/prizmkit-code-review/SKILL.md +1 -1
  18. package/bundled/skills/prizmkit-committer/SKILL.md +48 -41
  19. package/bundled/skills/prizmkit-deploy/SKILL.md +172 -198
  20. package/bundled/skills/prizmkit-deploy/references/capability-contract.md +137 -0
  21. package/bundled/skills/prizmkit-deploy/references/deploy-record-schema.json +1053 -0
  22. package/bundled/skills/prizmkit-deploy/references/deployment-declaration-schema.json +291 -0
  23. package/bundled/skills/prizmkit-deploy/references/legacy-migration.md +90 -0
  24. package/bundled/skills/prizmkit-deploy/references/policy-and-execution.md +170 -0
  25. package/bundled/skills/prizmkit-deploy/references/real-resource-test-policy.md +73 -0
  26. package/bundled/skills/prizmkit-deploy/references/verification-and-recovery.md +164 -0
  27. package/bundled/skills/prizmkit-deploy/scripts/validate-deploy-artifact.py +371 -0
  28. package/bundled/skills/prizmkit-implement/SKILL.md +2 -2
  29. package/bundled/skills/prizmkit-init/SKILL.md +17 -17
  30. package/bundled/skills/prizmkit-init/references/update-supplement.md +5 -5
  31. package/bundled/skills/prizmkit-prizm-docs/SKILL.md +17 -11
  32. package/bundled/skills/prizmkit-prizm-docs/assets/prizm-docs-format.md +95 -155
  33. package/bundled/skills/prizmkit-prizm-docs/references/op-init.md +6 -5
  34. package/bundled/skills/prizmkit-prizm-docs/references/op-rebuild.md +4 -2
  35. package/bundled/skills/prizmkit-prizm-docs/references/op-status.md +9 -10
  36. package/bundled/skills/prizmkit-prizm-docs/references/op-update.md +6 -5
  37. package/bundled/skills/prizmkit-prizm-docs/references/op-validate.md +13 -12
  38. package/bundled/skills/prizmkit-retrospective/SKILL.md +3 -3
  39. package/bundled/skills/prizmkit-test/SKILL.md +26 -13
  40. package/bundled/skills/prizmkit-test/references/boundary-contract-and-test-double-guidance.md +8 -4
  41. package/bundled/skills/prizmkit-test/references/independent-test-review.md +7 -3
  42. package/bundled/skills/prizmkit-test/references/test-coverage-model.md +33 -10
  43. package/bundled/skills/prizmkit-test/references/test-report-template.md +33 -11
  44. package/bundled/skills/prizmkit-workflow/SKILL.md +5 -7
  45. package/bundled/skills/prizmkit-workflow/references/workflow-state-protocol.md +5 -6
  46. package/bundled/templates/hooks/commit-intent-status.py +9 -41
  47. package/bundled/templates/hooks/commit-intent.json +3 -3
  48. package/bundled/templates/hooks/diff-prizm-docs.py +3 -1
  49. package/bundled/templates/hooks/prizm-pre-commit.py +32 -6
  50. package/bundled/templates/hooks/run-python-hook.cjs +44 -0
  51. package/bundled/templates/hooks/validate-prizm-docs.py +399 -173
  52. package/bundled/templates/project-memory-template.md +19 -19
  53. package/package.json +1 -1
  54. package/src/clean.js +6 -7
  55. package/src/gitignore-template.js +8 -12
  56. package/src/scaffold.js +125 -71
  57. package/bundled/skills/prizmkit-deploy/assets/deploy-document-template.md +0 -89
  58. package/bundled/skills/prizmkit-deploy/references/ci-cd-workflows.md +0 -145
  59. package/bundled/skills/prizmkit-deploy/references/cloud-platform-deploy.md +0 -109
  60. package/bundled/skills/prizmkit-deploy/references/data-safety-examples.md +0 -120
  61. package/bundled/skills/prizmkit-deploy/references/database-setup.md +0 -65
  62. package/bundled/skills/prizmkit-deploy/references/deploy-config-schema.md +0 -150
  63. package/bundled/skills/prizmkit-deploy/references/deploy-history-schema.md +0 -78
  64. package/bundled/skills/prizmkit-deploy/references/deploy-metadata-schema.json +0 -49
  65. package/bundled/skills/prizmkit-deploy/references/deployment-modes.md +0 -50
  66. package/bundled/skills/prizmkit-deploy/references/direct-upload.md +0 -26
  67. package/bundled/skills/prizmkit-deploy/references/dns-setup.md +0 -42
  68. package/bundled/skills/prizmkit-deploy/references/docker-deploy.md +0 -31
  69. package/bundled/skills/prizmkit-deploy/references/firewall-setup.md +0 -37
  70. package/bundled/skills/prizmkit-deploy/references/live-validation-notes.md +0 -21
  71. package/bundled/skills/prizmkit-deploy/references/nginx-blue-green.md +0 -59
  72. package/bundled/skills/prizmkit-deploy/references/pending-input-schema.json +0 -164
  73. package/bundled/skills/prizmkit-deploy/references/ssh-adapter-flow.md +0 -221
  74. package/bundled/skills/prizmkit-deploy/references/ssh-bootstrap-flow.md +0 -49
  75. package/bundled/skills/prizmkit-deploy/references/ssh-execution-flow.md +0 -41
  76. package/bundled/skills/prizmkit-deploy/references/ssh-takeover.md +0 -20
  77. package/bundled/skills/prizmkit-deploy/references/ssl-setup.md +0 -56
@@ -1,5 +1,5 @@
1
1
  {
2
- "frameworkVersion": "1.1.159",
3
- "bundledAt": "2026-07-28T08:35:59.394Z",
4
- "bundledFrom": "7908918"
2
+ "frameworkVersion": "1.1.160",
3
+ "bundledAt": "2026-07-28T13:41:42.840Z",
4
+ "bundledFrom": "cd9688c"
5
5
  }
@@ -1,15 +1,78 @@
1
1
  /**
2
- * CodeBuddy Settings Adapter
3
- * Generates .codebuddy/settings.json with PrizmKit hooks and permissions.
2
+ * CodeBuddy settings adapter.
3
+ * Replaces only deterministic PrizmKit-managed hook entries and preserves user settings.
4
4
  */
5
5
 
6
6
  import { existsSync, mkdirSync } from 'node:fs';
7
7
  import { readFile, writeFile } from 'node:fs/promises';
8
- import path from 'path';
8
+ import path from 'node:path';
9
+
10
+ const MANAGED_MARKERS = [
11
+ '.prizmkit/scripts/commit-intent-status.py',
12
+ '.prizmkit/scripts/post-command-prizm-drift.py',
13
+ 'PRIZMKIT_DOC_UPDATE_REQUIRED',
14
+ ];
15
+
16
+ function isManaged(entry) {
17
+ let serialized;
18
+ try {
19
+ serialized = JSON.stringify(entry);
20
+ } catch {
21
+ return false;
22
+ }
23
+ return MANAGED_MARKERS.some(marker => serialized.includes(marker));
24
+ }
25
+
26
+ function mergeManagedHooks(existingHooks = {}, managedHooks = {}) {
27
+ if (!existingHooks || typeof existingHooks !== 'object' || Array.isArray(existingHooks)) {
28
+ throw new Error('Cannot preserve malformed CodeBuddy hooks: hooks must be an object');
29
+ }
30
+ const merged = {};
31
+ for (const [event, entries] of Object.entries(existingHooks)) {
32
+ if (!Array.isArray(entries)) {
33
+ throw new Error(`Cannot preserve malformed CodeBuddy hooks: ${event} must be an array`);
34
+ }
35
+ merged[event] = entries.filter(entry => !isManaged(entry));
36
+ }
37
+ for (const [event, entries] of Object.entries(managedHooks)) {
38
+ if (!Array.isArray(entries)) {
39
+ throw new Error(`Managed CodeBuddy hook template is invalid: ${event} must be an array`);
40
+ }
41
+ merged[event] = [
42
+ ...(Array.isArray(merged[event]) ? merged[event] : []),
43
+ ...entries,
44
+ ];
45
+ }
46
+ return merged;
47
+ }
48
+
49
+ const MANAGED_HOOKS = {
50
+ UserPromptSubmit: [
51
+ {
52
+ matcher: '(?i)\\b(commit|push|finish|ship|merge|pull request|pr)\\b|提交|推送|收尾|完成任务|合并|发版|发布',
53
+ hooks: [
54
+ {
55
+ type: 'command',
56
+ command: 'node .prizmkit/scripts/run-python-hook.cjs .prizmkit/scripts/commit-intent-status.py',
57
+ },
58
+ ],
59
+ },
60
+ ],
61
+ PostToolUse: [
62
+ {
63
+ matcher: '.*',
64
+ hooks: [
65
+ {
66
+ type: 'command',
67
+ command: 'node .prizmkit/scripts/run-python-hook.cjs .prizmkit/scripts/post-command-prizm-drift.py',
68
+ },
69
+ ],
70
+ },
71
+ ],
72
+ };
9
73
 
10
74
  /**
11
- * Generate CodeBuddy settings.json for a PrizmKit-enabled project.
12
- * @param {string} targetRoot - Target project root
75
+ * @param {string} targetRoot
13
76
  * @param {Object} options - { hooks: boolean }
14
77
  */
15
78
  export async function generateSettings(targetRoot, options = {}) {
@@ -20,28 +83,16 @@ export async function generateSettings(targetRoot, options = {}) {
20
83
  if (existsSync(settingsPath)) {
21
84
  try {
22
85
  existing = JSON.parse(await readFile(settingsPath, 'utf8'));
23
- } catch {
24
- existing = {};
86
+ } catch (error) {
87
+ throw new Error(`Cannot preserve malformed CodeBuddy settings: ${error.message}`);
25
88
  }
26
- }
27
-
28
- // Merge PrizmKit hooks
29
- if (options.hooks !== false) {
30
- if (!existing.hooks) existing.hooks = {};
31
- if (!existing.hooks.UserPromptSubmit) {
32
- existing.hooks.UserPromptSubmit = [
33
- {
34
- matcher: '(?i)\\b(commit|push|finish|ship|merge|pull request|pr)\\b|提交|推送|收尾|完成任务|合并|发版|发布',
35
- hooks: [
36
- {
37
- type: 'prompt',
38
- prompt: 'You are a commit-intent detector for PrizmKit. Analyze the user prompt and determine if the user intends to COMMIT, PUSH, FINISH, SHIP, MERGE, or create a PULL REQUEST.\n\nUser prompt: $ARGUMENTS\n\nIF commit intent detected, respond with:\n{"ok": true, "reason": "PRIZMKIT_DOC_UPDATE_REQUIRED: Before committing, you MUST update .prizmkit/prizm-docs/ per Prizm auto-update protocol. Steps: 1) Run git diff --cached --name-status. 2) Map changed files to modules via root.prizm MODULE_INDEX. 3) Read and update affected .prizm files (only changed sections). 4) Append to changelog.prizm. 5) Stage .prizm files with git add .prizmkit/prizm-docs/. 6) Then proceed with commit using prizmkit-committer workflow. RULES: Never rewrite entire .prizm files. Never add prose. Only update affected sections."}\n\nIF no commit intent, respond with:\n{"ok": true}\n\nRespond with JSON only. No explanation.',
39
- },
40
- ],
41
- },
42
- ];
89
+ if (!existing || typeof existing !== 'object' || Array.isArray(existing)) {
90
+ throw new Error('Cannot preserve malformed CodeBuddy settings: root must be an object');
43
91
  }
44
92
  }
45
93
 
46
- await writeFile(settingsPath, JSON.stringify(existing, null, 2));
94
+ const settings = options.hooks === false
95
+ ? existing
96
+ : { ...existing, hooks: mergeManagedHooks(existing.hooks, MANAGED_HOOKS) };
97
+ await writeFile(settingsPath, JSON.stringify(settings, null, 2));
47
98
  }
@@ -17,8 +17,15 @@ PIPELINE_METADATA_EXCLUDES = (
17
17
  ":(top,exclude,glob).*/worktree/**",
18
18
  ":(top,exclude,glob).*/worktrees",
19
19
  ":(top,exclude,glob).*/worktrees/**",
20
- ":(top,exclude).prizmkit",
21
- ":(top,exclude,glob).prizmkit/**",
20
+ ":(top,exclude).prizmkit/dev-pipeline",
21
+ ":(top,exclude,glob).prizmkit/dev-pipeline/**",
22
+ ":(top,exclude).prizmkit/state",
23
+ ":(top,exclude,glob).prizmkit/state/**",
24
+ ":(top,exclude).prizmkit/scripts",
25
+ ":(top,exclude,glob).prizmkit/scripts/**",
26
+ ":(top,exclude).prizmkit/manifest.json",
27
+ ":(top,exclude,glob).prizmkit/specs/**/workflow-checkpoint.json",
28
+ ":(top,exclude,glob).prizmkit/specs/**/runtime-commit-request.json",
22
29
  )
23
30
 
24
31
  HIDDEN_TOOL_WORKTREE_EXCLUDES = (
@@ -106,9 +106,9 @@ def finalize_runtime_commit(
106
106
  return RuntimeCommitResult("not_ready", "runtime_commit_already_finalized")
107
107
  return RuntimeCommitResult("failed", error or "invalid_commit_request")
108
108
 
109
- if any(_is_tracked(root, path) for path in (request_path, checkpoint)):
110
- return RuntimeCommitResult("failed", "runtime_metadata_must_be_untracked")
111
-
109
+ # Request/checkpoint paths are excluded by their exact Runtime bookkeeping role.
110
+ # They may be project-tracked; commit verification below ensures their pre/post-
111
+ # commit writes never enter the prepared snapshot.
112
112
  current_head = _git(root, "rev-parse", "HEAD")
113
113
  if current_head.return_code != 0:
114
114
  return RuntimeCommitResult("failed", "git_head_unavailable")
@@ -133,7 +133,15 @@ def finalize_runtime_commit(
133
133
  staged = _stage_intended_paths(root, request.intended_paths)
134
134
  if staged.return_code != 0:
135
135
  return RuntimeCommitResult("failed", "git_stage_failed")
136
- if _git(root, "diff", "--cached", "--quiet", "--exit-code").return_code == 0:
136
+ staged_paths = _git(
137
+ root, "diff", "--cached", "--name-only", "--no-renames", "-z",
138
+ )
139
+ if staged_paths.return_code != 0:
140
+ return RuntimeCommitResult("failed", "git_staged_set_unavailable")
141
+ staged_set = {path for path in staged_paths.stdout.split("\0") if path}
142
+ if staged_set != set(request.intended_paths):
143
+ return RuntimeCommitResult("failed", "staged_paths_mismatch")
144
+ if not staged_set:
137
145
  return RuntimeCommitResult("failed", "empty_staged_change")
138
146
  committed = _git(
139
147
  root,
@@ -320,7 +328,21 @@ def _known_support_path(lower_path: str) -> bool:
320
328
  and parts[1] in {"worktree", "worktrees"}
321
329
  ):
322
330
  return True
323
- return lower_path == ".prizmkit" or lower_path.startswith(".prizmkit/")
331
+ if lower_path in {".prizmkit/manifest.json"}:
332
+ return True
333
+ if any(
334
+ lower_path == prefix or lower_path.startswith(prefix + "/")
335
+ for prefix in (
336
+ ".prizmkit/dev-pipeline",
337
+ ".prizmkit/state",
338
+ ".prizmkit/scripts",
339
+ )
340
+ ):
341
+ return True
342
+ return (
343
+ lower_path.startswith(".prizmkit/specs/")
344
+ and path.name in {REQUEST_FILENAME, "workflow-checkpoint.json"}
345
+ )
324
346
 
325
347
 
326
348
  def _status_record_paths(stdout: str) -> tuple[str, ...]:
@@ -342,8 +364,21 @@ def _status_record_paths(stdout: str) -> tuple[str, ...]:
342
364
 
343
365
 
344
366
  def _stage_intended_paths(project_root: Path, paths: Sequence[str]) -> _GitResult:
345
- pathspecs = tuple(f":(top,literal){path}" for path in paths)
346
- return _git(project_root, "add", "-A", "--", *pathspecs)
367
+ tracked: list[str] = []
368
+ untracked: list[str] = []
369
+ for path in paths:
370
+ pathspec = f":(top,literal){path}"
371
+ indexed = _git(project_root, "ls-files", "--error-unmatch", "--", pathspec)
372
+ (tracked if indexed.return_code == 0 else untracked).append(pathspec)
373
+ if tracked:
374
+ updated = _git(project_root, "add", "-u", "--", *tracked)
375
+ if updated.return_code != 0:
376
+ return updated
377
+ if untracked:
378
+ added = _git(project_root, "add", "--", *untracked)
379
+ if added.return_code != 0:
380
+ return added
381
+ return _GitResult(0, "", "")
347
382
 
348
383
 
349
384
  def _matches_prepared_commit(project_root: Path, request: RuntimeCommitRequest, head: str) -> bool:
@@ -378,14 +413,6 @@ def _record_runtime_commit_hash(path: Path, commit_hash: str) -> str:
378
413
  return "commit_request_hash_record_failed" if error else ""
379
414
 
380
415
 
381
- def _is_tracked(project_root: Path, path: Path) -> bool:
382
- try:
383
- relative = path.relative_to(project_root).as_posix()
384
- except ValueError:
385
- return True
386
- return _git(project_root, "ls-files", "--error-unmatch", "--", relative).return_code == 0
387
-
388
-
389
416
  def _finalize_checkpoint(
390
417
  path: Path,
391
418
  *,
@@ -38,7 +38,7 @@ Complete the feature in headless non-interactive mode using the active atomic sk
38
38
  5. Invoke `/prizmkit-test scope=this-change artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/`. Validate its report/result pair. For `TEST_NEEDS_FIXES`, classify the concrete correction into an allowed `repair_scope`; unknown/unsafe scope blocks, while a safe in-budget route re-enters Implement and requires fresh Review, configured verification, and Test. Do not duplicate the Skill's internal repair loop.
39
39
  6. Write `completion-summary.json` before retrospective and commit preparation.
40
40
  7. Invoke `/prizmkit-retrospective` with the exact artifact root, non-`.prizmkit/` `change_paths`, and `change_summary`; validate `outcome=RETRO_COMPLETE`.
41
- 8. Before commit preparation, all `.prizmkit/**` paths are PrizmKit-internal and stay outside `intended_paths` together with recognized platform support; project-specific transient data must already be Git-ignored, while unknown Git-visible paths block. After validating every required artifact, invoke `/prizmkit-committer operation=prepare-runtime-commit artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/ evidence_paths=<exact paths> excluded_paths=.prizmkit/specs/{{FEATURE_SLUG}}/workflow-checkpoint.json request_path=.prizmkit/specs/{{FEATURE_SLUG}}/runtime-commit-request.json`. Require `COMMIT_REQUEST_READY`; this session then records `COMMIT_PENDING` and stops. The Python runtime executes and verifies the local commit.
41
+ 8. Before commit preparation, classify paths by semantic role rather than a blanket `.prizmkit/**` rule. Safe Git-visible framework paths may be exact task output; ignored paths remain absent, and exact Runtime bookkeeping/installed support, host support, Secrets, unrelated, or unknown paths remain excluded or blocking. No path is force-added and no ignore policy is changed. After validating every required artifact, invoke `/prizmkit-committer operation=prepare-runtime-commit artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/ evidence_paths=<exact paths> excluded_paths=.prizmkit/specs/{{FEATURE_SLUG}}/workflow-checkpoint.json request_path=.prizmkit/specs/{{FEATURE_SLUG}}/runtime-commit-request.json`. Require `COMMIT_REQUEST_READY`; this session then records `COMMIT_PENDING` and stops. The Python runtime executes and verifies the local commit.
42
42
 
43
43
  ## Failure Capture
44
44
 
@@ -448,7 +448,7 @@ Invoke `/prizmkit-retrospective` with the exact artifact root, exact non-`.prizm
448
448
 
449
449
  **6c. Runtime commit preparation**
450
450
 
451
- Before commit preparation, all `.prizmkit/**` paths are PrizmKit-internal and stay outside `intended_paths`, together with `AGENTS.md`, `skills-lock.json`, installed platform directories, and local platform settings. Project-specific transient data must already be covered by Git ignore rules. Unknown Git-visible paths are not silently ignored: justify and include them as task output or block.
451
+ Before commit preparation, classify paths by semantic role rather than a blanket `.prizmkit/**` exclusion. Safe Git-visible framework paths may be justified and included as exact task output; ignored paths remain naturally absent. Exact Runtime request/checkpoint/state and installed Runtime/host support stay outside `intended_paths`; Secrets, unrelated, and unknown Git-visible paths block. Never force-add or change/interpret project ignore policy.
452
452
 
453
453
  After this injected session validates every required artifact, invoke `/prizmkit-committer operation=prepare-runtime-commit artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/ evidence_paths=<exact paths> excluded_paths=.prizmkit/specs/{{FEATURE_SLUG}}/workflow-checkpoint.json request_path=.prizmkit/specs/{{FEATURE_SLUG}}/runtime-commit-request.json`. Require `COMMIT_REQUEST_READY`; this session records `COMMIT_PENDING` and stops. The Python runtime validates the request, executes/verifies the local commit, and finalizes checkpoint `COMMITTED`.
454
454
 
@@ -11,11 +11,11 @@ After Code Review, all configured verification, `TEST_PASS`, family reports/summ
11
11
  /prizmkit-committer operation=prepare-runtime-commit artifact_dir={{ARTIFACT_DIR}} evidence_paths=<exact validated artifact paths> excluded_paths={{ARTIFACT_DIR}}/workflow-checkpoint.json request_path={{ARTIFACT_DIR}}/runtime-commit-request.json
12
12
  ```
13
13
 
14
- 3. The committer validates only the supplied evidence and final diff, then classifies paths before writing the request:
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.
14
+ 3. The committer validates only the supplied evidence and final diff, then classifies paths by semantic role before writing the request:
15
+ - safe Git-visible `.prizmkit/**` requirement output is admitted like any other exact task path and needs no documentation-specific evidence;
16
+ - ignored paths remain absent and are never force-added; project ignore policy is not changed or interpreted;
17
+ - exact Runtime request/checkpoint/state, installed Runtime/host payloads, and local host settings remain support/bookkeeping outside the task commit;
18
+ - global Secret checks still apply, and every unrelated or unknown Git-visible path blocks rather than disappearing.
19
19
 
20
20
  It then rejects sensitive/unrelated/unknown paths, generates one Conventional Commit message, and writes this request without staging or committing:
21
21
 
@@ -32,4 +32,4 @@ After Code Review, all configured verification, `TEST_PASS`, family reports/summ
32
32
  4. 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`.
33
33
  5. 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 files.
34
34
 
35
- The runtime validates exact task-owned path coverage outside recognized internal/support namespaces, rejects a request that explicitly names one of those namespaces, stages only the requested literal paths, executes and verifies the local commit, finalizes the Runtime-owned checkpoint to `COMMITTED`, and then performs its configured merge/publication behavior. Unknown Git-visible paths are not silently ignored: they produce a mismatch and preserve the task checkout for recovery. A malformed, stale, unsafe, incomplete, or contradictory request also blocks without deleting user data.
35
+ The Runtime validates exact task-owned path coverage outside recognized semantic support/bookkeeping, does not reject a safe path solely because it is under `.prizmkit/**`, stages only requested literal paths, verifies staged/committed set equality and the Git receipt, and only then writes the Runtime-owned receipt/checkpoint and performs configured integration. Those post-commit writes are never inserted retroactively into the committed snapshot or allowed to falsify integration. Unknown Git-visible paths are not silently ignored: they produce a mismatch and preserve the task checkout for recovery. A malformed, stale, unsafe, incomplete, or contradictory request also blocks without deleting user data.
@@ -1556,9 +1556,10 @@ class TestFeatureBootstrapShellExtraction:
1556
1556
  assert "/prizmkit-committer operation=prepare-runtime-commit" in tier3
1557
1557
  assert "Require `COMMIT_REQUEST_READY`; this session records `COMMIT_PENDING`" in tier3
1558
1558
  assert "The Python runtime validates the request" in tier3
1559
- assert "all `.prizmkit/**` paths are PrizmKit-internal" in tier3
1560
- assert "project-specific transient data must already be covered by git ignore rules" in tier3.lower()
1561
- assert "Unknown Git-visible paths are not silently ignored" in tier3
1559
+ assert "classify paths by semantic role rather than a blanket `.prizmkit/**` exclusion" in tier3
1560
+ assert "Safe Git-visible framework paths" in tier3
1561
+ assert "Never force-add or change/interpret project ignore policy" in tier3
1562
+ assert "unknown Git-visible paths block" in tier3
1562
1563
  assert "git add" not in tier3
1563
1564
  assert "git commit" not in tier3
1564
1565
 
@@ -596,8 +596,8 @@ 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 "all `.prizmkit/**` paths are PrizmKit-internal" in prompt
600
- assert "Unknown Git-visible paths are not silently ignored" in prompt
599
+ assert "safe Git-visible `.prizmkit/**` requirement output is admitted" in prompt
600
+ assert "unknown Git-visible path blocks" in prompt
601
601
  assert "push_authorized\": true" not in prompt
602
602
  assert ".prizmkit/bugfix/B-001/" in prompt
603
603
  assert "write the session status" not in prompt.lower()
@@ -435,8 +435,8 @@ 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 "all `.prizmkit/**` paths are PrizmKit-internal" in prompt
439
- assert "Unknown Git-visible paths are not silently ignored" in prompt
438
+ assert "safe Git-visible `.prizmkit/**` requirement output is admitted" in prompt
439
+ assert "unknown Git-visible path blocks" in prompt
440
440
  assert "automatic push" not in prompt.lower()
441
441
  assert "push_authorized\": true" not in prompt
442
442
  assert "write the session status" not in prompt.lower()
@@ -229,18 +229,18 @@ def test_runtime_commit_executes_exact_request_and_finalizes_only_checkpoint(tmp
229
229
  ".prizmkit/prizm-docs/src/counter.prizm",
230
230
  ],
231
231
  )
232
- def test_runtime_commit_excludes_tracked_prizmkit_internal_paths(tmp_path, durable_path):
232
+ def test_runtime_commit_admits_tracked_prizmkit_path_in_exact_request(tmp_path, durable_path):
233
233
  _init_repo(tmp_path)
234
234
  durable = tmp_path / durable_path
235
235
  durable.parent.mkdir(parents=True, exist_ok=True)
236
236
  durable.write_text("before\n", encoding="utf-8")
237
237
  _git(tmp_path, "add", "-f", durable_path)
238
- _git(tmp_path, "commit", "-m", "track durable PrizmKit project data")
238
+ _git(tmp_path, "commit", "-m", "track project-selected PrizmKit data")
239
239
  base_head = _git(tmp_path, "rev-parse", "HEAD")
240
240
  artifact_dir, checkpoint_path = _write_commit_ready_checkpoint(tmp_path)
241
241
  (tmp_path / "tracked.txt").write_text("after\n", encoding="utf-8")
242
242
  durable.write_text("after\n", encoding="utf-8")
243
- _write_request(tmp_path, artifact_dir, base_head, ["tracked.txt"])
243
+ _write_request(tmp_path, artifact_dir, base_head, ["tracked.txt", durable_path])
244
244
 
245
245
  result = finalize_runtime_commit(
246
246
  tmp_path,
@@ -249,21 +249,16 @@ def test_runtime_commit_excludes_tracked_prizmkit_internal_paths(tmp_path, durab
249
249
  )
250
250
 
251
251
  assert result.status == "committed", result
252
- assert _git(
252
+ changed = set(_git(
253
253
  tmp_path,
254
254
  "diff-tree",
255
255
  "--no-commit-id",
256
256
  "--name-only",
257
257
  "-r",
258
258
  "HEAD",
259
- ) == "tracked.txt"
259
+ ).splitlines())
260
+ assert changed == {"tracked.txt", durable_path}
260
261
  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
262
 
268
263
 
269
264
  def test_runtime_commit_ignores_runner_support_paths_but_leaves_them_unmodified(tmp_path):
@@ -520,8 +515,7 @@ def test_runtime_commit_handles_rename_as_exact_delete_and_add(tmp_path):
520
515
  "skills-lock.json",
521
516
  ".codex/config.toml",
522
517
  ".CLAUDE/settings.local.json",
523
- ".prizmkit/config.json",
524
- ".prizmkit/prizm-docs/src/counter.prizm",
518
+ ".prizmkit/prizm-docs/.env",
525
519
  ".prizmkit/state/runtime.json",
526
520
  ".prizmkit/dev-pipeline/cli.py",
527
521
  ".prizmkit/scripts/helper.py",
@@ -547,6 +541,67 @@ def test_runtime_commit_rejects_unsafe_intended_paths(tmp_path, unsafe_path):
547
541
  assert _git(tmp_path, "rev-parse", "HEAD") == base_head
548
542
 
549
543
 
544
+ def test_runtime_commit_verifies_staged_set_before_commit(tmp_path):
545
+ _init_repo(tmp_path)
546
+ support = tmp_path / "AGENTS.md"
547
+ support.write_text("before\n", encoding="utf-8")
548
+ _git(tmp_path, "add", "AGENTS.md")
549
+ _git(tmp_path, "commit", "-m", "track support")
550
+ base_head = _git(tmp_path, "rev-parse", "HEAD")
551
+ artifact_dir, checkpoint_path = _write_commit_ready_checkpoint(tmp_path)
552
+ (tmp_path / "tracked.txt").write_text("after\n", encoding="utf-8")
553
+ support.write_text("after\n", encoding="utf-8")
554
+ _git(tmp_path, "add", "AGENTS.md")
555
+ _write_request(tmp_path, artifact_dir, base_head, ["tracked.txt"])
556
+
557
+ result = finalize_runtime_commit(
558
+ tmp_path,
559
+ artifact_dir=artifact_dir,
560
+ checkpoint_path=checkpoint_path,
561
+ )
562
+
563
+ assert result.status == "failed"
564
+ assert result.reason == "staged_paths_mismatch"
565
+ assert _git(tmp_path, "rev-parse", "HEAD") == base_head
566
+
567
+
568
+ def test_runtime_commit_keeps_tracked_post_commit_bookkeeping_out_of_snapshot(tmp_path):
569
+ from prizmkit_runtime.gitops import HIDDEN_TOOL_WORKTREE_EXCLUDES
570
+
571
+ initial_head = _init_repo(tmp_path)
572
+ artifact_dir, checkpoint_path = _write_commit_ready_checkpoint(tmp_path)
573
+ request_path = _write_request(tmp_path, artifact_dir, initial_head, ["tracked.txt"])
574
+ checkpoint_rel = checkpoint_path.relative_to(tmp_path).as_posix()
575
+ request_rel = request_path.relative_to(tmp_path).as_posix()
576
+ _git(tmp_path, "add", "-f", checkpoint_rel, request_rel)
577
+ _git(tmp_path, "commit", "-m", "track runtime bookkeeping by project policy")
578
+ base_head = _git(tmp_path, "rev-parse", "HEAD")
579
+ _write_request(tmp_path, artifact_dir, base_head, ["tracked.txt"])
580
+ (tmp_path / "tracked.txt").write_text("after\n", encoding="utf-8")
581
+
582
+ result = finalize_runtime_commit(
583
+ tmp_path,
584
+ artifact_dir=artifact_dir,
585
+ checkpoint_path=checkpoint_path,
586
+ )
587
+
588
+ assert result.status == "committed", result
589
+ assert _git(tmp_path, "diff-tree", "--no-commit-id", "--name-only", "-r", "HEAD") == "tracked.txt"
590
+ assert checkpoint_rel not in _git(tmp_path, "diff-tree", "--no-commit-id", "--name-only", "-r", "HEAD")
591
+ visible = _git(
592
+ tmp_path,
593
+ "status",
594
+ "--porcelain",
595
+ "--",
596
+ ".",
597
+ *HIDDEN_TOOL_WORKTREE_EXCLUDES,
598
+ )
599
+ assert visible == ""
600
+ raw_status = _git(tmp_path, "status", "--porcelain", "--", checkpoint_rel, request_rel)
601
+ assert checkpoint_rel in raw_status
602
+ assert request_rel in raw_status
603
+
604
+
550
605
  def test_runtime_commit_rejects_caller_orchestration_fields(tmp_path):
551
606
  base_head = _init_repo(tmp_path)
552
607
  artifact_dir, checkpoint_path = _write_commit_ready_checkpoint(tmp_path)
@@ -3621,8 +3621,11 @@ def test_git_status_safe_ignores_worktree_support_assets(monkeypatch, tmp_path):
3621
3621
  joined = " ".join(status_args)
3622
3622
  assert ":(top,exclude).prizmkit-worktree" in status_args
3623
3623
  assert ":(top,exclude).claude" in status_args
3624
- assert ":(top,exclude).prizmkit" in status_args
3625
- assert ":(top,exclude,glob).prizmkit/**" in status_args
3624
+ assert ":(top,exclude).prizmkit" not in status_args
3625
+ assert ":(top,exclude,glob).prizmkit/**" not in status_args
3626
+ assert ":(top,exclude,glob).prizmkit/dev-pipeline/**" in status_args
3627
+ assert ":(top,exclude,glob).prizmkit/state/**" in status_args
3628
+ assert ":(top,exclude,glob).prizmkit/specs/**/workflow-checkpoint.json" in status_args
3626
3629
  assert all(exclude in status_args for exclude in HIDDEN_TOOL_WORKTREE_EXCLUDES)
3627
3630
  assert ".prizmkit-worktree" in joined
3628
3631
 
@@ -3883,7 +3886,7 @@ def test_materialize_worktree_support_assets_copies_ignored_assets_without_retir
3883
3886
  assert guarded_worktree_remove(runtime, delete_branch=False).ok
3884
3887
 
3885
3888
 
3886
- def test_linked_worktree_fast_forwards_with_dirty_prizmkit_internal_state(tmp_path):
3889
+ def test_linked_worktree_rejects_dirty_tracked_prizmkit_config(tmp_path):
3887
3890
  from prizmkit_runtime.gitops import (
3888
3891
  BranchContext,
3889
3892
  WorktreePolicy,
@@ -3930,10 +3933,11 @@ def test_linked_worktree_fast_forwards_with_dirty_prizmkit_internal_state(tmp_pa
3930
3933
  assert branch_fast_forward_possible(repo, runtime.context) is True
3931
3934
  result = merge_linked_worktree(runtime)
3932
3935
 
3933
- assert result.ok is True
3934
- assert not any(item.args and item.args[0] == "rebase" for item in result.results)
3935
- assert (repo / "feature.txt").read_text(encoding="utf-8") == "done\n"
3936
+ assert result.ok is False
3937
+ assert result.reason == "dirty_task_checkout"
3938
+ assert not (repo / "feature.txt").exists()
3936
3939
  assert json.loads(worktree_config.read_text(encoding="utf-8"))["mode"] == "session-local"
3940
+ worktree_config.write_text('{"mode":"base"}\n', encoding="utf-8")
3937
3941
  assert guarded_worktree_remove(runtime, delete_branch=True).ok
3938
3942
 
3939
3943
 
@@ -2,10 +2,10 @@
2
2
  description: "PrizmKit commit workflow rules"
3
3
  ---
4
4
 
5
- Before any git commit in this project:
6
- 1. Run `/prizmkit-retrospective` to sync `.prizmkit/prizm-docs/` (architecture index with TRAPS/RULES/DECISIONS)
7
- 2. Use Conventional Commits format: type(scope): description
8
- 3. Bug fixes use `fix()` prefix, not `feat()`
9
- 4. Bug fixes run retrospective with structural sync only (Job 1)
10
- 5. Use `/prizmkit-committer` command for the pure commit workflow
11
- 6. After commit, `/prizmkit-committer` generates `session-summary.md` (lightweight cross-session handoff, not committed to git)
5
+ For a formal requirement:
6
+ 1. Complete `/prizmkit-retrospective` after Test and before Committer; it synchronizes durable documentation or records `NO_DOC_CHANGE` but never stages or commits.
7
+ 2. Use `/prizmkit-committer` for one exact local commit operation and Conventional Commit message.
8
+ 3. Interactive Committer stages only the user-confirmed exact manifest and verifies staged-set/receipt equality; broad staging and force-add are prohibited.
9
+ 4. A Git-visible `.prizmkit/**` requirement path is handled like any other exact intended path and requires no documentation-specific commit evidence. Ignored paths remain absent; project tracking policy is unchanged.
10
+ 5. Exact Runtime bookkeeping/support and Secrets remain excluded by semantic role. Secret checks apply globally and no framework-directory exception exists.
11
+ 6. Remote publication and deployment remain separate.
@@ -11,68 +11,27 @@ globs:
11
11
  - "**/*.java"
12
12
  ---
13
13
 
14
- WHEN TO UPDATE .prizmkit/prizm-docs/:
15
- - Feature development (new interface, new module, new behavior) UPDATE .prizmkit/prizm-docs/
16
- - Bug fix (fixing broken logic, no structural change) SKIP, do NOT update
17
- - Rationale: bugs are incomplete features. Recording bug details causes doc bloat with no AI value.
18
- - Before modifying any source file, read `.prizmkit/prizm-docs/root.prizm` if it exists to understand project structure.
19
-
20
- FORMAT RULES (enforced by pre-commit hook — violations block commit):
21
- - ALL CAPS section headers: MODULE:, FILES:, RESPONSIBILITY:, etc.
22
- - KEY: value pairs and dash-prefixed lists only
23
- - PROHIBITED: prose paragraphs, markdown headers (##/###), code blocks (```), emoji, ASCII art
24
- - No UPDATED timestamps — git is the authoritative source for temporal information
25
- - PROHIBITED: CHANGELOG sections/files, UPDATED/date metadata, feature/bug/refactor/task/session/run/pipeline/workflow IDs, branch names, absolute worktree paths, and `.prizmkit/specs` / `.prizmkit/dev-pipeline` artifact paths
26
- - This format is designed for AI token efficiency, not human readability. Do not add human-friendly formatting.
27
-
28
- SIZE LIMITS (hard pre-commit hook blocks commits exceeding these):
29
- - L0 root.prizm: 4KB max
30
- - L1 module.prizm: 4KB max
31
- - L2 detail.prizm: 5KB max
32
-
33
- SIZE OVERFLOW HANDLING:
34
- - L0 approaching 4KB: if MODULE_INDEX has > 15 entries, convert to MODULE_GROUPS format (group by domain). Otherwise consolidate descriptions, keep only top-5 RULES, remove PATTERNS detail.
35
- - L1 approaching 4KB: trim KEY_FILES descriptions, ensure RULES <= 3 entries, move detail to L2
36
- - L2 approaching 5KB: remove stale or trivially derivable entries; never create changelog-archive.prizm
37
- - NEVER exceed hard limits pre-commit hook will block the commit
38
-
39
- REQUIRED FIELDS PER LEVEL:
40
-
41
- L0 root.prizm:
42
- - PRIZM_VERSION
43
- - PROJECT
44
- - LANG
45
- - MODULE_INDEX or MODULE_GROUPS (with -> pointers to L1 files)
46
- - RULES (top-level project rules)
47
-
48
- L1 module.prizm (structural index only):
49
- - MODULE
50
- - FILES
51
- - RESPONSIBILITY
52
- - DEPENDENCIES
53
- - L1 does NOT contain: INTERFACES, DATA_FLOW, TRAPS, DECISIONS (those belong in L2)
54
-
55
- L2 detail.prizm:
56
- - MODULE
57
- - FILES
58
- - KEY_FILES
59
- - DEPENDENCIES
60
- - INTERFACES
61
- - TRAPS (with severity prefix: [CRITICAL], [HIGH], or [LOW])
62
-
63
- L2 GENERATION TEMPLATE (use when AI first touches a sub-module with no L2 doc):
64
-
65
- MODULE: <path>
66
- FILES: <comma-separated file list>
67
- RESPONSIBILITY: <one-line>
68
- KEY_FILES:
69
- - <file>: <role, line count, complexity note>
70
- DEPENDENCIES:
71
- - uses: <lib>: <why>
72
- - imports: <module>: <what>
73
- INTERFACES:
74
- - <exported function/class>: <signature and purpose>
75
- TRAPS:
76
- - [LOW] <gotcha, race condition, or non-obvious coupling> | FIX: <approach>
77
-
78
- TRAPS is critical — always record gotchas, race conditions, non-obvious behavior, and surprising coupling between modules. Every TRAP must have a severity prefix ([CRITICAL], [HIGH], or [LOW]).
14
+ WHEN TO UPDATE `.prizmkit/prizm-docs/`:
15
+ - Use `/prizmkit-retrospective` after a validated change affects structure, interfaces, dependencies, behavior, or durable TRAPS/RULES/DECISIONS.
16
+ - Skip documentation writes when no current durable non-obvious fact passes the Value Gate.
17
+ - Before source modification, read exact root, the relevant direct-child L1, the complete relevant nested L2, and complete resolving pointer documents.
18
+ - If relevant L2 is absent, inspect bounded relevant source without creating a placeholder.
19
+
20
+ FRAMEWORK DIRECTORY AND GIT POLICY:
21
+ - `.prizmkit/**` is framework-owned capability/artifact space; an owner may read/write only its managed paths.
22
+ - The project decides whether framework paths are ignored, untracked, or tracked. Do not add, remove, force-add, stage, commit, or interpret `.gitignore` entries as part of documentation maintenance.
23
+ - Validation/generation/reconciliation behavior is identical across tracking states apart from ordinary Git visibility; Git history is not required.
24
+
25
+ FORMAT RULES:
26
+ - New roots use `PRIZM_VERSION: 4`.
27
+ - Only exact `.prizmkit/prizm-docs/root.prizm` is L0; direct `.prizm` children other than root are L1; every nested `.prizm` document is L2.
28
+ - ALL CAPS section headers, KEY: value pairs, and dash-prefixed lists only.
29
+ - PROHIBITED: CHANGELOG sections/files, prose paragraphs, markdown headers, code blocks, horizontal rules, UPDATED/date metadata, feature/bug/refactor/task/session/run/pipeline/workflow IDs, branch names, absolute worktree paths, and `.prizmkit/specs` / `.prizmkit/dev-pipeline` artifact paths.
30
+ - L1 is structural and must not contain INTERFACES, DATA_FLOW, TRAPS, DECISIONS, CONCERN, or full RULES.
31
+ - Mirrored L2 requires MODULE, FILES, RESPONSIBILITY, INTERFACES, KEY_FILES, DEPENDENCIES, and TRAPS. Semantic L2 also requires deterministic CONCERN/SLUG, DATA_FLOW, RULES, DECISIONS, exact parent DETAILS pointer, and non-overlapping FILES ownership.
32
+
33
+ CAPACITY AND WRITES:
34
+ - Raw UTF-8 hard limits: L0 4096B, L1 4096B, L2 5120B. Existing warning bands remain advisory; hard-limit violations fail.
35
+ - Apply Value/Cleanup gates and protect still-valid contracts, constraints, dependencies, traps, decisions, side effects, and safety/integrity rules.
36
+ - Build complete candidates and write bottom-up. Skip byte-identical replacements, re-read actual bytes/pointers, and restore exact prior bytes or remove invalid new targets after any failed post-write check.
37
+ - Never add L3, a documentation state machine, task-named shards, or placeholder L2 documents.