agent-borg 3.2.2__tar.gz → 3.2.3__tar.gz

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 (153) hide show
  1. {agent_borg-3.2.2 → agent_borg-3.2.3}/PKG-INFO +1 -1
  2. {agent_borg-3.2.2 → agent_borg-3.2.3}/agent_borg.egg-info/PKG-INFO +1 -1
  3. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/__init__.py +1 -1
  4. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/core/pack_taxonomy.py +105 -4
  5. {agent_borg-3.2.2 → agent_borg-3.2.3}/pyproject.toml +1 -1
  6. {agent_borg-3.2.2 → agent_borg-3.2.3}/README.md +0 -0
  7. {agent_borg-3.2.2 → agent_borg-3.2.3}/agent_borg.egg-info/SOURCES.txt +0 -0
  8. {agent_borg-3.2.2 → agent_borg-3.2.3}/agent_borg.egg-info/dependency_links.txt +0 -0
  9. {agent_borg-3.2.2 → agent_borg-3.2.3}/agent_borg.egg-info/entry_points.txt +0 -0
  10. {agent_borg-3.2.2 → agent_borg-3.2.3}/agent_borg.egg-info/requires.txt +0 -0
  11. {agent_borg-3.2.2 → agent_borg-3.2.3}/agent_borg.egg-info/top_level.txt +0 -0
  12. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/benchmark/skills/test_skills.py +0 -0
  13. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/benchmarks/__init__.py +0 -0
  14. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/benchmarks/report.py +0 -0
  15. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/benchmarks/runner.py +0 -0
  16. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/benchmarks/scorer.py +0 -0
  17. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/benchmarks/tasks.py +0 -0
  18. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/benchmarks/tests/__init__.py +0 -0
  19. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/benchmarks/tests/test_benchmarks.py +0 -0
  20. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/cli.py +0 -0
  21. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/core/__init__.py +0 -0
  22. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/core/agentskills_converter.py +0 -0
  23. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/core/aggregator.py +0 -0
  24. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/core/apply.py +0 -0
  25. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/core/changes.py +0 -0
  26. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/core/conditions.py +0 -0
  27. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/core/contextual_selector.py +0 -0
  28. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/core/convert.py +0 -0
  29. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/core/crypto.py +0 -0
  30. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/core/failure_memory.py +0 -0
  31. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/core/feedback_loop.py +0 -0
  32. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/core/generator.py +0 -0
  33. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/core/mutation_engine.py +0 -0
  34. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/core/openclaw_converter.py +0 -0
  35. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/core/privacy.py +0 -0
  36. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/core/proof_gates.py +0 -0
  37. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/core/publish.py +0 -0
  38. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/core/safety.py +0 -0
  39. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/core/schema.py +0 -0
  40. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/core/search.py +0 -0
  41. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/core/semantic_search.py +0 -0
  42. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/core/session.py +0 -0
  43. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/core/signals.py +0 -0
  44. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/core/trace_matcher.py +0 -0
  45. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/core/traces.py +0 -0
  46. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/core/uri.py +0 -0
  47. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/core/v3_integration.py +0 -0
  48. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/db/__init__.py +0 -0
  49. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/db/analytics.py +0 -0
  50. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/db/embeddings.py +0 -0
  51. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/db/migrations.py +0 -0
  52. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/db/reputation.py +0 -0
  53. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/db/store.py +0 -0
  54. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/__init__.py +0 -0
  55. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/alpha_signal.py +0 -0
  56. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/api_clients/__init__.py +0 -0
  57. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/api_clients/alchemy.py +0 -0
  58. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/api_clients/arkham.py +0 -0
  59. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/api_clients/base.py +0 -0
  60. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/api_clients/birdeye.py +0 -0
  61. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/api_clients/cache.py +0 -0
  62. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/api_clients/defillama.py +0 -0
  63. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/api_clients/dexscreener.py +0 -0
  64. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/api_clients/goplus.py +0 -0
  65. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/api_clients/helius.py +0 -0
  66. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/cli.py +0 -0
  67. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/cron/__init__.py +0 -0
  68. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/cron/alpha_cron.py +0 -0
  69. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/cron/delivery.py +0 -0
  70. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/cron/liquidation_cron.py +0 -0
  71. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/cron/live_scans.py +0 -0
  72. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/cron/portfolio_cron.py +0 -0
  73. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/cron/risk_cron.py +0 -0
  74. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/cron/state.py +0 -0
  75. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/cron/whale_cron.py +0 -0
  76. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/cron/yield_cron.py +0 -0
  77. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/data_models.py +0 -0
  78. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/dojo_bridge.py +0 -0
  79. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/liquidation_watcher.py +0 -0
  80. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/lp_manager.py +0 -0
  81. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/mcp_tools.py +0 -0
  82. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/mev/__init__.py +0 -0
  83. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/mev/flashbots.py +0 -0
  84. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/mev/jito.py +0 -0
  85. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/portfolio_monitor.py +0 -0
  86. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/risk_engine.py +0 -0
  87. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/security/__init__.py +0 -0
  88. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/security/keystore.py +0 -0
  89. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/security/tx_guard.py +0 -0
  90. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/strategy_backtester.py +0 -0
  91. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/strategy_selector.py +0 -0
  92. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/swap_executor.py +0 -0
  93. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/v2/__init__.py +0 -0
  94. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/v2/borg_bridge.py +0 -0
  95. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/v2/circuit_breaker.py +0 -0
  96. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/v2/daily_brief.py +0 -0
  97. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/v2/drift.py +0 -0
  98. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/v2/models.py +0 -0
  99. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/v2/outcome_store.py +0 -0
  100. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/v2/pack_store.py +0 -0
  101. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/v2/recommender.py +0 -0
  102. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/v2/reputation.py +0 -0
  103. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/v2/seed_packs.py +0 -0
  104. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/v2/warnings.py +0 -0
  105. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/whale_tracker.py +0 -0
  106. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/defi/yield_scanner.py +0 -0
  107. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/dojo/__init__.py +0 -0
  108. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/dojo/auto_fixer.py +0 -0
  109. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/dojo/cron_runner.py +0 -0
  110. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/dojo/data_models.py +0 -0
  111. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/dojo/failure_classifier.py +0 -0
  112. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/dojo/learning_curve.py +0 -0
  113. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/dojo/pipeline.py +0 -0
  114. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/dojo/report_generator.py +0 -0
  115. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/dojo/session_reader.py +0 -0
  116. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/dojo/skill_gap_detector.py +0 -0
  117. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/dojo/tests/__init__.py +0 -0
  118. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/dojo/tests/test_auto_fixer.py +0 -0
  119. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/dojo/tests/test_failure_classifier.py +0 -0
  120. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/dojo/tests/test_learning_curve.py +0 -0
  121. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/dojo/tests/test_pipeline.py +0 -0
  122. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/dojo/tests/test_report_generator.py +0 -0
  123. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/dojo/tests/test_session_reader.py +0 -0
  124. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/dojo/tests/test_skill_gap_detector.py +0 -0
  125. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/eval/__init__.py +0 -0
  126. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/eval/e1a_seed_pack_validation.py +0 -0
  127. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/fleet/syncer.py +0 -0
  128. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/integrations/__init__.py +0 -0
  129. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/integrations/agent_hook.py +0 -0
  130. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/integrations/http_server.py +0 -0
  131. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/integrations/mcp_server.py +0 -0
  132. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/integrations/nudge.py +0 -0
  133. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/seeds_data/borg/SKILL.md +0 -0
  134. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/seeds_data/circular-dependency-migration.md +0 -0
  135. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/seeds_data/code-review.md +0 -0
  136. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/seeds_data/configuration-error.md +0 -0
  137. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/seeds_data/defi-risk-check.md +0 -0
  138. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/seeds_data/defi-yield-strategy.md +0 -0
  139. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/seeds_data/guild-autopilot/SKILL.md +0 -0
  140. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/seeds_data/import-cycle.md +0 -0
  141. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/seeds_data/migration-state-desync.md +0 -0
  142. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/seeds_data/missing-dependency.md +0 -0
  143. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/seeds_data/missing-foreign-key.md +0 -0
  144. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/seeds_data/null-pointer-chain.md +0 -0
  145. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/seeds_data/permission-denied.md +0 -0
  146. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/seeds_data/race-condition.md +0 -0
  147. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/seeds_data/schema-drift.md +0 -0
  148. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/seeds_data/systematic-debugging.md +0 -0
  149. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/seeds_data/test-driven-development.md +0 -0
  150. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/seeds_data/timeout-hang.md +0 -0
  151. {agent_borg-3.2.2 → agent_borg-3.2.3}/borg/seeds_data/type-mismatch.md +0 -0
  152. {agent_borg-3.2.2 → agent_borg-3.2.3}/setup.cfg +0 -0
  153. {agent_borg-3.2.2 → agent_borg-3.2.3}/tests/test_e2e_verify.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agent-borg
