sourcecode 4.18.0__tar.gz → 5.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {sourcecode-4.18.0 → sourcecode-5.0.0}/.github/workflows/perf-gate.yml +6 -1
- {sourcecode-4.18.0 → sourcecode-5.0.0}/CHANGELOG.md +77 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/PKG-INFO +5 -5
- {sourcecode-4.18.0 → sourcecode-5.0.0}/README.md +4 -4
- {sourcecode-4.18.0 → sourcecode-5.0.0}/pyproject.toml +1 -1
- {sourcecode-4.18.0 → sourcecode-5.0.0}/scripts/perf_gate.py +19 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/__init__.py +1 -1
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/cache_model.py +199 -37
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/cli.py +20 -4
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/detach.py +7 -3
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/execution_plan.py +36 -19
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/perf.py +4 -2
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/phased_run.py +10 -8
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/release_info.py +1 -1
- {sourcecode-4.18.0 → sourcecode-5.0.0}/.github/workflows/build-windows.yml +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/.gitignore +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/.ruff.toml +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/CLAUDE.md +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/CONTRIBUTING.md +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/LICENSE +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/SECURITY.md +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/raw +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/scripts/compare_integration_engines.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/scripts/customer_smoke_test.sh +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/scripts/generate_jdk_exports.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/scripts/perf_harness.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/adaptive_scanner.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/archetype.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/architectural_baseline.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/architectural_delta.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/architecture_analyzer.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/architecture_summary.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/ast_extractor.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/audit_report.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/baseline_autocapture.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/cache.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/call_surface.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/caller_metrics.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/caller_reach.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/canonical_ir.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/chain_rules.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/change_plan.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/cir_graphs.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/classifier.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/client_calls.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/code_notes_analyzer.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/compare.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/confidence_analyzer.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/constraint_diff.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/container_wiring.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/context_cache.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/context_graph.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/context_scorer.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/context_summarizer.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/contract_diff.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/contract_init.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/contract_model.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/contract_pipeline.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/coverage_parser.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/data_exposure.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/data_labels.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/declarations.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/defect_identity.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/degradation.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/dependency_analyzer.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/deployment_prefix.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/detectors/__init__.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/detectors/base.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/detectors/csproj_parser.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/detectors/dart.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/detectors/dotnet.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/detectors/elixir.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/detectors/go.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/detectors/heuristic.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/detectors/hybrid.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/detectors/java.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/detectors/jvm_ext.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/detectors/nodejs.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/detectors/parsers.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/detectors/php.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/detectors/project.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/detectors/python.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/detectors/ruby.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/detectors/rust.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/detectors/systems.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/detectors/terraform.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/detectors/tooling.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/doc_analyzer.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/dynamic_argument_surface.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/endpoint_literals.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/endpoint_metrics.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/entrypoint_classifier.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/env_analyzer.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/envelope.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/environment_resolution.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/error_schema.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/evidence_provider.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/explain.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/facts/__init__.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/facts/registry.json +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/file_chunker.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/file_classifier.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/filter_surface.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/format_contract.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/fqn_utils.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/git_analyzer.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/git_checkout.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/graph_analyzer.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/graph_evidence.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/hibernate_strat.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/identity_fallback.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/integration_coordinates.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/jdk_exports.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/license.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/mcp/__init__.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/mcp/dependency_import.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/mcp/onboarding/__init__.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/mcp/onboarding/applier.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/mcp/onboarding/backup.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/mcp/onboarding/detector.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/mcp/onboarding/planner.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/mcp/orchestrator.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/mcp/registry.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/mcp/runner.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/mcp/server.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/mcp_nudge.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/metrics_analyzer.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/migrate_check.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/migration_blast.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/non_coverage.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/openapi_surface.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/openrewrite_recipe.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/output_budget.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/output_encoding.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/parallel.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/parse_cache.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/partial_contract.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/path_admission.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/path_filters.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/pipe_contract.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/posture.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/pr_comment_renderer.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/pr_impact.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/prepare_context.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/progress.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/provenance.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/ranking_engine.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/readiness_timeline.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/readonly.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/reconciliation.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/redactor.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/reference_facts.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/relevance_scorer.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/remedies.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/rename_refactor.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/repo_classifier.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/repository_ir.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/retrieval/__init__.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/retrieval/context.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/retrieval/errors.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/retrieval/executor.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/retrieval/planner.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/retrieval/query.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/retrieval/request.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/retrieval/resolution.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/retrieval/result.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/retrieval/retriever.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/retrieval/runtime.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/retrieval/steps.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/retrieval/steps_endpoint.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/retrieval/steps_graph.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/retrieval/steps_impact.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/retrieval/steps_intf.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/retrieval/steps_struct.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/retrieval/steps_txsec.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/ris.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/risk.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/rule_catalog.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/rule_pass.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/runs.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/runtime_classifier.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/sarif.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/scanner.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/schema.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/schemas/envelope-v1.schema.json +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/security_config.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/security_config_scan.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/security_posture.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/semantic_analyzer.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/semantic_impact_engine.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/semantic_integration_engine.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/semantic_services.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/serializer.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/servlet_surface.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/source_text.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/spring_event_topology.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/spring_findings.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/spring_impact.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/spring_model.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/spring_profiles.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/spring_properties.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/spring_security_audit.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/spring_semantic.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/spring_tx_analyzer.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/summarizer.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/target_admission.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/telemetry/__init__.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/telemetry/config.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/telemetry/consent.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/telemetry/events.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/telemetry/filters.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/telemetry/transport.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/test_gap_ranking.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/test_sources.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/text_input.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/token_estimate.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/tree_utils.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/type_usage_surface.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/validation_inference.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/validation_surface.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/verify_edit.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/verify_repo.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/verify_rules.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/version_check.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/src/sourcecode/workspace.py +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/supabase/functions/README.md +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/supabase/functions/get-license/index.ts +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/supabase/functions/lemonsqueezy-webhook/index.ts +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/supabase/functions/telemetry/index.ts +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/supabase/sql/license_event_ordering.sql +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/supabase/sql/licensing_schema.sql +0 -0
- {sourcecode-4.18.0 → sourcecode-5.0.0}/supabase/sql/telemetry_events.sql +0 -0
|
@@ -59,14 +59,18 @@ jobs:
|
|
|
59
59
|
python3 scripts/perf_gate.py --print-config | tee gate-config.json
|
|
60
60
|
echo "repo_url=$(python3 -c "import json;print(json.load(open('gate-config.json'))['repository_url'])")" >> "$GITHUB_OUTPUT"
|
|
61
61
|
echo "repo=$(python3 -c "import json;print(json.load(open('gate-config.json'))['repository'])")" >> "$GITHUB_OUTPUT"
|
|
62
|
+
echo "fleet_subdir=$(python3 -c "import json;print(json.load(open('gate-config.json'))['fleet_subdir'])")" >> "$GITHUB_OUTPUT"
|
|
62
63
|
echo "mode=$(python3 -c "import json;print(json.load(open('gate-config.json'))['mode'])")" >> "$GITHUB_OUTPUT"
|
|
63
64
|
echo "runs=$(python3 -c "import json;print(json.load(open('gate-config.json'))['min_runs'])")" >> "$GITHUB_OUTPUT"
|
|
64
65
|
echo "commands=$(python3 -c "import json;print(' '.join(repr(c) for c in json.load(open('gate-config.json'))['commands']))")" >> "$GITHUB_OUTPUT"
|
|
65
66
|
|
|
66
67
|
- name: Clone the gate repository
|
|
68
|
+
# Into the directory the harness resolves the gate repository to, which
|
|
69
|
+
# `--print-config` publishes. Naming it here instead cost three nightlies
|
|
70
|
+
# that measured nothing.
|
|
67
71
|
run: |
|
|
68
72
|
mkdir -p fleet
|
|
69
|
-
git clone --depth 1 "${{ steps.cfg.outputs.repo_url }}" "fleet/${{ steps.cfg.outputs.
|
|
73
|
+
git clone --depth 1 "${{ steps.cfg.outputs.repo_url }}" "fleet/${{ steps.cfg.outputs.fleet_subdir }}"
|
|
70
74
|
|
|
71
75
|
- name: Measure
|
|
72
76
|
env:
|
|
@@ -84,6 +88,7 @@ jobs:
|
|
|
84
88
|
run: |
|
|
85
89
|
python3 scripts/perf_gate.py \
|
|
86
90
|
--baseline "$BASELINE_DIR" \
|
|
91
|
+
--require-baseline \
|
|
87
92
|
--current perf-run \
|
|
88
93
|
--report perf-run/gate.json \
|
|
89
94
|
--table perf-run/RELEASE-TABLE.md
|
|
@@ -2,6 +2,83 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [5.0.0] — 2026-08-11
|
|
6
|
+
|
|
7
|
+
**The engine got 280× faster in 4.18.0 and every number the product quoted about
|
|
8
|
+
its own cost still described the build before it.** This release changes no
|
|
9
|
+
analysis: it makes what ASK says about itself true again, and makes the way it
|
|
10
|
+
went stale impossible to repeat silently. Field evaluation #22 — eighth
|
|
11
|
+
measurement of the same 3 342-file repository at the same commit — scored the
|
|
12
|
+
build **9,2/10** and named this as the one place the product states something
|
|
13
|
+
false with confidence.
|
|
14
|
+
|
|
15
|
+
**Why a major.** No API breaks. What changes is an answer thousands of readers
|
|
16
|
+
act on: commands that were published as *"not a foreground run here — `--output
|
|
17
|
+
<file> --detach`, or a nightly job"* are now published as foreground work, and
|
|
18
|
+
the operational advice in `--help`, `cache model`, the budget warning and the
|
|
19
|
+
remedies moves with them. A recommendation that reverses is a contract change
|
|
20
|
+
whatever the surface, so it is versioned like one.
|
|
21
|
+
|
|
22
|
+
**Fixed in this release:**
|
|
23
|
+
|
|
24
|
+
- **The cost anchors described a build that no longer exists (C3-97).** `spring-audit`'s
|
|
25
|
+
field anchor was **2 351 s**, measured on 4.11.0; the same command, on the same
|
|
26
|
+
repository at the same commit, takes **8,4 s** on 4.18.0 — the two
|
|
27
|
+
catastrophic-backtracking patterns behind that figure were deleted in C3-95 and
|
|
28
|
+
C3-96. Four surfaces read the anchors and none could tell they were old:
|
|
29
|
+
`execution_plan`'s `here:` verdict, the budget warning, the `cache model`
|
|
30
|
+
header, and the front page. The product therefore recommended a nightly job for
|
|
31
|
+
an eight-second command, and an operator sizing `ASK_MAX_ANALYSIS_SECONDS` from
|
|
32
|
+
it would set the budget ~280× too high. Anchors refreshed from evaluation #22
|
|
33
|
+
(`spring-audit` 2 351 → 8,4 s · `risk` 3 232 → 73,3 s · `posture` 38 → 8,0 s ·
|
|
34
|
+
`migrate-check` 26,7 → 10,2 s · `endpoints` 5,0 → 3,8 s), first anchors recorded
|
|
35
|
+
for `impact-chain` 5,5 s, `validation` 17,4 s, `pr-impact` 12,5 s, `impact`
|
|
36
|
+
7,7 s and `explain` 4,4 s — and `modernize`, carried as *did not finish* since
|
|
37
|
+
4.10.4, is a measurement again at **9,1 s**.
|
|
38
|
+
- **And they cannot go stale silently again.** Every field figure now carries
|
|
39
|
+
`field_measured_version`, the build it was taken on. A figure from an earlier
|
|
40
|
+
release is still published — a measurement at that size beats silence — but it
|
|
41
|
+
arrives labelled *"measured on 4.10.4, not re-measured on 5.0.0"* wherever it is
|
|
42
|
+
read, and `ask cache model --json` publishes `field_currency` naming every row
|
|
43
|
+
in that state. This is the mechanism `REFERENCE_MEASURED_VERSION` already gave
|
|
44
|
+
the reference figures; the field anchors, which are the ones that decide how a
|
|
45
|
+
command is offered, had none.
|
|
46
|
+
- **The front page paraphrased the table instead of deriving it (CL-21).** *"Repo-wide/deep
|
|
47
|
+
compositions can take minutes … use deep jobs nightly"* was written in `cli`
|
|
48
|
+
beside the model it described, so it aged separately from the anchors it
|
|
49
|
+
paraphrased. It is generated from `cache_model.cost_sentence()` now: refreshing
|
|
50
|
+
a measurement refreshes the prose, and a battery asserts the front page contains
|
|
51
|
+
exactly what the model generates.
|
|
52
|
+
- **The performance gate had no baseline to compare against (C3-98).** F-AP shipped
|
|
53
|
+
the detector in 4.13.0 and it has run nightly since, self-testing that a
|
|
54
|
+
synthetic 3× regression would fail — against `docs/perf/baselines/gate-latest`,
|
|
55
|
+
a directory that was never created. Every run ended in the gate refusing to
|
|
56
|
+
report green (*"a gate that cannot be red is not evidence"*), which is why eight
|
|
57
|
+
consecutive field evaluations found no evidence that any benchmark gates a
|
|
58
|
+
release. The baseline is committed: six cells on BroadleafCommerce, warm, five
|
|
59
|
+
runs each, captured on the runner at 4.18.0, with provenance and a refresh
|
|
60
|
+
procedure beside them. First real comparison passed with `regressions: []`, and
|
|
61
|
+
the observed runner noise floor — ±5 %, widest on the shortest cell — is
|
|
62
|
+
published next to the 20 % threshold it has to be read against.
|
|
63
|
+
- **The gate's exclusion list quoted a deleted cost (C3-99).** `risk` was excluded
|
|
64
|
+
because it took *54 minutes* on the gate repository. Since C3-96 it takes
|
|
65
|
+
**68 s** there. The reason now says so, and names the only thing still keeping
|
|
66
|
+
it out: no baseline cell exists for it yet.
|
|
67
|
+
- **Stale cost claims elsewhere in the documentation.** README (the proof table's
|
|
68
|
+
caveat and the problem statement), `USER_GUIDE` (the "Start here" framing and
|
|
69
|
+
the spinner paragraph), `docs/CACHE.md` (regenerated), `docs/perf/REGRESSION-GATE.md`
|
|
70
|
+
§3, and the module docstrings of `execution_plan`, `phased_run` and `detach`,
|
|
71
|
+
where a 408 s / 2 351 s cost was narrated in the present tense.
|
|
72
|
+
|
|
73
|
+
**Deliberately not in this release:** the `chunk-file -c` remap. The guide says the
|
|
74
|
+
short form moves from `--chunk` to `--copy` "at the next major"; this major
|
|
75
|
+
changes no invocation, and breaking a working command line as a side effect of a
|
|
76
|
+
documentation-truth release would be the wrong trade. It waits for a major that
|
|
77
|
+
changes the command surface on purpose.
|
|
78
|
+
|
|
79
|
+
**Not changed:** any analysis, any payload, any schema. Every rule, every count and
|
|
80
|
+
every verdict this build produces is byte-identical to 4.18.0's.
|
|
81
|
+
|
|
5
82
|
## [4.18.0] — 2026-08-10
|
|
6
83
|
|
|
7
84
|
**A field battery over the test repositories, run against 4.17.0 and aimed first
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sourcecode
|
|
3
|
-
Version:
|
|
3
|
+
Version: 5.0.0
|
|
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`**
|
|
@@ -54,7 +54,7 @@ Description-Content-Type: text/markdown
|
|
|
54
54
|
|
|
55
55
|
## The problem
|
|
56
56
|
|
|
57
|
-
Every time an AI coding agent starts a new session, it has to re-parse the repository from scratch. On
|
|
57
|
+
Every time an AI coding agent starts a new session, it has to re-parse the repository from scratch. On a large Java/Spring monolith that is thousands of files of parsing per turn, repeated for every question asked about the same unchanged tree. Multiply it by dozens of agent turns per hour, and repo context acquisition becomes a real bottleneck — not just latency, but tokens, compute, and iteration velocity.
|
|
58
58
|
|
|
59
59
|
ASK Engine solves this with a persistent structural cache keyed on file content hashes. After the first scan, later invocations reuse pre-built context whenever their command can consume the warmed layers. The repo doesn't change? The cache doesn't expire.
|
|
60
60
|
|
|
@@ -69,7 +69,7 @@ ASK Engine solves this with a persistent structural cache keyed on file content
|
|
|
69
69
|
| Keycloak | 7,885 Java files | 10.5s | 0.6s | **~17x** |
|
|
70
70
|
| BroadleafCommerce | 2,985 Java files | 2.7s | 0.3s | **~9x** |
|
|
71
71
|
|
|
72
|
-
These numbers are cache-layer benchmarks, not a promise for every command. Per-symbol queries and compact context benefit most
|
|
72
|
+
These numbers are cache-layer benchmarks, not a promise for every command. Per-symbol queries and compact context benefit most, and inventory commands scale with file count. What a repository-wide analysis costs tracks the build more than the file count: on one 3,342-file monolith, at one commit, `spring-audit` measured 2,351s on 4.11.0 and **8.4s on 4.18.0** with a byte-identical payload — so ASK publishes measured anchors and the release each was taken on, and never projects a duration for your repository. `ask cache model` prints both anchors per command, and `risk` — the one composition still measured in the tens of seconds at that size — is the one to give a budget or a detached run.
|
|
73
73
|
|
|
74
74
|
With the right command class, ASK Engine becomes **constant infrastructure** inside agent loops — call the fast/context surfaces before edits and reserve deep compositions for the points where their evidence is worth the runtime.
|
|
75
75
|
|
|
@@ -126,7 +126,7 @@ brew tap haroundominique/sourcecode && brew install sourcecode
|
|
|
126
126
|
# pip / pipx
|
|
127
127
|
pipx install sourcecode # or: pip install sourcecode
|
|
128
128
|
|
|
129
|
-
ask version # ask
|
|
129
|
+
ask version # ask 5.0.0 — and, on a build that has aged,
|
|
130
130
|
# how many releases have probably shipped since
|
|
131
131
|
```
|
|
132
132
|
|
|
@@ -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`**
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
## The problem
|
|
18
18
|
|
|
19
|
-
Every time an AI coding agent starts a new session, it has to re-parse the repository from scratch. On
|
|
19
|
+
Every time an AI coding agent starts a new session, it has to re-parse the repository from scratch. On a large Java/Spring monolith that is thousands of files of parsing per turn, repeated for every question asked about the same unchanged tree. Multiply it by dozens of agent turns per hour, and repo context acquisition becomes a real bottleneck — not just latency, but tokens, compute, and iteration velocity.
|
|
20
20
|
|
|
21
21
|
ASK Engine solves this with a persistent structural cache keyed on file content hashes. After the first scan, later invocations reuse pre-built context whenever their command can consume the warmed layers. The repo doesn't change? The cache doesn't expire.
|
|
22
22
|
|
|
@@ -31,7 +31,7 @@ ASK Engine solves this with a persistent structural cache keyed on file content
|
|
|
31
31
|
| Keycloak | 7,885 Java files | 10.5s | 0.6s | **~17x** |
|
|
32
32
|
| BroadleafCommerce | 2,985 Java files | 2.7s | 0.3s | **~9x** |
|
|
33
33
|
|
|
34
|
-
These numbers are cache-layer benchmarks, not a promise for every command. Per-symbol queries and compact context benefit most
|
|
34
|
+
These numbers are cache-layer benchmarks, not a promise for every command. Per-symbol queries and compact context benefit most, and inventory commands scale with file count. What a repository-wide analysis costs tracks the build more than the file count: on one 3,342-file monolith, at one commit, `spring-audit` measured 2,351s on 4.11.0 and **8.4s on 4.18.0** with a byte-identical payload — so ASK publishes measured anchors and the release each was taken on, and never projects a duration for your repository. `ask cache model` prints both anchors per command, and `risk` — the one composition still measured in the tens of seconds at that size — is the one to give a budget or a detached run.
|
|
35
35
|
|
|
36
36
|
With the right command class, ASK Engine becomes **constant infrastructure** inside agent loops — call the fast/context surfaces before edits and reserve deep compositions for the points where their evidence is worth the runtime.
|
|
37
37
|
|
|
@@ -88,7 +88,7 @@ brew tap haroundominique/sourcecode && brew install sourcecode
|
|
|
88
88
|
# pip / pipx
|
|
89
89
|
pipx install sourcecode # or: pip install sourcecode
|
|
90
90
|
|
|
91
|
-
ask version # ask
|
|
91
|
+
ask version # ask 5.0.0 — and, on a build that has aged,
|
|
92
92
|
# how many releases have probably shipped since
|
|
93
93
|
```
|
|
94
94
|
|
|
@@ -33,7 +33,13 @@ import sys
|
|
|
33
33
|
from pathlib import Path
|
|
34
34
|
|
|
35
35
|
sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "src"))
|
|
36
|
+
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
|
36
37
|
from sourcecode import perf # noqa: E402
|
|
38
|
+
# The directory a repository is checked out under is the harness's fact, not a
|
|
39
|
+
# second one this script or a workflow may restate: CI cloned the gate repo into
|
|
40
|
+
# `fleet/broadleaf` while the harness looked for `fleet/BroadleafCommerce`, so
|
|
41
|
+
# every nightly measured zero cells. `--print-config` now publishes the one name.
|
|
42
|
+
from perf_harness import FLEET # noqa: E402
|
|
37
43
|
|
|
38
44
|
|
|
39
45
|
def load_cells(directory: Path) -> dict[str, dict]:
|
|
@@ -98,6 +104,8 @@ def _print_config() -> int:
|
|
|
98
104
|
"threshold": perf.RELEASE_GATE_THRESHOLD,
|
|
99
105
|
"repository": perf.RELEASE_GATE_REPO,
|
|
100
106
|
"repository_url": perf.RELEASE_GATE_REPO_URL,
|
|
107
|
+
# Where the harness will look for that checkout, under the fleet root.
|
|
108
|
+
"fleet_subdir": FLEET.get(perf.RELEASE_GATE_REPO, perf.RELEASE_GATE_REPO),
|
|
101
109
|
"repository_scale": perf.RELEASE_GATE_REPO_SCALE,
|
|
102
110
|
"mode": perf.RELEASE_GATE_MODE,
|
|
103
111
|
"min_runs": perf.RELEASE_GATE_MIN_RUNS,
|
|
@@ -122,6 +130,11 @@ def main() -> int:
|
|
|
122
130
|
ap.add_argument("--allow-incomparable", action="store_true",
|
|
123
131
|
help="Do not fail cells whose env/host differ. Off by default: "
|
|
124
132
|
"an incomparable cell is an unmeasured one.")
|
|
133
|
+
ap.add_argument("--require-baseline", action="store_true",
|
|
134
|
+
help="Fail when the baseline holds no cells. A run with nothing "
|
|
135
|
+
"to compare against records every cell as `new` and passes; "
|
|
136
|
+
"that is a recording, not a gate, and CI must not read it "
|
|
137
|
+
"as one.")
|
|
125
138
|
ap.add_argument("--report", type=Path, help="Write the perf-gate-v1 report here.")
|
|
126
139
|
ap.add_argument("--table", type=Path, help="Write the release-notes markdown table here.")
|
|
127
140
|
ap.add_argument("--self-test", action="store_true",
|
|
@@ -143,6 +156,12 @@ def main() -> int:
|
|
|
143
156
|
f"which the gate reads as a failure, not a pass.", file=sys.stderr)
|
|
144
157
|
return 1
|
|
145
158
|
baseline = load_cells(args.baseline) if args.baseline else {}
|
|
159
|
+
if args.require_baseline and not baseline:
|
|
160
|
+
where = args.baseline if args.baseline else "<no --baseline given>"
|
|
161
|
+
print(f"no baseline cells in {where} — every cell would be recorded as "
|
|
162
|
+
f"`new` and the run would pass without comparing anything. A gate "
|
|
163
|
+
f"that cannot be red is not evidence.", file=sys.stderr)
|
|
164
|
+
return 1
|
|
146
165
|
|
|
147
166
|
report = perf.gate_report(
|
|
148
167
|
baseline, current,
|
|
@@ -74,11 +74,11 @@ class CommandCache:
|
|
|
74
74
|
cold_seconds: "Optional[float]" = None
|
|
75
75
|
warm_seconds: "Optional[float]" = None
|
|
76
76
|
#: The other measured point: this command on the field repository
|
|
77
|
-
#: (3 342 Java files, Windows 11 / PowerShell 5.1 / pipx,
|
|
78
|
-
#: evaluations
|
|
79
|
-
#:
|
|
80
|
-
#:
|
|
81
|
-
#:
|
|
77
|
+
#: (3 342 Java files, Windows 11 / PowerShell 5.1 / pipx, warm), from the
|
|
78
|
+
#: field evaluations. Seconds where a run finished; `field_blocked` where it
|
|
79
|
+
#: did not — the harness promoted the process and the session died, which is a
|
|
80
|
+
#: measurement of a different kind and is never written as a duration. Rows
|
|
81
|
+
#: with neither were not attempted there.
|
|
82
82
|
#:
|
|
83
83
|
#: C3-72: where two evaluations of the same command at this size disagree, the
|
|
84
84
|
#: figure here is the **most recent** one, because it describes the build a
|
|
@@ -88,6 +88,17 @@ class CommandCache:
|
|
|
88
88
|
#: measurement C3-76 exists for.
|
|
89
89
|
field_seconds: "Optional[float]" = None
|
|
90
90
|
field_blocked: bool = False
|
|
91
|
+
#: **C3-97.** The build the field figure was taken on. An anchor without one is
|
|
92
|
+
#: a measurement that can outlive its build and keep deciding: 4.18.0 deleted
|
|
93
|
+
#: two catastrophic-backtracking patterns (C3-95, C3-96) and every figure taken
|
|
94
|
+
#: before it describes a cost that no longer exists — `spring-audit` at 2 351 s
|
|
95
|
+
#: where the same command on the same commit of the same repository now takes
|
|
96
|
+
#: 8,4 s. Anchors older than the running build are still published, because a
|
|
97
|
+
#: measurement is worth more than silence; what changes is that they are
|
|
98
|
+
#: **labelled** with the build they belong to, so a reader can see the figure is
|
|
99
|
+
#: not this one's. `field_anchor_note()` renders that label and
|
|
100
|
+
#: `execution_plan` appends it to the `here:` line.
|
|
101
|
+
field_measured_version: "Optional[str]" = None
|
|
91
102
|
|
|
92
103
|
|
|
93
104
|
#: Where every `measured` figure comes from.
|
|
@@ -109,26 +120,38 @@ REFERENCE_JAVA_FILES = 2000
|
|
|
109
120
|
REFERENCE_MEASURED_VERSION = "3.2.2"
|
|
110
121
|
|
|
111
122
|
#: The other end of the measured range, and the reason this module publishes a
|
|
112
|
-
#: *class* rather than a projected duration (C4-19). Field evaluation #
|
|
123
|
+
#: *class* rather than a projected duration (C4-19). Field evaluation #22, on
|
|
113
124
|
#: Windows 11 / PowerShell 5.1 / pipx / Python 3.10: `spring-audit` on a
|
|
114
|
-
#: 3 342-file repository ran **
|
|
115
|
-
#:
|
|
116
|
-
#: scale with file count in any way this product has measured, so a projected
|
|
117
|
-
#: "~15 s on your repository" would be a confident falsehood of exactly the kind
|
|
118
|
-
#: the ledger exists to prevent. What can be said honestly is the class, the two
|
|
119
|
-
#: measured anchors, and how to run it.
|
|
125
|
+
#: 3 342-file repository ran **8,4 s** — the same command takes 8.8 s on the
|
|
126
|
+
#: 2 000-file reference, for a repository 1,7× the size.
|
|
120
127
|
#:
|
|
121
|
-
#:
|
|
122
|
-
#:
|
|
123
|
-
#:
|
|
124
|
-
#:
|
|
125
|
-
#:
|
|
128
|
+
#: **The refusal to project stands, and this evaluation strengthened it** (C3-97).
|
|
129
|
+
#: For eight releases the pair of anchors said *cost does not track file count*;
|
|
130
|
+
#: what the series actually shows is that **cost tracks the build**. The identical
|
|
131
|
+
#: command on the identical commit of the identical repository measured 2 557 s
|
|
132
|
+
#: (4.10.6), 2 398 s (4.10.7), 2 351 s (4.11.0), 2 377 s (4.12.0), 1 371 s
|
|
133
|
+
#: (4.16.0) and 8,4 s (4.18.0) — a 280× move produced by deleting two
|
|
134
|
+
#: catastrophic-backtracking patterns (C3-95, C3-96), with every payload
|
|
135
|
+
#: byte-identical throughout. A projection would therefore have to predict our own
|
|
136
|
+
#: next release, which is the confident falsehood the ledger exists to prevent.
|
|
137
|
+
#: What can be said honestly is the class, the two measured anchors, **the build
|
|
138
|
+
#: each was measured on**, and how to run it.
|
|
139
|
+
#:
|
|
140
|
+
#: History of this constant, kept because it is the measurement C3-76 exists for:
|
|
141
|
+
#: 408 s (#13) → 2 351 s (#16, C3-72) → 8,4 s (#22, C3-97). The middle figure was
|
|
142
|
+
#: quoted as an operational anchor for four releases after the build that produced
|
|
143
|
+
#: it, and told operators to detach commands that finish in seconds.
|
|
126
144
|
FIELD_ANCHOR = (
|
|
127
|
-
"field evaluation #
|
|
145
|
+
"field evaluation #22: spring-audit on 3 342 Java files took 8.4 s "
|
|
128
146
|
"(Windows, pipx, warm cache) against 8.8 s on the 2 000-file reference"
|
|
129
147
|
)
|
|
130
148
|
FIELD_ANCHOR_JAVA_FILES = 3342
|
|
131
|
-
FIELD_ANCHOR_SECONDS =
|
|
149
|
+
FIELD_ANCHOR_SECONDS = 8.4
|
|
150
|
+
|
|
151
|
+
#: The build the field anchors above were taken on. Rows carrying a different
|
|
152
|
+
#: `field_measured_version` are published with that build's name attached rather
|
|
153
|
+
#: than as figures for this one (C3-97).
|
|
154
|
+
FIELD_ANCHOR_MEASURED_VERSION = "4.18.0"
|
|
132
155
|
|
|
133
156
|
|
|
134
157
|
#: Every layer keys on `cache.worktree_signature` — the exact tree state (C1-9).
|
|
@@ -196,12 +219,12 @@ COMMANDS: tuple[CommandCache, ...] = (
|
|
|
196
219
|
"`--env-map`, `--depth N` and `--exclude` change the *analysis*, so they miss the "
|
|
197
220
|
"warmed core and rescan — this is the 171 s the field measured after a 103 s warm.",
|
|
198
221
|
"--compact 13.3 s cold → 0.3 s warm (cold re-measured on 3.7.0: was 19.3 s, C3-6); "
|
|
199
|
-
"--agent --full --env-map --depth 20 34.7 s → 33.9 s (no gain)", analysis_class="repo-wide", cold_seconds=13.3, warm_seconds=0.3, field_seconds=115.0),
|
|
222
|
+
"--agent --full --env-map --depth 20 34.7 s → 33.9 s (no gain)", analysis_class="repo-wide", cold_seconds=13.3, warm_seconds=0.3, field_seconds=115.0, field_measured_version="4.10.4"),
|
|
200
223
|
CommandCache("posture", ("cir", "parse"), "shared", False,
|
|
201
224
|
"Resolves the conditional bean graph on every run, over the shared CIR a warm "
|
|
202
225
|
"builds — the parse it used to repeat for itself. `--diff` compares two profile "
|
|
203
226
|
"sets over that one IR, so the second side costs the resolution only.",
|
|
204
|
-
"10.1 s → 1.6 s", analysis_class="repo-wide", cold_seconds=10.1, warm_seconds=1.6, field_seconds=
|
|
227
|
+
"10.1 s → 1.6 s", analysis_class="repo-wide", cold_seconds=10.1, warm_seconds=1.6, field_seconds=8.0, field_measured_version="4.18.0"),
|
|
205
228
|
CommandCache("risk", ("cir", "parse"), "shared", False,
|
|
206
229
|
"Composes what the audit, impact-chain and the posture already answer, so it "
|
|
207
230
|
"pays each of their costs once over the shared CIR a warm builds — one parse "
|
|
@@ -209,7 +232,7 @@ COMMANDS: tuple[CommandCache, ...] = (
|
|
|
209
232
|
"within the run.",
|
|
210
233
|
"not measured on the battery yet — the composition is bounded by the "
|
|
211
234
|
"`spring-audit` + `impact-chain` costs listed here, not by new analysis",
|
|
212
|
-
analysis_class="deep", field_seconds=
|
|
235
|
+
analysis_class="deep", field_seconds=73.3, field_measured_version="4.18.0"),
|
|
213
236
|
CommandCache("enrich", ("cir", "parse"), "shared", False,
|
|
214
237
|
"Runs the same composition as `risk` over the repository, then joins a SARIF "
|
|
215
238
|
"log to it. Reading the log is negligible; everything a warm helps with is the "
|
|
@@ -239,25 +262,31 @@ COMMANDS: tuple[CommandCache, ...] = (
|
|
|
239
262
|
"Recomputes the endpoint surface on every run, over a parse a warm has already "
|
|
240
263
|
"paid for. Until 3.7.0 the extractor parsed every file itself instead of reading "
|
|
241
264
|
"the shared parse cache, and a warm measurably bought it nothing (C3-6).",
|
|
242
|
-
"3.3 s → 1.4 s (re-measured on 3.7.0; was 2.8 s → 2.9 s)", analysis_class="repo-wide", cold_seconds=3.3, warm_seconds=1.4, field_seconds=
|
|
265
|
+
"3.3 s → 1.4 s (re-measured on 3.7.0; was 2.8 s → 2.9 s)", analysis_class="repo-wide", cold_seconds=3.3, warm_seconds=1.4, field_seconds=3.8, field_measured_version="4.18.0"),
|
|
243
266
|
CommandCache("spring-audit", ("ris", "parse"), "shared", False,
|
|
244
267
|
"Recomputes every run, but over a parse a warm has already paid for.",
|
|
245
|
-
"8.8 s → 3.7 s", analysis_class="repo-wide", cold_seconds=8.8, warm_seconds=3.7, field_seconds=
|
|
268
|
+
"8.8 s → 3.7 s", analysis_class="repo-wide", cold_seconds=8.8, warm_seconds=3.7, field_seconds=8.4, field_measured_version="4.18.0"),
|
|
246
269
|
CommandCache("migrate-check", ("cir",), "none", False,
|
|
247
270
|
"Computes its own inventory and shares nothing a warm builds. Only `--blast-radius` "
|
|
248
271
|
"reuses the shared CIR.",
|
|
249
|
-
"4.8 s → 4.8 s", analysis_class="repo-wide", cold_seconds=4.8, warm_seconds=4.8, field_seconds=
|
|
272
|
+
"4.8 s → 4.8 s", analysis_class="repo-wide", cold_seconds=4.8, warm_seconds=4.8, field_seconds=10.2, field_measured_version="4.18.0"),
|
|
250
273
|
CommandCache("impact-chain", ("cir", "parse"), "shared", False,
|
|
251
274
|
"The CIR is the expensive half — this is where a warm pays most.",
|
|
252
|
-
"9.9 s → 1.7 s", analysis_class="core", cold_seconds=9.9, warm_seconds=1.7
|
|
253
|
-
|
|
275
|
+
"9.9 s → 1.7 s", analysis_class="core", cold_seconds=9.9, warm_seconds=1.7,
|
|
276
|
+
field_seconds=5.5, field_measured_version="4.18.0"),
|
|
277
|
+
CommandCache("impact", ("parse",), "shared", False, "", "4.9 s → 2.8 s", analysis_class="core", cold_seconds=4.9, warm_seconds=2.8,
|
|
278
|
+
field_seconds=7.7, field_measured_version="4.18.0"),
|
|
254
279
|
CommandCache("pr-impact", ("parse",), "shared", False,
|
|
255
|
-
"Diff-dependent: the answer itself is never stored.
|
|
280
|
+
"Diff-dependent: the answer itself is never stored. What it costs follows the "
|
|
281
|
+
"diff, not the repository: 12,5 s on an ordinary one and 11,8 s on a diff of "
|
|
282
|
+
"security configuration, measured at field scale.", analysis_class="core",
|
|
283
|
+
field_seconds=12.5, field_measured_version="4.18.0"),
|
|
256
284
|
CommandCache("verify", (), "none", False, "Runs the contracts against a fresh reading.", analysis_class="core"),
|
|
257
285
|
CommandCache("verify-edit", ("parse",), "shared", True,
|
|
258
286
|
"Built for the edit loop: the parse cache is what keeps an unchanged file out of the "
|
|
259
287
|
"next run. Its own second run is faster again.",
|
|
260
|
-
"14.6 s → 9.6 s → 5.6 s on repeat", analysis_class="repo-wide", cold_seconds=14.6, warm_seconds=9.6,
|
|
288
|
+
"14.6 s → 9.6 s → 5.6 s on repeat", analysis_class="repo-wide", cold_seconds=14.6, warm_seconds=9.6,
|
|
289
|
+
field_blocked=True, field_measured_version="4.10.4"),
|
|
261
290
|
CommandCache("review-pr", ("cir",), "none", False,
|
|
262
291
|
"Diff-dependent, and it reuses the CIR only if one exists. On a small diff, loading "
|
|
263
292
|
"the warmed CIR costs more than the work it saves.",
|
|
@@ -286,11 +315,18 @@ COMMANDS: tuple[CommandCache, ...] = (
|
|
|
286
315
|
"WITHOUT a warm, a second identical run: 10.2 s → 9.4 s (5 486 files) — "
|
|
287
316
|
"no answer hit", analysis_class="repo-wide", cold_seconds=6.5, warm_seconds=0.3),
|
|
288
317
|
CommandCache("explain", ("cir",), "shared", False, "Serves from the shared CIR a warm builds.",
|
|
289
|
-
"9.8 s → 1.6 s", analysis_class="core", cold_seconds=9.8, warm_seconds=1.6
|
|
318
|
+
"9.8 s → 1.6 s", analysis_class="core", cold_seconds=9.8, warm_seconds=1.6,
|
|
319
|
+
field_seconds=4.4, field_measured_version="4.18.0"),
|
|
290
320
|
CommandCache("export", ("parse",), "shared", False, "", "8.8 s → 3.7 s", analysis_class="repo-wide", cold_seconds=8.8, warm_seconds=3.7),
|
|
291
|
-
CommandCache("repo-ir", ("parse",), "shared", False, "", "5.1 s → 2.9 s", analysis_class="repo-wide", cold_seconds=5.1, warm_seconds=2.9,
|
|
292
|
-
|
|
293
|
-
CommandCache("
|
|
321
|
+
CommandCache("repo-ir", ("parse",), "shared", False, "", "5.1 s → 2.9 s", analysis_class="repo-wide", cold_seconds=5.1, warm_seconds=2.9,
|
|
322
|
+
field_blocked=True, field_measured_version="4.10.4"),
|
|
323
|
+
CommandCache("validation", ("parse",), "shared", False, "", "11.6 s → 6.4 s", analysis_class="repo-wide", cold_seconds=11.6, warm_seconds=6.4,
|
|
324
|
+
field_seconds=17.4, field_measured_version="4.18.0"),
|
|
325
|
+
CommandCache("modernize", ("parse",), "shared", False,
|
|
326
|
+
"Blocked in the session that recorded C3-53 and measured since: a run that did "
|
|
327
|
+
"not finish once is not a command that cannot finish.",
|
|
328
|
+
"5.2 s → 3.0 s", analysis_class="repo-wide", cold_seconds=5.2, warm_seconds=3.0,
|
|
329
|
+
field_seconds=9.1, field_measured_version="4.18.0"),
|
|
294
330
|
CommandCache("chunk-file", (), "none", False, "Reads one file; nothing to cache.", analysis_class="core"),
|
|
295
331
|
CommandCache("cold-start", ("ris",), "answer", True,
|
|
296
332
|
"Reads the RIS a warm rebuilds — that is all it does. Without one it answers "
|
|
@@ -298,7 +334,7 @@ COMMANDS: tuple[CommandCache, ...] = (
|
|
|
298
334
|
"0.2 s either way", analysis_class="core", cold_seconds=0.2, warm_seconds=0.2),
|
|
299
335
|
CommandCache("trend", (), "none", False, "Reads stored baseline artifacts from disk; analyses no source, so no cache layer applies. Same command as `baseline trend`.", analysis_class="none"),
|
|
300
336
|
CommandCache("baseline", ("parse",), "shared", False, "`capture`/`diff`/`trend` over architectural metrics.",
|
|
301
|
-
"capture 8.7 s → 3.6 s", analysis_class="repo-wide", cold_seconds=8.7, warm_seconds=3.6, field_seconds=11.0),
|
|
337
|
+
"capture 8.7 s → 3.6 s", analysis_class="repo-wide", cold_seconds=8.7, warm_seconds=3.6, field_seconds=11.0, field_measured_version="4.10.4"),
|
|
302
338
|
CommandCache("retrieve", ("cir", "parse"), "shared", False,
|
|
303
339
|
"Every query builds or reuses the shared CIR a warm builds.", analysis_class="core"),
|
|
304
340
|
CommandCache("archetype", ("parse",), "shared", False, "", "9.3 s → 5.6 s", analysis_class="repo-wide", cold_seconds=9.3, warm_seconds=5.6),
|
|
@@ -363,12 +399,102 @@ class Conditioning:
|
|
|
363
399
|
return (
|
|
364
400
|
f"This repository ({self.scope}) is larger than the repository the "
|
|
365
401
|
f"figures below were measured on ({REFERENCE_JAVA_FILES} Java files), "
|
|
366
|
-
f"and cost
|
|
402
|
+
f"and what cost tracks here is the build rather than the file count: "
|
|
367
403
|
f"{FIELD_ANCHOR}. Read each figure as the reference's, not as yours; "
|
|
368
404
|
f"the `here:` lines say how each command can be run on this one."
|
|
369
405
|
)
|
|
370
406
|
|
|
371
407
|
|
|
408
|
+
def field_anchor_note(row: "Optional[CommandCache]") -> "Optional[str]":
|
|
409
|
+
"""The build a row's field figure belongs to, when it is not this one (C3-97).
|
|
410
|
+
|
|
411
|
+
``None`` when there is nothing to qualify — no field figure, or one measured on
|
|
412
|
+
the running build. Otherwise a short parenthetical naming the build, because a
|
|
413
|
+
figure carrying another release's name is a measurement and a figure carrying
|
|
414
|
+
none is a claim about this one.
|
|
415
|
+
|
|
416
|
+
The figure is never suppressed. A measurement from four releases ago still
|
|
417
|
+
beats silence for a reader deciding how to run a command; what it must not do
|
|
418
|
+
is arrive undated, which is how `spring-audit`'s 2 351 s went on recommending
|
|
419
|
+
a nightly job for a command that had come to take 8,4 s.
|
|
420
|
+
"""
|
|
421
|
+
if row is None or (row.field_seconds is None and not row.field_blocked):
|
|
422
|
+
return None
|
|
423
|
+
from sourcecode import __version__
|
|
424
|
+
|
|
425
|
+
measured_on = row.field_measured_version
|
|
426
|
+
if measured_on is None:
|
|
427
|
+
return "build not recorded"
|
|
428
|
+
if measured_on == __version__:
|
|
429
|
+
return None
|
|
430
|
+
# Short on purpose: this rides along every `here:` line and every row of
|
|
431
|
+
# `cache model`, and the build is the whole fact. The sentence that explains
|
|
432
|
+
# what an older build means is `field_currency()['statement']`, printed once.
|
|
433
|
+
return f"on {measured_on}"
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
def cost_sentence() -> str:
|
|
437
|
+
"""The one paragraph the front page says about cost, derived here (CL-21).
|
|
438
|
+
|
|
439
|
+
`--help` and the README used to carry their own hand-written version of it —
|
|
440
|
+
*"repo-wide/deep compositions can take minutes … use deep jobs nightly"* —
|
|
441
|
+
which stayed true for as long as the anchors behind it did and then went on
|
|
442
|
+
being printed for two more releases, recommending a nightly job for commands
|
|
443
|
+
that had come to finish in seconds. A sentence maintained beside the table it
|
|
444
|
+
describes is the second copy of a fact, which is the rule this module opens
|
|
445
|
+
with. It is generated from the anchors instead, so refreshing them refreshes
|
|
446
|
+
the prose.
|
|
447
|
+
"""
|
|
448
|
+
audit = next((r for r in COMMANDS if r.command == "spring-audit"), None)
|
|
449
|
+
seconds = FIELD_ANCHOR_SECONDS if audit is None or audit.field_seconds is None else audit.field_seconds
|
|
450
|
+
return (
|
|
451
|
+
f"Cost tracks the command class and the build, not the file count: "
|
|
452
|
+
f"per-symbol queries are the fast path, inventory commands scale with "
|
|
453
|
+
f"files, and a repository-wide audit measured {seconds:g} s on a "
|
|
454
|
+
f"{_thousands(FIELD_ANCHOR_JAVA_FILES)}-file repository "
|
|
455
|
+
f"({FIELD_ANCHOR_MEASURED_VERSION}). `ask cache model` prints the figure "
|
|
456
|
+
f"and the build behind it for every command; "
|
|
457
|
+
f"ASK_MAX_ANALYSIS_SECONDS/ASK_PROGRESS bound and narrate a run where CI "
|
|
458
|
+
f"wants an explicit budget."
|
|
459
|
+
)
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
def _thousands(n: int) -> str:
|
|
463
|
+
return f"{n:,}".replace(",", " ")
|
|
464
|
+
|
|
465
|
+
|
|
466
|
+
def field_currency() -> dict:
|
|
467
|
+
"""The same statement as `reference_currency`, for the field anchors (C3-97).
|
|
468
|
+
|
|
469
|
+
Published so a consumer can see which side of the pair is current without
|
|
470
|
+
parsing prose, and so the gap is visible the day it opens rather than the day
|
|
471
|
+
an evaluation points at it.
|
|
472
|
+
"""
|
|
473
|
+
from sourcecode import __version__
|
|
474
|
+
|
|
475
|
+
current = __version__
|
|
476
|
+
stale = sorted(
|
|
477
|
+
row.command
|
|
478
|
+
for row in COMMANDS
|
|
479
|
+
if (row.field_seconds is not None or row.field_blocked)
|
|
480
|
+
and row.field_measured_version not in (None, current)
|
|
481
|
+
)
|
|
482
|
+
return {
|
|
483
|
+
"anchor": FIELD_ANCHOR,
|
|
484
|
+
"measured_on_version": FIELD_ANCHOR_MEASURED_VERSION,
|
|
485
|
+
"running_version": current,
|
|
486
|
+
"current": FIELD_ANCHOR_MEASURED_VERSION == current,
|
|
487
|
+
"rows_measured_on_an_earlier_build": stale,
|
|
488
|
+
"statement": (
|
|
489
|
+
f"The field anchors were taken on {FIELD_ANCHOR_MEASURED_VERSION}; you "
|
|
490
|
+
f"are running {current}. Each row states the build its field figure "
|
|
491
|
+
f"belongs to, and no figure is projected onto this one."
|
|
492
|
+
if FIELD_ANCHOR_MEASURED_VERSION != current
|
|
493
|
+
else f"The field anchors were taken on {current}, the build you are running."
|
|
494
|
+
),
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
|
|
372
498
|
def reference_currency() -> dict:
|
|
373
499
|
"""How old the reference figures are, in releases the reader can name (F-AP).
|
|
374
500
|
|
|
@@ -429,9 +555,10 @@ def as_dict(here: "Optional[Conditioning]" = None) -> dict:
|
|
|
429
555
|
# table nine releases old cannot read as this build's measurement.
|
|
430
556
|
"reference_currency": reference_currency(),
|
|
431
557
|
# Published beside the reference so no consumer reads the figures as a
|
|
432
|
-
# law: the same command
|
|
433
|
-
#
|
|
558
|
+
# law: the same command on the same commit of the same repository has
|
|
559
|
+
# measured 2 351 s and 8,4 s on two of our own builds (C4-19, C3-97).
|
|
434
560
|
"field_anchor": FIELD_ANCHOR,
|
|
561
|
+
"field_currency": field_currency(),
|
|
435
562
|
"commands": [
|
|
436
563
|
{
|
|
437
564
|
"command": cmd.command,
|
|
@@ -453,6 +580,20 @@ def as_dict(here: "Optional[Conditioning]" = None) -> dict:
|
|
|
453
580
|
if cmd.cold_seconds is None
|
|
454
581
|
else {"cold": cmd.cold_seconds, "warm": cmd.warm_seconds}
|
|
455
582
|
),
|
|
583
|
+
# C3-97: the field figure and the build it belongs to travel
|
|
584
|
+
# together, or not at all. A consumer that reads the seconds
|
|
585
|
+
# without the build is the defect this key exists to prevent.
|
|
586
|
+
"field_measurement": (
|
|
587
|
+
None
|
|
588
|
+
if cmd.field_seconds is None and not cmd.field_blocked
|
|
589
|
+
else {
|
|
590
|
+
"seconds": cmd.field_seconds,
|
|
591
|
+
"did_not_finish": cmd.field_blocked,
|
|
592
|
+
"java_files": FIELD_ANCHOR_JAVA_FILES,
|
|
593
|
+
"measured_on_version": cmd.field_measured_version,
|
|
594
|
+
"note": field_anchor_note(cmd),
|
|
595
|
+
}
|
|
596
|
+
),
|
|
456
597
|
}
|
|
457
598
|
for cmd in COMMANDS
|
|
458
599
|
],
|
|
@@ -478,6 +619,13 @@ def render_markdown() -> str:
|
|
|
478
619
|
f"performance gate (`docs/perf/REGRESSION-GATE.md`) is what re-measures them."
|
|
479
620
|
)
|
|
480
621
|
out.append("")
|
|
622
|
+
out.append(
|
|
623
|
+
f"The second anchor is the field one, and it carries its own build for the "
|
|
624
|
+
f"same reason (C3-97): {FIELD_ANCHOR}. Where a command was measured on an "
|
|
625
|
+
f"earlier release than the one you are running, `ask cache model` says so "
|
|
626
|
+
f"on that row rather than presenting the figure as this build's."
|
|
627
|
+
)
|
|
628
|
+
out.append("")
|
|
481
629
|
out.append("| Command | A warm gives it | Measured (nothing cached → after a warm) | Repeat run cached | Layers | Notes |")
|
|
482
630
|
out.append("|---|---|---|---|---|---|")
|
|
483
631
|
for cmd in COMMANDS:
|
|
@@ -556,12 +704,26 @@ def render_text(here: "Optional[Conditioning]" = None) -> str:
|
|
|
556
704
|
lines.append("What a warm gives each command")
|
|
557
705
|
lines.append(f" Timings: {REFERENCE_REPOSITORY}, each command measured in isolation.")
|
|
558
706
|
lines.append(f" {reference_currency()['statement']}")
|
|
707
|
+
lines.append(f" {field_currency()['statement']}")
|
|
559
708
|
width = max(len(c.command) for c in COMMANDS)
|
|
560
709
|
for cmd in COMMANDS:
|
|
561
710
|
repeat = "repeat cached" if cmd.repeat else "recomputes"
|
|
562
711
|
lines.append(f" {cmd.command.ljust(width)} {_WARM_LABEL[cmd.warm]:<16} ({repeat})")
|
|
563
712
|
if cmd.measured:
|
|
564
713
|
lines.append(f" {' ' * width} measured: {cmd.measured}")
|
|
714
|
+
if cmd.field_seconds is not None or cmd.field_blocked:
|
|
715
|
+
# C3-97: never the seconds without the build they were taken on.
|
|
716
|
+
note = field_anchor_note(cmd)
|
|
717
|
+
shown = (
|
|
718
|
+
"did not finish in an interactive session"
|
|
719
|
+
if cmd.field_seconds is None
|
|
720
|
+
else f"{cmd.field_seconds:g} s"
|
|
721
|
+
)
|
|
722
|
+
suffix = f" ({note})" if note else ""
|
|
723
|
+
lines.append(
|
|
724
|
+
f" {' ' * width} field: {shown} at "
|
|
725
|
+
f"{_thousands(FIELD_ANCHOR_JAVA_FILES)} Java files{suffix}"
|
|
726
|
+
)
|
|
565
727
|
if cmd.note:
|
|
566
728
|
lines.append(f" {' ' * width} {cmd.note}")
|
|
567
729
|
if here is not None and cmd.command in here.per_command:
|