sourcecode 4.10.5__tar.gz → 4.10.7__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.
- {sourcecode-4.10.5 → sourcecode-4.10.7}/CHANGELOG.md +245 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/PKG-INFO +15 -6
- {sourcecode-4.10.5 → sourcecode-4.10.7}/README.md +14 -5
- {sourcecode-4.10.5 → sourcecode-4.10.7}/pyproject.toml +1 -1
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/__init__.py +1 -1
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/architectural_baseline.py +80 -1
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/cache.py +8 -3
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/cache_model.py +109 -45
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/canonical_ir.py +2 -1
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/change_plan.py +51 -11
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/cli.py +676 -106
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/compare.py +91 -11
- sourcecode-4.10.7/src/sourcecode/container_wiring.py +315 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/context_cache.py +63 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/data_exposure.py +27 -1
- sourcecode-4.10.7/src/sourcecode/detach.py +155 -0
- sourcecode-4.10.7/src/sourcecode/execution_plan.py +428 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/non_coverage.py +54 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/output_budget.py +26 -3
- sourcecode-4.10.7/src/sourcecode/output_encoding.py +51 -0
- sourcecode-4.10.7/src/sourcecode/phased_run.py +210 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/posture.py +3 -3
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/pr_impact.py +69 -2
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/prepare_context.py +38 -4
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/progress.py +60 -6
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/remedies.py +37 -5
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/repository_ir.py +100 -3
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/runs.py +8 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/security_posture.py +29 -1
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/serializer.py +19 -1
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/servlet_surface.py +17 -1
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/spring_impact.py +38 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/spring_security_audit.py +21 -5
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/verify_repo.py +2 -2
- {sourcecode-4.10.5 → sourcecode-4.10.7}/.github/workflows/build-windows.yml +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/.gitignore +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/.ruff.toml +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/CLAUDE.md +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/CONTRIBUTING.md +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/LICENSE +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/SECURITY.md +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/raw +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/scripts/compare_integration_engines.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/scripts/customer_smoke_test.sh +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/scripts/generate_jdk_exports.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/scripts/perf_harness.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/adaptive_scanner.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/archetype.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/architectural_delta.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/architecture_analyzer.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/architecture_summary.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/ast_extractor.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/audit_report.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/baseline_autocapture.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/call_surface.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/caller_metrics.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/caller_reach.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/chain_rules.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/cir_graphs.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/classifier.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/client_calls.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/code_notes_analyzer.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/confidence_analyzer.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/constraint_diff.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/context_graph.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/context_scorer.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/context_summarizer.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/contract_diff.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/contract_init.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/contract_model.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/contract_pipeline.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/coverage_parser.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/data_labels.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/defect_identity.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/degradation.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/dependency_analyzer.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/deployment_prefix.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/__init__.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/base.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/csproj_parser.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/dart.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/dotnet.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/elixir.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/go.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/heuristic.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/hybrid.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/java.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/jvm_ext.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/nodejs.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/parsers.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/php.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/project.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/python.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/ruby.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/rust.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/systems.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/terraform.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/detectors/tooling.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/doc_analyzer.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/dynamic_argument_surface.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/endpoint_literals.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/endpoint_metrics.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/entrypoint_classifier.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/env_analyzer.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/envelope.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/environment_resolution.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/error_schema.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/evidence_provider.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/explain.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/facts/__init__.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/facts/registry.json +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/file_chunker.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/file_classifier.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/filter_surface.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/format_contract.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/fqn_utils.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/git_analyzer.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/git_checkout.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/graph_analyzer.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/graph_evidence.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/hibernate_strat.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/identity_fallback.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/integration_coordinates.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/jdk_exports.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/license.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/mcp/__init__.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/mcp/onboarding/__init__.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/mcp/onboarding/applier.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/mcp/onboarding/backup.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/mcp/onboarding/detector.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/mcp/onboarding/planner.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/mcp/orchestrator.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/mcp/registry.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/mcp/runner.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/mcp/server.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/mcp_nudge.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/metrics_analyzer.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/migrate_check.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/migration_blast.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/openapi_surface.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/openrewrite_recipe.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/parse_cache.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/path_admission.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/path_filters.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/perf.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/pipe_contract.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/pr_comment_renderer.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/provenance.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/ranking_engine.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/readiness_timeline.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/reconciliation.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/redactor.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/reference_facts.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/release_info.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/relevance_scorer.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/rename_refactor.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/repo_classifier.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/__init__.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/context.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/errors.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/executor.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/planner.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/query.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/request.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/resolution.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/result.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/retriever.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/runtime.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/steps.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/steps_endpoint.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/steps_graph.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/steps_impact.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/steps_intf.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/steps_struct.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/retrieval/steps_txsec.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/ris.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/risk.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/rule_catalog.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/runtime_classifier.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/sarif.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/scanner.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/schema.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/schemas/envelope-v1.schema.json +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/security_config.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/security_config_scan.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/semantic_analyzer.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/semantic_impact_engine.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/semantic_integration_engine.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/semantic_services.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/source_text.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/spring_event_topology.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/spring_findings.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/spring_model.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/spring_profiles.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/spring_properties.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/spring_semantic.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/spring_tx_analyzer.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/summarizer.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/target_admission.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/telemetry/__init__.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/telemetry/config.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/telemetry/consent.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/telemetry/events.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/telemetry/filters.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/telemetry/transport.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/test_gap_ranking.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/test_sources.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/text_input.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/token_estimate.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/tree_utils.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/type_usage_surface.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/validation_inference.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/validation_surface.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/verify_edit.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/verify_rules.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/version_check.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/src/sourcecode/workspace.py +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/supabase/functions/README.md +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/supabase/functions/get-license/index.ts +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/supabase/functions/lemonsqueezy-webhook/index.ts +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/supabase/functions/telemetry/index.ts +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/supabase/sql/license_event_ordering.sql +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/supabase/sql/licensing_schema.sql +0 -0
- {sourcecode-4.10.5 → sourcecode-4.10.7}/supabase/sql/telemetry_events.sql +0 -0
|
@@ -2,6 +2,251 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [4.10.7] — 2026-08-07
|
|
6
|
+
|
|
7
|
+
**Tier D, and with it the M13 bug queue.** Five ledger rows close (C4-17 · C4-18 ·
|
|
8
|
+
C4-19 · C4-20 · C4-21), one commit each, all of them discoverability: none was
|
|
9
|
+
publishing a false claim, and together they are the ergonomics score two field
|
|
10
|
+
evaluations put at 5/10. What remains of the queue is a *measurement*, not a fix —
|
|
11
|
+
the C3-53 re-run on Windows under an agent harness, which is written the same way
|
|
12
|
+
in the ledger and in the 4.10.6 entry below.
|
|
13
|
+
|
|
14
|
+
⚠ **Three behaviour changes to read before upgrading a pipeline:**
|
|
15
|
+
|
|
16
|
+
- **`ask cache status --json` renames `cores` to `cached_cores`.** It always
|
|
17
|
+
counted cached core entries; `cores` is what a captured baseline calls the
|
|
18
|
+
machine's CPU count (C4-18).
|
|
19
|
+
- **`--output/-o` is now accepted after every command that publishes `--copy`**,
|
|
20
|
+
including eleven that refused it. On those the answer goes to the file and
|
|
21
|
+
stdout carries one `Written to <path>` line (C4-17).
|
|
22
|
+
- **`--detach` accepts every repository-wide and deep command**, not the six that
|
|
23
|
+
happened to be listed in a hand-kept table. `posture`, `modernize`, `repo-ir`
|
|
24
|
+
and `verify-edit` — four of the commands the field could not run in a session —
|
|
25
|
+
could not be detached before this release (C4-19).
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
|
|
29
|
+
- **`ask --help` orders its front page by what will run on the repository being
|
|
30
|
+
read** (C4-19). *Start here* was, on the field repository, exactly the set of
|
|
31
|
+
commands that could not run there — four of five unrunnable in one evaluation,
|
|
32
|
+
three of five killing the session in the next. The help now measures the scope
|
|
33
|
+
(a capped tree walk plus two stat calls, paid only when help is what was asked
|
|
34
|
+
for) and groups the entries into **Runs now**, **Warm the cache first** and
|
|
35
|
+
**Too big for this session — `--output <file> --detach`**. What it deliberately
|
|
36
|
+
does not do is project a duration: `spring-audit` is 8.8 s on the 2 000-file
|
|
37
|
+
reference and was measured at 408 s on 3 342 files, so a scaled estimate would
|
|
38
|
+
be a confident falsehood; the class and the measured anchors are published
|
|
39
|
+
instead, and a command measured fast at field size (`endpoints`, 4.2 s) stays
|
|
40
|
+
on the fast list whatever its class. `--detach` accepts every repository-wide
|
|
41
|
+
and deep command now, not the six that happened to be in a hand-kept table:
|
|
42
|
+
`posture`, `modernize`, `repo-ir` and `verify-edit` were on the field's blocked
|
|
43
|
+
list and could not be detached.
|
|
44
|
+
- **A remedy is checked against the repository it is printed on** (C4-20).
|
|
45
|
+
`plan` pointed an unresolved symbol at `ask repo-ir`, and `onboard` named
|
|
46
|
+
`ask posture --profile <set>` as the authority — both correct, and neither
|
|
47
|
+
finished in an interactive session on the repository whose answer named them.
|
|
48
|
+
Every remedy block (`posture`, `data-exposure`, `verify`, the security-surface
|
|
49
|
+
limitation, the unresolved-target message) now carries `how_to_run_here` when
|
|
50
|
+
there is something to say: run it detached, or warm the cache first. Nothing is
|
|
51
|
+
added where the command runs in the foreground, and nothing is guessed where
|
|
52
|
+
the scope is unknown.
|
|
53
|
+
- **`--output/-o` works after every command that produces an answer** (C4-17).
|
|
54
|
+
It was a per-command decision, and the decisions disagreed: `endpoints`,
|
|
55
|
+
`validation` and `data-exposure` accepted it after the command, `baseline
|
|
56
|
+
capture` refused it — while its own siblings `baseline diff` and `baseline
|
|
57
|
+
trend` accepted it — and the refusal's hint blamed the placement rather than
|
|
58
|
+
the gap. The rule is now one line with its population taken from the CLI
|
|
59
|
+
registry: **a command that publishes `--copy` publishes `--output`**. Eleven
|
|
60
|
+
commands gained it (`version`, `baseline capture`, `cache status/warm/model/
|
|
61
|
+
freshness/context-stats`, `auth status`, `mcp status`, `mcp list-tools`,
|
|
62
|
+
`telemetry status`); on those the answer goes to the file and stdout carries
|
|
63
|
+
only `Written to <path>`. The hint for a genuinely global flag typed after a
|
|
64
|
+
subcommand was corrected with it: it said *"it goes before the command"*, which
|
|
65
|
+
is a placement that does nothing, since the root analysis is skipped as soon as
|
|
66
|
+
a subcommand is invoked.
|
|
67
|
+
- **`ask config` lists the repository's own declaration** (C4-21). `data-exposure`
|
|
68
|
+
answers `answered: false` until `sourcecode.config.json` declares which types
|
|
69
|
+
and fields are sensitive — the right refusal, since a label is a judgement
|
|
70
|
+
about a domain and is never inferred — but nothing afterwards said whether the
|
|
71
|
+
file had been picked up, so the last step of the cold start was a guess.
|
|
72
|
+
`ask config [path]` now resolves that file and reports its path, the labels
|
|
73
|
+
read from it, the custom security annotations, and any declaration that could
|
|
74
|
+
not be used; when it is absent, the path it looked at and the answer that
|
|
75
|
+
absence produces. The `data-exposure` refusal points at it (`declare.confirm`).
|
|
76
|
+
- **`cache status` no longer calls a cache count `Cores:`** (C4-18). The line
|
|
77
|
+
counted `core-*.json.gz` entries under the field name a captured baseline uses
|
|
78
|
+
for the machine's CPU count (`env: {cores: 20}` on the same machine, same
|
|
79
|
+
scope, minutes apart), and it sat beside `Views: 0 / CAS blobs: 0`, so
|
|
80
|
+
`Cores: 0` read as *the cache is empty* rather than *no core entries yet*. The
|
|
81
|
+
text line is `Cached cores: N entries` and the JSON key is `cached_cores`.
|
|
82
|
+
**Behaviour change for consumers of `ask cache status --json`: the `cores` key
|
|
83
|
+
is gone, replaced by `cached_cores`** — one fact, one name.
|
|
84
|
+
|
|
85
|
+
## [4.10.6] — 2026-08-07
|
|
86
|
+
|
|
87
|
+
The M13 sanitation queue, tiers A through C plus the claims tier: **eighteen ledger
|
|
88
|
+
rows close** (C1-36 · C1-37 · C1-38 · C1-39 · C1-40 · C2-27 · C2-28 · C2-29 ·
|
|
89
|
+
C3-53 · C3-54 part 3 · C3-55 · C3-61 · C3-65 · C3-66 · C3-67 · C3-68 · C3-69 ·
|
|
90
|
+
CL-16), against the two independent field evaluations of 4.10.4 and 4.10.5 that
|
|
91
|
+
agreed on the diagnosis and disagreed on nothing material. No feature ships here:
|
|
92
|
+
the owner directive for this milestone is that every bug is sanitated before the
|
|
93
|
+
first feature starts.
|
|
94
|
+
|
|
95
|
+
⚠ **Five behaviour changes to read before upgrading a pipeline.** All five are the
|
|
96
|
+
fix working, and three of them can move a gate:
|
|
97
|
+
|
|
98
|
+
- **`pr-impact`, `impact`, `impact-chain`, `plan` and `compare` now floor the
|
|
99
|
+
verdict at `HIGH` when the change touches a component the container invokes** —
|
|
100
|
+
a `@Configuration`, an `@Aspect`, a `Filter`, a `@ControllerAdvice`, a bean
|
|
101
|
+
resolved through an interface something injects, `web.xml`,
|
|
102
|
+
`application*.y*ml`. A gate that was passing green over a security-config diff
|
|
103
|
+
will start failing, with the verdict that diff always deserved (C1-36).
|
|
104
|
+
- **`ASK_MAX_ANALYSIS_SECONDS` is honoured instead of vetoed.** A value below the
|
|
105
|
+
class floor no longer refuses to run: it warns and runs, and a run that spends
|
|
106
|
+
its budget publishes what it measured with `partial: true`. `--ci` fails on a
|
|
107
|
+
partial answer (C3-55, C3-54 part 3).
|
|
108
|
+
- **`ask endpoints --servlets` answers with the servlet population only**, plus
|
|
109
|
+
the endpoint total as one number. A consumer that read `endpoints[]` out of that
|
|
110
|
+
document has to call `ask endpoints` for it (C3-65).
|
|
111
|
+
- **`ask plan` publishes `null`, not `0`, for anything it did not measure** — an
|
|
112
|
+
unresolved target, or `covering_tests` in a repository with no test source root.
|
|
113
|
+
A consumer coercing those to `int` needs to handle `null` (C1-39).
|
|
114
|
+
- **`baseline capture` no longer records the machine by default** (`cpu`, `cores`,
|
|
115
|
+
`hostname_hash`); `--record-env` restores it. A comparison keyed on those fields
|
|
116
|
+
needs the flag (C3-68).
|
|
117
|
+
|
|
118
|
+
`posture` moves from `experimental` to `supported` (CL-16).
|
|
119
|
+
|
|
120
|
+
### Fixed
|
|
121
|
+
|
|
122
|
+
- **A component the container calls is not a component nothing calls** (C1-36).
|
|
123
|
+
*The one blind spot this product did not declare, reproduced on two builds by
|
|
124
|
+
two evaluations.* Blast radius is projected over the call graph, so a class the
|
|
125
|
+
framework invokes has fan-in ~0 and every figure derived from it reads as no
|
|
126
|
+
impact: a diff over the filter chain, the aspect gating 935 routes and the
|
|
127
|
+
production password encoder published `LOW / "No high-risk signals detected" /
|
|
128
|
+
affected_endpoints: []`, while a plain POJO in the same repository published
|
|
129
|
+
`CRITICAL` with 3 382 endpoints. The fan-in figure was never wrong; using it as
|
|
130
|
+
a risk proxy on that population was. `container_wiring.py` answers the one
|
|
131
|
+
question that separates them, from facts the CIR already carries — the role it
|
|
132
|
+
assigns, the interception annotations and supertypes fixed by published
|
|
133
|
+
specifications, and one route that consults no name at all: *the class
|
|
134
|
+
implements an interface something injects and has zero incoming call edges*,
|
|
135
|
+
which catches a password encoder without anyone naming one. Wired at the single
|
|
136
|
+
blast-radius authority so the four commands that disagreed now answer from one
|
|
137
|
+
place. The verdict is floored, never lowered; the population is published with
|
|
138
|
+
its evidence; and **NC-010** states the limit in the payload, the README and the
|
|
139
|
+
help.
|
|
140
|
+
- **A killed analysis keeps what it measured** (C3-54 part 3). `phased_run.py`
|
|
141
|
+
gives a long command a declared phase list and a durable checkpoint after each
|
|
142
|
+
phase, written through the same fsynced, atomic seam as the final answer and
|
|
143
|
+
removed only once the complete answer is on disk — so a teardown leaves the
|
|
144
|
+
better of the two files and never neither. A checkpoint can never pass for a
|
|
145
|
+
finished answer: `partial: true`, `phases_completed`, `phases_pending`,
|
|
146
|
+
`why_stopped`. The field lost 6,8 minutes of CPU and every recoverable byte
|
|
147
|
+
four times.
|
|
148
|
+
- **A budget that is set is honoured** (C3-55). Below the class floor was refused
|
|
149
|
+
and above it admitted a run that outlived the session, so no value was both
|
|
150
|
+
accepted and survivable on the variable the help presents as the CI control.
|
|
151
|
+
The floor is advice printed before the work; the budget stops the run between
|
|
152
|
+
phases; counts in a partial answer are a floor over the phases that completed
|
|
153
|
+
and say so.
|
|
154
|
+
- **A repository-wide run can outlive its shell** (C3-53, survivable half).
|
|
155
|
+
`--detach` (with `--output`) starts the analysis in a process that leads its own
|
|
156
|
+
session and, on Windows, carries `CREATE_BREAKAWAY_FROM_JOB` — the documented
|
|
157
|
+
way out of the parent shell's job object, which is what killed even
|
|
158
|
+
`Start-Process -NoNewWindow` and all six of its children at the same second the
|
|
159
|
+
session died. When a platform refuses the breakaway the envelope says so rather
|
|
160
|
+
than implying a guarantee it does not have. **Not closed:** the field case is
|
|
161
|
+
Windows under an agent harness, and only a Windows re-run proves the tree
|
|
162
|
+
survives there.
|
|
163
|
+
- **`--servlets` answers with the population it names** (C3-65). The flag read as
|
|
164
|
+
a filter and behaved as an aggregator: 1,8 MB to stdout, the useful signal at
|
|
165
|
+
0,08 % of the bytes, at line 49 622 of 49 730 — and the agent session that asked
|
|
166
|
+
for it died. Every servlet row also carries `population: "servlet"`, so a
|
|
167
|
+
consumer iterating rows finally sees a servlet after passing the flag built to
|
|
168
|
+
show them.
|
|
169
|
+
- **`compare` no longer ranks the repository first** (C3-67). A candidate that
|
|
170
|
+
resolves to an existing directory is published as `resolved: false` /
|
|
171
|
+
`not_a_candidate` and ranks last. `ask compare A B .` used to rank the `.`
|
|
172
|
+
first, with 3 574 endpoints and 3 342 rollback files as its cost.
|
|
173
|
+
- **`secured_endpoints` published a display cap as a measurement** (C1-38). The
|
|
174
|
+
`15` that reconciled with nothing was `min(real, 15)`: the count was `len()` of
|
|
175
|
+
a truncated 15-row sample. The population is counted before the cut, the list is
|
|
176
|
+
still sampled, and the omission is published with its `cap_effect`. All four
|
|
177
|
+
figures that share the name now carry their unit and name the other three.
|
|
178
|
+
- **Four figures called "endpoints" each say what they counted** (C1-37), and the
|
|
179
|
+
baseline stopped disagreeing with itself: `totals.endpoints` counts handler
|
|
180
|
+
mappings, `totals.endpoint_contract_pairs` counts the distinct (METHOD, path)
|
|
181
|
+
pairs `endpoint_surface` lists, and the battery holds the invariant between the
|
|
182
|
+
second and the list — an invariant that is only checkable because the two
|
|
183
|
+
figures finally describe two things.
|
|
184
|
+
- **What was not measured is `null`, never `0`** (C1-39), in `plan` and in
|
|
185
|
+
`covering_tests` on a repository with no test source root. The shape
|
|
186
|
+
`data-exposure` already had, one level up.
|
|
187
|
+
- **`cache model` promised a hit the command does not store** (C1-40). Measured on
|
|
188
|
+
keycloak: **with** a warm, `onboard` costs 0,7 s; **without** one, a second
|
|
189
|
+
identical run costs 9,4 s against 10,2 s cold. `repeat` is now false for
|
|
190
|
+
`onboard`, with the figures published at two scales.
|
|
191
|
+
- **A local artefact is not committable by accident** (C3-68). `.ask/` gets its own
|
|
192
|
+
`.gitignore` the moment it is created — self-confined, never touching the user's
|
|
193
|
+
own, never overwriting one they edited — and `env` records only the two fields
|
|
194
|
+
that decide comparability.
|
|
195
|
+
- **A heartbeat does not make a successful run look failed** (C3-66).
|
|
196
|
+
`ASK_PROGRESS` takes `1`/`stderr`, `off` and `file:<path>`; the file form leaves
|
|
197
|
+
stderr empty, so a PowerShell job can watch a six-minute run and still trust
|
|
198
|
+
`$?`. No setting writes to stdout.
|
|
199
|
+
- **Fix the decoder, not the bytes** (C3-69). `SetConsoleOutputCP(65001)` at entry
|
|
200
|
+
tells the Windows console to read the UTF-8 we were always writing; only when
|
|
201
|
+
that fails does the emit seam escape the payload to ASCII. One decision, made
|
|
202
|
+
once, read by every emit seam.
|
|
203
|
+
- **A budget note that contradicts the summary beside it** (C2-27). The unit is
|
|
204
|
+
bytes, so `29KB → 29KB` beside `total_omitted_items: 10` cannot recur, and both
|
|
205
|
+
the note and `_truncation_summary.applies_to` state that trimming describes the
|
|
206
|
+
stdout rendering — `--output` writes the answer untrimmed.
|
|
207
|
+
- **Git churn is not evidence about semantics** (C2-29). When the symptom names
|
|
208
|
+
something this repository contains, activity signals contribute nothing to the
|
|
209
|
+
`fix-bug` rank and are reported as context; when nothing resolves they still
|
|
210
|
+
rank, published as correlational rather than as triage.
|
|
211
|
+
- **A limit is stated once and referenced** (C2-28). `NC-007` was emitted twice,
|
|
212
|
+
byte for byte, in the heaviest payload the tool produces.
|
|
213
|
+
|
|
214
|
+
### Performance
|
|
215
|
+
|
|
216
|
+
- **The rule pass was never mostly rules** (C3-61, second measurement).
|
|
217
|
+
Re-profiled after the pre-filter shipped: `infer_security_posture` ran **twice**
|
|
218
|
+
per audit — once to learn the custom-gate tokens the rules match on, once to
|
|
219
|
+
publish the posture block — at ~2,1 s each, each rebuilding the filter surface
|
|
220
|
+
and re-walking the tree underneath it; and `_proxy_bypass` scanned every
|
|
221
|
+
admissible source for methods twice. Both are identities and both are fixed as
|
|
222
|
+
identities. **keycloak 6,17 s → 4,07 s, 90 findings before and after, payload
|
|
223
|
+
identical except `generated_at` and `analysis_time_ms`.** No threads and no
|
|
224
|
+
processes: parallelising would have bought ~15 % of a wall clock now dominated
|
|
225
|
+
by the CIR build (12,6 s warm against 4,1 s for the whole rule pass), which is
|
|
226
|
+
F-AA's problem and not this row's.
|
|
227
|
+
- **Deciding whether a cached context is still valid no longer deserialises it**
|
|
228
|
+
(C1-40, second half). The validity keys live in an uncompressed sidecar beside
|
|
229
|
+
the blob; the field measured 1 029 ms average / 1 955 ms p95 to read three short
|
|
230
|
+
strings out of a 10 MB envelope, and an entry invalidated by a changed signature
|
|
231
|
+
paid all of it before discarding the result.
|
|
232
|
+
|
|
233
|
+
### Changed
|
|
234
|
+
|
|
235
|
+
- `posture` is `supported`, not `experimental` (CL-16). It is the one command
|
|
236
|
+
neither field evaluation found a competitor for, and it produced 2 of
|
|
237
|
+
evaluation #15's 3 CRITICAL findings.
|
|
238
|
+
- `pr-impact` keeps its `core` tier because C1-36's silent half is closed: it can
|
|
239
|
+
now keep the promise that tier makes.
|
|
240
|
+
|
|
241
|
+
### Still open from this queue
|
|
242
|
+
|
|
243
|
+
`C4-17` (`--output` accepted postfix on some subcommands, absent on others),
|
|
244
|
+
`C4-19` (a scope-aware `--help` ordered by what can actually run), `C4-20`
|
|
245
|
+
(suggested next commands checked against the cost model before printing), `C4-21`
|
|
246
|
+
(`ask config` listing the label source it resolved) and `C4-18` (`cache status`
|
|
247
|
+
printing `Cores:` for a cache count). All five are discoverability; none of them
|
|
248
|
+
publishes a false claim.
|
|
249
|
+
|
|
5
250
|
## [4.10.5] — 2026-08-07
|
|
6
251
|
|
|
7
252
|
Second release of the field-evaluation #13 queue. Three rows close and one closes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sourcecode
|
|
3
|
-
Version: 4.10.
|
|
3
|
+
Version: 4.10.7
|
|
4
4
|
Summary: Persistent structural context and ultra-fast repeated analysis for AI coding agents
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Keywords: agents,ai,codebase,context,developer-tools,llm
|
|
@@ -42,7 +42,7 @@ Description-Content-Type: text/markdown
|
|
|
42
42
|
|
|
43
43
|
**Context · Impact · Migration · Architecture · Review — everything from one structural model.**
|
|
44
44
|
|
|
45
|
-

