prizmkit 1.0.45 → 1.0.66
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/claude/agent-adapter.js +2 -1
- package/bundled/adapters/claude/command-adapter.js +3 -3
- package/bundled/agents/prizm-dev-team-dev.md +1 -1
- package/bundled/dev-pipeline/README.md +6 -8
- package/bundled/dev-pipeline/assets/prizm-dev-team-integration.md +24 -19
- package/bundled/dev-pipeline/launch-bugfix-daemon.sh +2 -2
- package/bundled/dev-pipeline/launch-daemon.sh +2 -2
- package/bundled/dev-pipeline/lib/branch.sh +76 -0
- package/bundled/dev-pipeline/run-bugfix.sh +58 -149
- package/bundled/dev-pipeline/run.sh +60 -153
- package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +17 -4
- package/bundled/dev-pipeline/scripts/parse-stream-progress.py +2 -2
- package/bundled/dev-pipeline/templates/bootstrap-tier1.md +16 -27
- package/bundled/dev-pipeline/templates/bootstrap-tier2.md +20 -32
- package/bundled/dev-pipeline/templates/bootstrap-tier3.md +32 -53
- package/bundled/dev-pipeline/templates/bugfix-bootstrap-prompt.md +29 -41
- package/bundled/dev-pipeline/templates/session-status-schema.json +1 -1
- package/bundled/dev-pipeline/tests/conftest.py +19 -126
- package/bundled/dev-pipeline/tests/test_generate_bootstrap_prompt.py +207 -0
- package/bundled/dev-pipeline/tests/test_generate_bugfix_prompt.py +128 -141
- package/bundled/dev-pipeline/tests/test_utils.py +51 -110
- package/bundled/rules/prizm/prizm-commit-workflow.md +3 -3
- package/bundled/skills/_metadata.json +15 -16
- package/bundled/skills/app-planner/SKILL.md +8 -7
- package/bundled/skills/bug-fix-workflow/SKILL.md +171 -0
- package/bundled/skills/bug-planner/SKILL.md +25 -33
- package/bundled/skills/bug-planner/scripts/validate-bug-list.py +156 -0
- package/bundled/skills/bugfix-pipeline-launcher/SKILL.md +5 -7
- package/bundled/skills/dev-pipeline-launcher/SKILL.md +4 -6
- package/bundled/skills/feature-workflow/SKILL.md +25 -42
- package/bundled/skills/prizm-kit/SKILL.md +61 -23
- package/bundled/skills/prizm-kit/assets/{claude-md-template.md → project-memory-template.md} +3 -3
- package/bundled/skills/prizmkit-analyze/SKILL.md +44 -33
- package/bundled/skills/prizmkit-clarify/SKILL.md +40 -30
- package/bundled/skills/prizmkit-code-review/SKILL.md +58 -45
- package/bundled/skills/prizmkit-committer/SKILL.md +30 -68
- package/bundled/skills/prizmkit-implement/SKILL.md +60 -28
- package/bundled/skills/prizmkit-init/SKILL.md +57 -66
- package/bundled/skills/prizmkit-plan/SKILL.md +60 -23
- package/bundled/skills/prizmkit-prizm-docs/SKILL.md +74 -19
- package/bundled/skills/prizmkit-prizm-docs/assets/PRIZM-SPEC.md +23 -23
- package/bundled/skills/prizmkit-retrospective/SKILL.md +142 -65
- package/bundled/skills/prizmkit-retrospective/assets/retrospective-template.md +13 -0
- package/bundled/skills/prizmkit-specify/SKILL.md +69 -15
- package/bundled/skills/refactor-workflow/SKILL.md +116 -52
- package/bundled/team/prizm-dev-team.json +2 -2
- package/package.json +1 -1
- package/src/scaffold.js +4 -4
- package/bundled/dev-pipeline/lib/worktree.sh +0 -164
- package/bundled/dev-pipeline/tests/__init__.py +0 -0
- package/bundled/dev-pipeline/tests/test_check_session.py +0 -131
- package/bundled/dev-pipeline/tests/test_cleanup_logs.py +0 -119
- package/bundled/dev-pipeline/tests/test_detect_stuck.py +0 -207
- package/bundled/dev-pipeline/tests/test_generate_prompt.py +0 -190
- package/bundled/dev-pipeline/tests/test_init_bugfix_pipeline.py +0 -153
- package/bundled/dev-pipeline/tests/test_init_pipeline.py +0 -241
- package/bundled/dev-pipeline/tests/test_update_bug_status.py +0 -142
- package/bundled/dev-pipeline/tests/test_update_feature_status.py +0 -338
- package/bundled/dev-pipeline/tests/test_worktree.py +0 -236
- package/bundled/dev-pipeline/tests/test_worktree_integration.py +0 -796
- package/bundled/skills/prizm-kit/assets/codebuddy-md-template.md +0 -35
- package/bundled/skills/prizm-kit/assets/hooks/prizm-commit-hook.json +0 -15
- package/bundled/skills/prizmkit-summarize/SKILL.md +0 -51
- package/bundled/skills/prizmkit-summarize/assets/registry-template.md +0 -18
- package/bundled/templates/hooks/commit-intent-claude.json +0 -26
- /package/bundled/templates/hooks/{commit-intent-codebuddy.json → commit-intent.json} +0 -0
package/bundled/VERSION.json
CHANGED
|
@@ -65,7 +65,8 @@ export function convertAgent(agentContent, options = {}) {
|
|
|
65
65
|
'run `/$1` command'
|
|
66
66
|
);
|
|
67
67
|
|
|
68
|
-
//
|
|
68
|
+
// Legacy fallback: replace any remaining prizmkit.xxx shorthand with /prizmkit-xxx
|
|
69
|
+
// Core files now use /prizmkit-xxx natively, but this catches any stragglers
|
|
69
70
|
convertedBody = convertedBody.replace(
|
|
70
71
|
/prizmkit\.(\w+)/g,
|
|
71
72
|
(match, sub) => `/prizmkit-${sub.replace(/_/g, '-')}`
|
|
@@ -56,7 +56,6 @@ export function convertSkillToCommand(skillContent, skillName) {
|
|
|
56
56
|
const { frontmatter, body } = parseFrontmatter(skillContent);
|
|
57
57
|
|
|
58
58
|
// Claude Code command frontmatter only uses description
|
|
59
|
-
// Also convert prizmkit.xxx references in the description field
|
|
60
59
|
let desc = frontmatter.description || `PrizmKit ${skillName} command`;
|
|
61
60
|
desc = desc.replace(/prizmkit\.(\w+)/g, (_m, sub) => `/${toClaudePrizmkitCommand(sub)}`);
|
|
62
61
|
|
|
@@ -74,13 +73,14 @@ export function convertSkillToCommand(skillContent, skillName) {
|
|
|
74
73
|
`.claude/command-assets/${skillName}`
|
|
75
74
|
);
|
|
76
75
|
|
|
77
|
-
// Replace "invoke the X skill" or "prizmkit
|
|
76
|
+
// Replace "invoke the X skill" or "/prizmkit-X" patterns with /X slash command (legacy fallback)
|
|
78
77
|
convertedBody = convertedBody.replace(
|
|
79
78
|
/invoke\s+(?:the\s+)?[`"]?(\w[\w-]*)[`"]?\s+skill/gi,
|
|
80
79
|
'run the `/$1` command'
|
|
81
80
|
);
|
|
82
81
|
|
|
83
|
-
//
|
|
82
|
+
// Legacy fallback: replace any remaining prizmkit.xxx with /prizmkit-xxx for Claude Code
|
|
83
|
+
// Core files now use /prizmkit-xxx natively, but this catches any stragglers
|
|
84
84
|
convertedBody = convertedBody.replace(
|
|
85
85
|
/prizmkit\.(\w+)/g,
|
|
86
86
|
(_match, sub) => {
|
|
@@ -47,7 +47,7 @@ skills: prizmkit-implement, prizmkit-prizm-docs
|
|
|
47
47
|
- 不进行集成测试(Reviewer 的职责)
|
|
48
48
|
- **不执行任何 git 操作**(git commit / git add / git reset / git push 均禁止 — 由 Orchestrator 通过 /prizmkit-committer 统一提交)
|
|
49
49
|
- 不修改 `.prizmkit/specs/` 中除 `plan.md`(标记 Tasks section [x])以外的任何文件
|
|
50
|
-
- 不为 bug 修复创建新的文档条目;bug
|
|
50
|
+
- 不为 bug 修复创建新的文档条目;bug 修复是现有功能的完善,应更新原始功能的文档
|
|
51
51
|
- 不使用 TaskCreate/TaskUpdate 创建或修改 Orchestrator 层的任务(Task 工具仅用于内部进度追踪,且任务 ID 在各 agent 子会话中互不共享)
|
|
52
52
|
|
|
53
53
|
### 行为规则
|
|
@@ -85,7 +85,7 @@ When a feature is stuck (e.g. retry count exceeded, bad artifacts), use `reset-f
|
|
|
85
85
|
|
|
86
86
|
What gets cleaned with `--clean`:
|
|
87
87
|
- `state/features/F-XXX/sessions/` — all session logs and prompts
|
|
88
|
-
- `.prizmkit/specs/{feature-slug}/` — spec.md, plan.md
|
|
88
|
+
- `.prizmkit/specs/{feature-slug}/` — spec.md, plan.md (with Tasks section), contracts/
|
|
89
89
|
|
|
90
90
|
What is always reset (with or without `--clean`):
|
|
91
91
|
- `status.json` — status → pending, retry_count → 0
|
|
@@ -221,7 +221,7 @@ run.sh main loop
|
|
|
221
221
|
├─ AI CLI session # cbc --print -y < prompt (CodeBuddy)
|
|
222
222
|
│ │ # claude --print -p "$(cat prompt)" --yes (Claude Code)
|
|
223
223
|
│ └─ prizm-dev-team # Multi-agent team implements the feature
|
|
224
|
-
│ ├─ Orchestrator # Main agent: init, plan, schedule,
|
|
224
|
+
│ ├─ Orchestrator # Main agent: init, plan, schedule, retrospective, commit
|
|
225
225
|
│ ├─ Dev x N # Implementation with TDD
|
|
226
226
|
│ └─ Reviewer # Analyze + code review
|
|
227
227
|
│
|
|
@@ -247,7 +247,7 @@ Each AI CLI session drives the prizm-dev-team through these phases. **All phases
|
|
|
247
247
|
| 5 | Implement | Dev x N | `prizmkit-implement` | Code + tests, plan.md Tasks marked `[x]` |
|
|
248
248
|
| 6 | Review | Reviewer | `prizmkit-code-review` | Integration tests, review report |
|
|
249
249
|
| 7 | Fix Loop | Dev | — | Max 3 rounds of fixes |
|
|
250
|
-
| 8 |
|
|
250
|
+
| 8 | Retrospective & Commit | Orchestrator | `prizmkit-retrospective`, `prizmkit-committer` | .prizm-docs/ synced + enriched, git commit |
|
|
251
251
|
|
|
252
252
|
### Feature Dependency Resolution
|
|
253
253
|
|
|
@@ -383,15 +383,13 @@ Each feature generates artifacts in a dedicated subdirectory under `.prizmkit/sp
|
|
|
383
383
|
.prizmkit/
|
|
384
384
|
├── config.json # PrizmKit configuration
|
|
385
385
|
└── specs/
|
|
386
|
-
├── REGISTRY.md # Feature registry (Phase 9 appends here)
|
|
387
386
|
├── 001-project-infrastructure-setup/
|
|
388
387
|
│ ├── spec.md # Phase 1: Feature specification
|
|
389
388
|
│ ├── checklists/
|
|
390
389
|
│ │ └── requirements.md # Phase 1: Spec quality checklist
|
|
391
390
|
│ ├── plan.md # Phase 2: Implementation plan
|
|
392
391
|
│ ├── data-model.md # Phase 2: Data model (if applicable)
|
|
393
|
-
│
|
|
394
|
-
│ └── tasks.md # Phase 3: Task breakdown
|
|
392
|
+
│ └── contracts/ # Phase 2: API contracts (if applicable)
|
|
395
393
|
├── 002-core-encryption-vault/
|
|
396
394
|
│ └── ...
|
|
397
395
|
└── ...
|
|
@@ -438,7 +436,7 @@ The AI CLI session exited without producing a `session-status.json`. This typica
|
|
|
438
436
|
|
|
439
437
|
### .prizmkit/specs/ is empty after feature completion
|
|
440
438
|
|
|
441
|
-
The session skipped the PrizmKit artifact generation phases (spec.md, plan.md
|
|
439
|
+
The session skipped the PrizmKit artifact generation phases (spec.md, plan.md). This can happen if:
|
|
442
440
|
|
|
443
441
|
1. **Agent definitions not found**: Check that agent definition files exist
|
|
444
442
|
- CodeBuddy: `.codebuddy/agents/prizm-dev-team-*.md`
|
|
@@ -574,7 +572,7 @@ dev-pipeline/bugfix-state/ # Runtime state (gitignored)
|
|
|
574
572
|
| Ordering | Dependencies DAG → priority | N/A (single refactor per session) | Severity → priority (no dependencies) |
|
|
575
573
|
| Phases | 10-phase (specify → plan → tasks → implement → review) | 6-phase (analyze → plan → tasks → implement → review → commit) | 5-phase (triage → reproduce → fix → verify → commit) |
|
|
576
574
|
| Agents | Orchestrator + Dev + Reviewer | Dev + Reviewer only | Dev + Reviewer only |
|
|
577
|
-
| Artifacts | spec.md, plan.md
|
|
575
|
+
| Artifacts | spec.md, plan.md (with Tasks section) | refactor-analysis.md, plan.md (with Tasks section) | fix-plan.md, fix-report.md only |
|
|
578
576
|
| Commit prefix | `feat(<scope>):` | `refactor(<scope>):` | `fix(<scope>):` |
|
|
579
577
|
| Scope Guard | N/A | ✅ (behavior change → STOP) | N/A |
|
|
580
578
|
| Test Strategy | TDD per task | Full suite after EVERY task | Reproduction test |
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Overview
|
|
4
4
|
|
|
5
|
-
dev-pipeline drives the prizm-dev-team multi-agent team through an outer shell loop. Each iteration spawns a new
|
|
5
|
+
dev-pipeline drives the prizm-dev-team multi-agent team through an outer shell loop. Each iteration spawns a new AI CLI session with a bootstrap prompt that instructs the agent to create and orchestrate the team for one feature.
|
|
6
6
|
|
|
7
7
|
## Architecture
|
|
8
8
|
|
|
@@ -16,11 +16,11 @@ dev-pipeline (outer loop)
|
|
|
16
16
|
└── [per session] AI CLI
|
|
17
17
|
│
|
|
18
18
|
├── Phase 0: Init (Orchestrator)
|
|
19
|
-
├── Phase 1-2: Context snapshot +
|
|
20
|
-
├── Phase 3
|
|
21
|
-
├── Phase
|
|
22
|
-
├── Phase 6: Review (Reviewer agent)
|
|
23
|
-
└── Phase 7:
|
|
19
|
+
├── Phase 1-2: Context snapshot + Specify + Plan (Orchestrator)
|
|
20
|
+
├── Phase 3: Analyze (Reviewer agent) [tier2] / Phase 4: Analyze [tier3]
|
|
21
|
+
├── Phase 4: Implement (Dev agent) [tier2] / Phase 5: Implement [tier3]
|
|
22
|
+
├── Phase 4.5/6: Review (Reviewer agent)
|
|
23
|
+
└── Phase 5/7: Retrospective & Commit (Orchestrator)
|
|
24
24
|
│
|
|
25
25
|
└── Write session-status.json → exit
|
|
26
26
|
```
|
|
@@ -34,17 +34,24 @@ dev-pipeline (outer loop)
|
|
|
34
34
|
|
|
35
35
|
Note: The Orchestrator role is handled by the main agent (session orchestrator) directly — no separate agent definition needed.
|
|
36
36
|
|
|
37
|
-
##
|
|
37
|
+
## Pipeline Scripts
|
|
38
38
|
|
|
39
39
|
Located at `dev-pipeline/scripts/`:
|
|
40
40
|
|
|
41
|
-
| Script |
|
|
42
|
-
|
|
43
|
-
| `init-dev-team.py` |
|
|
44
|
-
| `
|
|
45
|
-
| `
|
|
46
|
-
| `
|
|
47
|
-
| `
|
|
41
|
+
| Script | Purpose |
|
|
42
|
+
|--------|---------|
|
|
43
|
+
| `init-dev-team.py` | Initialize `.dev-team/` + `.prizmkit/` directories |
|
|
44
|
+
| `init-pipeline.py` | Initialize pipeline state directories and config |
|
|
45
|
+
| `init-bugfix-pipeline.py` | Initialize bugfix pipeline state |
|
|
46
|
+
| `generate-bootstrap-prompt.py` | Render tier-specific bootstrap prompt with feature context |
|
|
47
|
+
| `generate-bugfix-prompt.py` | Render bugfix bootstrap prompt with bug context |
|
|
48
|
+
| `update-feature-status.py` | Update feature status in feature-list.json after session |
|
|
49
|
+
| `update-bug-status.py` | Update bug status in bug-fix-list.json after session |
|
|
50
|
+
| `check-session-status.py` | Read and validate session-status.json output |
|
|
51
|
+
| `detect-stuck.py` | Detect stuck/hung pipeline sessions via heartbeat |
|
|
52
|
+
| `parse-stream-progress.py` | Parse AI CLI output stream for progress tracking |
|
|
53
|
+
| `cleanup-logs.py` | Clean up old pipeline logs and state files |
|
|
54
|
+
| `utils.py` | Shared utility functions for pipeline scripts |
|
|
48
55
|
|
|
49
56
|
## Artifact Mapping
|
|
50
57
|
|
|
@@ -54,9 +61,8 @@ Located at `dev-pipeline/scripts/`:
|
|
|
54
61
|
|-------|------|---------|
|
|
55
62
|
| 1 | `specs/spec.md` | Feature specification (WHAT/WHY) |
|
|
56
63
|
| 2 | `plans/plan.md` | Technical plan (architecture, API, tests) |
|
|
57
|
-
| 3 | `tasks/tasks.md` | Executable task list with `[ ]` / `[x]` |
|
|
64
|
+
| 3 | `tasks/tasks.md` | Executable task list with `[ ]` / `[x]` (legacy — now part of plan.md Tasks section) |
|
|
58
65
|
| 4 | `analysis/analyze-report.md` | Consistency analysis |
|
|
59
|
-
| 9 | `specs/REGISTRY.md` | Completed features archive |
|
|
60
66
|
|
|
61
67
|
### Dev-Team Artifacts (.dev-team/)
|
|
62
68
|
|
|
@@ -78,7 +84,7 @@ Located at `dev-pipeline/scripts/`:
|
|
|
78
84
|
The bootstrap prompt instructs the agent to:
|
|
79
85
|
- Execute phases directly as the session orchestrator
|
|
80
86
|
- Spawn Dev and Reviewer agents as subagents for implementation and review phases
|
|
81
|
-
- The orchestrator handles context building, planning,
|
|
87
|
+
- The orchestrator handles context building, planning, retrospective, and commit phases directly
|
|
82
88
|
|
|
83
89
|
### 2. Pipeline Execution
|
|
84
90
|
|
|
@@ -103,8 +109,7 @@ The agent MUST write `session-status.json` before exiting:
|
|
|
103
109
|
"resume_from_phase": null,
|
|
104
110
|
"artifacts": {
|
|
105
111
|
"spec_path": ".prizmkit/specs/spec.md",
|
|
106
|
-
"plan_path": ".prizmkit/plans/plan.md"
|
|
107
|
-
"tasks_path": ".prizmkit/tasks/tasks.md"
|
|
112
|
+
"plan_path": ".prizmkit/plans/plan.md"
|
|
108
113
|
},
|
|
109
114
|
"timestamp": "2026-03-04T11:30:00Z"
|
|
110
115
|
}
|
|
@@ -436,8 +436,8 @@ Environment Variables (pass via --env):
|
|
|
436
436
|
SESSION_TIMEOUT Session timeout in seconds (default: 0 = no limit)
|
|
437
437
|
VERBOSE Set to 1 for verbose AI CLI output
|
|
438
438
|
HEARTBEAT_INTERVAL Heartbeat log interval in seconds (default: 30)
|
|
439
|
-
|
|
440
|
-
AUTO_PUSH Auto-push to remote after successful
|
|
439
|
+
DEV_BRANCH Custom dev branch name (default: auto-generated)
|
|
440
|
+
AUTO_PUSH Auto-push to remote after successful bug fix (default: 0, set 1 to enable)
|
|
441
441
|
HELP
|
|
442
442
|
}
|
|
443
443
|
|
|
@@ -576,8 +576,8 @@ Environment Variables (pass via --env):
|
|
|
576
576
|
SESSION_TIMEOUT Session timeout in seconds (default: 0 = no limit)
|
|
577
577
|
VERBOSE Set to 1 for verbose AI CLI output
|
|
578
578
|
HEARTBEAT_INTERVAL Heartbeat log interval in seconds (default: 30)
|
|
579
|
-
|
|
580
|
-
AUTO_PUSH Auto-push to remote after successful
|
|
579
|
+
DEV_BRANCH Custom dev branch name (default: auto-generated)
|
|
580
|
+
AUTO_PUSH Auto-push to remote after successful feature (default: 0, set 1 to enable)
|
|
581
581
|
HELP
|
|
582
582
|
}
|
|
583
583
|
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ============================================================
|
|
3
|
+
# dev-pipeline/lib/branch.sh - Git Branch Lifecycle Library
|
|
4
|
+
#
|
|
5
|
+
# Shared by run.sh and run-bugfix.sh for branch-based serial
|
|
6
|
+
# development. Each pipeline run creates a dev branch and all
|
|
7
|
+
# features/bugs commit directly on it in sequence.
|
|
8
|
+
#
|
|
9
|
+
# Functions:
|
|
10
|
+
# branch_create — Create and checkout a new branch
|
|
11
|
+
# branch_return — Checkout back to original branch
|
|
12
|
+
#
|
|
13
|
+
# Environment:
|
|
14
|
+
# DEV_BRANCH — Optional custom branch name override
|
|
15
|
+
# AUTO_PUSH — Set to 1 to auto-push after successful feature
|
|
16
|
+
# ============================================================
|
|
17
|
+
|
|
18
|
+
# branch_create <project_root> <branch_name> <source_branch>
|
|
19
|
+
#
|
|
20
|
+
# Creates a new branch from source_branch and checks it out.
|
|
21
|
+
# If the branch already exists, checks it out instead.
|
|
22
|
+
#
|
|
23
|
+
# Returns 0 on success, 1 on failure.
|
|
24
|
+
branch_create() {
|
|
25
|
+
local project_root="$1"
|
|
26
|
+
local branch_name="$2"
|
|
27
|
+
local source_branch="$3"
|
|
28
|
+
|
|
29
|
+
# Check if branch already exists
|
|
30
|
+
if git -C "$project_root" rev-parse --verify "$branch_name" >/dev/null 2>&1; then
|
|
31
|
+
log_info "Branch already exists: $branch_name — checking out"
|
|
32
|
+
if ! git -C "$project_root" checkout "$branch_name" 2>/dev/null; then
|
|
33
|
+
log_error "Failed to checkout existing branch: $branch_name"
|
|
34
|
+
return 1
|
|
35
|
+
fi
|
|
36
|
+
return 0
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
# Create and checkout new branch
|
|
40
|
+
if ! git -C "$project_root" checkout -b "$branch_name" "$source_branch" 2>/dev/null; then
|
|
41
|
+
log_error "Failed to create branch: $branch_name from $source_branch"
|
|
42
|
+
return 1
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
log_info "Created and checked out branch: $branch_name (from $source_branch)"
|
|
46
|
+
return 0
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
# branch_return <project_root> <original_branch>
|
|
50
|
+
#
|
|
51
|
+
# Checks out the original branch after pipeline completes.
|
|
52
|
+
# Safe to call even if already on the original branch.
|
|
53
|
+
#
|
|
54
|
+
# Returns 0 on success, 1 on failure.
|
|
55
|
+
branch_return() {
|
|
56
|
+
local project_root="$1"
|
|
57
|
+
local original_branch="$2"
|
|
58
|
+
|
|
59
|
+
local current_branch
|
|
60
|
+
current_branch=$(git -C "$project_root" rev-parse --abbrev-ref HEAD 2>/dev/null) || {
|
|
61
|
+
log_error "Failed to determine current branch"
|
|
62
|
+
return 1
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if [[ "$current_branch" == "$original_branch" ]]; then
|
|
66
|
+
return 0
|
|
67
|
+
fi
|
|
68
|
+
|
|
69
|
+
if ! git -C "$project_root" checkout "$original_branch" 2>/dev/null; then
|
|
70
|
+
log_error "Failed to checkout original branch: $original_branch"
|
|
71
|
+
return 1
|
|
72
|
+
fi
|
|
73
|
+
|
|
74
|
+
log_info "Returned to branch: $original_branch"
|
|
75
|
+
return 0
|
|
76
|
+
}
|
|
@@ -25,8 +25,8 @@ set -euo pipefail
|
|
|
25
25
|
# LOG_CLEANUP_ENABLED Run periodic log cleanup (default: 1)
|
|
26
26
|
# LOG_RETENTION_DAYS Delete logs older than N days (default: 14)
|
|
27
27
|
# LOG_MAX_TOTAL_MB Keep total logs under N MB via oldest-first cleanup (default: 1024)
|
|
28
|
-
#
|
|
29
|
-
# AUTO_PUSH Auto-push to remote after successful
|
|
28
|
+
# DEV_BRANCH Custom dev branch name (default: auto-generated bugfix/pipeline-{run_id})
|
|
29
|
+
# AUTO_PUSH Auto-push to remote after successful bug fix (default: 0). Set to 1 to enable.
|
|
30
30
|
# ============================================================
|
|
31
31
|
|
|
32
32
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
@@ -42,7 +42,7 @@ LOG_CLEANUP_ENABLED=${LOG_CLEANUP_ENABLED:-1}
|
|
|
42
42
|
LOG_RETENTION_DAYS=${LOG_RETENTION_DAYS:-14}
|
|
43
43
|
LOG_MAX_TOTAL_MB=${LOG_MAX_TOTAL_MB:-1024}
|
|
44
44
|
VERBOSE=${VERBOSE:-0}
|
|
45
|
-
|
|
45
|
+
DEV_BRANCH=${DEV_BRANCH:-""}
|
|
46
46
|
AUTO_PUSH=${AUTO_PUSH:-0}
|
|
47
47
|
|
|
48
48
|
# Source shared common helpers (CLI/platform detection + logs + deps)
|
|
@@ -52,8 +52,8 @@ prizm_detect_cli_and_platform
|
|
|
52
52
|
# Source shared heartbeat library
|
|
53
53
|
source "$SCRIPT_DIR/lib/heartbeat.sh"
|
|
54
54
|
|
|
55
|
-
# Source shared
|
|
56
|
-
source "$SCRIPT_DIR/lib/
|
|
55
|
+
# Source shared branch library
|
|
56
|
+
source "$SCRIPT_DIR/lib/branch.sh"
|
|
57
57
|
|
|
58
58
|
# Detect stream-json support
|
|
59
59
|
detect_stream_json_support "$CLI_CMD"
|
|
@@ -61,9 +61,9 @@ detect_stream_json_support "$CLI_CMD"
|
|
|
61
61
|
# Bug list path (set in main, used by cleanup trap)
|
|
62
62
|
BUG_LIST=""
|
|
63
63
|
|
|
64
|
-
#
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
# Branch tracking (for cleanup on interrupt)
|
|
65
|
+
_ORIGINAL_BRANCH=""
|
|
66
|
+
_DEV_BRANCH_NAME=""
|
|
67
67
|
|
|
68
68
|
# ============================================================
|
|
69
69
|
# Shared: Spawn AI CLI session and wait for result
|
|
@@ -76,7 +76,6 @@ spawn_and_wait_session() {
|
|
|
76
76
|
local bootstrap_prompt="$4"
|
|
77
77
|
local session_dir="$5"
|
|
78
78
|
local max_retries="$6"
|
|
79
|
-
local worktree_path="${7:-}"
|
|
80
79
|
|
|
81
80
|
local session_log="$session_dir/logs/session.log"
|
|
82
81
|
local progress_json="$session_dir/logs/progress.json"
|
|
@@ -100,14 +99,6 @@ spawn_and_wait_session() {
|
|
|
100
99
|
# within an existing Claude Code session (e.g. via launch-bugfix-daemon.sh).
|
|
101
100
|
unset CLAUDECODE 2>/dev/null || true
|
|
102
101
|
|
|
103
|
-
# If worktree path is provided, cd into it for the AI CLI session
|
|
104
|
-
local _saved_pwd=""
|
|
105
|
-
if [[ -n "$worktree_path" && -d "$worktree_path" ]]; then
|
|
106
|
-
_saved_pwd="$(pwd)"
|
|
107
|
-
cd "$worktree_path"
|
|
108
|
-
log_info "Running AI CLI in worktree: $worktree_path"
|
|
109
|
-
fi
|
|
110
|
-
|
|
111
102
|
case "$CLI_CMD" in
|
|
112
103
|
*claude*)
|
|
113
104
|
# Claude Code: prompt via -p, --dangerously-skip-permissions for auto-accept
|
|
@@ -133,11 +124,6 @@ spawn_and_wait_session() {
|
|
|
133
124
|
esac
|
|
134
125
|
local cli_pid=$!
|
|
135
126
|
|
|
136
|
-
# Restore original directory if we changed it
|
|
137
|
-
if [[ -n "$_saved_pwd" ]]; then
|
|
138
|
-
cd "$_saved_pwd"
|
|
139
|
-
fi
|
|
140
|
-
|
|
141
127
|
# Start progress parser (no-op if stream-json not supported)
|
|
142
128
|
start_progress_parser "$session_log" "$progress_json" "$SCRIPTS_DIR"
|
|
143
129
|
local parser_pid="${_PARSER_PID:-}"
|
|
@@ -231,13 +217,10 @@ cleanup() {
|
|
|
231
217
|
# Kill all child processes (claude-internal, heartbeat, progress parser, etc.)
|
|
232
218
|
kill 0 2>/dev/null || true
|
|
233
219
|
|
|
234
|
-
#
|
|
235
|
-
if [[ -n "$
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
worktree_cleanup "$_project_root" "$_ACTIVE_WORKTREE_PATH" "$_ACTIVE_WORKTREE_BRANCH"
|
|
239
|
-
_ACTIVE_WORKTREE_PATH=""
|
|
240
|
-
_ACTIVE_WORKTREE_BRANCH=""
|
|
220
|
+
# Log current branch info for recovery
|
|
221
|
+
if [[ -n "$_DEV_BRANCH_NAME" ]]; then
|
|
222
|
+
log_info "Development was on branch: $_DEV_BRANCH_NAME"
|
|
223
|
+
log_info "Original branch was: $_ORIGINAL_BRANCH"
|
|
241
224
|
fi
|
|
242
225
|
|
|
243
226
|
if [[ -n "$BUG_LIST" && -f "$BUG_LIST" ]]; then
|
|
@@ -420,13 +403,9 @@ sys.exit(1)
|
|
|
420
403
|
echo ""
|
|
421
404
|
log_warn "Interrupted. Killing session..."
|
|
422
405
|
kill 0 2>/dev/null || true
|
|
423
|
-
#
|
|
424
|
-
if [[ -n "$
|
|
425
|
-
|
|
426
|
-
_proj_root="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
427
|
-
worktree_cleanup "$_proj_root" "$_ACTIVE_WORKTREE_PATH" "$_ACTIVE_WORKTREE_BRANCH"
|
|
428
|
-
_ACTIVE_WORKTREE_PATH=""
|
|
429
|
-
_ACTIVE_WORKTREE_BRANCH=""
|
|
406
|
+
# Log current branch info
|
|
407
|
+
if [[ -n "$_DEV_BRANCH_NAME" ]]; then
|
|
408
|
+
log_info "Development was on branch: $_DEV_BRANCH_NAME"
|
|
430
409
|
fi
|
|
431
410
|
log_info "Session log: $session_dir/logs/session.log"
|
|
432
411
|
exit 130
|
|
@@ -435,63 +414,31 @@ sys.exit(1)
|
|
|
435
414
|
|
|
436
415
|
_SPAWN_RESULT=""
|
|
437
416
|
|
|
438
|
-
#
|
|
439
|
-
local
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
_WORKTREE_PATH=""
|
|
451
|
-
_WORKTREE_BRANCH=""
|
|
452
|
-
if worktree_create "$_proj_root" "$_wt_base" "$session_id" "$_source_branch"; then
|
|
453
|
-
_wt_path="$_WORKTREE_PATH"
|
|
454
|
-
_wt_branch="$_WORKTREE_BRANCH"
|
|
455
|
-
_ACTIVE_WORKTREE_PATH="$_wt_path"
|
|
456
|
-
_ACTIVE_WORKTREE_BRANCH="$_wt_branch"
|
|
457
|
-
else
|
|
458
|
-
log_warn "Failed to create worktree; running session in main working tree"
|
|
459
|
-
fi
|
|
417
|
+
# Branch lifecycle: create and checkout bugfix branch
|
|
418
|
+
local _proj_root
|
|
419
|
+
_proj_root="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
420
|
+
local _source_branch
|
|
421
|
+
_source_branch=$(git -C "$_proj_root" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "main")
|
|
422
|
+
_ORIGINAL_BRANCH="$_source_branch"
|
|
423
|
+
|
|
424
|
+
local _branch_name="${DEV_BRANCH:-bugfix/${bug_id}-$(date +%s)}"
|
|
425
|
+
if branch_create "$_proj_root" "$_branch_name" "$_source_branch"; then
|
|
426
|
+
_DEV_BRANCH_NAME="$_branch_name"
|
|
427
|
+
else
|
|
428
|
+
log_warn "Failed to create branch; running session on current branch"
|
|
460
429
|
fi
|
|
461
430
|
|
|
462
431
|
spawn_and_wait_session \
|
|
463
432
|
"$bug_id" "$bug_list" "$session_id" \
|
|
464
|
-
"$bootstrap_prompt" "$session_dir" 999
|
|
433
|
+
"$bootstrap_prompt" "$session_dir" 999
|
|
465
434
|
local session_status="$_SPAWN_RESULT"
|
|
466
435
|
|
|
467
|
-
#
|
|
468
|
-
if [[
|
|
436
|
+
# Auto-push after successful session
|
|
437
|
+
if [[ "$session_status" == "success" && "$AUTO_PUSH" == "1" ]]; then
|
|
469
438
|
local _proj_root
|
|
470
439
|
_proj_root="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
if [[ "$session_status" == "success" ]]; then
|
|
475
|
-
_MERGE_RESULT=""
|
|
476
|
-
worktree_merge "$_proj_root" "$_wt_branch" "$_target_branch" "$bug_id" "$session_id" || true
|
|
477
|
-
if [[ "$_MERGE_RESULT" == "success" ]]; then
|
|
478
|
-
if [[ "$AUTO_PUSH" == "1" ]]; then
|
|
479
|
-
log_info "AUTO_PUSH enabled; pushing to remote..."
|
|
480
|
-
git -C "$_proj_root" push 2>/dev/null || log_warn "Auto-push failed"
|
|
481
|
-
fi
|
|
482
|
-
worktree_cleanup "$_proj_root" "$_wt_path" "$_wt_branch"
|
|
483
|
-
elif [[ "$_MERGE_RESULT" == "conflict" ]]; then
|
|
484
|
-
session_status="merge_conflict"
|
|
485
|
-
_SPAWN_RESULT="merge_conflict"
|
|
486
|
-
log_warn "Worktree branch preserved for manual conflict resolution: $_wt_branch"
|
|
487
|
-
else
|
|
488
|
-
worktree_cleanup "$_proj_root" "$_wt_path" "$_wt_branch"
|
|
489
|
-
fi
|
|
490
|
-
else
|
|
491
|
-
worktree_cleanup "$_proj_root" "$_wt_path" "$_wt_branch"
|
|
492
|
-
fi
|
|
493
|
-
_ACTIVE_WORKTREE_PATH=""
|
|
494
|
-
_ACTIVE_WORKTREE_BRANCH=""
|
|
440
|
+
log_info "AUTO_PUSH enabled; pushing to remote..."
|
|
441
|
+
git -C "$_proj_root" push -u origin "$_DEV_BRANCH_NAME" 2>/dev/null || log_warn "Auto-push failed"
|
|
495
442
|
fi
|
|
496
443
|
|
|
497
444
|
echo ""
|
|
@@ -529,13 +476,6 @@ main() {
|
|
|
529
476
|
check_dependencies
|
|
530
477
|
run_log_cleanup
|
|
531
478
|
|
|
532
|
-
# Prune stale worktree references at startup
|
|
533
|
-
if [[ "$USE_WORKTREE" == "1" ]]; then
|
|
534
|
-
local _prune_root
|
|
535
|
-
_prune_root="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
536
|
-
worktree_prune_stale "$_prune_root"
|
|
537
|
-
fi
|
|
538
|
-
|
|
539
479
|
# Initialize pipeline state if needed
|
|
540
480
|
if [[ ! -f "$STATE_DIR/pipeline.json" ]]; then
|
|
541
481
|
log_info "Initializing bugfix pipeline state..."
|
|
@@ -576,6 +516,23 @@ main() {
|
|
|
576
516
|
echo -e "${BOLD}════════════════════════════════════════════════════${NC}"
|
|
577
517
|
echo ""
|
|
578
518
|
|
|
519
|
+
# Branch lifecycle: create bugfix branch for this pipeline run
|
|
520
|
+
local _proj_root
|
|
521
|
+
_proj_root="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
522
|
+
local _source_branch
|
|
523
|
+
_source_branch=$(git -C "$_proj_root" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "main")
|
|
524
|
+
_ORIGINAL_BRANCH="$_source_branch"
|
|
525
|
+
|
|
526
|
+
local run_id_for_branch
|
|
527
|
+
run_id_for_branch=$(jq -r '.run_id' "$STATE_DIR/pipeline.json" 2>/dev/null || echo "$$")
|
|
528
|
+
local _branch_name="${DEV_BRANCH:-bugfix/pipeline-${run_id_for_branch}}"
|
|
529
|
+
if branch_create "$_proj_root" "$_branch_name" "$_source_branch"; then
|
|
530
|
+
_DEV_BRANCH_NAME="$_branch_name"
|
|
531
|
+
log_info "Dev branch: $_branch_name"
|
|
532
|
+
else
|
|
533
|
+
log_warn "Failed to create bugfix branch; running on current branch: $_source_branch"
|
|
534
|
+
fi
|
|
535
|
+
|
|
579
536
|
local session_count=0
|
|
580
537
|
|
|
581
538
|
while true; do
|
|
@@ -592,6 +549,10 @@ main() {
|
|
|
592
549
|
log_success "════════════════════════════════════════════════════"
|
|
593
550
|
log_success " All bugs processed! Bug fix pipeline finished."
|
|
594
551
|
log_success " Total sessions: $session_count"
|
|
552
|
+
if [[ -n "$_DEV_BRANCH_NAME" ]]; then
|
|
553
|
+
log_success " Dev branch: $_DEV_BRANCH_NAME"
|
|
554
|
+
log_success " Merge with: git checkout $_ORIGINAL_BRANCH && git merge $_DEV_BRANCH_NAME"
|
|
555
|
+
fi
|
|
595
556
|
log_success "════════════════════════════════════════════════════"
|
|
596
557
|
rm -f "$STATE_DIR/current-session.json"
|
|
597
558
|
break
|
|
@@ -662,68 +623,16 @@ os.replace(tmp, target)
|
|
|
662
623
|
log_info "Spawning AI CLI session: $session_id"
|
|
663
624
|
_SPAWN_RESULT=""
|
|
664
625
|
|
|
665
|
-
# Worktree lifecycle: create worktree before session if enabled
|
|
666
|
-
local _wt_path="" _wt_branch=""
|
|
667
|
-
if [[ "$USE_WORKTREE" == "1" ]]; then
|
|
668
|
-
local _proj_root
|
|
669
|
-
_proj_root="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
670
|
-
local _wt_base="$STATE_DIR/worktrees"
|
|
671
|
-
local _source_branch
|
|
672
|
-
_source_branch=$(git -C "$_proj_root" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "main")
|
|
673
|
-
|
|
674
|
-
_WORKTREE_PATH=""
|
|
675
|
-
_WORKTREE_BRANCH=""
|
|
676
|
-
if worktree_create "$_proj_root" "$_wt_base" "$session_id" "$_source_branch"; then
|
|
677
|
-
_wt_path="$_WORKTREE_PATH"
|
|
678
|
-
_wt_branch="$_WORKTREE_BRANCH"
|
|
679
|
-
_ACTIVE_WORKTREE_PATH="$_wt_path"
|
|
680
|
-
_ACTIVE_WORKTREE_BRANCH="$_wt_branch"
|
|
681
|
-
else
|
|
682
|
-
log_warn "Failed to create worktree; running session in main working tree"
|
|
683
|
-
fi
|
|
684
|
-
fi
|
|
685
|
-
|
|
686
626
|
spawn_and_wait_session \
|
|
687
627
|
"$bug_id" "$bug_list" "$session_id" \
|
|
688
|
-
"$bootstrap_prompt" "$session_dir" "$MAX_RETRIES"
|
|
628
|
+
"$bootstrap_prompt" "$session_dir" "$MAX_RETRIES"
|
|
689
629
|
|
|
690
|
-
#
|
|
691
|
-
if [[
|
|
630
|
+
# Auto-push after successful session
|
|
631
|
+
if [[ "$_SPAWN_RESULT" == "success" && "$AUTO_PUSH" == "1" ]]; then
|
|
692
632
|
local _proj_root
|
|
693
633
|
_proj_root="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
local _session_status="$_SPAWN_RESULT"
|
|
697
|
-
|
|
698
|
-
if [[ "$_session_status" == "success" ]]; then
|
|
699
|
-
_MERGE_RESULT=""
|
|
700
|
-
worktree_merge "$_proj_root" "$_wt_branch" "$_target_branch" "$bug_id" "$session_id" || true
|
|
701
|
-
if [[ "$_MERGE_RESULT" == "success" ]]; then
|
|
702
|
-
if [[ "$AUTO_PUSH" == "1" ]]; then
|
|
703
|
-
log_info "AUTO_PUSH enabled; pushing to remote..."
|
|
704
|
-
git -C "$_proj_root" push 2>/dev/null || log_warn "Auto-push failed"
|
|
705
|
-
fi
|
|
706
|
-
worktree_cleanup "$_proj_root" "$_wt_path" "$_wt_branch"
|
|
707
|
-
elif [[ "$_MERGE_RESULT" == "conflict" ]]; then
|
|
708
|
-
_SPAWN_RESULT="merge_conflict"
|
|
709
|
-
log_warn "Worktree branch preserved for manual conflict resolution: $_wt_branch"
|
|
710
|
-
# Update bug status to merge_conflict
|
|
711
|
-
python3 "$SCRIPTS_DIR/update-bug-status.py" \
|
|
712
|
-
--bug-list "$bug_list" \
|
|
713
|
-
--state-dir "$STATE_DIR" \
|
|
714
|
-
--bug-id "$bug_id" \
|
|
715
|
-
--session-status "merge_conflict" \
|
|
716
|
-
--session-id "$session_id" \
|
|
717
|
-
--max-retries "$MAX_RETRIES" \
|
|
718
|
-
--action update >/dev/null 2>&1 || true
|
|
719
|
-
else
|
|
720
|
-
worktree_cleanup "$_proj_root" "$_wt_path" "$_wt_branch"
|
|
721
|
-
fi
|
|
722
|
-
else
|
|
723
|
-
worktree_cleanup "$_proj_root" "$_wt_path" "$_wt_branch"
|
|
724
|
-
fi
|
|
725
|
-
_ACTIVE_WORKTREE_PATH=""
|
|
726
|
-
_ACTIVE_WORKTREE_BRANCH=""
|
|
634
|
+
log_info "AUTO_PUSH enabled; pushing to remote..."
|
|
635
|
+
git -C "$_proj_root" push 2>/dev/null || log_warn "Auto-push failed"
|
|
727
636
|
fi
|
|
728
637
|
|
|
729
638
|
session_count=$((session_count + 1))
|