sourcecode 5.8.3__tar.gz → 5.8.4__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.8.3 → sourcecode-5.8.4}/CHANGELOG.md +61 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/PKG-INFO +4 -3
- {sourcecode-5.8.3 → sourcecode-5.8.4}/README.md +2 -2
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/DEFECT-LEDGER.md +5 -4
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/USER_GUIDE.md +1 -1
- {sourcecode-5.8.3 → sourcecode-5.8.4}/pyproject.toml +5 -1
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/__init__.py +1 -1
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/cli.py +34 -17
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/progress.py +19 -4
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/repository_ir.py +142 -18
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/schema_registry.py +8 -4
- sourcecode-5.8.4/src/sourcecode/schemas/core-analysis-v1.schema.json +98 -0
- sourcecode-5.8.4/src/sourcecode/schemas/endpoints-v1.schema.json +159 -0
- sourcecode-5.8.4/src/sourcecode/schemas/pr-impact-v1.schema.json +143 -0
- sourcecode-5.8.4/src/sourcecode/schemas/verify-edit-v1.schema.json +138 -0
- sourcecode-5.8.4/src/sourcecode/schemas/verify-v1.schema.json +132 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/.github/workflows/build-windows.yml +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/.github/workflows/perf-gate.yml +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/.gitignore +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/.ruff.toml +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/CLAUDE.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/CONTRIBUTING.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/LICENSE +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/NOTICE +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/SECURITY.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/CACHE.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/COMMERCIAL-OFFER.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/CUSTOMER-VALIDATION.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/DEMO-5MIN.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/DEVELOPMENT-ROADMAP.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/EXECUTION-PLAN-12MO.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/EXECUTIVE-ROADMAP.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/MANUAL-USUARIO.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/MODERNIZATION.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/PRODUCT_AUDIT.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/PRODUCT_IDENTITY.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/PRODUCT_TIERS.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/RC1-CHECKLIST.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/RELEASE-CHECKLIST.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/architecture/CATALOG-retrieval-intents.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/architecture/DESIGN-knowledge-provider-integration.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/architecture/DESIGN-p5.3b-statement-surface.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/architecture/DESIGN-p5.5-span-index.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/architecture/DESIGN-p6-semantic-impact-engine.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/architecture/DESIGN-p6-semantic-integration-engine.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/architecture/DESIGN-p7-semantic-services.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/architecture/DESIGN-robustness-security-inference.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/architecture/DESIGN-semantic-retrieval.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/architecture/EPV-p6-class-typeref.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/architecture/REPORT-p6-flow-analyzer-comparison.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/architecture/REPORT-p6-integration-detector-comparison.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/architecture/REPORT-p8-flow-analyzer-migration.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/architecture/REPORT-p9-integration-detector-migration.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/architecture/adr/0001-semantic-ir.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/architecture/adr/0002-source-evidence-boundary.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/architecture/adr/0003-architectural-characterization.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/architecture/adr/0004-semantic-retrieval.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/architecture/adr/0005-evidence-reconciliation.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/architecture/adr/0006-performance-harness.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/architecture/adr/0007-composition-semantics.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/architecture/adr/0008-answer-coherence.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/architecture/consumer-disposition-inventory.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/architecture/overview.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/architecture/product-architecture-review.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/architecture/product-strategy-layering.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/architecture/semantic-ir-consumer-matrix.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/architecture/semantic-ir-roadmap.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/baseline-ci.yml +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/commercial-pipeline-audit.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/contracts-ci.yml +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/contracts.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/eval/2026-06-15-petclinic-rest-issue11-vets-pagination.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/eval/2026-06-15-petclinic-rest-issue147-validation.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/eval/2026-06-15-petclinic-rest-workflow.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/eval/2026-06-15-phase18-openapi-surface.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/eval/2026-06-15-phase20-validation-surface.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/eval/2026-06-16-broadleaf-checkout-impact-fieldtest.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/eval/2026-06-16-petclinic-rest-issue11-weakness2-closed.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/eval/2026-06-16-spring-petclinic-issue2333-dead-vets.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/licensing-schema.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/migrate-check.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/README.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/REGRESSION-GATE.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.15/SUMMARY.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.15/alfresco__ask__cold.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.15/alfresco__ask__warm.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.15/broadleaf__ask__cold.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.15/broadleaf__ask__warm.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.15/eureka__ask__cold.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.15/eureka__ask__warm.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.15/jenkins__ask__cold.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.15/jenkins__ask__warm.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.15/jobrunr__ask__cold.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.15/jobrunr__ask__warm.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.15/keycloak__ask__cold.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.15/keycloak__ask__warm.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.15/neo4j__ask__cold.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.15/neo4j__ask__warm.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.15/ofbiz__ask__cold.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.15/ofbiz__ask__warm.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.15/openmrs__ask__cold.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.15/openmrs__ask__warm.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.15/petclinic__ask__cold.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.15/petclinic__ask__warm.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.16/SUMMARY.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.16/alfresco__ask__cold.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.16/alfresco__ask__warm.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.16/broadleaf__ask__cold.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.16/broadleaf__ask__warm.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.16/eureka__ask__cold.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.16/eureka__ask__warm.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.16/jenkins__ask__cold.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.16/jenkins__ask__warm.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.16/jobrunr__ask__cold.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.16/jobrunr__ask__warm.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.16/keycloak__ask__cold.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.16/keycloak__ask__warm.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.16/neo4j__ask__cold.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.16/neo4j__ask__warm.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.16/ofbiz__ask__cold.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.16/ofbiz__ask__warm.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.16/openmrs__ask__cold.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.16/openmrs__ask__warm.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.16/petclinic__ask__cold.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/2.5.16/petclinic__ask__warm.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/gate-latest/README.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/gate-latest/broadleaf__ask__warm.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/gate-latest/broadleaf__endpoints__warm.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/gate-latest/broadleaf__migrate-check__warm.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/gate-latest/broadleaf__posture__warm.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/gate-latest/broadleaf__spring-audit__warm.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/gate-latest/broadleaf__validation__warm.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/perf/baselines/reference-best/README.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/posture.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/privacy.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/pro-experience-audit.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/schema.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/spec/envelope-v1.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/docs/spring-audit-ci.yml +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/scripts/compare_integration_engines.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/scripts/customer_smoke_test.sh +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/scripts/generate_jdk_exports.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/scripts/perf_gate.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/scripts/perf_harness.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/scripts/sync_gate_anchors.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/adaptive_scanner.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/archetype.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/architectural_baseline.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/architectural_delta.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/architecture_analyzer.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/architecture_summary.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/ast_extractor.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/audit_report.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/baseline_autocapture.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/breaking_changes.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/build_modules.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/bundled_docs.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/cache.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/cache_model.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/call_surface.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/caller_metrics.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/caller_reach.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/canonical_ir.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/chain_rules.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/change_plan.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/cir_graphs.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/classifier.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/client_calls.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/code_notes_analyzer.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/compare.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/confidence_analyzer.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/constraint_diff.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/consumer_join.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/container_wiring.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/context_cache.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/context_graph.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/context_scorer.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/context_summarizer.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/contract_diff.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/contract_init.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/contract_model.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/contract_pipeline.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/coverage_parser.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/data_exposure.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/data_labels.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/declarations.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/defect_identity.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/degradation.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/dependency_analyzer.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/deployment_prefix.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/detach.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/detectors/__init__.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/detectors/base.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/detectors/csproj_parser.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/detectors/dart.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/detectors/dotnet.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/detectors/elixir.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/detectors/go.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/detectors/heuristic.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/detectors/hybrid.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/detectors/java.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/detectors/jvm_ext.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/detectors/nodejs.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/detectors/parsers.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/detectors/php.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/detectors/project.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/detectors/python.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/detectors/ruby.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/detectors/rust.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/detectors/systems.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/detectors/terraform.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/detectors/tooling.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/doc_analyzer.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/dynamic_argument_surface.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/empty_reach.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/endpoint_disposition.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/endpoint_literals.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/endpoint_metrics.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/entrypoint_classifier.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/env_analyzer.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/envelope.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/environment_resolution.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/error_schema.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/evidence_provider.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/execution_plan.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/explain.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/facts/__init__.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/facts/registry.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/file_chunker.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/file_classifier.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/filter_surface.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/format_contract.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/fqn_utils.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/gate_anchors.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/git_analyzer.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/git_checkout.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/graph_analyzer.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/graph_evidence.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/hibernate_strat.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/identity_fallback.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/integration_coordinates.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/jdk_exports.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/license.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/manifest_cache.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/mcp/__init__.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/mcp/dependency_import.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/mcp/onboarding/__init__.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/mcp/onboarding/applier.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/mcp/onboarding/backup.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/mcp/onboarding/detector.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/mcp/onboarding/planner.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/mcp/orchestrator.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/mcp/registry.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/mcp/runner.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/mcp/server.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/mcp_nudge.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/metrics_analyzer.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/migrate_check.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/migration_blast.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/non_coverage.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/openapi_surface.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/openrewrite_recipe.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/output_bounds.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/output_budget.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/output_ceiling.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/output_encoding.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/output_sink.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/parallel.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/parse_cache.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/partial_contract.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/path_admission.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/path_filters.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/perf.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/phased_run.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/pipe_contract.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/posture.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/pr_comment_renderer.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/pr_impact.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/prepare_context.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/product_info.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/provenance.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/ranking_engine.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/readiness_timeline.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/readonly.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/reconciliation.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/redactor.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/reference_facts.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/release_info.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/relevance_scorer.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/remedies.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/rename_refactor.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/repo_classifier.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/retrieval/__init__.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/retrieval/context.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/retrieval/errors.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/retrieval/executor.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/retrieval/planner.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/retrieval/query.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/retrieval/request.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/retrieval/resolution.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/retrieval/result.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/retrieval/retriever.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/retrieval/runtime.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/retrieval/steps.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/retrieval/steps_endpoint.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/retrieval/steps_graph.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/retrieval/steps_impact.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/retrieval/steps_intf.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/retrieval/steps_struct.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/retrieval/steps_txsec.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/ris.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/risk.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/risk_model.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/rule_catalog.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/rule_pass.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/runs.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/runtime_classifier.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/sarif.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/scanner.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/schema.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/schemas/envelope-v1.schema.json +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/security_chain.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/security_config.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/security_config_scan.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/security_posture.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/semantic_analyzer.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/semantic_impact_engine.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/semantic_integration_engine.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/semantic_services.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/serializer.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/servlet_surface.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/source_text.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/spring_event_topology.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/spring_findings.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/spring_impact.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/spring_model.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/spring_profiles.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/spring_properties.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/spring_security_audit.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/spring_semantic.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/spring_tx_analyzer.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/sql_taint.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/summarizer.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/target_admission.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/telemetry/__init__.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/telemetry/config.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/telemetry/consent.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/telemetry/events.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/telemetry/filters.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/telemetry/transport.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/test_gap_ranking.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/test_sources.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/text_input.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/timeline.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/token_estimate.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/tree_utils.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/type_usage_surface.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/validation_inference.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/validation_surface.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/verify_edit.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/verify_repo.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/verify_rules.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/version_check.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/waivers.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/src/sourcecode/workspace.py +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/supabase/functions/README.md +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/supabase/functions/get-license/index.ts +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/supabase/functions/lemonsqueezy-webhook/index.ts +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/supabase/functions/telemetry/index.ts +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/supabase/sql/license_event_ordering.sql +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/supabase/sql/licensing_schema.sql +0 -0
- {sourcecode-5.8.3 → sourcecode-5.8.4}/supabase/sql/telemetry_events.sql +0 -0
|
@@ -2,6 +2,67 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [5.8.4] — 2026-08-17
|
|
6
|
+
|
|
7
|
+
*Four rows, and three of them were reported with the wrong cause — which is the
|
|
8
|
+
theme worth naming rather than the row count. `endpoints` printing nothing under
|
|
9
|
+
`ASK_PROGRESS=1` was not `endpoints`; the ceiling hint denying a `--compact` that
|
|
10
|
+
fits does not reproduce on this tree at all; and the ceiling row's real defect
|
|
11
|
+
was one command's guard, not the hint every command shares. Measuring before
|
|
12
|
+
fixing changed the answer three times out of four.*
|
|
13
|
+
|
|
14
|
+
*The fourth is a defect the field never reported and could not have: a Spring
|
|
15
|
+
handler written on one line was not read as a handler, and its mapping bound to
|
|
16
|
+
the next method in the class. It was found by re-measuring a row that had been
|
|
17
|
+
closed twice — the battery that closed it writes its fixture in exactly that
|
|
18
|
+
style, so it had been asserting over a 0-endpoint payload since it was written.
|
|
19
|
+
A green test certified a defect the field reproduced three cycles running.*
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
- **JSON Schema documents for the five shapes a CI gate consumes** (B19):
|
|
23
|
+
`verify-v1`, `verify-edit-v1`, `endpoints-v1`, `pr-impact-v1` and
|
|
24
|
+
`core-analysis-v1`. B6 made all 44 identifiers *resolvable*; the use case that
|
|
25
|
+
opened it was validation in CI, which needs the document, and only
|
|
26
|
+
`envelope-v1` had one. `with_published_document` goes 1 → 7. Each document is
|
|
27
|
+
validated in the suite against the payload its command actually emits, so one
|
|
28
|
+
that stops describing the answer fails the battery — cross-checking against a
|
|
29
|
+
second repository is what caught `verify-edit`'s verdict vocabulary, which is
|
|
30
|
+
`pass` / `break` / `unverified`. The two canonically-named documents sit
|
|
31
|
+
beside emitted values that are still bare numbers, deliberately: renaming an
|
|
32
|
+
emitted `schema_version` is an incompatible change, declared and not applied.
|
|
33
|
+
|
|
34
|
+
### Fixed
|
|
35
|
+
- **A phase boundary is announced whatever the machine's speed** (P1-proc).
|
|
36
|
+
`endpoints` printed **nothing** under `ASK_PROGRESS=1` — the flag an operator
|
|
37
|
+
turns on to ask *"is this working, or is it hung?"* — while `posture` printed
|
|
38
|
+
1, `spring-audit` 2 and `risk` 5. It was instrumented all along: a phase was
|
|
39
|
+
announced by the heartbeat, which fires only once the interval has elapsed, so
|
|
40
|
+
the reported counts were measuring how slow each command is rather than how
|
|
41
|
+
well it reports. Entering a phase now prints at `start()` and at every
|
|
42
|
+
`update()`; the periodic line is still rate-limited. `endpoints` goes 0 → 2
|
|
43
|
+
phase lines, and on a 24 073-file repository the first arrives at
|
|
44
|
+
`elapsed=0.0s` instead of after five seconds of silence.
|
|
45
|
+
- **`repo-ir` answers to the ceiling everybody else answers to** (ASK-09
|
|
46
|
+
residue). Its stdout guard compared against a constant bound at import, so
|
|
47
|
+
`ASK_MAX_OUTPUT_TOKENS=0` — declared in `breaking-changes-v1` as restoring
|
|
48
|
+
pre-5.7.0 behaviour exactly, and offered by `repo-ir`'s own hint — left it
|
|
49
|
+
refusing while every other command printed. Its refusal also published no
|
|
50
|
+
`estimated_tokens`, `ceiling_tokens` or `estimate_basis`: the number it
|
|
51
|
+
refused on existed only inside an English sentence. Both now come from
|
|
52
|
+
`output_ceiling.exceeds`. **The hint half of ASK-09 / B16-sv does not
|
|
53
|
+
reproduce** — measured on the reporter's own subject, `tutorials`, with no
|
|
54
|
+
environment variable and the real ceiling — and closes with a battery that
|
|
55
|
+
overflows for real instead of forcing a ceiling of 1 over a small fixture.
|
|
56
|
+
- **A handler written on one line is a handler** (E-36). `@GetMapping("/orders")
|
|
57
|
+
public List<Order> orders() { … }` was read as an annotation *line*: the
|
|
58
|
+
method was never parsed, and the mapping bound to the next declaration in the
|
|
59
|
+
class instead — so the route was published on a method that does not serve it
|
|
60
|
+
and its real handler disappeared. `endpoints tutorials` (24 073 `.java`)
|
|
61
|
+
recovers five routes, 2 263 → 2 268, none lost; the other ten golden
|
|
62
|
+
repositories are byte-identical, because none of them writes handlers this
|
|
63
|
+
way. Found while re-measuring `ASK-09`, whose own fixture is written in that
|
|
64
|
+
style and had been asserting over a 0-endpoint payload.
|
|
65
|
+
|
|
5
66
|
## [5.8.3] — 2026-08-17
|
|
6
67
|
|
|
7
68
|
*The whole queue of an adversarial audit run against BroadleafCommerce, closed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sourcecode
|
|
3
|
-
Version: 5.8.
|
|
3
|
+
Version: 5.8.4
|
|
4
4
|
Summary: Persistent structural context and ultra-fast repeated analysis for AI coding agents
|
|
5
5
|
Project-URL: Homepage, https://github.com/HarounDominique/sourcecode
|
|
6
6
|
Project-URL: Repository, https://github.com/HarounDominique/sourcecode
|
|
@@ -33,6 +33,7 @@ Requires-Dist: tree-sitter-javascript>=0.21; extra == 'ast'
|
|
|
33
33
|
Requires-Dist: tree-sitter-typescript>=0.21; extra == 'ast'
|
|
34
34
|
Requires-Dist: tree-sitter>=0.21; extra == 'ast'
|
|
35
35
|
Provides-Extra: dev
|
|
36
|
+
Requires-Dist: jsonschema>=4.18; extra == 'dev'
|
|
36
37
|
Requires-Dist: mcp<2,>=1.2; extra == 'dev'
|
|
37
38
|
Requires-Dist: mypy>=1.10; extra == 'dev'
|
|
38
39
|
Requires-Dist: pytest-xdist>=3.8; extra == 'dev'
|
|
@@ -48,7 +49,7 @@ Description-Content-Type: text/markdown
|
|
|
48
49
|
|
|
49
50
|
**Context · Impact · Migration · Architecture · Review — everything from one structural model.**
|
|
50
51
|
|
|
51
|
-

