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.
Files changed (188) hide show
  1. package/bin/create-prizmkit.js +8 -6
  2. package/bundled/VERSION.json +3 -3
  3. package/bundled/adapters/codex/agent-adapter.js +38 -0
  4. package/bundled/adapters/codex/paths.js +27 -0
  5. package/bundled/adapters/codex/rules-adapter.js +30 -0
  6. package/bundled/adapters/codex/settings-adapter.js +27 -0
  7. package/bundled/adapters/codex/skill-adapter.js +65 -0
  8. package/bundled/adapters/codex/team-adapter.js +37 -0
  9. package/bundled/dev-pipeline/.env.example +2 -1
  10. package/bundled/dev-pipeline/README.md +10 -7
  11. package/bundled/dev-pipeline/lib/common.sh +278 -37
  12. package/bundled/dev-pipeline/run-bugfix.sh +10 -61
  13. package/bundled/dev-pipeline/run-feature.sh +10 -78
  14. package/bundled/dev-pipeline/run-recovery.sh +10 -46
  15. package/bundled/dev-pipeline/run-refactor.sh +10 -61
  16. package/bundled/dev-pipeline/scripts/generate-bootstrap-prompt.py +17 -7
  17. package/bundled/dev-pipeline/scripts/generate-bugfix-prompt.py +9 -3
  18. package/bundled/dev-pipeline/scripts/generate-refactor-prompt.py +9 -3
  19. package/bundled/dev-pipeline/scripts/utils.py +6 -4
  20. package/bundled/dev-pipeline-windows/.env.example +28 -0
  21. package/bundled/dev-pipeline-windows/README.md +30 -0
  22. package/bundled/dev-pipeline-windows/SCHEMA_ANALYSIS.md +525 -0
  23. package/bundled/dev-pipeline-windows/assets/feature-list-example.json +146 -0
  24. package/bundled/dev-pipeline-windows/assets/prizm-dev-team-integration.md +138 -0
  25. package/bundled/dev-pipeline-windows/launch-bugfix-daemon.ps1 +9 -0
  26. package/bundled/dev-pipeline-windows/launch-feature-daemon.ps1 +9 -0
  27. package/bundled/dev-pipeline-windows/launch-refactor-daemon.ps1 +9 -0
  28. package/bundled/dev-pipeline-windows/lib/common.ps1 +432 -0
  29. package/bundled/dev-pipeline-windows/lib/daemon.ps1 +140 -0
  30. package/bundled/dev-pipeline-windows/lib/pipeline.ps1 +446 -0
  31. package/bundled/dev-pipeline-windows/lib/reset.ps1 +87 -0
  32. package/bundled/dev-pipeline-windows/reset-bug.ps1 +9 -0
  33. package/bundled/dev-pipeline-windows/reset-feature.ps1 +9 -0
  34. package/bundled/dev-pipeline-windows/reset-refactor.ps1 +9 -0
  35. package/bundled/dev-pipeline-windows/run-bugfix.ps1 +9 -0
  36. package/bundled/dev-pipeline-windows/run-feature.ps1 +9 -0
  37. package/bundled/dev-pipeline-windows/run-recovery.ps1 +76 -0
  38. package/bundled/dev-pipeline-windows/run-refactor.ps1 +9 -0
  39. package/bundled/dev-pipeline-windows/scripts/check-session-status.py +228 -0
  40. package/bundled/dev-pipeline-windows/scripts/cleanup-logs.py +192 -0
  41. package/bundled/dev-pipeline-windows/scripts/detect-stuck.py +530 -0
  42. package/bundled/dev-pipeline-windows/scripts/generate-bootstrap-prompt.py +1737 -0
  43. package/bundled/dev-pipeline-windows/scripts/generate-bugfix-prompt.py +685 -0
  44. package/bundled/dev-pipeline-windows/scripts/generate-recovery-prompt.py +805 -0
  45. package/bundled/dev-pipeline-windows/scripts/generate-refactor-prompt.py +763 -0
  46. package/bundled/dev-pipeline-windows/scripts/init-bugfix-pipeline.py +316 -0
  47. package/bundled/dev-pipeline-windows/scripts/init-dev-team.py +134 -0
  48. package/bundled/dev-pipeline-windows/scripts/init-pipeline.py +380 -0
  49. package/bundled/dev-pipeline-windows/scripts/init-refactor-pipeline.py +399 -0
  50. package/bundled/dev-pipeline-windows/scripts/parse-stream-progress.py +388 -0
  51. package/bundled/dev-pipeline-windows/scripts/patch-completion-notes.py +191 -0
  52. package/bundled/dev-pipeline-windows/scripts/update-bug-status.py +864 -0
  53. package/bundled/dev-pipeline-windows/scripts/update-checkpoint.py +173 -0
  54. package/bundled/dev-pipeline-windows/scripts/update-feature-status.py +1501 -0
  55. package/bundled/dev-pipeline-windows/scripts/update-refactor-status.py +1073 -0
  56. package/bundled/dev-pipeline-windows/scripts/utils.py +542 -0
  57. package/bundled/dev-pipeline-windows/templates/agent-prompts/critic-plan-challenge.md +7 -0
  58. package/bundled/dev-pipeline-windows/templates/agent-prompts/dev-fix.md +7 -0
  59. package/bundled/dev-pipeline-windows/templates/agent-prompts/dev-implement.md +30 -0
  60. package/bundled/dev-pipeline-windows/templates/agent-prompts/dev-resume.md +5 -0
  61. package/bundled/dev-pipeline-windows/templates/agent-prompts/reviewer-review.md +7 -0
  62. package/bundled/dev-pipeline-windows/templates/bootstrap-prompt.md +46 -0
  63. package/bundled/dev-pipeline-windows/templates/bootstrap-tier1.md +43 -0
  64. package/bundled/dev-pipeline-windows/templates/bootstrap-tier2.md +43 -0
  65. package/bundled/dev-pipeline-windows/templates/bootstrap-tier3.md +43 -0
  66. package/bundled/dev-pipeline-windows/templates/bug-fix-list-schema.json +263 -0
  67. package/bundled/dev-pipeline-windows/templates/bugfix-bootstrap-prompt.md +320 -0
  68. package/bundled/dev-pipeline-windows/templates/feature-list-schema.json +237 -0
  69. package/bundled/dev-pipeline-windows/templates/refactor-bootstrap-prompt.md +331 -0
  70. package/bundled/dev-pipeline-windows/templates/refactor-list-schema.json +270 -0
  71. package/bundled/dev-pipeline-windows/templates/sections/ac-verification-checklist.md +13 -0
  72. package/bundled/dev-pipeline-windows/templates/sections/checkpoint-system.md +91 -0
  73. package/bundled/dev-pipeline-windows/templates/sections/context-budget-rules.md +33 -0
  74. package/bundled/dev-pipeline-windows/templates/sections/critical-paths-agent.md +10 -0
  75. package/bundled/dev-pipeline-windows/templates/sections/critical-paths-full.md +12 -0
  76. package/bundled/dev-pipeline-windows/templates/sections/critical-paths-lite.md +7 -0
  77. package/bundled/dev-pipeline-windows/templates/sections/directory-convention-agent.md +8 -0
  78. package/bundled/dev-pipeline-windows/templates/sections/directory-convention-full.md +9 -0
  79. package/bundled/dev-pipeline-windows/templates/sections/directory-convention-lite.md +6 -0
  80. package/bundled/dev-pipeline-windows/templates/sections/failure-capture.md +21 -0
  81. package/bundled/dev-pipeline-windows/templates/sections/feature-context.md +31 -0
  82. package/bundled/dev-pipeline-windows/templates/sections/phase-browser-verification-auto.md +72 -0
  83. package/bundled/dev-pipeline-windows/templates/sections/phase-browser-verification-opencli.md +63 -0
  84. package/bundled/dev-pipeline-windows/templates/sections/phase-browser-verification.md +62 -0
  85. package/bundled/dev-pipeline-windows/templates/sections/phase-commit-full.md +71 -0
  86. package/bundled/dev-pipeline-windows/templates/sections/phase-commit.md +64 -0
  87. package/bundled/dev-pipeline-windows/templates/sections/phase-context-snapshot-agent-suffix.md +23 -0
  88. package/bundled/dev-pipeline-windows/templates/sections/phase-context-snapshot-base.md +24 -0
  89. package/bundled/dev-pipeline-windows/templates/sections/phase-context-snapshot-lite-suffix.md +12 -0
  90. package/bundled/dev-pipeline-windows/templates/sections/phase-critic-plan-full.md +53 -0
  91. package/bundled/dev-pipeline-windows/templates/sections/phase-critic-plan.md +32 -0
  92. package/bundled/dev-pipeline-windows/templates/sections/phase-implement-agent.md +37 -0
  93. package/bundled/dev-pipeline-windows/templates/sections/phase-implement-full.md +50 -0
  94. package/bundled/dev-pipeline-windows/templates/sections/phase-implement-lite.md +52 -0
  95. package/bundled/dev-pipeline-windows/templates/sections/phase-plan-agent.md +27 -0
  96. package/bundled/dev-pipeline-windows/templates/sections/phase-plan-lite.md +27 -0
  97. package/bundled/dev-pipeline-windows/templates/sections/phase-review-agent.md +27 -0
  98. package/bundled/dev-pipeline-windows/templates/sections/phase-review-full.md +29 -0
  99. package/bundled/dev-pipeline-windows/templates/sections/phase-specify-plan-full.md +77 -0
  100. package/bundled/dev-pipeline-windows/templates/sections/phase0-init.md +13 -0
  101. package/bundled/dev-pipeline-windows/templates/sections/phase0-test-baseline.md +23 -0
  102. package/bundled/dev-pipeline-windows/templates/sections/session-context.md +5 -0
  103. package/bundled/dev-pipeline-windows/templates/sections/subagent-timeout-recovery.md +6 -0
  104. package/bundled/dev-pipeline-windows/templates/sections/test-failure-recovery-agent.md +67 -0
  105. package/bundled/dev-pipeline-windows/templates/sections/test-failure-recovery-lite.md +58 -0
  106. package/bundled/dev-pipeline-windows/templates/session-status-schema.json +83 -0
  107. package/bundled/skills/_metadata.json +1 -1
  108. package/bundled/skills/app-planner/SKILL.md +26 -18
  109. package/bundled/skills/app-planner/references/architecture-decisions.md +9 -5
  110. package/bundled/skills/app-planner/references/frontend-design-guide.md +1 -1
  111. package/bundled/skills/feature-planner/SKILL.md +9 -2
  112. package/bundled/skills/prizmkit-init/SKILL.md +7 -6
  113. package/bundled/skills/recovery-workflow/scripts/detect-recovery-state.py +2 -0
  114. package/bundled/skills-windows/app-planner/SKILL.md +639 -0
  115. package/bundled/skills-windows/app-planner/assets/app-design-guide.md +101 -0
  116. package/bundled/skills-windows/app-planner/references/architecture-decisions.md +52 -0
  117. package/bundled/skills-windows/app-planner/references/brainstorm-guide.md +101 -0
  118. package/bundled/skills-windows/app-planner/references/frontend-design-guide.md +71 -0
  119. package/bundled/skills-windows/app-planner/references/project-brief-guide.md +82 -0
  120. package/bundled/skills-windows/app-planner/references/red-team-checklist.md +40 -0
  121. package/bundled/skills-windows/app-planner/references/rules/backend/derivation-rules.md +609 -0
  122. package/bundled/skills-windows/app-planner/references/rules/backend/fixed-rules.md +285 -0
  123. package/bundled/skills-windows/app-planner/references/rules/backend/question-bank.md +249 -0
  124. package/bundled/skills-windows/app-planner/references/rules/backend/template.md +173 -0
  125. package/bundled/skills-windows/app-planner/references/rules/database/derivation-rules.md +373 -0
  126. package/bundled/skills-windows/app-planner/references/rules/database/fixed-rules.md +211 -0
  127. package/bundled/skills-windows/app-planner/references/rules/database/question-bank.md +184 -0
  128. package/bundled/skills-windows/app-planner/references/rules/database/template.md +158 -0
  129. package/bundled/skills-windows/app-planner/references/rules/frontend/derivation-rules.md +810 -0
  130. package/bundled/skills-windows/app-planner/references/rules/frontend/fixed-rules.md +188 -0
  131. package/bundled/skills-windows/app-planner/references/rules/frontend/question-bank.md +302 -0
  132. package/bundled/skills-windows/app-planner/references/rules/frontend/template.md +320 -0
  133. package/bundled/skills-windows/app-planner/references/rules/mobile/derivation-rules.md +639 -0
  134. package/bundled/skills-windows/app-planner/references/rules/mobile/fixed-rules.md +290 -0
  135. package/bundled/skills-windows/app-planner/references/rules/mobile/question-bank.md +232 -0
  136. package/bundled/skills-windows/app-planner/references/rules/mobile/template.md +175 -0
  137. package/bundled/skills-windows/bug-fix-workflow/SKILL.md +415 -0
  138. package/bundled/skills-windows/bug-planner/SKILL.md +395 -0
  139. package/bundled/skills-windows/bug-planner/assets/bug-confirmation-template.md +43 -0
  140. package/bundled/skills-windows/bug-planner/references/critic-and-verification.md +44 -0
  141. package/bundled/skills-windows/bug-planner/references/error-recovery.md +73 -0
  142. package/bundled/skills-windows/bug-planner/references/input-formats.md +53 -0
  143. package/bundled/skills-windows/bug-planner/references/schema-validation.md +25 -0
  144. package/bundled/skills-windows/bug-planner/references/severity-rules.md +16 -0
  145. package/bundled/skills-windows/bug-planner/scripts/validate-bug-list.py +322 -0
  146. package/bundled/skills-windows/bugfix-pipeline-launcher/SKILL.md +380 -0
  147. package/bundled/skills-windows/feature-pipeline-launcher/SKILL.md +441 -0
  148. package/bundled/skills-windows/feature-pipeline-launcher/scripts/preflight-check.py +462 -0
  149. package/bundled/skills-windows/feature-planner/SKILL.md +401 -0
  150. package/bundled/skills-windows/feature-planner/assets/evaluation-guide.md +64 -0
  151. package/bundled/skills-windows/feature-planner/assets/planning-guide.md +214 -0
  152. package/bundled/skills-windows/feature-planner/references/browser-interaction.md +59 -0
  153. package/bundled/skills-windows/feature-planner/references/completeness-review.md +57 -0
  154. package/bundled/skills-windows/feature-planner/references/decomposition-patterns.md +75 -0
  155. package/bundled/skills-windows/feature-planner/references/error-recovery.md +90 -0
  156. package/bundled/skills-windows/feature-planner/references/incremental-feature-planning.md +112 -0
  157. package/bundled/skills-windows/feature-planner/references/new-project-planning.md +85 -0
  158. package/bundled/skills-windows/feature-planner/scripts/validate-and-generate.py +1029 -0
  159. package/bundled/skills-windows/feature-workflow/SKILL.md +531 -0
  160. package/bundled/skills-windows/prizmkit-init/SKILL.md +356 -0
  161. package/bundled/skills-windows/prizmkit-init/assets/project-brief-template.md +82 -0
  162. package/bundled/skills-windows/prizmkit-init/references/config-schema.md +68 -0
  163. package/bundled/skills-windows/prizmkit-init/references/rules/layer-detection.md +41 -0
  164. package/bundled/skills-windows/prizmkit-init/references/tech-stack-catalog.md +13 -0
  165. package/bundled/skills-windows/prizmkit-init/references/update-supplement.md +9 -0
  166. package/bundled/skills-windows/recovery-workflow/SKILL.md +456 -0
  167. package/bundled/skills-windows/recovery-workflow/evals/evals.json +46 -0
  168. package/bundled/skills-windows/recovery-workflow/scripts/detect-recovery-state.py +544 -0
  169. package/bundled/skills-windows/refactor-pipeline-launcher/SKILL.md +406 -0
  170. package/bundled/skills-windows/refactor-planner/SKILL.md +540 -0
  171. package/bundled/skills-windows/refactor-planner/assets/planning-guide.md +292 -0
  172. package/bundled/skills-windows/refactor-planner/references/behavior-preservation.md +301 -0
  173. package/bundled/skills-windows/refactor-planner/references/refactor-scoping-guide.md +221 -0
  174. package/bundled/skills-windows/refactor-planner/scripts/validate-and-generate-refactor.py +858 -0
  175. package/bundled/skills-windows/refactor-workflow/SKILL.md +503 -0
  176. package/package.json +3 -2
  177. package/src/clean.js +73 -2
  178. package/src/config.js +159 -50
  179. package/src/detect-platform.js +16 -8
  180. package/src/external-skills.js +26 -19
  181. package/src/index.js +31 -9
  182. package/src/manifest.js +6 -2
  183. package/src/metadata.js +43 -5
  184. package/src/platforms.js +36 -0
  185. package/src/prompts.js +31 -6
  186. package/src/runtimes.js +20 -0
  187. package/src/scaffold.js +314 -110
  188. package/src/upgrade.js +81 -41