3
- Version: 3.2.2
3
+ Version: 3.2.3
4
4
  Summary: Collective memory for AI coding agents — your agent learns from every session
5
5
  Author-email: Hermes Team <aleshbrown@gmail.com>
6
6
  License-Expression: MIT
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agent-borg
3
- Version: 3.2.2
3
+ Version: 3.2.3
4
4
  Summary: Collective memory for AI coding agents — your agent learns from every session
5
5
  Author-email: Hermes Team <aleshbrown@gmail.com>
6
6
  License-Expression: MIT
@@ -1,6 +1,6 @@
1
1
  """Borg — Collective intelligence for AI coding agents."""
2
2
 
3
- __version__ = "3.2.2"
3
+ __version__ = "3.2.3"
4
4
 
5
5
 
6
6
  def check(context: str, constraints: dict = None, top_k: int = 3) -> list:
@@ -182,6 +182,95 @@ def _detect_language_quick(error_message: str) -> Optional[str]:
182
182
  return lang
183
183
  return None
184
184
 
185
+
186
+ # -----------------------------------------------------------------------
187
+ # v3.2.3 anti_signatures — suppress first-match-wins over-fires
188
+ # -----------------------------------------------------------------------
189
+ # An anti_signature is a regex that, if it matches the error text, blocks
190
+ # the firing keyword's problem_class from winning. The classifier loop
191
+ # continues to the next keyword and returns None if nothing clears.
192
+ #
193
+ # Each entry names the corpus row it targets and the Python positive it
194
+ # explicitly does NOT match. See docs/20260408-0623_classifier_prd/
195
+ # v323_fc_analysis.md for the full design + simulation proof.
196
+ #
197
+ # Phase 1 will migrate these into per-pack `anti_signatures` frontmatter
198
+ # (ARCHITECTURE_SPEC.md §4.2 / §8.1). Until then, the dict lives here next
199
+ # to _ERROR_KEYWORDS so the patch is a pure classifier change.
200
+ _ANTI_SIGNATURES: Dict[str, List["_re.Pattern[str]"]] = {
201
+ "circular_dependency": [
202
+ # Corpus row e0009 — Python's canonical "partially initialized
203
+ # module" phrasing is the RIGHT phrase for import_cycle, not
204
+ # circular_dependency. Does NOT match any of the 10
205
+ # PYTHON_REGRESSION_FIXTURES (none contain "partially initialized
206
+ # module" or "most likely due to a circular import").
207
+ _re.compile(r"partially initialized module", _re.IGNORECASE),
208
+ _re.compile(r"most likely due to a circular import", _re.IGNORECASE),
209
+ # Corpus row e0044 — JS JSON.stringify cyclic structure error.
210
+ # Does NOT match any Python fixture (no Python fixture mentions
211
+ # "Converting circular structure to JSON").
212
+ _re.compile(r"Converting circular structure to JSON", _re.IGNORECASE),
213
+ ],
214
+ "type_mismatch": [
215
+ # Corpus row e0036 — JS "Cannot read property 'length' of null"
216
+ # (pre-2019 singular phrasing). The 0-40 char gap covers the
217
+ # quoted key like 'length'. Anchored on `of (null|undefined)` so
218
+ # a Python message containing the literal phrase "cannot read
219
+ # property" without the JS-specific null/undefined ending will
220
+ # not match. Does NOT match any Python fixture.
221
+ _re.compile(
222
+ r"Cannot read propert(?:y|ies)\b[^\n]{0,40}?\bof (?:null|undefined)",
223
+ _re.IGNORECASE,
224
+ ),
225
+ # Corpus row e0042 — JS "x is not a function". Python equivalent
226
+ # for non-callables is "is not callable" (PEP 8 / CPython), so
227
+ # the literal `is not a function` is JS-only. Does NOT match any
228
+ # Python fixture.
229
+ _re.compile(r"\bis not a function\b", _re.IGNORECASE),
230
+ # Corpus row e0043 — JS "Assignment to constant variable". Python
231
+ # does not have const-reassignment errors (no consts). Does NOT
232
+ # match any Python fixture.
233
+ _re.compile(r"Assignment to constant variable", _re.IGNORECASE),
234
+ # Corpus row e0044 — defence-in-depth duplicate of the
235
+ # circular_dependency anti_signature. If _ERROR_KEYWORDS is ever
236
+ # reordered so TypeError fires before 'circular', this row still
237
+ # gets suppressed. Does NOT match any Python fixture.
238
+ _re.compile(r"Converting circular structure to JSON", _re.IGNORECASE),
239
+ ],
240
+ "import_cycle": [
241
+ # Corpus row e0122 — Go's exact cyclic-import compiler phrasing.
242
+ # Does NOT match any Python fixture (no Python fixture contains
243
+ # the literal string "import cycle not allowed").
244
+ _re.compile(r"import cycle not allowed", _re.IGNORECASE),
245
+ ],
246
+ "timeout_hang": [
247
+ # Corpus row e0157 — K8s readiness/liveness/startup probe failures
248
+ # that contain the substring "connection refused" but should
249
+ # route to k8s_probe_failed (no pack yet — Phase 3). Does NOT
250
+ # match Python fixture #7 "TimeoutError: [Errno 110] Connection
251
+ # timed out" because that fixture has no probe-failed phrasing.
252
+ _re.compile(
253
+ r"\b(?:Readiness|Liveness|Startup) probe failed\b",
254
+ _re.IGNORECASE,
255
+ ),
256
+ ],
257
+ }
258
+
259
+
260
+ def _anti_signature_blocks(error_message: str, problem_class: str) -> bool:
261
+ """Return True if any anti_signature for the class matches the text.
262
+
263
+ Preserves case of the original `error_message` — the regexes use
264
+ re.IGNORECASE themselves where appropriate. Safe on empty / None
265
+ inputs (returns False).
266
+ """
267
+ if not error_message:
268
+ return False
269
+ for pattern in _ANTI_SIGNATURES.get(problem_class, ()):
270
+ if pattern.search(error_message):
271
+ return True
272
+ return False
273
+
185
274
  # Canonical list of all known problem classes (must match seed pack filenames)
