atomadic-forge 0.59.0__tar.gz → 0.60.0__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 (450) hide show
  1. {atomadic_forge-0.59.0/src/atomadic_forge.egg-info → atomadic_forge-0.60.0}/PKG-INFO +1 -1
  2. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/pyproject.toml +1 -1
  3. atomadic_forge-0.60.0/src/atomadic_forge/a1_at_functions/abstract_method_repair.py +333 -0
  4. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/forge_pipeline.py +20 -0
  5. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0/src/atomadic_forge.egg-info}/PKG-INFO +1 -1
  6. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge.egg-info/SOURCES.txt +2 -0
  7. atomadic_forge-0.60.0/tests/test_abstract_method_repair.py +122 -0
  8. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/.github/FUNDING.yml +0 -0
  9. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  10. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  11. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  12. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/.github/actions/forge-action/README.md +0 -0
  13. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/.github/actions/forge-action/action.yml +0 -0
  14. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/.github/dependabot.yml +0 -0
  15. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/.github/pull_request_template.md +0 -0
  16. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/.github/workflows/ci.yml +0 -0
  17. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/.github/workflows/customer-refactor.yml +0 -0
  18. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/.github/workflows/forge-self-certify.yml +0 -0
  19. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/.github/workflows/mcp-registry-publish.yml +0 -0
  20. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/.github/workflows/metrics-auto-regen.yml +0 -0
  21. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/.github/workflows/metrics-drift.yml +0 -0
  22. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/.github/workflows/publish-on-tag.yml +0 -0
  23. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/.github/workflows/release-readiness.yml +0 -0
  24. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/.github/workflows/release.yml +0 -0
  25. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/.github/workflows/surface-drift.yml +0 -0
  26. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/.github/workflows/uptime.yml +0 -0
  27. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/ARCHITECTURE.md +0 -0
  28. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/CHANGELOG.md +0 -0
  29. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/CONTRIBUTING.md +0 -0
  30. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/LICENSE +0 -0
  31. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/MANIFEST.in +0 -0
  32. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/README.md +0 -0
  33. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/SECURITY.md +0 -0
  34. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/assets/Atomadic-Forge-01.png +0 -0
  35. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/01-getting-started.md +0 -0
  36. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/02-commands.md +0 -0
  37. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/03-tutorial.md +0 -0
  38. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/04-llm-loops.md +0 -0
  39. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/05-faq.md +0 -0
  40. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/AGENTS_GUIDE.md +0 -0
  41. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/AIR_GAPPED.md +0 -0
  42. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/CI_CD.md +0 -0
  43. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/CODEX_WALKTHROUGH.md +0 -0
  44. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/COMMANDS.md +0 -0
  45. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/FIRST_10_MINUTES.md +0 -0
  46. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/FORMALIZATION.md +0 -0
  47. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/HIVE_PRIMITIVES.md +0 -0
  48. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/HIVE_STATUS.md +0 -0
  49. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/IDE_INTEGRATION.md +0 -0
  50. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/LANDSCAPE.md +0 -0
  51. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/MARKET_POSITIONING.md +0 -0
  52. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/MCP_TOOLS.md +0 -0
  53. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/MIGRATION.md +0 -0
  54. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/MULTI_REPO.md +0 -0
  55. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/PROVIDERS.md +0 -0
  56. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/README.md +0 -0
  57. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/RECEIPT.md +0 -0
  58. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/RELAY_PROTOCOL.md +0 -0
  59. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/RELEASE_CHECKLIST.md +0 -0
  60. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/RELEASE_MESSAGING.md +0 -0
  61. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/ROADMAP.md +0 -0
  62. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/SHOWCASE.md +0 -0
  63. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/SIDECAR.md +0 -0
  64. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/STUDIO.md +0 -0
  65. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/TOOL_FACTORY_WALKTHROUGH.md +0 -0
  66. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/V0.46.0_JUSTIFICATION_REPORT.md +0 -0
  67. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/V0.47.0_SELF_TEST_REPORT.md +0 -0
  68. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/WHY_NOW.md +0 -0
  69. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/WORKER_VS_LOCAL_MCP.md +0 -0
  70. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/WORLD_COLLISION.md +0 -0
  71. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/commands/INDEX.md +0 -0
  72. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/commands/absorb.md +0 -0
  73. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/commands/audit.md +0 -0
  74. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/commands/chat.md +0 -0
  75. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/commands/commandsmith.md +0 -0
  76. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/commands/config.md +0 -0
  77. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/commands/create.md +0 -0
  78. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/commands/demo.md +0 -0
  79. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/commands/emergent-swarm.md +0 -0
  80. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/commands/emergent-then-synergy.md +0 -0
  81. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/commands/emergent.md +0 -0
  82. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/commands/enhancement.md +0 -0
  83. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/commands/evolve-then-iterate.md +0 -0
  84. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/commands/evolve.md +0 -0
  85. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/commands/feature-then-emergent.md +0 -0
  86. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/commands/guard-install.md +0 -0
  87. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/commands/handoff.md +0 -0
  88. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/commands/harvest.md +0 -0
  89. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/commands/hive.md +0 -0
  90. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/commands/iterate.md +0 -0
  91. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/commands/materialize.md +0 -0
  92. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/commands/metrics.md +0 -0
  93. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/commands/recon-swarm.md +0 -0
  94. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/commands/relay.md +0 -0
  95. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/commands/surface.md +0 -0
  96. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/commands/synergy-then-emergent.md +0 -0
  97. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/commands/synergy.md +0 -0
  98. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/commands/welcome.md +0 -0
  99. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/commands/wisdom.md +0 -0
  100. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/compliance/CMMC_AI_MAPPING.md +0 -0
  101. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/compliance/CS-1.md +0 -0
  102. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/compliance/EU_AI_ACT_ANNEX_IV.md +0 -0
  103. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/compliance/FDA_PCCP_MAPPING.md +0 -0
  104. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/compliance/SR_11-7_MAPPING.md +0 -0
  105. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/handoffs/WORKER_AUTO_DEPLOY_2026-05-06.md +0 -0
  106. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/tutorials/01-quickstart.md +0 -0
  107. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/tutorials/02-your-first-package.md +0 -0
  108. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/tutorials/03-the-five-tier-law.md +0 -0
  109. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/tutorials/04-plug-in-llms.md +0 -0
  110. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/tutorials/05-multi-repo-absorb.md +0 -0
  111. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/docs/tutorials/06-javascript-quickstart.md +0 -0
  112. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/setup.cfg +0 -0
  113. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/__init__.py +0 -0
  114. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/__main__.py +0 -0
  115. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a0_qk_constants/__init__.py +0 -0
  116. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a0_qk_constants/agent_plan_schema.py +0 -0
  117. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a0_qk_constants/auth_constants.py +0 -0
  118. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a0_qk_constants/commandsmith_types.py +0 -0
  119. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a0_qk_constants/config_defaults.py +0 -0
  120. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a0_qk_constants/emergent_types.py +0 -0
  121. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a0_qk_constants/enhancement_proposal_constants.py +0 -0
  122. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a0_qk_constants/error_codes.py +0 -0
  123. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a0_qk_constants/forge_types.py +0 -0
  124. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a0_qk_constants/gen_language.py +0 -0
  125. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a0_qk_constants/handoff_constants.py +0 -0
  126. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a0_qk_constants/hive_constants.py +0 -0
  127. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a0_qk_constants/lang_extensions.py +0 -0
  128. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a0_qk_constants/lifetime_savings_constants.py +0 -0
  129. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a0_qk_constants/materialize_types.py +0 -0
  130. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a0_qk_constants/mhed_invariants.py +0 -0
  131. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a0_qk_constants/nexus_constants.py +0 -0
  132. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a0_qk_constants/policy_schema.py +0 -0
  133. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a0_qk_constants/receipt_schema.py +0 -0
  134. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a0_qk_constants/response_enrichment.py +0 -0
  135. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a0_qk_constants/roi_constants.py +0 -0
  136. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a0_qk_constants/schema_version_registry.py +0 -0
  137. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a0_qk_constants/semantic_types.py +0 -0
  138. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a0_qk_constants/sidecar_schema.py +0 -0
  139. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a0_qk_constants/synergy_types.py +0 -0
  140. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a0_qk_constants/tier_names.py +0 -0
  141. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a0_qk_constants/welcome_constants.py +0 -0
  142. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a0_qk_constants/wisdom_constants.py +0 -0
  143. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/__init__.py +0 -0
  144. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/agent_context_pack.py +0 -0
  145. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/agent_memory.py +0 -0
  146. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/agent_plan_emitter.py +0 -0
  147. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/agent_summary.py +0 -0
  148. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/ast_scope_lock.py +0 -0
  149. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/body_extractor.py +0 -0
  150. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/call_graph.py +0 -0
  151. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/capability_scout.py +0 -0
  152. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/card_renderer.py +0 -0
  153. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/certify_checks.py +0 -0
  154. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/chat_context.py +0 -0
  155. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/cherry_pick.py +0 -0
  156. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/classify_tier.py +0 -0
  157. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/code_signature.py +0 -0
  158. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/commandsmith_discover.py +0 -0
  159. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/commandsmith_render.py +0 -0
  160. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/compiler_feedback.py +0 -0
  161. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/compliance_checker.py +0 -0
  162. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/config_io.py +0 -0
  163. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/cs1_renderer.py +0 -0
  164. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/custom_provider_client.py +0 -0
  165. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/dead_code_check.py +0 -0
  166. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/doc_auto_update.py +0 -0
  167. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/doc_synthesizer.py +0 -0
  168. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/emergent_compose.py +0 -0
  169. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/emergent_rank.py +0 -0
  170. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/emergent_signature_extract.py +0 -0
  171. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/emergent_synthesize.py +0 -0
  172. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/enforce_planner.py +0 -0
  173. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/enhancement_proposal_builder.py +0 -0
  174. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/error_hints.py +0 -0
  175. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/evolution_log.py +0 -0
  176. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/exported_api_check.py +0 -0
  177. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/forge_auth.py +0 -0
  178. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/forge_feedback.py +0 -0
  179. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/forge_locate.py +0 -0
  180. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/forge_metrics.py +0 -0
  181. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/generation_quality.py +0 -0
  182. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/git_churn.py +0 -0
  183. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/handoff_builder.py +0 -0
  184. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/harvest_absorb.py +0 -0
  185. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/harvest_concept_bridge.py +0 -0
  186. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/hive_consensus_math.py +0 -0
  187. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/hive_io.py +0 -0
  188. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/import_repair.py +0 -0
  189. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/import_smoke.py +0 -0
  190. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/intent_similarity.py +0 -0
  191. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/js_parser.py +0 -0
  192. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/lifetime_savings.py +0 -0
  193. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/lineage_chain.py +0 -0
  194. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/lineage_reader.py +0 -0
  195. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/llm_client.py +0 -0
  196. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/local_signer.py +0 -0
  197. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/lsp_protocol.py +0 -0
  198. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/maintainability_index.py +0 -0
  199. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/manifest_diff.py +0 -0
  200. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/mcp_protocol.py +0 -0
  201. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/patch_scorer.py +0 -0
  202. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/plan_adapter.py +0 -0
  203. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/policy_loader.py +0 -0
  204. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/polyglot_classify.py +0 -0
  205. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/polyglot_imports.py +0 -0
  206. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/polyglot_surface.py +0 -0
  207. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/preflight_change.py +0 -0
  208. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/progress_reporter.py +0 -0
  209. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/provider_detect.py +0 -0
  210. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/provider_resolver.py +0 -0
  211. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/receipt_emitter.py +0 -0
  212. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/recipes.py +0 -0
  213. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/repo_explainer.py +0 -0
  214. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/research_note_distiller.py +0 -0
  215. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/response_enricher.py +0 -0
  216. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/roi_calculator.py +0 -0
  217. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/rollback_planner.py +0 -0
  218. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/sbom_emitter.py +0 -0
  219. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/scaffold_js.py +0 -0
  220. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/scaffold_polyglot.py +0 -0
  221. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/scaffold_pyproject.py +0 -0
  222. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/scaffold_starter.py +0 -0
  223. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/scout_walk.py +0 -0
  224. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/sidecar_parser.py +0 -0
  225. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/sidecar_validator.py +0 -0
  226. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/smell_scan.py +0 -0
  227. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/steersman_pack.py +0 -0
  228. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/stub_detector.py +0 -0
  229. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/surface_gap_check.py +0 -0
  230. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/synergy_detect.py +0 -0
  231. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/synergy_render.py +0 -0
  232. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/synergy_surface_extract.py +0 -0
  233. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/test_runner.py +0 -0
  234. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/test_selector.py +0 -0
  235. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/tier_init_rebuild.py +0 -0
  236. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/tool_composer.py +0 -0
  237. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/transcript_log.py +0 -0
  238. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/trust_gate_response.py +0 -0
  239. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/validation_commands.py +0 -0
  240. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/welcome_narrator.py +0 -0
  241. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/wire_check.py +0 -0
  242. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/wire_stubs_gen.py +0 -0
  243. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/wisdom_capture.py +0 -0
  244. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/wisdom_io.py +0 -0
  245. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/wisdom_promote.py +0 -0
  246. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/wisdom_recall.py +0 -0
  247. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a1_at_functions/worktree_status.py +0 -0
  248. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a2_mo_composites/__init__.py +0 -0
  249. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a2_mo_composites/cost_circuit_breaker.py +0 -0
  250. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a2_mo_composites/cross_agent_intent_deduplicator.py +0 -0
  251. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a2_mo_composites/evolve_session_store.py +0 -0
  252. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a2_mo_composites/forge_auth_client.py +0 -0
  253. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a2_mo_composites/hierarchical_memory.py +0 -0
  254. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a2_mo_composites/iterate_session_store.py +0 -0
  255. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a2_mo_composites/lineage_chain_store.py +0 -0
  256. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a2_mo_composites/manifest_store.py +0 -0
  257. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a2_mo_composites/nexus_client.py +0 -0
  258. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a2_mo_composites/plan_store.py +0 -0
  259. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a2_mo_composites/receipt_signer.py +0 -0
  260. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a2_mo_composites/remote_seed_store.py +0 -0
  261. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/__init__.py +0 -0
  262. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/absorb_feature.py +0 -0
  263. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/agent_hire_protocol.py +0 -0
  264. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/cherry_hunter.py +0 -0
  265. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/cna_check.py +0 -0
  266. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/commandsmith_feature.py +0 -0
  267. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/commit_compose.py +0 -0
  268. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/create_feature.py +0 -0
  269. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/dedup_engine.py +0 -0
  270. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/demo_packages/mixed_py_js/src/mixed_pkg/__init__.py +0 -0
  271. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/demo_packages/mixed_py_js/src/mixed_pkg/a0_qk_constants/__init__.py +0 -0
  272. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/demo_packages/mixed_py_js/src/mixed_pkg/a1_at_functions/__init__.py +0 -0
  273. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/demo_packages/mixed_py_js/tests/conftest.py +0 -0
  274. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/demo_packages/mixed_py_js/tests/test_mixed.py +0 -0
  275. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/demo_runner.py +0 -0
  276. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/emergent_feature.py +0 -0
  277. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/emergent_pipeline_integration.py +0 -0
  278. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/emergent_swarm.py +0 -0
  279. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/enhancement_proposal_feature.py +0 -0
  280. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/forge_enforce.py +0 -0
  281. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/forge_evolve.py +0 -0
  282. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/forge_evolve_session.py +0 -0
  283. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/forge_loop.py +0 -0
  284. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/forge_loop_session.py +0 -0
  285. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/forge_metrics_feature.py +0 -0
  286. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/forge_plan_apply.py +0 -0
  287. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/guard_install.py +0 -0
  288. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/handoff_feature.py +0 -0
  289. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/hive_sync.py +0 -0
  290. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/lsp_server.py +0 -0
  291. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/materialize_feature.py +0 -0
  292. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/mcp_server.py +0 -0
  293. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/nexus_bridge.py +0 -0
  294. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/relay_daemon.py +0 -0
  295. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/setup_wizard.py +0 -0
  296. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/surface_export.py +0 -0
  297. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/synergy_feature.py +0 -0
  298. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/tool_factory.py +0 -0
  299. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/verify_umbrella.py +0 -0
  300. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/welcome_feature.py +0 -0
  301. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a3_og_features/wisdom_feature.py +0 -0
  302. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a4_sy_orchestration/__init__.py +0 -0
  303. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a4_sy_orchestration/cli.py +0 -0
  304. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a4_sy_orchestration/copilots_cmd.py +0 -0
  305. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a4_sy_orchestration/login_cmd.py +0 -0
  306. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/a4_sy_orchestration/whoami_cmd.py +0 -0
  307. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/commands/__init__.py +0 -0
  308. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/commands/_registry.py +0 -0
  309. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/commands/absorb.py +0 -0
  310. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/commands/audit.py +0 -0
  311. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/commands/chat.py +0 -0
  312. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/commands/commandsmith.py +0 -0
  313. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/commands/config_cmd.py +0 -0
  314. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/commands/create.py +0 -0
  315. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/commands/demo.py +0 -0
  316. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/commands/emergent.py +0 -0
  317. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/commands/emergent_swarm.py +0 -0
  318. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/commands/emergent_then_synergy.py +0 -0
  319. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/commands/enhancement.py +0 -0
  320. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/commands/evolve.py +0 -0
  321. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/commands/evolve_then_iterate.py +0 -0
  322. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/commands/feature_then_emergent.py +0 -0
  323. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/commands/guard_install.py +0 -0
  324. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/commands/handoff.py +0 -0
  325. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/commands/harvest.py +0 -0
  326. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/commands/hive.py +0 -0
  327. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/commands/iterate.py +0 -0
  328. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/commands/materialize.py +0 -0
  329. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/commands/metrics.py +0 -0
  330. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/commands/recon_swarm.py +0 -0
  331. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/commands/relay.py +0 -0
  332. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/commands/surface.py +0 -0
  333. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/commands/synergy.py +0 -0
  334. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/commands/synergy_then_emergent.py +0 -0
  335. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/commands/welcome.py +0 -0
  336. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge/commands/wisdom.py +0 -0
  337. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge.egg-info/dependency_links.txt +0 -0
  338. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge.egg-info/entry_points.txt +0 -0
  339. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge.egg-info/requires.txt +0 -0
  340. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/src/atomadic_forge.egg-info/top_level.txt +0 -0
  341. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_aaaa_nexus_client.py +0 -0
  342. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_agent_hire_protocol.py +0 -0
  343. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_agent_plan.py +0 -0
  344. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_agent_plan_pkg_label.py +0 -0
  345. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_agent_summary.py +0 -0
  346. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_ast_scope_lock.py +0 -0
  347. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_audit_verb.py +0 -0
  348. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_body_extractor_repairs.py +0 -0
  349. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_call_graph_summary.py +0 -0
  350. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_capability_scout.py +0 -0
  351. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_card_renderer.py +0 -0
  352. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_certify_operational_axis.py +0 -0
  353. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_chat.py +0 -0
  354. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_cherry_pick.py +0 -0
  355. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_classify_tier.py +0 -0
  356. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_classify_tier_ast_signals.py +0 -0
  357. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_cli_smoke.py +0 -0
  358. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_cli_swarm_aliases.py +0 -0
  359. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_codex_5_complete.py +0 -0
  360. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_codex_6_enforce_polyglot.py +0 -0
  361. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_commandsmith.py +0 -0
  362. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_compiler_feedback.py +0 -0
  363. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_compliance_checker.py +0 -0
  364. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_config.py +0 -0
  365. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_copilots_copilot.py +0 -0
  366. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_cost_circuit_breaker.py +0 -0
  367. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_create_feature.py +0 -0
  368. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_cs1_renderer.py +0 -0
  369. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_custom_provider.py +0 -0
  370. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_dead_code_check.py +0 -0
  371. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_dedup_engine.py +0 -0
  372. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_demo.py +0 -0
  373. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_doc_auto_update.py +0 -0
  374. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_emergent_compose.py +0 -0
  375. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_emergent_signature_extract.py +0 -0
  376. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_emergent_synthesize_imports.py +0 -0
  377. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_enhancement_proposal.py +0 -0
  378. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_error_codes.py +0 -0
  379. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_error_hints.py +0 -0
  380. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_evolve_js.py +0 -0
  381. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_exported_api_check.py +0 -0
  382. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_finalize_scaffold.py +0 -0
  383. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_forge_action.py +0 -0
  384. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_forge_auth_a1.py +0 -0
  385. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_forge_auth_a2.py +0 -0
  386. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_forge_enforce.py +0 -0
  387. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_generation_quality.py +0 -0
  388. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_git_churn.py +0 -0
  389. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_handoff.py +0 -0
  390. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_harvest_concept_bridge.py +0 -0
  391. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_hierarchical_memory.py +0 -0
  392. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_hive_sync.py +0 -0
  393. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_ignore_and_docs.py +0 -0
  394. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_import_smoke.py +0 -0
  395. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_iterate_evolve.py +0 -0
  396. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_js_certify.py +0 -0
  397. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_js_parser.py +0 -0
  398. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_js_recon.py +0 -0
  399. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_js_wire.py +0 -0
  400. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_lineage_chain.py +0 -0
  401. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_ling_provider.py +0 -0
  402. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_local_signer.py +0 -0
  403. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_lsp_protocol.py +0 -0
  404. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_maintainability_index.py +0 -0
  405. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_manifest_diff.py +0 -0
  406. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_materialize_feature.py +0 -0
  407. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_mcp_lazy_bootstrap.py +0 -0
  408. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_mcp_protocol.py +0 -0
  409. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_nexus_bridge.py +0 -0
  410. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_ollama_client.py +0 -0
  411. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_pipeline.py +0 -0
  412. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_plan_apply.py +0 -0
  413. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_polyglot_cli_mcp.py +0 -0
  414. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_polyglot_full_pipeline.py +0 -0
  415. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_polyglot_hardening.py +0 -0
  416. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_polyglot_swift_kotlin_go.py +0 -0
  417. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_polyglot_symbol_parity.py +0 -0
  418. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_pre_audit_smoke.py +0 -0
  419. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_precommit_hooks.py +0 -0
  420. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_progress_reporter.py +0 -0
  421. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_receipt_emitter.py +0 -0
  422. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_receipt_schema.py +0 -0
  423. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_receipt_signer.py +0 -0
  424. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_remote_seed_store.py +0 -0
  425. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_response_enricher.py +0 -0
  426. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_roi_calculator.py +0 -0
  427. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_sbom_cmd_text_summary.py +0 -0
  428. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_sbom_emitter.py +0 -0
  429. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_scaffold.py +0 -0
  430. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_sidecar.py +0 -0
  431. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_sidecar_validate.py +0 -0
  432. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_smell_score_formula.py +0 -0
  433. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_stagnation.py +0 -0
  434. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_steersman_pack.py +0 -0
  435. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_stub_detector.py +0 -0
  436. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_surface_export.py +0 -0
  437. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_surface_gap_check.py +0 -0
  438. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_synergy.py +0 -0
  439. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_test_runner.py +0 -0
  440. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_tier_init_rebuild.py +0 -0
  441. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_trust_gate_response.py +0 -0
  442. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_verify_suggested_recipe.py +0 -0
  443. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_welcome.py +0 -0
  444. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_welcome_enhancements.py +0 -0
  445. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_whoami_cmd.py +0 -0
  446. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_wire_certify.py +0 -0
  447. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_wire_stubs_gen.py +0 -0
  448. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_wire_suggest_repairs.py +0 -0
  449. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_wire_type_checking.py +0 -0
  450. {atomadic_forge-0.59.0 → atomadic_forge-0.60.0}/tests/test_wisdom.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: atomadic-forge
