claude-dev-env 1.38.0 → 1.39.0

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 (271) hide show
  1. package/CLAUDE.md +10 -36
  2. package/_shared/pr-loop/audit-reply-template.md +147 -0
  3. package/_shared/pr-loop/fix-protocol.md +25 -4
  4. package/_shared/pr-loop/gh-payloads.md +37 -50
  5. package/_shared/pr-loop/scripts/code_rules_gate.py +0 -60
  6. package/_shared/pr-loop/scripts/config/post_audit_thread_constants.py +189 -0
  7. package/_shared/pr-loop/scripts/post_audit_thread.py +947 -0
  8. package/_shared/pr-loop/scripts/tests/test_code_rules_gate.py +0 -19
  9. package/_shared/pr-loop/scripts/tests/test_post_audit_thread.py +923 -0
  10. package/_shared/pr-loop/scripts/tests/test_post_audit_thread_constants.py +127 -0
  11. package/_shared/pr-loop/state-schema.md +1 -1
  12. package/agents/clean-coder.md +2 -2
  13. package/bin/install.mjs +6 -7
  14. package/bin/install.test.mjs +8 -0
  15. package/commands/doc-gist.md +16 -0
  16. package/commands/plan.md +0 -2
  17. package/commands/review-plan.md +1 -1
  18. package/docs/CODE_RULES.md +122 -2
  19. package/hooks/blocking/bot_mention_comment_blocker.py +75 -0
  20. package/hooks/blocking/code_rules_enforcer.py +1236 -161
  21. package/hooks/blocking/convergence_gate_blocker.py +130 -0
  22. package/hooks/blocking/destructive_command_blocker.py +74 -0
  23. package/hooks/blocking/gh_body_arg_blocker.py +30 -0
  24. package/hooks/blocking/md_to_html_blocker.py +119 -0
  25. package/hooks/blocking/test_bot_mention_comment_blocker.py +131 -0
  26. package/hooks/blocking/test_code_rules_enforcer.py +21 -0
  27. package/hooks/blocking/test_code_rules_enforcer_any_exempt_files.py +70 -0
  28. package/hooks/blocking/test_code_rules_enforcer_any_imports_and_cast.py +92 -0
  29. package/hooks/blocking/test_code_rules_enforcer_banned_import_alias.py +143 -0
  30. package/hooks/blocking/test_code_rules_enforcer_banned_prefixes.py +152 -0
  31. package/hooks/blocking/test_code_rules_enforcer_bare_except.py +120 -0
  32. package/hooks/blocking/test_code_rules_enforcer_boundary_types.py +175 -0
  33. package/hooks/blocking/test_code_rules_enforcer_cap_meta.py +0 -1
  34. package/hooks/blocking/test_code_rules_enforcer_collection_prefix.py +50 -0
  35. package/hooks/blocking/test_code_rules_enforcer_docstring_format.py +255 -0
  36. package/hooks/blocking/test_code_rules_enforcer_inline_tuple_string_magic.py +130 -0
  37. package/hooks/blocking/test_code_rules_enforcer_stub_implementations.py +141 -0
  38. package/hooks/blocking/test_code_rules_enforcer_test_branching.py +143 -0
  39. package/hooks/blocking/test_code_rules_enforcer_thin_wrapper_files.py +169 -0
  40. package/hooks/blocking/test_code_rules_enforcer_todo_markers.py +99 -0
  41. package/hooks/blocking/test_code_rules_enforcer_typed_dict_pairs.py +141 -0
  42. package/hooks/blocking/test_code_rules_enforcer_unused_imports.py +158 -0
  43. package/hooks/blocking/test_convergence_gate_blocker.py +63 -0
  44. package/hooks/blocking/test_destructive_command_blocker.py +146 -0
  45. package/hooks/blocking/test_destructive_command_blocker_no_verify.py +102 -0
  46. package/hooks/blocking/test_gh_body_arg_blocker.py +45 -0
  47. package/hooks/blocking/test_md_to_html_blocker.py +317 -0
  48. package/hooks/config/any_type_config.py +7 -0
  49. package/hooks/config/banned_identifiers_constants.py +11 -0
  50. package/hooks/config/blocking_check_limits.py +38 -0
  51. package/hooks/config/bot_mention_comment_blocker_constants.py +20 -0
  52. package/hooks/config/code_rules_enforcer_constants.py +53 -0
  53. package/hooks/config/convergence_branch_constants.py +9 -0
  54. package/hooks/config/doc_gist_auto_publish_constants.py +18 -0
  55. package/hooks/config/html_companion_constants.py +20 -0
  56. package/hooks/config/inline_tuple_string_magic_constants.py +22 -0
  57. package/hooks/config/test_banned_identifiers_constants.py +17 -0
  58. package/hooks/hooks.json +28 -20
  59. package/hooks/pyproject.toml +69 -0
  60. package/hooks/validators/mypy_integration.py +47 -1
  61. package/hooks/validators/run_all_validators.py +3 -3
  62. package/hooks/validators/test_mypy_integration.py +50 -1
  63. package/hooks/workflow/doc_gist_auto_publish.py +144 -0
  64. package/hooks/workflow/md_to_html_companion.py +365 -0
  65. package/hooks/workflow/test_doc_gist_auto_publish.py +117 -0
  66. package/hooks/workflow/test_md_to_html_companion.py +452 -0
  67. package/package.json +1 -1
  68. package/rules/gh-body-file.md +2 -0
  69. package/scripts/Install-SweepEmptyDirs.ps1 +111 -0
  70. package/scripts/check.ps1 +106 -0
  71. package/scripts/config/timing.py +11 -0
  72. package/scripts/sweep_empty_dirs.py +138 -0
  73. package/scripts/sync_to_cursor/rules.py +1 -1
  74. package/scripts/test_sweep_empty_dirs.py +183 -0
  75. package/skills/_shared/pr-loop/prompts/pr-consistency-audit.xml +323 -0
  76. package/skills/_shared/pr-loop/scripts/_cli_utils.py +22 -0
  77. package/skills/_shared/pr-loop/scripts/_path_resolver.py +165 -0
  78. package/skills/_shared/pr-loop/scripts/_xml_utils.py +20 -0
  79. package/skills/_shared/pr-loop/scripts/build_audit_prompt.py +182 -0
  80. package/skills/_shared/pr-loop/scripts/build_fix_prompt.py +185 -0
  81. package/skills/_shared/pr-loop/scripts/config/__init__.py +0 -0
  82. package/skills/_shared/pr-loop/scripts/config/path_resolver_constants.py +78 -0
  83. package/skills/_shared/pr-loop/scripts/init_loop_state.py +135 -0
  84. package/skills/_shared/pr-loop/scripts/teardown_worktrees.py +175 -0
  85. package/skills/_shared/pr-loop/scripts/write_audit_outcomes.py +182 -0
  86. package/skills/_shared/pr-loop/scripts/write_fix_outcomes.py +206 -0
  87. package/skills/bugteam/CONSTRAINTS.md +21 -22
  88. package/skills/bugteam/EXAMPLES.md +3 -3
  89. package/skills/bugteam/PROMPTS.md +227 -67
  90. package/skills/bugteam/SKILL.md +114 -455
  91. package/skills/bugteam/reference/README.md +1 -1
  92. package/skills/bugteam/reference/audit-and-teammates.md +112 -39
  93. package/skills/bugteam/reference/audit-contract.md +4 -22
  94. package/skills/bugteam/reference/copilot-gap-analysis.md +8 -5
  95. package/skills/bugteam/reference/design-rationale.md +2 -2
  96. package/skills/bugteam/reference/github-pr-reviews.md +50 -57
  97. package/skills/bugteam/reference/obstacles/audit-assign-ids.md +13 -0
  98. package/skills/bugteam/reference/obstacles/audit-capture-excerpts.md +13 -0
  99. package/skills/bugteam/reference/obstacles/audit-walk-categories.md +13 -0
  100. package/skills/bugteam/reference/obstacles/audit-write-xml.md +13 -0
  101. package/skills/bugteam/reference/obstacles/fix-append-summary.md +13 -0
  102. package/skills/bugteam/reference/obstacles/fix-apply-fixes.md +13 -0
  103. package/skills/bugteam/reference/obstacles/fix-git-add-commit.md +13 -0
  104. package/skills/bugteam/reference/obstacles/fix-git-push.md +13 -0
  105. package/skills/bugteam/reference/obstacles/fix-post-reply.md +13 -0
  106. package/skills/bugteam/reference/obstacles/fix-publish-summary.md +13 -0
  107. package/skills/bugteam/reference/obstacles/fix-py-compile.md +13 -0
  108. package/skills/bugteam/reference/obstacles/fix-read-files.md +13 -0
  109. package/skills/bugteam/reference/obstacles/fix-resolve-thread.md +13 -0
  110. package/skills/bugteam/reference/obstacles/fix-test-suite.md +13 -0
  111. package/skills/bugteam/reference/obstacles/fix-violation-count.md +13 -0
  112. package/skills/bugteam/reference/obstacles/fix-write-xml.md +13 -0
  113. package/skills/bugteam/reference/team-setup.md +106 -9
  114. package/skills/bugteam/reference/teardown-publish-permissions.md +39 -8
  115. package/skills/bugteam/scripts/README.md +60 -0
  116. package/skills/bugteam/scripts/_claude_permissions_common.py +358 -0
  117. package/skills/bugteam/scripts/bugteam_code_rules_gate.py +976 -0
  118. package/skills/bugteam/scripts/bugteam_fix_hookspath.py +375 -0
  119. package/skills/bugteam/scripts/bugteam_preflight.py +294 -0
  120. package/skills/bugteam/scripts/config/bugteam_code_rules_gate_constants.py +25 -0
  121. package/skills/bugteam/scripts/config/bugteam_fix_hookspath_constants.py +26 -0
  122. package/skills/bugteam/scripts/config/bugteam_preflight_constants.py +35 -0
  123. package/skills/bugteam/scripts/config/claude_permissions_common_constants.py +20 -0
  124. package/skills/bugteam/scripts/config/probe_code_rules_enforcer_check_constants.py +12 -0
  125. package/skills/bugteam/scripts/config/windows_safe_rmtree_constants.py +7 -0
  126. package/skills/bugteam/scripts/grant_project_claude_permissions.py +175 -0
  127. package/skills/bugteam/scripts/probe_code_rules_enforcer_check.py +107 -0
  128. package/skills/bugteam/scripts/revoke_project_claude_permissions.py +220 -0
  129. package/skills/bugteam/scripts/test__claude_permissions_common.py +112 -0
  130. package/skills/bugteam/scripts/test_bugteam_code_rules_gate.py +400 -0
  131. package/skills/bugteam/scripts/test_bugteam_fix_hookspath.py +384 -0
  132. package/skills/bugteam/scripts/test_bugteam_preflight.py +268 -0
  133. package/skills/bugteam/scripts/test_claude_permissions_common.py +195 -0
  134. package/skills/bugteam/scripts/test_grant_project_claude_permissions.py +55 -0
  135. package/skills/bugteam/scripts/test_probe_code_rules_enforcer_check.py +76 -0
  136. package/skills/bugteam/scripts/test_revoke_project_claude_permissions.py +55 -0
  137. package/skills/bugteam/scripts/test_windows_safe_rmtree.py +108 -0
  138. package/skills/bugteam/scripts/windows_safe_rmtree.py +100 -0
  139. package/skills/bugteam/test_skill_additions.py +1 -11
  140. package/skills/code/SKILL.md +176 -0
  141. package/skills/doc-gist/SKILL.md +99 -0
  142. package/skills/doc-gist/references/examples/01-exploration-code-approaches.html +453 -0
  143. package/skills/doc-gist/references/examples/02-exploration-visual-designs.html +515 -0
  144. package/skills/doc-gist/references/examples/03-code-review-pr.html +638 -0
  145. package/skills/doc-gist/references/examples/04-code-understanding.html +491 -0
  146. package/skills/doc-gist/references/examples/05-design-system.html +629 -0
  147. package/skills/doc-gist/references/examples/06-component-variants.html +605 -0
  148. package/skills/doc-gist/references/examples/07-prototype-animation.html +455 -0
  149. package/skills/doc-gist/references/examples/08-prototype-interaction.html +396 -0
  150. package/skills/doc-gist/references/examples/09-slide-deck.html +592 -0
  151. package/skills/doc-gist/references/examples/10-svg-illustrations.html +492 -0
  152. package/skills/doc-gist/references/examples/11-status-report.html +528 -0
  153. package/skills/doc-gist/references/examples/12-incident-report.html +596 -0
  154. package/skills/doc-gist/references/examples/13-flowchart-diagram.html +395 -0
  155. package/skills/doc-gist/references/examples/14-research-feature-explainer.html +381 -0
  156. package/skills/doc-gist/references/examples/15-research-concept-explainer.html +368 -0
  157. package/skills/doc-gist/references/examples/16-implementation-plan.html +702 -0
  158. package/skills/doc-gist/references/examples/17-pr-writeup.html +595 -0
  159. package/skills/doc-gist/references/examples/18-editor-triage-board.html +573 -0
  160. package/skills/doc-gist/references/examples/19-editor-feature-flags.html +663 -0
  161. package/skills/doc-gist/references/examples/20-editor-prompt-tuner.html +722 -0
  162. package/skills/doc-gist/references/examples/README.md +5 -0
  163. package/skills/doc-gist/scripts/config/__init__.py +0 -0
  164. package/skills/doc-gist/scripts/config/gist_upload_constants.py +16 -0
  165. package/skills/doc-gist/scripts/gist_upload.py +177 -0
  166. package/skills/doc-gist/scripts/test_gist_upload.py +51 -0
  167. package/skills/findbugs/SKILL.md +68 -2
  168. package/skills/monitor-open-prs/SKILL.md +13 -32
  169. package/skills/monitor-open-prs/test_skill_contract.py +0 -11
  170. package/skills/pr-consistency-audit/SKILL.md +112 -0
  171. package/skills/pr-consistency-audit/reference/detection-rules.md +96 -0
  172. package/skills/pr-consistency-audit/reference/illustrations.md +78 -0
  173. package/skills/pr-converge/SKILL.md +227 -23
  174. package/skills/pr-converge/config/__init__.py +0 -0
  175. package/skills/pr-converge/config/constants.py +62 -0
  176. package/skills/pr-converge/reference/convergence-gates.md +138 -44
  177. package/skills/pr-converge/reference/examples.md +43 -11
  178. package/skills/pr-converge/reference/fix-protocol.md +6 -5
  179. package/skills/pr-converge/reference/ground-rules.md +5 -3
  180. package/skills/pr-converge/reference/multi-pr-orchestration.md +44 -19
  181. package/skills/pr-converge/reference/obstacles/fix-post-replies.md +13 -0
  182. package/skills/pr-converge/reference/obstacles/fix-publish-summary.md +13 -0
  183. package/skills/pr-converge/reference/obstacles/fix-push.md +13 -0
  184. package/skills/pr-converge/reference/obstacles/fix-read-filelines.md +13 -0
  185. package/skills/pr-converge/reference/obstacles/fix-reset-state.md +13 -0
  186. package/skills/pr-converge/reference/obstacles/fix-resolve-threads.md +13 -0
  187. package/skills/pr-converge/reference/obstacles/fix-spawn-clean-coder.md +13 -0
  188. package/skills/pr-converge/reference/obstacles/fix-stage-commit.md +13 -0
  189. package/skills/pr-converge/reference/obstacles/fix-trigger-bugbot.md +13 -0
  190. package/skills/pr-converge/reference/obstacles/fix-write-test.md +13 -0
  191. package/skills/pr-converge/reference/per-tick.md +90 -31
  192. package/skills/pr-converge/reference/state-schema.md +22 -1
  193. package/skills/pr-converge/reference/stop-conditions.md +9 -7
  194. package/skills/pr-converge/scripts/README.md +34 -46
  195. package/skills/pr-converge/scripts/check_bugbot_ci.py +174 -0
  196. package/skills/pr-converge/scripts/check_convergence.py +497 -0
  197. package/skills/pr-converge/scripts/check_pending_reviews.py +154 -0
  198. package/skills/pr-converge/scripts/config/pr_converge_constants.py +118 -0
  199. package/skills/pr-converge/scripts/fetch_copilot_reviews.py +134 -0
  200. package/skills/pr-converge/scripts/post_fix_reply.py +168 -0
  201. package/skills/pr-converge/workflows/schedule-wakeup-loop.md +5 -12
  202. package/skills/qbug/SKILL.md +132 -27
  203. package/skills/session-log/SKILL.md +216 -114
  204. package/skills/session-tidy/SKILL.md +1 -1
  205. package/skills/skill-builder/SKILL.md +138 -56
  206. package/skills/skill-builder/references/delegation-map.md +72 -113
  207. package/skills/skill-builder/references/progressive-disclosure.md +122 -0
  208. package/skills/skill-builder/references/self-audit-checklist.md +92 -0
  209. package/skills/skill-builder/references/skill-types.md +228 -0
  210. package/skills/skill-builder/references/thariq-x-post-skills.json +33 -0
  211. package/skills/skill-builder/templates/gap-analysis.md +15 -8
  212. package/skills/skill-builder/workflows/improve-skill.md +86 -57
  213. package/skills/skill-builder/workflows/new-skill.md +80 -168
  214. package/skills/skill-builder/workflows/polish-skill.md +78 -54
  215. package/skills/structure-prompt/SKILL.md +50 -0
  216. package/skills/structure-prompt/reference/adversarial-tuning.md +62 -0
  217. package/skills/structure-prompt/reference/block-classification.md +27 -0
  218. package/skills/structure-prompt/reference/canonical-case.md +48 -0
  219. package/skills/structure-prompt/reference/citation-depth.md +70 -0
  220. package/skills/structure-prompt/reference/cleanup.md +33 -0
  221. package/skills/structure-prompt/reference/constraints.md +33 -0
  222. package/skills/structure-prompt/reference/directives.md +37 -0
  223. package/skills/structure-prompt/reference/examples.md +72 -0
  224. package/skills/structure-prompt/reference/instantiation.md +51 -0
  225. package/skills/structure-prompt/reference/output-contract.md +72 -0
  226. package/skills/structure-prompt/reference/per-category.md +23 -0
  227. package/skills/structure-prompt/reference/persona.md +38 -0
  228. package/skills/structure-prompt/reference/research.md +33 -0
  229. package/skills/structure-prompt/reference/structure.md +28 -0
  230. package/agents/code-standards-agent.md +0 -93
  231. package/agents/groq-coder.md +0 -113
  232. package/agents/plan-executor.md +0 -226
  233. package/agents/project-docs-analyzer.md +0 -53
  234. package/agents/project-structure-organizer-agent.md +0 -72
  235. package/agents/skill-to-agent-converter.md +0 -370
  236. package/agents/skill-writer-agent.md +0 -470
  237. package/agents/user-docs-writer.md +0 -67
  238. package/agents/workflow-visual-documenter.md +0 -82
  239. package/commands/readability-review.md +0 -20
  240. package/hooks/mypy.ini +0 -2
  241. package/hooks/notification/attention_needed_notify.py +0 -71
  242. package/hooks/notification/claude_notification_handler.py +0 -67
  243. package/hooks/notification/notification_utils.py +0 -267
  244. package/hooks/notification/subagent_complete_notify.py +0 -381
  245. package/hooks/notification/test_attention_needed_notify.py +0 -47
  246. package/hooks/notification/test_claude_notification_handler.py +0 -54
  247. package/hooks/notification/test_notification_utils.py +0 -91
  248. package/hooks/notification/test_subagent_complete_notify.py +0 -79
  249. package/scripts/config/groq_bugteam_config.py +0 -230
  250. package/scripts/config/test_groq_bugteam_config.py +0 -83
  251. package/scripts/config/test_spec_implementer_prompt.py +0 -32
  252. package/scripts/groq_bugteam.README.md +0 -131
  253. package/scripts/groq_bugteam.py +0 -647
  254. package/scripts/groq_bugteam_dotenv.py +0 -40
  255. package/scripts/groq_bugteam_spec.py +0 -226
  256. package/scripts/test_groq_bugteam.py +0 -529
  257. package/scripts/test_groq_bugteam_apply_fix_from_spec.py +0 -426
  258. package/scripts/test_groq_bugteam_dotenv.py +0 -66
  259. package/scripts/test_groq_bugteam_spec.py +0 -338
  260. package/skills/bugteam/SKILL_EVALS.md +0 -309
  261. package/skills/dream/SKILL.md +0 -118
  262. package/skills/ingest/SKILL.md +0 -40
  263. package/skills/npm-creator/SKILL.md +0 -187
  264. package/skills/readability-review/SKILL.md +0 -127
  265. package/skills/resume-review/SKILL.md +0 -261
  266. package/skills/rule-audit/SKILL.md +0 -307
  267. package/skills/rule-creator/SKILL.md +0 -150
  268. package/skills/searching-obsidian-vault/SKILL.md +0 -131
  269. package/skills/skill-writer/REFERENCE.md +0 -284
  270. package/skills/skill-writer/SKILL.md +0 -222
  271. package/skills/tdd-team/SKILL.md +0 -128
