sourcecode 3.5.0__tar.gz → 3.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {sourcecode-3.5.0 → sourcecode-3.7.0}/CHANGELOG.md +305 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/PKG-INFO +1 -1
- {sourcecode-3.5.0 → sourcecode-3.7.0}/pyproject.toml +1 -1
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/__init__.py +1 -1
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/change_plan.py +5 -1
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/cli.py +461 -112
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/compare.py +75 -8
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/explain.py +11 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/hibernate_strat.py +60 -7
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/migrate_check.py +244 -19
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/output_budget.py +35 -2
- sourcecode-3.7.0/src/sourcecode/pipe_contract.py +208 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/repository_ir.py +114 -15
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/serializer.py +174 -69
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/spring_findings.py +124 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/spring_impact.py +18 -1
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/spring_security_audit.py +6 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/spring_tx_analyzer.py +6 -0
- sourcecode-3.7.0/src/sourcecode/target_admission.py +168 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/verify_edit.py +32 -9
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/verify_repo.py +22 -4
- {sourcecode-3.5.0 → sourcecode-3.7.0}/.github/workflows/build-windows.yml +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/.gitignore +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/.ruff.toml +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/CONTRIBUTING.md +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/LICENSE +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/README.md +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/SECURITY.md +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/raw +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/scripts/compare_integration_engines.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/scripts/customer_smoke_test.sh +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/scripts/generate_jdk_exports.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/scripts/perf_harness.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/adaptive_scanner.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/archetype.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/architectural_baseline.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/architectural_delta.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/architecture_analyzer.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/architecture_summary.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/ast_extractor.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/cache.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/cache_model.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/call_surface.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/caller_metrics.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/caller_reach.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/canonical_ir.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/chain_rules.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/cir_graphs.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/classifier.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/code_notes_analyzer.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/confidence_analyzer.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/constraint_diff.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/context_cache.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/context_graph.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/context_scorer.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/context_summarizer.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/contract_diff.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/contract_model.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/contract_pipeline.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/coverage_parser.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/degradation.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/dependency_analyzer.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/deployment_prefix.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/__init__.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/base.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/csproj_parser.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/dart.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/dotnet.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/elixir.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/go.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/heuristic.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/hybrid.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/java.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/jvm_ext.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/nodejs.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/parsers.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/php.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/project.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/python.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/ruby.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/rust.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/systems.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/terraform.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/detectors/tooling.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/doc_analyzer.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/dynamic_argument_surface.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/endpoint_literals.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/endpoint_metrics.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/entrypoint_classifier.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/env_analyzer.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/envelope.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/error_schema.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/evidence_provider.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/facts/__init__.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/facts/registry.json +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/file_chunker.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/file_classifier.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/filter_surface.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/format_contract.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/fqn_utils.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/git_analyzer.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/graph_analyzer.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/graph_evidence.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/integration_coordinates.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/jdk_exports.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/license.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/mcp/__init__.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/mcp/onboarding/__init__.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/mcp/onboarding/applier.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/mcp/onboarding/backup.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/mcp/onboarding/detector.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/mcp/onboarding/planner.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/mcp/orchestrator.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/mcp/registry.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/mcp/runner.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/mcp/server.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/mcp_nudge.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/metrics_analyzer.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/migration_blast.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/openapi_surface.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/parse_cache.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/path_admission.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/path_filters.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/perf.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/posture.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/pr_comment_renderer.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/pr_impact.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/prepare_context.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/progress.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/ranking_engine.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/readiness_timeline.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/reconciliation.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/redactor.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/reference_facts.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/relevance_scorer.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/rename_refactor.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/repo_classifier.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/__init__.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/context.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/errors.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/executor.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/planner.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/query.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/request.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/resolution.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/result.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/retriever.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/runtime.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/steps.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/steps_endpoint.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/steps_graph.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/steps_impact.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/steps_intf.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/steps_struct.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/retrieval/steps_txsec.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/ris.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/runtime_classifier.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/scanner.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/schema.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/schemas/envelope-v1.schema.json +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/security_config.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/security_posture.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/semantic_analyzer.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/semantic_impact_engine.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/semantic_integration_engine.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/semantic_services.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/spring_event_topology.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/spring_model.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/spring_profiles.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/spring_properties.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/spring_semantic.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/summarizer.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/telemetry/__init__.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/telemetry/config.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/telemetry/consent.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/telemetry/events.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/telemetry/filters.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/telemetry/transport.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/test_sources.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/token_estimate.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/tree_utils.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/type_usage_surface.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/validation_inference.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/validation_surface.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/verify_rules.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/version_check.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/src/sourcecode/workspace.py +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/supabase/functions/README.md +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/supabase/functions/get-license/index.ts +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/supabase/functions/lemonsqueezy-webhook/index.ts +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/supabase/functions/telemetry/index.ts +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/supabase/sql/license_event_ordering.sql +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/supabase/sql/licensing_schema.sql +0 -0
- {sourcecode-3.5.0 → sourcecode-3.7.0}/supabase/sql/telemetry_events.sql +0 -0
|
@@ -1,5 +1,310 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [3.7.0] — 2026-08-01
|
|
4
|
+
|
|
5
|
+
**The exit-code contract and the C3 surface block.** Seven rows closed: the two the field named
|
|
6
|
+
as blocking for CI (exit codes over correct answers), the fourth and fifth appearance of a
|
|
7
|
+
curated list beside real data, and three surfaces that published a promise the payload did not
|
|
8
|
+
keep.
|
|
9
|
+
|
|
10
|
+
Minor and not patch, because a pipeline can see the difference: `plan` exits 1 where it exited 0
|
|
11
|
+
over a target it never resolved (C3-29), `ask <cmd> | head` exits 0 where a correct run used to
|
|
12
|
+
exit non-zero (C3-28), `--output FILE` carries the whole answer where it was silently trimmed
|
|
13
|
+
(C3-17), `--agent` publishes sections it used to omit (C3-10), and a path-shaped target that was
|
|
14
|
+
refused as ambiguous now resolves (C3-35).
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- **A broken output pipe is no longer a failed run** (C3-28, **exit code changes for
|
|
19
|
+
`ask <cmd> | head`**). `ask repo-ir . --force | head -c 100` returned the correct bytes and
|
|
20
|
+
exit 1; under `set -e` that stops a pipeline with no error anywhere to explain it — the field
|
|
21
|
+
named it one of two blockers for CI. One authority now says what a closed stream means
|
|
22
|
+
(`pipe_contract.py`, installed at the entry point): **a broken output stream changes nothing
|
|
23
|
+
except where the remaining bytes go.** The descriptor is redirected to the null device on the
|
|
24
|
+
first broken write and the command finishes and exits on its own terms.
|
|
25
|
+
- **It does not overwrite the command's own verdict.** `ask impact <ambiguous target> | head`
|
|
26
|
+
still exits 1, because a consumer that stopped reading has no opinion about whether the
|
|
27
|
+
analysis resolved its target.
|
|
28
|
+
- Redirecting before the shutdown flush is what keeps Python from printing
|
|
29
|
+
`Exception ignored in: <_io.TextIOWrapper …>` and exiting 120 — the same defect wearing a
|
|
30
|
+
different number.
|
|
31
|
+
- **The wrapper covers `.buffer`, which is the whole fix**: payloads are written as bytes
|
|
32
|
+
through `sys.stdout.buffer` at the single emit seam, so a text-only wrapper sits beside the
|
|
33
|
+
one write this exists for. Measured: with the text wrapper alone, nothing changed.
|
|
34
|
+
- Only visible above a pipe buffer, which is why it looked intermittent: `endpoints` on a
|
|
35
|
+
small repository exits 0 either way, `repo-ir` on the same repository did not.
|
|
36
|
+
|
|
37
|
+
- **An unresolved target has one exit code across every command** (C3-29, **`plan` now exits 1
|
|
38
|
+
where it exited 0**). `plan <unknown> <repo>` ran to completion, emitted a plan-shaped payload
|
|
39
|
+
of zeros with `resolution: "not_found"` and exited **0**, while `impact` on the same input
|
|
40
|
+
exited 1 — so a gate could not tell "nothing to review" from "I never found what you asked
|
|
41
|
+
about". One authority (`target_admission.py`), four commands rebound (`impact`,
|
|
42
|
+
`impact-chain`, `plan`, `explain`), and the two other copies of the same literal set
|
|
43
|
+
(`compare`, `change_plan`) now read it instead of restating it.
|
|
44
|
+
- **Ambiguity is the same fact, and it was not in the field report.** A target matching
|
|
45
|
+
several classes returns `ambiguous_path`, empty results and a message asking for the full
|
|
46
|
+
FQN — the command declined to answer — and `impact` exited **0** on it. Measured on a
|
|
47
|
+
purpose-built two-class fixture, since no battery repository carries the shape.
|
|
48
|
+
- Unresolved is **1, not 2**: 2 is reserved by the `verify` family for a run that could not
|
|
49
|
+
look, and this run looked. Partial and expanded resolutions stay 0 — they are answers about
|
|
50
|
+
the target the caller named.
|
|
51
|
+
- `plan`'s `Note:` on stderr is gone with it: the payload already carries the statement, and
|
|
52
|
+
a successful-looking run should not be narrating on stderr (the `plan` half of C3-34).
|
|
53
|
+
|
|
54
|
+
- **`--help` reaches inside command groups** (C4-7). `ask cache model` — what a warm buys each
|
|
55
|
+
command, per layer, including the commands it buys nothing for — appeared in no help text at
|
|
56
|
+
all: the root catalogue was generated (C4-1/C4-2) but the Cache and Auth blocks under it were
|
|
57
|
+
three lines somebody typed by hand. The blocks are now built from the registered groups, so a
|
|
58
|
+
subcommand is listed the moment it is registered; a group too large to name in full (`retrieve`,
|
|
59
|
+
29 parked intents) publishes its **exact count** and a pointer, never silence. The battery
|
|
60
|
+
fails if a subcommand of a listed group is missing, or if a collapsed group's count drifts.
|
|
61
|
+
|
|
62
|
+
- **A successful run says nothing on stderr — measured over the commands, not over a list**
|
|
63
|
+
(C3-34, the `repo-ir` half). `ask repo-ir . --force` wrote an 82-byte size advisory on a run
|
|
64
|
+
that exited 0 with the IR on stdout, which PowerShell 5.1 raises as a `NativeCommandError`.
|
|
65
|
+
The advisory is terminal-gated now, like every other notice, and so is the `--exclude`
|
|
66
|
+
directory warning and the output-budget trim warning found beside it.
|
|
67
|
+
- **The list was the defect.** `tests/test_stderr_purity_matrix.py` enumerated 13 commands by
|
|
68
|
+
hand for the fourth time in three releases; the rows are now **discovered from the CLI**,
|
|
69
|
+
with every command either driven or carrying a written reason it cannot be. Nine more
|
|
70
|
+
commands are driven as a result, `cache` subcommands included.
|
|
71
|
+
- The `repo-ir` row builds a repository large enough for the advisory to actually fire and
|
|
72
|
+
**asserts it fired**, because a row that never reaches the branch proves nothing.
|
|
73
|
+
|
|
74
|
+
- **`--output FILE` is no longer trimmed to an agent's context window** (C3-17). The payload
|
|
75
|
+
budget exists because a context window is finite — it is a constraint on **stdout**. Written
|
|
76
|
+
to a file it cut the answer anyway, dropped `key_dependencies` entirely, and the note
|
|
77
|
+
explaining the cut advised `--output`, the flag already in use. Two of six call sites had the
|
|
78
|
+
rule and four did not (`prepare-context`, `modernize`, the cached-view rebuild, and `impact`
|
|
79
|
+
in part), so it now lives in one seam (`cli._apply_budget`) and a battery fails if a seventh
|
|
80
|
+
call site decides for itself.
|
|
81
|
+
- **The cache had the same defect one layer down**, found while field-checking the seam:
|
|
82
|
+
`prepare-context` stored the document *after* trimming, so the first stdout run poisoned the
|
|
83
|
+
cache and every later `--output FILE` hit received a stdout-sized answer. The cache stores
|
|
84
|
+
the analysis now and the budget is applied per run — measured on alfresco-community-repo:
|
|
85
|
+
stdout 5 files, cache hit to a file 26.
|
|
86
|
+
- **`--full` says what it does.** It raises the caps (boundaries and DTO mappers in full,
|
|
87
|
+
`file_relevance` to 40); it never removed them — under `--agent --full` the file list stayed
|
|
88
|
+
capped at 40 of 710 while the flag's help promised "remove truncation limits".
|
|
89
|
+
|
|
90
|
+
- **`--agent` cannot publish less than `--compact`** (C3-10). `--compact` documents
|
|
91
|
+
`security_surface` "when custom security annotations detected" and closes with "use `--agent`
|
|
92
|
+
for maximum signal", while `--agent` was assembled from its own hand-written list of sections:
|
|
93
|
+
measured on BroadleafCommerce it omitted `deployment` and `language_version` outright, and
|
|
94
|
+
nothing stopped the security surface going the same way. Both views now read one authority
|
|
95
|
+
(`serializer.JAVA_SPRING_SECTIONS`), and the battery fails on any section `--compact` publishes
|
|
96
|
+
that `--agent` does not.
|
|
97
|
+
|
|
98
|
+
- **A path that names one file resolves to that file** (C3-35). Every resolver reduced a
|
|
99
|
+
path-shaped target to its basename before anything looked at it, so
|
|
100
|
+
`ask impact src/main/java/com/a/Service.java` answered `ambiguous_path` and offered
|
|
101
|
+
`com.a.Service` **and** `com.b.Service` — being more specific made the answer worse. A path is
|
|
102
|
+
matched against the `source_file` each symbol came from, strongest tier first (exact, then
|
|
103
|
+
module-relative, then parent-relative), and nested types collapse to the type the file is about
|
|
104
|
+
(on eureka, `DiscoveryClient.java` declares its outer class and five inner ones). One authority
|
|
105
|
+
in `target_admission`, because three graphs answer target questions — the repo IR, and the CIR
|
|
106
|
+
that `explain` and `impact-chain` read, both of which used to answer `not_found` for a path.
|
|
107
|
+
Parity checked on eureka: by path and by name give byte-identical `stats`.
|
|
108
|
+
|
|
109
|
+
- **`verify-edit` stops paying for a diff it has already proved empty** (C3-32). It computed the
|
|
110
|
+
change set and then built the HEAD CIR *and* the working CIR unconditionally — on a clean tree
|
|
111
|
+
the second is the first by construction. Measured on a clean ofbiz-framework: **5.9 s -> 1.7 s**
|
|
112
|
+
warm. The shortcut is taken only when git actually answered: a failed `git diff` also returns an
|
|
113
|
+
empty list, and reading that as "nothing changed" would trade dead cost for a false green.
|
|
114
|
+
|
|
115
|
+
- **`spring-audit --compact`** (C3-31). The one analysis command with no summary mode: 1.99 MB for
|
|
116
|
+
14 findings in the field, *"a context overflow against an LLM with no filter in between"*. The
|
|
117
|
+
weight is not the findings — on BroadleafCommerce `security_posture.endpoints` is 113 KB of a
|
|
118
|
+
178 KB report, and the counts it supports are published beside it. `--compact` caps that list and
|
|
119
|
+
`findings` to their top 5, ordered by what asks something of the reader (`probably_exposed`
|
|
120
|
+
first; most severe first), and recomputes nothing: **178 KB -> 25 KB with every count
|
|
121
|
+
identical**. A flag changes how much is emitted, never the shape (C2-10) — each list stays a list
|
|
122
|
+
and the totals live in a `*_cap` sibling that exists only when the cap bit.
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
### Documentation
|
|
126
|
+
|
|
127
|
+
- **Field evaluation #6 of 3.5.0 recorded** (`.planning/FIELD-EVAL-6-2026-08-01.md`, defect
|
|
128
|
+
ledger, development roadmap). Full 27-command catalogue, repository left byte-identical,
|
|
129
|
+
scored 8/10. Every reported defect was re-measured on 3.6.0 before it was written down: two
|
|
130
|
+
do not reproduce (one closed here as C3-15, one by the 3.5.0 admission authority) and the
|
|
131
|
+
re-measurement found two the evaluation did not report.
|
|
132
|
+
- **New rows**: C1-18 (profile population differs per command, and the narrower one is what an
|
|
133
|
+
agent reads) · C3-28/C3-29 (**exit codes that lie over correct answers** — a broken pipe
|
|
134
|
+
exits non-zero on a successful run, `plan` exits 0 on a target it did not resolve while
|
|
135
|
+
`impact` exits 1) · C3-30 (`verify --init`) · C3-31…C3-34 · C4-7 (`cache model` in no help
|
|
136
|
+
panel) · P-4 (`baseline` history nobody automated) · CL-7 (non-coverage: no dataflow, no
|
|
137
|
+
secrets outside Java/YAML, filter order not reconstructed) · CL-8 (`posture --diff` answers
|
|
138
|
+
conditionally because the profile is decided outside the repository).
|
|
139
|
+
- **The executive roadmap gains what the product does *not* do**, published beside the
|
|
140
|
+
capabilities, and the evaluation table is current through eval #6.
|
|
141
|
+
|
|
142
|
+
## [3.6.0] — 2026-08-01
|
|
143
|
+
|
|
144
|
+
**The P0 block and the C1/C2 backlog.** Nine rows closed, three closed by measurement alone
|
|
145
|
+
(C1-17, C2-11, and C2-12 as stated did not reproduce). `migrate-check` stops billing work a
|
|
146
|
+
declared dependency already did, stops billing a Hibernate rewrite to another vendor's provider,
|
|
147
|
+
and stops assuming a single destination — `--target-jdk 11 --keep-boot` takes MIG-001 from 85 to 0
|
|
148
|
+
on openmrs-core.
|
|
149
|
+
|
|
150
|
+
Two patterns from 3.5.0 repeat, and both are worth carrying forward. **The reported symptom keeps
|
|
151
|
+
being narrower than the defect**: C1-10 was one rule and was also an evidence rule admitting JPA as
|
|
152
|
+
proof of Hibernate; C2-1 was a `why` trail and was also the ranking key underneath it. **And a
|
|
153
|
+
curated list beside real data keeps being the cause** — C2-3's trim schedule named sections the
|
|
154
|
+
payload does not have while the weight sat in two it never mentions, the third appearance of the
|
|
155
|
+
C4-1 shape in two releases.
|
|
156
|
+
|
|
157
|
+
**Minor, not patch**: blocking counts move (C1-10), reach-derived counts become nullable (C1-13),
|
|
158
|
+
`compare`'s ranking can move (C2-1), `migrate-check.findings` keeps one type across `--compact`
|
|
159
|
+
(C2-10), and two commands that wrote their confirmation to stderr now write it to stdout (C3-18).
|
|
160
|
+
|
|
161
|
+
### Added
|
|
162
|
+
|
|
163
|
+
- **`migrate-check --target-jdk N` and `--keep-boot`** (C1-15, P0 gate 2). Asked about a JDK move,
|
|
164
|
+
the answer was `headline_blocker: boot3_migration` with fix hints sending a developer to migrate
|
|
165
|
+
481 `javax.persistence` imports they never planned to touch; nothing could say "JDK 11, keep Boot
|
|
166
|
+
2.7". The route is filtered over the `migration_target` vocabulary every rule already carried.
|
|
167
|
+
Measured on openmrs-core with `--target-jdk 11 --keep-boot`: **MIG-001 85 → 0**, blocking 114 → 0,
|
|
168
|
+
headline `hibernate_rewrite` → `none_applicable`. Narrowing is not silencing — `metadata.route`
|
|
169
|
+
publishes the target and every excluded axis, and a `limitations` entry states what was left out
|
|
170
|
+
and that it is unresolved, not fixed. **The default is unchanged**: no flags means every axis at
|
|
171
|
+
once.
|
|
172
|
+
|
|
173
|
+
- **`spring-audit` findings carry `first_line`** (C2-4), from the `SourceSpan` index the IR already
|
|
174
|
+
records. `null` where the symbol has no recorded span, never 0.
|
|
175
|
+
|
|
176
|
+
### Changed
|
|
177
|
+
|
|
178
|
+
- **`migrate-check` reconciles findings with the build it already read** (C1-10, P0 gate 1,
|
|
179
|
+
**blocking counts move**). `MIG-021` fired as blocking while `javax.xml.bind:jaxb-api:2.3.1` sat
|
|
180
|
+
in the same `pom.xml`. A rule now declares the coordinates that satisfy it; a satisfied finding
|
|
181
|
+
gets `mitigated_by` and `code_context: "dependency_satisfied"`, leaving `blocking_count` exactly
|
|
182
|
+
as test scope does, and its hint stops saying "add this dependency". `satisfied_by` is empty for
|
|
183
|
+
every rule whose remedy is a source change.
|
|
184
|
+
- **The Hibernate axis now needs Hibernate evidence.** It billed 45.6 days to a repository whose
|
|
185
|
+
declared provider was EclipseLink because a bare `javax.persistence` import counted as proof —
|
|
186
|
+
that proves JPA, not Hibernate. A declared competing provider refutes the inference, and only
|
|
187
|
+
the inference: a repository carrying both coordinates keeps direct evidence. An inference from
|
|
188
|
+
a JPA import alone now reports `medium`, not `high`.
|
|
189
|
+
- Battery: `blocking_count` identical on all six repositories.
|
|
190
|
+
|
|
191
|
+
- **A capped blast radius answers `unknown`, not `0`** (C1-13, **reach-derived counts become
|
|
192
|
+
nullable**). A hub capped at `depth=1` reported `endpoints_affected_count: 0` for a walk that
|
|
193
|
+
never looked. Under the cap a reach-derived zero becomes `null`, named in
|
|
194
|
+
`stats.unknown_under_cap`. A **non-zero** count under the cap stays a number — it is a floor — and
|
|
195
|
+
an **uncapped** run keeps its measured zero.
|
|
196
|
+
|
|
197
|
+
- **`compare` ranks on measurements, not on rendered rows** (C1-13/C2-1, **ranking may move**).
|
|
198
|
+
Three of the seven cost fields were `len()` of a display list, so the ordering was computed over
|
|
199
|
+
however many rows the renderer had decided to show. Capped magnitudes are declared in
|
|
200
|
+
`cost_floor_fields` beside `cost`, never inside it.
|
|
201
|
+
|
|
202
|
+
- **`impact.endpoints_affected[]` gains `controller_class` and `handler_symbol`** (C2-12), the names
|
|
203
|
+
`impact-chain` already uses. Grouping by controller needed a different key per command on payloads
|
|
204
|
+
one run produces. Original keys kept as aliases.
|
|
205
|
+
|
|
206
|
+
- **`effort_breakdown.affected_files` is now `blocking_affected_files`** (C1-14, alias kept). It
|
|
207
|
+
named a different population from `summary.affected_files` — 264 against 265 on openmrs-core — and
|
|
208
|
+
the shared name was the whole of the contradiction. Both carry a `_basis`.
|
|
209
|
+
|
|
210
|
+
### Fixed
|
|
211
|
+
|
|
212
|
+
- **The payload budget cuts where the bytes are** (C2-3). `_TRIM_SCHEDULE` is a hand-written list of
|
|
213
|
+
key names: on a 1 222-file `review-pr` diff it trimmed 1 733 KB → 1 732 KB against a 97 KB budget,
|
|
214
|
+
walking to `execution_paths` while every byte sat in `changed_files` and `runtime_changes`, which
|
|
215
|
+
it does not mention. Once the schedule is exhausted the remaining cut is chosen by measuring which
|
|
216
|
+
list is largest. Measured on that payload shape: **566 KB → 71 KB**.
|
|
217
|
+
|
|
218
|
+
- **`ask verify` no longer passes with zero contracts declared** (C3-15, **behaviour change for
|
|
219
|
+
pipelines**). It returned `pass` + exit 0 on a repository that declared nothing — a green light
|
|
220
|
+
for having verified nothing. `evaluate_repo` returns before it even builds the CIR when no
|
|
221
|
+
contracts exist, so no code was read and no contract was checked: the same standing as a
|
|
222
|
+
repository that could not be analysed, and now reported the same way — **`unverified`, exit 2**,
|
|
223
|
+
with the reason stated. Exit 2 and not 1 because the published contract reserves 1 for
|
|
224
|
+
violations found and 2 for a run that could not verify. Asserted under every `--fail-on` choice:
|
|
225
|
+
`never` suppresses violations from blocking, it does not turn a run that verified nothing into a
|
|
226
|
+
verified one. This is C3-22 in different clothes — there a typo in `$DIR` made the gate
|
|
227
|
+
permanently green, here a repository that never adopted contracts did.
|
|
228
|
+
|
|
229
|
+
- **A command that writes its answer to a file now confirms on stdout, not stderr** (C3-18,
|
|
230
|
+
**behaviour change for scripts reading stderr**). `repo-ir`, `modernize`, `export` and
|
|
231
|
+
`cold-start` wrote the "written to" confirmation to stderr while the payload went to the file
|
|
232
|
+
and stdout stayed empty, so `ask repo-ir -o ir.json > log.txt` captured **nothing** and
|
|
233
|
+
PowerShell 5.1 raised `NativeCommandError` over a run that succeeded. Measured on
|
|
234
|
+
spring-petclinic before the fix: stdout 0 bytes, stderr 155. C3-26 set this rule in 3.5.0 for
|
|
235
|
+
`cache warm`/`cache clear`; these four were missed because the stderr battery listed its
|
|
236
|
+
commands **by hand**. The `--output` rows are now discovered from the CLI.
|
|
237
|
+
|
|
238
|
+
- **Usage errors emit the JSON envelope for a pipeline** (C3-4). The interception was patched onto
|
|
239
|
+
`click.UsageError.show`, which Typer never calls when `rich_markup_mode` is set — it is, for the
|
|
240
|
+
help panels — so **no usage error had been emitting an envelope at all** and `ask <cmd>
|
|
241
|
+
--badflag` answered automation with a rich text box. Split by audience: a pipeline gets the
|
|
242
|
+
envelope, a person at a terminal keeps the `Usage:` line and the pointer to `--help`.
|
|
243
|
+
|
|
244
|
+
- **A flag no longer changes the type of a key** (C2-10, **breaking for `--compact` consumers**).
|
|
245
|
+
`migrate-check.findings` was a bare array in full output and a
|
|
246
|
+
`{total, shown, omitted, items}` object under `--compact` — the same key, two types. A consumer
|
|
247
|
+
iterating `findings` broke silently on a flag it did not pass: nothing errored, the loop simply
|
|
248
|
+
ran over the four keys of a summary object instead of over the findings.
|
|
249
|
+
- `findings` is a **list in both modes**. The counts moved to a `findings_cap` sibling that
|
|
250
|
+
exists **only when a cap actually bit**, and it carries the I-8 `display_list` statement of
|
|
251
|
+
what the cut changed and what stayed exact.
|
|
252
|
+
- **Five collections had it, not one**: top-level `findings`, `hibernate.rewrite_targets`,
|
|
253
|
+
`hibernate.findings`, `hibernate.critical_call_chains`, `hibernate.golden_sql_hotspots`, and
|
|
254
|
+
`blast_radius.files`.
|
|
255
|
+
- **Half of C2-13 falls out of the same fix.** `migrate-check.findings` is now the bare array
|
|
256
|
+
`spring-audit.findings` always was — one word, one type, one parser, measured across all
|
|
257
|
+
three payloads. The `schema_version` fragmentation is the half that stays open.
|
|
258
|
+
- Enforced rather than documented: `tests/test_flag_shape_stability.py` walks both payloads key
|
|
259
|
+
by key and fails on any type that moves. The same walk covers the root command's `--compact`
|
|
260
|
+
and `--agent`, which were **measured clean** while fixing this and are locked so they stay
|
|
261
|
+
clean.
|
|
262
|
+
|
|
263
|
+
- **A misplaced global flag is told where that flag lives** (C3-4). `ask spring-audit --full`
|
|
264
|
+
answered "No such option: --full" about a flag the tool does have — it is declared on the root
|
|
265
|
+
command. The flag is looked up on the root command, so every global flag typed after every
|
|
266
|
+
subcommand is covered and no flag name is written into the check; a genuinely unknown flag earns
|
|
267
|
+
no hint, asserted.
|
|
268
|
+
|
|
269
|
+
- **`repo-ir` states the output cost before it is paid** (C3-18). The advisory ran after the IR was
|
|
270
|
+
built, serialized and written — the whole bill settled. It now runs off the file count before the
|
|
271
|
+
build starts, as a **band** (10.8–27.9 KB per Java file) rather than a point: the per-file cost
|
|
272
|
+
spreads 2.6× across sampled repositories with how densely the code cross-references, and
|
|
273
|
+
publishing a midpoint as one figure is the C1-12 defect. The band is asserted to bracket what
|
|
274
|
+
those repositories actually produced.
|
|
275
|
+
|
|
276
|
+
- **A capped `file_relevance` list says what was cut, measured** (C3-20). The hint published the
|
|
277
|
+
*budget* as the number of files shown — on spring-petclinic, "Showing top 40/176" beside a list
|
|
278
|
+
of **25** — fired even when nothing had been cut, and advised `--full` while `--full` was active.
|
|
279
|
+
Two constraints trim the list (a visibility threshold and a per-category cap of half the budget)
|
|
280
|
+
and the sentence knew about neither. Now: nothing unless a cap really bit, the figure is what was
|
|
281
|
+
shown against the population it samples, a flag is named only when it would change the answer,
|
|
282
|
+
and the I-8 `display_list` block sits beside it.
|
|
283
|
+
|
|
284
|
+
- **`--no-cache` on a subcommand says what it does** (C3-5). Six commands claimed "always reads
|
|
285
|
+
fresh source (no snapshot cache)" while `ask cache model` records them reading `ris`, `cir` and
|
|
286
|
+
`parse`. One string now, stating the reason it is a no-op: since C1-9 every layer keys on the
|
|
287
|
+
exact tree state and the parse layer is content-addressed, so there is no staleness to bypass.
|
|
288
|
+
The flag stays accepted so scripts do not break, and is real on `ask --no-cache` (root).
|
|
289
|
+
|
|
290
|
+
- **`--output <file>` now returns the whole answer, which is what its own note promised**
|
|
291
|
+
(C2-2, first M8 increment). Measured on `org.broadleafcommerce.common.money.Money`: the file
|
|
292
|
+
held **30 of 134** caller classes and **50 of 1 302** indirect callers — the same sample stdout
|
|
293
|
+
gets — while the payload told the reader *"use `--output` for the full list"*.
|
|
294
|
+
- **The recorded cause was wrong, and fixing what was recorded would not have worked.** The
|
|
295
|
+
file carried no `_budget_note` at all: the caps were applied at *construction*, inside
|
|
296
|
+
`compute_blast_radius`, before any output flag was consulted. No option could have returned
|
|
297
|
+
the full list.
|
|
298
|
+
- A cap is now a **rendering** parameter (`list_limit`) and never a measurement one — every
|
|
299
|
+
`stats.*_count` is taken over the full population either way (ADR-0008 R5-R8). `--output`
|
|
300
|
+
renders unbounded; stdout keeps the sample and names the total; and the note only claims a
|
|
301
|
+
cap that actually bit, with the I-8 `display_list` effect block beside it.
|
|
302
|
+
- The output budget is skipped for a file as well. `--agent` and `--compact` already did this;
|
|
303
|
+
`impact` was the one that did not.
|
|
304
|
+
- Same rule for `impact-chain`, with one qualification: an **explicit `--limit` still wins**.
|
|
305
|
+
A default is not a request; a typed flag is (`_flag_was_given`, off Click's parameter source).
|
|
306
|
+
- The USER_GUIDE now states the rule where a reader meets it, beside the `impact` output.
|
|
307
|
+
|
|
3
308
|
## [3.5.0] — 2026-07-31
|
|
4
309
|
|
|
5
310
|
**M7.7 "Robustness floor" — the axis field evaluation #5 scored 4/10.** Ten pieces, and the
|
|
@@ -88,7 +88,11 @@ def build_change_plan(
|
|
|
88
88
|
resolution = blast.get("resolution", "not_found")
|
|
89
89
|
|
|
90
90
|
# Unresolvable target → return a plan-shaped resolution notice (never crash).
|
|
91
|
-
|
|
91
|
+
# The set of resolutions that means "never found it" is one fact, and the CLI
|
|
92
|
+
# reads the same one to decide the exit code (C3-29).
|
|
93
|
+
from sourcecode.target_admission import is_unresolved
|
|
94
|
+
|
|
95
|
+
if is_unresolved(resolution) or not blast.get("matched_fqns"):
|
|
92
96
|
return {
|
|
93
97
|
"schema": CHANGE_PLAN_SCHEMA,
|
|
94
98
|
"target": target,
|