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.
- 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/runtime_commit.py +42 -15
- package/bundled/dev-pipeline/templates/bootstrap-prompt.md +1 -1
- package/bundled/dev-pipeline/templates/bootstrap-tier3.md +1 -1
- package/bundled/dev-pipeline/templates/sections/runtime-commit-handoff.md +6 -6
- package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +4 -3
- package/bundled/dev-pipeline/tests/test_generate_bugfix_prompt.py +2 -2
- package/bundled/dev-pipeline/tests/test_generate_refactor_prompt.py +2 -2
- package/bundled/dev-pipeline/tests/test_runtime_commit.py +68 -13
- package/bundled/dev-pipeline/tests/test_unified_cli.py +10 -6
- package/bundled/rules/prizm/prizm-commit-workflow.md +7 -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 +1 -1
- package/bundled/skills/prizmkit-committer/SKILL.md +48 -41
- 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 +26 -13
- 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 +33 -10
- package/bundled/skills/prizmkit-test/references/test-report-template.md +33 -11
- package/bundled/skills/prizmkit-workflow/SKILL.md +5 -7
- package/bundled/skills/prizmkit-workflow/references/workflow-state-protocol.md +5 -6
- 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
package/bundled/VERSION.json
CHANGED
|
@@ -1,15 +1,78 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* CodeBuddy
|
|
3
|
-
*
|
|
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
|
-
*
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
110
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
346
|
-
|
|
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,
|
|
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,
|
|
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
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
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
|
|
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 "
|
|
1560
|
-
assert "
|
|
1561
|
-
assert "
|
|
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 "
|
|
600
|
-
assert "
|
|
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 "
|
|
439
|
-
assert "
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
)
|
|
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/
|
|
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
|
|
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
|
|
3934
|
-
assert
|
|
3935
|
-
assert (repo / "feature.txt").
|
|
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
|
-
|
|
6
|
-
1.
|
|
7
|
-
2. Use
|
|
8
|
-
3.
|
|
9
|
-
4.
|
|
10
|
-
5.
|
|
11
|
-
6.
|
|
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
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
-
|
|
30
|
-
- L1
|
|
31
|
-
- L2
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
-
|
|
35
|
-
-
|
|
36
|
-
-
|
|
37
|
-
-
|
|
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.
|