prizmkit 1.1.57 → 1.1.60
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 +8 -6
- package/bundled/VERSION.json +3 -3
- package/bundled/adapters/codex/agent-adapter.js +38 -0
- package/bundled/adapters/codex/paths.js +27 -0
- package/bundled/adapters/codex/rules-adapter.js +30 -0
- package/bundled/adapters/codex/settings-adapter.js +27 -0
- package/bundled/adapters/codex/skill-adapter.js +65 -0
- package/bundled/adapters/codex/team-adapter.js +37 -0
- package/bundled/dev-pipeline/.env.example +2 -1
- package/bundled/dev-pipeline/README.md +10 -7
- package/bundled/dev-pipeline/lib/common.sh +278 -37
- package/bundled/dev-pipeline/run-bugfix.sh +10 -61
- package/bundled/dev-pipeline/run-feature.sh +10 -78
- package/bundled/dev-pipeline/run-recovery.sh +10 -46
- package/bundled/dev-pipeline/run-refactor.sh +10 -61
- package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +17 -7
- package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +9 -3
- package/bundled/dev-pipeline/scripts/generate-refactor-prompt.py +9 -3
- package/bundled/dev-pipeline/scripts/utils.py +6 -4
- package/bundled/dev-pipeline-windows/.env.example +28 -0
- package/bundled/dev-pipeline-windows/README.md +30 -0
- package/bundled/dev-pipeline-windows/SCHEMA_ANALYSIS.md +525 -0
- package/bundled/dev-pipeline-windows/assets/feature-list-example.json +146 -0
- package/bundled/dev-pipeline-windows/assets/prizm-dev-team-integration.md +138 -0
- package/bundled/dev-pipeline-windows/launch-bugfix-daemon.ps1 +9 -0
- package/bundled/dev-pipeline-windows/launch-feature-daemon.ps1 +9 -0
- package/bundled/dev-pipeline-windows/launch-refactor-daemon.ps1 +9 -0
- package/bundled/dev-pipeline-windows/lib/common.ps1 +432 -0
- package/bundled/dev-pipeline-windows/lib/daemon.ps1 +140 -0
- package/bundled/dev-pipeline-windows/lib/pipeline.ps1 +446 -0
- package/bundled/dev-pipeline-windows/lib/reset.ps1 +87 -0
- package/bundled/dev-pipeline-windows/reset-bug.ps1 +9 -0
- package/bundled/dev-pipeline-windows/reset-feature.ps1 +9 -0
- package/bundled/dev-pipeline-windows/reset-refactor.ps1 +9 -0
- package/bundled/dev-pipeline-windows/run-bugfix.ps1 +9 -0
- package/bundled/dev-pipeline-windows/run-feature.ps1 +9 -0
- package/bundled/dev-pipeline-windows/run-recovery.ps1 +76 -0
- package/bundled/dev-pipeline-windows/run-refactor.ps1 +9 -0
- package/bundled/dev-pipeline-windows/scripts/check-session-status.py +228 -0
- package/bundled/dev-pipeline-windows/scripts/cleanup-logs.py +192 -0
- package/bundled/dev-pipeline-windows/scripts/detect-stuck.py +530 -0
- package/bundled/dev-pipeline-windows/scripts/generate-bootstrap-prompt.py +1737 -0
- package/bundled/dev-pipeline-windows/scripts/generate-bugfix-prompt.py +685 -0
- package/bundled/dev-pipeline-windows/scripts/generate-recovery-prompt.py +805 -0
- package/bundled/dev-pipeline-windows/scripts/generate-refactor-prompt.py +763 -0
- package/bundled/dev-pipeline-windows/scripts/init-bugfix-pipeline.py +316 -0
- package/bundled/dev-pipeline-windows/scripts/init-dev-team.py +134 -0
- package/bundled/dev-pipeline-windows/scripts/init-pipeline.py +380 -0
- package/bundled/dev-pipeline-windows/scripts/init-refactor-pipeline.py +399 -0
- package/bundled/dev-pipeline-windows/scripts/parse-stream-progress.py +388 -0
- package/bundled/dev-pipeline-windows/scripts/patch-completion-notes.py +191 -0
- package/bundled/dev-pipeline-windows/scripts/update-bug-status.py +864 -0
- package/bundled/dev-pipeline-windows/scripts/update-checkpoint.py +173 -0
- package/bundled/dev-pipeline-windows/scripts/update-feature-status.py +1501 -0
- package/bundled/dev-pipeline-windows/scripts/update-refactor-status.py +1073 -0
- package/bundled/dev-pipeline-windows/scripts/utils.py +542 -0
- package/bundled/dev-pipeline-windows/templates/agent-prompts/critic-plan-challenge.md +7 -0
- package/bundled/dev-pipeline-windows/templates/agent-prompts/dev-fix.md +7 -0
- package/bundled/dev-pipeline-windows/templates/agent-prompts/dev-implement.md +30 -0
- package/bundled/dev-pipeline-windows/templates/agent-prompts/dev-resume.md +5 -0
- package/bundled/dev-pipeline-windows/templates/agent-prompts/reviewer-review.md +7 -0
- package/bundled/dev-pipeline-windows/templates/bootstrap-prompt.md +46 -0
- package/bundled/dev-pipeline-windows/templates/bootstrap-tier1.md +43 -0
- package/bundled/dev-pipeline-windows/templates/bootstrap-tier2.md +43 -0
- package/bundled/dev-pipeline-windows/templates/bootstrap-tier3.md +43 -0
- package/bundled/dev-pipeline-windows/templates/bug-fix-list-schema.json +263 -0
- package/bundled/dev-pipeline-windows/templates/bugfix-bootstrap-prompt.md +320 -0
- package/bundled/dev-pipeline-windows/templates/feature-list-schema.json +237 -0
- package/bundled/dev-pipeline-windows/templates/refactor-bootstrap-prompt.md +331 -0
- package/bundled/dev-pipeline-windows/templates/refactor-list-schema.json +270 -0
- package/bundled/dev-pipeline-windows/templates/sections/ac-verification-checklist.md +13 -0
- package/bundled/dev-pipeline-windows/templates/sections/checkpoint-system.md +91 -0
- package/bundled/dev-pipeline-windows/templates/sections/context-budget-rules.md +33 -0
- package/bundled/dev-pipeline-windows/templates/sections/critical-paths-agent.md +10 -0
- package/bundled/dev-pipeline-windows/templates/sections/critical-paths-full.md +12 -0
- package/bundled/dev-pipeline-windows/templates/sections/critical-paths-lite.md +7 -0
- package/bundled/dev-pipeline-windows/templates/sections/directory-convention-agent.md +8 -0
- package/bundled/dev-pipeline-windows/templates/sections/directory-convention-full.md +9 -0
- package/bundled/dev-pipeline-windows/templates/sections/directory-convention-lite.md +6 -0
- package/bundled/dev-pipeline-windows/templates/sections/failure-capture.md +21 -0
- package/bundled/dev-pipeline-windows/templates/sections/feature-context.md +31 -0
- package/bundled/dev-pipeline-windows/templates/sections/phase-browser-verification-auto.md +72 -0
- package/bundled/dev-pipeline-windows/templates/sections/phase-browser-verification-opencli.md +63 -0
- package/bundled/dev-pipeline-windows/templates/sections/phase-browser-verification.md +62 -0
- package/bundled/dev-pipeline-windows/templates/sections/phase-commit-full.md +71 -0
- package/bundled/dev-pipeline-windows/templates/sections/phase-commit.md +64 -0
- package/bundled/dev-pipeline-windows/templates/sections/phase-context-snapshot-agent-suffix.md +23 -0
- package/bundled/dev-pipeline-windows/templates/sections/phase-context-snapshot-base.md +24 -0
- package/bundled/dev-pipeline-windows/templates/sections/phase-context-snapshot-lite-suffix.md +12 -0
- package/bundled/dev-pipeline-windows/templates/sections/phase-critic-plan-full.md +53 -0
- package/bundled/dev-pipeline-windows/templates/sections/phase-critic-plan.md +32 -0
- package/bundled/dev-pipeline-windows/templates/sections/phase-implement-agent.md +37 -0
- package/bundled/dev-pipeline-windows/templates/sections/phase-implement-full.md +50 -0
- package/bundled/dev-pipeline-windows/templates/sections/phase-implement-lite.md +52 -0
- package/bundled/dev-pipeline-windows/templates/sections/phase-plan-agent.md +27 -0
- package/bundled/dev-pipeline-windows/templates/sections/phase-plan-lite.md +27 -0
- package/bundled/dev-pipeline-windows/templates/sections/phase-review-agent.md +27 -0
- package/bundled/dev-pipeline-windows/templates/sections/phase-review-full.md +29 -0
- package/bundled/dev-pipeline-windows/templates/sections/phase-specify-plan-full.md +77 -0
- package/bundled/dev-pipeline-windows/templates/sections/phase0-init.md +13 -0
- package/bundled/dev-pipeline-windows/templates/sections/phase0-test-baseline.md +23 -0
- package/bundled/dev-pipeline-windows/templates/sections/session-context.md +5 -0
- package/bundled/dev-pipeline-windows/templates/sections/subagent-timeout-recovery.md +6 -0
- package/bundled/dev-pipeline-windows/templates/sections/test-failure-recovery-agent.md +67 -0
- package/bundled/dev-pipeline-windows/templates/sections/test-failure-recovery-lite.md +58 -0
- package/bundled/dev-pipeline-windows/templates/session-status-schema.json +83 -0
- package/bundled/skills/_metadata.json +1 -1
- package/bundled/skills/app-planner/SKILL.md +26 -18
- package/bundled/skills/app-planner/references/architecture-decisions.md +9 -5
- package/bundled/skills/app-planner/references/frontend-design-guide.md +1 -1
- package/bundled/skills/feature-planner/SKILL.md +9 -2
- package/bundled/skills/prizmkit-init/SKILL.md +7 -6
- package/bundled/skills/recovery-workflow/scripts/detect-recovery-state.py +2 -0
- package/bundled/skills-windows/app-planner/SKILL.md +639 -0
- package/bundled/skills-windows/app-planner/assets/app-design-guide.md +101 -0
- package/bundled/skills-windows/app-planner/references/architecture-decisions.md +52 -0
- package/bundled/skills-windows/app-planner/references/brainstorm-guide.md +101 -0
- package/bundled/skills-windows/app-planner/references/frontend-design-guide.md +71 -0
- package/bundled/skills-windows/app-planner/references/project-brief-guide.md +82 -0
- package/bundled/skills-windows/app-planner/references/red-team-checklist.md +40 -0
- package/bundled/skills-windows/app-planner/references/rules/backend/derivation-rules.md +609 -0
- package/bundled/skills-windows/app-planner/references/rules/backend/fixed-rules.md +285 -0
- package/bundled/skills-windows/app-planner/references/rules/backend/question-bank.md +249 -0
- package/bundled/skills-windows/app-planner/references/rules/backend/template.md +173 -0
- package/bundled/skills-windows/app-planner/references/rules/database/derivation-rules.md +373 -0
- package/bundled/skills-windows/app-planner/references/rules/database/fixed-rules.md +211 -0
- package/bundled/skills-windows/app-planner/references/rules/database/question-bank.md +184 -0
- package/bundled/skills-windows/app-planner/references/rules/database/template.md +158 -0
- package/bundled/skills-windows/app-planner/references/rules/frontend/derivation-rules.md +810 -0
- package/bundled/skills-windows/app-planner/references/rules/frontend/fixed-rules.md +188 -0
- package/bundled/skills-windows/app-planner/references/rules/frontend/question-bank.md +302 -0
- package/bundled/skills-windows/app-planner/references/rules/frontend/template.md +320 -0
- package/bundled/skills-windows/app-planner/references/rules/mobile/derivation-rules.md +639 -0
- package/bundled/skills-windows/app-planner/references/rules/mobile/fixed-rules.md +290 -0
- package/bundled/skills-windows/app-planner/references/rules/mobile/question-bank.md +232 -0
- package/bundled/skills-windows/app-planner/references/rules/mobile/template.md +175 -0
- package/bundled/skills-windows/bug-fix-workflow/SKILL.md +415 -0
- package/bundled/skills-windows/bug-planner/SKILL.md +395 -0
- package/bundled/skills-windows/bug-planner/assets/bug-confirmation-template.md +43 -0
- package/bundled/skills-windows/bug-planner/references/critic-and-verification.md +44 -0
- package/bundled/skills-windows/bug-planner/references/error-recovery.md +73 -0
- package/bundled/skills-windows/bug-planner/references/input-formats.md +53 -0
- package/bundled/skills-windows/bug-planner/references/schema-validation.md +25 -0
- package/bundled/skills-windows/bug-planner/references/severity-rules.md +16 -0
- package/bundled/skills-windows/bug-planner/scripts/validate-bug-list.py +322 -0
- package/bundled/skills-windows/bugfix-pipeline-launcher/SKILL.md +380 -0
- package/bundled/skills-windows/feature-pipeline-launcher/SKILL.md +441 -0
- package/bundled/skills-windows/feature-pipeline-launcher/scripts/preflight-check.py +462 -0
- package/bundled/skills-windows/feature-planner/SKILL.md +401 -0
- package/bundled/skills-windows/feature-planner/assets/evaluation-guide.md +64 -0
- package/bundled/skills-windows/feature-planner/assets/planning-guide.md +214 -0
- package/bundled/skills-windows/feature-planner/references/browser-interaction.md +59 -0
- package/bundled/skills-windows/feature-planner/references/completeness-review.md +57 -0
- package/bundled/skills-windows/feature-planner/references/decomposition-patterns.md +75 -0
- package/bundled/skills-windows/feature-planner/references/error-recovery.md +90 -0
- package/bundled/skills-windows/feature-planner/references/incremental-feature-planning.md +112 -0
- package/bundled/skills-windows/feature-planner/references/new-project-planning.md +85 -0
- package/bundled/skills-windows/feature-planner/scripts/validate-and-generate.py +1029 -0
- package/bundled/skills-windows/feature-workflow/SKILL.md +531 -0
- package/bundled/skills-windows/prizmkit-init/SKILL.md +356 -0
- package/bundled/skills-windows/prizmkit-init/assets/project-brief-template.md +82 -0
- package/bundled/skills-windows/prizmkit-init/references/config-schema.md +68 -0
- package/bundled/skills-windows/prizmkit-init/references/rules/layer-detection.md +41 -0
- package/bundled/skills-windows/prizmkit-init/references/tech-stack-catalog.md +13 -0
- package/bundled/skills-windows/prizmkit-init/references/update-supplement.md +9 -0
- package/bundled/skills-windows/recovery-workflow/SKILL.md +456 -0
- package/bundled/skills-windows/recovery-workflow/evals/evals.json +46 -0
- package/bundled/skills-windows/recovery-workflow/scripts/detect-recovery-state.py +544 -0
- package/bundled/skills-windows/refactor-pipeline-launcher/SKILL.md +406 -0
- package/bundled/skills-windows/refactor-planner/SKILL.md +540 -0
- package/bundled/skills-windows/refactor-planner/assets/planning-guide.md +292 -0
- package/bundled/skills-windows/refactor-planner/references/behavior-preservation.md +301 -0
- package/bundled/skills-windows/refactor-planner/references/refactor-scoping-guide.md +221 -0
- package/bundled/skills-windows/refactor-planner/scripts/validate-and-generate-refactor.py +858 -0
- package/bundled/skills-windows/refactor-workflow/SKILL.md +503 -0
- package/package.json +3 -2
- package/src/clean.js +73 -2
- package/src/config.js +159 -50
- package/src/detect-platform.js +16 -8
- package/src/external-skills.js +26 -19
- package/src/index.js +31 -9
- package/src/manifest.js +6 -2
- package/src/metadata.js +43 -5
- package/src/platforms.js +36 -0
- package/src/prompts.js +31 -6
- package/src/runtimes.js +20 -0
- package/src/scaffold.js +314 -110
- package/src/upgrade.js +81 -41
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Initialize the bug-fix pipeline state directory from a .prizmkit/plans/bug-fix-list.json file.
|
|
3
|
+
|
|
4
|
+
Validates the bug fix list schema, sorts by priority/severity, and creates
|
|
5
|
+
the state directory structure with pipeline and per-bug status files.
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
python3 init-bugfix-pipeline.py --bug-list <path> --state-dir <path>
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import argparse
|
|
12
|
+
import json
|
|
13
|
+
import os
|
|
14
|
+
import re
|
|
15
|
+
import sys
|
|
16
|
+
from datetime import datetime, timezone
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
EXPECTED_SCHEMA = "dev-pipeline-bug-fix-list-v1"
|
|
20
|
+
BUG_ID_PATTERN = re.compile(r"^B-\d{3}$")
|
|
21
|
+
|
|
22
|
+
REQUIRED_BUG_FIELDS = [
|
|
23
|
+
"id",
|
|
24
|
+
"title",
|
|
25
|
+
"description",
|
|
26
|
+
"severity",
|
|
27
|
+
"error_source",
|
|
28
|
+
"verification_type",
|
|
29
|
+
"acceptance_criteria",
|
|
30
|
+
"status",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
VALID_SEVERITIES = ["critical", "high", "medium", "low"]
|
|
34
|
+
VALID_VERIFICATION_TYPES = ["automated", "manual", "hybrid"]
|
|
35
|
+
VALID_STATUSES = [
|
|
36
|
+
"pending", "in_progress", "completed", "failed",
|
|
37
|
+
"skipped", "needs_info",
|
|
38
|
+
]
|
|
39
|
+
TERMINAL_STATUSES = {"completed", "failed", "skipped", "needs_info"}
|
|
40
|
+
VALID_ERROR_SOURCE_TYPES = [
|
|
41
|
+
"stack_trace", "user_report", "failed_test", "log_pattern", "monitoring_alert",
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def parse_args():
|
|
46
|
+
parser = argparse.ArgumentParser(
|
|
47
|
+
description="Initialize bug-fix pipeline state from a .prizmkit/plans/bug-fix-list.json file."
|
|
48
|
+
)
|
|
49
|
+
parser.add_argument(
|
|
50
|
+
"--bug-list",
|
|
51
|
+
required=True,
|
|
52
|
+
help="Path to the .prizmkit/plans/bug-fix-list.json file",
|
|
53
|
+
)
|
|
54
|
+
parser.add_argument(
|
|
55
|
+
"--state-dir",
|
|
56
|
+
required=True,
|
|
57
|
+
help="Path to the state directory (default: .prizmkit/state/bugfix)",
|
|
58
|
+
)
|
|
59
|
+
return parser.parse_args()
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def load_bug_list(path):
|
|
63
|
+
"""Load and return the parsed JSON from the bug fix list file."""
|
|
64
|
+
abs_path = os.path.abspath(path)
|
|
65
|
+
if not os.path.isfile(abs_path):
|
|
66
|
+
return None, ["Bug fix list file not found: {}".format(abs_path)]
|
|
67
|
+
try:
|
|
68
|
+
with open(abs_path, "r", encoding="utf-8") as f:
|
|
69
|
+
data = json.load(f)
|
|
70
|
+
except json.JSONDecodeError as e:
|
|
71
|
+
return None, ["Invalid JSON in bug fix list: {}".format(str(e))]
|
|
72
|
+
except IOError as e:
|
|
73
|
+
return None, ["Cannot read bug fix list file: {}".format(str(e))]
|
|
74
|
+
return data, []
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def validate_schema(data):
|
|
78
|
+
"""Validate the top-level schema and structure of the bug fix list."""
|
|
79
|
+
errors = []
|
|
80
|
+
|
|
81
|
+
# Check $schema
|
|
82
|
+
schema = data.get("$schema")
|
|
83
|
+
if schema != EXPECTED_SCHEMA:
|
|
84
|
+
errors.append(
|
|
85
|
+
"Invalid $schema: expected '{}', got '{}'".format(EXPECTED_SCHEMA, schema)
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
# Check project_name
|
|
89
|
+
if "project_name" not in data:
|
|
90
|
+
errors.append("Missing required field: project_name")
|
|
91
|
+
elif not isinstance(data["project_name"], str) or not data["project_name"].strip():
|
|
92
|
+
errors.append("project_name must be a non-empty string")
|
|
93
|
+
|
|
94
|
+
# Check bugs array
|
|
95
|
+
if "bugs" not in data:
|
|
96
|
+
errors.append("Missing required field: bugs")
|
|
97
|
+
elif not isinstance(data["bugs"], list):
|
|
98
|
+
errors.append("bugs must be an array")
|
|
99
|
+
elif len(data["bugs"]) == 0:
|
|
100
|
+
errors.append("bugs array must contain at least one bug")
|
|
101
|
+
|
|
102
|
+
return errors
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def validate_bugs(bugs):
|
|
106
|
+
"""Validate each bug object in the list."""
|
|
107
|
+
errors = []
|
|
108
|
+
seen_ids = set()
|
|
109
|
+
|
|
110
|
+
for i, bug in enumerate(bugs):
|
|
111
|
+
if not isinstance(bug, dict):
|
|
112
|
+
errors.append("Bug at index {} is not an object".format(i))
|
|
113
|
+
continue
|
|
114
|
+
|
|
115
|
+
# Check required fields
|
|
116
|
+
for field in REQUIRED_BUG_FIELDS:
|
|
117
|
+
if field not in bug:
|
|
118
|
+
errors.append(
|
|
119
|
+
"Bug at index {} missing required field: {}".format(i, field)
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
# Validate bug ID format
|
|
123
|
+
bid = bug.get("id")
|
|
124
|
+
if bid is not None:
|
|
125
|
+
if not isinstance(bid, str) or not BUG_ID_PATTERN.match(bid):
|
|
126
|
+
errors.append(
|
|
127
|
+
"Bug at index {} has invalid id '{}' "
|
|
128
|
+
"(must match B-NNN pattern)".format(i, bid)
|
|
129
|
+
)
|
|
130
|
+
elif bid in seen_ids:
|
|
131
|
+
errors.append("Duplicate bug id: {}".format(bid))
|
|
132
|
+
else:
|
|
133
|
+
seen_ids.add(bid)
|
|
134
|
+
|
|
135
|
+
# Validate severity
|
|
136
|
+
severity = bug.get("severity")
|
|
137
|
+
if severity is not None and severity not in VALID_SEVERITIES:
|
|
138
|
+
errors.append(
|
|
139
|
+
"Bug '{}' has invalid severity '{}' "
|
|
140
|
+
"(must be one of {})".format(
|
|
141
|
+
bid or "index {}".format(i), severity, VALID_SEVERITIES
|
|
142
|
+
)
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
# Validate verification_type
|
|
146
|
+
vtype = bug.get("verification_type")
|
|
147
|
+
if vtype is not None and vtype not in VALID_VERIFICATION_TYPES:
|
|
148
|
+
errors.append(
|
|
149
|
+
"Bug '{}' has invalid verification_type '{}' "
|
|
150
|
+
"(must be one of {})".format(
|
|
151
|
+
bid or "index {}".format(i), vtype, VALID_VERIFICATION_TYPES
|
|
152
|
+
)
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
# Validate status
|
|
156
|
+
status = bug.get("status")
|
|
157
|
+
if status is not None and status not in VALID_STATUSES:
|
|
158
|
+
errors.append(
|
|
159
|
+
"Bug '{}' has invalid status '{}' "
|
|
160
|
+
"(must be one of {})".format(
|
|
161
|
+
bid or "index {}".format(i), status, VALID_STATUSES
|
|
162
|
+
)
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
# Validate error_source has type field
|
|
166
|
+
error_source = bug.get("error_source")
|
|
167
|
+
if error_source is not None:
|
|
168
|
+
if not isinstance(error_source, dict):
|
|
169
|
+
errors.append(
|
|
170
|
+
"Bug '{}' error_source must be an object".format(
|
|
171
|
+
bid or "index {}".format(i)
|
|
172
|
+
)
|
|
173
|
+
)
|
|
174
|
+
elif "type" not in error_source:
|
|
175
|
+
errors.append(
|
|
176
|
+
"Bug '{}' error_source missing required field: type".format(
|
|
177
|
+
bid or "index {}".format(i)
|
|
178
|
+
)
|
|
179
|
+
)
|
|
180
|
+
else:
|
|
181
|
+
es_type = error_source["type"]
|
|
182
|
+
if es_type not in VALID_ERROR_SOURCE_TYPES:
|
|
183
|
+
# Warn but don't error — the pipeline can still attempt the fix
|
|
184
|
+
print(
|
|
185
|
+
"WARNING: Bug '{}' error_source.type '{}' is not one of {} "
|
|
186
|
+
"— pipeline will still attempt to process this bug".format(
|
|
187
|
+
bid or "index {}".format(i), es_type, VALID_ERROR_SOURCE_TYPES
|
|
188
|
+
),
|
|
189
|
+
file=sys.stderr,
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
# Validate acceptance_criteria is a list
|
|
193
|
+
ac = bug.get("acceptance_criteria")
|
|
194
|
+
if ac is not None and not isinstance(ac, list):
|
|
195
|
+
errors.append(
|
|
196
|
+
"Bug '{}' acceptance_criteria must be an array".format(
|
|
197
|
+
bid or "index {}".format(i)
|
|
198
|
+
)
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
return errors, seen_ids
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def create_state_directory(state_dir, bug_list_path, bugs):
|
|
205
|
+
"""Create the state directory structure with pipeline.json and per-bug status files."""
|
|
206
|
+
abs_state_dir = os.path.abspath(state_dir)
|
|
207
|
+
abs_bug_list_path = os.path.abspath(bug_list_path)
|
|
208
|
+
# Store as relative path from state_dir so pipeline.json is portable across machines
|
|
209
|
+
rel_bug_list_path = os.path.relpath(abs_bug_list_path, abs_state_dir)
|
|
210
|
+
bugs_dir = os.path.join(abs_state_dir, "bugs")
|
|
211
|
+
|
|
212
|
+
now = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
213
|
+
run_id = "bugfix-run-" + datetime.now(timezone.utc).strftime("%Y%m%d%H%M%S")
|
|
214
|
+
|
|
215
|
+
# Create top-level state directory
|
|
216
|
+
os.makedirs(abs_state_dir, exist_ok=True)
|
|
217
|
+
os.makedirs(bugs_dir, exist_ok=True)
|
|
218
|
+
|
|
219
|
+
# Count bugs already in terminal status at init time
|
|
220
|
+
completed_count = sum(
|
|
221
|
+
1 for b in bugs
|
|
222
|
+
if isinstance(b, dict) and b.get("status") in TERMINAL_STATUSES
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
# Write pipeline.json
|
|
226
|
+
pipeline_state = {
|
|
227
|
+
"run_id": run_id,
|
|
228
|
+
"pipeline_type": "bugfix",
|
|
229
|
+
"status": "initialized",
|
|
230
|
+
"bug_list_path": rel_bug_list_path,
|
|
231
|
+
"created_at": now,
|
|
232
|
+
"total_bugs": len(bugs),
|
|
233
|
+
"completed_bugs": completed_count,
|
|
234
|
+
}
|
|
235
|
+
pipeline_path = os.path.join(abs_state_dir, "pipeline.json")
|
|
236
|
+
with open(pipeline_path, "w", encoding="utf-8") as f:
|
|
237
|
+
json.dump(pipeline_state, f, indent=2, ensure_ascii=False)
|
|
238
|
+
f.write("\n")
|
|
239
|
+
|
|
240
|
+
# Write per-bug status.json and create sessions directory
|
|
241
|
+
for bug in bugs:
|
|
242
|
+
if not isinstance(bug, dict):
|
|
243
|
+
continue
|
|
244
|
+
bid = bug.get("id")
|
|
245
|
+
if bid is None:
|
|
246
|
+
continue
|
|
247
|
+
|
|
248
|
+
bug_dir = os.path.join(bugs_dir, bid)
|
|
249
|
+
sessions_dir = os.path.join(bug_dir, "sessions")
|
|
250
|
+
os.makedirs(sessions_dir, exist_ok=True)
|
|
251
|
+
|
|
252
|
+
bug_status = {
|
|
253
|
+
"bug_id": bid,
|
|
254
|
+
"retry_count": 0,
|
|
255
|
+
"max_retries": 3,
|
|
256
|
+
"sessions": [],
|
|
257
|
+
"last_session_id": None,
|
|
258
|
+
"resume_from_phase": None,
|
|
259
|
+
"created_at": now,
|
|
260
|
+
"updated_at": now,
|
|
261
|
+
}
|
|
262
|
+
status_path = os.path.join(bug_dir, "status.json")
|
|
263
|
+
with open(status_path, "w", encoding="utf-8") as f:
|
|
264
|
+
json.dump(bug_status, f, indent=2, ensure_ascii=False)
|
|
265
|
+
f.write("\n")
|
|
266
|
+
|
|
267
|
+
return abs_state_dir
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
def main():
|
|
271
|
+
args = parse_args()
|
|
272
|
+
|
|
273
|
+
# Load bug fix list
|
|
274
|
+
data, load_errors = load_bug_list(args.bug_list)
|
|
275
|
+
if load_errors:
|
|
276
|
+
output = {"valid": False, "errors": load_errors}
|
|
277
|
+
print(json.dumps(output, indent=2, ensure_ascii=False))
|
|
278
|
+
sys.exit(1)
|
|
279
|
+
|
|
280
|
+
# Validate schema
|
|
281
|
+
schema_errors = validate_schema(data)
|
|
282
|
+
if schema_errors:
|
|
283
|
+
output = {"valid": False, "errors": schema_errors}
|
|
284
|
+
print(json.dumps(output, indent=2, ensure_ascii=False))
|
|
285
|
+
sys.exit(1)
|
|
286
|
+
|
|
287
|
+
# Validate bugs
|
|
288
|
+
bugs = data["bugs"]
|
|
289
|
+
bug_errors, bug_ids = validate_bugs(bugs)
|
|
290
|
+
if bug_errors:
|
|
291
|
+
output = {"valid": False, "errors": bug_errors}
|
|
292
|
+
print(json.dumps(output, indent=2, ensure_ascii=False))
|
|
293
|
+
sys.exit(1)
|
|
294
|
+
|
|
295
|
+
# Create state directory
|
|
296
|
+
try:
|
|
297
|
+
abs_state_dir = create_state_directory(
|
|
298
|
+
args.state_dir, args.bug_list, bugs
|
|
299
|
+
)
|
|
300
|
+
except (IOError, OSError) as e:
|
|
301
|
+
output = {"valid": False, "errors": ["Failed to create state directory: {}".format(str(e))]}
|
|
302
|
+
print(json.dumps(output, indent=2, ensure_ascii=False))
|
|
303
|
+
sys.exit(1)
|
|
304
|
+
|
|
305
|
+
# Success output
|
|
306
|
+
output = {
|
|
307
|
+
"valid": True,
|
|
308
|
+
"bugs_count": len(bugs),
|
|
309
|
+
"state_dir": abs_state_dir,
|
|
310
|
+
}
|
|
311
|
+
print(json.dumps(output, indent=2, ensure_ascii=False))
|
|
312
|
+
sys.exit(0)
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
if __name__ == "__main__":
|
|
316
|
+
main()
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Initialize prizmkit directory structures for a feature.
|
|
3
|
+
|
|
4
|
+
Creates the standard directory layout expected by prizm-dev-team agents:
|
|
5
|
+
- .prizmkit/specs/<feature-slug>/ ← per-feature subdirectory
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
python3 init-dev-team.py --project-root <path> --feature-slug <slug>
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import argparse
|
|
12
|
+
import json
|
|
13
|
+
import os
|
|
14
|
+
import sys
|
|
15
|
+
from datetime import datetime, timezone
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def parse_args():
|
|
19
|
+
parser = argparse.ArgumentParser(
|
|
20
|
+
description="Initialize dev-team and prizmkit directories"
|
|
21
|
+
)
|
|
22
|
+
parser.add_argument(
|
|
23
|
+
"--project-root",
|
|
24
|
+
required=True,
|
|
25
|
+
help="Project root directory",
|
|
26
|
+
)
|
|
27
|
+
parser.add_argument(
|
|
28
|
+
"--feature-id",
|
|
29
|
+
default=None,
|
|
30
|
+
help="Feature ID (e.g. F-001)",
|
|
31
|
+
)
|
|
32
|
+
parser.add_argument(
|
|
33
|
+
"--feature-slug",
|
|
34
|
+
default=None,
|
|
35
|
+
help="Feature slug for per-feature directory (e.g. 001-project-infrastructure-setup)",
|
|
36
|
+
)
|
|
37
|
+
return parser.parse_args()
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def create_directories(project_root, feature_slug=None):
|
|
41
|
+
"""Create the prizmkit directory structures."""
|
|
42
|
+
dirs_to_create = []
|
|
43
|
+
|
|
44
|
+
# PrizmKit per-feature directories
|
|
45
|
+
if feature_slug:
|
|
46
|
+
dirs_to_create.extend([
|
|
47
|
+
".prizmkit/specs/{}".format(feature_slug),
|
|
48
|
+
])
|
|
49
|
+
else:
|
|
50
|
+
# Fallback: create flat directories (not recommended)
|
|
51
|
+
dirs_to_create.extend([
|
|
52
|
+
".prizmkit/specs",
|
|
53
|
+
])
|
|
54
|
+
|
|
55
|
+
created = []
|
|
56
|
+
for dir_path in dirs_to_create:
|
|
57
|
+
full_path = os.path.join(project_root, dir_path)
|
|
58
|
+
if not os.path.exists(full_path):
|
|
59
|
+
os.makedirs(full_path, exist_ok=True)
|
|
60
|
+
created.append(dir_path)
|
|
61
|
+
|
|
62
|
+
return created
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def init_prizmkit_config(project_root, feature_id):
|
|
66
|
+
"""Initialize or update .prizmkit/config.json."""
|
|
67
|
+
config_path = os.path.join(project_root, ".prizmkit", "config.json")
|
|
68
|
+
|
|
69
|
+
if os.path.exists(config_path):
|
|
70
|
+
# Update existing config
|
|
71
|
+
with open(config_path, "r", encoding="utf-8") as f:
|
|
72
|
+
config = json.load(f)
|
|
73
|
+
config["current_feature"] = feature_id
|
|
74
|
+
config["updated_at"] = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
75
|
+
else:
|
|
76
|
+
# Create new config
|
|
77
|
+
# Try to get project name from package.json or directory name
|
|
78
|
+
project_name = os.path.basename(project_root)
|
|
79
|
+
pkg_json_path = os.path.join(project_root, "package.json")
|
|
80
|
+
if os.path.exists(pkg_json_path):
|
|
81
|
+
try:
|
|
82
|
+
with open(pkg_json_path, "r", encoding="utf-8") as f:
|
|
83
|
+
pkg = json.load(f)
|
|
84
|
+
project_name = pkg.get("name", project_name)
|
|
85
|
+
except (json.JSONDecodeError, IOError):
|
|
86
|
+
pass
|
|
87
|
+
|
|
88
|
+
config = {
|
|
89
|
+
"adoption_mode": "active",
|
|
90
|
+
"speckit_hooks_enabled": True,
|
|
91
|
+
"project_name": project_name,
|
|
92
|
+
"initialized_at": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
|
|
93
|
+
"feature_prefix": "F-",
|
|
94
|
+
"current_feature": feature_id,
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
with open(config_path, "w", encoding="utf-8") as f:
|
|
98
|
+
json.dump(config, f, indent=2)
|
|
99
|
+
|
|
100
|
+
return config_path
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def main():
|
|
104
|
+
args = parse_args()
|
|
105
|
+
project_root = os.path.abspath(args.project_root)
|
|
106
|
+
|
|
107
|
+
if not os.path.isdir(project_root):
|
|
108
|
+
result = {
|
|
109
|
+
"success": False,
|
|
110
|
+
"error": f"Project root does not exist: {project_root}",
|
|
111
|
+
}
|
|
112
|
+
print(json.dumps(result, indent=2))
|
|
113
|
+
sys.exit(1)
|
|
114
|
+
|
|
115
|
+
# Create directories
|
|
116
|
+
created_dirs = create_directories(project_root, args.feature_slug)
|
|
117
|
+
|
|
118
|
+
# Initialize config
|
|
119
|
+
config_path = init_prizmkit_config(project_root, args.feature_id)
|
|
120
|
+
|
|
121
|
+
result = {
|
|
122
|
+
"success": True,
|
|
123
|
+
"project_root": project_root,
|
|
124
|
+
"feature_slug": args.feature_slug,
|
|
125
|
+
"directories_created": created_dirs,
|
|
126
|
+
"config_path": config_path,
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
print(json.dumps(result, indent=2))
|
|
130
|
+
sys.exit(0)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
if __name__ == "__main__":
|
|
134
|
+
main()
|