3
- Version: 0.59.0
3
+ Version: 0.60.0
4
4
  Summary: Atomadic Forge — absorb, enforce, emerge. Polyglot (Python · JavaScript/TypeScript · Rust · Go · Swift · Kotlin) architecture guardian for AI-generated code.
5
5
  Author: Atomadic
6
6
  License-Expression: BUSL-1.1
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "atomadic-forge"
7
- version = "0.59.0"
7
+ version = "0.60.0"
8
8
  description = "Atomadic Forge — absorb, enforce, emerge. Polyglot (Python · JavaScript/TypeScript · Rust · Go · Swift · Kotlin) architecture guardian for AI-generated code."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -0,0 +1,333 @@
1
+ """Tier a1 — Abstract-by-convention auto-repair for absorbed packages.
2
+
3
+ Many real Python repos use the "abstract by convention" pattern instead
4
+ of formally declaring abstract base classes:
5
+
6
+ class BaseCompressor:
7
+ \"\"\"Abstract base compressor.\"\"\"
8
+
9
+ def compress(self, messages: list[dict]) -> tuple[str, int]:
10
+ raise NotImplementedError
11
+
12
+ Concrete subclasses override ``compress`` and the runtime never sees the
13
+ parent's body. Python's ``abc`` module would catch this at instantiation
14
+ time with ``@abstractmethod`` and ``ABC``, but the upstream code never
15
+ did. When Forge absorbs such a repo, certify's stub detector — correctly
16
+ strict about ``NotImplementedError`` bodies — flags every copy of the
17
+ parent as a stub.
18
+
19
+ This module performs a post-emit pass on the absorbed package:
20
+
21
+ 1. Walk the tier directories.
22
+ 2. For each class whose name starts with ``Base``/``Abstract`` OR whose
23
+ docstring labels it abstract, scan its methods.
24
+ 3. A method is "abstract by convention" when its body is exclusively a
25
+ ``raise NotImplementedError`` (with optional docstring) AND its
26
+ signature is mirrored by a concrete override in another emitted
27
+ file under the same package.
28
+ 4. Insert an ``@abstractmethod`` decorator and ensure the file imports
29
+ ``abstractmethod`` from ``abc``. Add ``ABC`` to the class bases when
30
+ it has no other base (preserves runtime behavior; Python's
31
+ ``ABCMeta`` is forgiving when subclasses don't formally inherit).
32
+
33
+ The repair is deterministic and confined to source-text edits expressible
34
+ as line insertions — no AST round-trip rewrite. Idempotent: re-running
35
+ on an already-repaired file is a no-op.
36
+
37
+ Pure: no LLM, no I/O outside the supplied package root.
38
+ """
39
+ from __future__ import annotations
40
+
41
+ import ast
42
+ import re
43
+ from collections import defaultdict
44
+ from collections.abc import Iterable
45
+ from dataclasses import dataclass
46
+ from pathlib import Path
47
+
48
+ # Class-name signals that the author intends the class as a base/abstract.
49
+ _BASE_NAME_PREFIXES = ("Base", "Abstract", "_Base", "_Abstract")
50
+ # Class-name suffixes that imply "interface / contract" semantics.
51
+ _BASE_NAME_SUFFIXES = ("Interface", "Protocol", "ABC", "Abstract", "Base")
52
+ # Docstring tokens (case-insensitive) that signal the class is abstract.
53
+ _ABSTRACT_DOCSTRING_TOKENS = ("abstract", "interface", "must be implemented",
54
+ "must override", "subclasses must",
55
+ "subclasses should override",
56
+ "override this", "implementations must")
57
+
58
+
59
+ @dataclass(frozen=True)
60
+ class AbstractRepair:
61
+ """A single planned repair: add @abstractmethod to method ``qualname``.
62
+
63
+ ``file`` is the absolute path on disk. ``method_lineno`` and
64
+ ``method_indent`` are 1-based source coordinates. ``class_lineno``
65
+ captures the parent class so the repair can also adjust the bases
66
+ when needed.
67
+ """
68
+ file: str
69
+ qualname: str
70
+ class_lineno: int
71
+ method_lineno: int
72
+ method_indent: int
73
+
74
+
75
+ def _has_abstract_docstring(class_def: ast.ClassDef) -> bool:
76
+ if not class_def.body:
77
+ return False
78
+ first = class_def.body[0]
79
+ if not isinstance(first, ast.Expr):
80
+ return False
81
+ if not isinstance(first.value, ast.Constant):
82
+ return False
83
+ if not isinstance(first.value.value, str):
84
+ return False
85
+ doc = first.value.value.lower()
86
+ return any(tok in doc for tok in _ABSTRACT_DOCSTRING_TOKENS)
87
+
88
+
89
+ def _is_base_class_name(name: str) -> bool:
90
+ if any(name.startswith(p) for p in _BASE_NAME_PREFIXES):
91
+ return True
92
+ return any(name.endswith(s) for s in _BASE_NAME_SUFFIXES)
93
+
94
+
95
+ def _is_pure_stub_body(fn: ast.AST) -> bool:
96
+ """True when the method body is the canonical contract-only shape:
97
+
98
+ * ``raise NotImplementedError`` (with optional docstring), OR
99
+ * a bare ``pass`` (with optional docstring), OR
100
+ * a docstring only (the implicit ``pass`` form), OR
101
+ * an ellipsis (``...``) literal as the only statement.
102
+
103
+ Each of these forms communicates "this method is a placeholder" and,
104
+ when paired with a Base/Abstract/Interface class signal plus a
105
+ concrete override elsewhere, is the abstract-by-convention pattern.
106
+ """
107
+ if not isinstance(fn, ast.FunctionDef | ast.AsyncFunctionDef):
108
+ return False
109
+ body = list(fn.body)
110
+ if (body and isinstance(body[0], ast.Expr)
111
+ and isinstance(body[0].value, ast.Constant)
112
+ and isinstance(body[0].value.value, str)):
113
+ body = body[1:]
114
+ # Docstring-only body — implicit pass.
115
+ if not body:
116
+ return True
117
+ if len(body) != 1:
118
+ return False
119
+ only = body[0]
120
+ # Bare `pass`.
121
+ if isinstance(only, ast.Pass):
122
+ return True
123
+ # Bare `...` literal (Ellipsis).
124
+ if (isinstance(only, ast.Expr) and isinstance(only.value, ast.Constant)
125
+ and only.value.value is Ellipsis):
126
+ return True
127
+ # `raise NotImplementedError`.
128
+ if isinstance(only, ast.Raise) and only.exc is not None:
129
+ target = only.exc
130
+ if isinstance(target, ast.Call):
131
+ target = target.func
132
+ if isinstance(target, ast.Name) and target.id == "NotImplementedError":
133
+ return True
134
+ if (isinstance(target, ast.Attribute)
135
+ and target.attr == "NotImplementedError"):
136
+ return True
137
+ return False
138
+
139
+
140
+ # Backward-compat alias — earlier code may import the old name.
141
+ _is_pure_not_implemented = _is_pure_stub_body
142
+
143
+
144
+ def _has_explicit_abstract_decorator(fn: ast.FunctionDef) -> bool:
145
+ for deco in fn.decorator_list:
146
+ target = deco.func if isinstance(deco, ast.Call) else deco
147
+ name: str | None = None
148
+ if isinstance(target, ast.Name):
149
+ name = target.id
150
+ elif isinstance(target, ast.Attribute):
151
+ name = target.attr
152
+ if name and name.startswith("abstract"):
153
+ return True
154
+ return False
155
+
156
+
157
+ def _index_overrides(pkg_root: Path) -> dict[str, set[str]]:
158
+ """Map method-name -> set of qualified class names that define it.
159
+
160
+ A concrete override is any method whose body is NOT just a
161
+ ``NotImplementedError`` raise.
162
+ """
163
+ table: dict[str, set[str]] = defaultdict(set)
164
+ for path in pkg_root.rglob("*.py"):
165
+ if "__pycache__" in path.parts:
166
+ continue
167
+ try:
168
+ tree = ast.parse(path.read_text(encoding="utf-8", errors="replace"),
169
+ filename=str(path))
170
+ except SyntaxError:
171
+ continue
172
+ for node in ast.walk(tree):
173
+ if not isinstance(node, ast.ClassDef):
174
+ continue
175
+ for item in node.body:
176
+ if not isinstance(item, ast.FunctionDef | ast.AsyncFunctionDef):
177
+ continue
178
+ if _is_pure_stub_body(item):
179
+ continue
180
+ table[item.name].add(node.name)
181
+ return table
182
+
183
+
184
+ def find_abstract_repairs(pkg_root: Path) -> list[AbstractRepair]:
185
+ """Return every method that should be decorated with @abstractmethod.
186
+
187
+ Selection rules (all must hold):
188
+
189
+ * The enclosing class signals abstract intent (Base/Abstract prefix
190
+ OR an "abstract"-flavored docstring).
191
+ * The method body is exclusively a ``raise NotImplementedError``.
192
+ * The method does NOT already carry an abstractmethod decorator.
193
+ * Some other class in the package defines a concrete override of
194
+ the same method name.
195
+ """
196
+ pkg_root = Path(pkg_root)
197
+ if not pkg_root.is_dir():
198
+ return []
199
+
200
+ overrides = _index_overrides(pkg_root)
201
+ repairs: list[AbstractRepair] = []
202
+
203
+ for path in pkg_root.rglob("*.py"):
204
+ if "__pycache__" in path.parts:
205
+ continue
206
+ text = path.read_text(encoding="utf-8", errors="replace")
207
+ try:
208
+ tree = ast.parse(text, filename=str(path))
209
+ except SyntaxError:
210
+ continue
211
+ for node in tree.body:
212
+ if not isinstance(node, ast.ClassDef):
213
+ continue
214
+ if not (_is_base_class_name(node.name)
215
+ or _has_abstract_docstring(node)):
216
+ continue
217
+ for item in node.body:
218
+ if not isinstance(item, ast.FunctionDef | ast.AsyncFunctionDef):
219
+ continue
220
+ if _has_explicit_abstract_decorator(item):
221
+ continue
222
+ if not _is_pure_not_implemented(item):
223
+ continue
224
+ # Find concrete overrides in OTHER classes.
225
+ other_classes = overrides.get(item.name, set()) - {node.name}
226
+ if not other_classes:
227
+ continue
228
+ # Compute the indent of the method def.
229
+ lines = text.splitlines()
230
+ if not 0 < item.lineno <= len(lines):
231
+ continue
232
+ method_line = lines[item.lineno - 1]
233
+ indent = len(method_line) - len(method_line.lstrip())
234
+ repairs.append(AbstractRepair(
235
+ file=str(path),
236
+ qualname=f"{node.name}.{item.name}",
237
+ class_lineno=node.lineno,
238
+ method_lineno=item.lineno,
239
+ method_indent=indent,
240
+ ))
241
+ return repairs
242
+
243
+
244
+ _IMPORT_RE = re.compile(
245
+ r"^\s*from\s+abc\s+import\s+([^#\n]+)$", re.MULTILINE)
246
+
247
+
248
+ def _ensure_abstractmethod_import(text: str) -> str:
249
+ """Make sure ``abstractmethod`` is imported from ``abc``."""
250
+ match = _IMPORT_RE.search(text)
251
+ if match:
252
+ names = [n.strip() for n in match.group(1).split(",")]
253
+ if "abstractmethod" in names:
254
+ return text
255
+ new_names = sorted({*names, "abstractmethod"})
256
+ new_line = f"from abc import {', '.join(new_names)}"
257
+ return text[:match.start()] + new_line + text[match.end():]
258
+ # No abc import yet — insert after `from __future__` block or at top.
259
+ lines = text.splitlines(keepends=True)
260
+ insert_at = 0
261
+ for idx, line in enumerate(lines):
262
+ if line.startswith("from __future__"):
263
+ insert_at = idx + 1
264
+ elif line.startswith('"""') or line.startswith("'''"):
265
+ # Walk past a module docstring.
266
+ quote = line.strip()[:3]
267
+ if line.count(quote) >= 2:
268
+ insert_at = max(insert_at, idx + 1)
269
+ else:
270
+ for j in range(idx + 1, len(lines)):
271
+ if quote in lines[j]:
272
+ insert_at = max(insert_at, j + 1)
273
+ break
274
+ new_line = "from abc import abstractmethod\n"
275
+ lines.insert(insert_at, new_line)
276
+ return "".join(lines)
277
+
278
+
279
+ def apply_repairs(repairs: Iterable[AbstractRepair]) -> dict[str, int]:
280
+ """Apply each planned @abstractmethod insertion.
281
+
282
+ Returns a summary dict ``{'files_touched': N, 'methods_decorated': M}``.
283
+ """
284
+ files_to_repairs: dict[Path, list[AbstractRepair]] = defaultdict(list)
285
+ for repair in repairs:
286
+ files_to_repairs[Path(repair.file)].append(repair)
287
+
288
+ methods_decorated = 0
289
+ files_touched = 0
290
+
291
+ for path, file_repairs in files_to_repairs.items():
292
+ text = path.read_text(encoding="utf-8", errors="replace")
293
+ # Decorator insertion uses line numbers from the AST that was
294
+ # parsed against THIS source. Apply decorators FIRST so those
295
+ # coordinates stay valid. Then add the abc import on top.
296
+ lines = text.splitlines(keepends=True)
297
+ # Apply from highest line number down so earlier inserts don't
298
+ # shift later coordinates within the same file.
299
+ for repair in sorted(file_repairs,
300
+ key=lambda r: r.method_lineno, reverse=True):
301
+ decorator_line = (" " * repair.method_indent
302
+ + "@abstractmethod\n")
303
+ insert_index = repair.method_lineno - 1
304
+ # If the previous non-blank line is already @abstractmethod,
305
+ # skip — this is a re-run.
306
+ j = insert_index - 1
307
+ while j >= 0 and lines[j].strip() == "":
308
+ j -= 1
309
+ if j >= 0 and lines[j].strip() == "@abstractmethod":
310
+ continue
311
+ lines.insert(insert_index, decorator_line)
312
+ methods_decorated += 1
313
+ new_text = "".join(lines)
314
+ new_text = _ensure_abstractmethod_import(new_text)
315
+ path.write_text(new_text, encoding="utf-8")
316
+ files_touched += 1
317
+
318
+ return {
319
+ "files_touched": files_touched,
320
+ "methods_decorated": methods_decorated,
321
+ }
322
+
323
+
324
+ def repair_abstract_by_convention(pkg_root: Path) -> dict[str, int]:
325
+ """Detect and apply all abstract-by-convention repairs in one call.
326
+
327
+ Returns the same summary shape as :func:`apply_repairs`, plus
328
+ ``repairs_planned`` for traceability.
329
+ """
330
+ planned = find_abstract_repairs(Path(pkg_root))
331
+ summary = apply_repairs(planned)
332
+ summary["repairs_planned"] = len(planned)
333
+ return summary
@@ -21,6 +21,9 @@ from typing import Any
21
21
 