|
|
52
53
|

|
|
53
54
|
|
|
54
55
|
Copyright (c) 2026 Dominique Haroun. All rights reserved. ASK Engine 5.7.0 and
|
|
@@ -136,7 +137,7 @@ brew tap haroundominique/sourcecode && brew install sourcecode
|
|
|
136
137
|
# pip / pipx
|
|
137
138
|
pipx install sourcecode # or: pip install sourcecode
|
|
138
139
|
|
|
139
|
-
ask version # ask 5.8.
|
|
140
|
+
ask version # ask 5.8.4 — and, on a build that has aged,
|
|
140
141
|
# how many releases have probably shipped since
|
|
141
142
|
```
|
|
142
143
|
|
|
@@ -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
|
Copyright (c) 2026 Dominique Haroun. All rights reserved. ASK Engine 5.7.0 and
|
|
@@ -92,7 +92,7 @@ brew tap haroundominique/sourcecode && brew install sourcecode
|
|
|
92
92
|
# pip / pipx
|
|
93
93
|
pipx install sourcecode # or: pip install sourcecode
|
|
94
94
|
|
|
95
|
-
ask version # ask 5.8.
|
|
95
|
+
ask version # ask 5.8.4 — and, on a build that has aged,
|
|
96
96
|
# how many releases have probably shipped since
|
|
97
97
|
```
|
|
98
98
|
|
|
@@ -41,7 +41,7 @@ The facts these rows are keyed to are published: `ask schema facts-v1` prints th
|
|
|
41
41
|
| B15 | **A write that could not finish left its temporary inside the caller's repository.** The payload goes to `.<name>.tmp-<pid>-<ns>` beside the destination and is renamed onto it — atomic, and correct — but when the rename failed nothing removed the temporary. Field matrix of five bad destinations on Windows: **13,9 MB of untracked files inside the repository** (2 757 334 B per attempt plus a 153 481 B `.partial`), as `??` in `git status`. Three edges came with it: a discard sink (`nul`, `NUL`, `CON`, `/dev/null`) was reported as an I/O error for successfully throwing output away; the OS `strerror` was interpolated into our English message, so the same matrix produced two `es-ES` messages and one English; and `-o ./missing/out.json` created the tree in silence while the hint told the caller to check that the directory exists. | 5.6.1 audit, re-reported and widened in the 5.7.2 audits | **High** — it is what breaks the read-only premise the product is sold on, and the auditor grades it blocking for any pre-CI security review | **closed 5.8.1** — one authority, `sourcecode.output_sink`. The temporary is removed in a **`finally`**, so the guarantee does not depend on enumerating the exit paths correctly (which is how five escape routes were missed). A discard sink answers `written: false`, `sink: "null-device"`, `exit 0`, is matched only on the platform that reserves the name (a POSIX file called `nul` is a file), and a run writing there keeps its checkpoint in the partials directory instead of `nul.partial`. The platform's message travels in `os_error: {raw, errno, errno_name, locale}`, never inside the contract sentence, and the error publishes `cleaned_up: [...]` — what the run took back with it, so "read-only" is checkable rather than trusted. Parent directories are created, deliberately, and the hint says so. `phased_run` writes through the same authority and registers its checkpoint as this run's, so a failed answer removes it. Regression `tests/test_output_sink_leaves_nothing_b15.py`, 12 assertions, including the end-to-end matrix leaving the tree byte-identical and a negative control that cleanup can only ever remove what this run wrote. |
|
|
42
42
|
| ASK-10 | **A command with an output ceiling and no flag that can get under it.** `posture spring-boot` returned 355 032 B / `exit 0` in 5.6.1; the unified ceiling made it `exit 1` — the right call — and left no in-band way out: not `--limit`, not `--top-n`, not `--min-severity`, not `--compact`. The only routes were `--output FILE` (the answer leaves the reader's context) and `ASK_MAX_OUTPUT_TOKENS=0` (the guard off). `exit 1` on **2 of 8** corpus repositories, and `thingsboard` returned `exit 0` in 5.7.2 — so the trap closes as the product improves: the growth was **better detection**, `unresolved` 64 120 → 184 864 B because conditional beans now name `@ConditionalOnExpression` instead of a generic reason. `validation` inherits it. | 5.7.2 audits, escalated to high and blocking by the 5.8.0 re-audit | **High** — structural rather than incidental: every future gain in exhaustiveness pushes another command at the ceiling | **closed 5.8.1** — `posture` and `validation` declare `--limit N` and `--compact`, both already in the ceiling's vocabulary, so the hint offers them without being taught (verified: with the ceiling forced, both now answer *"Use --compact …, --limit N …"*). Bounding is one authority, `sourcecode.output_bounds`: it walks the payload so a `--diff` answer is bounded on **both** sides, touches lists and never counts (`summary.unresolved` is an int under the same name), and every cut publishes the `*_cap` contract — `{total, shown, omitted}` plus the registered effect — because a flag that cuts without declaring the cut is B14 again. **Nothing is bounded by default**: a payload that shrinks silently between releases is what AS-16 was filed for. Measured: `posture keycloak-config-cli` 53 115 → 4 605 B under `--compact`, summary byte-identical. The invariant is now derived from the CLI registry (`tests/test_bounding_flag_registry_ask10.py`): a command that can exceed the ceiling and declares no bounding flag fails the battery until somebody decides, with `cli.COMMANDS_WITHOUT_BOUNDING` carrying the exemptions and their reasons — including, on the record, the repository-scale commands that have not yet been measured against the ceiling. Behaviour battery `tests/test_output_bounds_ask10.py`, 13 assertions. |
|
|
43
43
|
| B4 | **`verify-edit` reported two repository-wide builds beside two empty lists, and nothing in the payload could explain them.** Reported as the empty-diff short circuit failing: clean worktree, `changed_files: []`, `changed_build_files: []`, `head_model_cache_hit: true`, `model_built: true`, 23 468 ms with `ASK_PROGRESS` never leaving *diffing working tree vs HEAD*. | 5.6.1 audit, re-reported through the 5.7.2 and 5.8.0 audits | High | **closed 5.8.1 — and the reported cause is not the cause.** Measured on BroadleafCommerce (2 985 `.java`) with a clean tree: **0,47 s, `model_built: false`** — the short circuit (C3-32 / C3-102 / AS-13) fires, and the row's stated acceptance (`< 2 000 ms`, `model_built: false`, `verdict: pass`) already held. The reported shape reproduces exactly with **one untracked `zz.yml`**: both lists empty, `model_built: true`, **16,3 s**. `_can_move_a_verdict` admits any suffix an axis may read — deliberately, since C3-14 — so a `.yml` that is not `application*` is neither a changed `.java` nor a changed build file, and appeared in **no** published list. The change set was never empty; the payload could not say so. `analysis.model_forced_by: {count, paths, reason}` is that sentence, and `basis` no longer reads *"0 changed .java file(s) and 0 changed build file(s)"* beside two full builds. Regression `tests/test_verify_edit_names_what_forced_the_model_b4.py`, 5 assertions, including the negative control that a changed `.java` file is not explained twice. ⚠ Still open and now separable: the two-build cost itself when a forcing path exists (the parse cache serves the parse; the IR assembly is paid twice), tracked as the profiling half. |
|
|
44
|
-
| ASK-09 / B16-sv | **Three output-ceiling guards written outside the authority that owns them.** Reported as `endpoints`, `cold-start` and `posture` claiming *"No smaller inline variant is available with the current flags"* while `--compact` fits (10 194 B ≈ 2,5 K tokens). | 5.7.2 audits (corpus `ASK-09`, `saint-server` `B16-sv` — one row, two origin IDs) | High (corpus: medium) | **REOPENED 5.8.2 — the closure was verified against the wrong path
|
|
44
|
+
| ASK-09 / B16-sv | **Three output-ceiling guards written outside the authority that owns them.** Reported as `endpoints`, `cold-start` and `posture` claiming *"No smaller inline variant is available with the current flags"* while `--compact` fits (10 194 B ≈ 2,5 K tokens). | 5.7.2 audits (corpus `ASK-09`, `saint-server` `B16-sv` — one row, two origin IDs) | High (corpus: medium) | **closed 5.8.4 — does not reproduce, measured on the reporter's own subject, and the residue it was hiding is fixed.** `tutorials` (24 073 `.java`), no environment variable, the real 50K ceiling: `endpoints` answers *"Use --compact …, --limit N …"* at `estimated_tokens: 241 041`, `cold-start` answers *"Use --compact …"* at 230 518, and `posture` does not arise — 134 431 B ≈ 33K tokens, `exit 0`, no hint at all. Three cycles of byte-identical text were measured against a build, not against this tree. **What the row's rewritten acceptance did buy is the battery**: `tests/test_ceiling_hint_at_real_scale_ask09.py` builds a repository that genuinely overflows (1 200 handler mappings, ~107K tokens), *discovers* the population by running every path-only command that declares a bounding flag rather than listing them, and asserts that no such command denies a flag it declares — parametrised by (command, repository), never by (command, artificial ceiling). It is verified red: forcing the *"nothing smaller"* prefix fails it. It also refuses to be vacuous — the fixture must overflow, the population must contain the two commands the field named, and the flag the hint offers must actually get the answer under the ceiling when run. ⚠ **The residue the old fixture could not see**: `repo-ir`'s stdout guard compared against a constant bound at import, so `ASK_MAX_OUTPUT_TOKENS=0` — which `breaking-changes-v1` declares as restoring pre-5.7.0 behaviour *exactly*, and which `repo-ir`'s own hint offers — left it refusing while every other command printed, and its refusal published no `estimated_tokens`, no `ceiling_tokens` and no `estimate_basis`, so the number it refused on existed only inside an English sentence. Both now come from `output_ceiling.exceeds`, the authority: one refusal, one shape, one ceiling that the caller can actually move. Measured: `=0` now exits 0, a lowered ceiling bites, and the payload carries its measurement. **History, kept because the row was closed twice on it:** REOPENED 5.8.2 — the closure was verified against the wrong path: against the unified emit seam, with the ceiling forced, `endpoints` answers *"Use --compact …, --limit N …"* and `cold-start` *"Use --compact …"* — the derivation reads `ctx.command.params` and works. What did reproduce is the half the row itself names: `repo-ir` carried **two** hand-written hints (stdout and the separate MB guard on a written file) and `migrate-check` a **third**, `_migrate_check_output_hint` — a hand-maintained copy of `build_hint`, same list, same prefix rule. A hand-written escape list cannot know which flags the caller already passed, which is the reported defect seen from the other side. `output_ceiling` now owns the whole vocabulary: `--force` as a **bypass** (offered only where the command declares it), `--gzip` as a **file-only** bound, `ways_out(destination="file")` for the MB guard — where `--output FILE` is not an escape and the token env var does not apply — and the *"nothing smaller"* prefix decided by counting the **bounding** escapes rather than the sentence, so a command whose only remaining escape is `--force` no longer opens with "Use". `_migrate_check_output_hint` is deleted. Regression `tests/test_ceiling_hint_one_authority_ask09.py`, 7 assertions, two of which are structural: `cli.py` may not contain the prefix sentence, and every `OUTPUT_TOO_LARGE` hint in it must come from `build_hint` (AST-checked). ⚠ **Reopened by the 5.8.2 re-audits, which report it as `B16` (saint-server) and `ASK-09` (corpus) — one defect, two origin IDs, like `B16-sv` before it.** The fix landed and the *hint* half did not: `ask endpoints tutorials` (24 073 `.java`) still answers *"No smaller inline variant is available with the current flags"* at `estimated_tokens: 240 908`, while `--compact` (45 902 B ≈ 11,5 K) and `--limit 50` (66 765 B ≈ 16,7 K) both fit with 4× of margin and are both declared on `endpoints`. Byte-identical text since 5.7.2, third cycle. **The diagnosis is the valuable part and it is about our method, not the code**: the regression assertion forces a low ceiling (`ASK_MAX_OUTPUT_TOKENS=1`) over a *small* fixture payload, and the path that fails is the *natural* rebase of a 240 K-token payload against the real 50 K ceiling — so the battery validates one route while the defect lives in another, and a green test certified a defect the field reproduces in three consecutive cycles. `posture` received `--limit`/`--compact` in the same release this row was closed in and *does* answer correctly, which is why the derivation looked proven. Suspected: a short-circuit that decides the hint before `ctx.command.params` is consulted, reachable only at a size the fixture never reaches (compare `ASK_MAX_OUTPUT_TOKENS=2000 ask endpoints <small>` against `ask endpoints <24k-file repo>`). **Acceptance, restated so the same closure cannot repeat**: the hint names `--limit` and `--compact` with an unforced ceiling on a repository that genuinely exceeds 50 K, and the regression is parametrised by `(command, repository)` over a fixture that really overflows — never by `(command, artificial ceiling)`. |
|
|
45
45
|
| ASK-12 | **A field describing an exclusion named three production trees as excluded.** `spring-audit spring-boot` published `patterns_matched: [… "core/", "module/", "cli/" …]` — 4 254 + 1 625 + 76 production files. Read literally, whole modules had left the audit population; measured, the exclusion was *conservative* (3 650 excluded against 4 214 files actually under a test root). The auditor filed an over-exclusion false positive on the strength of the field and then withdrew it. Cause: the constructor's fallback named `parts[0]`, the first path segment, when no source-root marker matched — and the same published field had **two constructors** with different shapes and different `basis` strings (`cli.py` for `spring-audit`, `repository_ir.py` for `endpoints`) over the one authority both already shared. | 5.7.2 audits | Low — a reporting defect, not an exclusion one, which is why it cost an auditor a round instead of costing a finding | **closed 5.8.1** — one producer, `repository_ir.excluded_test_source_detail`, beside `is_test_source_file`, which is the authority that decides the fact. `patterns_matched` can now only hold a **declared test root** — a directory whose files are excluded in their entirety — and everything else is published as a `rules_matched` census with a `rules_meaning` sentence per rule, so a per-file rule can no longer be read as a whole-directory claim. A surface counting something other than files says so (`unit`, `files_matched`), because `endpoints` counts route annotations. Regression `tests/test_test_source_exclusion_one_producer_ask12.py`, 14 assertions, two of them structural: `cli.py` may not compose the key at all, and exactly one function in `repository_ir.py` may (AST-checked). |
|
|
46
46
|
| B14 | **`--compact` made the answer smaller by making it unattributable.** `cold-start --compact` took 1 968 807 characters to 16 452 (−99,2 %) and removed **11 of 19 keys** on the way — `schema_version`, `repo_id`, `current_git_head` and the 331-character `hotspots` among them — in a document whose weight was **97,7 % `endpoints`**, and cut the endpoint list to 30 with no `*_cap`. The view an agent is told to inject could not say which repository, which commit or which schema it described. | 5.6.1 audit; AS-15 closed the root `--compact` half in 5.7.0, this is the `cold-start` half, re-reported against 5.8.0 | High | **closed 5.8.1** — three rules, in the shared bound rather than invented per command. `COMPACT_IMMUTABLE_KEYS` is the minimum no `--compact` may remove (provenance is contract, not content). Every collection that was cut declares `{total, shown, omitted}` with the registered effect — measured on BroadleafCommerce, `endpoints_cap` now publishes `total: 272, shown: 30, omitted: 242` where the cut was silent. And trimming goes by **weight**: a section already under 2 KB is kept rather than dropped by a fixed list, which is what recovers `hotspots`; everything actually removed is named with its size in `compact_omitted`. Regression `tests/test_compact_keeps_identity_b14.py`, 12 assertions, including that nothing removed claims nothing. |
|
|
47
47
|
| B2 | **A risk band and a rule severity share a vocabulary and measure different things.** They disagreed on **34 of 50 rows (68 %)** — 5 defects rated `medium` band as `critical`, 29 rated `high` band as `medium` — and both numbers were right: severity is what the rule says about the defect, the band is what the composition says about it in *this* repository (reach, access, write effect). One surface on, the collision became a contradiction a reader could not resolve: `audit-report` announced **14 critical** over bands while `--min-severity critical` filtered severities and returned **0**. | 5.6.1 audit, reproduced through 5.8.0 | Medium | **closed 5.8.1** — the band now also has a name that cannot be mistaken for a severity: `risk_tier: R1…R5`, published **beside** `band` and never instead of it, so no consumer loses a field it reads. One mapping (`risk_model.tier`), one sentence (`TIER_CROSSWALK_NOTE`) travelling with every count — it names both axes, states that they disagree by construction, gives the crosswalk, and points at `--min-band` as the flag that filters tiers rather than `--min-severity`. `risk` publishes `by_tier` beside `by_band`; `audit-report` leads with tiers, keeps bands under the legacy spelling, renders the note, and derives tiers from bands when it is handed an older bundle. Regression `tests/test_risk_tier_is_not_a_severity_b2.py`, 12 assertions, including that no tier shares a spelling with any severity and that a summary with no census still says *not measured* rather than zero. ⚠ The row's `reach`/`access`/`score_raw` per row was already shipped (`factors`, `endpoints_reached`, `reach_scope`); `--min-band` already existed on `risk` and `enrich`. |
|
|
@@ -54,13 +54,13 @@ The facts these rows are keyed to are published: `ask schema facts-v1` prints th
|
|
|
54
54
|
| P0-2 | **Endpoint reach is not monotone: a callee reports less than its caller.** `ask impact BasicPersistenceModule . --depth 6` → 268 endpoints; `ask impact CriteriaTranslator . --depth {6,8}` → **0**, with `BasicPersistenceModule` a direct caller of `CriteriaTranslator` and the walk reporting `closure_complete` for itself. Breaks the property a tech lead assumes without asking — if A calls B, the reach of B contains the reach of A — and invites excluding the core of the change | Broadleaf adversarial audit 2026-08-17 (§13) | **High** | **closed 5.8.3** (`41c3150`, `a6cbe21`) — **the reported cause is not the cause**: the hub-frontier heuristic expands its nodes in the main walk and the closure was genuinely exhausted. Two expansions applied to the SEED and to nothing else — the subtype expansion (E-27's rule) and the interface bridge for `implements` edges carrying an unresolved short name, which `ImplementationGraph` cannot see. Reach depended on where the walk started. Both now live in `caller_reach.ReachExpansion`, applied at every node by the traversal both commands share. Measured A/B, depth 6, same cache: `CriteriaTranslator` **0 → 274** endpoints, `BasicPersistenceModule` 268 → 274, `Money` 60 → 277, and `AdminSecurityFilter`/`IdOverrideTableGenerator`/`SkuCustomPersistenceHandler` unchanged at 0. Cost flat (0.09–0.16 s/query vs 0.08–0.23 s). `impact-chain` takes the same object: 0 → 239 endpoints at the same depth. ⚠ The subtype half narrows to the corresponding member and the DI bridge does not — see `C1-25`, which the first cut of this fix reopened. Battery `tests/test_reach_monotonicity_p02.py`, 8 assertions |
|
|
55
55
|
| P0-3 | **The negative set derived from `pr-impact` is wrong in ≥54 % and does not exist as a state.** `ask pr-impact . --files -` over the Hibernate surface → 258 affected endpoints; the complement against `ask endpoints` is 13, of which **3 are reachable according to ASK itself** (`impact-chain 'AdminBasicEntityController#viewEntityForm'` returns `/user-management/{id}`) and 4 more through `ProductHandlerMapping`/`CategoryHandlerMapping`/`SkuHandlerMapping` → `blCatalogService` → `ProductDaoImpl`, which is in the changed set | Broadleaf adversarial audit 2026-08-17 (§6.2, §13) | **High** — it is literally the deliverable (*"what NOT to review"*), and it would fail on the routes a QA lead checks first | **closed 5.8.3** (`1803ebb`) — three states with one authority (`sourcecode.endpoint_disposition`): `affected`, `unknown` (with the reason), `unaffected` (with its basis), partitioning the declared route population so nothing is subtracted. Three blockers demote `unaffected`, each repository-wide because none is a statement about one route: a container-wired class inside the cone (the audit's handler-mapping chain, caught through the `container_wiring` authority, never by a name), a closure that was not exhausted, a changed file that mapped to no class. Closing it needed two missing edges, both found by reproducing §6.2: **`super.m()` produced no call edge when the overriding class declared `m` itself** — which is what an override IS — and **a request handler was not callable**, because handlers carry `symbol_kind: "endpoint"` and `_type_indices` indexed only `"method"`. Re-run on the audited commit: **affected 254 · unknown 14 · unaffected 0 of 268**, with every one of the 7 rows the audit proved reachable now `affected`. Batteries `tests/test_endpoint_disposition_p03.py` (9 assertions) |
|
|
56
56
|
| B15-res | **The `.partial` is not removed on the error path.** B15 closed the atomic-temporary half in 5.8.1 and it holds — the null device answers `exit 0` with no residue, the OS locale is isolated in `os_error`, the hint names the parent-directory decision — but a fourth artefact was outside the `finally`: `ask spring-audit . -o ./saint-server` against an existing directory leaves `?? saint-server.partial` in the caller's repository. The auditor has cleaned the user's repository by hand in four consecutive sessions. | 5.8.0 → 5.8.2 re-audits (residual of `B15`) | Medium — small in code, large in claim: **the pitch is read-only deterministic analysis**, and a pre-CI security review blocks a tool that writes into the client's tree and leaves it there | **closed 5.8.3** (`6fd8001`) — registration is about OWNERSHIP, not about which writer did the writing, and the `register_artifact` call sat inside the branch of `PhasedRun._write` that writes the file itself. The three commands that supply `_safe_write_file` therefore wrote a checkpoint nobody owned, so the failure path ran `cleanup_artifacts()` against an empty registry. Reproduced before and after on `spring-audit -o <existing dir>`: `cleaned_up: []` + residue → `cleaned_up: ["target-dir.partial"]` + a clean tree. Battery `tests/test_hygiene_rows_b15res_b18_ask16.py`, with the negative control that a delivered answer leaves no checkpoint and cleanup does not fire on a good run |
|
|
57
|
-
| B16 / ASK-09 | *(see the `ASK-09 / B16-sv` row above — same defect, reopened there.)* The 5.8.2 saint-server audit files it as `B16` and the corpus audit as `ASK-09`; both describe the ceiling hint denying a `--compact` that exists and fits. Recorded here only so a reader searching `B16` lands on the reopened row rather than concluding it is untracked. | 5.8.2 re-audits | High | **
|
|
57
|
+
| B16 / ASK-09 | *(see the `ASK-09 / B16-sv` row above — same defect, reopened there.)* The 5.8.2 saint-server audit files it as `B16` and the corpus audit as `ASK-09`; both describe the ceiling hint denying a `--compact` that exists and fits. Recorded here only so a reader searching `B16` lands on the reopened row rather than concluding it is untracked. | 5.8.2 re-audits | High | **closed 5.8.4 — tracked as `ASK-09 / B16-sv`**, which closed by measurement on `tutorials` with a battery that overflows for real |
|
|
58
58
|
| B18 | **`--min-band` rejects the tier vocabulary that our own report teaches.** `audit-report` prints *"Risk tiers: R1 14, R2 7, R3 74, R4 3"*, the crosswalk *"R1 = band critical …"*, and the instruction *"Filter tiers with --min-band"* — and then `ask risk . --min-band R1` answers `INVALID_INPUT` and lists the severity spellings (`critical`, `high`, `medium`, `low`) as the only ones it takes. Two surfaces of one product, one teaching a vocabulary the other refuses. | 5.8.1 → 5.8.2 re-audits | Medium — **a regression introduced by the `B2` fix**: B2 gave the band a tier spelling precisely so it could not be read as a severity, and the filter was never taught the new vocabulary, so the product documents a filter expression it refuses | **closed 5.8.3** (`6fd8001`) — `risk_model.band_of` resolves either spelling from the crosswalk the report is already rendered from, with `BAND_OF_TIER` derived rather than retyped so the two cannot drift. `--min-band` and `--band` on `risk`, and `--min-band` on `enrich`, all read it; a rejection names both spellings. Measured on BroadleafCommerce: `--min-band R1` and `--min-band critical` both return 0 rows, `--min-band R2` returns 18. The second thread is closed too — `TIER_CROSSWALK_NOTE` names the command the flag lives on (`ask risk --min-band`) and what the other two carry instead. ⚠ **This row read `open` for its whole first day closed**: the verdict was written into the *defect* cell because the quoted error message carried escaped pipes (`\|`), and a reader — or a `grep` — counting open rows counted this one. The quoted message no longer carries a pipe; `tests/test_ledger_rows_are_wellformed.py` now asserts that every row has exactly five cells and that no cell but the last opens with a verdict. |
|
|
59
|
-
| B19 | **The schema registry resolves 44 identifiers and one of them has a document.** Residual of `B6`, which the same audit calls excellent and better than what it asked for: every identifier resolves, `pending_renames` declares the 13 non-conforming ones with their canonical name, and `endpoints` emits `endpoints-v1`. But `with_published_document: 1` — only `envelope-v1` has a JSON Schema behind it, and the rest resolve to their *description*. | 5.8.2 re-audit (residual of `B6`) | Medium — resolution enables **discovery**; the use case that opened B6 was **validation in CI** (`--ci` / `--fail-on`), and that needs the document, not the description | **
|
|
59
|
+
| B19 | **The schema registry resolves 44 identifiers and one of them has a document.** Residual of `B6`, which the same audit calls excellent and better than what it asked for: every identifier resolves, `pending_renames` declares the 13 non-conforming ones with their canonical name, and `endpoints` emits `endpoints-v1`. But `with_published_document: 1` — only `envelope-v1` has a JSON Schema behind it, and the rest resolve to their *description*. | 5.8.2 re-audit (residual of `B6`) | Medium — resolution enables **discovery**; the use case that opened B6 was **validation in CI** (`--ci` / `--fail-on`), and that needs the document, not the description | **closed 5.8.4 for the five a gate consumes** — `verify-v1`, `verify-edit-v1`, `endpoints-v1`, `pr-impact-v1` and `core-analysis-v1`, the set the audit puts at 90 % of CI use, are published as JSON Schema documents and served by `ask schema <name>`; `with_published_document` goes **1 → 7** (six identifiers; `pr-impact` and the root analysis each carry two emitted values pointing at one document). **The documents are held to the payloads, not to prose**: every one is validated in the battery against output the suite produces, so a document that stops describing what the command emits fails — a schema written from a reading of the code drifts the first time the code moves. Cross-checking against a second repository is what made them true rather than fitted: `spring-petclinic` caught `verify-edit`'s verdict vocabulary, which is `pass` / **`break`** / `unverified` and not the `fail` the first draft assumed — `break` is a statement about the change, not about the repository. **The two canonically-named documents sit beside emitted values that are still bare numbers** (`1.3`/`1.0` for `pr-impact`, `1.0` for the root analysis), deliberately: renaming an emitted `schema_version` is the incompatible change `ASK-11` exists to stop us making in silence, so `ask schema 1.0` still resolves to all seven shapes and each offers its canonical name to pin. Asserted both ways — every claimed document exists, every document is claimed, and no emitted identifier was quietly renamed to match one. Battery `tests/test_published_schema_documents_b19.py`, 30 assertions. ⚠ **Still open**: the other ~37 identifiers, which continue to resolve to their description. Original note — the row is honest about this already (`documented_note` says exactly which of the two it gives), so this is a scope completion rather than a correction. Recommended order, from the audit: the five a gate would actually consume — `verify-v1`, `verify-edit-v1`, the root analysis (`1.0` → `core-analysis-v1`), `endpoints-v1`, `pr-impact` (`1.2` → `pr-impact-v1`) — which it estimates at 90 % of CI use. Generate from the code that already owns each shape rather than by hand, since `entries[].constant` already names the authority. Publish `with_published_document` as a progress metric. |
|
|
60
60
|
| ASK-16 | **74 % of `spring-audit`'s wall clock is outside the instrumented phase.** Clean CPU, all layers warm, writing to a file to bypass ceiling estimation: wall 9,4 s against `analysis_time_ms: 2 454` — 26 % of the clock. `symbols_analyzed` identical across 5.8.0/5.8.1/5.8.2 (30 053), output grew 8–10 % while time doubled, and stdout-vs-file is only ~1,6 s, so serialisation, population, cache state and ceiling estimation are all **excluded as causes by measurement**. ~5,4 s unattributed. The command recovered 7 of the 10,4 s it lost in 5.8.1 and sits **+45 % over its 5.7.2 best** (7,6 s → 11,0 s). | 5.8.1 → 5.8.2 corpus re-audits | High | **closed 5.8.3 by measurement** (`6fd8001`) — `perf.PhaseTimings` is always on and always published: `metadata.timings` gives the per-phase split, the measured total and `unaccounted_ms`, published rather than distributed over the phases. **The missing 74 % is the CIR build.** BroadleafCommerce, 2 985 files: cold wall 9 690 ms — `cir_build` 8 679 (90 %), `security_rules` 732, `semantic_model` 63, `tx_rules` 53, unaccounted 163 (1,7 %); warm wall 2 133 ms — `cir_build` 1 118, `security_rules` 735, unaccounted 164 (7,7 %). So `analysis_time_ms: 2 454` was never the analysis, it was the security rule pass alone, and the optimisation target is the parse, not the rules. The auditor's ordering — instrument before tuning — was right, and it changed the answer |
|
|
61
61
|
| R2 | **WebFlux functional routing is not modelled.** Sixth consecutive cycle. `ask endpoints halo` returns `total: 0` over a CMS with a full REST API: `functional_routing: {files: 58, route_registrations: 183, modeled: false}`, `gaps: ["webflux_functional: 58 files"]`. Independently counted in the repository: 3 `@RestController` (all three are tests) against 89 files using `RouterFunctions`/`coRouter`/`SpringdocRouteBuilder`. | 5.6.1 → 5.8.2, every cycle | Medium — **the signalling is exemplary and carries no misreading risk**: the zero is declared with its cause, its count and a prose warning naming the failure mode. What is missing is the analysis, not the honesty | **open (6 cycles)** — cascades: `posture`, `risk`, `data-exposure` and `spring-audit` all derive their population from `cir.endpoints`, so a repository at 0 endpoints makes four commands report an empty surface honestly and uselessly (`spring-audit halo` = 0 findings on a full REST CMS). Acceptance: `endpoints halo` returns a non-empty inventory agreeing with Halo's published API on a 20-route sample, `supported_styles.webflux_functional: true`, and path resolution composes the builder chain (`route().path("/apis/x").GET("/{name}", …)`). **The only open row that requires new analysis, and the one both audits name as the single item separating the product from a 9,5.** |
|
|
62
62
|
| C3-127 | **`validation` is the only command with sustained monotonic degradation.** Steady-state, three consecutive versions worsening: 17 268 → 18 273 → 21 337 ms, **+23,6 % over the record**, while every other command returned to record level or better after the cache converged. `ASK_PROGRESS=1` attributes 100 % of it to one phase, `mapping validation surface`. | 5.8.2 re-audit | Medium | **open, premise corrected by measurement (5.8.3, `e57f3e7`).** `risk` publishes `timings` now, and on BroadleafCommerce the two substrates this row is about are **2,6 s of 13,5 s (19 %)** — `indexing the validation surface` 2 103 ms, `resolving the conditional bean graph` 525 ms — while **75 % of the clock is `reading HTTP-input query sinks` (10 051 ms)**, a phase the row does not mention. Two consequences: the ~27 s figure is a property of the audited corpus, not of the command; and within a single `risk` invocation each substrate already runs exactly once, so the saving this row imagines is a **cross-command** cache — a feature with its own contract, not a patch. What stays open is the real one: the query-sink walk |
|
|
63
|
-
| P1-proc | **A performance regression battery still does not exist, and the sixth request now arrives with a validated protocol.** `R6` (the parse cache never converging, so timings were irreproducible) was a real defect, was fixed well in 5.8.2 — dispersion between consecutive warm runs fell from 2,81× to a median of 1,04×, and `cache status` no longer prints its `over by N MB` line — and **was found only because an auditor happened to be measuring**. The same auditor then reported a 43 % regression that did not exist, and retracted it: a 2-run protocol produces artefacts up to **2,8×**. | 5.5.6 → 5.8.2, sixth request | Medium — process, not code | **open** — 5.8.2 shipped the *assertions* (`P1 / F-BR`: absolute ceilings and `max(sample) < 8 × posture_warm`, whose validation table the audit independently reproduces and extends with 5.8.2 at 6,8× ✅). What is still missing is the **harness that runs them**, and the audit supplies the missing half — a measurement protocol this ledger should treat as binding: `wall_steady()` = one discarded warm-up, then **4 runs**, report the **minimum**, and fail the measurement itself when `max/min ≥ 1,25` because at that point the cache is still evicting and no number is comparable. **Two independent corpora now report the same confounder**: 5 of 7 false positives in one audit and 4 of 7 in the other came from cache state or CPU contention — a competing `ask` process took `spring-audit` from 11,0 s to 71,4 s (+549 %), and `analysis_time_ms` inherits the bias (2 454 → 8 109 ms), so it is not an independent metric either. Acceptance: the battery runs `wall_steady`, asserts the reproducibility gate first, and no performance figure enters this ledger without a clean-CPU check.
|
|
63
|
+
| P1-proc | **A performance regression battery still does not exist, and the sixth request now arrives with a validated protocol.** `R6` (the parse cache never converging, so timings were irreproducible) was a real defect, was fixed well in 5.8.2 — dispersion between consecutive warm runs fell from 2,81× to a median of 1,04×, and `cache status` no longer prints its `over by N MB` line — and **was found only because an auditor happened to be measuring**. The same auditor then reported a 43 % regression that did not exist, and retracted it: a 2-run protocol produces artefacts up to **2,8×**. | 5.5.6 → 5.8.2, sixth request | Medium — process, not code | **open** — 5.8.2 shipped the *assertions* (`P1 / F-BR`: absolute ceilings and `max(sample) < 8 × posture_warm`, whose validation table the audit independently reproduces and extends with 5.8.2 at 6,8× ✅). What is still missing is the **harness that runs them**, and the audit supplies the missing half — a measurement protocol this ledger should treat as binding: `wall_steady()` = one discarded warm-up, then **4 runs**, report the **minimum**, and fail the measurement itself when `max/min ≥ 1,25` because at that point the cache is still evicting and no number is comparable. **Two independent corpora now report the same confounder**: 5 of 7 false positives in one audit and 4 of 7 in the other came from cache state or CPU contention — a competing `ask` process took `spring-audit` from 11,0 s to 71,4 s (+549 %), and `analysis_time_ms` inherits the bias (2 454 → 8 109 ms), so it is not an independent metric either. Acceptance: the battery runs `wall_steady`, asserts the reproducibility gate first, and no performance figure enters this ledger without a clean-CPU check. ⚠ **The cheap half closed 5.8.4, and the cause was not `endpoints`**: it was instrumented all along — one `Progress()`, started and finished — but a phase was announced by the *heartbeat*, which only fires once the interval has elapsed, so a run that finished inside 5 s printed nothing and an instrumented fast command was indistinguishable from an uninstrumented one. The counts the audit reported (posture 1 · spring-audit 2 · validation 3 · risk 5) were measuring how slow each command was, not how well it reports. Entering a phase is now announced whether or not the interval has passed, at `start()` and at every `update()`; the `_last_emit` stamp is still taken there, so the timed loop waits a full interval behind it and the two cannot double-print, and a counted stage is still rate-limited (asserted). `endpoints` also names the snapshot write as its own phase rather than charging that time to the scan. Measured: `endpoints` **0 → 2** phase lines on a 3-file repository, and on `tutorials` the first line arrives at `elapsed=0.0s` instead of after five seconds of silence. Battery `tests/test_phase_boundaries_are_announced_p1proc.py`, 8 assertions. |
|
|
64
64
|
|
|
65
65
|
---
|
|
66
66
|
|
|
@@ -423,6 +423,7 @@ class's subject, not its provenance.
|
|
|
423
423
|
| E-33 | **`verify-edit`'s contract diff attributes a removed method to the wrong type and misses a `throws` clause removal that breaks callers.** On a real working-tree change it reported `SpringBootBootstrappingServletContextListener#run` as a removed public method — `run()` belonged to an **anonymous inner class** — and did not report that `protected createInitializer(...)` lost `throws PrivilegedActionException`, which breaks every caller that catches it. The verdict itself was right (`break`, `contract_broken: 1 public API change`, correct `head_sha`, `security_delta: false`) | 5.7.3 (field, BroadleafCommerce, D8) | Low — the gate answered correctly; the evidence beside the answer is what is wrong, and this gate's product is its evidence | **closed 5.8.0** — both halves are about what an owner and a signature *are*. **Owner:** the extractor now opens a scope on an anonymous class body (`new Runnable() {`) and names it the way Java does, `Outer$1`, so the members inside are attributed to it and the type itself is a symbol — a member's owner always exists in the model. Both public-surface readers (`verify_edit._nodes_by_fqn`, `contract_diff.extract_public_contract`) skip owners containing `$`: nothing outside can name an anonymous type, so nothing can depend on it, and the discriminator is the owner rather than a naming rule. A creation whose argument list spans lines is not matched — the scope stays with the enclosing type, as before, rather than being guessed. **Signature:** the `throws` clause is captured and published as `(String)->Object throws PrivilegedActionException`, which is DR-1 applied to the other half of the declaration. End-to-end on the field's own shape: `verify-edit` went from *2 public API changes* (one of them the phantom `#run`) to **1**, and that one is the `throws` removal it used to miss entirely, cited from and to. Fleet A/B: symbol population BroadleafCommerce 30 427 → 30 694, killbill 18 513 → 18 887, spring-petclinic 267 → 269, mall 15 752 → 15 757 — the growth is the anonymous types themselves; their members are **re-attributed, not added** — and the endpoint population is byte-identical on all five (268 / 285 / 17 / 240 / 0). Regression `tests/test_contract_evidence_e33.py`, 9 assertions covering both halves and the negative controls (the named type keeps its own members; a method that throws nothing says nothing) |
|
|
424
424
|
| E-34 | **A type that declares parameters of its own has no supertype anywhere in the model — not an edge, not a signature.** Two independent readers of the `extends`/`implements` clause, both written as if a declaration went straight from the type's name to its supertype. **(a)** The `extends`/`implements` **edge** builder (`repository_ir.py:3229-3232`) matches `(?:class\|interface)\s+(\w+)(?:\s+extends\s+…)?(?:\s+implements\s+…)?\s*\{`: after the name it requires whitespace, so `class Generic<T, V> extends Base {` matches **nothing at all** — not a partial match, no edge of either kind. **(b)** `SymbolRecord.signature` drops the clause the same way, so `class B<T, V> extends HashMap<String, V>` is recorded as `class B`, and `extends_map` — derived from that signature at `repository_ir.py:7043` and handed to `_build_route_surface` — inherits the hole. Minimal end-to-end witness: three classes, `Plain extends Base` and `Generic<T, V> extends Base`; `ask explain Base` publishes **`Used By: Plain`** and nothing else. Census over 8 repositories, counting only types whose declaration really does carry a clause: **254 of 8 182 (3,1 %)** lose it — open-banking-gateway 57 of 595 (**9,6 %**), keycloak 144 of 4 356, killbill 25 of 838, BroadleafCommerce 26 of 1 965 | 5.7.3 (found while closing E-29(c), 2026-08-16) | **High** — it is silent, it is repo-wide, and it removes the one relation the two commercial blockers are about to be fixed by. A generic abstract controller loses its inheritance projection (the E-3 family), a generic filter loses the supertype `container_wiring` classifies on (E-28), and any supertype **closure** built for E-27 will walk a chain with holes in it and report the result as complete | **closed 5.8.0** — one root, one fix: the type's own parameter block is now matched as a **balanced** `<…>` span instead of "everything up to the next `>`". The unbalanced form stopped inside `<T, V>` and, to reach the body brace, had to swallow the whole `extends …` clause — which is why the same defect appeared twice from one cause, in `_CLASS_DECL_RE` (the signature) and in the edge builder (`repository_ir.py:3229`, where it matched nothing at all). Balancing is also what settles the bounded-parameter trap without a second rule: the `extends` inside `class E<T extends Map<String, X>>` belongs to the parameter, and the reader now walks past it to the type's own clause. Nesting is bounded at four levels, past which the old unbalanced branch is kept as a **fallback**: it loses the clause as it always did, and the type still matches — a declaration this product cannot fully read must not vanish from the model. ⚠ The signature half was weighed as the row asked and carries no churn: `_compute_stable_id` is built from `(package, class, kind, name)` and never from `signature`, and `contract_diff.extract_public_contract` reads signatures of **method** nodes only, so restoring a type's clause changes no identity and no contract diff. Two consumers that read the clause off `signature` (interface closure `:3688`, `Api`-interface controllers `:6737`) gain the generic types they were silently skipping. Measured A/B over **25 repositories** (61 k `.java`): **0 type declarations lost, 0 gained** — the population is byte-identical — and clause-carrying declarations recovered wherever the shape occurs: dubbo +207, alfresco +130, jenkins +104, keycloak +74, langchain4j +67, BroadleafCommerce +26, killbill +27; keycloak-config-cli and mall +0, which is the correct answer for repositories without the shape. Regression `tests/test_generic_supertype_clause_e34.py`, 15 assertions: the end-to-end witness (`explain Base` now names `Plain`, `Generic` **and** `Bounded`), the `extends` edge in the CIR, the signature, and the negative controls — record components, enums, an unparameterised type, and the past-depth declaration that must still match with no clause. The E-29(c) test that documented this hole from the other side was updated to assert both readers agree |
|
|
425
425
|
| E-35 | **A statement is parsed as a method declaration, and the method it invents is published with a call edge pointing at it.** `return unknownHelper("x");` matches the declaration shape read by `_METHOD_DECL_RE` — no modifiers, "return type" `return`, name `unknownHelper`, parameter list `"x"` — so the symbol table gained `com.a.BasicCtl#unknownHelper` with `signature: ("x")->return`, an `in_degree` of 1 and a `calls` edge from the real method that contains the statement. Census over 5 repositories: **BroadleafCommerce 1 047 of 23 913 methods (4,4 %)**, killbill 846, keycloak-config-cli 76, mall 11, spring-petclinic 6 | 5.7.3 (found while writing the E-27 negative controls, 2026-08-16) | Medium — it inflates every method population and every degree derived from it, and a phantom callee is the shape a reader cannot check: the symbol does not exist to be looked up | **closed 5.8.0** — the discriminator is the return-type slot, because nothing declares a method whose type is `return`. `_STATEMENT_HEADS` lists the keywords that start a statement and can stand where a type is read (`return`, `throw`, `new`, `else`, `assert`, `yield`, `case`, `do`, `instanceof`, `break`, `continue`, `catch`, `finally`); **`void` is deliberately absent — it is a return type**. Measured A/B: phantoms **1 047 → 0** on Broadleaf, 846 → 0 on killbill, 76 → 0 on keycloak-config-cli, and the method population falls by **exactly** that count on each repository, so no real declaration was lost; the endpoint population is byte-identical on all five. Regression `tests/test_statement_is_not_a_declaration_e35.py`, 10 assertions, of which 7 are negative controls — every real declaration in the same file, `void` kept as a type, and a method that returns a constructed object ⚠ **Testigo de campo, 2026-08-17: este cierre movió un invariante publicado y no lo declaró.** La re-auditoría de `saint-server` mide `metadata.symbols_analyzed` cayendo de 43 642 a 43 003 (−639, −1,46 %) tras cinco versiones constante, la clasifica P0 y la nombra *"AS-14 otra vez"*. Es exactamente esta fila: los dos invariantes que lo confirman —`endpoints_analyzed` 3 742 y `total_findings` 385— están intactos en su propio informe, y el −1,46 % cae dentro del censo de fantasmas medido aquí. La corrección es correcta; lo que falta es `metadata.symbols_excluded` con su razón, y la regla que AS-14 ya fijó: una población analizada no cambia entre releases sin un campo que lo explique. Se sigue como **B17-sv** en el roadmap. |
|
|
426
|
+
| E-36 | **A declaration that shares its line with its annotations is not a declaration.** `@GetMapping("/orders") public List<Order> orders() { … }` is ordinary Java, and the parse loop read it as an *annotation line*: it registered `@GetMapping`, moved on, and never parsed the method. Two losses, both silent. The handler left the symbol table, so the route lost the member that serves it; and the mapping stayed pending and bound to the **next** declaration in the class, so the route was published on a method that does not serve it — reproduced on a constructed controller as `GET /api/compact -> notAHandler`, with the real handler absent. A controller written entirely in this style answers `total: 0` under a `zero_result_reason` saying no routing construct was found. | 5.8.3, found while re-measuring `ASK-09` — the battery's own fixture writes its handlers this way and had therefore been asserting over a **0-endpoint** payload since it was written | **High** — the mis-attribution half is a wrong answer rather than a missing one, and every command downstream of the route surface keys on the handler symbol: `impact` computes a blast radius for the wrong member, `spring-audit` reads the wrong method's gate, `risk` composes over both | **closed 5.8.4** — annotations are peeled off the front of the line by `_split_leading_annotations`, and what remains is re-read as the declaration it is. One authority for where an annotation ends (`_scan_annotation`), shared with `_parse_annotation_line`, because a run of annotations can only be walked safely if both agree on the boundary. Measured on `tutorials` (24 073 `.java`): **2 263 → 2 268 endpoints**, five recovered, none lost, each verified at source — four handlers and one `@ResponseBody public FileSystemResource getFile(…)`. The other ten golden repositories are byte-identical, which is the point: the census cannot see this until a repository written in the compact style arrives. ⚠ **Two negative controls, one of which was the first cut's own regression**: a trailing comment is not a declaration (`@SaCheckPermission(…) // 注解式鉴权…` fell through to the loop's pending-annotation reset and cost sa-token a route, 214 → 213, caught by the corpus A/B and not by the suite); and only a **method or type** declaration is taken from a shared line — a field is left where it was, because `@Autowired private X x;` would add a DI `injects` edge and the interface bridge does not narrow to a member (`C1-25`, open), so the recall would arrive as a false caller rather than a better answer. Battery `tests/test_annotation_shares_its_line_e36.py`, 17 assertions |
|
|
426
427
|
|
|
427
428
|
## Class P — Product and procurement (not analysis defects)
|
|
428
429
|
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "sourcecode"
|
|
7
|
-
version = "5.8.
|
|
7
|
+
version = "5.8.4"
|
|
8
8
|
description = "Persistent structural context and ultra-fast repeated analysis for AI coding agents"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
@@ -51,6 +51,10 @@ dev = [
|
|
|
51
51
|
"ruff>=0.15",
|
|
52
52
|
"mypy>=1.10",
|
|
53
53
|
"mcp>=1.2,<2",
|
|
54
|
+
# B19: the published JSON Schema documents are checked against the payloads
|
|
55
|
+
# the commands actually emit, which needs a validator. A schema written from
|
|
56
|
+
# a reading of the code drifts the first time the code moves.
|
|
57
|
+
"jsonschema>=4.18",
|
|
54
58
|
]
|
|
55
59
|
ast = [
|
|
56
60
|
"tree-sitter>=0.21",
|
|
@@ -2927,6 +2927,12 @@ _IR_FILE_CEILING_MB: int = 50
|
|
|
2927
2927
|
#: so a reader cannot find two 50 000s and have to guess which one bites.
|
|
2928
2928
|
_OUTPUT_CEILING_DEFAULT: int = _output_ceiling.DEFAULT_CEILING_TOKENS
|
|
2929
2929
|
_OUTPUT_CEILING_ENV: str = _output_ceiling.ENV_CEILING
|
|
2930
|
+
#: The *default*, for help text that describes the shipped behaviour. It is not
|
|
2931
|
+
#: what any guard compares against: `ASK_MAX_OUTPUT_TOKENS` and
|
|
2932
|
+
#: `--max-output-tokens` move the ceiling at call time, and a constant bound at
|
|
2933
|
+
#: import cannot see them. `repo-ir` compared against this one and therefore
|
|
2934
|
+
#: refused an answer the caller had explicitly re-permitted — with a hint
|
|
2935
|
+
#: offering `ASK_MAX_OUTPUT_TOKENS=0` as the way out (ASK-09 residue).
|
|
2930
2936
|
_IR_STDOUT_CEILING_TOKENS: int = _OUTPUT_CEILING_DEFAULT
|
|
2931
2937
|
|
|
2932
2938
|
|
|
@@ -6501,26 +6507,35 @@ def repo_ir_cmd(
|
|
|
6501
6507
|
expected="--output path when --gzip is used.",
|
|
6502
6508
|
)
|
|
6503
6509
|
raise typer.Exit(1)
|
|
6504
|
-
_ir_size = len(output.encode("utf-8"))
|
|
6505
|
-
_ir_tokens_est = _ir_size // 4
|
|
6506
6510
|
# P1-C: abort when estimated tokens > the stdout ceiling unless --force
|
|
6507
6511
|
# or --output is given.
|
|
6508
|
-
|
|
6512
|
+
#
|
|
6513
|
+
# ASK-09 residue: the hint was unified here and the *guard* was not. It
|
|
6514
|
+
# compared against a constant bound at import, so the ceiling this
|
|
6515
|
+
# command answered to could not be moved — `ASK_MAX_OUTPUT_TOKENS=0`,
|
|
6516
|
+
# which `breaking_changes` declares as restoring pre-5.7.0 behaviour
|
|
6517
|
+
# exactly, and which this very hint offers, left `repo-ir` refusing
|
|
6518
|
+
# while every other command printed. `exceeds` is the authority: it
|
|
6519
|
+
# reads the ceiling at call time and returns the same measured payload
|
|
6520
|
+
# every other refusal carries, so one refusal has one shape.
|
|
6521
|
+
_ir_ceiling = _output_ceiling.exceeds(output, to_file=False)
|
|
6522
|
+
if _ir_ceiling is not None and not force:
|
|
6509
6523
|
_emit_error_json(
|
|
6510
|
-
"
|
|
6511
|
-
|
|
6512
|
-
|
|
6513
|
-
# hand it could not know which of them the caller had already
|
|
6514
|
-
# passed. The derivation reads this invocation's own parameters.
|
|
6515
|
-
hint=_output_ceiling.build_hint(),
|
|
6524
|
+
_ir_ceiling["code"],
|
|
6525
|
+
_ir_ceiling["message"],
|
|
6526
|
+
hint=_ir_ceiling["hint"],
|
|
6516
6527
|
expected=(
|
|
6517
|
-
f"Output under {
|
|
6528
|
+
f"Output under {_ir_ceiling['ceiling_tokens'] // 1000}K estimated "
|
|
6518
6529
|
f"tokens on stdout, or under {_IR_FILE_CEILING_MB} MB with "
|
|
6519
6530
|
"--output FILE — the two destinations have separate ceilings "
|
|
6520
6531
|
"in separate units"
|
|
6521
6532
|
),
|
|
6533
|
+
estimated_tokens=_ir_ceiling["estimated_tokens"],
|
|
6534
|
+
ceiling_tokens=_ir_ceiling["ceiling_tokens"],
|
|
6535
|
+
estimate_basis=_ir_ceiling["estimate_basis"],
|
|
6522
6536
|
)
|
|
6523
6537
|
raise typer.Exit(1)
|
|
6538
|
+
_ir_tokens_est = _output_ceiling.estimate_tokens(output)
|
|
6524
6539
|
if _ir_tokens_est > 10_000:
|
|
6525
6540
|
# C3-34: the run succeeded and the IR is on stdout, so this advisory
|
|
6526
6541
|
# is a note to a person — on a pipe it is noise, and on PowerShell
|
|
@@ -6935,16 +6950,18 @@ def endpoints_cmd(
|
|
|
6935
6950
|
_prog.start("scanning endpoints")
|
|
6936
6951
|
try:
|
|
6937
6952
|
data = _extract_java_endpoints(target, include_tests=include_tests)
|
|
6953
|
+
# P1-proc: the snapshot write is work this command does and waits on,
|
|
6954
|
+
# so it is a phase of its own rather than time attributed to the scan.
|
|
6955
|
+
_prog.update("updating the repository snapshot")
|
|
6956
|
+
# Update RIS api_surface section (non-fatal side-effect).
|
|
6957
|
+
try:
|
|
6958
|
+
from sourcecode.ris import update_ris_api_surface as _ris_ep
|
|
6959
|
+
_ris_ep(target, data)
|
|
6960
|
+
except Exception:
|
|
6961
|
+
pass
|
|
6938
6962
|
finally:
|
|
6939
6963
|
_prog.finish()
|
|
6940
6964
|
|
|
6941
|
-
# Update RIS api_surface section (non-fatal side-effect).
|
|
6942
|
-
try:
|
|
6943
|
-
from sourcecode.ris import update_ris_api_surface as _ris_ep
|
|
6944
|
-
_ris_ep(target, data)
|
|
6945
|
-
except Exception:
|
|
6946
|
-
pass
|
|
6947
|
-
|
|
6948
6965
|
# Apply filters before serialization.
|
|
6949
6966
|
_total_before = data.get("total", len(data.get("endpoints", [])))
|
|
6950
6967
|
endpoints_list = data.get("endpoints", [])
|
|
@@ -217,6 +217,10 @@ class Progress:
|
|
|
217
217
|
self._stop_event.clear()
|
|
218
218
|
self._thread = threading.Thread(target=self._loop, daemon=True)
|
|
219
219
|
self._thread.start()
|
|
220
|
+
# Entering the first phase is a phase boundary like any other, and the
|
|
221
|
+
# answer to "is this command instrumented?" must not depend on the run
|
|
222
|
+
# lasting longer than one heartbeat interval.
|
|
223
|
+
self._beat(force=True)
|
|
220
224
|
return self
|
|
221
225
|
|
|
222
226
|
def update(self, phase: str) -> None:
|
|
@@ -233,8 +237,9 @@ class Progress:
|
|
|
233
237
|
self._estimate = True
|
|
234
238
|
self._count_t0 = time.monotonic()
|
|
235
239
|
# C3-80: a new phase is the most informative thing this line can say, and
|
|
236
|
-
# the phase that follows it may be the long one.
|
|
237
|
-
|
|
240
|
+
# the phase that follows it may be the long one. It is announced whether
|
|
241
|
+
# or not the interval has elapsed — see `_beat(force=…)`.
|
|
242
|
+
self._beat(force=True)
|
|
238
243
|
|
|
239
244
|
def work(
|
|
240
245
|
self,
|
|
@@ -375,7 +380,7 @@ class Progress:
|
|
|
375
380
|
except Exception:
|
|
376
381
|
pass
|
|
377
382
|
|
|
378
|
-
def _beat(self) -> None:
|
|
383
|
+
def _beat(self, *, force: bool = False) -> None:
|
|
379
384
|
"""Emit from the thread doing the work, when the interval has elapsed (C3-80).
|
|
380
385
|
|
|
381
386
|
The field watched one line for **39 minutes** on the phase that holds most
|
|
@@ -394,10 +399,20 @@ class Progress:
|
|
|
394
399
|
|
|
395
400
|
Line mode only. A TTY spinner is animation at 0.08 s and re-entering its
|
|
396
401
|
frame sequence from the analysis would fight the loop, not help it.
|
|
402
|
+
|
|
403
|
+
`force=True` says *this is a phase boundary*, and a phase boundary is not
|
|
404
|
+
a heartbeat: it is the one thing the line has to say that a later line
|
|
405
|
+
cannot say for it. Rate-limiting it made the number of lines a function
|
|
406
|
+
of how slow the machine was — a command whose phases each finish inside
|
|
407
|
+
the interval printed **nothing at all** (P1-proc: `endpoints` 0 lines
|
|
408
|
+
against `posture` 1, `spring-audit` 2, `validation` 3, `risk` 5), so a
|
|
409
|
+
reader could not tell an instrumented fast command from an
|
|
410
|
+
uninstrumented one. The `_last_emit` stamp is still taken, so the timed
|
|
411
|
+
loop simply waits a full interval after it and the two never double-print.
|
|
397
412
|
"""
|
|
398
413
|
if not self._enabled or not self._line_mode or self._stopped:
|
|
399
414
|
return
|
|
400
|
-
if time.monotonic() - self._last_emit < self._interval:
|
|
415
|
+
if not force and time.monotonic() - self._last_emit < self._interval:
|
|
401
416
|
return
|
|
402
417
|
self._emit(0)
|
|
403
418
|
|