atomadic-forge 0.77.0__tar.gz → 0.79.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.
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/.github/workflows/metrics-auto-regen.yml +1 -1
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/CHANGELOG.md +16 -0
- {atomadic_forge-0.77.0/src/atomadic_forge.egg-info → atomadic_forge-0.79.0}/PKG-INFO +3 -3
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/README.md +2 -2
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/CI_CD.md +3 -3
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/COMMANDS.md +1 -1
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/FORMALIZATION.md +2 -2
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/RECEIPT.md +2 -2
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/pyproject.toml +1 -1
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/certify_checks.py +2 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/doc_auto_update.py +2 -2
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/response_enricher.py +22 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/scout_walk.py +2 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/wire_check.py +2 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/emergent_feature.py +2 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/forge_pipeline.py +2 -0
- atomadic_forge-0.79.0/src/atomadic_forge/a3_og_features/recipe_replay.py +158 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/synergy_feature.py +2 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/verify_umbrella.py +2 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a4_sy_orchestration/cli.py +10 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/commands/metrics.py +8 -13
- atomadic_forge-0.79.0/src/atomadic_forge/commands/replay.py +101 -0
- atomadic_forge-0.79.0/src/atomadic_forge/commands/token_savings.py +70 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0/src/atomadic_forge.egg-info}/PKG-INFO +3 -3
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge.egg-info/SOURCES.txt +5 -0
- atomadic_forge-0.79.0/tests/test_recipe_replay.py +88 -0
- atomadic_forge-0.79.0/tests/test_token_savings_ledger.py +76 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_welcome_enhancements.py +10 -7
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/.github/FUNDING.yml +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/.github/actions/forge-action/README.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/.github/actions/forge-action/action.yml +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/.github/dependabot.yml +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/.github/pull_request_template.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/.github/workflows/ci.yml +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/.github/workflows/customer-refactor.yml +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/.github/workflows/forge-self-certify.yml +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/.github/workflows/mcp-registry-publish.yml +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/.github/workflows/metrics-drift.yml +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/.github/workflows/publish-on-tag.yml +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/.github/workflows/release-readiness.yml +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/.github/workflows/release.yml +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/.github/workflows/surface-drift.yml +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/.github/workflows/uptime.yml +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/ARCHITECTURE.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/CONTRIBUTING.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/LICENSE +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/MANIFEST.in +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/SECURITY.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/assets/Atomadic-Forge-01.png +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/01-getting-started.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/02-commands.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/03-tutorial.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/04-llm-loops.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/05-faq.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/AGENTS_GUIDE.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/AIR_GAPPED.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/CODEX_WALKTHROUGH.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/FIRST_10_MINUTES.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/HIVE_PRIMITIVES.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/HIVE_STATUS.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/IDE_INTEGRATION.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/LANDSCAPE.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/MARKET_POSITIONING.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/MCP_TOOLS.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/MIGRATION.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/MULTI_REPO.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/PROVIDERS.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/README.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/RELAY_PROTOCOL.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/RELEASE_CHECKLIST.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/RELEASE_MESSAGING.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/ROADMAP.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/SHOWCASE.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/SIDECAR.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/STUDIO.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/TOOL_FACTORY_WALKTHROUGH.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/V0.46.0_JUSTIFICATION_REPORT.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/V0.47.0_SELF_TEST_REPORT.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/WHY_NOW.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/WORKER_VS_LOCAL_MCP.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/WORLD_COLLISION.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/commands/INDEX.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/commands/absorb.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/commands/audit.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/commands/chat.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/commands/commandsmith.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/commands/config.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/commands/create.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/commands/demo.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/commands/emergent-swarm.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/commands/emergent-then-synergy.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/commands/emergent.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/commands/enhancement.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/commands/evolve-then-iterate.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/commands/evolve.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/commands/feature-then-emergent.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/commands/guard-install.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/commands/handoff.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/commands/harvest.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/commands/hive.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/commands/iterate.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/commands/materialize.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/commands/metrics.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/commands/recon-swarm.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/commands/relay.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/commands/surface.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/commands/synergy-then-emergent.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/commands/synergy.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/commands/welcome.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/commands/wisdom.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/compliance/CMMC_AI_MAPPING.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/compliance/CS-1.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/compliance/EU_AI_ACT_ANNEX_IV.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/compliance/FDA_PCCP_MAPPING.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/compliance/SR_11-7_MAPPING.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/handoffs/WORKER_AUTO_DEPLOY_2026-05-06.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/tutorials/01-quickstart.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/tutorials/02-your-first-package.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/tutorials/03-the-five-tier-law.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/tutorials/04-plug-in-llms.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/tutorials/05-multi-repo-absorb.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/docs/tutorials/06-javascript-quickstart.md +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/setup.cfg +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/__init__.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/__main__.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a0_qk_constants/__init__.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a0_qk_constants/agent_plan_schema.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a0_qk_constants/auth_constants.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a0_qk_constants/commandsmith_types.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a0_qk_constants/config_defaults.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a0_qk_constants/emergent_types.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a0_qk_constants/enhancement_proposal_constants.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a0_qk_constants/error_codes.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a0_qk_constants/forge_types.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a0_qk_constants/gen_language.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a0_qk_constants/handoff_constants.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a0_qk_constants/hive_constants.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a0_qk_constants/lang_extensions.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a0_qk_constants/lifetime_savings_constants.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a0_qk_constants/materialize_types.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a0_qk_constants/mhed_invariants.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a0_qk_constants/nexus_constants.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a0_qk_constants/policy_schema.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a0_qk_constants/receipt_schema.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a0_qk_constants/response_enrichment.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a0_qk_constants/roi_constants.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a0_qk_constants/schema_version_registry.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a0_qk_constants/semantic_types.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a0_qk_constants/sidecar_schema.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a0_qk_constants/synergy_types.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a0_qk_constants/tier_names.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a0_qk_constants/welcome_constants.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a0_qk_constants/wisdom_constants.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/__init__.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/abstract_method_repair.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/agent_context_pack.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/agent_memory.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/agent_plan_emitter.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/agent_summary.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/ast_scope_lock.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/body_extractor.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/call_graph.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/capability_scout.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/card_renderer.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/chat_context.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/cherry_pick.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/classify_tier.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/code_signature.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/commandsmith_discover.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/commandsmith_render.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/compiler_feedback.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/compliance_checker.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/config_io.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/cosine_similarity.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/cs1_renderer.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/custom_provider_client.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/dead_code_check.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/doc_synthesizer.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/emergent_compose.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/emergent_rank.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/emergent_signature_extract.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/emergent_synthesize.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/enforce_planner.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/enhancement_proposal_builder.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/error_hints.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/evolution_log.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/exported_api_check.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/forge_auth.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/forge_feedback.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/forge_locate.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/forge_metrics.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/generation_quality.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/git_churn.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/graft_extract.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/handoff_builder.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/harvest_absorb.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/harvest_concept_bridge.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/hive_consensus_math.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/hive_io.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/import_repair.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/import_smoke.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/intent_similarity.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/js_parser.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/lifetime_savings.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/lineage_chain.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/lineage_reader.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/llm_client.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/local_signer.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/lsp_protocol.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/maintainability_index.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/manifest_diff.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/mcp_protocol.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/patch_scorer.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/plan_adapter.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/policy_loader.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/polyglot_classify.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/polyglot_imports.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/polyglot_surface.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/preflight_change.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/progress_reporter.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/provider_detect.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/provider_resolver.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/receipt_emitter.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/recipes.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/repo_explainer.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/repo_public_surface.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/research_note_distiller.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/roi_calculator.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/rollback_planner.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/sbom_emitter.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/scaffold_js.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/scaffold_polyglot.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/scaffold_pyproject.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/scaffold_starter.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/sidecar_parser.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/sidecar_validator.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/smell_scan.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/steersman_pack.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/stub_detector.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/surface_gap_check.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/synergy_detect.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/synergy_render.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/synergy_surface_extract.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/test_runner.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/test_selector.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/tier_init_rebuild.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/tool_composer.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/transcript_log.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/trust_gate_response.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/validation_commands.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/welcome_narrator.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/wire_stubs_gen.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/wisdom_capture.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/wisdom_io.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/wisdom_promote.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/wisdom_recall.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a1_at_functions/worktree_status.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a2_mo_composites/__init__.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a2_mo_composites/cost_circuit_breaker.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a2_mo_composites/cross_agent_intent_deduplicator.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a2_mo_composites/evolve_session_store.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a2_mo_composites/forge_auth_client.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a2_mo_composites/hierarchical_memory.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a2_mo_composites/iterate_session_store.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a2_mo_composites/lineage_chain_store.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a2_mo_composites/manifest_store.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a2_mo_composites/nexus_client.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a2_mo_composites/plan_store.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a2_mo_composites/receipt_signer.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a2_mo_composites/remote_seed_store.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a2_mo_composites/repo_public_surface_sync.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/__init__.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/absorb_feature.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/agent_hire_protocol.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/cherry_hunter.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/cna_check.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/commandsmith_feature.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/commit_compose.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/create_feature.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/dedup_engine.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/demo_packages/mixed_py_js/src/mixed_pkg/__init__.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/demo_packages/mixed_py_js/src/mixed_pkg/a0_qk_constants/__init__.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/demo_packages/mixed_py_js/src/mixed_pkg/a1_at_functions/__init__.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/demo_packages/mixed_py_js/tests/conftest.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/demo_packages/mixed_py_js/tests/test_mixed.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/demo_runner.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/emergent_pipeline_integration.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/emergent_swarm.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/enhancement_proposal_feature.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/forge_enforce.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/forge_evolve.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/forge_evolve_session.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/forge_loop.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/forge_loop_session.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/forge_metrics_feature.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/forge_plan_apply.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/graft_feature.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/guard_install.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/handoff_feature.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/hive_sync.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/lsp_server.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/materialize_feature.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/mcp_server.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/nexus_bridge.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/relay_daemon.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/setup_wizard.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/surface_export.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/tool_factory.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/welcome_feature.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a3_og_features/wisdom_feature.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a4_sy_orchestration/__init__.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a4_sy_orchestration/copilots_cmd.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a4_sy_orchestration/login_cmd.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a4_sy_orchestration/whoami_cmd.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/commands/__init__.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/commands/_registry.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/commands/absorb.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/commands/audit.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/commands/chat.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/commands/commandsmith.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/commands/config_cmd.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/commands/create.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/commands/demo.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/commands/emergent.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/commands/emergent_swarm.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/commands/emergent_then_synergy.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/commands/enhancement.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/commands/evolve.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/commands/evolve_then_iterate.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/commands/feature_then_emergent.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/commands/graft.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/commands/guard_install.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/commands/handoff.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/commands/harvest.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/commands/hive.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/commands/iterate.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/commands/materialize.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/commands/recon_swarm.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/commands/relay.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/commands/surface.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/commands/synergy.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/commands/synergy_then_emergent.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/commands/welcome.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/commands/wisdom.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge.egg-info/dependency_links.txt +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge.egg-info/entry_points.txt +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge.egg-info/requires.txt +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge.egg-info/top_level.txt +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_aaaa_nexus_client.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_abstract_method_repair.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_agent_hire_protocol.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_agent_plan.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_agent_plan_pkg_label.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_agent_summary.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_ast_scope_lock.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_audit_verb.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_body_extractor_repairs.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_call_graph_summary.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_capability_scout.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_card_renderer.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_certify_operational_axis.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_chat.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_cherry_dedup_class_methods.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_cherry_pick.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_classify_tier.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_classify_tier_ast_signals.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_cli_smoke.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_cli_swarm_aliases.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_codex_5_complete.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_codex_6_enforce_polyglot.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_commandsmith.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_compiler_feedback.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_compliance_checker.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_config.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_copilots_copilot.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_cost_circuit_breaker.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_create_feature.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_cs1_renderer.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_custom_provider.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_dead_code_check.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_dedup_engine.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_demo.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_doc_auto_update.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_emergent_compose.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_emergent_signature_extract.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_emergent_synthesize_imports.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_enhancement_proposal.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_error_codes.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_error_hints.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_evolve_js.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_exported_api_check.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_finalize_scaffold.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_forge_action.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_forge_auth_a1.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_forge_auth_a2.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_forge_enforce.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_generation_quality.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_git_churn.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_graft_feature.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_handoff.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_harvest_concept_bridge.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_harvest_source_warnings.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_hierarchical_memory.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_hive_sync.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_ignore_and_docs.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_import_smoke.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_iterate_evolve.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_js_certify.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_js_parser.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_js_recon.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_js_wire.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_lineage_chain.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_ling_provider.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_local_signer.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_lsp_protocol.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_maintainability_index.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_manifest_diff.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_materialize_feature.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_mcp_lazy_bootstrap.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_mcp_protocol.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_nexus_bridge.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_ollama_client.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_pipeline.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_plan_apply.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_polyglot_cli_mcp.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_polyglot_full_pipeline.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_polyglot_hardening.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_polyglot_swift_kotlin_go.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_polyglot_symbol_parity.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_pre_audit_smoke.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_precommit_hooks.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_progress_reporter.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_receipt_emitter.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_receipt_schema.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_receipt_signer.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_remote_seed_store.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_repo_public_surface.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_response_enricher.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_roi_calculator.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_sbom_cmd_text_summary.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_sbom_emitter.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_scaffold.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_sidecar.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_sidecar_validate.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_smell_score_formula.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_stagnation.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_steersman_pack.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_stub_detector.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_surface_export.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_surface_gap_check.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_synergy.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_test_runner.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_tier_init_rebuild.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_trust_gate_response.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_verify_suggested_recipe.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_welcome.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_whoami_cmd.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_wire_certify.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_wire_stubs_gen.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_wire_suggest_repairs.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_wire_type_checking.py +0 -0
- {atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/tests/test_wisdom.py +0 -0
|
@@ -33,7 +33,7 @@ jobs:
|
|
|
33
33
|
regen:
|
|
34
34
|
runs-on: ubuntu-latest
|
|
35
35
|
timeout-minutes: 8
|
|
36
|
-
if: ${{ !contains(github.event.head_commit.message, '[skip ci]') && !contains(github.event.head_commit.message, 'chore(metrics): auto-regenerate') }}
|
|
36
|
+
if: ${{ !contains(github.event.head_commit.message || '', '[skip ci]') && !contains(github.event.head_commit.message || '', 'chore(metrics): auto-regenerate') }}
|
|
37
37
|
steps:
|
|
38
38
|
- uses: actions/checkout@v4
|
|
39
39
|
with:
|
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## v0.79.0 — 2026-05-08
|
|
6
|
+
|
|
7
|
+
- feat(forge): replay — deterministic golden-recipe execution
|
|
8
|
+
- fix(compat): replace datetime.UTC with timezone.utc for Python 3.10 compat
|
|
9
|
+
- fix(ci): null-safe head_commit.message in metrics-auto-regen if condition
|
|
10
|
+
- chore(metrics): sync forge_metrics.json after cli_verb_count method change
|
|
11
|
+
- fix(surface): regenerate surface.json with package_version 0.78.0
|
|
12
|
+
- fix(metrics): replace upward a4 import in _live_cli_verb_count with file scan
|
|
13
|
+
- chore(release): sync artifacts + doc anchors for v0.78.0
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
## v0.78.0 — 2026-05-08
|
|
17
|
+
|
|
18
|
+
- feat(forge): token-savings auto-ledger across every enriched verb
|
|
19
|
+
|
|
20
|
+
|
|
5
21
|
## v0.77.0 — 2026-05-08
|
|
6
22
|
|
|
7
23
|
- fix(forge): cherry-pick — collapse Class.method explosion (root-cause)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: atomadic-forge
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.79.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
|
|
@@ -225,8 +225,8 @@ Full tool reference: [docs/MCP_TOOLS.md](docs/MCP_TOOLS.md) | First call: `welco
|
|
|
225
225
|
|
|
226
226
|
| MCP tools | **10 tools · 116 actions** |
|
|
227
227
|
| CLI verbs | **59** |
|
|
228
|
-
| Source files | **
|
|
229
|
-
| Tests | **
|
|
228
|
+
| Source files | **235** (~47K LOC) |
|
|
229
|
+
| Tests | **1597 passing** across **117 test files** |
|
|
230
230
|
| Lean4 formal proofs | **872 theorems** (mathematically verified core logic) |
|
|
231
231
|
| Monadic tiers | **5** (a0 → a4, strict upward-only composition) |
|
|
232
232
|
| Languages | Python, JS/TS, Swift, Kotlin, Go, Rust |
|
|
@@ -193,8 +193,8 @@ Full tool reference: [docs/MCP_TOOLS.md](docs/MCP_TOOLS.md) | First call: `welco
|
|
|
193
193
|
|
|
194
194
|
| MCP tools | **10 tools · 116 actions** |
|
|
195
195
|
| CLI verbs | **59** |
|
|
196
|
-
| Source files | **
|
|
197
|
-
| Tests | **
|
|
196
|
+
| Source files | **235** (~47K LOC) |
|
|
197
|
+
| Tests | **1597 passing** across **117 test files** |
|
|
198
198
|
| Lean4 formal proofs | **872 theorems** (mathematically verified core logic) |
|
|
199
199
|
| Monadic tiers | **5** (a0 → a4, strict upward-only composition) |
|
|
200
200
|
| Languages | Python, JS/TS, Swift, Kotlin, Go, Rust |
|
|
@@ -46,7 +46,7 @@ jobs:
|
|
|
46
46
|
run: |
|
|
47
47
|
pip install atomadic-forge # PyPI (preferred)
|
|
48
48
|
# Or pin to an exact tag:
|
|
49
|
-
# pip install "git+https://github.com/atomadictech/atomadic-forge@v0.
|
|
49
|
+
# pip install "git+https://github.com/atomadictech/atomadic-forge@v0.78.0"
|
|
50
50
|
# Or vendor wheels: pip install --no-index --find-links wheels/ atomadic-forge
|
|
51
51
|
|
|
52
52
|
- name: Wire scan (upward-import discipline)
|
|
@@ -97,7 +97,7 @@ forge-certify:
|
|
|
97
97
|
image: python:3.11-slim
|
|
98
98
|
timeout: 10 minutes
|
|
99
99
|
before_script:
|
|
100
|
-
- pip install "git+https://github.com/atomadictech/atomadic-forge@v0.
|
|
100
|
+
- pip install "git+https://github.com/atomadictech/atomadic-forge@v0.78.0"
|
|
101
101
|
script:
|
|
102
102
|
- forge wire src/your_package --fail-on-violations --json > wire.json
|
|
103
103
|
- forge certify . --package your_package --fail-under 75 --json > certify.json
|
|
@@ -156,7 +156,7 @@ Then in **the consuming repo's** `.pre-commit-config.yaml`:
|
|
|
156
156
|
```yaml
|
|
157
157
|
repos:
|
|
158
158
|
- repo: https://github.com/atomadictech/atomadic-forge
|
|
159
|
-
rev: v0.
|
|
159
|
+
rev: v0.78.0
|
|
160
160
|
hooks:
|
|
161
161
|
- id: forge-wire
|
|
162
162
|
- id: forge-certify
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Atomadic Forge — Command Reference
|
|
2
2
|
|
|
3
|
-
All verbs available in the `forge` CLI as of 0.
|
|
3
|
+
All verbs available in the `forge` CLI as of 0.78.0
|
|
4
4
|
|
|
5
5
|
> For the structured per-verb reference (with options, examples, and
|
|
6
6
|
> output samples), see [02-commands.md](02-commands.md). This page is
|
|
@@ -39,7 +39,7 @@ Forge certify scores out of **100** in two layers:
|
|
|
39
39
|
JS / TS packages cap at **60/100** today: they earn the four
|
|
40
40
|
structural axes, but the +25 runtime-import smoke and +30 behavioural
|
|
41
41
|
pytest are Python-only. Wiring `npm test` / Vitest into the
|
|
42
|
-
behavioural axis is on the post-v0.
|
|
42
|
+
behavioural axis is on the post-v0.78.0 roadmap.
|
|
43
43
|
|
|
44
44
|
---
|
|
45
45
|
|
|
@@ -131,7 +131,7 @@ runtime dependency makes the package unusable.
|
|
|
131
131
|
|
|
132
132
|
**Why JS/TS does not get this gate yet.** AAM §5.4 (Threats to
|
|
133
133
|
Validity) explicitly flags polyglot runtime gating as a roadmap
|
|
134
|
-
item (post-v0.
|
|
134
|
+
item (post-v0.78.0): the equivalent for JS would be an `npm test`
|
|
135
135
|
invocation, which requires a Node toolchain we do not yet bundle.
|
|
136
136
|
|
|
137
137
|
**Citation.** AAM §5.1 (Core Pipeline Pseudocode); AAM §5.4 (Threats
|
|
@@ -30,7 +30,7 @@ referenced from the Receipt.
|
|
|
30
30
|
{
|
|
31
31
|
"schema_version": "atomadic-forge.receipt/v1",
|
|
32
32
|
"generated_at_utc": "2026-04-28T17:42:11Z",
|
|
33
|
-
"forge_version": "0.
|
|
33
|
+
"forge_version": "0.78.0",
|
|
34
34
|
"verdict": "PASS",
|
|
35
35
|
"project": { ... },
|
|
36
36
|
"certify": { ... },
|
|
@@ -108,7 +108,7 @@ cited:
|
|
|
108
108
|
{
|
|
109
109
|
"schema_version": "atomadic-forge.receipt/v1",
|
|
110
110
|
"generated_at_utc": "2026-04-28T17:42:11Z",
|
|
111
|
-
"forge_version": "0.
|
|
111
|
+
"forge_version": "0.78.0",
|
|
112
112
|
"verdict": "PASS",
|
|
113
113
|
|
|
114
114
|
"project": {
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "atomadic-forge"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.79.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"
|
|
@@ -58,7 +58,7 @@ from __future__ import annotations
|
|
|
58
58
|
import json
|
|
59
59
|
import re
|
|
60
60
|
import subprocess
|
|
61
|
-
from datetime import
|
|
61
|
+
from datetime import datetime, timezone
|
|
62
62
|
from pathlib import Path
|
|
63
63
|
from typing import Any
|
|
64
64
|
|
|
@@ -318,7 +318,7 @@ def _build_metrics_table(metrics: dict[str, Any]) -> str:
|
|
|
318
318
|
|
|
319
319
|
def _build_changelog_block(version: str, log_lines: list[str]) -> str:
|
|
320
320
|
"""Generate a CHANGELOG section for the given version."""
|
|
321
|
-
today = datetime.now(
|
|
321
|
+
today = datetime.now(timezone.utc).strftime("%Y-%m-%d")
|
|
322
322
|
items = "\n".join(f"- {line}" for line in log_lines[:20]) if log_lines else "- (see git log)"
|
|
323
323
|
return (
|
|
324
324
|
f"## v{version} — {today}\n\n"
|
|
@@ -90,18 +90,40 @@ def enrich_response(
|
|
|
90
90
|
*,
|
|
91
91
|
scope: dict[str, Any] | None = None,
|
|
92
92
|
summary: str = "",
|
|
93
|
+
project_root: Any = None,
|
|
94
|
+
tool: str = "",
|
|
93
95
|
) -> dict[str, Any]:
|
|
94
96
|
"""Return ``report`` with ``scope`` and ``summary`` injected.
|
|
95
97
|
|
|
96
98
|
Existing keys are not modified. If the report already carries a
|
|
97
99
|
``scope`` or ``summary`` from upstream, the new values overwrite
|
|
98
100
|
(callers control the order).
|
|
101
|
+
|
|
102
|
+
When ``project_root`` and ``tool`` are provided AND the supplied
|
|
103
|
+
``scope.tokens_saved_estimate`` is positive, this also appends an
|
|
104
|
+
entry to the project's lifetime-savings ledger so every verb
|
|
105
|
+
contributes to the boastable total. Best-effort: a ledger write
|
|
106
|
+
failure never affects the returned report.
|
|
99
107
|
"""
|
|
100
108
|
out = dict(report)
|
|
101
109
|
if scope is not None:
|
|
102
110
|
out["scope"] = scope
|
|
103
111
|
if summary:
|
|
104
112
|
out["summary"] = summary
|
|
113
|
+
if project_root is not None and tool:
|
|
114
|
+
try:
|
|
115
|
+
est = int((scope or {}).get("tokens_saved_estimate") or 0)
|
|
116
|
+
except (TypeError, ValueError):
|
|
117
|
+
est = 0
|
|
118
|
+
if est > 0:
|
|
119
|
+
try:
|
|
120
|
+
from pathlib import Path as _P
|
|
121
|
+
|
|
122
|
+
from .lifetime_savings import append_savings as _append
|
|
123
|
+
_append(project_root=_P(str(project_root)),
|
|
124
|
+
tool=tool, tokens_saved=est)
|
|
125
|
+
except Exception: # pragma: no cover - never break tool response
|
|
126
|
+
pass
|
|
105
127
|
return out
|
|
106
128
|
|
|
107
129
|
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"""Tier a3 — Recipe Replayer: deterministic execution of golden recipes.
|
|
2
|
+
|
|
3
|
+
Each ``GoldenRecipe`` carries a ``validation_gate`` list of shell
|
|
4
|
+
commands that an LLM agent would otherwise reason about and run one
|
|
5
|
+
at a time. The replayer just runs them — no LLM round-trip per step
|
|
6
|
+
— and reports per-step verdict + token savings.
|
|
7
|
+
|
|
8
|
+
Token savings basis: each command an LLM would have planned + dispatched
|
|
9
|
+
costs ~80 tokens of round-trip overhead (read prior result, decide next
|
|
10
|
+
step, emit tool call). Replaying N commands deterministically avoids
|
|
11
|
+
N × 80 tokens.
|
|
12
|
+
"""
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import subprocess
|
|
16
|
+
import time
|
|
17
|
+
from dataclasses import asdict, dataclass
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
from typing import Any
|
|
20
|
+
|
|
21
|
+
from ..a1_at_functions.lifetime_savings import append_savings
|
|
22
|
+
from ..a1_at_functions.recipes import get_recipe
|
|
23
|
+
|
|
24
|
+
SCHEMA_VERSION_REPLAY_V1 = "atomadic-forge.replay/v1"
|
|
25
|
+
TOKENS_PER_LLM_DISPATCH = 80
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@dataclass
|
|
29
|
+
class StepResult:
|
|
30
|
+
command: str
|
|
31
|
+
exit_code: int
|
|
32
|
+
duration_ms: int
|
|
33
|
+
stdout_tail: str
|
|
34
|
+
stderr_tail: str
|
|
35
|
+
skipped: bool = False
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@dataclass
|
|
39
|
+
class ReplayReport:
|
|
40
|
+
schema_version: str
|
|
41
|
+
recipe_name: str
|
|
42
|
+
project_root: str
|
|
43
|
+
steps: list[StepResult]
|
|
44
|
+
verdict: str # PASS | FAIL | PARTIAL
|
|
45
|
+
pass_count: int
|
|
46
|
+
fail_count: int
|
|
47
|
+
skipped_count: int
|
|
48
|
+
duration_ms: int
|
|
49
|
+
tokens_saved_estimate: int
|
|
50
|
+
|
|
51
|
+
def to_dict(self) -> dict[str, Any]:
|
|
52
|
+
return {**asdict(self),
|
|
53
|
+
"steps": [asdict(s) for s in self.steps]}
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _tail(text: str, lines: int = 10) -> str:
|
|
57
|
+
if not text:
|
|
58
|
+
return ""
|
|
59
|
+
return "\n".join(text.splitlines()[-lines:])
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def replay_recipe(
|
|
63
|
+
*,
|
|
64
|
+
recipe_name: str,
|
|
65
|
+
project_root: Path,
|
|
66
|
+
stop_on_fail: bool = True,
|
|
67
|
+
dry_run: bool = False,
|
|
68
|
+
) -> ReplayReport:
|
|
69
|
+
"""Replay a golden recipe's ``validation_gate`` deterministically.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
recipe_name: name from :func:`recipes.list_recipes`.
|
|
73
|
+
project_root: cwd for the subprocesses.
|
|
74
|
+
stop_on_fail: when True, remaining steps are marked skipped on
|
|
75
|
+
the first non-zero exit. When False, every step runs and
|
|
76
|
+
failures accumulate.
|
|
77
|
+
dry_run: print the plan, mark all steps skipped, don't shell out.
|
|
78
|
+
|
|
79
|
+
Raises:
|
|
80
|
+
KeyError: when ``recipe_name`` is not in the catalogue.
|
|
81
|
+
"""
|
|
82
|
+
recipe = get_recipe(recipe_name)
|
|
83
|
+
if recipe is None:
|
|
84
|
+
raise KeyError(f"unknown recipe: {recipe_name!r}")
|
|
85
|
+
|
|
86
|
+
commands = list(recipe.get("validation_gate") or [])
|
|
87
|
+
project_root = Path(project_root).resolve()
|
|
88
|
+
|
|
89
|
+
t0 = time.monotonic()
|
|
90
|
+
steps: list[StepResult] = []
|
|
91
|
+
failed = False
|
|
92
|
+
for cmd in commands:
|
|
93
|
+
if dry_run or (failed and stop_on_fail):
|
|
94
|
+
steps.append(StepResult(
|
|
95
|
+
command=cmd, exit_code=-1, duration_ms=0,
|
|
96
|
+
stdout_tail="", stderr_tail="", skipped=True,
|
|
97
|
+
))
|
|
98
|
+
continue
|
|
99
|
+
s_t0 = time.monotonic()
|
|
100
|
+
try:
|
|
101
|
+
proc = subprocess.run( # noqa: S602
|
|
102
|
+
cmd, cwd=project_root, shell=True,
|
|
103
|
+
capture_output=True, text=True, timeout=600,
|
|
104
|
+
)
|
|
105
|
+
steps.append(StepResult(
|
|
106
|
+
command=cmd,
|
|
107
|
+
exit_code=proc.returncode,
|
|
108
|
+
duration_ms=int((time.monotonic() - s_t0) * 1000),
|
|
109
|
+
stdout_tail=_tail(proc.stdout),
|
|
110
|
+
stderr_tail=_tail(proc.stderr),
|
|
111
|
+
))
|
|
112
|
+
if proc.returncode != 0:
|
|
113
|
+
failed = True
|
|
114
|
+
except (OSError, subprocess.TimeoutExpired) as exc:
|
|
115
|
+
steps.append(StepResult(
|
|
116
|
+
command=cmd, exit_code=-2,
|
|
117
|
+
duration_ms=int((time.monotonic() - s_t0) * 1000),
|
|
118
|
+
stdout_tail="", stderr_tail=str(exc),
|
|
119
|
+
))
|
|
120
|
+
failed = True
|
|
121
|
+
|
|
122
|
+
pass_count = sum(1 for s in steps
|
|
123
|
+
if not s.skipped and s.exit_code == 0)
|
|
124
|
+
fail_count = sum(1 for s in steps
|
|
125
|
+
if not s.skipped and s.exit_code != 0)
|
|
126
|
+
skipped_count = sum(1 for s in steps if s.skipped)
|
|
127
|
+
|
|
128
|
+
if dry_run:
|
|
129
|
+
verdict = "DRY_RUN"
|
|
130
|
+
elif fail_count == 0 and pass_count > 0:
|
|
131
|
+
verdict = "PASS"
|
|
132
|
+
elif fail_count > 0 and pass_count > 0:
|
|
133
|
+
verdict = "PARTIAL"
|
|
134
|
+
else:
|
|
135
|
+
verdict = "FAIL"
|
|
136
|
+
|
|
137
|
+
# Token-savings: every non-skipped command avoided one LLM dispatch.
|
|
138
|
+
tokens_saved = (pass_count + fail_count) * TOKENS_PER_LLM_DISPATCH
|
|
139
|
+
|
|
140
|
+
if tokens_saved > 0 and not dry_run:
|
|
141
|
+
append_savings(
|
|
142
|
+
project_root=project_root,
|
|
143
|
+
tool=f"replay/{recipe_name}",
|
|
144
|
+
tokens_saved=tokens_saved,
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
return ReplayReport(
|
|
148
|
+
schema_version=SCHEMA_VERSION_REPLAY_V1,
|
|
149
|
+
recipe_name=recipe_name,
|
|
150
|
+
project_root=str(project_root),
|
|
151
|
+
steps=steps,
|
|
152
|
+
verdict=verdict,
|
|
153
|
+
pass_count=pass_count,
|
|
154
|
+
fail_count=fail_count,
|
|
155
|
+
skipped_count=skipped_count,
|
|
156
|
+
duration_ms=int((time.monotonic() - t0) * 1000),
|
|
157
|
+
tokens_saved_estimate=tokens_saved,
|
|
158
|
+
)
|
{atomadic_forge-0.77.0 → atomadic_forge-0.79.0}/src/atomadic_forge/a4_sy_orchestration/cli.py
RENAMED
|
@@ -2734,6 +2734,16 @@ def _register_specialty_apps() -> None:
|
|
|
2734
2734
|
("atomadic_forge.commands.graft", "graft",
|
|
2735
2735
|
"Pull one symbol from a source file into the target's tier "
|
|
2736
2736
|
"surface and optionally auto-wire CLI + MCP."),
|
|
2737
|
+
# v0.78.0 — token-savings: lifetime ledger of LLM round-trips
|
|
2738
|
+
# spared. Every enriched verb appends to .atomadic-forge/
|
|
2739
|
+
# lifetime_savings.jsonl automatically.
|
|
2740
|
+
("atomadic_forge.commands.token_savings", "token-savings",
|
|
2741
|
+
"Show the project's lifetime token-savings ledger."),
|
|
2742
|
+
# v0.79.0 — replay: deterministic golden-recipe execution.
|
|
2743
|
+
# Skips the LLM round-trip per step that an agent would
|
|
2744
|
+
# otherwise spend planning + dispatching each command.
|
|
2745
|
+
("atomadic_forge.commands.replay", "replay",
|
|
2746
|
+
"Replay a golden recipe's validation_gate deterministically."),
|
|
2737
2747
|
("atomadic_forge.commands.emergent_swarm", "emergent-swarm",
|
|
2738
2748
|
"Round-5: cross-repo emergent composition discovery."),
|
|
2739
2749
|
("atomadic_forge.commands.emergent_swarm", "emergent_swarm",
|
|
@@ -32,19 +32,14 @@ from atomadic_forge.a2_mo_composites.repo_public_surface_sync import (
|
|
|
32
32
|
from atomadic_forge.a3_og_features.forge_metrics_feature import emit_forge_metrics
|
|
33
33
|
|
|
34
34
|
|
|
35
|
-
def _live_cli_verb_count() -> int:
|
|
36
|
-
"""
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
"""
|
|
41
|
-
try:
|
|
42
|
-
from atomadic_forge.a4_sy_orchestration import cli as _cli
|
|
43
|
-
commands = getattr(_cli.app, "registered_commands", []) or []
|
|
44
|
-
groups = getattr(_cli.app, "registered_groups", []) or []
|
|
45
|
-
return len(commands) + len(groups)
|
|
46
|
-
except Exception:
|
|
35
|
+
def _live_cli_verb_count(project_root: Path = Path(".")) -> int:
|
|
36
|
+
"""Count CLI verbs by scanning cli.py for @app.command( decorators."""
|
|
37
|
+
import re
|
|
38
|
+
cli_path = project_root / "src" / "atomadic_forge" / "a4_sy_orchestration" / "cli.py"
|
|
39
|
+
if not cli_path.exists():
|
|
47
40
|
return 0
|
|
41
|
+
text = cli_path.read_text(encoding="utf-8", errors="replace")
|
|
42
|
+
return len(re.findall(r'@\w+\.command\(', text))
|
|
48
43
|
|
|
49
44
|
COMMAND_NAME = "metrics"
|
|
50
45
|
COMMAND_HELP = (
|
|
@@ -95,7 +90,7 @@ def run(
|
|
|
95
90
|
apply=apply,
|
|
96
91
|
proof_corpus_root=mhed,
|
|
97
92
|
skip_self_cert=not self_cert,
|
|
98
|
-
cli_verbs_count=_live_cli_verb_count(),
|
|
93
|
+
cli_verbs_count=_live_cli_verb_count(project),
|
|
99
94
|
tests_passing=tests_passing,
|
|
100
95
|
)
|
|
101
96
|
if json_out:
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"""Tier a4 — `forge replay` CLI surface.
|
|
2
|
+
|
|
3
|
+
Run a golden recipe's validation_gate deterministically — no LLM in
|
|
4
|
+
the loop. Each command an LLM would otherwise plan + dispatch costs
|
|
5
|
+
real round-trip tokens; replaying skips that overhead entirely.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import json
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Annotated
|
|
12
|
+
|
|
13
|
+
import typer
|
|
14
|
+
|
|
15
|
+
from atomadic_forge.a1_at_functions.recipes import list_recipes
|
|
16
|
+
from atomadic_forge.a3_og_features.recipe_replay import replay_recipe
|
|
17
|
+
|
|
18
|
+
COMMAND_NAME = "replay"
|
|
19
|
+
COMMAND_HELP = (
|
|
20
|
+
"Replay a golden recipe's validation_gate deterministically — zero "
|
|
21
|
+
"LLM round-trips. Use `--list` to see available recipes."
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
app = typer.Typer(no_args_is_help=False, help=COMMAND_HELP)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@app.callback(invoke_without_command=True)
|
|
28
|
+
def run(
|
|
29
|
+
recipe: Annotated[str, typer.Argument(
|
|
30
|
+
help="Recipe name (use --list to see all).")] = "",
|
|
31
|
+
project: Annotated[Path, typer.Option(
|
|
32
|
+
"--project", "-p",
|
|
33
|
+
help="Project root used as cwd for each step.",
|
|
34
|
+
exists=True, file_okay=False, dir_okay=True,
|
|
35
|
+
resolve_path=True)] = Path("."),
|
|
36
|
+
list_all: Annotated[bool, typer.Option(
|
|
37
|
+
"--list", help="List available recipes and exit.")] = False,
|
|
38
|
+
dry_run: Annotated[bool, typer.Option(
|
|
39
|
+
"--dry-run", help="Print the plan without running.")] = False,
|
|
40
|
+
keep_going: Annotated[bool, typer.Option(
|
|
41
|
+
"--keep-going",
|
|
42
|
+
help="Run every step even if one fails (default: stop on first fail).",
|
|
43
|
+
)] = False,
|
|
44
|
+
json_out: Annotated[bool, typer.Option(
|
|
45
|
+
"--json", help="Emit machine-readable JSON.")] = False,
|
|
46
|
+
) -> None:
|
|
47
|
+
"""Replay a recipe's validation_gate."""
|
|
48
|
+
if list_all:
|
|
49
|
+
names = list_recipes()
|
|
50
|
+
if json_out:
|
|
51
|
+
typer.echo(json.dumps({"recipes": names}, indent=2))
|
|
52
|
+
return
|
|
53
|
+
typer.echo("Available recipes:")
|
|
54
|
+
for n in names:
|
|
55
|
+
typer.echo(f" • {n}")
|
|
56
|
+
return
|
|
57
|
+
|
|
58
|
+
if not recipe:
|
|
59
|
+
typer.secho("forge replay: pass a recipe name or --list", fg="red", err=True)
|
|
60
|
+
raise typer.Exit(2)
|
|
61
|
+
|
|
62
|
+
try:
|
|
63
|
+
report = replay_recipe(
|
|
64
|
+
recipe_name=recipe,
|
|
65
|
+
project_root=project,
|
|
66
|
+
stop_on_fail=not keep_going,
|
|
67
|
+
dry_run=dry_run,
|
|
68
|
+
)
|
|
69
|
+
except KeyError as exc:
|
|
70
|
+
typer.secho(f"forge replay: {exc}", fg="red", err=True)
|
|
71
|
+
raise typer.Exit(2) from exc
|
|
72
|
+
|
|
73
|
+
if json_out:
|
|
74
|
+
typer.echo(json.dumps(report.to_dict(), indent=2, default=str))
|
|
75
|
+
if report.verdict in ("FAIL", "PARTIAL"):
|
|
76
|
+
raise typer.Exit(1)
|
|
77
|
+
return
|
|
78
|
+
|
|
79
|
+
typer.echo("")
|
|
80
|
+
typer.echo(f"Replay — {recipe}")
|
|
81
|
+
typer.echo("-" * 60)
|
|
82
|
+
for i, step in enumerate(report.steps, 1):
|
|
83
|
+
if step.skipped:
|
|
84
|
+
mark = typer.style("SKIP", fg="yellow")
|
|
85
|
+
elif step.exit_code == 0:
|
|
86
|
+
mark = typer.style("PASS", fg="green")
|
|
87
|
+
else:
|
|
88
|
+
mark = typer.style("FAIL", fg="red")
|
|
89
|
+
typer.echo(f" [{i}] {mark} {step.command}")
|
|
90
|
+
if step.exit_code not in (0, -1) and step.stderr_tail:
|
|
91
|
+
for line in step.stderr_tail.splitlines()[:3]:
|
|
92
|
+
typer.echo(f" {line}")
|
|
93
|
+
typer.echo("-" * 60)
|
|
94
|
+
typer.echo(f" verdict: {report.verdict}")
|
|
95
|
+
typer.echo(f" pass / fail: {report.pass_count} / {report.fail_count}"
|
|
96
|
+
+ (f" ({report.skipped_count} skipped)"
|
|
97
|
+
if report.skipped_count else ""))
|
|
98
|
+
typer.echo(f" duration: {report.duration_ms} ms")
|
|
99
|
+
typer.echo(f" tokens saved: ~{report.tokens_saved_estimate:,}")
|
|
100
|
+
if report.verdict in ("FAIL", "PARTIAL"):
|
|
101
|
+
raise typer.Exit(1)
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"""Tier a4 — `forge token-savings` CLI surface.
|
|
2
|
+
|
|
3
|
+
Display the lifetime token-savings ledger for a project. Every Forge
|
|
4
|
+
verb that reports a ``scope.tokens_saved_estimate`` automatically
|
|
5
|
+
appends to this ledger via ``response_enricher.enrich_response``, so
|
|
6
|
+
the running total is the cumulative LLM round-trip cost the Forge has
|
|
7
|
+
spared the caller — boastable, verifiable, file-backed.
|
|
8
|
+
|
|
9
|
+
The ledger lives at ``<project>/.atomadic-forge/lifetime_savings.jsonl``.
|
|
10
|
+
One JSON object per line, append-only. Read it directly to audit.
|
|
11
|
+
"""
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import json
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
from typing import Annotated
|
|
17
|
+
|
|
18
|
+
import typer
|
|
19
|
+
|
|
20
|
+
from atomadic_forge.a1_at_functions.lifetime_savings import (
|
|
21
|
+
read_savings_summary,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
COMMAND_NAME = "token-savings"
|
|
25
|
+
COMMAND_HELP = (
|
|
26
|
+
"Show the project's lifetime token-savings ledger — the cumulative "
|
|
27
|
+
"LLM round-trips the Forge has spared, broken down by tool."
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
app = typer.Typer(no_args_is_help=False, help=COMMAND_HELP)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@app.callback(invoke_without_command=True)
|
|
34
|
+
def run(
|
|
35
|
+
project: Annotated[Path, typer.Option(
|
|
36
|
+
"--project", "-p",
|
|
37
|
+
help="Project root (must contain .atomadic-forge/).",
|
|
38
|
+
exists=True, file_okay=False, dir_okay=True, resolve_path=True)] = (
|
|
39
|
+
Path(".")),
|
|
40
|
+
json_out: Annotated[bool, typer.Option(
|
|
41
|
+
"--json", help="Emit machine-readable JSON.")] = False,
|
|
42
|
+
) -> None:
|
|
43
|
+
"""Show lifetime token-savings for the project."""
|
|
44
|
+
summary = read_savings_summary(project_root=project)
|
|
45
|
+
|
|
46
|
+
if json_out:
|
|
47
|
+
typer.echo(json.dumps(summary, indent=2, default=str))
|
|
48
|
+
return
|
|
49
|
+
|
|
50
|
+
typer.echo("")
|
|
51
|
+
typer.echo("Forge — lifetime token-savings ledger")
|
|
52
|
+
typer.echo("-" * 60)
|
|
53
|
+
typer.echo(f" project: {project}")
|
|
54
|
+
typer.echo(f" ledger: {summary['ledger_file']}")
|
|
55
|
+
if not summary["ledger_present"]:
|
|
56
|
+
typer.secho(" (no ledger yet — run any verb to start logging)",
|
|
57
|
+
fg="yellow")
|
|
58
|
+
return
|
|
59
|
+
total = int(summary["tokens_saved_lifetime"])
|
|
60
|
+
typer.echo(f" entries: {summary['entry_count']}")
|
|
61
|
+
typer.echo(f" tokens saved: {total:,}")
|
|
62
|
+
typer.echo(f" first seen: {summary['first_seen_at']}")
|
|
63
|
+
typer.echo(f" last seen: {summary['last_seen_at']}")
|
|
64
|
+
by_tool = summary.get("by_tool") or {}
|
|
65
|
+
if by_tool:
|
|
66
|
+
typer.echo("")
|
|
67
|
+
typer.echo(" by tool:")
|
|
68
|
+
for tool, n in sorted(by_tool.items(), key=lambda kv: -kv[1]):
|
|
69
|
+
pct = (100.0 * n / total) if total else 0.0
|
|
70
|
+
typer.echo(f" {tool:<14} {n:>10,} ({pct:5.1f}%)")
|