|
|
46
46
|

|
|
47
47
|
|
|
48
48
|
> **ASK Engine** is the product. The CLI command is **`ask`**. The legacy **`sourcecode`**
|
|
@@ -106,7 +106,7 @@ brew tap haroundominique/sourcecode && brew install sourcecode
|
|
|
106
106
|
# pip / pipx
|
|
107
107
|
pipx install sourcecode # or: pip install sourcecode
|
|
108
108
|
|
|
109
|
-
ask version # ask 4.10.
|
|
109
|
+
ask version # ask 4.10.7 — and, on a build that has aged,
|
|
110
110
|
# how many releases have probably shipped since
|
|
111
111
|
```
|
|
112
112
|
|
|
@@ -299,7 +299,7 @@ experimental: both are true, and they are two different facts.
|
|
|
299
299
|
|---|---|---|
|
|
300
300
|
| **core** | contract stable within a major — safe to gate CI on | `endpoints` · `spring-audit` · `migrate-check` · `impact` · `impact-chain` · `pr-impact` · `verify` |
|
|
301
301
|
| **supported** | maintained; fields are added, never removed without a major | every command not named in another row |
|
|
302
|
-
| **experimental** | shape may change in a minor — do not gate CI on it | `risk` · `enrich` · `audit-report` · `data-exposure` · `migrate-recipe` · `
|
|
302
|
+
| **experimental** | shape may change in a minor — do not gate CI on it | `risk` · `enrich` · `audit-report` · `data-exposure` · `migrate-recipe` · `archetype` |
|
|
303
303
|
| **parked** | kept working, no longer developed | `retrieve` |
|
|
304
304
|
|
|
305
305
|
The same table is printed by `ask --help`, and both are generated from one authority
|
|
@@ -315,7 +315,7 @@ from it.
|
|
|
315
315
|
|
|
316
316
|
| Command | Tier | Answers | Note |
|
|
317
317
|
|---|---|---|---|
|
|
318
|
-
| `posture` |
|
|
318
|
+
| `posture` | supported | which beans a profile set wires, and how effective endpoint access differs between two sets | the most differentiated capability here |
|
|
319
319
|
| `risk` | experimental | what each defect actually costs, once reach, access, write effect and the shape of the input path are in it | `defect_severity × reachability × auth_verdict × write_effect × query_construction × input_constraints`; every factor names its authority; `--table --rule SEC-008 --band high --top-n 20` gives audit triage without `jq` |
|
|
320
320
|
| `enrich` | experimental | another scanner's SARIF findings, ranked by what this repository does with them | `--sarif <log>`; same composition as `risk`, with `--table --rule <id> --band high --top-n 20` for triage |
|
|
321
321
|
| `audit-report` | experimental | human audit bundle over existing `risk` + `posture` evidence, optionally signed | includes `evidence_manifest` claim provenance; `--format markdown`; `--sign-key <file>` signs canonical JSON with HMAC-SHA256 |
|
|
@@ -398,6 +398,12 @@ And one about who calls a route:
|
|
|
398
398
|
|---|---|---|
|
|
399
399
|
| **Whether a route is called from outside this repository — another service, a mobile app, a partner, a cron job, or a client whose URL is assembled at run time.** | The join reads the TypeScript/JavaScript checked in beside the server and only the call shapes whose verb and path are written at the call site. That is a floor on who calls a route and can never be a ceiling: the repository cannot observe consumers it does not contain. So a route with no call site here is published as a candidate for deletion, never as dead API. | Access logs or an API gateway answer who really calls a route. The opposite direction is decisive without them: a client call matching no route is a request this repository's own front end makes and its server does not serve. |
|
|
400
400
|
|
|
401
|
+
And one about blast radius:
|
|
402
|
+
|
|
403
|
+
| Not covered | Why | What answers it |
|
|
404
|
+
|---|---|---|
|
|
405
|
+
| **The reach of a component the container invokes rather than the code — a security filter chain, an around-advice aspect, a `@ControllerAdvice`, a bean resolved through the interface it implements.** | Blast radius here is projected over the call graph: who calls the changed symbol, and which routes reach those callers. Nothing in the repository calls a container-wired component, so its measured call-graph fan-in is ~0 and every figure derived from it — affected endpoints, direct callers, rollback surface — reads as no impact. The fan-in figure is correct; using it as a risk proxy on this population is not. Publishing that as a low verdict would be a confident zero, which is the one thing this product does not do. | Such a change is flagged in `analysis_warnings` and its verdict is floored, never rated on fan-in. The reach itself is measured elsewhere and was there all along: `ask endpoints` resolves a gate annotation to the routes carrying it, `ask explain <class>` prints the request chain a configuration declares with its source line, and `ask posture --profile <set>` states what each profile leaves open. Projecting those into the blast radius (pointcut → routes, matcher → routes) is a measurement this command does not yet make. |
|
|
406
|
+
|
|
401
407
|
The one row above with a remedy in this build: `ask endpoints /path/to/repo --servlets`
|
|
402
408
|
lists the servlet-mounted HTTP surface as a population of its own — `web.xml` mappings and
|
|
403
409
|
`ServletRegistrationBean` registrations, with the file that declares each — and never merges
|
|
@@ -461,6 +467,9 @@ Full breakdown: [docs/PRODUCT_TIERS.md](docs/PRODUCT_TIERS.md).
|
|
|
461
467
|
|
|
462
468
|
```bash
|
|
463
469
|
ask config # version, config file path, telemetry status
|
|
470
|
+
ask config /repo # + the repository's own sourcecode.config.json:
|
|
471
|
+
# data labels, custom security annotations,
|
|
472
|
+
# and any declaration that could not be used
|
|
464
473
|
ask telemetry enable # anonymous telemetry is OFF by default (opt-in)
|
|
465
474
|
```
|
|
466
475
|
|
|
@@ -497,7 +506,7 @@ Matching endpoints report `policy: "custom"` and drop out of the `no_security_si
|
|
|
497
506
|
| [USER_GUIDE.md](docs/USER_GUIDE.md) | Full command reference, flags, output schema, workflows |
|
|
498
507
|
| [contracts.md](docs/contracts.md) | Declare invariants in `.ask/contracts.yml` (or derive them with `ask verify --init`), enforce them in the edit loop and in CI |
|
|
499
508
|
| [baseline-ci.yml](docs/baseline-ci.yml) | Capture an architectural baseline per release, so the series exists when you want to read it |
|
|
500
|
-
| [posture.md](docs/posture.md) | What a profile set actually wires — down to which endpoints its filter chain permits — and what could not be decided
|
|
509
|
+
| [posture.md](docs/posture.md) | What a profile set actually wires — down to which endpoints its filter chain permits — and what could not be decided |
|
|
501
510
|
| [migrate-check.md](docs/migrate-check.md) | Migration rule catalogue (MIG-001..043) + Hibernate stratification |
|
|
502
511
|
| [MODERNIZATION.md](docs/MODERNIZATION.md) | The modernization product: assess → understand → plan → execute |
|
|
503
512
|
| [PRODUCT_TIERS.md](docs/PRODUCT_TIERS.md) | Free vs Pro, pricing model |
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
**Context · Impact · Migration · Architecture · Review — everything from one structural model.**
|
|
6
6
|
|
|
7
|
-

|
|
8
8
|

|
|
9
9
|
|
|
10
10
|
> **ASK Engine** is the product. The CLI command is **`ask`**. The legacy **`sourcecode`**
|
|
@@ -68,7 +68,7 @@ brew tap haroundominique/sourcecode && brew install sourcecode
|
|
|
68
68
|
# pip / pipx
|
|
69
69
|
pipx install sourcecode # or: pip install sourcecode
|
|
70
70
|
|
|
71
|
-
ask version # ask 4.10.
|
|
71
|
+
ask version # ask 4.10.7 — and, on a build that has aged,
|
|
72
72
|
# how many releases have probably shipped since
|
|
73
73
|
```
|
|
74
74
|
|
|
@@ -261,7 +261,7 @@ experimental: both are true, and they are two different facts.
|
|
|
261
261
|
|---|---|---|
|
|
262
262
|
| **core** | contract stable within a major — safe to gate CI on | `endpoints` · `spring-audit` · `migrate-check` · `impact` · `impact-chain` · `pr-impact` · `verify` |
|
|
263
263
|
| **supported** | maintained; fields are added, never removed without a major | every command not named in another row |
|
|
264
|
-
| **experimental** | shape may change in a minor — do not gate CI on it | `risk` · `enrich` · `audit-report` · `data-exposure` · `migrate-recipe` · `
|
|
264
|
+
| **experimental** | shape may change in a minor — do not gate CI on it | `risk` · `enrich` · `audit-report` · `data-exposure` · `migrate-recipe` · `archetype` |
|
|
265
265
|
| **parked** | kept working, no longer developed | `retrieve` |
|
|
266
266
|
|
|
267
267
|
The same table is printed by `ask --help`, and both are generated from one authority
|
|
@@ -277,7 +277,7 @@ from it.
|
|
|
277
277
|
|
|
278
278
|
| Command | Tier | Answers | Note |
|
|
279
279
|
|---|---|---|---|
|
|
280
|
-
| `posture` |
|
|
280
|
+
| `posture` | supported | which beans a profile set wires, and how effective endpoint access differs between two sets | the most differentiated capability here |
|
|
281
281
|
| `risk` | experimental | what each defect actually costs, once reach, access, write effect and the shape of the input path are in it | `defect_severity × reachability × auth_verdict × write_effect × query_construction × input_constraints`; every factor names its authority; `--table --rule SEC-008 --band high --top-n 20` gives audit triage without `jq` |
|
|
282
282
|
| `enrich` | experimental | another scanner's SARIF findings, ranked by what this repository does with them | `--sarif <log>`; same composition as `risk`, with `--table --rule <id> --band high --top-n 20` for triage |
|
|
283
283
|
| `audit-report` | experimental | human audit bundle over existing `risk` + `posture` evidence, optionally signed | includes `evidence_manifest` claim provenance; `--format markdown`; `--sign-key <file>` signs canonical JSON with HMAC-SHA256 |
|
|
@@ -360,6 +360,12 @@ And one about who calls a route:
|
|
|
360
360
|
|---|---|---|
|
|
361
361
|
| **Whether a route is called from outside this repository — another service, a mobile app, a partner, a cron job, or a client whose URL is assembled at run time.** | The join reads the TypeScript/JavaScript checked in beside the server and only the call shapes whose verb and path are written at the call site. That is a floor on who calls a route and can never be a ceiling: the repository cannot observe consumers it does not contain. So a route with no call site here is published as a candidate for deletion, never as dead API. | Access logs or an API gateway answer who really calls a route. The opposite direction is decisive without them: a client call matching no route is a request this repository's own front end makes and its server does not serve. |
|
|
362
362
|
|
|
363
|
+
And one about blast radius:
|
|
364
|
+
|
|
365
|
+
| Not covered | Why | What answers it |
|
|
366
|
+
|---|---|---|
|
|
367
|
+
| **The reach of a component the container invokes rather than the code — a security filter chain, an around-advice aspect, a `@ControllerAdvice`, a bean resolved through the interface it implements.** | Blast radius here is projected over the call graph: who calls the changed symbol, and which routes reach those callers. Nothing in the repository calls a container-wired component, so its measured call-graph fan-in is ~0 and every figure derived from it — affected endpoints, direct callers, rollback surface — reads as no impact. The fan-in figure is correct; using it as a risk proxy on this population is not. Publishing that as a low verdict would be a confident zero, which is the one thing this product does not do. | Such a change is flagged in `analysis_warnings` and its verdict is floored, never rated on fan-in. The reach itself is measured elsewhere and was there all along: `ask endpoints` resolves a gate annotation to the routes carrying it, `ask explain <class>` prints the request chain a configuration declares with its source line, and `ask posture --profile <set>` states what each profile leaves open. Projecting those into the blast radius (pointcut → routes, matcher → routes) is a measurement this command does not yet make. |
|
|
368
|
+
|
|
363
369
|
The one row above with a remedy in this build: `ask endpoints /path/to/repo --servlets`
|
|
364
370
|
lists the servlet-mounted HTTP surface as a population of its own — `web.xml` mappings and
|
|
365
371
|
`ServletRegistrationBean` registrations, with the file that declares each — and never merges
|
|
@@ -423,6 +429,9 @@ Full breakdown: [docs/PRODUCT_TIERS.md](docs/PRODUCT_TIERS.md).
|
|
|
423
429
|
|
|
424
430
|
```bash
|
|
425
431
|
ask config # version, config file path, telemetry status
|
|
432
|
+
ask config /repo # + the repository's own sourcecode.config.json:
|
|
433
|
+
# data labels, custom security annotations,
|
|
434
|
+
# and any declaration that could not be used
|
|
426
435
|
ask telemetry enable # anonymous telemetry is OFF by default (opt-in)
|
|
427
436
|
```
|
|
428
437
|
|
|
@@ -459,7 +468,7 @@ Matching endpoints report `policy: "custom"` and drop out of the `no_security_si
|
|
|
459
468
|
| [USER_GUIDE.md](docs/USER_GUIDE.md) | Full command reference, flags, output schema, workflows |
|
|
460
469
|
| [contracts.md](docs/contracts.md) | Declare invariants in `.ask/contracts.yml` (or derive them with `ask verify --init`), enforce them in the edit loop and in CI |
|
|
461
470
|
| [baseline-ci.yml](docs/baseline-ci.yml) | Capture an architectural baseline per release, so the series exists when you want to read it |
|
|
462
|
-
| [posture.md](docs/posture.md) | What a profile set actually wires — down to which endpoints its filter chain permits — and what could not be decided
|
|
471
|
+
| [posture.md](docs/posture.md) | What a profile set actually wires — down to which endpoints its filter chain permits — and what could not be decided |
|
|
463
472
|
| [migrate-check.md](docs/migrate-check.md) | Migration rule catalogue (MIG-001..043) + Hibernate stratification |
|
|
464
473
|
| [MODERNIZATION.md](docs/MODERNIZATION.md) | The modernization product: assess → understand → plan → execute |
|
|
465
474
|
| [PRODUCT_TIERS.md](docs/PRODUCT_TIERS.md) | Free vs Pro, pricing model |
|
|
@@ -136,6 +136,19 @@ def _fan_in_from_stored(value: Any) -> dict[str, int]:
|
|
|
136
136
|
return {}
|
|
137
137
|
|
|
138
138
|
|
|
139
|
+
def _comparability_env() -> dict:
|
|
140
|
+
"""The environment fields a delta actually depends on (C3-68).
|
|
141
|
+
|
|
142
|
+
A baseline is comparable to another when the platform and the tool agree;
|
|
143
|
+
the CPU model, the core count and a hash of the hostname change none of
|
|
144
|
+
that. `--record-env` restores the full set for someone benchmarking runs
|
|
145
|
+
against each other on one machine.
|
|
146
|
+
"""
|
|
147
|
+
import sys as _sys
|
|
148
|
+
|
|
149
|
+
return {"os": _sys.platform, "tool_version": TOOL_VERSION, "recorded": "comparability_only"}
|
|
150
|
+
|
|
151
|
+
|
|
139
152
|
def build_baseline(
|
|
140
153
|
cir: "CanonicalRepositoryIR",
|
|
141
154
|
*,
|
|
@@ -145,6 +158,7 @@ def build_baseline(
|
|
|
145
158
|
captured_at: str | None = None,
|
|
146
159
|
env: dict | None = None,
|
|
147
160
|
tool_version: str | None = None,
|
|
161
|
+
record_env: bool = False,
|
|
148
162
|
) -> dict:
|
|
149
163
|
"""Freeze a CIR's measured architectural metrics into a baseline artifact.
|
|
150
164
|
|
|
@@ -168,6 +182,21 @@ def build_baseline(
|
|
|
168
182
|
"files": m.file_count,
|
|
169
183
|
"symbols": m.symbol_count,
|
|
170
184
|
"endpoints": m.endpoint_count,
|
|
185
|
+
# C1-37: this artefact's declared purpose is to be a replayable
|
|
186
|
+
# fingerprint, and it disagreed with itself — `totals.endpoints`
|
|
187
|
+
# 3 574 against `len(endpoint_surface)` 3 538 on the field
|
|
188
|
+
# repository. Neither figure was wrong: `endpoints` counts handler
|
|
189
|
+
# mappings and `endpoint_surface` is the set of distinct
|
|
190
|
+
# (METHOD, path) contract pairs, so 36 routes are declared by more
|
|
191
|
+
# than one handler. Two facts, two names, and the invariant the
|
|
192
|
+
# battery can actually hold.
|
|
193
|
+
"endpoint_contract_pairs": len(m.endpoints),
|
|
194
|
+
"endpoints_unit": (
|
|
195
|
+
"handler mappings declared in the repository; "
|
|
196
|
+
"`endpoint_contract_pairs` counts the distinct (METHOD, path) "
|
|
197
|
+
"pairs those mappings expose, which is what `endpoint_surface` "
|
|
198
|
+
"lists and what a diff compares"
|
|
199
|
+
),
|
|
171
200
|
"dependency_edges": m.dependency_edge_count,
|
|
172
201
|
"import_cycles": len(m.cycles),
|
|
173
202
|
},
|
|
@@ -175,7 +204,16 @@ def build_baseline(
|
|
|
175
204
|
"endpoint_surface": endpoints,
|
|
176
205
|
"fan_in": _fan_in_to_list(m.fan_in),
|
|
177
206
|
"import_cycles": cycles,
|
|
178
|
-
|
|
207
|
+
# C3-68: this artefact is written inside the work tree, so what it
|
|
208
|
+
# records is what a `git add -A` publishes. `hostname_hash`, `cpu` and
|
|
209
|
+
# `cores` describe the developer's machine and affect nothing a delta
|
|
210
|
+
# compares — from a tool whose own `ask config` says telemetry is off.
|
|
211
|
+
# The default is now the two fields that DO decide comparability; the
|
|
212
|
+
# rest is opt-in per capture.
|
|
213
|
+
"env": (
|
|
214
|
+
env if env is not None
|
|
215
|
+
else (collect_env() if record_env else _comparability_env())
|
|
216
|
+
),
|
|
179
217
|
"provenance": (
|
|
180
218
|
"architectural_baseline (D5): a measured structural fingerprint of one "
|
|
181
219
|
"CIR, persisted per ref. Metric content is a pure function of the repo "
|
|
@@ -319,9 +357,50 @@ def _baseline_filename(baseline: dict) -> str:
|
|
|
319
357
|
return f"{safe}.json"
|
|
320
358
|
|
|
321
359
|
|
|
360
|
+
#: What `.ask/` gets the moment it is created, and why.
|
|
361
|
+
#:
|
|
362
|
+
#: C3-68: `baseline capture` writes into the work tree and nothing protected it.
|
|
363
|
+
#: The field verified `grep -nE "^\.ask|sourcecode" .gitignore` → no matches, so
|
|
364
|
+
#: a `git add -A` commits the artefact — which carries a machine fingerprint and
|
|
365
|
+
#: a 14 587-entry structural inventory of the code. A self-confined
|
|
366
|
+
#: `.ask/.gitignore` is the honest form: it never touches the user's own
|
|
367
|
+
#: `.gitignore`, and it stops applying the moment they delete the directory.
|
|
368
|
+
_ASK_DIR_GITIGNORE = (
|
|
369
|
+
"# Written by `ask` the first time it created this directory.\n"
|
|
370
|
+
"# These are local analysis artefacts: a structural inventory of your code\n"
|
|
371
|
+
"# and, if you asked for it, the machine that measured it. Nothing here\n"
|
|
372
|
+
"# belongs in a commit. Delete this file to version them deliberately.\n"
|
|
373
|
+
"*\n"
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
def protect_ask_dir(out_dir: Path) -> None:
|
|
378
|
+
"""Give a freshly created `.ask/` its own `.gitignore` (C3-68).
|
|
379
|
+
|
|
380
|
+
Best-effort and never overwriting: a user who edited it decided something,
|
|
381
|
+
and a tool that re-imposes its default on every run is worse than one that
|
|
382
|
+
never wrote it.
|
|
383
|
+
"""
|
|
384
|
+
try:
|
|
385
|
+
ask_dir = Path(out_dir)
|
|
386
|
+
while ask_dir.name and ask_dir.name != ".ask":
|
|
387
|
+
if ask_dir.parent == ask_dir:
|
|
388
|
+
return
|
|
389
|
+
ask_dir = ask_dir.parent
|
|
390
|
+
if ask_dir.name != ".ask":
|
|
391
|
+
return
|
|
392
|
+
marker = ask_dir / ".gitignore"
|
|
393
|
+
if not marker.exists():
|
|
394
|
+
ask_dir.mkdir(parents=True, exist_ok=True)
|
|
395
|
+
marker.write_text(_ASK_DIR_GITIGNORE, encoding="utf-8")
|
|
396
|
+
except OSError:
|
|
397
|
+
return
|
|
398
|
+
|
|
399
|
+
|
|
322
400
|
def write_baseline(baseline: dict, out_dir: Path) -> Path:
|
|
323
401
|
"""Write `baseline` as deterministic JSON under `out_dir`; return the file path."""
|
|
324
402
|
out_dir.mkdir(parents=True, exist_ok=True)
|
|
403
|
+
protect_ask_dir(out_dir)
|
|
325
404
|
path = out_dir / _baseline_filename(baseline)
|
|
326
405
|
path.write_text(
|
|
327
406
|
json.dumps(baseline, sort_keys=True, indent=2) + "\n", encoding="utf-8"
|
|
@@ -336,10 +336,15 @@ def cache_dir(repo_root: Path) -> Path:
|
|
|
336
336
|
def status(repo_root: Path) -> dict[str, Any]:
|
|
337
337
|
"""Return a stats dict describing the current cache state for *repo_root*.
|
|
338
338
|
|
|
339
|
-
Keys: ``cache_dir``, ``
|
|
339
|
+
Keys: ``cache_dir``, ``cached_cores``, ``views``, ``cas_blobs``,
|
|
340
340
|
``total_size_bytes``, ``total_size_mb``, ``ris_exists``, ``ris_git_head``,
|
|
341
341
|
``ris_last_updated_at``, ``ris_is_stale``, ``current_git_head``.
|
|
342
342
|
|
|
343
|
+
``cached_cores`` counts ``core-*.json.gz`` entries in this cache. It was
|
|
344
|
+
named ``cores`` until 4.10.7, which is the field name a captured baseline
|
|
345
|
+
uses for the machine's CPU count (``env.cores``) — two different facts under
|
|
346
|
+
one name, on the same machine, minutes apart (C4-18).
|
|
347
|
+
|
|
343
348
|
Note: ``snapshots`` is a legacy v1 field — always 0 in v2 (kept for
|
|
344
349
|
backward compatibility; v2 writes ``core-*`` and ``view-*`` files only).
|
|
345
350
|
"""
|
|
@@ -377,7 +382,7 @@ def status(repo_root: Path) -> dict[str, Any]:
|
|
|
377
382
|
if not cache_d.exists():
|
|
378
383
|
return {
|
|
379
384
|
"cache_dir": str(cache_d),
|
|
380
|
-
"
|
|
385
|
+
"cached_cores": 0, "snapshots": 0, "views": 0, "cas_blobs": 0,
|
|
381
386
|
"total_size_bytes": 0, "total_size_mb": 0.0,
|
|
382
387
|
"current_git_head": current_head,
|
|
383
388
|
"stores": _store_breakdown(repo_root, 0),
|
|
@@ -391,7 +396,7 @@ def status(repo_root: Path) -> dict[str, Any]:
|
|
|
391
396
|
total_bytes = sum(f.stat().st_size for f in all_files if f.exists())
|
|
392
397
|
return {
|
|
393
398
|
"cache_dir": str(cache_d),
|
|
394
|
-
"
|
|
399
|
+
"cached_cores": len(cores),
|
|
395
400
|
"snapshots": len(snapshots),
|
|
396
401
|
"views": len(views),
|
|
397
402
|
"cas_blobs": len(cas_blobs),
|