@@ -0,0 +1,542 @@
1
+ #!/usr/bin/env python3
2
+ """Shared utility functions for dev-pipeline scripts.
3
+
4
+ Centralizes common operations (JSON I/O, error reporting, display helpers)
5
+ to avoid duplication across pipeline scripts.
6
+ """
7
+
8
+ import json
9
+ import logging
10
+ import os
11
+ import re
12
+ import sys
13
+
14
+
15
+ def load_json_file(path):
16
+ """Load and return parsed JSON from a file.
17
+
18
+ Returns (data, error_string). On success error_string is None.
19
+ """
20
+ abs_path = os.path.abspath(path)
21
+ if not os.path.isfile(abs_path):
22
+ return None, "File not found: {}".format(abs_path)
23
+ try:
24
+ with open(abs_path, "r", encoding="utf-8") as f:
25
+ data = json.load(f)
26
+ except json.JSONDecodeError as e:
27
+ return None, "Invalid JSON: {}".format(str(e))
28
+ except IOError as e:
29
+ return None, "Cannot read file: {}".format(str(e))
30
+ return data, None
31
+
32
+
33
+ def write_json_file(path, data):
34
+ """Write data as JSON to a file. Creates parent directories if needed.
35
+
36
+ Returns an error string on failure, None on success.
37
+ """
38
+ abs_path = os.path.abspath(path)
39
+ parent = os.path.dirname(abs_path)
40
+ if parent and not os.path.isdir(parent):
41
+ try:
42
+ os.makedirs(parent, exist_ok=True)
43
+ except OSError as e:
44
+ return "Cannot create directory: {}".format(str(e))
45
+ try:
46
+ with open(abs_path, "w", encoding="utf-8") as f:
47
+ json.dump(data, f, indent=2, ensure_ascii=False)
48
+ f.write("\n")
49
+ except IOError as e:
50
+ return "Cannot write file: {}".format(str(e))
51
+ return None
52
+
53
+
54
+ def setup_logging(name="prizmkit.dev_pipeline", level=None):
55
+ """Configure and return a standard logger for pipeline scripts.
56
+
57
+ Logs are written to stderr to avoid interfering with stdout JSON outputs.
58
+ """
59
+ resolved_level = (level or os.environ.get("PRIZMKIT_LOG_LEVEL", "INFO")).upper()
60
+ numeric_level = getattr(logging, resolved_level, logging.INFO)
61
+
62
+ root_logger = logging.getLogger()
63
+ if not root_logger.handlers:
64
+ logging.basicConfig(
65
+ level=numeric_level,
66
+ stream=sys.stderr,
67
+ format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
68
+ )
69
+
70
+ logger = logging.getLogger(name)
71
+ logger.setLevel(numeric_level)
72
+ return logger
73
+
74
+
75
+ def error_out(message, code=1):
76
+ """Print an error JSON and exit with the given code."""
77
+ output = {"error": message}
78
+ print(json.dumps(output, indent=2, ensure_ascii=False))
79
+ sys.exit(code)
80
+
81
+
82
+ def pad_right(text, width):
83
+ """Pad text with spaces to fill width, accounting for ANSI escape codes."""
84
+ i = 0
85
+ visible_len = 0
86
+ while i < len(text):
87
+ if text[i] == "\033":
88
+ while i < len(text) and text[i] != "m":
89
+ i += 1
90
+ i += 1
91
+ else:
92
+ visible_len += 1
93
+ i += 1
94
+ padding = width - visible_len
95
+ if padding > 0:
96
+ return text + " " * padding
97
+ return text
98
+
99
+
100
+ def _build_progress_bar(percent, width=20):
101
+ """Build a text progress bar.
102
+
103
+ Example: ████████░░░░░░░░░░░░ 40%
104
+ """
105
+ filled = int(width * percent / 100)
106
+ empty = width - filled
107
+ bar = "\u2588" * filled + "\u2591" * empty
108
+ return "{} {:>3}%".format(bar, int(percent))
109
+
110
+
111
+ def _read_file_safe(filepath):
112
+ """Read a file and return its content, or empty string on error."""
113
+ try:
114
+ with open(filepath, "r", encoding="utf-8") as f:
115
+ return f.read()
116
+ except (IOError, OSError):
117
+ return ""
118
+
119
+
120
+ def _detect_node_runtime(project_root, pkg):
121
+ """Detect Node.js runtime version from engines, .nvmrc, or .node-version."""
122
+ engines = pkg.get("engines", {})
123
+ node_ver = engines.get("node", "")
124
+ if node_ver:
125
+ return "Node.js {}".format(node_ver)
126
+
127
+ for version_file in [".nvmrc", ".node-version"]:
128
+ vpath = os.path.join(project_root, version_file)
129
+ if os.path.isfile(vpath):
130
+ content = _read_file_safe(vpath).strip()
131
+ if content:
132
+ return "Node.js {}".format(content)
133
+
134
+ return "Node.js"
135
+
136
+
137
+ def _parse_python_deps(py_content, req_content):
138
+ """Extract Python package names from pyproject.toml and requirements.txt.
139
+
140
+ Returns a set of lowercased package names (without version specifiers).
141
+ """
142
+ deps = set()
143
+
144
+ # Parse requirements.txt lines: "package==1.0", "package>=2.0", "package"
145
+ for line in req_content.splitlines():
146
+ line = line.strip()
147
+ if not line or line.startswith("#") or line.startswith("-"):
148
+ continue
149
+ # Split on version specifiers and extras
150
+ name = re.split(r"[>=<!~;\[\s]", line, 1)[0].strip()
151
+ if name:
152
+ deps.add(name.lower())
153
+
154
+ # Parse pyproject.toml dependencies (simplified: look for quoted strings
155
+ # in [project.dependencies] and [project.optional-dependencies.*] sections)
156
+ in_deps_section = False
157
+ for line in py_content.splitlines():
158
+ stripped = line.strip()
159
+ if stripped.startswith("["):
160
+ in_deps_section = (
161
+ "dependencies" in stripped.lower()
162
+ and "optional" not in stripped.lower()
163
+ ) or "dependencies" in stripped.lower()
164
+ continue
165
+ if in_deps_section:
166
+ # Match quoted dependency: "flask>=2.0" or 'django~=4.0'
167
+ match = re.match(r"""^[\s"']*([a-zA-Z0-9_-]+)""", stripped)
168
+ if match:
169
+ deps.add(match.group(1).lower())
170
+
171
+ return deps
172
+
173
+
174
+ def detect_project_context(project_root):
175
+ """Auto-detect project tech stack from project files.
176
+
177
+ Reads package.json, pyproject.toml, requirements.txt, docker-compose,
178
+ and common config files to infer language, frameworks, styling,
179
+ database, ORM, bundler, testing, and project type.
180
+
181
+ Returns a dict of detected key-value pairs. Only detected fields are
182
+ included — no empty or null values. Adapts to any project type
183
+ (frontend-only, backend-only, fullstack, library, CLI, monorepo).
184
+ """
185
+ detected = {}
186
+
187
+ # ── 1. Node.js / JavaScript / TypeScript project ──
188
+ pkg_path = os.path.join(project_root, "package.json")
189
+ if os.path.isfile(pkg_path):
190
+ try:
191
+ with open(pkg_path, "r", encoding="utf-8") as f:
192
+ pkg = json.load(f)
193
+
194
+ # All dependencies combined for detection
195
+ deps = {}
196
+ deps.update(pkg.get("dependencies", {}))
197
+ deps.update(pkg.get("devDependencies", {}))
198
+
199
+ # Language
200
+ if "typescript" in deps or os.path.isfile(
201
+ os.path.join(project_root, "tsconfig.json")
202
+ ):
203
+ detected["language"] = "TypeScript"
204
+ else:
205
+ detected["language"] = "JavaScript"
206
+
207
+ # Runtime
208
+ detected["runtime"] = _detect_node_runtime(project_root, pkg)
209
+
210
+ # Test framework (more specific first)
211
+ scripts = pkg.get("scripts", {})
212
+ test_script = (
213
+ scripts.get("test", "")
214
+ + " "
215
+ + scripts.get("test:unit", "")
216
+ )
217
+ if "vitest" in deps or "vitest" in test_script:
218
+ detected["testing_framework"] = "Vitest"
219
+ elif "jest" in deps or "jest" in test_script:
220
+ detected["testing_framework"] = "Jest"
221
+ elif "mocha" in deps or "mocha" in test_script:
222
+ detected["testing_framework"] = "Mocha"
223
+ elif "--test" in test_script or "node:test" in test_script:
224
+ detected["testing_framework"] = "Node.js built-in test runner"
225
+
226
+ # ── Frontend framework ──
227
+ frontend_frameworks = [
228
+ ("next", "Next.js"),
229
+ ("nuxt", "Nuxt"),
230
+ ("@angular/core", "Angular"),
231
+ ("svelte", "Svelte"),
232
+ ("solid-js", "Solid.js"),
233
+ ("react", "React"),
234
+ ("vue", "Vue.js"),
235
+ ]
236
+ for dep_name, fw_name in frontend_frameworks:
237
+ if dep_name in deps:
238
+ detected["frontend_framework"] = fw_name
239
+ break
240
+
241
+ # ── Backend framework ──
242
+ backend_frameworks = [
243
+ ("@nestjs/core", "NestJS"),
244
+ ("express", "Express.js"),
245
+ ("fastify", "Fastify"),
246
+ ("koa", "Koa"),
247
+ ("hapi", "Hapi"),
248
+ ("hono", "Hono"),
249
+ ]
250
+ for dep_name, fw_name in backend_frameworks:
251
+ if dep_name in deps:
252
+ detected["backend_framework"] = fw_name
253
+ break
254
+
255
+ # Legacy "framework" field for backward compatibility
256
+ if "frontend_framework" in detected:
257
+ detected["framework"] = detected["frontend_framework"]
258
+ elif "backend_framework" in detected:
259
+ detected["framework"] = detected["backend_framework"]
260
+
261
+ # ── Frontend styling ──
262
+ styling_libs = [
263
+ ("tailwindcss", "Tailwind CSS"),
264
+ ("@tailwindcss/vite", "Tailwind CSS"),
265
+ ("styled-components", "Styled Components"),
266
+ ("@emotion/react", "Emotion"),
267
+ ("@emotion/styled", "Emotion"),
268
+ ("@mui/material", "Material UI"),
269
+ ("@chakra-ui/react", "Chakra UI"),
270
+ ("antd", "Ant Design"),
271
+ ("sass", "SCSS/Sass"),
272
+ ("node-sass", "SCSS/Sass"),
273
+ ("less", "Less"),
274
+ ]
275
+ for dep_name, style_name in styling_libs:
276
+ if dep_name in deps:
277
+ detected["frontend_styling"] = style_name
278
+ break
279
+
280
+ # ── Database ──
281
+ db_libs = [
282
+ ("pg", "PostgreSQL"),
283
+ ("postgres", "PostgreSQL"),
284
+ ("mysql2", "MySQL"),
285
+ ("mysql", "MySQL"),
286
+ ("better-sqlite3", "SQLite"),
287
+ ("mongodb", "MongoDB"),
288
+ ("mongoose", "MongoDB"),
289
+ ("redis", "Redis"),
290
+ ("ioredis", "Redis"),
291
+ ]
292
+ for dep_name, db_name in db_libs:
293
+ if dep_name in deps:
294
+ detected["database"] = db_name
295
+ break
296
+
297
+ # ── ORM ──
298
+ orm_libs = [
299
+ ("@prisma/client", "Prisma"),
300
+ ("prisma", "Prisma"),
301
+ ("drizzle-orm", "Drizzle"),
302
+ ("typeorm", "TypeORM"),
303
+ ("sequelize", "Sequelize"),
304
+ ("mongoose", "Mongoose"),
305
+ ("knex", "Knex.js"),
306
+ ("@mikro-orm/core", "MikroORM"),
307
+ ]
308
+ for dep_name, orm_name in orm_libs:
309
+ if dep_name in deps:
310
+ detected["orm"] = orm_name
311
+ break
312
+
313
+ # ── Bundler ──
314
+ bundler_libs = [
315
+ ("vite", "Vite"),
316
+ ("webpack", "Webpack"),
317
+ ("esbuild", "esbuild"),
318
+ ("rollup", "Rollup"),
319
+ ("parcel", "Parcel"),
320
+ ("turbo", "Turborepo"),
321
+ ("@rspack/core", "Rspack"),
322
+ ]
323
+ for dep_name, bundler_name in bundler_libs:
324
+ if dep_name in deps:
325
+ detected["bundler"] = bundler_name
326
+ break
327
+
328
+ # ── Project type inference ──
329
+ has_frontend = "frontend_framework" in detected
330
+ has_backend = "backend_framework" in detected
331
+ has_workspaces = "workspaces" in pkg
332
+ has_bin = "bin" in pkg
333
+
334
+ if has_workspaces:
335
+ detected["project_type"] = "monorepo"
336
+ elif has_frontend and has_backend:
337
+ detected["project_type"] = "fullstack"
338
+ elif has_frontend:
339
+ detected["project_type"] = "frontend"
340
+ elif has_backend:
341
+ detected["project_type"] = "backend"
342
+ elif has_bin:
343
+ detected["project_type"] = "cli"
344
+ elif "main" in pkg or "exports" in pkg:
345
+ detected["project_type"] = "library"
346
+
347
+ except (json.JSONDecodeError, IOError):
348
+ pass
349
+
350
+ # ── 2. Python project detection ──
351
+ if "language" not in detected:
352
+ py_content = ""
353
+ for marker in ["pyproject.toml", "setup.py", "requirements.txt"]:
354
+ marker_path = os.path.join(project_root, marker)
355
+ if os.path.isfile(marker_path):
356
+ detected["language"] = "Python"
357
+ if marker == "pyproject.toml":
358
+ py_content = _read_file_safe(marker_path)
359
+ break
360
+
361
+ if detected.get("language") == "Python":
362
+ req_path = os.path.join(project_root, "requirements.txt")
363
+ req_content = _read_file_safe(req_path) if os.path.isfile(req_path) else ""
364
+ py_deps = _parse_python_deps(py_content, req_content)
365
+
366
+ # Runtime version (regex for requires-python = ">=3.11")
367
+ if py_content:
368
+ ver_match = re.search(
369
+ r'requires-python\s*=\s*["\']([^"\']+)["\']', py_content
370
+ )
371
+ if ver_match:
372
+ detected["runtime"] = "Python {}".format(ver_match.group(1))
373
+
374
+ # Testing
375
+ if "pytest" in py_deps:
376
+ detected["testing_framework"] = "pytest"
377
+
378
+ # Backend framework
379
+ py_backend = [
380
+ ("django", "Django"),
381
+ ("fastapi", "FastAPI"),
382
+ ("flask", "Flask"),
383
+ ("starlette", "Starlette"),
384
+ ("tornado", "Tornado"),
385
+ ("aiohttp", "aiohttp"),
386
+ ]
387
+ for dep_name, fw_name in py_backend:
388
+ if dep_name in py_deps:
389
+ detected["backend_framework"] = fw_name
390
+ detected["framework"] = fw_name
391
+ break
392
+
393
+ # Database / ORM
394
+ py_db = [
395
+ ("psycopg2", "PostgreSQL"),
396
+ ("psycopg", "PostgreSQL"),
397
+ ("asyncpg", "PostgreSQL"),
398
+ ("pymysql", "MySQL"),
399
+ ("pymongo", "MongoDB"),
400
+ ("motor", "MongoDB"),
401
+ ]
402
+ for dep_name, db_name in py_db:
403
+ if dep_name in py_deps:
404
+ detected["database"] = db_name
405
+ break
406
+
407
+ py_orm = [
408
+ ("sqlalchemy", "SQLAlchemy"),
409
+ ("tortoise-orm", "Tortoise ORM"),
410
+ ("peewee", "Peewee"),
411
+ ]
412
+ for dep_name, orm_name in py_orm:
413
+ if dep_name in py_deps:
414
+ detected["orm"] = orm_name
415
+ break
416
+ # Django ORM: if django is a dep and no other ORM detected
417
+ if "django" in py_deps and "orm" not in detected:
418
+ detected["orm"] = "Django ORM"
419
+
420
+ # Project type
421
+ if "backend_framework" in detected:
422
+ detected["project_type"] = "backend"
423
+
424
+ # ── 3. Go project detection ──
425
+ if "language" not in detected:
426
+ go_mod_path = os.path.join(project_root, "go.mod")
427
+ if os.path.isfile(go_mod_path):
428
+ detected["language"] = "Go"
429
+ detected["runtime"] = "Go"
430
+ go_content = _read_file_safe(go_mod_path)
431
+ if "gin-gonic" in go_content:
432
+ detected["backend_framework"] = "Gin"
433
+ elif "labstack/echo" in go_content:
434
+ detected["backend_framework"] = "Echo"
435
+ elif "go-chi/chi" in go_content:
436
+ detected["backend_framework"] = "Chi"
437
+ if "backend_framework" in detected:
438
+ detected["framework"] = detected["backend_framework"]
439
+ detected["project_type"] = "backend"
440
+
441
+ # ── 4. Rust / Java / other languages (basic detection) ──
442
+ if "language" not in detected:
443
+ if os.path.isfile(os.path.join(project_root, "Cargo.toml")):
444
+ detected["language"] = "Rust"
445
+ detected["runtime"] = "Rust"
446
+ elif os.path.isfile(os.path.join(project_root, "pom.xml")):
447
+ detected["language"] = "Java"
448
+ detected["runtime"] = "Java (Maven)"
449
+ elif os.path.isfile(os.path.join(project_root, "build.gradle")):
450
+ detected["language"] = "Java/Kotlin"
451
+ detected["runtime"] = "Java (Gradle)"
452
+
453
+ # ── 5. Database from docker-compose (cross-language) ──
454
+ if "database" not in detected:
455
+ for dc_name in [
456
+ "docker-compose.yml",
457
+ "docker-compose.yaml",
458
+ "compose.yml",
459
+ "compose.yaml",
460
+ ]:
461
+ dc_path = os.path.join(project_root, dc_name)
462
+ if os.path.isfile(dc_path):
463
+ dc_content = _read_file_safe(dc_path).lower()
464
+ dc_db = [
465
+ ("postgres", "PostgreSQL"),
466
+ ("mysql", "MySQL"),
467
+ ("mariadb", "MariaDB"),
468
+ ("mongo", "MongoDB"),
469
+ ("redis", "Redis"),
470
+ ("sqlite", "SQLite"),
471
+ ]
472
+ for pattern, db_name in dc_db:
473
+ if pattern in dc_content:
474
+ detected["database"] = db_name
475
+ break
476
+ break
477
+
478
+ return detected
479
+
480
+
481
+ def enrich_global_context(global_context, project_root):
482
+ """Fill gaps in global_context using auto-detected project info.
483
+
484
+ Only adds auto-detected values for keys not already present.
485
+ Mutates global_context in place and returns it.
486
+ """
487
+ if not project_root:
488
+ return global_context
489
+
490
+ detected = detect_project_context(project_root)
491
+ # Map detected keys → global_context convention names
492
+ key_mapping = {
493
+ "language": "language",
494
+ "testing_framework": "testing_strategy",
495
+ "framework": "framework",
496
+ "frontend_framework": "frontend_framework",
497
+ "frontend_styling": "frontend_styling",
498
+ "backend_framework": "backend_framework",
499
+ "database": "database",
500
+ "orm": "orm",
501
+ "bundler": "bundler",
502
+ "project_type": "project_type",
503
+ "runtime": "runtime",
504
+ }
505
+ # Alternate key names that should block auto-detection
506
+ alt_keys = {
507
+ "testing_strategy": ["testing_framework", "test_framework", "testing"],
508
+ }
509
+ for det_key, ctx_key in key_mapping.items():
510
+ if det_key not in detected:
511
+ continue
512
+ if ctx_key in global_context:
513
+ continue
514
+ already_set = any(
515
+ k in global_context for k in alt_keys.get(ctx_key, [])
516
+ )
517
+ if not already_set:
518
+ global_context[ctx_key] = detected[det_key] + " (auto-detected)"
519
+
520
+ return global_context
521
+
522
+
523
+ def read_platform_conventions(project_root):
524
+ """Resolve the platform-specific project conventions file.
525
+
526
+ Returns a path reference for the AI agent to read at runtime,
527
+ rather than inlining the full file content into the prompt.
528
+ """
529
+ platform = os.environ.get("PRIZMKIT_PLATFORM", "claude")
530
+ if platform == "codebuddy":
531
+ candidates = ["CODEBUDDY.md", "CLAUDE.md", "AGENTS.md"]
532
+ elif platform == "codex":
533
+ candidates = ["AGENTS.md", "CLAUDE.md", "CODEBUDDY.md"]
534
+ else:
535
+ candidates = ["CLAUDE.md", "CODEBUDDY.md", "AGENTS.md"]
536
+
537
+ for filename in candidates:
538
+ filepath = os.path.join(project_root, filename)
539
+ if os.path.isfile(filepath):
540
+ return "`{}`".format(filename)
541
+
542
+ return "(No project conventions file found — AGENTS.md, CLAUDE.md, or CODEBUDDY.md)"
@@ -0,0 +1,7 @@
1
+ "Read {{CRITIC_SUBAGENT_PATH}}. For feature {{FEATURE_ID}} (slug: {{FEATURE_SLUG}}):
2
+ **MODE: Plan Challenge**
3
+ 1. Read `.prizmkit/specs/{{FEATURE_SLUG}}/context-snapshot.md` FIRST — Section 3 has project context, Section 4 has file manifest.
4
+ 2. Read `.prizmkit/prizm-docs/root.prizm` and relevant L1/L2 docs for affected modules.
5
+ 3. Read existing source files in the modules this plan touches.
6
+ 4. Challenge plan.md against the project's existing architecture, patterns, and style.
7
+ Write `.prizmkit/specs/{{FEATURE_SLUG}}/challenge-report.md` with findings (or 'No significant challenges')."
@@ -0,0 +1,7 @@
1
+ "Read {{DEV_SUBAGENT_PATH}}. Fix NEEDS_FIXES issues for feature {{FEATURE_ID}} (slug: {{FEATURE_SLUG}}).
2
+ 1. Read `.prizmkit/specs/{{FEATURE_SLUG}}/review-report.md` — contains structured Fix Instructions with exact steps.
3
+ 2. Follow Fix Instructions in order (respect Depends On / Blocks dependencies). Each FIX-N has: Root Cause, Fix Strategy, Code Guidance, and Verification criteria.
4
+ 3. After each fix, run the Verification command listed in that FIX-N to confirm it works.
5
+ 4. Run `{{TEST_CMD}}` to verify no regressions.
6
+ 5. Append fix summary to '## Implementation Log' in context-snapshot.md.
7
+ 6. Do NOT execute any git commands."
@@ -0,0 +1,30 @@
1
+ "Read {{DEV_SUBAGENT_PATH}}. Implement feature {{FEATURE_ID}} (slug: {{FEATURE_SLUG}}).
2
+ **IMPORTANT**: Read `.prizmkit/specs/{{FEATURE_SLUG}}/context-snapshot.md` FIRST — Section 3 has Prizm Context (TRAPS/RULES), Section 4 has File Manifest with paths and interfaces.
3
+ ⚠️ DO NOT re-read source files already listed in Section 4 File Manifest unless you need implementation detail beyond the interface summary.
4
+ 1. Read `.prizmkit/specs/{{FEATURE_SLUG}}/context-snapshot.md` for full context.
5
+ 2. Run `/prizmkit-implement` to execute the tasks in plan.md. Run tests with: `{{TEST_CMD}}`. Known baseline failures (pre-existing, not your fault): `{{BASELINE_FAILURES}}`.
6
+ 3. If plan.md has more than 5 tasks: run `/compact` after completing every 3 tasks to manage context budget. If `/compact` is unavailable, continue without it.
7
+ 4. After implement completes, verify the '## Implementation Log' section was written to context-snapshot.md.
8
+
9
+ ## Acceptance Criteria Verification
10
+
11
+ Update the AC Verification Checklist in context-snapshot.md by marking each item [x] as you verify it:
12
+ - As you complete each task, verify the corresponding acceptance criteria
13
+ - Check the AC Checklist at the end of implementation
14
+ - All [ ] must become [x] — if any AC remains unverified, the feature is incomplete
15
+ - Document any AC that cannot be verified due to test failures
16
+
17
+ ## Test Failure Recovery (Convergence-Based)
18
+
19
+ If tests fail, use convergence recovery — keep fixing while progress is being made:
20
+
21
+ 1. **Run tests, record results**: count failures, exclude baseline failures
22
+ 2. **Check termination**: All pass → done | Plateau (same failures 3 rounds) → stop | Failures decreased → continue
23
+ 3. **Fix and iterate**: analyze, apply fix, re-run `{{TEST_CMD}}`, go back to step 1
24
+
25
+ **Key rule**: If failures decrease (even by 1), plateau counter resets.
26
+ **Do NOT block completion** if unable to resolve — only NEW REGRESSIONS (not in baseline) require fixing.
27
+ **If any AC cannot be verified** due to test failure: the feature is incomplete, add to failure notes.
28
+
29
+ 4. Do NOT execute any git commands (no git add/commit/reset/push).
30
+ Do NOT exit until all tasks are [x], the '## Implementation Log' section is written, and AC Verification Checklist is 100% complete in context-snapshot.md."
@@ -0,0 +1,5 @@
1
+ "Read {{DEV_SUBAGENT_PATH}}. You are resuming implementation of feature {{FEATURE_ID}} (slug: {{FEATURE_SLUG}}).
2
+ 1. Read `.prizmkit/specs/{{FEATURE_SLUG}}/context-snapshot.md` — Section 4 has File Manifest, 'Implementation Log' (if present) shows what was already done.
3
+ 2. Run `git diff HEAD` to see actual code changes already made.
4
+ 3. Run `/prizmkit-implement` to complete the remaining `[ ]` tasks. Run tests with: `{{TEST_CMD}}`.
5
+ 4. Do NOT execute any git commands."
@@ -0,0 +1,7 @@
1
+ "Read {{REVIEWER_SUBAGENT_PATH}}. For feature {{FEATURE_ID}} (slug: {{FEATURE_SLUG}}):
2
+ 1. Read `.prizmkit/specs/{{FEATURE_SLUG}}/spec.md` (if it exists) for goals and acceptance criteria; if spec.md does not exist, read `.prizmkit/specs/{{FEATURE_SLUG}}/context-snapshot.md` Section 1 instead
3
+ 2. Read `.prizmkit/specs/{{FEATURE_SLUG}}/plan.md` for architecture decisions and completed tasks
4
+ 3. Run /prizmkit-code-review with artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/. The skill will run its internal review-fix loop (Reviewer → filter → Dev fix, max 3 rounds) and write review-report.md.
5
+ 4. Run the full test suite using `{{TEST_CMD}}`. When running tests: `({{TEST_CMD}}) 2>&1 | Tee-Object (Join-Path $env:TEMP "review-test-out.txt") | Select-Object -Last 20`, then Select-String (Join-Path $env:TEMP "review-test-out.txt") for details — do NOT re-run the suite multiple times.
6
+ 5. review-report.md will be written to .prizmkit/specs/{{FEATURE_SLUG}}/ by prizmkit-code-review.
7
+ Report: verdict (PASS/NEEDS_FIXES), number of rounds, findings fixed/rejected."
@@ -0,0 +1,46 @@
1
+ # Dev-Pipeline Fallback Bootstrap Prompt
2
+
3
+ > **Note**: This is an emergency fallback template. Normally, `generate-bootstrap-prompt.py`
4
+ > selects a tier-specific template (`bootstrap-tier1.md`, `bootstrap-tier2.md`, or `bootstrap-tier3.md`).
5
+ > If you are seeing this prompt, the tier-specific templates were not found.
6
+
7
+ ## Feature Context
8
+
9
+ - **Feature ID**: {{FEATURE_ID}}
10
+ - **Title**: {{FEATURE_TITLE}}
11
+ - **Description**: {{FEATURE_DESCRIPTION}}
12
+ - **Slug**: {{FEATURE_SLUG}}
13
+
14
+ {{USER_CONTEXT}}
15
+
16
+ ### Acceptance Criteria
17
+
18
+ {{ACCEPTANCE_CRITERIA}}
19
+
20
+ ## Instructions
21
+
22
+ You are running in **headless non-interactive mode** — no human is available for input.
23
+ Infer what needs to be done from the feature context above and follow the standard dev loop.
24
+
25
+ ### Execution Steps
26
+
27
+ 1. **Read context**: Read `.prizmkit/prizm-docs/root.prizm` and relevant L1/L2 docs to understand the codebase.
28
+
29
+ 2. **Plan**: Run `/prizmkit-plan` with `artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/` to produce `spec.md` and `plan.md`.
30
+
31
+ 3. **Implement**: Run `/prizmkit-implement` with `artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/` to execute the plan using TDD (write tests first, then implement).
32
+
33
+ 4. **Test**: Run the project test suite to verify all tests pass with no regressions.
34
+
35
+ 5. **Review**: Run `/prizmkit-code-review` with `artifact_dir=.prizmkit/specs/{{FEATURE_SLUG}}/` to review and auto-fix changes against the spec (internal review-fix loop, max 3 rounds).
36
+
37
+ 6. **Retrospective**: Run `/prizmkit-retrospective` to sync `.prizmkit/prizm-docs/` with code changes.
38
+
39
+ 7. **Commit**: Run `/prizmkit-committer --headless` to commit all changes. Do NOT push.
40
+
41
+ ### Critical Rules
42
+
43
+ - Do NOT ask for user input — decide autonomously.
44
+ - Do NOT push to remote — the user will push manually.
45
+ - Write all artifacts to `.prizmkit/specs/{{FEATURE_SLUG}}/`.
46
+ - If a step fails after 3 attempts, write a status report and stop.