prizmkit 1.1.119 → 1.1.121
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/bin/create-prizmkit.js +1 -5
- package/bundled/VERSION.json +3 -3
- package/bundled/dev-pipeline/README.md +41 -38
- package/bundled/dev-pipeline/assets/skill-subagent-integration.md +76 -0
- package/bundled/dev-pipeline/prizmkit_runtime/config.py +2 -8
- package/bundled/dev-pipeline/prizmkit_runtime/interoperability.py +1 -1
- package/bundled/dev-pipeline/prizmkit_runtime/platform_detection.py +3 -3
- package/bundled/dev-pipeline/prizmkit_runtime/runner_classification.py +23 -25
- package/bundled/dev-pipeline/prizmkit_runtime/runner_models.py +8 -2
- package/bundled/dev-pipeline/prizmkit_runtime/runner_prompts.py +10 -1
- package/bundled/dev-pipeline/prizmkit_runtime/runners.py +88 -32
- package/bundled/dev-pipeline/prizmkit_runtime/sessions.py +28 -6
- package/bundled/dev-pipeline/scripts/continuation.py +51 -6
- package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +60 -102
- package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +1 -19
- package/bundled/dev-pipeline/scripts/generate-refactor-prompt.py +1 -19
- package/bundled/dev-pipeline/scripts/{init-dev-team.py → init-change-artifact.py} +6 -16
- package/bundled/dev-pipeline/scripts/parse-stream-progress.py +364 -76
- package/bundled/dev-pipeline/scripts/update-bug-status.py +57 -14
- package/bundled/dev-pipeline/scripts/update-feature-status.py +54 -5
- package/bundled/dev-pipeline/scripts/update-refactor-status.py +57 -14
- package/bundled/dev-pipeline/scripts/utils.py +1 -1
- package/bundled/dev-pipeline/templates/bootstrap-prompt.md +2 -2
- package/bundled/dev-pipeline/templates/bootstrap-tier3.md +9 -11
- package/bundled/dev-pipeline/templates/bugfix-bootstrap-prompt.md +2 -1
- package/bundled/dev-pipeline/templates/refactor-bootstrap-prompt.md +2 -2
- package/bundled/dev-pipeline/templates/sections/bugfix-phase-review.md +3 -3
- package/bundled/dev-pipeline/templates/sections/context-budget-rules.md +1 -1
- package/bundled/dev-pipeline/templates/sections/critical-paths-agent.md +0 -1
- package/bundled/dev-pipeline/templates/sections/critical-paths-full.md +0 -2
- package/bundled/dev-pipeline/templates/sections/phase-commit-full.md +8 -1
- package/bundled/dev-pipeline/templates/sections/phase-implement-agent.md +6 -7
- package/bundled/dev-pipeline/templates/sections/phase-implement-full.md +6 -7
- package/bundled/dev-pipeline/templates/sections/phase-implement-lite.md +4 -2
- package/bundled/dev-pipeline/templates/sections/phase-review-agent.md +3 -3
- package/bundled/dev-pipeline/templates/sections/phase-review-full.md +5 -3
- package/bundled/dev-pipeline/templates/sections/phase-specify-plan-full.md +20 -0
- package/bundled/dev-pipeline/templates/sections/refactor-phase-review.md +3 -3
- package/bundled/dev-pipeline/tests/test_auto_skip.py +5 -5
- package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +214 -144
- package/bundled/dev-pipeline/tests/test_generate_bugfix_prompt.py +25 -12
- package/bundled/dev-pipeline/tests/test_generate_refactor_prompt.py +11 -14
- package/bundled/dev-pipeline/tests/test_python_runner_parity.py +235 -32
- package/bundled/dev-pipeline/tests/test_unified_cli.py +219 -16
- package/bundled/skills/_metadata.json +4 -4
- package/bundled/skills/app-planner/SKILL.md +2 -2
- package/bundled/skills/app-planner/references/architecture-decisions.md +1 -3
- package/bundled/skills/prizmkit-code-review/SKILL.md +50 -47
- package/bundled/skills/prizmkit-code-review/references/review-report-template.md +13 -8
- package/bundled/skills/prizmkit-code-review/references/reviewer-agent-prompt.md +47 -33
- package/bundled/skills/prizmkit-code-review/references/reviewer-workspace-protocol.md +90 -0
- package/bundled/skills/prizmkit-implement/SKILL.md +21 -1
- package/bundled/skills/prizmkit-implement/references/implementation-subagent-procedure.md +67 -0
- package/bundled/skills/prizmkit-test/SKILL.md +159 -155
- package/bundled/skills/prizmkit-test/assets/authoritative-records.schema.json +420 -0
- package/bundled/skills/prizmkit-test/assets/behavior-risk-matrix.schema.json +116 -0
- package/bundled/skills/prizmkit-test/assets/evidence-manifest.schema.json +112 -0
- package/bundled/skills/prizmkit-test/assets/evidence-package-template.json +97 -0
- package/bundled/skills/prizmkit-test/references/boundary-coverage-protocol.md +76 -192
- package/bundled/skills/prizmkit-test/references/contract-mock-protocol.md +65 -0
- package/bundled/skills/prizmkit-test/references/evidence-protocol.md +194 -0
- package/bundled/skills/prizmkit-test/references/evidence-request-protocol.md +78 -0
- package/bundled/skills/prizmkit-test/references/examples.md +65 -108
- package/bundled/skills/prizmkit-test/references/service-boundary-test-catalog.md +10 -7
- package/bundled/skills/prizmkit-test/references/test-generation-steps.md +90 -82
- package/bundled/skills/prizmkit-test/references/test-report-template.md +77 -98
- package/bundled/skills/prizmkit-test/references/trusted-evidence-execution.md +97 -0
- package/bundled/skills/prizmkit-test/scripts/build_test_evidence.py +723 -0
- package/bundled/skills/prizmkit-test/scripts/validate_test_evidence.py +1426 -0
- package/package.json +1 -1
- package/src/clean.js +12 -8
- package/src/config.js +24 -42
- package/src/index.js +1 -10
- package/src/manifest.js +3 -9
- package/src/metadata.js +0 -26
- package/src/prompts.js +0 -13
- package/src/scaffold.js +76 -201
- package/src/upgrade.js +16 -33
- package/bundled/adapters/claude/agent-adapter.js +0 -96
- package/bundled/adapters/claude/team-adapter.js +0 -183
- package/bundled/adapters/codebuddy/agent-adapter.js +0 -42
- package/bundled/adapters/codebuddy/team-adapter.js +0 -46
- package/bundled/adapters/codex/agent-adapter.js +0 -38
- package/bundled/adapters/codex/team-adapter.js +0 -37
- package/bundled/agents/prizm-dev-team-dev.md +0 -123
- package/bundled/agents/prizm-dev-team-reviewer.md +0 -113
- package/bundled/dev-pipeline/assets/prizm-dev-team-integration.md +0 -65
- package/bundled/dev-pipeline/templates/bootstrap-tier1.md +0 -436
- package/bundled/dev-pipeline/templates/bootstrap-tier2.md +0 -510
- package/bundled/skills/prizmkit-test/scripts/validate_boundary_report.py +0 -347
- package/bundled/team/prizm-dev-team.json +0 -27
package/bin/create-prizmkit.js
CHANGED
|
@@ -34,8 +34,6 @@ program
|
|
|
34
34
|
.option('--platform <platform>', 'Target platform: codebuddy, claude, codex, or all')
|
|
35
35
|
.option('--runtime <runtime>', 'Runtime assets: python or auto; unix/windows are accepted as legacy aliases for python')
|
|
36
36
|
.option('--skills <suite>', 'Skill suite: core, minimal, or recommended:<type> (frontend/backend/fullstack/library)', 'core')
|
|
37
|
-
.option('--team', 'Enable multi-agent team mode (default: true)')
|
|
38
|
-
.option('--no-team', 'Disable multi-agent team mode')
|
|
39
37
|
.option('--pipeline', 'Install dev-pipeline (default: true)')
|
|
40
38
|
.option('--no-pipeline', 'Disable dev-pipeline')
|
|
41
39
|
.option('--playwright-cli', 'Install playwright-cli browser tool (default: true)')
|
|
@@ -64,7 +62,7 @@ program
|
|
|
64
62
|
.command('uninstall [directory]')
|
|
65
63
|
.description('Remove PrizmKit files from an existing project')
|
|
66
64
|
.option('--dry-run', 'Show what would be removed without deleting')
|
|
67
|
-
.option('--global-team', 'Also remove
|
|
65
|
+
.option('--global-team', 'Also remove legacy global CodeBuddy team config')
|
|
68
66
|
.action(async (directory = '.', options) => {
|
|
69
67
|
try {
|
|
70
68
|
await runClean(directory, options);
|
|
@@ -99,8 +97,6 @@ program
|
|
|
99
97
|
.option('--ai-cli <command>', 'AI CLI executable command (e.g. cbc, claude, codex)')
|
|
100
98
|
.option('--headless-prompt-arg <arg>', 'Prompt injection argv token for a custom AI CLI (e.g. -p or -i)')
|
|
101
99
|
.option('--headless-extra-args <args>', 'Additional headless argv tokens for a custom AI CLI')
|
|
102
|
-
.option('--team', 'Enable multi-agent team mode')
|
|
103
|
-
.option('--no-team', 'Disable multi-agent team mode')
|
|
104
100
|
.option('--pipeline', 'Enable dev-pipeline')
|
|
105
101
|
.option('--no-pipeline', 'Disable dev-pipeline')
|
|
106
102
|
.option('--non-interactive', 'Skip interactive prompts')
|
package/bundled/VERSION.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# dev-pipeline
|
|
2
2
|
|
|
3
|
-
Autonomous development pipeline that drives
|
|
3
|
+
Autonomous development pipeline that drives iterative AI CLI sessions through PrizmKit skills, implementing feature, bugfix, and refactor work from `.prizmkit/plans/*.json` specifications.
|
|
4
4
|
|
|
5
5
|
## Prerequisites
|
|
6
6
|
|
|
@@ -258,12 +258,12 @@ python3 scripts/init-bugfix-pipeline.py \
|
|
|
258
258
|
|
|
259
259
|
---
|
|
260
260
|
|
|
261
|
-
### `scripts/init-
|
|
261
|
+
### `scripts/init-change-artifact.py` — Initialize PrizmKit Directories
|
|
262
262
|
|
|
263
|
-
Creates per-feature directory structure for PrizmKit
|
|
263
|
+
Creates per-feature directory structure for PrizmKit change artifacts.
|
|
264
264
|
|
|
265
265
|
```bash
|
|
266
|
-
python3 scripts/init-
|
|
266
|
+
python3 scripts/init-change-artifact.py \
|
|
267
267
|
--project-root <path> \
|
|
268
268
|
[--feature-id <id>] \
|
|
269
269
|
[--feature-slug <slug>]
|
|
@@ -275,7 +275,7 @@ python3 scripts/init-dev-team.py \
|
|
|
275
275
|
|
|
276
276
|
### `scripts/generate-bootstrap-prompt.py` — Generate Feature Session Prompt
|
|
277
277
|
|
|
278
|
-
Renders a session-specific bootstrap prompt from
|
|
278
|
+
Renders a session-specific bootstrap prompt from modular `templates/sections/` content and `.prizmkit/plans/feature-list.json`.
|
|
279
279
|
|
|
280
280
|
```bash
|
|
281
281
|
python3 scripts/generate-bootstrap-prompt.py \
|
|
@@ -291,13 +291,15 @@ python3 scripts/generate-bootstrap-prompt.py \
|
|
|
291
291
|
[--mode lite|standard|full]
|
|
292
292
|
```
|
|
293
293
|
|
|
294
|
-
**
|
|
294
|
+
**Prompt assembly:**
|
|
295
295
|
|
|
296
|
-
|
|
|
297
|
-
|
|
298
|
-
| `
|
|
299
|
-
|
|
|
300
|
-
|
|
|
296
|
+
| Condition | Prompt Source | Behavior |
|
|
297
|
+
|-----------|---------------|----------|
|
|
298
|
+
| `templates/sections/` exists and no `--template` | Modular sections | Uses the full/tier3-equivalent guidance for every `estimated_complexity` value |
|
|
299
|
+
| Custom `--template <path>` supplied | Caller template | Renders the explicit template with legacy placeholder/conditional support |
|
|
300
|
+
| Sections unavailable and no custom template | `bootstrap-tier3.md`, then `bootstrap-prompt.md` | Monolithic compatibility fallback; never defaults to retired reduced-tier templates |
|
|
301
|
+
|
|
302
|
+
`estimated_complexity` remains in feature metadata and rendered Session Context for planning summaries and compatibility, but it no longer chooses a reduced prompt template.
|
|
301
303
|
|
|
302
304
|
**Output (JSON to stdout):**
|
|
303
305
|
|
|
@@ -307,10 +309,10 @@ python3 scripts/generate-bootstrap-prompt.py \
|
|
|
307
309
|
|
|
308
310
|
The `model` field is extracted from the feature's `"model"` field in .prizmkit/plans/feature-list.json (empty string if not specified). Used by `cli.py feature` to set `--model` on the AI CLI.
|
|
309
311
|
|
|
310
|
-
**Conditional blocks resolved:**
|
|
312
|
+
**Conditional blocks resolved for explicit legacy templates:**
|
|
311
313
|
- `{{IF_RESUME}}` / `{{IF_FRESH_START}}` — Resume vs fresh start
|
|
312
314
|
- `{{IF_INIT_NEEDED}}` / `{{IF_INIT_DONE}}` — PrizmKit init status
|
|
313
|
-
- `{{IF_MODE_LITE}}` / `{{IF_MODE_STANDARD}}` / `{{IF_MODE_FULL}}` —
|
|
315
|
+
- `{{IF_MODE_LITE}}` / `{{IF_MODE_STANDARD}}` / `{{IF_MODE_FULL}}` — Compatibility mode blocks
|
|
314
316
|
|
|
315
317
|
---
|
|
316
318
|
|
|
@@ -686,17 +688,19 @@ cli.py feature run command
|
|
|
686
688
|
+- loop -> next feature
|
|
687
689
|
```
|
|
688
690
|
|
|
689
|
-
###
|
|
691
|
+
### Unified Feature Prompt Execution
|
|
692
|
+
|
|
693
|
+
Feature bootstrap prompts use the same full/tier3-equivalent modular section composition for every feature task. Complexity metadata is still retained for planning, summaries, dependency/status compatibility, and rendered Session Context, but it no longer reduces prompt guidance.
|
|
690
694
|
|
|
691
|
-
|
|
695
|
+
| Feature metadata | Normal prompt source | Execution guidance |
|
|
696
|
+
|------------------|----------------------|--------------------|
|
|
697
|
+
| `estimated_complexity: low` | `templates/sections/` full composition | Main orchestrator builds context, plans, implements directly, runs review/test/browser/commit gates |
|
|
698
|
+
| `estimated_complexity: medium` | `templates/sections/` full composition | Same full guidance |
|
|
699
|
+
| `estimated_complexity: high` / `critical` | `templates/sections/` full composition | Same full guidance |
|
|
692
700
|
|
|
693
|
-
|
|
694
|
-
|------|----------|--------|----------|
|
|
695
|
-
| Tier 1 (lite) | `bootstrap-tier1.md` | Single agent handles everything | Low complexity features |
|
|
696
|
-
| Tier 2 (standard) | `bootstrap-tier2.md` | Orchestrator implements directly + Reviewer gate | Medium/high complexity |
|
|
697
|
-
| Tier 3 (full) | `bootstrap-tier3.md` | Orchestrator implements directly + strongest planning, testing, and Reviewer gates | High/critical complexity |
|
|
701
|
+
Monolithic compatibility fallback uses `bootstrap-tier3.md` before `bootstrap-prompt.md` only when sections are unavailable and no custom `--template` was supplied.
|
|
698
702
|
|
|
699
|
-
**Self-evolve mode:** Uses
|
|
703
|
+
**Self-evolve mode:** Uses the same full feature prompt guidance with additional framework guardrails supplied by the feature context.
|
|
700
704
|
|
|
701
705
|
### Feature Dependency Resolution
|
|
702
706
|
|
|
@@ -718,7 +722,7 @@ Features are executed in dependency order via DAG:
|
|
|
718
722
|
### Heartbeat Output
|
|
719
723
|
|
|
720
724
|
```
|
|
721
|
-
> [HEARTBEAT] 1m30s elapsed | log: 245KB (+12480B) | Creating
|
|
725
|
+
> [HEARTBEAT] 1m30s elapsed | log: 245KB (+12480B) | Creating feature change artifacts...
|
|
722
726
|
> [HEARTBEAT] 2m0s elapsed | log: 389KB (+147456B) | Generating spec.md for feature...
|
|
723
727
|
@ [HEARTBEAT] 2m30s elapsed | log: 389KB (+0B) | (waiting for AI response)
|
|
724
728
|
```
|
|
@@ -863,7 +867,7 @@ cli.py bugfix run command
|
|
|
863
867
|
| +-- utils.py # Shared Python utilities (JSON I/O, logging)
|
|
864
868
|
| +-- init-pipeline.py # Validate .prizmkit/plans/feature-list.json + create .prizmkit/state/features/
|
|
865
869
|
| +-- init-bugfix-pipeline.py # Validate .prizmkit/plans/bug-fix-list.json + create .prizmkit/state/bugfix/
|
|
866
|
-
| +-- init-
|
|
870
|
+
| +-- init-change-artifact.py # Create .prizmkit/specs/{slug}/ directories
|
|
867
871
|
| +-- generate-bootstrap-prompt.py # Render feature session prompt from template
|
|
868
872
|
| +-- generate-bugfix-prompt.py # Render bugfix session prompt from template
|
|
869
873
|
| +-- check-session-status.py # Parse session-status.json outcome
|
|
@@ -873,18 +877,17 @@ cli.py bugfix run command
|
|
|
873
877
|
| +-- parse-stream-progress.py # Real-time stream-json progress parser
|
|
874
878
|
|
|
|
875
879
|
+-- templates/
|
|
876
|
-
| +--
|
|
877
|
-
| +-- bootstrap-
|
|
878
|
-
| +-- bootstrap-
|
|
879
|
-
| +-- bootstrap-prompt.md
|
|
880
|
-
| +--
|
|
881
|
-
| +--
|
|
882
|
-
| +--
|
|
883
|
-
| +-- session-status-schema.json # JSON schema for session-status.json
|
|
880
|
+
| +-- sections/ # Modular feature prompt sections (normal full guidance path)
|
|
881
|
+
| +-- bootstrap-tier3.md # Legacy monolithic full prompt fallback
|
|
882
|
+
| +-- bootstrap-prompt.md # Last-resort monolithic fallback
|
|
883
|
+
| +-- bugfix-bootstrap-prompt.md # Bug-fix session prompt template
|
|
884
|
+
| +-- feature-list-schema.json # JSON schema for .prizmkit/plans/feature-list.json
|
|
885
|
+
| +-- bug-fix-list-schema.json # JSON schema for .prizmkit/plans/bug-fix-list.json
|
|
886
|
+
| +-- session-status-schema.json # JSON schema for session-status.json
|
|
884
887
|
|
|
|
885
888
|
+-- assets/
|
|
886
889
|
| +-- feature-list-example.json # Example feature list
|
|
887
|
-
| +--
|
|
890
|
+
| +-- skill-subagent-integration.md # Pipeline + skill-owned subagent integration docs
|
|
888
891
|
|
|
|
889
892
|
+-- tests/
|
|
890
893
|
| +-- conftest.py # Pytest configuration
|
|
@@ -909,14 +912,14 @@ cli.py bugfix run command
|
|
|
909
912
|
|
|
910
913
|
---
|
|
911
914
|
|
|
912
|
-
##
|
|
915
|
+
## Skill-Owned Subagent References
|
|
913
916
|
|
|
914
|
-
|
|
|
915
|
-
|
|
916
|
-
|
|
|
917
|
-
|
|
|
917
|
+
| Skill | Reference | Purpose |
|
|
918
|
+
|-------|-----------|---------|
|
|
919
|
+
| `/prizmkit-implement` | skill-local implementation-subagent procedure | Optional narrow implementation delegation in the active checkout |
|
|
920
|
+
| `/prizmkit-code-review` | skill-local reviewer prompt | Required independent reviewer loop in the active checkout |
|
|
918
921
|
|
|
919
|
-
|
|
922
|
+
Platform-installed named agents and team topology are not part of the current runtime model. Prompt flows call skills, and the skills own any inline subagent prompts plus active-checkout/no-worktree constraints.
|
|
920
923
|
|
|
921
924
|
---
|
|
922
925
|
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Skill Subagent Integration Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
`dev-pipeline` drives feature, bugfix, and refactor sessions through the unified Python outer loop. Each iteration spawns a new AI CLI session with a bootstrap prompt that makes the main session orchestrator responsible for planning, implementation, review coordination, testing, retrospective, and commit.
|
|
6
|
+
|
|
7
|
+
Implementation and review behavior is owned by skills:
|
|
8
|
+
- `/prizmkit-implement` executes plan tasks directly and may use its local implementation-subagent reference for narrow active-checkout delegation.
|
|
9
|
+
- `/prizmkit-code-review` owns its internal inline reviewer subagent review loop through its local reviewer prompt reference.
|
|
10
|
+
|
|
11
|
+
## Architecture
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
dev-pipeline (outer loop)
|
|
15
|
+
|
|
|
16
|
+
+-- cli.py feature/bugfix/refactor Python runtime CLI — picks next item, spawns CLI
|
|
17
|
+
+-- scripts/ Python state and prompt management scripts
|
|
18
|
+
+-- templates/ Session prompt templates and sections
|
|
19
|
+
|
|
|
20
|
+
+-- [per session] AI CLI
|
|
21
|
+
|
|
|
22
|
+
+-- Context snapshot + specify + plan (orchestrator)
|
|
23
|
+
+-- Local plan/spec review loop inside prizmkit-plan
|
|
24
|
+
+-- Implement through /prizmkit-implement
|
|
25
|
+
+-- Code review through /prizmkit-code-review inline reviewer loop
|
|
26
|
+
+-- Scoped test gate and browser attempt
|
|
27
|
+
+-- Retrospective & commit (orchestrator)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Skill-Owned References
|
|
31
|
+
|
|
32
|
+
| Skill | Reference | Purpose |
|
|
33
|
+
|-------|-----------|---------|
|
|
34
|
+
| `/prizmkit-implement` | skill-local `references/implementation-subagent-procedure.md` | Optional narrow implementation delegation contract |
|
|
35
|
+
| `/prizmkit-code-review` | skill-local `references/reviewer-agent-prompt.md` | Required independent reviewer-loop prompt |
|
|
36
|
+
|
|
37
|
+
The orchestrator role is handled by the main agent directly — no separate platform agent definition or team topology is installed.
|
|
38
|
+
|
|
39
|
+
## Active Checkout Contract
|
|
40
|
+
|
|
41
|
+
Any skill-level implementation or review subagent must run in the expected active git top-level. The prompt contract forbids git worktrees, tool-created worktree isolation, copied repository checkouts, remote isolated checkouts, branch switching, and operating outside the expected active checkout.
|
|
42
|
+
|
|
43
|
+
Pipeline runner-owned linked worktrees are an outer runtime option. They do not authorize skill-level subagents to create or enter their own worktrees.
|
|
44
|
+
|
|
45
|
+
## Pipeline Scripts
|
|
46
|
+
|
|
47
|
+
Located at `.prizmkit/dev-pipeline/scripts/`:
|
|
48
|
+
|
|
49
|
+
| Script | Purpose |
|
|
50
|
+
|--------|---------|
|
|
51
|
+
| `init-pipeline.py` | Initialize feature pipeline state |
|
|
52
|
+
| `init-bugfix-pipeline.py` | Initialize bugfix pipeline state |
|
|
53
|
+
| `init-refactor-pipeline.py` | Initialize refactor pipeline state |
|
|
54
|
+
| `init-change-artifact.py` | Initialize feature change-artifact directories |
|
|
55
|
+
| `generate-bootstrap-prompt.py` | Render feature bootstrap prompt with feature context |
|
|
56
|
+
| `generate-bugfix-prompt.py` | Render bugfix bootstrap prompt with bug context |
|
|
57
|
+
| `generate-refactor-prompt.py` | Render refactor bootstrap prompt with refactor context |
|
|
58
|
+
| `update-feature-status.py` | Update feature status after session |
|
|
59
|
+
| `update-bug-status.py` | Update bug status after session |
|
|
60
|
+
| `update-refactor-status.py` | Update refactor status after session |
|
|
61
|
+
| `check-session-status.py` | Read and validate session-status output |
|
|
62
|
+
| `detect-stuck.py` | Detect stuck or stale pipeline sessions |
|
|
63
|
+
| `parse-stream-progress.py` | Parse AI CLI output stream for progress tracking |
|
|
64
|
+
| `utils.py` | Shared utility functions for pipeline scripts |
|
|
65
|
+
|
|
66
|
+
## Session Lifecycle
|
|
67
|
+
|
|
68
|
+
1. Runtime selects the next eligible item from the plan list.
|
|
69
|
+
2. Prompt generator renders a session prompt and checkpoint file.
|
|
70
|
+
3. AI CLI session executes the generated prompt in the active project checkout or runner-owned worktree.
|
|
71
|
+
4. Session writes status and completion artifacts.
|
|
72
|
+
5. Runtime updates plan-list status and propagates completion notes.
|
|
73
|
+
|
|
74
|
+
## Failure Recovery
|
|
75
|
+
|
|
76
|
+
The generated checkpoint file is the recovery truth. Continuation prompts resume from the first pending or in-progress checkpoint step and prefer synthesized artifacts over full log rereads.
|
|
@@ -269,10 +269,7 @@ def _installed_platform_cli(
|
|
|
269
269
|
paths: RuntimePaths,
|
|
270
270
|
env: Mapping[str, str],
|
|
271
271
|
) -> tuple[str | None, str | None]:
|
|
272
|
-
if (
|
|
273
|
-
(paths.project_root / ".codex" / "agents" / "prizm-dev-team-dev.toml").is_file()
|
|
274
|
-
or (paths.project_root / ".agents" / "skills" / "prizmkit" / "SKILL.md").is_file()
|
|
275
|
-
):
|
|
272
|
+
if (paths.project_root / ".agents" / "skills" / "prizmkit" / "SKILL.md").is_file():
|
|
276
273
|
resolved = _resolve_cli_name("codex", env)
|
|
277
274
|
if resolved:
|
|
278
275
|
return resolved, "installed-platform:codex"
|
|
@@ -280,10 +277,7 @@ def _installed_platform_cli(
|
|
|
280
277
|
resolved = _resolve_cli_name("claude", env)
|
|
281
278
|
if resolved:
|
|
282
279
|
return resolved, "installed-platform:claude"
|
|
283
|
-
if (
|
|
284
|
-
(paths.project_root / ".codebuddy" / "agents" / "prizm-dev-team-dev.md").is_file()
|
|
285
|
-
or (paths.project_root / ".codebuddy" / "skills" / "prizmkit" / "SKILL.md").is_file()
|
|
286
|
-
):
|
|
280
|
+
if (paths.project_root / ".codebuddy" / "skills" / "prizmkit" / "SKILL.md").is_file():
|
|
287
281
|
resolved = _resolve_cli_name("cbc", env)
|
|
288
282
|
if resolved:
|
|
289
283
|
return resolved, "installed-platform:codebuddy"
|
|
@@ -19,7 +19,7 @@ UTILITY_ENTRYPOINTS = {
|
|
|
19
19
|
"generate-recovery-prompt": "scripts/generate-recovery-prompt.py",
|
|
20
20
|
"generate-refactor-prompt": "scripts/generate-refactor-prompt.py",
|
|
21
21
|
"init-bugfix-pipeline": "scripts/init-bugfix-pipeline.py",
|
|
22
|
-
"init-
|
|
22
|
+
"init-change-artifact": "scripts/init-change-artifact.py",
|
|
23
23
|
"init-pipeline": "scripts/init-pipeline.py",
|
|
24
24
|
"init-refactor-pipeline": "scripts/init-refactor-pipeline.py",
|
|
25
25
|
"parse-stream-progress": "scripts/parse-stream-progress.py",
|
|
@@ -41,9 +41,9 @@ class SkillResolution:
|
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
_PLATFORM_MARKERS = {
|
|
44
|
-
"claude": (".claude/
|
|
45
|
-
"codex": (".
|
|
46
|
-
"codebuddy": (".codebuddy/
|
|
44
|
+
"claude": (".claude/commands", ".claude/skills"),
|
|
45
|
+
"codex": (".agents/skills",),
|
|
46
|
+
"codebuddy": (".codebuddy/skills",),
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
|
|
@@ -3,11 +3,12 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import hashlib
|
|
6
|
+
import json
|
|
6
7
|
import subprocess
|
|
7
8
|
from pathlib import Path
|
|
8
9
|
|
|
9
10
|
from .checkpoint_state import load_checkpoint_state
|
|
10
|
-
from .gitops import
|
|
11
|
+
from .gitops import git_status_safe, run_git_command
|
|
11
12
|
from .runner_models import PromptGenerationResult, SessionClassification
|
|
12
13
|
from .sessions import AISessionResult
|
|
13
14
|
|
|
@@ -54,8 +55,6 @@ def classify_session(
|
|
|
54
55
|
reason=f"invalid_workflow_checkpoint:{invalid_checkpoint.error_code}",
|
|
55
56
|
progress_fingerprint=fingerprint,
|
|
56
57
|
)
|
|
57
|
-
has_commit_since_base = _has_commit_since(project_root, base_head)
|
|
58
|
-
|
|
59
58
|
if _is_terminal_success(result) and _has_completed_workflow_artifact(prompt):
|
|
60
59
|
return SessionClassification(
|
|
61
60
|
"success",
|
|
@@ -63,7 +62,7 @@ def classify_session(
|
|
|
63
62
|
progress_fingerprint=fingerprint,
|
|
64
63
|
)
|
|
65
64
|
|
|
66
|
-
if _has_late_runtime_error_after_completion(result, prompt
|
|
65
|
+
if _has_late_runtime_error_after_completion(result, prompt):
|
|
67
66
|
return SessionClassification(
|
|
68
67
|
"success",
|
|
69
68
|
reason="completed_checkpoint_with_late_runtime_error",
|
|
@@ -71,8 +70,6 @@ def classify_session(
|
|
|
71
70
|
)
|
|
72
71
|
|
|
73
72
|
if _is_context_overflow(result):
|
|
74
|
-
if has_commit_since_base:
|
|
75
|
-
return SessionClassification("success", reason="commit_since_base", progress_fingerprint=fingerprint)
|
|
76
73
|
no_progress_count = _next_no_progress_count(previous_fingerprint, fingerprint, previous_no_progress_count)
|
|
77
74
|
if no_progress_count >= 2:
|
|
78
75
|
return SessionClassification(
|
|
@@ -90,19 +87,14 @@ def classify_session(
|
|
|
90
87
|
no_progress_count=no_progress_count,
|
|
91
88
|
)
|
|
92
89
|
|
|
93
|
-
if _is_infra_error(result):
|
|
94
|
-
return SessionClassification("infra_error", reason="ai_runtime_or_provider_error", progress_fingerprint=fingerprint)
|
|
95
90
|
if result.termination_reason == "stale_session":
|
|
96
91
|
return SessionClassification("crashed", reason="stale_session", progress_fingerprint=fingerprint)
|
|
97
92
|
if result.timed_out or result.termination_reason == "timeout":
|
|
98
93
|
return SessionClassification("timed_out", reason="timeout", progress_fingerprint=fingerprint)
|
|
94
|
+
if _is_infra_error(result):
|
|
95
|
+
return SessionClassification("infra_error", reason="ai_runtime_or_provider_error", progress_fingerprint=fingerprint)
|
|
99
96
|
if result.exit_code not in (0, None):
|
|
100
97
|
return SessionClassification("crashed", reason=f"exit_code={result.exit_code}", progress_fingerprint=fingerprint)
|
|
101
|
-
if has_commit_since_base:
|
|
102
|
-
return SessionClassification("success", reason="commit_since_base", progress_fingerprint=fingerprint)
|
|
103
|
-
if _has_workspace_changes(project_root):
|
|
104
|
-
_auto_commit_workspace(project_root)
|
|
105
|
-
return SessionClassification("success", reason="auto_commit_uncommitted_changes", progress_fingerprint=fingerprint)
|
|
106
98
|
return SessionClassification("crashed", reason="no_durable_success", progress_fingerprint=fingerprint)
|
|
107
99
|
|
|
108
100
|
|
|
@@ -138,9 +130,8 @@ def _is_terminal_success(result: AISessionResult) -> bool:
|
|
|
138
130
|
def _has_late_runtime_error_after_completion(
|
|
139
131
|
result: AISessionResult,
|
|
140
132
|
prompt: PromptGenerationResult | None,
|
|
141
|
-
has_commit_since_base: bool,
|
|
142
133
|
) -> bool:
|
|
143
|
-
if not
|
|
134
|
+
if not _has_completed_workflow_artifact(prompt):
|
|
144
135
|
return False
|
|
145
136
|
return _is_context_overflow(result) or _is_infra_error(result)
|
|
146
137
|
|
|
@@ -148,6 +139,8 @@ def _has_late_runtime_error_after_completion(
|
|
|
148
139
|
def _has_completed_workflow_artifact(prompt: PromptGenerationResult | None) -> bool:
|
|
149
140
|
if prompt is None:
|
|
150
141
|
return False
|
|
142
|
+
if _invalid_existing_workflow_checkpoint(prompt) is not None:
|
|
143
|
+
return False
|
|
151
144
|
if prompt.checkpoint_path and prompt.checkpoint_path.is_file():
|
|
152
145
|
state = load_checkpoint_state(prompt.checkpoint_path)
|
|
153
146
|
return state.valid and state.all_completed
|
|
@@ -170,7 +163,21 @@ def has_completed_artifact_path(artifact_path: Path | None) -> bool:
|
|
|
170
163
|
if checkpoint.is_file():
|
|
171
164
|
state = load_checkpoint_state(checkpoint)
|
|
172
165
|
return state.valid and state.all_completed
|
|
173
|
-
return (artifact_path / "completion-summary.json")
|
|
166
|
+
return _has_valid_completion_summary(artifact_path / "completion-summary.json")
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def _has_valid_completion_summary(path: Path) -> bool:
|
|
170
|
+
"""Return whether a completion summary contains usable durable notes."""
|
|
171
|
+
try:
|
|
172
|
+
data = json.loads(path.read_text(encoding="utf-8"))
|
|
173
|
+
except (OSError, UnicodeDecodeError, json.JSONDecodeError):
|
|
174
|
+
return False
|
|
175
|
+
if not isinstance(data, dict):
|
|
176
|
+
return False
|
|
177
|
+
notes = data.get("completion_notes")
|
|
178
|
+
return isinstance(notes, list) and bool(notes) and all(
|
|
179
|
+
isinstance(note, str) and note.strip() for note in notes
|
|
180
|
+
)
|
|
174
181
|
|
|
175
182
|
|
|
176
183
|
def _invalid_existing_workflow_checkpoint(prompt: PromptGenerationResult | None):
|
|
@@ -226,15 +233,6 @@ def _has_commit_since(project_root: Path, base_head: str) -> bool:
|
|
|
226
233
|
return _has_commit_range(project_root, base_head, "HEAD")
|
|
227
234
|
|
|
228
235
|
|
|
229
|
-
def _has_workspace_changes(project_root: Path) -> bool:
|
|
230
|
-
return bool(git_status_safe(project_root).strip())
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
def _auto_commit_workspace(project_root: Path) -> None:
|
|
234
|
-
run_git_command(project_root, ("add", "-A", "--", ".", *HIDDEN_TOOL_WORKTREE_EXCLUDES))
|
|
235
|
-
run_git_command(project_root, ("commit", "--no-verify", "-m", "chore: save runner session changes"))
|
|
236
|
-
|
|
237
|
-
|
|
238
236
|
def _tail(path: Path, max_bytes: int = 8192) -> str:
|
|
239
237
|
try:
|
|
240
238
|
data = path.read_bytes()
|
|
@@ -133,17 +133,23 @@ class SessionPaths:
|
|
|
133
133
|
|
|
134
134
|
@dataclass(frozen=True)
|
|
135
135
|
class ContinuationState:
|
|
136
|
-
"""
|
|
136
|
+
"""Provider-neutral durable handoff inputs for the next AI session."""
|
|
137
137
|
|
|
138
138
|
active: bool = False
|
|
139
139
|
previous_session_id: str = ""
|
|
140
|
+
failure_classification: str = ""
|
|
140
141
|
continuation_count: int = 0
|
|
141
142
|
context_overflow_count: int = 0
|
|
143
|
+
retry_count: int = 0
|
|
144
|
+
infra_error_count: int = 0
|
|
145
|
+
max_retries: int = 0
|
|
146
|
+
max_infra_retries: int = 0
|
|
142
147
|
no_progress_count: int = 0
|
|
148
|
+
progress_fingerprint: Mapping[str, object] = field(default_factory=dict)
|
|
143
149
|
summary_path: Path | None = None
|
|
144
150
|
active_dev_branch: str = ""
|
|
145
151
|
base_branch: str = ""
|
|
146
|
-
fatal_error_code: str = "
|
|
152
|
+
fatal_error_code: str = ""
|
|
147
153
|
|
|
148
154
|
|
|
149
155
|
@dataclass(frozen=True)
|
|
@@ -50,11 +50,18 @@ def generate_prompt(
|
|
|
50
50
|
if invocation.mode:
|
|
51
51
|
command.extend(["--mode", invocation.mode])
|
|
52
52
|
if continuation:
|
|
53
|
-
command.extend(["--continuation-mode", "
|
|
53
|
+
command.extend(["--continuation-mode", "ai_error"])
|
|
54
54
|
for flag, key in (
|
|
55
55
|
("--previous-session-id", "previous_session_id"),
|
|
56
|
+
("--failure-classification", "failure_classification"),
|
|
56
57
|
("--continuation-count", "continuation_count"),
|
|
57
58
|
("--context-overflow-count", "context_overflow_count"),
|
|
59
|
+
("--code-retry-count", "retry_count"),
|
|
60
|
+
("--infra-error-count", "infra_error_count"),
|
|
61
|
+
("--max-code-retries", "max_retries"),
|
|
62
|
+
("--max-infra-retries", "max_infra_retries"),
|
|
63
|
+
("--no-progress-count", "no_progress_count"),
|
|
64
|
+
("--progress-fingerprint", "progress_fingerprint"),
|
|
58
65
|
("--task-type", "task_type"),
|
|
59
66
|
("--active-dev-branch", "active_dev_branch"),
|
|
60
67
|
("--base-branch", "base_branch"),
|
|
@@ -62,6 +69,8 @@ def generate_prompt(
|
|
|
62
69
|
):
|
|
63
70
|
value = continuation.get(key)
|
|
64
71
|
if value not in (None, ""):
|
|
72
|
+
if key == "progress_fingerprint":
|
|
73
|
+
value = json.dumps(value, sort_keys=True)
|
|
65
74
|
command.extend([flag, str(value)])
|
|
66
75
|
|
|
67
76
|
completed = subprocess.run(
|