roam-code 12.42__tar.gz → 12.44__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.42 → roam_code-12.44}/PKG-INFO +7 -4
- {roam_code-12.42 → roam_code-12.44}/README.md +6 -3
- {roam_code-12.42 → roam_code-12.44}/pyproject.toml +1 -1
- roam_code-12.44/src/roam/capability.py +250 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/catalog/detectors.py +131 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/catalog/tasks.py +46 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/cli.py +6 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_article_12_check.py +17 -0
- roam_code-12.44/src/roam/commands/cmd_capabilities.py +129 -0
- roam_code-12.44/src/roam/commands/cmd_compare.py +223 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_permit.py +18 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_postmortem.py +17 -0
- roam_code-12.44/src/roam/commands/cmd_skill_generate.py +256 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/competitor_site_data.py +1 -1
- {roam_code-12.42 → roam_code-12.44}/src/roam/mcp-server-card.json +1 -1
- {roam_code-12.42 → roam_code-12.44}/src/roam/output/sarif.py +137 -6
- {roam_code-12.42 → roam_code-12.44}/src/roam_code.egg-info/PKG-INFO +7 -4
- {roam_code-12.42 → roam_code-12.44}/src/roam_code.egg-info/SOURCES.txt +8 -0
- roam_code-12.44/tests/test_capability_registry.py +137 -0
- roam_code-12.44/tests/test_compare_cli.py +121 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_math.py +3 -1
- roam_code-12.44/tests/test_sarif_enrichment.py +154 -0
- roam_code-12.44/tests/test_skill_generate.py +74 -0
- {roam_code-12.42 → roam_code-12.44}/LICENSE +0 -0
- {roam_code-12.42 → roam_code-12.44}/setup.cfg +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/__init__.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/__main__.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/analysis/__init__.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/analysis/effects.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/analysis/taint.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/api.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/ask/__init__.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/ask/classifier.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/ask/recipes.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/ask/runner.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/ask/workflow.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/attest/__init__.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/attest/cga.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/bridges/__init__.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/bridges/base.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/bridges/bridge_config.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/bridges/bridge_django.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/bridges/bridge_protobuf.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/bridges/bridge_rest_api.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/bridges/bridge_salesforce.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/bridges/bridge_template.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/bridges/registry.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/catalog/__init__.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/catalog/fixes.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/catalog/python_idioms.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/catalog/smells.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/__init__.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/audit_trail_helpers.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/changed_files.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_adrs.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_adversarial.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_affected.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_affected_tests.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_agent_context.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_agent_export.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_agent_plan.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_ai_ratio.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_ai_readiness.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_alerts.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_annotate.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_api.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_api_changes.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_api_drift.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_ask.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_attest.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_audit.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_audit_trail_conformance.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_audit_trail_export.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_audit_trail_verify.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_auth_gaps.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_bisect.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_breaking.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_budget.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_bus_factor.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_capsule.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_cga.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_changelog.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_check_rules.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_ci_setup.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_clean.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_clones.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_closure.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_clusters.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_codeowners.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_complexity.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_config.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_congestion.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_context.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_conventions.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_coupling.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_coverage_gaps.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_critique.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_cut.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_dark_matter.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_dashboard.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_dead.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_debt.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_deps.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_describe.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_dev_profile.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_diagnose.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_diff.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_disambiguate.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_doc_staleness.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_docs_coverage.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_doctor.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_dogfood.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_drift.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_duplicates.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_effects.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_endpoints.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_entry_points.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_eval_retrieve.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_exit_codes.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_fan.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_file.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_fingerprint.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_fitness.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_flag_dead.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_fleet.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_fn_coupling.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_forecast.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_graph_export.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_graph_stats.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_grep.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_guard.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_health.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_help_search.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_hooks.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_hotspots.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_hover.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_impact.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_index.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_index_bundle.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_index_stats.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_ingest_trace.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_init.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_intent.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_invariants.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_layers.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_map.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_math.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_mcp_setup.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_mcp_status.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_metrics.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_metrics_push.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_migration_safety.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_minimap.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_missing_index.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_module.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_mutate.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_n1.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_oracle.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_orchestrate.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_orphan_imports.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_orphan_routes.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_over_fetch.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_owner.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_partition.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_path_coverage.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_patterns.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_plan.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_plan_refactor.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_plugins.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_pr_analyze.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_pr_comment_render.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_pr_diff.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_pr_prep.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_pr_risk.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_pre_commit.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_preflight.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_py_modern.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_py_types.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_pytest_fixtures.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_recipes.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_recommend.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_relate.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_report.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_reset.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_retrieve.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_risk.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_rules.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_rules_validate.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_safe_delete.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_safe_zones.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_sbom.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_schema.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_search.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_search_semantic.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_secrets.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_semantic_diff.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_simulate.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_simulate_departure.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_sketch.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_smells.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_spectral.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_split.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_stats.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_suggest_refactoring.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_suggest_reviewers.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_supply_chain.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_suppress.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_symbol.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_syntax_check.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_taint.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_telemetry.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_test_gaps.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_test_impact.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_test_pyramid.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_test_scaffold.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_testmap.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_timeline.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_tour.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_trace.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_trends.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_triage.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_understand.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_uses.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_verify.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_verify_imports.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_version.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_vibe_check.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_visualize.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_vuln_map.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_vuln_reach.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_vulns.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_watch.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_weather.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_why.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_why_fail.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_workflow.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_ws.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/cmd_xlang.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/codeowners_helpers.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/context_helpers.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/finding_suppress.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/gate_presets.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/git_helpers.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/graph_helpers.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/metrics_history.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/next_steps.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/pr_analyze/__init__.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/pr_analyze/audit_trail.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/pr_analyze/cache.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/pr_analyze/rules.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/resolve.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/commands/suppression.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/config.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/coverage_reports.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/critique/__init__.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/critique/aggregator.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/critique/checks.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/db/__init__.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/db/connection.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/db/queries.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/db/schema.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/eval/__init__.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/eval/harness.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/exit_codes.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/fleet/__init__.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/fleet/adapters.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/fleet/manifest.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/git_utils.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/graph/__init__.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/graph/anomaly.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/graph/builder.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/graph/clone_detect.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/graph/clusters.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/graph/cycles.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/graph/dark_matter.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/graph/diff.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/graph/fingerprint.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/graph/layers.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/graph/pagerank.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/graph/partition.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/graph/pathfinding.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/graph/propagation.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/graph/simulate.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/graph/spectral.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/graph/stats.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/index/__init__.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/index/complexity.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/index/discovery.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/index/django_post.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/index/file_roles.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/index/git_stats.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/index/gitignore.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/index/incremental.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/index/indexer.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/index/parser.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/index/pytest_fixtures.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/index/registry_dispatch.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/index/relations.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/index/symbols.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/index/test_conventions.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/languages/__init__.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/languages/apex_lang.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/languages/aura_lang.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/languages/base.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/languages/c_lang.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/languages/csharp_lang.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/languages/extractor_schema.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/languages/extractors/kotlin.yaml +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/languages/foxpro_lang.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/languages/generic_lang.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/languages/go_lang.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/languages/hcl_lang.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/languages/java_lang.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/languages/javascript_lang.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/languages/kotlin_lang.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/languages/php_lang.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/languages/python_lang.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/languages/query_engine.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/languages/registry.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/languages/ruby_lang.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/languages/rust_lang.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/languages/scala_lang.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/languages/sfxml_lang.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/languages/sql_lang.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/languages/swift_lang.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/languages/typescript_lang.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/languages/visualforce_lang.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/languages/yaml_lang.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/mcp_extras/__init__.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/mcp_extras/completions.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/mcp_extras/concurrency.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/mcp_extras/progress.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/mcp_extras/sampling.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/mcp_extras/session.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/mcp_extras/watcher.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/mcp_server.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/observability.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/output/__init__.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/output/confidence.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/output/errors.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/output/file_role_hints.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/output/formatter.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/output/framework_filter.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/output/mermaid.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/output/project_shape.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/output/schema_registry.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/plugins.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/refactor/__init__.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/refactor/codegen.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/refactor/transforms.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/retrieve/__init__.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/retrieve/learned_ranker.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/retrieve/pipeline.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/retrieve/rerank.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/retrieve/seeds.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/retrieve/semantic.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/rules/__init__.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/rules/ast_match.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/rules/builtin.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/rules/dataflow.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/rules/engine.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/runtime/__init__.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/runtime/daemon.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/runtime/graph_backend.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/runtime/hotspots.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/runtime/lock_modes.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/runtime/lockmgr.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/runtime/trace_ingest.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/search/__init__.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/search/framework_packs.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/search/index_embeddings.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/search/onnx_embeddings.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/search/tfidf.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/security/__init__.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/security/aibom_extension.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/security/taint_classifier.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/security/taint_engine.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/security/taint_rules/api_error_leak.yaml +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/security/taint_rules/java_fileupload_path_traversal.yaml +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/security/taint_rules/js_insecure_jwt_decode.yaml +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/security/taint_rules/js_localstorage_secrets.yaml +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/security/taint_rules/js_prototype_pollution.yaml +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/security/taint_rules/js_ssrf.yaml +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/security/taint_rules/js_xss.yaml +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/security/taint_rules/python_basic.yaml +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/security/taint_rules/python_deserialization.yaml +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/security/taint_rules/python_path_traversal.yaml +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/security/taint_rules/python_socketio_remote_source.yaml +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/security/taint_rules/python_sqli.yaml +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/security/taint_rules/python_urllib_open_redirect.yaml +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/security/taint_rules/vue_v_html.yaml +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/security/vuln_reach.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/security/vuln_store.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/surface_counts.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/telemetry.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/templates/__init__.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/templates/ci/Jenkinsfile +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/templates/ci/__init__.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/templates/ci/agent-review.yml +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/templates/ci/azure-pipelines.yml +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/templates/ci/bitbucket-pipelines.yml +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/templates/ci/gitlab-ci.yml +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/workspace/__init__.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/workspace/aggregator.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/workspace/api_scanner.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/workspace/config.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam/workspace/db.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam_code.egg-info/dependency_links.txt +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam_code.egg-info/entry_points.txt +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam_code.egg-info/requires.txt +0 -0
- {roam_code-12.42 → roam_code-12.44}/src/roam_code.egg-info/top_level.txt +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_adrs.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_adversarial.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_affected.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_agent_export.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_agent_mode.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_agent_plan_context.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_ai_ratio.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_ai_readiness.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_alerts_cmd.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_annotations.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_anomaly.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_api_changes.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_api_drift.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_ask.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_attest.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_audit_trail_aggregate.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_audit_trail_conformance.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_audit_trail_sequence.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_audit_trail_verify.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_auth_gaps.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_backend_fixes_round2.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_backend_fixes_round3.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_basic.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_batch_mcp.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_bisect.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_bridge_django.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_bridges.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_bridges_extended.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_budget.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_budget_flag.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_budget_phase2.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_bus_factor.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_capsule.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_cga.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_check_rules.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_ci_gate_eval.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_ci_sarif_guard.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_ci_setup.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_clones.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_closure.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_codeowners.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_commands_architecture.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_commands_exploration.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_commands_health.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_commands_refactoring.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_commands_workflow.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_competitor_site_data.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_comprehensive.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_config.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_congestion.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_context_propagation.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_conventions_cmd.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_coverage_gaps_cmd.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_coverage_ingestion.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_critique.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_cut.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_dark_matter.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_dark_matter_helpers.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_dashboard.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_dataflow_dead.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_dead_aging.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_defer_loading.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_demo_gif_asset.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_describe.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_detail_flag_hints.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_detector_precision.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_deterministic_output.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_dev_profile.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_difficulty_scoring.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_doc_consistency.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_doc_staleness.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_docker_assets.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_docs_coverage.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_docs_site_quality.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_doctor.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_dogfood.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_drift.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_drift_by_team.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_duplicates.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_effects.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_effects_propagation.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_endpoints.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_entry_points_cmd.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_eval_retrieve.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_except_pass_narrow.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_exclude_patterns.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_exit_codes.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_extractor_grammar_drift.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_fallback_contracts.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_file_roles.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_finding_suppress.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_fingerprint.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_fixes.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_flag_dead.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_fleet.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_fn_coupling.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_forecast.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_formatters.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_foxpro.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_framework_detection.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_gate_presets.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_git_helpers.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_git_utils.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_guard.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_health_gate.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_hooks.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_hotspots.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_hover.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_index.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_index_bundle.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_init_cmd.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_install_check.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_intent.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_invariants.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_json_contracts.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_json_error_envelope.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_kotlin_swift_extractors.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_language_corpus.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_languages.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_laravel_fp_fixes.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_library_api.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_math_fp_fixes.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_math_tips.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_mcp_extras.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_mcp_server.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_mcp_setup.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_mermaid.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_metrics_cmd.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_metrics_push.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_migration_safety.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_minimap.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_missing_index.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_mutate.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_n1.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_next_steps.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_onboard.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_oracle.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_orchestrate.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_orphan_routes.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_oss_bench_harness.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_over_fetch.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_pagerank_truncation.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_partition.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_path_coverage.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_patterns_cmd.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_performance.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_personalized_pagerank.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_pivot_phase0_commands.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_plan.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_plugin_discovery.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_pr_analyze.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_pr_analyze_cache.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_pr_analyze_edge_cases.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_pr_analyze_helpers.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_pr_analyze_v2_signals.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_pr_comment_render.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_pr_comment_script.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_pr_diff.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_pr_risk_author.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_progress.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_progressive_disclosure.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_properties.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_pytest_fixtures.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_python_extractor_v2.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_python_idioms_e2e.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_python_pivot.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_readme_surface_consistency.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_realworld_feedback.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_refactoring_intelligence.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_registry_dispatch.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_regression_fp_corpus.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_relate.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_report.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_reset_clean.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_resolve.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_retrieve.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_retrieve_cross_repo.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_retrieve_seeds.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_risk.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_ruby.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_rule_profiles.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_rules.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_rules_ast_match.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_rules_community_pack.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_rules_dataflow.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_rules_symbol_requirements.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_rules_validate.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_runtime.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_runtime_score.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_salesforce.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_sarif_flag.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_sbom.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_scala.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_schema_versioning.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_search_explain.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_secrets.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_secrets_v2.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_semantic_diff.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_semantic_onnx.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_semantic_search.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_simulate.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_simulate_departure.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_sketch.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_smells.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_smoke.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_sna_metrics.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_spectral.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_split_cmd.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_sql.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_suggest_reviewers.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_supply_chain.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_surface_counts.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_syntax_check.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_taint.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_taint_analysis.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_taint_classifier.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_taint_intraprocedural.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_test_conventions.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_test_gaps.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_test_scaffold.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_testmap.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_top_flag_consistency.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_tour_cmd.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_trends.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_trends_cohort.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_triage.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_uses_cmd.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_v1215_passes.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_v1216_passes.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_v1216_passes_41_50.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_v1216_passes_51_60.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_v1217_passes_61_80.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_v1218_passes_81_90.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_v1219_passes_91_100.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_v1220_passes_101_110.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_v1221_query_timeout.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_v1221_untested_commands.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_v12_2.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_v2_edge_cases.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_v2_integration.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_v6_features.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_v71_features.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_v7_features.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_v82_features.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_verify.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_verify_imports.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_vibe_check.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_visualize.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_vuln.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_vulns_cmd.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_watch.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_why.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_workspace.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_ws_resolve_fixes.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/tests/test_xlang.py +0 -0
- {roam_code-12.42 → roam_code-12.44}/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.44
|
|
4
4
|
Summary: Instant codebase comprehension for AI coding agents
|
|
5
5
|
Author: CosmoHac
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -64,9 +64,9 @@ Dynamic: license-file
|
|
|
64
64
|
|
|
65
65
|
**Architectural sight for AI coding agents — before they edit.**
|
|
66
66
|
|
|
67
|
-
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
|
|
67
|
+
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 188 specialised commands are advanced surface for specialised workflows.
|
|
68
68
|
|
|
69
|
-
*
|
|
69
|
+
*193 commands · 136 MCP tools · 27 languages · 100% local · zero API keys*
|
|
70
70
|
|
|
71
71
|
[](https://pypi.org/project/roam-code/)
|
|
72
72
|
[](https://github.com/Cranot/roam-code/stargazers)
|
|
@@ -334,7 +334,7 @@ roam health
|
|
|
334
334
|
|
|
335
335
|
## Commands
|
|
336
336
|
|
|
337
|
-
**Lead with the 5 verbs.** The [5 core commands](#core-commands) cover ~80% of agent workflows: `understand`, `context`, `retrieve`, `preflight`, `critique`. The remaining
|
|
337
|
+
**Lead with the 5 verbs.** The [5 core commands](#core-commands) cover ~80% of agent workflows: `understand`, `context`, `retrieve`, `preflight`, `critique`. The remaining 188 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 **193 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.
|
|
338
338
|
|
|
339
339
|
<details>
|
|
340
340
|
<summary><strong>Full command reference</strong></summary>
|
|
@@ -383,6 +383,9 @@ roam health
|
|
|
383
383
|
| `roam audit-trail-export [--format md\|json\|csv] [--since T] [--verdict V] [--aggregate]` | Export the audit trail for procurement / compliance review; `--aggregate` rolls up per actor / repo / verdict / month |
|
|
384
384
|
| `roam audit-trail-conformance-check [--retention-days N] [--gate]` | Score the audit trail against an EU AI Act Article 12 checklist (chain integrity, timestamps, actors, reproducibility, retention) |
|
|
385
385
|
| `roam article-12-check [--output F] [--pdf F]` | EU AI Act Article 12 readiness assessment; 6-item checklist → 1-page Markdown / PDF report. Captures Article-12-curious leads (Aug 2 2026 deadline). |
|
|
386
|
+
| `roam capabilities [--emit yaml\|json\|text] [--category X] [--ai-safe-only]` | Emit the decorator-driven capability registry — every command's machine-readable shape (inputs, outputs, ai_safe flag, since-version). For Roam Review GitHub App + MCP filtering. |
|
|
387
|
+
| `roam skill-generate [--target claude\|cursor\|continue\|aider] [--output F]` | Generate an agent-runtime skill manifest from the capability registry. SKILL.md / .mdc / config snippets — derived from decorators, never hand-edited. |
|
|
388
|
+
| `roam compare <baseline.db> <target.db> [--top N] [--threshold N]` | Structural delta between two indices: symbols added/removed/moved + per-file complexity deltas + IMPROVED/SIDEWAYS/REGRESSED verdict. The "did this refactor actually work?" tool. |
|
|
386
389
|
| `roam permit [--staged] [--input F] [--symbol N]` | Structural-permission verdict facade for AI agents: ALLOW/REVIEW/BLOCK over critique + preflight + blast-radius. Exit codes 0/5/6 for Cursor rules / Claude Code hooks / pre-commit / CI gates. |
|
|
387
390
|
| `roam postmortem <commit-range> [--limit N] [--show N]` | Replay current detectors against past commits; reports findings that would have surfaced pre-merge. The "would Roam have caught my Q1 incident?" demo. |
|
|
388
391
|
| `roam rules-validate [PATH] [--against DIFF] [--strict] [--gate] [--explain]` | Lint a `.roam/rules.yml` for typos, schema mistakes, unknown patterns, duplicate IDs; optional dry-run against a sample diff |
|
|
@@ -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 188 specialised commands are advanced surface for specialised workflows.
|
|
8
8
|
|
|
9
|
-
*
|
|
9
|
+
*193 commands · 136 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)
|
|
@@ -274,7 +274,7 @@ roam health
|
|
|
274
274
|
|
|
275
275
|
## Commands
|
|
276
276
|
|
|
277
|
-
**Lead with the 5 verbs.** The [5 core commands](#core-commands) cover ~80% of agent workflows: `understand`, `context`, `retrieve`, `preflight`, `critique`. The remaining
|
|
277
|
+
**Lead with the 5 verbs.** The [5 core commands](#core-commands) cover ~80% of agent workflows: `understand`, `context`, `retrieve`, `preflight`, `critique`. The remaining 188 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 **193 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.
|
|
278
278
|
|
|
279
279
|
<details>
|
|
280
280
|
<summary><strong>Full command reference</strong></summary>
|
|
@@ -323,6 +323,9 @@ roam health
|
|
|
323
323
|
| `roam audit-trail-export [--format md\|json\|csv] [--since T] [--verdict V] [--aggregate]` | Export the audit trail for procurement / compliance review; `--aggregate` rolls up per actor / repo / verdict / month |
|
|
324
324
|
| `roam audit-trail-conformance-check [--retention-days N] [--gate]` | Score the audit trail against an EU AI Act Article 12 checklist (chain integrity, timestamps, actors, reproducibility, retention) |
|
|
325
325
|
| `roam article-12-check [--output F] [--pdf F]` | EU AI Act Article 12 readiness assessment; 6-item checklist → 1-page Markdown / PDF report. Captures Article-12-curious leads (Aug 2 2026 deadline). |
|
|
326
|
+
| `roam capabilities [--emit yaml\|json\|text] [--category X] [--ai-safe-only]` | Emit the decorator-driven capability registry — every command's machine-readable shape (inputs, outputs, ai_safe flag, since-version). For Roam Review GitHub App + MCP filtering. |
|
|
327
|
+
| `roam skill-generate [--target claude\|cursor\|continue\|aider] [--output F]` | Generate an agent-runtime skill manifest from the capability registry. SKILL.md / .mdc / config snippets — derived from decorators, never hand-edited. |
|
|
328
|
+
| `roam compare <baseline.db> <target.db> [--top N] [--threshold N]` | Structural delta between two indices: symbols added/removed/moved + per-file complexity deltas + IMPROVED/SIDEWAYS/REGRESSED verdict. The "did this refactor actually work?" tool. |
|
|
326
329
|
| `roam permit [--staged] [--input F] [--symbol N]` | Structural-permission verdict facade for AI agents: ALLOW/REVIEW/BLOCK over critique + preflight + blast-radius. Exit codes 0/5/6 for Cursor rules / Claude Code hooks / pre-commit / CI gates. |
|
|
327
330
|
| `roam postmortem <commit-range> [--limit N] [--show N]` | Replay current detectors against past commits; reports findings that would have surfaced pre-merge. The "would Roam have caught my Q1 incident?" demo. |
|
|
328
331
|
| `roam rules-validate [PATH] [--against DIFF] [--strict] [--gate] [--explain]` | Lint a `.roam/rules.yml` for typos, schema mistakes, unknown patterns, duplicate IDs; optional dry-run against a sample diff |
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
"""Capability Registry — decorator-driven introspection for roam commands.
|
|
2
|
+
|
|
3
|
+
Phase 1 of the v2 monetization plan (per build_priorities.md). The
|
|
4
|
+
architect's correction: the per-command capability YAML must be derived
|
|
5
|
+
from decorators, not hand-edited. This module implements the decorator
|
|
6
|
+
plus an emitter that walks all registered commands and produces a
|
|
7
|
+
machine-readable manifest.
|
|
8
|
+
|
|
9
|
+
Usage:
|
|
10
|
+
|
|
11
|
+
from roam.capability import roam_capability
|
|
12
|
+
|
|
13
|
+
@roam_capability(
|
|
14
|
+
category="review",
|
|
15
|
+
summary="Verify a patch against the indexed graph.",
|
|
16
|
+
inputs=["diff_text"],
|
|
17
|
+
outputs=["verdict", "findings"],
|
|
18
|
+
ai_safe=True,
|
|
19
|
+
since="12.0",
|
|
20
|
+
)
|
|
21
|
+
@click.command()
|
|
22
|
+
def critique(...):
|
|
23
|
+
...
|
|
24
|
+
|
|
25
|
+
The introspection layer (``CapabilityRegistry``) collects every
|
|
26
|
+
``@roam_capability``-decorated callable when it's imported, and
|
|
27
|
+
``emit_yaml`` / ``emit_json`` serialises the catalog.
|
|
28
|
+
|
|
29
|
+
The downstream consumer is the Roam Review GitHub App (Phase 2): it
|
|
30
|
+
reads the manifest at startup so it knows which commands are AI-safe to
|
|
31
|
+
expose as webhook actions vs which need human approval.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
from __future__ import annotations
|
|
35
|
+
|
|
36
|
+
from dataclasses import dataclass, field
|
|
37
|
+
from typing import Any, Callable, TypeVar
|
|
38
|
+
|
|
39
|
+
F = TypeVar("F", bound=Callable[..., Any])
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@dataclass(frozen=True)
|
|
43
|
+
class Capability:
|
|
44
|
+
"""One decorated command's metadata."""
|
|
45
|
+
|
|
46
|
+
name: str
|
|
47
|
+
category: str
|
|
48
|
+
summary: str
|
|
49
|
+
inputs: tuple[str, ...] = ()
|
|
50
|
+
outputs: tuple[str, ...] = ()
|
|
51
|
+
examples: tuple[str, ...] = ()
|
|
52
|
+
tags: tuple[str, ...] = ()
|
|
53
|
+
ai_safe: bool = False
|
|
54
|
+
requires_index: bool = True
|
|
55
|
+
since: str | None = None
|
|
56
|
+
deprecated: bool = False
|
|
57
|
+
module: str = ""
|
|
58
|
+
func_name: str = ""
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@dataclass
|
|
62
|
+
class CapabilityRegistry:
|
|
63
|
+
"""Process-wide registry of capability-decorated callables.
|
|
64
|
+
|
|
65
|
+
Populated as a side-effect of importing any decorated command module.
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
items: dict[str, Capability] = field(default_factory=dict)
|
|
69
|
+
|
|
70
|
+
def register(self, cap: Capability) -> None:
|
|
71
|
+
if cap.name in self.items:
|
|
72
|
+
existing = self.items[cap.name]
|
|
73
|
+
if existing.module != cap.module:
|
|
74
|
+
raise ValueError(
|
|
75
|
+
f"capability name collision: {cap.name!r} already registered from "
|
|
76
|
+
f"{existing.module!r}; tried to register from {cap.module!r}"
|
|
77
|
+
)
|
|
78
|
+
self.items[cap.name] = cap
|
|
79
|
+
|
|
80
|
+
def get(self, name: str) -> Capability | None:
|
|
81
|
+
return self.items.get(name)
|
|
82
|
+
|
|
83
|
+
def all(self) -> list[Capability]:
|
|
84
|
+
return sorted(self.items.values(), key=lambda c: (c.category, c.name))
|
|
85
|
+
|
|
86
|
+
def by_category(self) -> dict[str, list[Capability]]:
|
|
87
|
+
out: dict[str, list[Capability]] = {}
|
|
88
|
+
for cap in self.all():
|
|
89
|
+
out.setdefault(cap.category, []).append(cap)
|
|
90
|
+
return out
|
|
91
|
+
|
|
92
|
+
def to_dict(self) -> dict[str, Any]:
|
|
93
|
+
return {
|
|
94
|
+
"schema_version": 1,
|
|
95
|
+
"generated_by": "roam.capability.CapabilityRegistry",
|
|
96
|
+
"count": len(self.items),
|
|
97
|
+
"capabilities": [
|
|
98
|
+
{
|
|
99
|
+
"name": cap.name,
|
|
100
|
+
"category": cap.category,
|
|
101
|
+
"summary": cap.summary,
|
|
102
|
+
"inputs": list(cap.inputs),
|
|
103
|
+
"outputs": list(cap.outputs),
|
|
104
|
+
"examples": list(cap.examples),
|
|
105
|
+
"tags": list(cap.tags),
|
|
106
|
+
"ai_safe": cap.ai_safe,
|
|
107
|
+
"requires_index": cap.requires_index,
|
|
108
|
+
"since": cap.since,
|
|
109
|
+
"deprecated": cap.deprecated,
|
|
110
|
+
"module": cap.module,
|
|
111
|
+
"func_name": cap.func_name,
|
|
112
|
+
}
|
|
113
|
+
for cap in self.all()
|
|
114
|
+
],
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
REGISTRY = CapabilityRegistry()
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def roam_capability(
|
|
122
|
+
*,
|
|
123
|
+
category: str,
|
|
124
|
+
summary: str,
|
|
125
|
+
name: str | None = None,
|
|
126
|
+
inputs: tuple[str, ...] | list[str] = (),
|
|
127
|
+
outputs: tuple[str, ...] | list[str] = (),
|
|
128
|
+
examples: tuple[str, ...] | list[str] = (),
|
|
129
|
+
tags: tuple[str, ...] | list[str] = (),
|
|
130
|
+
ai_safe: bool = False,
|
|
131
|
+
requires_index: bool = True,
|
|
132
|
+
since: str | None = None,
|
|
133
|
+
deprecated: bool = False,
|
|
134
|
+
) -> Callable[[F], F]:
|
|
135
|
+
"""Mark a Click command as a capability for introspection.
|
|
136
|
+
|
|
137
|
+
Place ABOVE ``@click.command()`` so the decorator wraps a Click
|
|
138
|
+
Command instance — the introspection then has access to the
|
|
139
|
+
Click metadata as well.
|
|
140
|
+
"""
|
|
141
|
+
|
|
142
|
+
def deco(func: F) -> F:
|
|
143
|
+
cap_name = name or _derive_name(func)
|
|
144
|
+
# For Click Commands, the original module is on the callback
|
|
145
|
+
callback = getattr(func, "callback", None)
|
|
146
|
+
module = (
|
|
147
|
+
getattr(callback, "__module__", "")
|
|
148
|
+
if callback is not None
|
|
149
|
+
else getattr(func, "__module__", "")
|
|
150
|
+
)
|
|
151
|
+
func_name = (
|
|
152
|
+
getattr(callback, "__name__", "")
|
|
153
|
+
if callback is not None
|
|
154
|
+
else getattr(func, "__name__", "")
|
|
155
|
+
)
|
|
156
|
+
cap = Capability(
|
|
157
|
+
name=cap_name,
|
|
158
|
+
category=category,
|
|
159
|
+
summary=summary,
|
|
160
|
+
inputs=tuple(inputs),
|
|
161
|
+
outputs=tuple(outputs),
|
|
162
|
+
examples=tuple(examples),
|
|
163
|
+
tags=tuple(tags),
|
|
164
|
+
ai_safe=ai_safe,
|
|
165
|
+
requires_index=requires_index,
|
|
166
|
+
since=since,
|
|
167
|
+
deprecated=deprecated,
|
|
168
|
+
module=module,
|
|
169
|
+
func_name=func_name,
|
|
170
|
+
)
|
|
171
|
+
REGISTRY.register(cap)
|
|
172
|
+
# Stash on the function for later introspection (e.g. roam capabilities --explain X)
|
|
173
|
+
setattr(func, "__roam_capability__", cap)
|
|
174
|
+
return func
|
|
175
|
+
|
|
176
|
+
return deco
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def _derive_name(func: Callable[..., Any]) -> str:
|
|
180
|
+
"""Derive the CLI command name from the function or Click Command.
|
|
181
|
+
|
|
182
|
+
Order of preference:
|
|
183
|
+
1. ``func.name`` — set by ``@click.command(name=...)``
|
|
184
|
+
2. ``func.__name__`` — set by Python on a function
|
|
185
|
+
3. ``func.callback.__name__`` — Click stores the original here
|
|
186
|
+
Strips a leading ``cmd_`` and converts underscores to dashes.
|
|
187
|
+
"""
|
|
188
|
+
candidates: list[str] = []
|
|
189
|
+
name_attr = getattr(func, "name", None)
|
|
190
|
+
if isinstance(name_attr, str) and name_attr:
|
|
191
|
+
candidates.append(name_attr)
|
|
192
|
+
fn_name = getattr(func, "__name__", "")
|
|
193
|
+
if isinstance(fn_name, str) and fn_name:
|
|
194
|
+
candidates.append(fn_name)
|
|
195
|
+
callback = getattr(func, "callback", None)
|
|
196
|
+
if callback is not None:
|
|
197
|
+
cb_name = getattr(callback, "__name__", "")
|
|
198
|
+
if isinstance(cb_name, str) and cb_name:
|
|
199
|
+
candidates.append(cb_name)
|
|
200
|
+
for cand in candidates:
|
|
201
|
+
if cand and cand != "Command": # skip the click class name
|
|
202
|
+
if cand.startswith("cmd_"):
|
|
203
|
+
cand = cand[4:]
|
|
204
|
+
return cand.replace("_", "-")
|
|
205
|
+
return "<anonymous>"
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def emit_yaml() -> str:
|
|
209
|
+
"""Emit the capability catalog as YAML using the in-tree minimal emitter.
|
|
210
|
+
|
|
211
|
+
Avoids the PyYAML dependency to stay aligned with the rules engine's
|
|
212
|
+
fallback strategy (see roam.rules.engine._emit_simple_yaml).
|
|
213
|
+
"""
|
|
214
|
+
data = REGISTRY.to_dict()
|
|
215
|
+
lines: list[str] = [
|
|
216
|
+
f"schema_version: {data['schema_version']}",
|
|
217
|
+
f"generated_by: {data['generated_by']}",
|
|
218
|
+
f"count: {data['count']}",
|
|
219
|
+
"capabilities:",
|
|
220
|
+
]
|
|
221
|
+
for cap in data["capabilities"]:
|
|
222
|
+
lines.append(f" - name: {cap['name']}")
|
|
223
|
+
lines.append(f" category: {cap['category']}")
|
|
224
|
+
lines.append(f" summary: {_yaml_str(cap['summary'])}")
|
|
225
|
+
if cap["inputs"]:
|
|
226
|
+
lines.append(f" inputs: [{', '.join(_yaml_str(s) for s in cap['inputs'])}]")
|
|
227
|
+
if cap["outputs"]:
|
|
228
|
+
lines.append(f" outputs: [{', '.join(_yaml_str(s) for s in cap['outputs'])}]")
|
|
229
|
+
if cap["examples"]:
|
|
230
|
+
lines.append(" examples:")
|
|
231
|
+
for ex in cap["examples"]:
|
|
232
|
+
lines.append(f" - {_yaml_str(ex)}")
|
|
233
|
+
if cap["tags"]:
|
|
234
|
+
lines.append(f" tags: [{', '.join(_yaml_str(t) for t in cap['tags'])}]")
|
|
235
|
+
lines.append(f" ai_safe: {str(cap['ai_safe']).lower()}")
|
|
236
|
+
lines.append(f" requires_index: {str(cap['requires_index']).lower()}")
|
|
237
|
+
if cap["since"]:
|
|
238
|
+
lines.append(f" since: {_yaml_str(cap['since'])}")
|
|
239
|
+
if cap["deprecated"]:
|
|
240
|
+
lines.append(" deprecated: true")
|
|
241
|
+
lines.append(f" module: {cap['module']}")
|
|
242
|
+
lines.append(f" func_name: {cap['func_name']}")
|
|
243
|
+
return "\n".join(lines) + "\n"
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def _yaml_str(s: str) -> str:
|
|
247
|
+
"""Quote a string for YAML if needed."""
|
|
248
|
+
if any(c in s for c in (':', '#', '\n', '"', "'", '[', ']', '{', '}', ',', '&', '*', '!', '|', '>')):
|
|
249
|
+
return '"' + s.replace('\\', '\\\\').replace('"', '\\"') + '"'
|
|
250
|
+
return s
|
|
@@ -2485,6 +2485,135 @@ def detect_async_blocking_sleep(conn: sqlite3.Connection) -> list[dict]:
|
|
|
2485
2485
|
return results
|
|
2486
2486
|
|
|
2487
2487
|
|
|
2488
|
+
# R5 (2026-05-07) — `asyncio.create_task(coro())` whose return value is
|
|
2489
|
+
# discarded. The task is gc-collected before it runs to completion. The
|
|
2490
|
+
# fix is to either store the task in a long-lived collection or `await`
|
|
2491
|
+
# it. PEP 649 / Python 3.11+ docs explicitly call this a footgun.
|
|
2492
|
+
_RE_FIRE_AND_FORGET_TASK = re.compile(
|
|
2493
|
+
r"^\s*(?:asyncio\.)?create_task\s*\(",
|
|
2494
|
+
re.MULTILINE,
|
|
2495
|
+
)
|
|
2496
|
+
_RE_STORED_TASK = re.compile(
|
|
2497
|
+
r"^\s*(?:\w+\s*[+\-*/]?=\s*|\w+\s*\.\s*append\s*\(\s*|\w+\s*\.\s*add\s*\(\s*|return\s+|await\s+)"
|
|
2498
|
+
r"(?:asyncio\.)?create_task\s*\(",
|
|
2499
|
+
re.MULTILINE,
|
|
2500
|
+
)
|
|
2501
|
+
|
|
2502
|
+
|
|
2503
|
+
def detect_async_fire_and_forget(conn: sqlite3.Connection) -> list[dict]:
|
|
2504
|
+
"""``asyncio.create_task(...)`` whose return value is discarded.
|
|
2505
|
+
|
|
2506
|
+
Background tasks that aren't held in a long-lived reference get
|
|
2507
|
+
garbage-collected before they finish. Python 3.11+ explicitly warns
|
|
2508
|
+
about this footgun. The fix is to store the task somewhere that
|
|
2509
|
+
survives until ``await`` time, or just ``await`` it directly.
|
|
2510
|
+
|
|
2511
|
+
Conservative: Python only, only fires when the line clearly creates
|
|
2512
|
+
a task without storing it.
|
|
2513
|
+
"""
|
|
2514
|
+
try:
|
|
2515
|
+
rows = conn.execute(
|
|
2516
|
+
"SELECT s.id, s.name, s.qualified_name, s.kind, f.path AS file_path, "
|
|
2517
|
+
"s.line_start, s.line_end "
|
|
2518
|
+
"FROM symbols s "
|
|
2519
|
+
"JOIN files f ON s.file_id = f.id "
|
|
2520
|
+
"WHERE s.kind IN ('function', 'method') "
|
|
2521
|
+
"AND f.language = 'python'"
|
|
2522
|
+
).fetchall()
|
|
2523
|
+
except Exception:
|
|
2524
|
+
return []
|
|
2525
|
+
results = []
|
|
2526
|
+
for r in rows:
|
|
2527
|
+
if _is_test_path(r["file_path"]):
|
|
2528
|
+
continue
|
|
2529
|
+
snippet = _read_symbol_source(r["file_path"], r["line_start"], r["line_end"]) or ""
|
|
2530
|
+
if "create_task" not in snippet:
|
|
2531
|
+
continue
|
|
2532
|
+
# Subtract stored-task lines from total create_task occurrences
|
|
2533
|
+
total = len(_RE_FIRE_AND_FORGET_TASK.findall(snippet))
|
|
2534
|
+
stored = len(_RE_STORED_TASK.findall(snippet))
|
|
2535
|
+
leaked = total - stored
|
|
2536
|
+
if leaked <= 0:
|
|
2537
|
+
continue
|
|
2538
|
+
results.append(
|
|
2539
|
+
_finding(
|
|
2540
|
+
"async-fire-and-forget-task",
|
|
2541
|
+
"leaked-asyncio-task",
|
|
2542
|
+
r,
|
|
2543
|
+
f"{leaked} asyncio.create_task call(s) whose return value isn't stored — gc may discard the task before it completes",
|
|
2544
|
+
"high",
|
|
2545
|
+
snippet=snippet,
|
|
2546
|
+
matched_patterns=[
|
|
2547
|
+
f"create_task occurrences: {total}",
|
|
2548
|
+
f"stored: {stored}, leaked: {leaked}",
|
|
2549
|
+
],
|
|
2550
|
+
)
|
|
2551
|
+
)
|
|
2552
|
+
results[-1]["fix"] = "Store the task: `tasks.append(asyncio.create_task(coro()))` and await it later, or `await asyncio.create_task(coro())` directly."
|
|
2553
|
+
return results
|
|
2554
|
+
|
|
2555
|
+
|
|
2556
|
+
# R5 (2026-05-07) — `asyncio.run(...)` inside an async function. This
|
|
2557
|
+
# raises RuntimeError because the event loop is already running. The
|
|
2558
|
+
# fix is to call the coroutine directly with `await` instead.
|
|
2559
|
+
_RE_NESTED_ASYNCIO_RUN = re.compile(
|
|
2560
|
+
r"^\s*(?:asyncio\.)?run\s*\(",
|
|
2561
|
+
re.MULTILINE,
|
|
2562
|
+
)
|
|
2563
|
+
|
|
2564
|
+
|
|
2565
|
+
def detect_async_nested_run(conn: sqlite3.Connection) -> list[dict]:
|
|
2566
|
+
"""``asyncio.run()`` invoked inside another async function.
|
|
2567
|
+
|
|
2568
|
+
``asyncio.run`` creates a new event loop. If one is already running
|
|
2569
|
+
(which it is, inside an async function), this raises ``RuntimeError:
|
|
2570
|
+
asyncio.run() cannot be called from a running event loop``. The fix
|
|
2571
|
+
is to ``await`` the coroutine directly.
|
|
2572
|
+
|
|
2573
|
+
Python only, fires only when the host is async.
|
|
2574
|
+
"""
|
|
2575
|
+
try:
|
|
2576
|
+
rows = conn.execute(
|
|
2577
|
+
"SELECT s.id, s.name, s.qualified_name, s.kind, f.path AS file_path, "
|
|
2578
|
+
"s.line_start, s.line_end "
|
|
2579
|
+
"FROM symbols s "
|
|
2580
|
+
"JOIN files f ON s.file_id = f.id "
|
|
2581
|
+
"WHERE s.kind IN ('function', 'method') "
|
|
2582
|
+
"AND s.is_async = 1 "
|
|
2583
|
+
"AND f.language = 'python'"
|
|
2584
|
+
).fetchall()
|
|
2585
|
+
except Exception:
|
|
2586
|
+
return []
|
|
2587
|
+
results = []
|
|
2588
|
+
for r in rows:
|
|
2589
|
+
if _is_test_path(r["file_path"]):
|
|
2590
|
+
continue
|
|
2591
|
+
snippet = _read_symbol_source(r["file_path"], r["line_start"], r["line_end"]) or ""
|
|
2592
|
+
if "asyncio.run(" not in snippet:
|
|
2593
|
+
continue
|
|
2594
|
+
# Heuristic: must be `asyncio.run(` (not `await asyncio.run(`); the
|
|
2595
|
+
# latter is also wrong but caught by other linters more reliably.
|
|
2596
|
+
match_count = snippet.count("asyncio.run(")
|
|
2597
|
+
if match_count == 0:
|
|
2598
|
+
continue
|
|
2599
|
+
results.append(
|
|
2600
|
+
_finding(
|
|
2601
|
+
"async-nested-run",
|
|
2602
|
+
"asyncio-run-in-async",
|
|
2603
|
+
r,
|
|
2604
|
+
"asyncio.run() invoked inside an async function — raises RuntimeError at runtime (loop already running)",
|
|
2605
|
+
"high",
|
|
2606
|
+
snippet=snippet,
|
|
2607
|
+
matched_patterns=[
|
|
2608
|
+
"is_async = 1",
|
|
2609
|
+
f"asyncio.run( occurrences: {match_count}",
|
|
2610
|
+
],
|
|
2611
|
+
)
|
|
2612
|
+
)
|
|
2613
|
+
results[-1]["fix"] = "Replace `asyncio.run(coro())` with `await coro()` — you're already inside an event loop."
|
|
2614
|
+
return results
|
|
2615
|
+
|
|
2616
|
+
|
|
2488
2617
|
# X2 (2026-05-06) — Python: `except Exception:` / `except BaseException:`
|
|
2489
2618
|
# without `raise` is the canonical "swallowing bug" pattern. Catches
|
|
2490
2619
|
# KeyboardInterrupt, MemoryError, SystemExit silently. The fix is to
|
|
@@ -3927,6 +4056,8 @@ _MATH_DETECTORS = [
|
|
|
3927
4056
|
("io-in-loop", "loop-query", detect_io_in_loop),
|
|
3928
4057
|
("serial-await-loop", "for-of-await", detect_serial_await_loop),
|
|
3929
4058
|
("async-blocking-sleep", "blocking-call-in-async", detect_async_blocking_sleep),
|
|
4059
|
+
("async-fire-and-forget-task", "leaked-asyncio-task", detect_async_fire_and_forget),
|
|
4060
|
+
("async-nested-run", "asyncio-run-in-async", detect_async_nested_run),
|
|
3930
4061
|
("broad-except-swallow", "swallow-exception", detect_broad_except_swallow),
|
|
3931
4062
|
("spread-accumulator", "spread-rebind", detect_spread_accumulator),
|
|
3932
4063
|
("defer-in-loop", "loop-defer", detect_defer_in_loop),
|
|
@@ -584,6 +584,52 @@ CATALOG: dict[str, dict] = {
|
|
|
584
584
|
},
|
|
585
585
|
],
|
|
586
586
|
},
|
|
587
|
+
"async-fire-and-forget-task": {
|
|
588
|
+
"name": "asyncio.create_task() whose return value is discarded",
|
|
589
|
+
"category": "concurrency",
|
|
590
|
+
"kind": "algorithm",
|
|
591
|
+
"ways": [
|
|
592
|
+
{
|
|
593
|
+
"id": "store-task-reference",
|
|
594
|
+
"name": "Store the task in a long-lived collection",
|
|
595
|
+
"time": "n/a",
|
|
596
|
+
"space": "O(N tasks)",
|
|
597
|
+
"rank": 1,
|
|
598
|
+
"tip": "Capture the task: `tasks.append(asyncio.create_task(coro()))` and `await asyncio.gather(*tasks)` later. Or `await asyncio.create_task(coro())` directly for fire-and-await.",
|
|
599
|
+
},
|
|
600
|
+
{
|
|
601
|
+
"id": "leaked-asyncio-task",
|
|
602
|
+
"name": "Leaked asyncio.create_task — gc may discard before completion",
|
|
603
|
+
"time": "n/a",
|
|
604
|
+
"space": "O(1) — task object eligible for gc",
|
|
605
|
+
"rank": 10,
|
|
606
|
+
"tip": "",
|
|
607
|
+
},
|
|
608
|
+
],
|
|
609
|
+
},
|
|
610
|
+
"async-nested-run": {
|
|
611
|
+
"name": "asyncio.run() invoked inside an async function",
|
|
612
|
+
"category": "concurrency",
|
|
613
|
+
"kind": "algorithm",
|
|
614
|
+
"ways": [
|
|
615
|
+
{
|
|
616
|
+
"id": "await-the-coroutine",
|
|
617
|
+
"name": "await the coroutine directly",
|
|
618
|
+
"time": "non-blocking",
|
|
619
|
+
"space": "O(1)",
|
|
620
|
+
"rank": 1,
|
|
621
|
+
"tip": "Replace `asyncio.run(coro())` with `await coro()` — you're already inside an event loop.",
|
|
622
|
+
},
|
|
623
|
+
{
|
|
624
|
+
"id": "asyncio-run-in-async",
|
|
625
|
+
"name": "asyncio.run inside async — RuntimeError at runtime",
|
|
626
|
+
"time": "raises immediately",
|
|
627
|
+
"space": "n/a",
|
|
628
|
+
"rank": 10,
|
|
629
|
+
"tip": "",
|
|
630
|
+
},
|
|
631
|
+
],
|
|
632
|
+
},
|
|
587
633
|
"serial-await-loop": {
|
|
588
634
|
"name": "Serial `await` inside loop (Promise.all opportunity)",
|
|
589
635
|
"category": "concurrency",
|
|
@@ -86,6 +86,9 @@ _COMMANDS = {
|
|
|
86
86
|
"permit": ("roam.commands.cmd_permit", "permit_cmd"),
|
|
87
87
|
"postmortem": ("roam.commands.cmd_postmortem", "postmortem_cmd"),
|
|
88
88
|
"article-12-check": ("roam.commands.cmd_article_12_check", "article_12_check_cmd"),
|
|
89
|
+
"capabilities": ("roam.commands.cmd_capabilities", "capabilities_cmd"),
|
|
90
|
+
"skill-generate": ("roam.commands.cmd_skill_generate", "skill_generate_cmd"),
|
|
91
|
+
"compare": ("roam.commands.cmd_compare", "compare_cmd"),
|
|
89
92
|
"guard": ("roam.commands.cmd_guard", "guard"),
|
|
90
93
|
"init": ("roam.commands.cmd_init", "init"),
|
|
91
94
|
"config": ("roam.commands.cmd_config", "config"),
|
|
@@ -290,6 +293,9 @@ _CATEGORIES = {
|
|
|
290
293
|
"audit-trail-export",
|
|
291
294
|
"audit-trail-conformance-check",
|
|
292
295
|
"article-12-check",
|
|
296
|
+
"capabilities",
|
|
297
|
+
"skill-generate",
|
|
298
|
+
"compare",
|
|
293
299
|
"dogfood",
|
|
294
300
|
"suppress",
|
|
295
301
|
"pr-diff",
|
|
@@ -295,6 +295,23 @@ def _render_pdf_report(markdown_text: str, output_path: Path) -> bool:
|
|
|
295
295
|
return True
|
|
296
296
|
|
|
297
297
|
|
|
298
|
+
from roam.capability import roam_capability
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
@roam_capability(
|
|
302
|
+
category="compliance",
|
|
303
|
+
summary="EU AI Act Article 12 readiness assessment — 6-item checklist over the current repo.",
|
|
304
|
+
inputs=["repo_path"],
|
|
305
|
+
outputs=["readiness_score", "checklist_results", "markdown_report"],
|
|
306
|
+
examples=[
|
|
307
|
+
"roam article-12-check",
|
|
308
|
+
"roam article-12-check --pdf report.pdf",
|
|
309
|
+
],
|
|
310
|
+
tags=["compliance", "eu-ai-act", "audit", "phase0"],
|
|
311
|
+
ai_safe=True,
|
|
312
|
+
requires_index=False,
|
|
313
|
+
since="12.40",
|
|
314
|
+
)
|
|
298
315
|
@click.command(name="article-12-check")
|
|
299
316
|
@click.option(
|
|
300
317
|
"--output",
|