186
275
  PROBLEM_CLASSES: List[str] = [
187
276
  "circular_dependency",
@@ -286,17 +375,22 @@ def classify_error(error_message: str) -> Optional[str]:
286
375
  """
287
376
  Classify an error message string into a problem_class.
288
377
 
289
- v3.2.2 (Phase 0 of the multi-language classifier roadmap):
378
+ v3.2.3 (Phase 0 of the multi-language classifier roadmap):
290
379
  1. Detect non-Python locking signals (Rust E0xxx, Go panic, JS
291
380
  Cannot read properties of, TS####, React Hydration failed,
292
381
  Docker ENOSPC, Kubernetes CrashLoopBackOff, etc.). If any
293
382
  fire, return None ("we don't know yet, refusing to give a
294
383
  Python answer to a non-Python error").
295
- 2. Otherwise fall back to the legacy substring keyword table
296
- (Python/Django coverage unchanged).
384
+ 2. Walk the legacy substring keyword table (Python/Django coverage
385
+ unchanged).
386
+ 3. Before returning a keyword's problem_class, consult
387
+ `_ANTI_SIGNATURES` to suppress known first-match-wins
388
+ over-fires on Python-looking inputs whose text has a JS/Go/K8s
389
+ phrase the language guard did not catch.
297
390
 
298
391
  Phase 1+ (ARCHITECTURE_SPEC.md §3-§7) replaces this with a
299
- confidence-scored Match | UnknownMatch dataclass return type.
392
+ confidence-scored Match | UnknownMatch dataclass return type and
393
+ migrates `_ANTI_SIGNATURES` into per-pack frontmatter.
300
394
 
301
395
  See docs/20260408-0623_classifier_prd/ for the full PRD.
302
396
  """
@@ -308,6 +402,13 @@ def classify_error(error_message: str) -> Optional[str]:
308
402
  lower = error_message.lower()
309
403
  for keyword, problem_class in _ERROR_KEYWORDS:
310
404
  if keyword.lower() in lower:
405
+ # v3.2.3 anti_signature gate — if a class-specific regex
406
+ # matches the (case-preserved) text, suppress this keyword
407
+ # and keep scanning. Returns None at the end if nothing
408
+ # clears, so `debug_error()` falls through to the same
409
+ # UnknownMatch block as before.
410
+ if _anti_signature_blocks(error_message, problem_class):
411
+ continue
311
412
  return problem_class
312
413
  return None
313
414
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "agent-borg"
7
- version = "3.2.2"
7
+ version = "3.2.3"
8
8
  description = "Collective memory for AI coding agents — your agent learns from every session"
9
9
  readme = "README.md"
10
10
  license = "MIT"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes