sourcecode 5.1.0__tar.gz → 5.2.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-5.1.0 → sourcecode-5.2.0}/.github/workflows/perf-gate.yml +12 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/CHANGELOG.md +72 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/PKG-INFO +3 -3
- {sourcecode-5.1.0 → sourcecode-5.2.0}/README.md +2 -2
- {sourcecode-5.1.0 → sourcecode-5.2.0}/pyproject.toml +1 -1
- {sourcecode-5.1.0 → sourcecode-5.2.0}/scripts/perf_gate.py +23 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/scripts/perf_harness.py +60 -8
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/__init__.py +1 -1
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/architectural_delta.py +57 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/cache_model.py +92 -29
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/cli.py +110 -32
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/contract_diff.py +27 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/execution_plan.py +41 -2
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/perf.py +102 -5
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/verify_edit.py +70 -24
- {sourcecode-5.1.0 → sourcecode-5.2.0}/.github/workflows/build-windows.yml +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/.gitignore +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/.ruff.toml +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/CLAUDE.md +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/CONTRIBUTING.md +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/LICENSE +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/SECURITY.md +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/raw +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/scripts/compare_integration_engines.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/scripts/customer_smoke_test.sh +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/scripts/generate_jdk_exports.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/scripts/sync_gate_anchors.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/adaptive_scanner.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/archetype.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/architectural_baseline.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/architecture_analyzer.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/architecture_summary.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/ast_extractor.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/audit_report.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/baseline_autocapture.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/cache.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/call_surface.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/caller_metrics.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/caller_reach.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/canonical_ir.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/chain_rules.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/change_plan.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/cir_graphs.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/classifier.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/client_calls.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/code_notes_analyzer.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/compare.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/confidence_analyzer.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/constraint_diff.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/container_wiring.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/context_cache.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/context_graph.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/context_scorer.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/context_summarizer.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/contract_init.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/contract_model.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/contract_pipeline.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/coverage_parser.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/data_exposure.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/data_labels.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/declarations.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/defect_identity.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/degradation.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/dependency_analyzer.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/deployment_prefix.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/detach.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/detectors/__init__.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/detectors/base.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/detectors/csproj_parser.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/detectors/dart.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/detectors/dotnet.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/detectors/elixir.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/detectors/go.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/detectors/heuristic.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/detectors/hybrid.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/detectors/java.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/detectors/jvm_ext.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/detectors/nodejs.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/detectors/parsers.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/detectors/php.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/detectors/project.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/detectors/python.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/detectors/ruby.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/detectors/rust.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/detectors/systems.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/detectors/terraform.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/detectors/tooling.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/doc_analyzer.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/dynamic_argument_surface.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/endpoint_literals.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/endpoint_metrics.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/entrypoint_classifier.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/env_analyzer.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/envelope.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/environment_resolution.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/error_schema.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/evidence_provider.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/explain.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/facts/__init__.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/facts/registry.json +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/file_chunker.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/file_classifier.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/filter_surface.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/format_contract.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/fqn_utils.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/gate_anchors.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/git_analyzer.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/git_checkout.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/graph_analyzer.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/graph_evidence.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/hibernate_strat.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/identity_fallback.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/integration_coordinates.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/jdk_exports.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/license.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/mcp/__init__.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/mcp/dependency_import.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/mcp/onboarding/__init__.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/mcp/onboarding/applier.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/mcp/onboarding/backup.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/mcp/onboarding/detector.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/mcp/onboarding/planner.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/mcp/orchestrator.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/mcp/registry.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/mcp/runner.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/mcp/server.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/mcp_nudge.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/metrics_analyzer.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/migrate_check.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/migration_blast.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/non_coverage.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/openapi_surface.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/openrewrite_recipe.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/output_budget.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/output_encoding.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/parallel.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/parse_cache.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/partial_contract.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/path_admission.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/path_filters.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/phased_run.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/pipe_contract.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/posture.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/pr_comment_renderer.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/pr_impact.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/prepare_context.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/progress.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/provenance.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/ranking_engine.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/readiness_timeline.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/readonly.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/reconciliation.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/redactor.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/reference_facts.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/release_info.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/relevance_scorer.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/remedies.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/rename_refactor.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/repo_classifier.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/repository_ir.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/retrieval/__init__.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/retrieval/context.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/retrieval/errors.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/retrieval/executor.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/retrieval/planner.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/retrieval/query.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/retrieval/request.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/retrieval/resolution.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/retrieval/result.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/retrieval/retriever.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/retrieval/runtime.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/retrieval/steps.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/retrieval/steps_endpoint.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/retrieval/steps_graph.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/retrieval/steps_impact.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/retrieval/steps_intf.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/retrieval/steps_struct.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/retrieval/steps_txsec.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/ris.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/risk.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/rule_catalog.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/rule_pass.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/runs.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/runtime_classifier.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/sarif.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/scanner.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/schema.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/schemas/envelope-v1.schema.json +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/security_chain.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/security_config.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/security_config_scan.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/security_posture.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/semantic_analyzer.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/semantic_impact_engine.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/semantic_integration_engine.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/semantic_services.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/serializer.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/servlet_surface.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/source_text.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/spring_event_topology.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/spring_findings.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/spring_impact.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/spring_model.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/spring_profiles.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/spring_properties.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/spring_security_audit.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/spring_semantic.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/spring_tx_analyzer.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/summarizer.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/target_admission.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/telemetry/__init__.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/telemetry/config.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/telemetry/consent.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/telemetry/events.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/telemetry/filters.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/telemetry/transport.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/test_gap_ranking.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/test_sources.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/text_input.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/token_estimate.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/tree_utils.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/type_usage_surface.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/validation_inference.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/validation_surface.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/verify_repo.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/verify_rules.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/version_check.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/src/sourcecode/workspace.py +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/supabase/functions/README.md +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/supabase/functions/get-license/index.ts +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/supabase/functions/lemonsqueezy-webhook/index.ts +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/supabase/functions/telemetry/index.ts +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/supabase/sql/license_event_ordering.sql +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/supabase/sql/licensing_schema.sql +0 -0
- {sourcecode-5.1.0 → sourcecode-5.2.0}/supabase/sql/telemetry_events.sql +0 -0
|
@@ -7,7 +7,14 @@ name: Performance regression gate
|
|
|
7
7
|
# population are declared in `sourcecode.perf` and documented in
|
|
8
8
|
# `docs/perf/REGRESSION-GATE.md`; nothing here carries a number of its own.
|
|
9
9
|
|
|
10
|
+
# C3-110: for five releases this ran nightly and on demand, and nothing in the
|
|
11
|
+
# release path asked it anything - so a release could regress and ship, and the
|
|
12
|
+
# nightly would report it to nobody at 03:00. A tag is a release, and a release
|
|
13
|
+
# is gated.
|
|
10
14
|
on:
|
|
15
|
+
push:
|
|
16
|
+
tags:
|
|
17
|
+
- "v*"
|
|
11
18
|
schedule:
|
|
12
19
|
# Nightly, after the day's merges have settled.
|
|
13
20
|
- cron: "0 3 * * *"
|
|
@@ -85,10 +92,15 @@ jobs:
|
|
|
85
92
|
--out perf-run
|
|
86
93
|
|
|
87
94
|
- name: Gate
|
|
95
|
+
# Two comparisons, one verdict. `--baseline` is the previous release and
|
|
96
|
+
# decides; `--drift-baseline` is the best build ever measured and is
|
|
97
|
+
# published - a staircase of steps each under the threshold is invisible
|
|
98
|
+
# to the first and visible to the second (C3-110).
|
|
88
99
|
run: |
|
|
89
100
|
python3 scripts/perf_gate.py \
|
|
90
101
|
--baseline "$BASELINE_DIR" \
|
|
91
102
|
--require-baseline \
|
|
103
|
+
--drift-baseline "docs/perf/baselines/$(python3 -c "import json;print(json.load(open('gate-config.json'))['drift_baseline'])")" \
|
|
92
104
|
--current perf-run \
|
|
93
105
|
--report perf-run/gate.json \
|
|
94
106
|
--table perf-run/RELEASE-TABLE.md
|
|
@@ -2,6 +2,78 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [5.2.0] — 2026-08-11
|
|
6
|
+
|
|
7
|
+
**The queue field evaluation #26 opened, and the row underneath the other rows.**
|
|
8
|
+
The eleventh round retested 5.1.0 on the same subject with the same total purge,
|
|
9
|
+
scored 8,4/10, and printed the series that names the real defect: `validation` on
|
|
10
|
+
one commit of one repository, across eleven releases —
|
|
11
|
+
`35,4 → 14,0 → 36,8 → 35,8 → 41,8 → 17,8 → 39,8 → 13,8 → 34,1 → 39,5 s`. Four
|
|
12
|
+
oscillations of ~2,9×, no net direction, and a green gate throughout.
|
|
13
|
+
|
|
14
|
+
No analysis changes: what moves is what the product does when there is nothing to
|
|
15
|
+
diff, when two states are one state, when it writes an IR to a file, and when it
|
|
16
|
+
tells you what a command costs.
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- **The release is gated, over the population the field measures (C3-110).** The
|
|
21
|
+
detector has existed since 4.13.0 and had never blocked a release: nothing in
|
|
22
|
+
the release path asked it anything (`push: tags: v*` does now; the nightly
|
|
23
|
+
stays, to catch a regression the day it lands rather than the day it ships);
|
|
24
|
+
its population was six commands against the eighteen the field times (`risk`,
|
|
25
|
+
`modernize`, `repo-ir` and `data-exposure` are gated now, and every exclusion
|
|
26
|
+
carries its reason); and it compared against the previous release alone, which
|
|
27
|
+
passes every step of a staircase — `drift_report()` publishes the distance from
|
|
28
|
+
the best build this product has measured, without deciding, because some of that
|
|
29
|
+
distance is work deliberately added and the comparison cannot tell which. Two
|
|
30
|
+
defects found while measuring the gate itself: **cold cells were not cold**
|
|
31
|
+
(only the snapshot layer was isolated, so every cold run inherited the previous
|
|
32
|
+
cell's parse store — the exact regime four in-house A/Bs failed to reproduce a
|
|
33
|
+
field regression in), and **a failed run was recorded as a fast one**
|
|
34
|
+
(`--no-cache` is rejected by most subcommands, so `ask risk . --no-cache` exited
|
|
35
|
+
2 and the harness timed the error envelope at ~0,29 s on any repository).
|
|
36
|
+
- **A figure that advises names the build it was measured on (C3-110/C3-109).**
|
|
37
|
+
`spring-audit` published *"8,4 s (4.18.0)"* while the same command measured
|
|
38
|
+
31,0 s on the build in hand, and `risk` carried *"not a foreground run here — a
|
|
39
|
+
nightly job"* off a 73,3 s anchor from another build while the field ran it in
|
|
40
|
+
the foreground in 77,2 s. Advising surfaces now say the build **and** that this
|
|
41
|
+
build has not been re-measured, and *"not a foreground run"* is reserved for
|
|
42
|
+
figures above 120 s: between the thresholds a command is offered with its cost
|
|
43
|
+
attached. The anchors are refreshed from evaluation #26.
|
|
44
|
+
- **A tree with nothing to diff is not analysed (C3-102).** `verify-edit` spent
|
|
45
|
+
119,5 s on the field's repository to produce 807 bytes saying the tree is clean.
|
|
46
|
+
Every axis diffs the two models and on a clean tree they are one object, so no
|
|
47
|
+
analysis can change the answer: the clean run takes a model already cached for
|
|
48
|
+
that tree state and builds nothing when there is none. The verdict publishes
|
|
49
|
+
what it read, including the claim it does not make — `pass` means the working
|
|
50
|
+
tree equals HEAD, not that HEAD was audited. **9,94 s → 0,62 s** on a clean
|
|
51
|
+
worktree of BroadleafCommerce, every layer purged.
|
|
52
|
+
- **One tree state is not analysed at all (C3-107).** 5.1.0 stopped the second
|
|
53
|
+
build; this stops the first. `delta` **8,08 → 0,35 s** and `contract-diff`
|
|
54
|
+
**13,69 → 0,33 s** on the same subject, with every delta published as the zero
|
|
55
|
+
determinism proves and every per-side total as `null` — never 0, because an axis
|
|
56
|
+
nobody measured is unknown. `contract-diff` also states what `unchanged` means:
|
|
57
|
+
the difference between the two states, not the health of the contract in either.
|
|
58
|
+
- **The written IR has a ceiling, and the refusal reaches a script (C3-111).** The
|
|
59
|
+
stdout guard was real and the `-o` path had no limit at all, while the pre-build
|
|
60
|
+
size band travels through a notice that is silent off-TTY — so the run that
|
|
61
|
+
writes the file is the one that hears nothing: 101 254 852 B, byte-identical
|
|
62
|
+
across three releases. An estimate above 50 MB now refuses **before the
|
|
63
|
+
analysis**, through the error envelope, naming the band, its basis and the four
|
|
64
|
+
ways out that already existed (`--summary-only`, `--max-nodes/--max-edges`,
|
|
65
|
+
`--gzip`, `--force`).
|
|
66
|
+
|
|
67
|
+
### Measured, not fixed
|
|
68
|
+
|
|
69
|
+
- **C3-103 (two root views of one state).** On a purged BroadleafCommerce
|
|
70
|
+
worktree: `--compact --git-context --env-map` 14,1 s, `--agent` after it 20,5 s,
|
|
71
|
+
`--agent` alone 25,3 s. The analysis difference between the two cores is exactly
|
|
72
|
+
one flag (`graph_modules`), so the increment is augmenting a cached core with one
|
|
73
|
+
analyzer — with byte-identity against a cold `--agent` run as its acceptance
|
|
74
|
+
test. A core that is *almost* the cold one is the C3-94 class of defect, so it is
|
|
75
|
+
not attempted under a deadline.
|
|
76
|
+
|
|
5
77
|
## [5.1.0] — 2026-08-11
|
|
6
78
|
|
|
7
79
|
**The operational queue field evaluation #25 left open, and the one row it opened
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sourcecode
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.2.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`**
|
|
@@ -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 5.
|
|
129
|
+
ask version # ask 5.2.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`**
|
|
@@ -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 5.
|
|
91
|
+
ask version # ask 5.2.0 — and, on a build that has aged,
|
|
92
92
|
# how many releases have probably shipped since
|
|
93
93
|
```
|
|
94
94
|
|
|
@@ -114,6 +114,11 @@ def _print_config() -> int:
|
|
|
114
114
|
"deciding_modes": list(perf.RELEASE_GATE_DECIDING_MODES),
|
|
115
115
|
"min_runs": perf.RELEASE_GATE_MIN_RUNS,
|
|
116
116
|
"commands": list(perf.RELEASE_GATE_COMMANDS),
|
|
117
|
+
# C3-110: what a command needs to be measurable at all, in one place the
|
|
118
|
+
# workflow reads instead of typing flags of its own.
|
|
119
|
+
"command_args": {k: list(v) for k, v in sorted(perf.RELEASE_GATE_COMMAND_ARGS.items())},
|
|
120
|
+
"drift_baseline": perf.RELEASE_GATE_DRIFT_BASELINE,
|
|
121
|
+
"drift_threshold": perf.RELEASE_GATE_DRIFT_THRESHOLD,
|
|
117
122
|
"exclusions": [
|
|
118
123
|
{"command": c, "reason": r} for c, r in perf.RELEASE_GATE_EXCLUSIONS
|
|
119
124
|
],
|
|
@@ -139,6 +144,9 @@ def main() -> int:
|
|
|
139
144
|
"to compare against records every cell as `new` and passes; "
|
|
140
145
|
"that is a recording, not a gate, and CI must not read it "
|
|
141
146
|
"as one.")
|
|
147
|
+
ap.add_argument("--drift-baseline", type=Path,
|
|
148
|
+
help="Directory of the best measured build. Compared and "
|
|
149
|
+
"published; never fails the run (C3-110).")
|
|
142
150
|
ap.add_argument("--report", type=Path, help="Write the perf-gate-v1 report here.")
|
|
143
151
|
ap.add_argument("--table", type=Path, help="Write the release-notes markdown table here.")
|
|
144
152
|
ap.add_argument("--self-test", action="store_true",
|
|
@@ -173,6 +181,16 @@ def main() -> int:
|
|
|
173
181
|
allow_incomparable=args.allow_incomparable,
|
|
174
182
|
require_min_runs=args.min_runs,
|
|
175
183
|
)
|
|
184
|
+
drift = None
|
|
185
|
+
if args.drift_baseline:
|
|
186
|
+
drift_cells = load_cells(args.drift_baseline)
|
|
187
|
+
if drift_cells:
|
|
188
|
+
drift = perf.drift_report(drift_cells, current)
|
|
189
|
+
report["drift"] = drift
|
|
190
|
+
else:
|
|
191
|
+
print(f"no drift-baseline cells in {args.drift_baseline} — the "
|
|
192
|
+
f"distance from the best measured build was not computed.",
|
|
193
|
+
file=sys.stderr)
|
|
176
194
|
table = perf.release_table(list(current.values()), gate=report)
|
|
177
195
|
|
|
178
196
|
if args.report:
|
|
@@ -191,6 +209,11 @@ def main() -> int:
|
|
|
191
209
|
print(f"NOT MEASURED (baselined): {cid}", file=sys.stderr)
|
|
192
210
|
for cid in report["under_sampled_cells"]:
|
|
193
211
|
print(f"UNDER-SAMPLED: {cid}", file=sys.stderr)
|
|
212
|
+
if drift:
|
|
213
|
+
for entry in drift["cells"]:
|
|
214
|
+
if entry.get("status") == "drifted":
|
|
215
|
+
print(f"DRIFT vs {drift['reference']}: {entry['cell']} "
|
|
216
|
+
f"x{entry['ratio']}", file=sys.stderr)
|
|
194
217
|
|
|
195
218
|
return 0 if report["passed"] else 1
|
|
196
219
|
|
|
@@ -118,19 +118,44 @@ def build_argv(command: str, repo_path: Path, cold: bool) -> list[str]:
|
|
|
118
118
|
argv.append(command)
|
|
119
119
|
argv.append(str(repo_path))
|
|
120
120
|
argv += ["--format", "json"]
|
|
121
|
-
|
|
122
|
-
|
|
121
|
+
# C3-110: some commands need an argument to be measurable at all, and the one
|
|
122
|
+
# authority for which is `perf`, not this script and not a workflow.
|
|
123
|
+
argv += list(perf.RELEASE_GATE_COMMAND_ARGS.get(command, ()))
|
|
124
|
+
# C3-110: `--no-cache` used to be appended here for cold cells, and most
|
|
125
|
+
# subcommands **reject** it — `ask risk <repo> --no-cache` exits 2 with
|
|
126
|
+
# INVALID_INPUT — so the cold cell for every one of them timed an error
|
|
127
|
+
# envelope (~0,29 s on any repository, any size). Cold is now what the field
|
|
128
|
+
# means by cold: both cache trees emptied before the run (see `measure_cell`),
|
|
129
|
+
# which needs no flag and works for every command in the population.
|
|
123
130
|
return argv
|
|
124
131
|
|
|
125
132
|
|
|
133
|
+
class HarnessRunFailed(RuntimeError):
|
|
134
|
+
"""A measured invocation did not succeed, so it is not a measurement (C3-110).
|
|
135
|
+
|
|
136
|
+
The gate's whole claim is that a number came from the command doing its work.
|
|
137
|
+
A run that exits non-zero produced an error envelope in a third of a second on
|
|
138
|
+
a repository of any size, and recording that as `wall_ms` is not a slow gate —
|
|
139
|
+
it is a gate reporting green on a command it never ran.
|
|
140
|
+
"""
|
|
141
|
+
|
|
142
|
+
|
|
126
143
|
def run_once(argv: list[str], env: dict[str, str], perf_log: Path) -> tuple[float, float, dict | None]:
|
|
127
|
-
"""Run the CLI once. Returns (wall_ms, rss_bytes, phase_ms | None).
|
|
144
|
+
"""Run the CLI once. Returns (wall_ms, rss_bytes, phase_ms | None).
|
|
145
|
+
|
|
146
|
+
Raises :class:`HarnessRunFailed` on a non-zero exit: see the class docstring.
|
|
147
|
+
"""
|
|
128
148
|
if perf_log.exists():
|
|
129
149
|
perf_log.unlink()
|
|
130
150
|
rss_before = resource.getrusage(resource.RUSAGE_CHILDREN).ru_maxrss
|
|
131
151
|
t0 = time.perf_counter()
|
|
132
|
-
subprocess.run(argv, env=env, capture_output=True, timeout=1800)
|
|
152
|
+
proc = subprocess.run(argv, env=env, capture_output=True, timeout=1800)
|
|
133
153
|
wall_ms = (time.perf_counter() - t0) * 1000.0
|
|
154
|
+
if proc.returncode != 0:
|
|
155
|
+
detail = (proc.stderr or b"")[:400].decode("utf-8", "replace").strip()
|
|
156
|
+
raise HarnessRunFailed(
|
|
157
|
+
f"exit {proc.returncode} from `{' '.join(argv)}`: {detail or 'no stderr'}"
|
|
158
|
+
)
|
|
134
159
|
rss_after = resource.getrusage(resource.RUSAGE_CHILDREN).ru_maxrss
|
|
135
160
|
# ru_maxrss for RUSAGE_CHILDREN is the peak among reaped children; the delta
|
|
136
161
|
# approximates this run's peak. Approximate by construction — documented.
|
|
@@ -156,12 +181,21 @@ def measure_cell(command: str, repo_path: Path, mode: str, runs: int) -> dict:
|
|
|
156
181
|
phases: list[dict] = []
|
|
157
182
|
|
|
158
183
|
with tempfile.TemporaryDirectory(prefix="perf-cache-") as cache_dir, \
|
|
184
|
+
tempfile.TemporaryDirectory(prefix="perf-ctx-") as ctx_dir, \
|
|
159
185
|
tempfile.TemporaryDirectory(prefix="perf-log-") as log_dir:
|
|
160
186
|
perf_log = Path(log_dir) / "phases.jsonl"
|
|
161
187
|
base_env = dict(os.environ)
|
|
162
188
|
base_env[perf.ENV_ENABLE] = "1"
|
|
163
189
|
base_env[perf.ENV_LOG] = str(perf_log)
|
|
164
190
|
base_env["SOURCECODE_CACHE_DIR"] = cache_dir
|
|
191
|
+
# **C3-110.** `SOURCECODE_CACHE_DIR` isolates the snapshot/view layer and
|
|
192
|
+
# nothing else: the shared CIR and the content-addressed parse store live
|
|
193
|
+
# under `SOURCECODE_CONTEXT_CACHE_DIR` (default `~/.sourcecode`), so every
|
|
194
|
+
# "cold" cell ran with a parse cache the previous cell had filled. The
|
|
195
|
+
# cold regime C3-108 added to the gate is the regime every field report
|
|
196
|
+
# since #23 measures — after purging exactly these two trees — and it was
|
|
197
|
+
# the one regime the harness was not measuring.
|
|
198
|
+
base_env["SOURCECODE_CONTEXT_CACHE_DIR"] = ctx_dir
|
|
165
199
|
|
|
166
200
|
# Warm mode: one un-recorded priming run to populate the cache, then the
|
|
167
201
|
# first measured warm run is still discarded (belt and suspenders).
|
|
@@ -169,9 +203,10 @@ def measure_cell(command: str, repo_path: Path, mode: str, runs: int) -> dict:
|
|
|
169
203
|
for i in range(n):
|
|
170
204
|
argv = build_argv(command, repo_path, cold=cold)
|
|
171
205
|
if cold:
|
|
172
|
-
# Each cold run gets
|
|
173
|
-
for
|
|
174
|
-
|
|
206
|
+
# Each cold run gets pristine cache dirs — both of them (C3-110).
|
|
207
|
+
for base in (cache_dir, ctx_dir):
|
|
208
|
+
for child in Path(base).iterdir():
|
|
209
|
+
shutil.rmtree(child, ignore_errors=True) if child.is_dir() else child.unlink()
|
|
175
210
|
wall, rss, phase = run_once(argv, base_env, perf_log)
|
|
176
211
|
if mode == "warm" and i == 0:
|
|
177
212
|
continue # discard cache-fill run
|
|
@@ -234,6 +269,7 @@ def main() -> int:
|
|
|
234
269
|
|
|
235
270
|
out_dir.mkdir(parents=True, exist_ok=True)
|
|
236
271
|
failures: list[tuple[str, dict]] = []
|
|
272
|
+
not_measured: list[str] = []
|
|
237
273
|
for cmd, name, mode in plan:
|
|
238
274
|
subdir = FLEET.get(name, name)
|
|
239
275
|
repo_path = args.fleet_root / subdir
|
|
@@ -245,6 +281,15 @@ def main() -> int:
|
|
|
245
281
|
cell = measure_cell(cmd, repo_path, mode, args.runs)
|
|
246
282
|
except subprocess.TimeoutExpired:
|
|
247
283
|
print(" TIMEOUT", file=sys.stderr)
|
|
284
|
+
not_measured.append(f"{name}__{cmd or 'ask'}__{mode}: timeout")
|
|
285
|
+
continue
|
|
286
|
+
except HarnessRunFailed as exc:
|
|
287
|
+
# C3-110: a cell that did not run is not written, so the gate reads it
|
|
288
|
+
# as `missing` — which it already fails on — instead of blessing an
|
|
289
|
+
# error envelope as a fast command.
|
|
290
|
+
print(" FAILED", file=sys.stderr)
|
|
291
|
+
print(f" {exc}", file=sys.stderr)
|
|
292
|
+
not_measured.append(f"{name}__{cmd or 'ask'}__{mode}: {exc}")
|
|
248
293
|
continue
|
|
249
294
|
fname = f"{name}__{cmd or 'ask'}__{mode}.json"
|
|
250
295
|
(out_dir / fname).write_text(json.dumps(cell, indent=2) + "\n", encoding="utf-8")
|
|
@@ -276,13 +321,20 @@ def main() -> int:
|
|
|
276
321
|
print(f" p50={w['p50']}ms p95={w['p95']}ms{_gate_text} -> {fname}")
|
|
277
322
|
|
|
278
323
|
print(f"done. artifacts in {out_dir}")
|
|
324
|
+
if not_measured:
|
|
325
|
+
# Written before the gate section: a cell that was not measured is the
|
|
326
|
+
# failure the gate exists to notice, and it must not be reported as a
|
|
327
|
+
# green run with a smaller population (C3-110).
|
|
328
|
+
print("cells not measured:", file=sys.stderr)
|
|
329
|
+
for line in not_measured:
|
|
330
|
+
print(f" {line}", file=sys.stderr)
|
|
279
331
|
if failures:
|
|
280
332
|
print("perf regression gate failed:", file=sys.stderr)
|
|
281
333
|
for fname, gate in failures:
|
|
282
334
|
detail = gate.get("failed_metrics") or gate.get("reasons")
|
|
283
335
|
print(f" {fname}: {gate.get('status')} {detail}", file=sys.stderr)
|
|
284
336
|
return 1
|
|
285
|
-
return 0
|
|
337
|
+
return 1 if not_measured else 0
|
|
286
338
|
|
|
287
339
|
|
|
288
340
|
if __name__ == "__main__":
|
|
@@ -235,6 +235,63 @@ def diff_metrics(base: ArchMetrics, head: ArchMetrics) -> dict:
|
|
|
235
235
|
}
|
|
236
236
|
|
|
237
237
|
|
|
238
|
+
#: The one sentence both identical-state payloads are derived from (C3-107).
|
|
239
|
+
#: It is an argument, not an assumption, and it rests on a property this product
|
|
240
|
+
#: publishes and asserts every release: the analysis is a pure function of the
|
|
241
|
+
#: tree state, byte-identical across eleven field rounds and two major jumps.
|
|
242
|
+
IDENTICAL_STATE_BASIS = (
|
|
243
|
+
"The two states are one tree, and the analysis is a deterministic function of "
|
|
244
|
+
"the tree state, so every delta is zero without reading the tree. What is "
|
|
245
|
+
"*not* claimed is anything about the tree itself: the per-side totals were "
|
|
246
|
+
"not measured and are `null`, never 0 — pass two different states, or run "
|
|
247
|
+
"`ask <repo>` on one of them, to measure the repository rather than the diff."
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
def identical_state_delta() -> dict:
|
|
252
|
+
"""The `architectural-delta-v1` payload for two states that are one state.
|
|
253
|
+
|
|
254
|
+
C3-107 closed the second build; the eleventh round measured what was left —
|
|
255
|
+
`delta` 24,6 s and `contract-diff` 59,9 s to conclude that a tree does not
|
|
256
|
+
differ from itself, from a purged cache. Building one side to diff it against
|
|
257
|
+
itself is a measurement of the *repository*, and this command's answer is the
|
|
258
|
+
*difference*: with one tree state the difference is empty by construction.
|
|
259
|
+
|
|
260
|
+
So the deltas are published as the zeroes they provably are, and every figure
|
|
261
|
+
that would require an analysis is `null` with the reason attached — the rule
|
|
262
|
+
this product applies everywhere else (an axis that was not measured is
|
|
263
|
+
`unknown`, never `0`).
|
|
264
|
+
"""
|
|
265
|
+
empty_counts = {"base": None, "head": None, "delta": 0}
|
|
266
|
+
return {
|
|
267
|
+
"schema": ARCH_DELTA_SCHEMA,
|
|
268
|
+
"base_cir_hash": None,
|
|
269
|
+
"head_cir_hash": None,
|
|
270
|
+
"totals": {
|
|
271
|
+
"files": dict(empty_counts),
|
|
272
|
+
"symbols": dict(empty_counts),
|
|
273
|
+
"endpoints": dict(empty_counts),
|
|
274
|
+
"dependency_edges": dict(empty_counts),
|
|
275
|
+
"import_cycles": dict(empty_counts),
|
|
276
|
+
},
|
|
277
|
+
"endpoint_surface": {
|
|
278
|
+
"added_count": 0, "removed_count": 0, "added": [], "removed": [],
|
|
279
|
+
},
|
|
280
|
+
"fan_in_shifts": {"changed_count": 0, "shifts": []},
|
|
281
|
+
"import_cycle_shifts": {
|
|
282
|
+
"added_count": 0, "removed_count": 0, "added": [], "removed": [],
|
|
283
|
+
},
|
|
284
|
+
"blast_radius_shifts": {
|
|
285
|
+
"scope": "fan_in_shift_symbols", "changed_count": 0, "shifts": [],
|
|
286
|
+
},
|
|
287
|
+
"analysis": {"performed": False, "basis": IDENTICAL_STATE_BASIS},
|
|
288
|
+
"provenance": (
|
|
289
|
+
"architectural_delta (D1), identical states: no repository was read. "
|
|
290
|
+
+ IDENTICAL_STATE_BASIS
|
|
291
|
+
),
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
|
|
238
295
|
def _transitive_reach(fqn: str, reverse_graph: dict, node_cap: int) -> int:
|
|
239
296
|
"""Size of the transitive reverse-dependency set of `fqn` (its blast radius).
|
|
240
297
|
|