@@ -1,226 +0,0 @@
1
- """Spec-mode implementer for groq_bugteam.
2
-
3
- Splits the Claude-authored fix-spec pipeline into its own module so
4
- groq_bugteam.py can keep the single-shot audit+fix pipeline isolated
5
- from the mechanical patch applier. Both entrypoints share the same
6
- HTTP client (``call_groq_with_fallback``), string helpers
7
- (``parse_json_object``, ``preserve_trailing_newline``), and config
8
- constants via the parent groq_bugteam module, resolved at call time
9
- through resolve_groq_bugteam_module(). That resolver handles both
10
- contexts: tests register the parent as ``sys.modules["groq_bugteam"]``
11
- via spec_from_file_location, while a direct CLI invocation of
12
- ``python groq_bugteam.py --mode spec`` runs the parent as
13
- ``sys.modules["__main__"]``. The resolver also keeps tests able to
14
- monkeypatch ``groq_bugteam.call_groq_with_fallback`` and have the
15
- patch reach this module.
16
-
17
- This module is imported from the bottom of groq_bugteam.py so
18
- groq_bugteam.apply_fix_from_spec remains attribute-accessible to
19
- existing callers and tests. The module must not import groq_bugteam
20
- at its top level -- that would close the cycle during CLI startup
21
- and raise ImportError before groq_bugteam_spec finishes defining its
22
- public names.
23
- """
24
-
25
- from __future__ import annotations
26
-
27
- import json
28
- import os
29
- import sys
30
- from types import ModuleType
31
-
32
- from config.groq_bugteam_config import (
33
- GROQ_FIX_MAX_COMPLETION_TOKENS,
34
- GROQ_FIX_TEMPERATURE,
35
- JSON_INDENT_SPACES,
36
- MISSING_API_KEY_ERROR,
37
- PIPELINE_FAILURE_EXIT_CODE,
38
- REQUIRED_GROQ_BUGTEAM_ATTRIBUTES,
39
- SPEC_IMPLEMENTER_SYSTEM_PROMPT,
40
- SPEC_MODE_FLAG,
41
- SPEC_MODE_VALUE,
42
- )
43
-
44
- from groq_bugteam_dotenv import load_claude_dev_env_dotenv_file
45
-
46
-
47
- def extract_failing_criteria_by_finding(
48
- acceptance_checks: list[dict],
49
- ) -> dict[int, list[str]]:
50
- failing_by_finding: dict[int, list[str]] = {}
51
- for each_check in acceptance_checks:
52
- if each_check.get("met"):
53
- continue
54
- each_finding_index = each_check.get("finding_index")
55
- if not isinstance(each_finding_index, int):
56
- continue
57
- each_criterion_text = each_check.get("criterion", "")
58
- failing_by_finding.setdefault(each_finding_index, []).append(
59
- each_criterion_text
60
- )
61
- return failing_by_finding
62
-
63
-
64
- def demote_findings_with_failing_criteria(
65
- applied_finding_indexes: list[int],
66
- skipped_entries: list[dict],
67
- failing_criteria_by_finding: dict[int, list[str]],
68
- ) -> tuple[list[int], list[dict]]:
69
- demoted_applied = [
70
- each_index
71
- for each_index in applied_finding_indexes
72
- if each_index not in failing_criteria_by_finding
73
- ]
74
- already_skipped_indexes = {
75
- each.get("finding_index")
76
- for each in skipped_entries
77
- if each.get("finding_index") is not None
78
- }
79
- augmented_skipped = list(skipped_entries)
80
- for (
81
- each_finding_index,
82
- each_failing_criteria,
83
- ) in failing_criteria_by_finding.items():
84
- if each_finding_index in already_skipped_indexes:
85
- continue
86
- reason_text = "; ".join(each_failing_criteria)
87
- augmented_skipped.append(
88
- {"finding_index": each_finding_index, "reason": reason_text}
89
- )
90
- return demoted_applied, augmented_skipped
91
-
92
-
93
- def build_spec_user_message(spec_list: list[dict], current_content: str) -> str:
94
- payload = {"spec": spec_list, "current_content": current_content}
95
- return json.dumps(payload, indent=JSON_INDENT_SPACES)
96
-
97
-
98
- def find_missing_required_attributes(candidate_module: ModuleType) -> list[str]:
99
- return [
100
- each_attribute_name
101
- for each_attribute_name in REQUIRED_GROQ_BUGTEAM_ATTRIBUTES
102
- if not hasattr(candidate_module, each_attribute_name)
103
- ]
104
-
105
-
106
- def resolve_groq_bugteam_module() -> ModuleType:
107
- registered_module = sys.modules.get("groq_bugteam")
108
- if registered_module is not None and not find_missing_required_attributes(
109
- registered_module
110
- ):
111
- return registered_module
112
- main_module = sys.modules.get("__main__")
113
- if main_module is not None and not find_missing_required_attributes(main_module):
114
- return main_module
115
- stub_module = registered_module if registered_module is not None else main_module
116
- if stub_module is not None:
117
- missing_attributes = find_missing_required_attributes(stub_module)
118
- raise RuntimeError(
119
- "groq_bugteam module found but missing required attributes: "
120
- + ", ".join(missing_attributes)
121
- )
122
- raise RuntimeError(
123
- "groq_bugteam module not found in sys.modules; "
124
- "groq_bugteam_spec must be invoked from a context where "
125
- "groq_bugteam is the parent module (test loader or CLI)."
126
- )
127
-
128
-
129
- def coerce_to_list(candidate_value: object) -> list:
130
- if isinstance(candidate_value, list):
131
- return candidate_value
132
- return []
133
-
134
-
135
- def coerce_to_string_or_fallback(
136
- candidate_value: object, fallback_value: str
137
- ) -> str:
138
- if isinstance(candidate_value, str):
139
- return candidate_value
140
- return fallback_value
141
-
142
-
143
- def apply_fix_from_spec(spec_list: list[dict], current_content: str) -> dict:
144
- load_claude_dev_env_dotenv_file()
145
- api_key = os.environ.get("GROQ_API_KEY", "").strip()
146
- if not api_key:
147
- raise RuntimeError(MISSING_API_KEY_ERROR)
148
-
149
- groq_bugteam_module = resolve_groq_bugteam_module()
150
- user_message = build_spec_user_message(spec_list, current_content)
151
- groq_result = groq_bugteam_module.call_groq_with_fallback(
152
- api_key,
153
- messages=[
154
- {"role": "system", "content": SPEC_IMPLEMENTER_SYSTEM_PROMPT},
155
- {"role": "user", "content": user_message},
156
- ],
157
- temperature=GROQ_FIX_TEMPERATURE,
158
- max_completion_tokens=GROQ_FIX_MAX_COMPLETION_TOKENS,
159
- )
160
- parsed_response = groq_bugteam_module.parse_json_object(groq_result.content)
161
-
162
- raw_updated_content = coerce_to_string_or_fallback(
163
- parsed_response.get("updated_content"), current_content
164
- )
165
- applied_finding_indexes = coerce_to_list(
166
- parsed_response.get("applied_finding_indexes")
167
- )
168
- skipped_entries = coerce_to_list(parsed_response.get("skipped"))
169
- acceptance_checks = coerce_to_list(parsed_response.get("acceptance_checks"))
170
-
171
- failing_criteria_by_finding = extract_failing_criteria_by_finding(acceptance_checks)
172
- demoted_applied, augmented_skipped = demote_findings_with_failing_criteria(
173
- applied_finding_indexes, skipped_entries, failing_criteria_by_finding
174
- )
175
- updated_content = groq_bugteam_module.preserve_trailing_newline(
176
- current_content, raw_updated_content
177
- )
178
-
179
- return {
180
- "updated_content": updated_content,
181
- "applied_finding_indexes": demoted_applied,
182
- "skipped": augmented_skipped,
183
- "acceptance_checks": acceptance_checks,
184
- }
185
-
186
-
187
- def read_spec_input_from_stdin() -> tuple[list[dict], str]:
188
- stdin_text = sys.stdin.read()
189
- parsed_input = json.loads(stdin_text)
190
- spec_list = parsed_input.get("spec", [])
191
- current_content = parsed_input.get("current_content", "")
192
- return spec_list, current_content
193
-
194
-
195
- def run_spec_mode() -> dict:
196
- try:
197
- spec_list, current_content = read_spec_input_from_stdin()
198
- except (json.JSONDecodeError, ValueError) as parse_error:
199
- return {"error": f"stdin is not valid JSON: {parse_error}"}
200
- try:
201
- return apply_fix_from_spec(spec_list, current_content)
202
- except Exception as spec_error:
203
- return {"error": f"spec-mode fix failed: {spec_error}"}
204
-
205
-
206
- def is_spec_mode_invocation(argv: list[str]) -> bool:
207
- for each_argv_index, each_argv_token in enumerate(argv):
208
- if each_argv_token != SPEC_MODE_FLAG:
209
- continue
210
- if each_argv_index + 1 >= len(argv):
211
- continue
212
- if argv[each_argv_index + 1] == SPEC_MODE_VALUE:
213
- return True
214
- return False
215
-
216
-
217
- def emit_outcome(outcome: dict) -> None:
218
- json.dump(outcome, sys.stdout, indent=JSON_INDENT_SPACES)
219
- sys.stdout.write("\n")
220
-
221
-
222
- def run_spec_mode_main() -> None:
223
- spec_outcome = run_spec_mode()
224
- emit_outcome(spec_outcome)
225
- if "error" in spec_outcome:
226
- sys.exit(PIPELINE_FAILURE_EXIT_CODE)