sourcecode 2.0.0__tar.gz → 2.1.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-2.0.0 → sourcecode-2.1.0}/CHANGELOG.md +76 -0
- sourcecode-2.1.0/PKG-INFO +241 -0
- sourcecode-2.1.0/README.md +203 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/pyproject.toml +1 -1
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/__init__.py +1 -1
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/cli.py +28 -2
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/migrate_check.py +64 -0
- sourcecode-2.1.0/src/sourcecode/security_posture.py +608 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/spring_findings.py +4 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/spring_security_audit.py +31 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/summarizer.py +33 -2
- sourcecode-2.1.0/src/sourcecode/validation_inference.py +249 -0
- sourcecode-2.0.0/PKG-INFO +0 -925
- sourcecode-2.0.0/README.md +0 -887
- {sourcecode-2.0.0 → sourcecode-2.1.0}/.github/workflows/build-windows.yml +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/.gitignore +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/.ruff.toml +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/CONTRIBUTING.md +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/LICENSE +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/SECURITY.md +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/raw +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/scripts/compare_integration_engines.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/scripts/customer_smoke_test.sh +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/scripts/generate_jdk_exports.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/adaptive_scanner.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/architecture_analyzer.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/architecture_summary.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/ast_extractor.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/cache.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/call_surface.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/canonical_ir.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/cir_graphs.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/classifier.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/code_notes_analyzer.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/confidence_analyzer.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/context_graph.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/context_scorer.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/context_summarizer.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/contract_model.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/contract_pipeline.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/coverage_parser.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/dependency_analyzer.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/detectors/__init__.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/detectors/base.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/detectors/csproj_parser.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/detectors/dart.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/detectors/dotnet.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/detectors/elixir.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/detectors/go.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/detectors/heuristic.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/detectors/hybrid.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/detectors/java.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/detectors/jvm_ext.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/detectors/nodejs.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/detectors/parsers.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/detectors/php.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/detectors/project.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/detectors/python.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/detectors/ruby.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/detectors/rust.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/detectors/systems.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/detectors/terraform.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/detectors/tooling.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/doc_analyzer.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/dynamic_argument_surface.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/endpoint_literals.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/entrypoint_classifier.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/env_analyzer.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/error_schema.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/evidence_provider.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/explain.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/file_chunker.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/file_classifier.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/format_contract.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/fqn_utils.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/git_analyzer.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/graph_analyzer.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/hibernate_strat.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/jdk_exports.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/license.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/mcp/__init__.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/mcp/onboarding/__init__.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/mcp/onboarding/applier.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/mcp/onboarding/backup.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/mcp/onboarding/detector.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/mcp/onboarding/planner.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/mcp/orchestrator.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/mcp/registry.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/mcp/runner.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/mcp/server.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/mcp_nudge.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/metrics_analyzer.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/openapi_surface.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/output_budget.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/path_filters.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/pr_comment_renderer.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/pr_impact.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/prepare_context.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/progress.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/ranking_engine.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/redactor.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/relevance_scorer.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/rename_refactor.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/repo_classifier.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/repository_ir.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/ris.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/runtime_classifier.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/scanner.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/schema.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/security_config.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/semantic_analyzer.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/semantic_impact_engine.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/semantic_integration_engine.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/semantic_services.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/serializer.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/spring_event_topology.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/spring_impact.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/spring_model.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/spring_semantic.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/spring_tx_analyzer.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/telemetry/__init__.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/telemetry/config.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/telemetry/consent.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/telemetry/events.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/telemetry/filters.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/telemetry/transport.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/tree_utils.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/type_usage_surface.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/validation_surface.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/version_check.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/src/sourcecode/workspace.py +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/supabase/functions/README.md +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/supabase/functions/get-license/index.ts +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/supabase/functions/lemonsqueezy-webhook/index.ts +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/supabase/functions/telemetry/index.ts +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/supabase/sql/license_event_ordering.sql +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/supabase/sql/licensing_schema.sql +0 -0
- {sourcecode-2.0.0 → sourcecode-2.1.0}/supabase/sql/telemetry_events.sql +0 -0
|
@@ -1,5 +1,81 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.1.0] — 2026-07-10
|
|
4
|
+
|
|
5
|
+
**Robustness & Security Inference — vendor-agnostic security & validation posture.**
|
|
6
|
+
Two new Knowledge-Layer projections let the engine reason about a repo's security
|
|
7
|
+
and validation *model* without prior knowledge of the framework or any per-client
|
|
8
|
+
configuration. Detection is structural (coverage, specificity, correlation,
|
|
9
|
+
request-interception topology); a config file may only raise confidence, never
|
|
10
|
+
drive detection. No IR change — both projections reuse facts the engine already
|
|
11
|
+
extracts.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- **`spring-audit` — `security_posture` block (custom authorization inference).**
|
|
16
|
+
The engine now infers custom endpoint security models on a repo it has never
|
|
17
|
+
seen. It auto-detects a candidate custom-authorization annotation purely by
|
|
18
|
+
structure — an annotation outside the published open-standard baseline that
|
|
19
|
+
covers a systematic share of controller handlers, tracks the endpoint surface
|
|
20
|
+
(specificity), and correlates with a request-interception pipeline. The
|
|
21
|
+
concrete annotation name appears only as *evidence*, never in detection logic.
|
|
22
|
+
Every conclusion carries an Evidence-Confidence envelope
|
|
23
|
+
(`Verified | Likely | Unknown | RequiresManualReview`): detection fires at
|
|
24
|
+
`Likely` with no config present, and a `sourcecode.config.json` entry naming
|
|
25
|
+
the annotation upgrades it to `Verified`. Emits per-endpoint 4-way verdicts
|
|
26
|
+
(`protected_standard` / `protected_custom` / `coverage_unknown` /
|
|
27
|
+
`probably_exposed`) plus a request-interception ("authentication pipeline
|
|
28
|
+
inferred") conclusion. This kills the recurring false "N endpoints without
|
|
29
|
+
security" alarm on repos guarded by a bespoke gate — when a custom mechanism is
|
|
30
|
+
inferred, uncovered endpoints degrade to `coverage_unknown`, never a categorical
|
|
31
|
+
"unsecured". The related `SEC-001` finding is suppressed on any endpoint carrying
|
|
32
|
+
an auto-detected gate.
|
|
33
|
+
|
|
34
|
+
- **`validation` — `validation_pattern` block (present-but-unused inference).**
|
|
35
|
+
Instead of reporting silent zeros when a repo has no `@Valid`, the engine now
|
|
36
|
+
classifies the request-body validation *pattern*: `bean_validation_active`
|
|
37
|
+
(Verified), `bean_validation_available_unused` (Likely — a validation framework
|
|
38
|
+
is on the classpath and body endpoints exist but none validate), or
|
|
39
|
+
`no_validation_detected` (Unknown). The middle class is the real finding on
|
|
40
|
+
repos with many `@RequestBody` handlers and zero `@Valid`: "framework present
|
|
41
|
+
but unused", with a prioritized recommendation — not an empty report.
|
|
42
|
+
|
|
43
|
+
### Notes
|
|
44
|
+
|
|
45
|
+
- Both projections are vendor-agnostic: inference predicates key only on published
|
|
46
|
+
open standards (`org.springframework.security`, `jakarta`/`javax.validation`,
|
|
47
|
+
JAX-RS), loaded as a declarative baseline table used to subtract the known
|
|
48
|
+
vocabulary. No proprietary annotation, framework, or naming convention appears
|
|
49
|
+
in any inference predicate (enforced by test).
|
|
50
|
+
- Manual (throw-on-bad-parameter) validation detection is intentionally deferred:
|
|
51
|
+
guard-clause atoms do not yet cover endpoint-kind handler bodies. See
|
|
52
|
+
`docs/architecture/DESIGN-robustness-security-inference.md` §2.
|
|
53
|
+
- No breaking changes. Default command outputs are unchanged except for the added
|
|
54
|
+
blocks above.
|
|
55
|
+
|
|
56
|
+
## [2.0.1] — 2026-07-10
|
|
57
|
+
|
|
58
|
+
### Added
|
|
59
|
+
|
|
60
|
+
- **`migrate-check --compact` — bounded decision summary.** A new opt-in view of the
|
|
61
|
+
migration report that keeps every decision field (readiness scores, headline blocker,
|
|
62
|
+
blocking count, estimated effort, executive summary, Hibernate classification, aggregate
|
|
63
|
+
counts) and caps each large collection to its top items with a `+N more` count. On real
|
|
64
|
+
monoliths the report shrinks ~97% (BroadleafCommerce 1.2 MB → 32 KB, OpenMRS 908 KB →
|
|
65
|
+
23 KB) — an agent or reviewer gets the verdict without the leaf-level firehose. The full
|
|
66
|
+
report remains the default output.
|
|
67
|
+
|
|
68
|
+
### Fixed
|
|
69
|
+
|
|
70
|
+
- **`onboard` project summary no longer leaks raw README markup.** READMEs that open with
|
|
71
|
+
a logo block (`<img>` / `<p>` HTML) or use inline markdown links (`[label](url)`) had
|
|
72
|
+
produced summaries like `API: <img src="…"/>`. The summary is now rendered to clean prose
|
|
73
|
+
— HTML/badge blocks are skipped and inline links are unwrapped to their label.
|
|
74
|
+
|
|
75
|
+
### Notes
|
|
76
|
+
|
|
77
|
+
- No breaking changes. Default command outputs are unchanged except where explicitly noted.
|
|
78
|
+
|
|
3
79
|
## [2.0.0] — 2026-07-06
|
|
4
80
|
|
|
5
81
|
**ASK Engine 2.0** — the product identity is now final. The engine is unchanged;
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sourcecode
|
|
3
|
+
Version: 2.1.0
|
|
4
|
+
Summary: Persistent structural context and ultra-fast repeated analysis for AI coding agents
|
|
5
|
+
License-File: LICENSE
|
|
6
|
+
Keywords: agents,ai,codebase,context,developer-tools,llm
|
|
7
|
+
Classifier: Development Status :: 4 - Beta
|
|
8
|
+
Classifier: Environment :: Console
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
18
|
+
Classifier: Topic :: Utilities
|
|
19
|
+
Requires-Python: >=3.9
|
|
20
|
+
Requires-Dist: defusedxml>=0.7
|
|
21
|
+
Requires-Dist: mcp>=1.0.0
|
|
22
|
+
Requires-Dist: pathspec>=1.0
|
|
23
|
+
Requires-Dist: ruamel-yaml>=0.18
|
|
24
|
+
Requires-Dist: tomli>=2.0; python_version < '3.11'
|
|
25
|
+
Requires-Dist: typer>=0.24
|
|
26
|
+
Provides-Extra: ast
|
|
27
|
+
Requires-Dist: tree-sitter-javascript>=0.21; extra == 'ast'
|
|
28
|
+
Requires-Dist: tree-sitter-typescript>=0.21; extra == 'ast'
|
|
29
|
+
Requires-Dist: tree-sitter>=0.21; extra == 'ast'
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: mcp>=1.0.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: mypy>=1.10; extra == 'dev'
|
|
33
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
34
|
+
Requires-Dist: ruff>=0.15; extra == 'dev'
|
|
35
|
+
Provides-Extra: mcp
|
|
36
|
+
Requires-Dist: mcp>=1.0.0; extra == 'mcp'
|
|
37
|
+
Description-Content-Type: text/markdown
|
|
38
|
+
|
|
39
|
+
# ASK Engine
|
|
40
|
+
|
|
41
|
+
> **Persistent structural intelligence for AI coding agents.**
|
|
42
|
+
|
|
43
|
+
**Context · Impact · Migration · Architecture · Review — everything from one structural model.**
|
|
44
|
+
|
|
45
|
+

|
|
46
|
+

|
|
47
|
+
|
|
48
|
+
> **ASK Engine** is the product. The CLI command is **`ask`**. The legacy **`sourcecode`**
|
|
49
|
+
> command still works as a deprecated alias (it prints a one-line notice and forwards to
|
|
50
|
+
> `ask`) and remains the Python/PyPI package name for now. The authoritative version is
|
|
51
|
+
> whatever `ask version` reports. See [docs/PRODUCT_IDENTITY.md](docs/PRODUCT_IDENTITY.md).
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## The problem
|
|
56
|
+
|
|
57
|
+
Every time an AI coding agent starts a new session, it has to re-parse the repository from scratch. For a large Java or TypeScript monolith, that means 5–15 seconds per invocation. Multiply by dozens of agent turns per hour, and repo context acquisition becomes a real bottleneck — not just latency, but tokens, compute, and iteration velocity.
|
|
58
|
+
|
|
59
|
+
ASK Engine solves this with a persistent structural cache keyed on file content hashes. After the first scan, every subsequent invocation returns pre-built context in milliseconds. The repo doesn't change? The cache doesn't expire.
|
|
60
|
+
|
|
61
|
+
**The cache is not a performance optimization. It is what makes ASK Engine usable as infrastructure rather than a one-off tool.**
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Proof — measured on real repos
|
|
66
|
+
|
|
67
|
+
| Repo | Size | Cold scan | Cache hit | Speedup |
|
|
68
|
+
|------|------|-----------|-----------|---------|
|
|
69
|
+
| Keycloak | 7,885 Java files | 10.5s | 0.6s | **~17x** |
|
|
70
|
+
| BroadleafCommerce | 2,985 Java files | 2.7s | 0.3s | **~9x** |
|
|
71
|
+
|
|
72
|
+
Cache keyed on content hashes — invalidated only when source changes. On repeated agent sessions against the same codebase, nearly every invocation is a cache hit.
|
|
73
|
+
|
|
74
|
+
At 0.3s per call, ASK Engine becomes **constant infrastructure** inside agent loops — call it before every edit, every PR review, every test run, without batching or caching manually.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Install
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# Homebrew (macOS / Linux)
|
|
82
|
+
brew tap haroundominique/sourcecode && brew install sourcecode
|
|
83
|
+
|
|
84
|
+
# pip / pipx
|
|
85
|
+
pipx install sourcecode # or: pip install sourcecode
|
|
86
|
+
|
|
87
|
+
ask version # ask 2.1.0
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
> **Package vs. command.** The install package is named `sourcecode` this release
|
|
91
|
+
> (renaming the distribution is a separate, breaking change). Installing it gives you the
|
|
92
|
+
> canonical **`ask`** command plus the deprecated **`sourcecode`** alias.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Quickstart
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
# High-signal structural summary — warm cache ~0.3s, cold 2–10s
|
|
100
|
+
ask --compact
|
|
101
|
+
|
|
102
|
+
# Blast radius: what breaks if this class changes?
|
|
103
|
+
ask impact OrderService /path/to/repo
|
|
104
|
+
|
|
105
|
+
# Spring Boot 2→3 migration readiness (bounded decision summary)
|
|
106
|
+
ask migrate-check /path/to/repo --compact
|
|
107
|
+
|
|
108
|
+
# Spring semantic audit: TX anomalies + security surface
|
|
109
|
+
ask spring-audit /path/to/repo
|
|
110
|
+
|
|
111
|
+
# Onboard to an unfamiliar codebase
|
|
112
|
+
ask onboard /path/to/repo
|
|
113
|
+
|
|
114
|
+
# PR review: risk, test gaps, changed modules
|
|
115
|
+
ask review-pr /path/to/repo --since main
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Full command reference: **[docs/USER_GUIDE.md](docs/USER_GUIDE.md)**.
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Capabilities
|
|
123
|
+
|
|
124
|
+
Everything is computed from one cached structural model. Seven groups:
|
|
125
|
+
|
|
126
|
+
### 1 · Structural Context
|
|
127
|
+
Bounded, noise-free repo context designed to drop straight into an agent's context window.
|
|
128
|
+
`ask --compact` · `ask --agent` · `ask onboard` · `ask cold-start`
|
|
129
|
+
→ [reference](docs/USER_GUIDE.md#core-commands)
|
|
130
|
+
|
|
131
|
+
### 2 · Impact Analysis
|
|
132
|
+
Blast radius from a class or interface — reverse dependencies, through Spring DI, to the HTTP endpoints a change reaches.
|
|
133
|
+
`ask impact` · `ask impact-chain` (TX/SEC-enriched) · `ask pr-impact`
|
|
134
|
+
→ [reference](docs/USER_GUIDE.md#core-commands)
|
|
135
|
+
|
|
136
|
+
### 3 · Architecture Intelligence
|
|
137
|
+
The system map: module graph, dependency views, REST surface, per-class summaries, and a symbol-level IR for downstream tooling.
|
|
138
|
+
`ask export` · `ask repo-ir` · `ask endpoints` · `ask explain`
|
|
139
|
+
→ [reference](docs/USER_GUIDE.md#core-commands)
|
|
140
|
+
|
|
141
|
+
### 4 · Migration & Modernization
|
|
142
|
+
Is this codebase ready to upgrade? Per-dimension readiness (Jakarta / Spring Boot / JDK / Hibernate), located blockers, and an effort estimate.
|
|
143
|
+
`ask migrate-check` · `ask modernize`
|
|
144
|
+
→ [migrate-check reference](docs/migrate-check.md) · [MODERNIZATION.md](docs/MODERNIZATION.md)
|
|
145
|
+
|
|
146
|
+
### 5 · Spring Analysis
|
|
147
|
+
Deterministic Spring semantics: transactional anomalies (e.g. `@Transactional` on a private method = silent CGLIB no-op), security surface, request-body validation.
|
|
148
|
+
`ask spring-audit` · `ask validation`
|
|
149
|
+
→ [reference](docs/USER_GUIDE.md#core-commands)
|
|
150
|
+
|
|
151
|
+
### 6 · Developer Workflows
|
|
152
|
+
The everyday loop: diff-based PR review, symptom-driven bug triage, and delta context for continuous agent runs.
|
|
153
|
+
`ask review-pr` · `ask fix-bug` · `ask prepare-context`
|
|
154
|
+
→ [reference](docs/USER_GUIDE.md#typical-workflows)
|
|
155
|
+
|
|
156
|
+
### 7 · Utilities
|
|
157
|
+
`ask rename-class` (word-boundary Java rename) · `ask chunk-file` (split large files for agents) · `ask cache` (status / warm / clear / freshness)
|
|
158
|
+
→ [reference](docs/USER_GUIDE.md)
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## What it does — and doesn't
|
|
163
|
+
|
|
164
|
+
**ASK Engine reduces exploration cost.** It accelerates context acquisition and computes
|
|
165
|
+
blast radius; it does not replace reading code — it reduces how often an agent needs to.
|
|
166
|
+
All signals are **static and deterministic** (annotations, import graph, file structure) —
|
|
167
|
+
no runtime analysis, no LLM guessing.
|
|
168
|
+
|
|
169
|
+
Honest limits worth knowing before you rely on it:
|
|
170
|
+
|
|
171
|
+
- `impact` on an **implementation** class (`OrderServiceImpl`) returns 0 callers in Spring Boot — callers inject the interface. **Always target the interface.**
|
|
172
|
+
- `no_security_signal` on an endpoint means *no recognized method-level annotation*, **not** "unsecured" — Spring Security filter chains and custom authorization annotations show as `no_security_signal` unless taught via config (below).
|
|
173
|
+
- `spring-audit` / `impact-chain` are **Java/Spring only**; non-Java repos return `spring_detected: false`.
|
|
174
|
+
- Event topology (`--type events`) resolves Spring `ApplicationEvent` / `@EventListener` chains only — **not** Kafka/RabbitMQ/Redis routes.
|
|
175
|
+
- Architecture classification is tuned for Spring MVC layered apps; SPI/plugin models (e.g. Quarkus extensions) may be misclassified. JAX-RS subresource-locator endpoint recall is ~65%.
|
|
176
|
+
- Self-invocation `@Transactional` bypass (same-class call skipping the proxy) is not detected.
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Pricing
|
|
181
|
+
|
|
182
|
+
> **🎉 Early-adoption: Pro is currently unlocked for everyone.** Every install runs with
|
|
183
|
+
> full Pro entitlements — no size gate, no key. The tiers below describe the model the
|
|
184
|
+
> paywall will return to later.
|
|
185
|
+
|
|
186
|
+
**Gating is by repo size and automation — never by command.** Every command runs at full
|
|
187
|
+
power on Free for small and mid-size repos; you upgrade when the work gets bigger or automated.
|
|
188
|
+
|
|
189
|
+
| | **Free** — €0 | **Pro** — €19/mo · €190/yr per dev |
|
|
190
|
+
|---|---|---|
|
|
191
|
+
| Repo size | ≤ 500 Java source files | **> 500 Java files** (enterprise monoliths) |
|
|
192
|
+
| Commands | All of them, full output | Same commands, unlocked at scale |
|
|
193
|
+
| `impact` / `fix-bug` / `review-pr` / `modernize` | ✅ full on small repos | ✅ full on large repos (Free gets a capped preview) |
|
|
194
|
+
| `prepare-context delta` | 30 free runs/repo | unlimited — CI/CD automation |
|
|
195
|
+
| MCP local server, offline, no data egress | ✅ | ✅ |
|
|
196
|
+
|
|
197
|
+
**Non-Java repos are free at any size** — the size limit counts Java source files only.
|
|
198
|
+
ASK Engine monetises enterprise Java monoliths. Activate with `ask activate <key>`.
|
|
199
|
+
Full breakdown: [docs/PRODUCT_TIERS.md](docs/PRODUCT_TIERS.md).
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## Configuration & privacy
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
ask config # version, config file path, telemetry status
|
|
207
|
+
ask telemetry disable # anonymous telemetry is on by default (opt-out)
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Telemetry collects version, OS, commands, flags, duration, repo-size range, and errors —
|
|
211
|
+
**no source code, paths, secrets, or output**. Disable any time with
|
|
212
|
+
`export SOURCECODE_TELEMETRY=0` (or `DO_NOT_TRACK=1`).
|
|
213
|
+
|
|
214
|
+
**Custom security annotations.** Teach `endpoints`, `spring-audit`, and `explain` about
|
|
215
|
+
project-specific authorization annotations via an optional `sourcecode.config.json` at the
|
|
216
|
+
repo root (otherwise they report `policy: "none_detected"`):
|
|
217
|
+
|
|
218
|
+
```json
|
|
219
|
+
{
|
|
220
|
+
"customSecurityAnnotations": [
|
|
221
|
+
{ "fullyQualifiedName": "com.example.security.M3FiltroSeguridad", "shortName": "M3FiltroSeguridad" }
|
|
222
|
+
]
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Matching endpoints report `policy: "custom"` and drop out of the `no_security_signal` count.
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## Documentation
|
|
231
|
+
|
|
232
|
+
| Doc | What it covers |
|
|
233
|
+
|-----|----------------|
|
|
234
|
+
| [USER_GUIDE.md](docs/USER_GUIDE.md) | Full command reference, flags, output schema, workflows |
|
|
235
|
+
| [migrate-check.md](docs/migrate-check.md) | Migration rule catalogue (MIG-001..043) + Hibernate stratification |
|
|
236
|
+
| [MODERNIZATION.md](docs/MODERNIZATION.md) | The modernization product: assess → understand → plan → execute |
|
|
237
|
+
| [PRODUCT_TIERS.md](docs/PRODUCT_TIERS.md) | Free vs Pro, pricing model |
|
|
238
|
+
| [DEMO-5MIN.md](docs/DEMO-5MIN.md) | A reproducible 5-minute demo |
|
|
239
|
+
| [MANUAL-USUARIO.md](docs/MANUAL-USUARIO.md) | Guía de usuario en español |
|
|
240
|
+
| [PRODUCT_IDENTITY.md](docs/PRODUCT_IDENTITY.md) | `ask` (command) vs `sourcecode` (package/alias) |
|
|
241
|
+
| [privacy.md](docs/privacy.md) | Telemetry and data-handling policy |
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# ASK Engine
|
|
2
|
+
|
|
3
|
+
> **Persistent structural intelligence for AI coding agents.**
|
|
4
|
+
|
|
5
|
+
**Context · Impact · Migration · Architecture · Review — everything from one structural model.**
|
|
6
|
+
|
|
7
|
+

|
|
8
|
+

|
|
9
|
+
|
|
10
|
+
> **ASK Engine** is the product. The CLI command is **`ask`**. The legacy **`sourcecode`**
|
|
11
|
+
> command still works as a deprecated alias (it prints a one-line notice and forwards to
|
|
12
|
+
> `ask`) and remains the Python/PyPI package name for now. The authoritative version is
|
|
13
|
+
> whatever `ask version` reports. See [docs/PRODUCT_IDENTITY.md](docs/PRODUCT_IDENTITY.md).
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## The problem
|
|
18
|
+
|
|
19
|
+
Every time an AI coding agent starts a new session, it has to re-parse the repository from scratch. For a large Java or TypeScript monolith, that means 5–15 seconds per invocation. Multiply by dozens of agent turns per hour, and repo context acquisition becomes a real bottleneck — not just latency, but tokens, compute, and iteration velocity.
|
|
20
|
+
|
|
21
|
+
ASK Engine solves this with a persistent structural cache keyed on file content hashes. After the first scan, every subsequent invocation returns pre-built context in milliseconds. The repo doesn't change? The cache doesn't expire.
|
|
22
|
+
|
|
23
|
+
**The cache is not a performance optimization. It is what makes ASK Engine usable as infrastructure rather than a one-off tool.**
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Proof — measured on real repos
|
|
28
|
+
|
|
29
|
+
| Repo | Size | Cold scan | Cache hit | Speedup |
|
|
30
|
+
|------|------|-----------|-----------|---------|
|
|
31
|
+
| Keycloak | 7,885 Java files | 10.5s | 0.6s | **~17x** |
|
|
32
|
+
| BroadleafCommerce | 2,985 Java files | 2.7s | 0.3s | **~9x** |
|
|
33
|
+
|
|
34
|
+
Cache keyed on content hashes — invalidated only when source changes. On repeated agent sessions against the same codebase, nearly every invocation is a cache hit.
|
|
35
|
+
|
|
36
|
+
At 0.3s per call, ASK Engine becomes **constant infrastructure** inside agent loops — call it before every edit, every PR review, every test run, without batching or caching manually.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Install
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# Homebrew (macOS / Linux)
|
|
44
|
+
brew tap haroundominique/sourcecode && brew install sourcecode
|
|
45
|
+
|
|
46
|
+
# pip / pipx
|
|
47
|
+
pipx install sourcecode # or: pip install sourcecode
|
|
48
|
+
|
|
49
|
+
ask version # ask 2.1.0
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
> **Package vs. command.** The install package is named `sourcecode` this release
|
|
53
|
+
> (renaming the distribution is a separate, breaking change). Installing it gives you the
|
|
54
|
+
> canonical **`ask`** command plus the deprecated **`sourcecode`** alias.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Quickstart
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
# High-signal structural summary — warm cache ~0.3s, cold 2–10s
|
|
62
|
+
ask --compact
|
|
63
|
+
|
|
64
|
+
# Blast radius: what breaks if this class changes?
|
|
65
|
+
ask impact OrderService /path/to/repo
|
|
66
|
+
|
|
67
|
+
# Spring Boot 2→3 migration readiness (bounded decision summary)
|
|
68
|
+
ask migrate-check /path/to/repo --compact
|
|
69
|
+
|
|
70
|
+
# Spring semantic audit: TX anomalies + security surface
|
|
71
|
+
ask spring-audit /path/to/repo
|
|
72
|
+
|
|
73
|
+
# Onboard to an unfamiliar codebase
|
|
74
|
+
ask onboard /path/to/repo
|
|
75
|
+
|
|
76
|
+
# PR review: risk, test gaps, changed modules
|
|
77
|
+
ask review-pr /path/to/repo --since main
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Full command reference: **[docs/USER_GUIDE.md](docs/USER_GUIDE.md)**.
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Capabilities
|
|
85
|
+
|
|
86
|
+
Everything is computed from one cached structural model. Seven groups:
|
|
87
|
+
|
|
88
|
+
### 1 · Structural Context
|
|
89
|
+
Bounded, noise-free repo context designed to drop straight into an agent's context window.
|
|
90
|
+
`ask --compact` · `ask --agent` · `ask onboard` · `ask cold-start`
|
|
91
|
+
→ [reference](docs/USER_GUIDE.md#core-commands)
|
|
92
|
+
|
|
93
|
+
### 2 · Impact Analysis
|
|
94
|
+
Blast radius from a class or interface — reverse dependencies, through Spring DI, to the HTTP endpoints a change reaches.
|
|
95
|
+
`ask impact` · `ask impact-chain` (TX/SEC-enriched) · `ask pr-impact`
|
|
96
|
+
→ [reference](docs/USER_GUIDE.md#core-commands)
|
|
97
|
+
|
|
98
|
+
### 3 · Architecture Intelligence
|
|
99
|
+
The system map: module graph, dependency views, REST surface, per-class summaries, and a symbol-level IR for downstream tooling.
|
|
100
|
+
`ask export` · `ask repo-ir` · `ask endpoints` · `ask explain`
|
|
101
|
+
→ [reference](docs/USER_GUIDE.md#core-commands)
|
|
102
|
+
|
|
103
|
+
### 4 · Migration & Modernization
|
|
104
|
+
Is this codebase ready to upgrade? Per-dimension readiness (Jakarta / Spring Boot / JDK / Hibernate), located blockers, and an effort estimate.
|
|
105
|
+
`ask migrate-check` · `ask modernize`
|
|
106
|
+
→ [migrate-check reference](docs/migrate-check.md) · [MODERNIZATION.md](docs/MODERNIZATION.md)
|
|
107
|
+
|
|
108
|
+
### 5 · Spring Analysis
|
|
109
|
+
Deterministic Spring semantics: transactional anomalies (e.g. `@Transactional` on a private method = silent CGLIB no-op), security surface, request-body validation.
|
|
110
|
+
`ask spring-audit` · `ask validation`
|
|
111
|
+
→ [reference](docs/USER_GUIDE.md#core-commands)
|
|
112
|
+
|
|
113
|
+
### 6 · Developer Workflows
|
|
114
|
+
The everyday loop: diff-based PR review, symptom-driven bug triage, and delta context for continuous agent runs.
|
|
115
|
+
`ask review-pr` · `ask fix-bug` · `ask prepare-context`
|
|
116
|
+
→ [reference](docs/USER_GUIDE.md#typical-workflows)
|
|
117
|
+
|
|
118
|
+
### 7 · Utilities
|
|
119
|
+
`ask rename-class` (word-boundary Java rename) · `ask chunk-file` (split large files for agents) · `ask cache` (status / warm / clear / freshness)
|
|
120
|
+
→ [reference](docs/USER_GUIDE.md)
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## What it does — and doesn't
|
|
125
|
+
|
|
126
|
+
**ASK Engine reduces exploration cost.** It accelerates context acquisition and computes
|
|
127
|
+
blast radius; it does not replace reading code — it reduces how often an agent needs to.
|
|
128
|
+
All signals are **static and deterministic** (annotations, import graph, file structure) —
|
|
129
|
+
no runtime analysis, no LLM guessing.
|
|
130
|
+
|
|
131
|
+
Honest limits worth knowing before you rely on it:
|
|
132
|
+
|
|
133
|
+
- `impact` on an **implementation** class (`OrderServiceImpl`) returns 0 callers in Spring Boot — callers inject the interface. **Always target the interface.**
|
|
134
|
+
- `no_security_signal` on an endpoint means *no recognized method-level annotation*, **not** "unsecured" — Spring Security filter chains and custom authorization annotations show as `no_security_signal` unless taught via config (below).
|
|
135
|
+
- `spring-audit` / `impact-chain` are **Java/Spring only**; non-Java repos return `spring_detected: false`.
|
|
136
|
+
- Event topology (`--type events`) resolves Spring `ApplicationEvent` / `@EventListener` chains only — **not** Kafka/RabbitMQ/Redis routes.
|
|
137
|
+
- Architecture classification is tuned for Spring MVC layered apps; SPI/plugin models (e.g. Quarkus extensions) may be misclassified. JAX-RS subresource-locator endpoint recall is ~65%.
|
|
138
|
+
- Self-invocation `@Transactional` bypass (same-class call skipping the proxy) is not detected.
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Pricing
|
|
143
|
+
|
|
144
|
+
> **🎉 Early-adoption: Pro is currently unlocked for everyone.** Every install runs with
|
|
145
|
+
> full Pro entitlements — no size gate, no key. The tiers below describe the model the
|
|
146
|
+
> paywall will return to later.
|
|
147
|
+
|
|
148
|
+
**Gating is by repo size and automation — never by command.** Every command runs at full
|
|
149
|
+
power on Free for small and mid-size repos; you upgrade when the work gets bigger or automated.
|
|
150
|
+
|
|
151
|
+
| | **Free** — €0 | **Pro** — €19/mo · €190/yr per dev |
|
|
152
|
+
|---|---|---|
|
|
153
|
+
| Repo size | ≤ 500 Java source files | **> 500 Java files** (enterprise monoliths) |
|
|
154
|
+
| Commands | All of them, full output | Same commands, unlocked at scale |
|
|
155
|
+
| `impact` / `fix-bug` / `review-pr` / `modernize` | ✅ full on small repos | ✅ full on large repos (Free gets a capped preview) |
|
|
156
|
+
| `prepare-context delta` | 30 free runs/repo | unlimited — CI/CD automation |
|
|
157
|
+
| MCP local server, offline, no data egress | ✅ | ✅ |
|
|
158
|
+
|
|
159
|
+
**Non-Java repos are free at any size** — the size limit counts Java source files only.
|
|
160
|
+
ASK Engine monetises enterprise Java monoliths. Activate with `ask activate <key>`.
|
|
161
|
+
Full breakdown: [docs/PRODUCT_TIERS.md](docs/PRODUCT_TIERS.md).
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Configuration & privacy
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
ask config # version, config file path, telemetry status
|
|
169
|
+
ask telemetry disable # anonymous telemetry is on by default (opt-out)
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Telemetry collects version, OS, commands, flags, duration, repo-size range, and errors —
|
|
173
|
+
**no source code, paths, secrets, or output**. Disable any time with
|
|
174
|
+
`export SOURCECODE_TELEMETRY=0` (or `DO_NOT_TRACK=1`).
|
|
175
|
+
|
|
176
|
+
**Custom security annotations.** Teach `endpoints`, `spring-audit`, and `explain` about
|
|
177
|
+
project-specific authorization annotations via an optional `sourcecode.config.json` at the
|
|
178
|
+
repo root (otherwise they report `policy: "none_detected"`):
|
|
179
|
+
|
|
180
|
+
```json
|
|
181
|
+
{
|
|
182
|
+
"customSecurityAnnotations": [
|
|
183
|
+
{ "fullyQualifiedName": "com.example.security.M3FiltroSeguridad", "shortName": "M3FiltroSeguridad" }
|
|
184
|
+
]
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Matching endpoints report `policy: "custom"` and drop out of the `no_security_signal` count.
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## Documentation
|
|
193
|
+
|
|
194
|
+
| Doc | What it covers |
|
|
195
|
+
|-----|----------------|
|
|
196
|
+
| [USER_GUIDE.md](docs/USER_GUIDE.md) | Full command reference, flags, output schema, workflows |
|
|
197
|
+
| [migrate-check.md](docs/migrate-check.md) | Migration rule catalogue (MIG-001..043) + Hibernate stratification |
|
|
198
|
+
| [MODERNIZATION.md](docs/MODERNIZATION.md) | The modernization product: assess → understand → plan → execute |
|
|
199
|
+
| [PRODUCT_TIERS.md](docs/PRODUCT_TIERS.md) | Free vs Pro, pricing model |
|
|
200
|
+
| [DEMO-5MIN.md](docs/DEMO-5MIN.md) | A reproducible 5-minute demo |
|
|
201
|
+
| [MANUAL-USUARIO.md](docs/MANUAL-USUARIO.md) | Guía de usuario en español |
|
|
202
|
+
| [PRODUCT_IDENTITY.md](docs/PRODUCT_IDENTITY.md) | `ask` (command) vs `sourcecode` (package/alias) |
|
|
203
|
+
| [privacy.md](docs/privacy.md) | Telemetry and data-handling policy |
|
|
@@ -4496,7 +4496,18 @@ def validation_cmd(
|
|
|
4496
4496
|
from sourcecode.context_graph import ContextGraph
|
|
4497
4497
|
from sourcecode.validation_surface import build_validation_surface
|
|
4498
4498
|
# Structural facts come from the ContextGraph — the single access layer.
|
|
4499
|
-
|
|
4499
|
+
_graph = ContextGraph.build_from_root(target)
|
|
4500
|
+
data = build_validation_surface(target, graph=_graph)
|
|
4501
|
+
|
|
4502
|
+
# P1-C: classify the request-body validation *pattern* so a repo with a
|
|
4503
|
+
# validation framework on the classpath but no @Valid reads as
|
|
4504
|
+
# "present-but-unused" instead of a silent sea of zeros (DESIGN §2/§5).
|
|
4505
|
+
try:
|
|
4506
|
+
from sourcecode.validation_inference import infer_validation_pattern
|
|
4507
|
+
|
|
4508
|
+
data["validation_pattern"] = infer_validation_pattern(_graph.cir).to_dict()
|
|
4509
|
+
except Exception:
|
|
4510
|
+
pass
|
|
4500
4511
|
|
|
4501
4512
|
if path_prefix:
|
|
4502
4513
|
data["endpoints"] = [
|
|
@@ -4836,6 +4847,16 @@ def migrate_check_cmd(
|
|
|
4836
4847
|
help="Minimum severity to include: critical, high, medium, or low (default).",
|
|
4837
4848
|
show_default=True,
|
|
4838
4849
|
),
|
|
4850
|
+
compact: bool = typer.Option(
|
|
4851
|
+
False,
|
|
4852
|
+
"--compact",
|
|
4853
|
+
help=(
|
|
4854
|
+
"Bounded decision summary (JSON): readiness scores, headline blocker, "
|
|
4855
|
+
"effort, executive summary, Hibernate classification and aggregate "
|
|
4856
|
+
"counts, with large collections capped to their top items (+N more). "
|
|
4857
|
+
"No new analysis — same report, projected. Full detail is the default."
|
|
4858
|
+
),
|
|
4859
|
+
),
|
|
4839
4860
|
no_cache: bool = typer.Option(
|
|
4840
4861
|
False, "--no-cache",
|
|
4841
4862
|
help="Accepted for compatibility; this command always reads fresh source (no snapshot cache). No-op.",
|
|
@@ -4867,6 +4888,7 @@ def migrate_check_cmd(
|
|
|
4867
4888
|
\b
|
|
4868
4889
|
Examples:
|
|
4869
4890
|
ask migrate-check .
|
|
4891
|
+
ask migrate-check . --compact bounded decision summary
|
|
4870
4892
|
ask migrate-check /path/to/repo --format text
|
|
4871
4893
|
ask migrate-check . --min-severity high
|
|
4872
4894
|
ask migrate-check . --output migration.json
|
|
@@ -4905,7 +4927,11 @@ def migrate_check_cmd(
|
|
|
4905
4927
|
if format == "text":
|
|
4906
4928
|
output = report.to_text(min_severity=min_severity)
|
|
4907
4929
|
else:
|
|
4908
|
-
|
|
4930
|
+
# --compact projects the SAME report into a bounded, decision-grade view
|
|
4931
|
+
# (output-shaping only). Default (full) output is unchanged — it is the
|
|
4932
|
+
# baseline-oracle form and must stay byte-identical.
|
|
4933
|
+
payload = report.to_compact_dict() if compact else report.to_dict()
|
|
4934
|
+
output = _serialize_dict(payload, "json")
|
|
4909
4935
|
|
|
4910
4936
|
_total = report.summary.get("total_findings", 0)
|
|
4911
4937
|
_emit_command_output(
|
|
@@ -1308,6 +1308,33 @@ def _dimension_score(
|
|
|
1308
1308
|
return max(0, 100 - deduction)
|
|
1309
1309
|
|
|
1310
1310
|
|
|
1311
|
+
# --- Compact projection (output-shaping only) --------------------------------
|
|
1312
|
+
# `--compact` renders a bounded, decision-grade view of the SAME report: it caps
|
|
1313
|
+
# each large leaf collection to its top-N items and reports total/omitted counts.
|
|
1314
|
+
# It performs NO new analysis — it is a pure projection over the dict `to_dict()`
|
|
1315
|
+
# already produces (Semantic IR / ContextGraph / semantic engines untouched).
|
|
1316
|
+
# The default (full) output is unchanged and remains the baseline-oracle form.
|
|
1317
|
+
# FUTURE (not this increment): invert the default — emit compact by default and
|
|
1318
|
+
# add `--full` for the complete report — once the oracle baseline is recaptured.
|
|
1319
|
+
_COMPACT_TOP_N = 5
|
|
1320
|
+
|
|
1321
|
+
|
|
1322
|
+
def _cap_collection(items: list, top_n: int, key=None) -> dict:
|
|
1323
|
+
"""Project a list into a bounded `{total, shown, omitted, items}` view. Items
|
|
1324
|
+
are optionally reordered by `key` (stable) so the retained slice is the most
|
|
1325
|
+
important; ordering falls back to the engine's own emission order. No values
|
|
1326
|
+
are recomputed — only selected and counted."""
|
|
1327
|
+
total = len(items)
|
|
1328
|
+
ordered = sorted(items, key=key) if key is not None else items
|
|
1329
|
+
shown = ordered[:top_n]
|
|
1330
|
+
return {
|
|
1331
|
+
"total": total,
|
|
1332
|
+
"shown": len(shown),
|
|
1333
|
+
"omitted": max(0, total - len(shown)),
|
|
1334
|
+
"items": shown,
|
|
1335
|
+
}
|
|
1336
|
+
|
|
1337
|
+
|
|
1311
1338
|
@dataclass
|
|
1312
1339
|
class MigrationReport:
|
|
1313
1340
|
schema_version: str = "1.4"
|
|
@@ -1679,6 +1706,43 @@ class MigrationReport:
|
|
|
1679
1706
|
"metadata": self.metadata,
|
|
1680
1707
|
}
|
|
1681
1708
|
|
|
1709
|
+
def to_compact_dict(self, top_n: int = _COMPACT_TOP_N) -> dict:
|
|
1710
|
+
"""Bounded, decision-grade projection of `to_dict()`.
|
|
1711
|
+
|
|
1712
|
+
Keeps every decision field verbatim (readiness_score, per-dimension
|
|
1713
|
+
readiness, headline_blocker, blocking_count, estimated_effort_days,
|
|
1714
|
+
effort_breakdown, summary, Hibernate classification, aggregate counts) and
|
|
1715
|
+
caps only the large leaf collections — top-level `findings` and the
|
|
1716
|
+
Hibernate `rewrite_targets` / `findings` / `critical_call_chains` /
|
|
1717
|
+
`golden_sql_hotspots` — to their top-`top_n` items, each wrapped as
|
|
1718
|
+
`{total, shown, omitted, items}`. It reuses the already-computed
|
|
1719
|
+
`to_dict()` output and recomputes nothing (output-shaping only)."""
|
|
1720
|
+
full = self.to_dict()
|
|
1721
|
+
compact = dict(full)
|
|
1722
|
+
compact["mode"] = "compact"
|
|
1723
|
+
compact["compact_note"] = (
|
|
1724
|
+
f"Bounded decision summary: large collections are capped to the top {top_n} "
|
|
1725
|
+
"items (see each collection's total/omitted). Run without --compact (JSON "
|
|
1726
|
+
"default) for the complete report. A future release will invert this — "
|
|
1727
|
+
"compact by default with --full for the full detail."
|
|
1728
|
+
)
|
|
1729
|
+
# Top-level findings: retain the most severe first, then engine order.
|
|
1730
|
+
compact["findings"] = _cap_collection(
|
|
1731
|
+
full["findings"], top_n,
|
|
1732
|
+
key=lambda f: SEVERITY_ORDER.get(f.get("severity"), 3),
|
|
1733
|
+
)
|
|
1734
|
+
hib = full.get("hibernate")
|
|
1735
|
+
if isinstance(hib, dict):
|
|
1736
|
+
h = dict(hib)
|
|
1737
|
+
for _col in (
|
|
1738
|
+
"rewrite_targets", "findings",
|
|
1739
|
+
"critical_call_chains", "golden_sql_hotspots",
|
|
1740
|
+
):
|
|
1741
|
+
if isinstance(h.get(_col), list):
|
|
1742
|
+
h[_col] = _cap_collection(h[_col], top_n)
|
|
1743
|
+
compact["hibernate"] = h
|
|
1744
|
+
return compact
|
|
1745
|
+
|
|
1682
1746
|
def to_text(self, min_severity: str = "low") -> str:
|
|
1683
1747
|
min_order = SEVERITY_ORDER.get(min_severity, 3)
|
|
1684
1748
|
visible = [f for f in self.findings if SEVERITY_ORDER.get(f.severity, 3) <= min_order]
|