roam-code 12.17__tar.gz → 12.18__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.
- {roam_code-12.17/src/roam_code.egg-info → roam_code-12.18}/PKG-INFO +13 -8
- {roam_code-12.17 → roam_code-12.18}/README.md +12 -7
- {roam_code-12.17 → roam_code-12.18}/pyproject.toml +1 -1
- {roam_code-12.17 → roam_code-12.18}/src/roam/cli.py +10 -0
- roam_code-12.18/src/roam/commands/cmd_disambiguate.py +98 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_map.py +46 -1
- roam_code-12.18/src/roam/commands/cmd_mcp_status.py +89 -0
- roam_code-12.18/src/roam/commands/cmd_pre_commit.py +120 -0
- roam_code-12.18/src/roam/commands/cmd_recipes.py +53 -0
- roam_code-12.18/src/roam/commands/cmd_test_impact.py +145 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/competitor_site_data.py +2 -2
- {roam_code-12.17 → roam_code-12.18}/src/roam/config.py +21 -2
- {roam_code-12.17 → roam_code-12.18}/src/roam/mcp-server-card.json +1 -1
- {roam_code-12.17 → roam_code-12.18}/src/roam/mcp_server.py +37 -0
- {roam_code-12.17 → roam_code-12.18/src/roam_code.egg-info}/PKG-INFO +13 -8
- {roam_code-12.17 → roam_code-12.18}/src/roam_code.egg-info/SOURCES.txt +6 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_mcp_server.py +6 -4
- roam_code-12.18/tests/test_v1218_passes_81_90.py +118 -0
- {roam_code-12.17 → roam_code-12.18}/LICENSE +0 -0
- {roam_code-12.17 → roam_code-12.18}/setup.cfg +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/__init__.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/__main__.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/analysis/__init__.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/analysis/effects.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/analysis/taint.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/api.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/ask/__init__.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/ask/classifier.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/ask/recipes.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/ask/runner.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/ask/workflow.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/attest/__init__.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/attest/cga.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/bridges/__init__.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/bridges/base.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/bridges/bridge_config.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/bridges/bridge_django.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/bridges/bridge_protobuf.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/bridges/bridge_rest_api.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/bridges/bridge_salesforce.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/bridges/bridge_template.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/bridges/registry.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/catalog/__init__.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/catalog/detectors.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/catalog/fixes.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/catalog/python_idioms.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/catalog/smells.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/catalog/tasks.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/__init__.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/changed_files.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_adrs.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_adversarial.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_affected.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_affected_tests.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_agent_context.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_agent_export.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_agent_plan.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_ai_ratio.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_ai_readiness.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_alerts.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_annotate.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_api.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_api_changes.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_api_drift.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_ask.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_attest.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_auth_gaps.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_bisect.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_breaking.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_budget.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_bus_factor.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_capsule.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_cga.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_changelog.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_check_rules.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_ci_setup.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_clean.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_clones.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_closure.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_clusters.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_codeowners.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_complexity.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_config.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_congestion.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_context.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_conventions.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_coupling.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_coverage_gaps.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_critique.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_cut.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_dark_matter.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_dashboard.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_dead.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_debt.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_deps.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_describe.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_dev_profile.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_diagnose.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_diff.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_doc_staleness.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_docs_coverage.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_doctor.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_drift.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_duplicates.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_effects.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_endpoints.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_entry_points.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_eval_retrieve.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_exit_codes.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_fan.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_file.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_fingerprint.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_fitness.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_flag_dead.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_fleet.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_fn_coupling.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_forecast.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_graph_export.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_graph_stats.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_grep.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_guard.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_health.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_help_search.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_hooks.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_hotspots.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_hover.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_impact.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_index.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_index_bundle.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_index_stats.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_ingest_trace.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_init.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_intent.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_invariants.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_layers.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_math.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_mcp_setup.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_metrics.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_migration_safety.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_minimap.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_missing_index.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_module.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_mutate.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_n1.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_oracle.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_orchestrate.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_orphan_imports.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_orphan_routes.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_over_fetch.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_owner.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_partition.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_path_coverage.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_patterns.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_plan.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_plan_refactor.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_plugins.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_pr_diff.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_pr_prep.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_pr_risk.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_preflight.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_py_modern.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_py_types.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_pytest_fixtures.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_recommend.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_relate.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_report.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_reset.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_retrieve.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_risk.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_rules.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_safe_delete.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_safe_zones.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_sbom.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_schema.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_search.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_search_semantic.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_secrets.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_semantic_diff.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_simulate.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_simulate_departure.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_sketch.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_smells.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_spectral.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_split.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_stats.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_suggest_refactoring.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_suggest_reviewers.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_supply_chain.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_symbol.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_syntax_check.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_taint.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_telemetry.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_test_gaps.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_test_pyramid.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_test_scaffold.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_testmap.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_timeline.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_tour.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_trace.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_trends.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_triage.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_understand.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_uses.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_verify.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_verify_imports.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_version.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_vibe_check.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_visualize.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_vuln_map.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_vuln_reach.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_vulns.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_watch.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_weather.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_why.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_why_fail.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_workflow.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_ws.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/cmd_xlang.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/codeowners_helpers.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/context_helpers.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/gate_presets.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/graph_helpers.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/metrics_history.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/next_steps.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/resolve.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/commands/suppression.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/coverage_reports.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/critique/__init__.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/critique/aggregator.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/critique/checks.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/db/__init__.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/db/connection.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/db/queries.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/db/schema.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/eval/__init__.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/eval/harness.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/exit_codes.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/fleet/__init__.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/fleet/adapters.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/fleet/manifest.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/git_utils.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/graph/__init__.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/graph/anomaly.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/graph/builder.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/graph/clone_detect.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/graph/clusters.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/graph/cycles.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/graph/dark_matter.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/graph/diff.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/graph/fingerprint.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/graph/layers.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/graph/pagerank.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/graph/partition.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/graph/pathfinding.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/graph/propagation.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/graph/simulate.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/graph/spectral.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/graph/stats.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/index/__init__.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/index/complexity.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/index/discovery.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/index/django_post.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/index/file_roles.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/index/git_stats.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/index/gitignore.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/index/incremental.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/index/indexer.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/index/parser.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/index/pytest_fixtures.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/index/registry_dispatch.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/index/relations.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/index/symbols.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/index/test_conventions.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/languages/__init__.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/languages/apex_lang.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/languages/aura_lang.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/languages/base.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/languages/c_lang.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/languages/csharp_lang.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/languages/extractor_schema.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/languages/extractors/kotlin.yaml +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/languages/foxpro_lang.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/languages/generic_lang.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/languages/go_lang.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/languages/hcl_lang.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/languages/java_lang.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/languages/javascript_lang.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/languages/kotlin_lang.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/languages/php_lang.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/languages/python_lang.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/languages/query_engine.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/languages/registry.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/languages/ruby_lang.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/languages/rust_lang.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/languages/scala_lang.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/languages/sfxml_lang.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/languages/sql_lang.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/languages/swift_lang.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/languages/typescript_lang.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/languages/visualforce_lang.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/languages/yaml_lang.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/mcp_extras/__init__.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/mcp_extras/completions.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/mcp_extras/concurrency.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/mcp_extras/progress.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/mcp_extras/sampling.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/mcp_extras/session.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/mcp_extras/watcher.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/output/__init__.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/output/confidence.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/output/errors.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/output/file_role_hints.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/output/formatter.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/output/framework_filter.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/output/mermaid.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/output/project_shape.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/output/sarif.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/output/schema_registry.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/plugins.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/refactor/__init__.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/refactor/codegen.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/refactor/transforms.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/retrieve/__init__.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/retrieve/learned_ranker.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/retrieve/pipeline.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/retrieve/rerank.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/retrieve/seeds.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/retrieve/semantic.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/rules/__init__.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/rules/ast_match.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/rules/builtin.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/rules/dataflow.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/rules/engine.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/runtime/__init__.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/runtime/daemon.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/runtime/graph_backend.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/runtime/hotspots.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/runtime/lock_modes.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/runtime/lockmgr.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/runtime/trace_ingest.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/search/__init__.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/search/framework_packs.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/search/index_embeddings.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/search/onnx_embeddings.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/search/tfidf.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/security/__init__.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/security/aibom_extension.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/security/taint_classifier.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/security/taint_engine.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/security/taint_rules/api_error_leak.yaml +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/security/taint_rules/java_fileupload_path_traversal.yaml +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/security/taint_rules/js_insecure_jwt_decode.yaml +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/security/taint_rules/js_localstorage_secrets.yaml +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/security/taint_rules/js_prototype_pollution.yaml +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/security/taint_rules/js_ssrf.yaml +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/security/taint_rules/js_xss.yaml +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/security/taint_rules/python_basic.yaml +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/security/taint_rules/python_deserialization.yaml +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/security/taint_rules/python_path_traversal.yaml +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/security/taint_rules/python_socketio_remote_source.yaml +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/security/taint_rules/python_sqli.yaml +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/security/taint_rules/python_urllib_open_redirect.yaml +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/security/taint_rules/vue_v_html.yaml +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/security/vuln_reach.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/security/vuln_store.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/surface_counts.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/telemetry.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/templates/__init__.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/templates/ci/Jenkinsfile +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/templates/ci/__init__.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/templates/ci/azure-pipelines.yml +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/templates/ci/bitbucket-pipelines.yml +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/templates/ci/gitlab-ci.yml +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/workspace/__init__.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/workspace/aggregator.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/workspace/api_scanner.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/workspace/config.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam/workspace/db.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam_code.egg-info/dependency_links.txt +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam_code.egg-info/entry_points.txt +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam_code.egg-info/requires.txt +0 -0
- {roam_code-12.17 → roam_code-12.18}/src/roam_code.egg-info/top_level.txt +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_adrs.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_adversarial.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_affected.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_agent_export.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_agent_mode.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_agent_plan_context.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_ai_ratio.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_ai_readiness.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_alerts_cmd.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_annotations.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_anomaly.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_api_changes.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_api_drift.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_ask.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_attest.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_auth_gaps.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_backend_fixes_round2.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_backend_fixes_round3.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_basic.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_batch_mcp.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_bisect.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_bridge_django.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_bridges.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_bridges_extended.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_budget.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_budget_flag.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_budget_phase2.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_bus_factor.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_capsule.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_cga.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_check_rules.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_ci_gate_eval.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_ci_sarif_guard.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_ci_setup.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_clones.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_closure.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_codeowners.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_commands_architecture.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_commands_exploration.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_commands_health.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_commands_refactoring.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_commands_workflow.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_competitor_site_data.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_comprehensive.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_config.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_congestion.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_context_propagation.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_conventions_cmd.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_coverage_gaps_cmd.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_coverage_ingestion.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_critique.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_cut.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_dark_matter.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_dark_matter_helpers.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_dashboard.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_dataflow_dead.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_dead_aging.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_defer_loading.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_demo_gif_asset.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_describe.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_detail_flag_hints.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_detector_precision.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_deterministic_output.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_dev_profile.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_difficulty_scoring.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_doc_consistency.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_doc_staleness.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_docker_assets.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_docs_coverage.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_docs_site_quality.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_doctor.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_drift.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_drift_by_team.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_duplicates.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_effects.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_effects_propagation.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_endpoints.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_entry_points_cmd.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_eval_retrieve.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_except_pass_narrow.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_exclude_patterns.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_exit_codes.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_extractor_grammar_drift.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_fallback_contracts.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_file_roles.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_fingerprint.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_fixes.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_flag_dead.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_fleet.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_fn_coupling.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_forecast.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_formatters.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_foxpro.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_framework_detection.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_gate_presets.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_git_utils.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_guard.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_health_gate.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_hooks.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_hotspots.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_hover.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_index.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_index_bundle.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_init_cmd.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_install_check.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_intent.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_invariants.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_json_contracts.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_json_error_envelope.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_kotlin_swift_extractors.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_language_corpus.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_languages.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_library_api.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_math.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_math_tips.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_mcp_extras.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_mcp_setup.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_mermaid.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_metrics_cmd.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_migration_safety.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_minimap.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_missing_index.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_mutate.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_n1.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_next_steps.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_onboard.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_oracle.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_orchestrate.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_orphan_routes.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_oss_bench_harness.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_over_fetch.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_pagerank_truncation.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_partition.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_path_coverage.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_patterns_cmd.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_performance.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_personalized_pagerank.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_plan.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_plugin_discovery.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_pr_comment_script.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_pr_diff.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_pr_risk_author.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_progress.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_progressive_disclosure.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_properties.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_pytest_fixtures.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_python_extractor_v2.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_python_idioms_e2e.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_python_pivot.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_readme_surface_consistency.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_realworld_feedback.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_refactoring_intelligence.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_registry_dispatch.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_relate.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_report.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_reset_clean.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_resolve.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_retrieve.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_retrieve_cross_repo.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_retrieve_seeds.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_risk.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_ruby.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_rule_profiles.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_rules.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_rules_ast_match.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_rules_community_pack.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_rules_dataflow.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_rules_symbol_requirements.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_runtime.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_runtime_score.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_salesforce.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_sarif_flag.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_sbom.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_scala.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_schema_versioning.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_search_explain.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_secrets.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_secrets_v2.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_semantic_diff.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_semantic_onnx.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_semantic_search.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_simulate.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_simulate_departure.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_sketch.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_smells.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_smoke.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_sna_metrics.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_spectral.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_split_cmd.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_sql.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_suggest_reviewers.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_supply_chain.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_surface_counts.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_syntax_check.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_taint.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_taint_analysis.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_taint_classifier.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_taint_intraprocedural.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_test_conventions.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_test_gaps.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_test_scaffold.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_testmap.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_top_flag_consistency.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_tour_cmd.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_trends.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_trends_cohort.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_triage.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_uses_cmd.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_v1215_passes.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_v1216_passes.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_v1216_passes_41_50.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_v1216_passes_51_60.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_v1217_passes_61_80.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_v12_2.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_v6_features.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_v71_features.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_v7_features.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_v82_features.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_verify.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_verify_imports.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_vibe_check.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_visualize.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_vuln.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_vulns_cmd.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_watch.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_why.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_workspace.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_ws_resolve_fixes.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_xlang.py +0 -0
- {roam_code-12.17 → roam_code-12.18}/tests/test_yaml_hcl.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: roam-code
|
|
3
|
-
Version: 12.
|
|
3
|
+
Version: 12.18
|
|
4
4
|
Summary: Instant codebase comprehension for AI coding agents
|
|
5
5
|
Author: CosmoHac
|
|
6
6
|
License-Expression: MIT
|
|
@@ -62,9 +62,9 @@ Dynamic: license-file
|
|
|
62
62
|
|
|
63
63
|
**Architectural sight for AI coding agents — before they edit.**
|
|
64
64
|
|
|
65
|
-
A local code graph (SQLite + tree-sitter + git history) that gives any agent — Claude Code, Cursor, Aider, Continue, your own — five high-leverage verbs: `understand`, `retrieve`, `context`, `preflight`, `critique`. The other
|
|
65
|
+
A local code graph (SQLite + tree-sitter + git history) that gives any agent — Claude Code, Cursor, Aider, Continue, your own — five high-leverage verbs: `understand`, `retrieve`, `context`, `preflight`, `critique`. The other 172 specialised commands are advanced surface for specialised workflows.
|
|
66
66
|
|
|
67
|
-
*
|
|
67
|
+
*177 commands · 123 MCP tools · 27 languages · 100% local · zero API keys*
|
|
68
68
|
|
|
69
69
|
[](https://pypi.org/project/roam-code/)
|
|
70
70
|
[](https://github.com/Cranot/roam-code/stargazers)
|
|
@@ -83,7 +83,7 @@ Roam is a structural intelligence engine for software. It pre-indexes your codeb
|
|
|
83
83
|
Unlike LSPs (editor-bound, language-specific) or Sourcegraph (hosted search), Roam provides architecture-level graph queries -- offline, cross-language, and compact. It goes beyond comprehension: Roam governs architecture through budget gates, simulates refactoring outcomes, orchestrates multi-agent swarms with zero-conflict guarantees, maps vulnerability reachability paths, and enables graph-level code editing without syntax errors.
|
|
84
84
|
|
|
85
85
|
```
|
|
86
|
-
Codebase ──> [Index] ──> Semantic Graph ──>
|
|
86
|
+
Codebase ──> [Index] ──> Semantic Graph ──> 177 Commands ──> AI Agent
|
|
87
87
|
│ │ │
|
|
88
88
|
tree-sitter symbols comprehend
|
|
89
89
|
27 languages + edges govern
|
|
@@ -156,7 +156,7 @@ $ roam diff # blast radius of uncommitted changes
|
|
|
156
156
|
- **`personalized_pagerank()`** in `graph/pagerank.py`: NetworkX `personalization=` wrapper with empty-seed fallback to global PR; biases ranking toward query-relevant nodes for the retrieve reranker.
|
|
157
157
|
- **`.roam/config.toml`** (new): zero-dep TOML loader (stdlib `tomllib` → `tomli` → in-tree subset parser). Tunable retrieve weights (`alpha`/`beta`/`gamma`/`delta`/`epsilon`), `tokens_per_line`, `lexical_baseline`, `first_stage_token_cap`, `default_budget`, `default_k`, `default_rerank`.
|
|
158
158
|
- **DX corrections from dogfood pass**: `roam --detail <cmd>` is the canonical group-level flag; misleading "use --detail" hints in 7 commands rewritten to point users at `roam --detail <cmd>`. `--top N` aliased on `complexity`/`algo`/`rules` (`--top 0` means unlimited on `rules`). `roam fingerprint` no longer refuses graphs ≥5,000 symbols (new soft-warn threshold 20k, hard cap 100k).
|
|
159
|
-
- **
|
|
159
|
+
- **177 CLI commands, 123 MCP tools** (`fleet`, `ask`, `workflow`, `cga`, `eval-retrieve` remain CLI-only; v12 exposes `roam_retrieve`, `roam_critique`, `roam_fleet_plan`, plus 5 v12.1 boolean oracles (`roam_oracle_*`), `roam_taint_classify`, `roam_pytest_fixtures`, and `roam_hover` as MCP tools). 35-tool `core` preset is the default for token-budget-conscious clients.
|
|
160
160
|
|
|
161
161
|
## What's New in v11
|
|
162
162
|
|
|
@@ -327,7 +327,7 @@ roam health
|
|
|
327
327
|
|
|
328
328
|
## Commands
|
|
329
329
|
|
|
330
|
-
**Lead with the 5 verbs.** The [5 core commands](#core-commands) cover ~80% of agent workflows: `understand`, `context`, `retrieve`, `preflight`, `critique`. The remaining
|
|
330
|
+
**Lead with the 5 verbs.** The [5 core commands](#core-commands) cover ~80% of agent workflows: `understand`, `context`, `retrieve`, `preflight`, `critique`. The remaining 172 commands are detail surface for specialised workflows (taint, fleet, cga, oracle, eval, …) — they're called by agents on demand, not memorised. This is intentional design; under the hood the canonical surface is **177 commands organised into 7 categories** (plus 6 aliases for muscle memory: `algo` → `math`, `weather` → `churn`, `digest` / `snapshot` / `trend` → `trends`, `onboard` → `understand`), but you don't need to know that to start.
|
|
331
331
|
|
|
332
332
|
<details>
|
|
333
333
|
<summary><strong>Full command reference</strong></summary>
|
|
@@ -375,6 +375,11 @@ roam health
|
|
|
375
375
|
| `roam api [--scope <dir>]` | List the public API surface (exported public symbols + signatures) |
|
|
376
376
|
| `roam exit-codes` | List every roam exit code with its meaning |
|
|
377
377
|
| `roam version [--check]` | Show installed version; with `--check` also queries PyPI for newer releases |
|
|
378
|
+
| `roam disambiguate <name>` | List every symbol matching the name with file/line/kind/signature/docstring snippet to pick the right one |
|
|
379
|
+
| `roam pre-commit [--install\|--print]` | Install or preview a roam-critique git pre-commit hook |
|
|
380
|
+
| `roam mcp-status` | MCP server health: preset, registered tools, backpressure limits, cache entries, watcher state |
|
|
381
|
+
| `roam test-impact [<range>]` | Tests transitively reachable from changed symbols (sharper scope than `affected-tests`) |
|
|
382
|
+
| `roam recipes` | List every `roam ask` recipe with intent + example queries (sugar over `ask --list`) |
|
|
378
383
|
|
|
379
384
|
### Daily Workflow
|
|
380
385
|
|
|
@@ -1628,7 +1633,7 @@ roam-code/
|
|
|
1628
1633
|
├── action.yml # Reusable GitHub Action
|
|
1629
1634
|
├── src/roam/
|
|
1630
1635
|
│ ├── __init__.py # Version (from pyproject.toml)
|
|
1631
|
-
│ ├── cli.py # Click CLI (
|
|
1636
|
+
│ ├── cli.py # Click CLI (177 canonical + 7 aliases)
|
|
1632
1637
|
│ ├── mcp_server.py # MCP server (122 tools, 10 resources, 5 prompts)
|
|
1633
1638
|
│ ├── db/
|
|
1634
1639
|
│ │ ├── connection.py # SQLite (WAL, pragmas, batched IN)
|
|
@@ -1723,7 +1728,7 @@ Optional: Local semantic ONNX stack (`numpy`, `onnxruntime`, `tokenizers`) via `
|
|
|
1723
1728
|
### Shipped
|
|
1724
1729
|
|
|
1725
1730
|
- [x] MCP v2 agent surface: in-process execution, compound operations, presets, schemas, annotations, and compatibility profiles.
|
|
1726
|
-
- [x] Full command and MCP inventory parity in docs:
|
|
1731
|
+
- [x] Full command and MCP inventory parity in docs: 177 canonical CLI commands and 123 MCP tools.
|
|
1727
1732
|
- [x] CI hardening: composite action, changed-only mode, trend-aware gates, sticky PR updater, and SARIF guardrails.
|
|
1728
1733
|
- [x] Performance foundation: FTS5/BM25 search, O(changed) incremental indexing, DB/index optimizations.
|
|
1729
1734
|
- [x] Agent governance suite: `vibe-check`, `ai-readiness`, `verify`, `ai-ratio`, `duplicates`, advanced `algo` scoring/SARIF.
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
**Architectural sight for AI coding agents — before they edit.**
|
|
6
6
|
|
|
7
|
-
A local code graph (SQLite + tree-sitter + git history) that gives any agent — Claude Code, Cursor, Aider, Continue, your own — five high-leverage verbs: `understand`, `retrieve`, `context`, `preflight`, `critique`. The other
|
|
7
|
+
A local code graph (SQLite + tree-sitter + git history) that gives any agent — Claude Code, Cursor, Aider, Continue, your own — five high-leverage verbs: `understand`, `retrieve`, `context`, `preflight`, `critique`. The other 172 specialised commands are advanced surface for specialised workflows.
|
|
8
8
|
|
|
9
|
-
*
|
|
9
|
+
*177 commands · 123 MCP tools · 27 languages · 100% local · zero API keys*
|
|
10
10
|
|
|
11
11
|
[](https://pypi.org/project/roam-code/)
|
|
12
12
|
[](https://github.com/Cranot/roam-code/stargazers)
|
|
@@ -25,7 +25,7 @@ Roam is a structural intelligence engine for software. It pre-indexes your codeb
|
|
|
25
25
|
Unlike LSPs (editor-bound, language-specific) or Sourcegraph (hosted search), Roam provides architecture-level graph queries -- offline, cross-language, and compact. It goes beyond comprehension: Roam governs architecture through budget gates, simulates refactoring outcomes, orchestrates multi-agent swarms with zero-conflict guarantees, maps vulnerability reachability paths, and enables graph-level code editing without syntax errors.
|
|
26
26
|
|
|
27
27
|
```
|
|
28
|
-
Codebase ──> [Index] ──> Semantic Graph ──>
|
|
28
|
+
Codebase ──> [Index] ──> Semantic Graph ──> 177 Commands ──> AI Agent
|
|
29
29
|
│ │ │
|
|
30
30
|
tree-sitter symbols comprehend
|
|
31
31
|
27 languages + edges govern
|
|
@@ -98,7 +98,7 @@ $ roam diff # blast radius of uncommitted changes
|
|
|
98
98
|
- **`personalized_pagerank()`** in `graph/pagerank.py`: NetworkX `personalization=` wrapper with empty-seed fallback to global PR; biases ranking toward query-relevant nodes for the retrieve reranker.
|
|
99
99
|
- **`.roam/config.toml`** (new): zero-dep TOML loader (stdlib `tomllib` → `tomli` → in-tree subset parser). Tunable retrieve weights (`alpha`/`beta`/`gamma`/`delta`/`epsilon`), `tokens_per_line`, `lexical_baseline`, `first_stage_token_cap`, `default_budget`, `default_k`, `default_rerank`.
|
|
100
100
|
- **DX corrections from dogfood pass**: `roam --detail <cmd>` is the canonical group-level flag; misleading "use --detail" hints in 7 commands rewritten to point users at `roam --detail <cmd>`. `--top N` aliased on `complexity`/`algo`/`rules` (`--top 0` means unlimited on `rules`). `roam fingerprint` no longer refuses graphs ≥5,000 symbols (new soft-warn threshold 20k, hard cap 100k).
|
|
101
|
-
- **
|
|
101
|
+
- **177 CLI commands, 123 MCP tools** (`fleet`, `ask`, `workflow`, `cga`, `eval-retrieve` remain CLI-only; v12 exposes `roam_retrieve`, `roam_critique`, `roam_fleet_plan`, plus 5 v12.1 boolean oracles (`roam_oracle_*`), `roam_taint_classify`, `roam_pytest_fixtures`, and `roam_hover` as MCP tools). 35-tool `core` preset is the default for token-budget-conscious clients.
|
|
102
102
|
|
|
103
103
|
## What's New in v11
|
|
104
104
|
|
|
@@ -269,7 +269,7 @@ roam health
|
|
|
269
269
|
|
|
270
270
|
## Commands
|
|
271
271
|
|
|
272
|
-
**Lead with the 5 verbs.** The [5 core commands](#core-commands) cover ~80% of agent workflows: `understand`, `context`, `retrieve`, `preflight`, `critique`. The remaining
|
|
272
|
+
**Lead with the 5 verbs.** The [5 core commands](#core-commands) cover ~80% of agent workflows: `understand`, `context`, `retrieve`, `preflight`, `critique`. The remaining 172 commands are detail surface for specialised workflows (taint, fleet, cga, oracle, eval, …) — they're called by agents on demand, not memorised. This is intentional design; under the hood the canonical surface is **177 commands organised into 7 categories** (plus 6 aliases for muscle memory: `algo` → `math`, `weather` → `churn`, `digest` / `snapshot` / `trend` → `trends`, `onboard` → `understand`), but you don't need to know that to start.
|
|
273
273
|
|
|
274
274
|
<details>
|
|
275
275
|
<summary><strong>Full command reference</strong></summary>
|
|
@@ -317,6 +317,11 @@ roam health
|
|
|
317
317
|
| `roam api [--scope <dir>]` | List the public API surface (exported public symbols + signatures) |
|
|
318
318
|
| `roam exit-codes` | List every roam exit code with its meaning |
|
|
319
319
|
| `roam version [--check]` | Show installed version; with `--check` also queries PyPI for newer releases |
|
|
320
|
+
| `roam disambiguate <name>` | List every symbol matching the name with file/line/kind/signature/docstring snippet to pick the right one |
|
|
321
|
+
| `roam pre-commit [--install\|--print]` | Install or preview a roam-critique git pre-commit hook |
|
|
322
|
+
| `roam mcp-status` | MCP server health: preset, registered tools, backpressure limits, cache entries, watcher state |
|
|
323
|
+
| `roam test-impact [<range>]` | Tests transitively reachable from changed symbols (sharper scope than `affected-tests`) |
|
|
324
|
+
| `roam recipes` | List every `roam ask` recipe with intent + example queries (sugar over `ask --list`) |
|
|
320
325
|
|
|
321
326
|
### Daily Workflow
|
|
322
327
|
|
|
@@ -1570,7 +1575,7 @@ roam-code/
|
|
|
1570
1575
|
├── action.yml # Reusable GitHub Action
|
|
1571
1576
|
├── src/roam/
|
|
1572
1577
|
│ ├── __init__.py # Version (from pyproject.toml)
|
|
1573
|
-
│ ├── cli.py # Click CLI (
|
|
1578
|
+
│ ├── cli.py # Click CLI (177 canonical + 7 aliases)
|
|
1574
1579
|
│ ├── mcp_server.py # MCP server (122 tools, 10 resources, 5 prompts)
|
|
1575
1580
|
│ ├── db/
|
|
1576
1581
|
│ │ ├── connection.py # SQLite (WAL, pragmas, batched IN)
|
|
@@ -1665,7 +1670,7 @@ Optional: Local semantic ONNX stack (`numpy`, `onnxruntime`, `tokenizers`) via `
|
|
|
1665
1670
|
### Shipped
|
|
1666
1671
|
|
|
1667
1672
|
- [x] MCP v2 agent surface: in-process execution, compound operations, presets, schemas, annotations, and compatibility profiles.
|
|
1668
|
-
- [x] Full command and MCP inventory parity in docs:
|
|
1673
|
+
- [x] Full command and MCP inventory parity in docs: 177 canonical CLI commands and 123 MCP tools.
|
|
1669
1674
|
- [x] CI hardening: composite action, changed-only mode, trend-aware gates, sticky PR updater, and SARIF guardrails.
|
|
1670
1675
|
- [x] Performance foundation: FTS5/BM25 search, O(changed) incremental indexing, DB/index optimizations.
|
|
1671
1676
|
- [x] Agent governance suite: `vibe-check`, `ai-readiness`, `verify`, `ai-ratio`, `duplicates`, advanced `algo` scoring/SARIF.
|
|
@@ -126,6 +126,11 @@ _COMMANDS = {
|
|
|
126
126
|
"api": ("roam.commands.cmd_api", "api"),
|
|
127
127
|
"exit-codes": ("roam.commands.cmd_exit_codes", "exit_codes"),
|
|
128
128
|
"version": ("roam.commands.cmd_version", "version"),
|
|
129
|
+
"disambiguate": ("roam.commands.cmd_disambiguate", "disambiguate"),
|
|
130
|
+
"pre-commit": ("roam.commands.cmd_pre_commit", "pre_commit"),
|
|
131
|
+
"mcp-status": ("roam.commands.cmd_mcp_status", "mcp_status"),
|
|
132
|
+
"test-impact": ("roam.commands.cmd_test_impact", "test_impact"),
|
|
133
|
+
"recipes": ("roam.commands.cmd_recipes", "recipes"),
|
|
129
134
|
"forecast": ("roam.commands.cmd_forecast", "forecast"),
|
|
130
135
|
"plan": ("roam.commands.cmd_plan", "plan"),
|
|
131
136
|
"adversarial": ("roam.commands.cmd_adversarial", "adversarial"),
|
|
@@ -237,12 +242,15 @@ _CATEGORIES = {
|
|
|
237
242
|
"schema",
|
|
238
243
|
"mcp",
|
|
239
244
|
"mcp-setup",
|
|
245
|
+
"mcp-status",
|
|
240
246
|
"ci-setup",
|
|
241
247
|
"adrs",
|
|
242
248
|
"changelog",
|
|
243
249
|
"exit-codes",
|
|
244
250
|
"help-search",
|
|
245
251
|
"plugins",
|
|
252
|
+
"pre-commit",
|
|
253
|
+
"recipes",
|
|
246
254
|
"version",
|
|
247
255
|
"index-stats",
|
|
248
256
|
"stats",
|
|
@@ -271,10 +279,12 @@ _CATEGORIES = {
|
|
|
271
279
|
"critique",
|
|
272
280
|
"fleet",
|
|
273
281
|
"affected-tests",
|
|
282
|
+
"test-impact",
|
|
274
283
|
"diagnose",
|
|
275
284
|
"why-fail",
|
|
276
285
|
"recommend",
|
|
277
286
|
"api",
|
|
287
|
+
"disambiguate",
|
|
278
288
|
"annotate",
|
|
279
289
|
"annotations",
|
|
280
290
|
"plan",
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"""``roam disambiguate <name>`` — list every symbol matching this name.
|
|
2
|
+
|
|
3
|
+
Pass 81 — agents calling ``roam search`` then picking the first result
|
|
4
|
+
sometimes pick the wrong one when several functions share a name.
|
|
5
|
+
This command shows all matches with the disambiguators (file, line,
|
|
6
|
+
kind, signature, first docstring line) plus PageRank as a tiebreaker.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import click
|
|
12
|
+
|
|
13
|
+
from roam.commands.resolve import ensure_index
|
|
14
|
+
from roam.db.connection import open_db
|
|
15
|
+
from roam.output.formatter import json_envelope, to_json
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@click.command()
|
|
19
|
+
@click.argument("name")
|
|
20
|
+
@click.option("--limit", type=int, default=20, show_default=True, help="Max matches to display.")
|
|
21
|
+
@click.pass_context
|
|
22
|
+
def disambiguate(ctx, name, limit) -> None:
|
|
23
|
+
"""List every symbol matching <name> with disambiguators.
|
|
24
|
+
|
|
25
|
+
Match tiers, in order:
|
|
26
|
+
1. ``s.name = name`` (exact name match)
|
|
27
|
+
2. ``s.qualified_name = name`` (exact qname)
|
|
28
|
+
3. ``s.qualified_name LIKE '%.name'`` (suffix qname)
|
|
29
|
+
"""
|
|
30
|
+
json_mode = ctx.obj.get("json") if ctx.obj else False
|
|
31
|
+
ensure_index()
|
|
32
|
+
|
|
33
|
+
with open_db(readonly=True) as conn:
|
|
34
|
+
rows = conn.execute(
|
|
35
|
+
"""
|
|
36
|
+
SELECT s.id, s.name, s.qualified_name, s.kind, s.signature,
|
|
37
|
+
s.docstring, s.line_start, f.path,
|
|
38
|
+
COALESCE(gm.pagerank, 0) AS pagerank
|
|
39
|
+
FROM symbols s
|
|
40
|
+
JOIN files f ON f.id = s.file_id
|
|
41
|
+
LEFT JOIN graph_metrics gm ON gm.symbol_id = s.id
|
|
42
|
+
WHERE s.name = ?
|
|
43
|
+
OR s.qualified_name = ?
|
|
44
|
+
OR s.qualified_name LIKE ?
|
|
45
|
+
ORDER BY pagerank DESC, s.name
|
|
46
|
+
LIMIT ?
|
|
47
|
+
""",
|
|
48
|
+
(name, name, f"%.{name}", int(limit)),
|
|
49
|
+
).fetchall()
|
|
50
|
+
|
|
51
|
+
matches = []
|
|
52
|
+
for r in rows:
|
|
53
|
+
doc_first = ""
|
|
54
|
+
if r["docstring"]:
|
|
55
|
+
stripped = (r["docstring"] or "").strip().splitlines()
|
|
56
|
+
doc_first = stripped[0] if stripped else ""
|
|
57
|
+
matches.append(
|
|
58
|
+
{
|
|
59
|
+
"name": r["name"],
|
|
60
|
+
"qualified_name": r["qualified_name"],
|
|
61
|
+
"kind": r["kind"],
|
|
62
|
+
"signature": (r["signature"] or "").strip(),
|
|
63
|
+
"docstring_summary": doc_first,
|
|
64
|
+
"file": r["path"],
|
|
65
|
+
"line": r["line_start"],
|
|
66
|
+
"pagerank": round(float(r["pagerank"]), 6),
|
|
67
|
+
}
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
verdict = (
|
|
71
|
+
f"no symbol matching '{name}'"
|
|
72
|
+
if not matches
|
|
73
|
+
else f"{len(matches)} symbol(s) matching '{name}' (top: {matches[0]['qualified_name'] or matches[0]['name']})"
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
if json_mode:
|
|
77
|
+
click.echo(
|
|
78
|
+
to_json(
|
|
79
|
+
json_envelope(
|
|
80
|
+
"disambiguate",
|
|
81
|
+
summary={"verdict": verdict, "count": len(matches)},
|
|
82
|
+
matches=matches,
|
|
83
|
+
)
|
|
84
|
+
)
|
|
85
|
+
)
|
|
86
|
+
return
|
|
87
|
+
|
|
88
|
+
click.echo(f"VERDICT: {verdict}")
|
|
89
|
+
if not matches:
|
|
90
|
+
return
|
|
91
|
+
click.echo()
|
|
92
|
+
for m in matches:
|
|
93
|
+
ident = m["qualified_name"] or m["name"]
|
|
94
|
+
click.echo(f" {m['kind']:<10} {ident} ({m['file']}:{m['line']}) PR={m['pagerank']:.5f}")
|
|
95
|
+
if m["signature"]:
|
|
96
|
+
click.echo(f" sig: {m['signature'][:100]}")
|
|
97
|
+
if m["docstring_summary"]:
|
|
98
|
+
click.echo(f" doc: {m['docstring_summary'][:100]}")
|
|
@@ -42,8 +42,23 @@ def _build_symbol_entry_text(s, *, for_budget: bool = False) -> str:
|
|
|
42
42
|
@click.option("-n", "count", default=20, help="Number of top symbols to show")
|
|
43
43
|
@click.option("--full", is_flag=True, help="Show all results without truncation")
|
|
44
44
|
@click.option("--budget", type=int, default=None, help="Approximate token limit for output")
|
|
45
|
+
@click.option(
|
|
46
|
+
"--seed",
|
|
47
|
+
"seed_path",
|
|
48
|
+
type=str,
|
|
49
|
+
default=None,
|
|
50
|
+
help="Pass 90 — restrict the top-symbols list to symbols reachable from this file.",
|
|
51
|
+
)
|
|
52
|
+
@click.option(
|
|
53
|
+
"--depth",
|
|
54
|
+
"seed_depth",
|
|
55
|
+
type=int,
|
|
56
|
+
default=2,
|
|
57
|
+
show_default=True,
|
|
58
|
+
help="Pass 90 — BFS hop limit when --seed is given.",
|
|
59
|
+
)
|
|
45
60
|
@click.pass_context
|
|
46
|
-
def map_cmd(ctx, count, full, budget):
|
|
61
|
+
def map_cmd(ctx, count, full, budget, seed_path, seed_depth):
|
|
47
62
|
"""Show project skeleton with entry points and key symbols.
|
|
48
63
|
|
|
49
64
|
Unlike ``describe`` (which generates a prose project overview), this
|
|
@@ -96,6 +111,36 @@ def map_cmd(ctx, count, full, budget):
|
|
|
96
111
|
fetch_limit = count if budget is None else 10_000
|
|
97
112
|
all_ranked = conn.execute(TOP_SYMBOLS_BY_PAGERANK, (fetch_limit,)).fetchall()
|
|
98
113
|
|
|
114
|
+
# Pass 90 — if a seed file is given, narrow ``all_ranked`` to
|
|
115
|
+
# symbols reachable from that file within ``seed_depth`` hops.
|
|
116
|
+
if seed_path:
|
|
117
|
+
try:
|
|
118
|
+
import networkx as nx
|
|
119
|
+
|
|
120
|
+
from roam.graph.builder import build_symbol_graph
|
|
121
|
+
except ImportError:
|
|
122
|
+
seed_path = None # graph unavailable, fall through
|
|
123
|
+
if seed_path:
|
|
124
|
+
seed_norm = seed_path.replace("\\", "/")
|
|
125
|
+
seed_rows = conn.execute(
|
|
126
|
+
"SELECT s.id FROM symbols s JOIN files f ON f.id = s.file_id "
|
|
127
|
+
"WHERE REPLACE(f.path, '\\', '/') = ? OR REPLACE(f.path, '\\', '/') LIKE ?",
|
|
128
|
+
(seed_norm, f"{seed_norm}%"),
|
|
129
|
+
).fetchall()
|
|
130
|
+
seed_ids = [r["id"] for r in seed_rows]
|
|
131
|
+
if seed_ids:
|
|
132
|
+
G = build_symbol_graph(conn)
|
|
133
|
+
reach: set[int] = set(seed_ids)
|
|
134
|
+
for sid in seed_ids:
|
|
135
|
+
if sid not in G:
|
|
136
|
+
continue
|
|
137
|
+
try:
|
|
138
|
+
lengths = nx.single_source_shortest_path_length(G, sid, cutoff=int(seed_depth))
|
|
139
|
+
reach.update(lengths.keys())
|
|
140
|
+
except Exception:
|
|
141
|
+
continue
|
|
142
|
+
all_ranked = [r for r in all_ranked if r["id"] in reach]
|
|
143
|
+
|
|
99
144
|
# ---- Budget-aware symbol selection ----
|
|
100
145
|
if budget is not None:
|
|
101
146
|
# Pre-compute the preamble (stats, dirs, entries) to account
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"""``roam mcp-status`` — health check for the MCP server.
|
|
2
|
+
|
|
3
|
+
Pass 83 — companion to ``roam doctor``. Reports:
|
|
4
|
+
|
|
5
|
+
* preset (core / review / refactor / debug / architecture / full)
|
|
6
|
+
* registered tool count + core tool count
|
|
7
|
+
* backpressure limits (max_concurrent, in_flight, per-tool overrides)
|
|
8
|
+
* MCP-level result cache size + hit-rate (if anything cached this session)
|
|
9
|
+
* recent ``busy_responses_total`` count
|
|
10
|
+
* watcher status (if ROAM_MCP_WATCH=1)
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import os
|
|
16
|
+
|
|
17
|
+
import click
|
|
18
|
+
|
|
19
|
+
from roam.output.formatter import json_envelope, to_json
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@click.command(name="mcp-status")
|
|
23
|
+
@click.pass_context
|
|
24
|
+
def mcp_status(ctx) -> None:
|
|
25
|
+
"""Report MCP server status: preset, tools, backpressure, cache, watcher."""
|
|
26
|
+
json_mode = ctx.obj.get("json") if ctx.obj else False
|
|
27
|
+
|
|
28
|
+
preset = os.environ.get("ROAM_MCP_PRESET", "core")
|
|
29
|
+
watch_enabled = os.environ.get("ROAM_MCP_WATCH", "").strip() in {"1", "true", "yes"}
|
|
30
|
+
|
|
31
|
+
try:
|
|
32
|
+
from roam.mcp_server import _CORE_TOOLS, _REGISTERED_TOOLS, _ROAM_RESULT_CACHE
|
|
33
|
+
except Exception as exc:
|
|
34
|
+
msg = f"MCP server module unavailable: {type(exc).__name__}: {exc}"
|
|
35
|
+
if json_mode:
|
|
36
|
+
click.echo(to_json(json_envelope("mcp-status", summary={"verdict": msg, "ready": False})))
|
|
37
|
+
else:
|
|
38
|
+
click.echo(f"VERDICT: {msg}")
|
|
39
|
+
return
|
|
40
|
+
|
|
41
|
+
try:
|
|
42
|
+
from roam.mcp_extras.concurrency import metrics as concurrency_metrics
|
|
43
|
+
|
|
44
|
+
bp = concurrency_metrics()
|
|
45
|
+
except Exception:
|
|
46
|
+
bp = {"max_concurrent": None, "in_flight": None, "busy_responses_total": None, "per_tool_limits": {}}
|
|
47
|
+
|
|
48
|
+
cache_size = len(_ROAM_RESULT_CACHE)
|
|
49
|
+
registered = len(_REGISTERED_TOOLS)
|
|
50
|
+
core_count = sum(1 for n in _REGISTERED_TOOLS if n in _CORE_TOOLS)
|
|
51
|
+
|
|
52
|
+
verdict = (
|
|
53
|
+
f"MCP ready — preset={preset}, {registered} tools registered "
|
|
54
|
+
f"({core_count} core), max_concurrent={bp.get('max_concurrent')}"
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
if json_mode:
|
|
58
|
+
click.echo(
|
|
59
|
+
to_json(
|
|
60
|
+
json_envelope(
|
|
61
|
+
"mcp-status",
|
|
62
|
+
summary={
|
|
63
|
+
"verdict": verdict,
|
|
64
|
+
"preset": preset,
|
|
65
|
+
"tools_registered": registered,
|
|
66
|
+
"core_tool_count": core_count,
|
|
67
|
+
"max_concurrent": bp.get("max_concurrent"),
|
|
68
|
+
"in_flight": bp.get("in_flight"),
|
|
69
|
+
"busy_responses_total": bp.get("busy_responses_total"),
|
|
70
|
+
"cache_entries": cache_size,
|
|
71
|
+
"watcher_enabled": watch_enabled,
|
|
72
|
+
},
|
|
73
|
+
backpressure=bp,
|
|
74
|
+
)
|
|
75
|
+
)
|
|
76
|
+
)
|
|
77
|
+
return
|
|
78
|
+
|
|
79
|
+
click.echo(f"VERDICT: {verdict}")
|
|
80
|
+
click.echo()
|
|
81
|
+
click.echo(f"Preset: {preset}")
|
|
82
|
+
click.echo(f"Tools registered: {registered}")
|
|
83
|
+
click.echo(f" of which core preset: {core_count}")
|
|
84
|
+
click.echo(f"Max concurrent: {bp.get('max_concurrent')}")
|
|
85
|
+
click.echo(f"In flight (now): {bp.get('in_flight')}")
|
|
86
|
+
click.echo(f"Busy responses total: {bp.get('busy_responses_total')}")
|
|
87
|
+
click.echo(f"Per-tool override count: {len(bp.get('per_tool_limits') or {})}")
|
|
88
|
+
click.echo(f"Result-cache entries: {cache_size}")
|
|
89
|
+
click.echo(f"Watcher enabled: {'yes' if watch_enabled else 'no'}")
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"""``roam pre-commit`` — install or print a git pre-commit hook.
|
|
2
|
+
|
|
3
|
+
Pass 82 — generates a hook that runs ``git diff --cached | roam critique``
|
|
4
|
+
on staged changes, exiting non-zero on high-severity findings. Idempotent:
|
|
5
|
+
installing twice is a no-op (rewrites the same content).
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
import click
|
|
13
|
+
|
|
14
|
+
from roam.commands.resolve import ensure_index
|
|
15
|
+
from roam.db.connection import find_project_root
|
|
16
|
+
from roam.output.formatter import json_envelope, to_json
|
|
17
|
+
|
|
18
|
+
_HOOK_NAME = "pre-commit"
|
|
19
|
+
_HOOK_TEMPLATE = """#!/bin/sh
|
|
20
|
+
# Generated by `roam pre-commit --install`. Idempotent.
|
|
21
|
+
# Runs roam critique on staged changes. Exit 5 = high-severity finding.
|
|
22
|
+
# Set ROAM_PRECOMMIT_SKIP=1 to bypass.
|
|
23
|
+
|
|
24
|
+
if [ "${ROAM_PRECOMMIT_SKIP:-0}" = "1" ]; then
|
|
25
|
+
exit 0
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
if ! command -v roam >/dev/null 2>&1; then
|
|
29
|
+
echo "roam not on PATH; install with `pip install roam-code` or set ROAM_PRECOMMIT_SKIP=1." >&2
|
|
30
|
+
exit 0
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
DIFF="$(git diff --cached)"
|
|
34
|
+
if [ -z "$DIFF" ]; then
|
|
35
|
+
exit 0
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
echo "$DIFF" | roam critique
|
|
39
|
+
status=$?
|
|
40
|
+
case "$status" in
|
|
41
|
+
0) exit 0 ;;
|
|
42
|
+
5) echo "roam critique flagged a high-severity finding. ROAM_PRECOMMIT_SKIP=1 to bypass." >&2 ; exit 1 ;;
|
|
43
|
+
*) echo "roam critique exited $status — not blocking. ROAM_PRECOMMIT_SKIP=1 to silence." >&2 ; exit 0 ;;
|
|
44
|
+
esac
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _hooks_dir(root: Path) -> Path:
|
|
49
|
+
return root / ".git" / "hooks"
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@click.command(name="pre-commit")
|
|
53
|
+
@click.option("--install", is_flag=True, help="Write the hook into .git/hooks/pre-commit (idempotent).")
|
|
54
|
+
@click.option("--print", "print_only", is_flag=True, help="Print the hook script to stdout instead of installing.")
|
|
55
|
+
@click.pass_context
|
|
56
|
+
def pre_commit(ctx, install, print_only) -> None:
|
|
57
|
+
"""Install or preview a roam-critique pre-commit git hook."""
|
|
58
|
+
json_mode = ctx.obj.get("json") if ctx.obj else False
|
|
59
|
+
ensure_index()
|
|
60
|
+
root = find_project_root()
|
|
61
|
+
hooks = _hooks_dir(root)
|
|
62
|
+
target = hooks / _HOOK_NAME
|
|
63
|
+
|
|
64
|
+
if print_only or (not install):
|
|
65
|
+
if json_mode:
|
|
66
|
+
click.echo(
|
|
67
|
+
to_json(
|
|
68
|
+
json_envelope(
|
|
69
|
+
"pre-commit",
|
|
70
|
+
summary={
|
|
71
|
+
"verdict": "preview-only — pass --install to write the hook",
|
|
72
|
+
"target": str(target),
|
|
73
|
+
"exists": target.exists(),
|
|
74
|
+
},
|
|
75
|
+
script=_HOOK_TEMPLATE,
|
|
76
|
+
)
|
|
77
|
+
)
|
|
78
|
+
)
|
|
79
|
+
else:
|
|
80
|
+
click.echo(f"# Would write to: {target}")
|
|
81
|
+
click.echo()
|
|
82
|
+
click.echo(_HOOK_TEMPLATE)
|
|
83
|
+
click.echo()
|
|
84
|
+
click.echo("Run `roam pre-commit --install` to write the hook.")
|
|
85
|
+
return
|
|
86
|
+
|
|
87
|
+
if not (root / ".git").exists():
|
|
88
|
+
verdict = f"no .git directory under {root} — run from inside a git repository"
|
|
89
|
+
if json_mode:
|
|
90
|
+
click.echo(to_json(json_envelope("pre-commit", summary={"verdict": verdict, "installed": False})))
|
|
91
|
+
else:
|
|
92
|
+
click.echo(f"VERDICT: {verdict}")
|
|
93
|
+
ctx.exit(2)
|
|
94
|
+
return
|
|
95
|
+
|
|
96
|
+
hooks.mkdir(parents=True, exist_ok=True)
|
|
97
|
+
existing = target.read_text(encoding="utf-8") if target.exists() else None
|
|
98
|
+
if existing == _HOOK_TEMPLATE:
|
|
99
|
+
verdict = f"hook already up to date at {target}"
|
|
100
|
+
else:
|
|
101
|
+
target.write_text(_HOOK_TEMPLATE, encoding="utf-8")
|
|
102
|
+
try:
|
|
103
|
+
# chmod +x on POSIX. On Windows the bit is ignored but harmless.
|
|
104
|
+
target.chmod(0o755)
|
|
105
|
+
except OSError:
|
|
106
|
+
pass
|
|
107
|
+
verdict = f"installed roam pre-commit hook to {target}"
|
|
108
|
+
|
|
109
|
+
if json_mode:
|
|
110
|
+
click.echo(
|
|
111
|
+
to_json(
|
|
112
|
+
json_envelope(
|
|
113
|
+
"pre-commit",
|
|
114
|
+
summary={"verdict": verdict, "installed": True, "target": str(target)},
|
|
115
|
+
)
|
|
116
|
+
)
|
|
117
|
+
)
|
|
118
|
+
return
|
|
119
|
+
click.echo(f"VERDICT: {verdict}")
|
|
120
|
+
click.echo(" ROAM_PRECOMMIT_SKIP=1 to bypass on a single commit.")
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""``roam recipes`` — list every ask recipe with intent + examples.
|
|
2
|
+
|
|
3
|
+
Pass 88 — sugar over ``roam ask --list`` for discoverability. Useful as
|
|
4
|
+
the first thing an agent runs to see what natural-language tasks
|
|
5
|
+
``roam ask`` handles.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import click
|
|
11
|
+
|
|
12
|
+
from roam.ask.recipes import RECIPES
|
|
13
|
+
from roam.output.formatter import json_envelope, to_json
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@click.command()
|
|
17
|
+
@click.pass_context
|
|
18
|
+
def recipes(ctx) -> None:
|
|
19
|
+
"""List every ``roam ask`` recipe with intent + example queries."""
|
|
20
|
+
json_mode = ctx.obj.get("json") if ctx.obj else False
|
|
21
|
+
items = [
|
|
22
|
+
{
|
|
23
|
+
"name": r.name,
|
|
24
|
+
"intent": r.intent,
|
|
25
|
+
"phase": r.phase,
|
|
26
|
+
"examples": list(r.examples),
|
|
27
|
+
"commands": [{"cmd": c[0], "args": list(c[1])} for c in r.commands],
|
|
28
|
+
}
|
|
29
|
+
for r in RECIPES
|
|
30
|
+
]
|
|
31
|
+
items.sort(key=lambda x: x["name"])
|
|
32
|
+
verdict = f"{len(items)} ask recipe(s) in registry"
|
|
33
|
+
|
|
34
|
+
if json_mode:
|
|
35
|
+
click.echo(
|
|
36
|
+
to_json(
|
|
37
|
+
json_envelope(
|
|
38
|
+
"recipes",
|
|
39
|
+
summary={"verdict": verdict, "count": len(items)},
|
|
40
|
+
recipes=items,
|
|
41
|
+
)
|
|
42
|
+
)
|
|
43
|
+
)
|
|
44
|
+
return
|
|
45
|
+
|
|
46
|
+
click.echo(f"VERDICT: {verdict}")
|
|
47
|
+
click.echo()
|
|
48
|
+
click.echo(f"{'Name':<26} {'Phase':<14} Intent")
|
|
49
|
+
click.echo(f"{'-' * 26} {'-' * 14} {'-' * 50}")
|
|
50
|
+
for it in items:
|
|
51
|
+
click.echo(f"{it['name']:<26} {it['phase'][:14]:<14} {it['intent'][:60]}")
|
|
52
|
+
click.echo()
|
|
53
|
+
click.echo('Run `roam ask "<query>"` to dispatch by intent.')
|