22
22
  from .. import __version__
23
23
  from ..a0_qk_constants.tier_names import TIER_NAMES
24
+ from ..a1_at_functions.abstract_method_repair import (
25
+ repair_abstract_by_convention,
26
+ )
24
27
  from ..a1_at_functions.agent_plan_emitter import emit_agent_plan
25
28
  from ..a1_at_functions.certify_checks import certify
26
29
  from ..a1_at_functions.cherry_pick import select_items
@@ -299,6 +302,9 @@ def run_finalize(*, target: Path, output: Path, package: str = "absorbed",
299
302
  ).hexdigest()[:16]
300
303
 
301
304
  scaffold_written: list[str] = []
305
+ abstract_repair: dict[str, int] = {
306
+ "files_touched": 0, "methods_decorated": 0, "repairs_planned": 0,
307
+ }
302
308
  if apply:
303
309
  status = _STATUS_TEMPLATE.format(
304
310
  source_count=1,
@@ -318,6 +324,19 @@ def run_finalize(*, target: Path, output: Path, package: str = "absorbed",
318
324
  digest=digest,
319
325
  )
320
326
 
327
+ # Auto-repair abstract-by-convention: when the absorbed source
328
+ # uses Base*/Abstract* classes with NotImplementedError methods
329
+ # that are concretely overridden elsewhere in the package, add
330
+ # the @abstractmethod decorator. Closes the residual 92→100
331
+ # gap on real-world repos that don't formally use abc.ABC.
332
+ try:
333
+ abstract_repair = repair_abstract_by_convention(pkg_root)
334
+ except Exception: # pragma: no cover - never abort absorption on repair
335
+ abstract_repair = {"files_touched": 0,
336
+ "methods_decorated": 0,
337
+ "repairs_planned": 0,
338
+ "error": "exception"}
339
+
321
340
  wire_report = scan_violations(pkg_root) if apply else {
322
341
  "verdict": "DRY_RUN", "violation_count": 0, "violations": []
323
342
  }
@@ -339,6 +358,7 @@ def run_finalize(*, target: Path, output: Path, package: str = "absorbed",
339
358
  "applied": apply,
340
359
  "on_conflict": on_conflict,
341
360
  "scaffold_files_written": scaffold_written,
361
+ "abstract_repair": abstract_repair,
342
362
  }
343
363
  if apply:
344
364
  ManifestStore(output).save("assimilate", report)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: atomadic-forge
3
- Version: 0.59.0
3
+ Version: 0.60.0
4
4
  Summary: Atomadic Forge — absorb, enforce, emerge. Polyglot (Python · JavaScript/TypeScript · Rust · Go · Swift · Kotlin) architecture guardian for AI-generated code.
5
5
  Author: Atomadic
6
6
  License-Expression: BUSL-1.1
@@ -140,6 +140,7 @@ src/atomadic_forge/a0_qk_constants/tier_names.py
140
140
  src/atomadic_forge/a0_qk_constants/welcome_constants.py
141
141
  src/atomadic_forge/a0_qk_constants/wisdom_constants.py
142
142
  src/atomadic_forge/a1_at_functions/__init__.py
143
+ src/atomadic_forge/a1_at_functions/abstract_method_repair.py
143
144
  src/atomadic_forge/a1_at_functions/agent_context_pack.py
144
145
  src/atomadic_forge/a1_at_functions/agent_memory.py
145
146
  src/atomadic_forge/a1_at_functions/agent_plan_emitter.py
@@ -335,6 +336,7 @@ src/atomadic_forge/commands/synergy_then_emergent.py
335
336
  src/atomadic_forge/commands/welcome.py
336
337
  src/atomadic_forge/commands/wisdom.py
337
338
  tests/test_aaaa_nexus_client.py
339
+ tests/test_abstract_method_repair.py
338
340
  tests/test_agent_hire_protocol.py
339
341
  tests/test_agent_plan.py
340
342
  tests/test_agent_plan_pkg_label.py
@@ -0,0 +1,122 @@
1
+ """Tests for abstract_method_repair — closes the abstract-by-convention gap."""
2
+ from __future__ import annotations
3
+
4
+ from pathlib import Path
5
+
6
+ from atomadic_forge.a1_at_functions.abstract_method_repair import (
7
+ apply_repairs,
8
+ find_abstract_repairs,
9
+ repair_abstract_by_convention,
10
+ )
11
+
12
+
13
+ def _seed(pkg_root: Path) -> None:
14
+ """A package whose Base class uses the abstract-by-convention pattern."""
15
+ pkg_root.mkdir(parents=True, exist_ok=True)
16
+ (pkg_root / "base.py").write_text(
17
+ '"""Abstract base compressor."""\n'
18
+ "\n"
19
+ "class BaseCompressor:\n"
20
+ ' """Abstract base compressor."""\n'
21
+ "\n"
22
+ " def compress(self, messages):\n"
23
+ " raise NotImplementedError\n",
24
+ encoding="utf-8",
25
+ )
26
+ (pkg_root / "concrete.py").write_text(
27
+ "\n"
28
+ "class EngramCompressor:\n"
29
+ " def compress(self, messages):\n"
30
+ ' return ("compressed", 1)\n',
31
+ encoding="utf-8",
32
+ )
33
+
34
+
35
+ def test_finds_abstract_by_convention(tmp_path):
36
+ _seed(tmp_path / "pkg")
37
+ repairs = find_abstract_repairs(tmp_path / "pkg")
38
+ quals = [r.qualname for r in repairs]
39
+ assert quals == ["BaseCompressor.compress"]
40
+
41
+
42
+ def test_skips_when_no_concrete_override_exists(tmp_path):
43
+ """A Base class with no subclass override is genuinely undefined —
44
+ don't auto-decorate; the author hasn't expressed intent yet."""
45
+ pkg = tmp_path / "pkg"
46
+ pkg.mkdir()
47
+ (pkg / "base.py").write_text(
48
+ "class BaseThing:\n"
49
+ ' """Abstract."""\n'
50
+ " def run(self):\n"
51
+ " raise NotImplementedError\n",
52
+ encoding="utf-8",
53
+ )
54
+ repairs = find_abstract_repairs(pkg)
55
+ assert repairs == []
56
+
57
+
58
+ def test_skips_when_already_decorated(tmp_path):
59
+ pkg = tmp_path / "pkg"
60
+ pkg.mkdir()
61
+ (pkg / "base.py").write_text(
62
+ "from abc import abstractmethod\n"
63
+ "class BaseCompressor:\n"
64
+ ' """Abstract base compressor."""\n'
65
+ " @abstractmethod\n"
66
+ " def compress(self, messages):\n"
67
+ " raise NotImplementedError\n",
68
+ encoding="utf-8",
69
+ )
70
+ (pkg / "concrete.py").write_text(
71
+ "class EngramCompressor:\n"
72
+ " def compress(self, messages):\n"
73
+ " return ('x', 1)\n",
74
+ encoding="utf-8",
75
+ )
76
+ repairs = find_abstract_repairs(pkg)
77
+ assert repairs == []
78
+
79
+
80
+ def test_apply_repairs_inserts_decorator_and_import(tmp_path):
81
+ pkg = tmp_path / "pkg"
82
+ _seed(pkg)
83
+ repairs = find_abstract_repairs(pkg)
84
+ summary = apply_repairs(repairs)
85
+ assert summary["files_touched"] == 1
86
+ assert summary["methods_decorated"] == 1
87
+
88
+ after = (pkg / "base.py").read_text(encoding="utf-8")
89
+ assert "from abc import abstractmethod" in after
90
+ assert "@abstractmethod\n def compress" in after
91
+
92
+
93
+ def test_repair_abstract_by_convention_is_idempotent(tmp_path):
94
+ pkg = tmp_path / "pkg"
95
+ _seed(pkg)
96
+ first = repair_abstract_by_convention(pkg)
97
+ second = repair_abstract_by_convention(pkg)
98
+ assert first["methods_decorated"] == 1
99
+ # Second pass: the file is already decorated; planned == 0.
100
+ assert second["repairs_planned"] == 0
101
+ assert second["methods_decorated"] == 0
102
+
103
+
104
+ def test_handles_class_without_base_prefix_but_abstract_docstring(tmp_path):
105
+ pkg = tmp_path / "pkg"
106
+ pkg.mkdir()
107
+ (pkg / "iface.py").write_text(
108
+ "class Compressor:\n"
109
+ ' """Interface — subclasses must implement compress."""\n'
110
+ " def compress(self, messages):\n"
111
+ " raise NotImplementedError\n",
112
+ encoding="utf-8",
113
+ )
114
+ (pkg / "impl.py").write_text(
115
+ "class FastCompressor:\n"
116
+ " def compress(self, messages):\n"
117
+ " return ('y', 2)\n",
118
+ encoding="utf-8",
119
+ )
120
+ repairs = find_abstract_repairs(pkg)
121
+ quals = [r.qualname for r in repairs]
122
+ assert quals == ["Compressor.compress"]
File without changes