sourcecode 2.4.0__tar.gz → 2.5.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.
Files changed (159) hide show
  1. {sourcecode-2.4.0 → sourcecode-2.5.0}/CHANGELOG.md +53 -0
  2. {sourcecode-2.4.0 → sourcecode-2.5.0}/PKG-INFO +4 -4
  3. {sourcecode-2.4.0 → sourcecode-2.5.0}/README.md +3 -3
  4. {sourcecode-2.4.0 → sourcecode-2.5.0}/pyproject.toml +1 -1
  5. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/__init__.py +1 -1
  6. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/archetype.py +46 -0
  7. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/cli.py +429 -3
  8. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/context_graph.py +32 -24
  9. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/repository_ir.py +1 -1
  10. sourcecode-2.5.0/src/sourcecode/retrieval/__init__.py +192 -0
  11. sourcecode-2.5.0/src/sourcecode/retrieval/context.py +241 -0
  12. sourcecode-2.5.0/src/sourcecode/retrieval/errors.py +41 -0
  13. sourcecode-2.5.0/src/sourcecode/retrieval/executor.py +51 -0
  14. sourcecode-2.5.0/src/sourcecode/retrieval/planner.py +297 -0
  15. sourcecode-2.5.0/src/sourcecode/retrieval/query.py +484 -0
  16. sourcecode-2.5.0/src/sourcecode/retrieval/request.py +94 -0
  17. sourcecode-2.5.0/src/sourcecode/retrieval/resolution.py +135 -0
  18. sourcecode-2.5.0/src/sourcecode/retrieval/result.py +144 -0
  19. sourcecode-2.5.0/src/sourcecode/retrieval/retriever.py +62 -0
  20. sourcecode-2.5.0/src/sourcecode/retrieval/runtime.py +259 -0
  21. sourcecode-2.5.0/src/sourcecode/retrieval/steps.py +242 -0
  22. sourcecode-2.5.0/src/sourcecode/retrieval/steps_endpoint.py +311 -0
  23. sourcecode-2.5.0/src/sourcecode/retrieval/steps_graph.py +248 -0
  24. sourcecode-2.5.0/src/sourcecode/retrieval/steps_impact.py +293 -0
  25. sourcecode-2.5.0/src/sourcecode/retrieval/steps_intf.py +247 -0
  26. sourcecode-2.5.0/src/sourcecode/retrieval/steps_struct.py +338 -0
  27. sourcecode-2.5.0/src/sourcecode/retrieval/steps_txsec.py +351 -0
  28. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/security_config.py +4 -4
  29. {sourcecode-2.4.0 → sourcecode-2.5.0}/.github/workflows/build-windows.yml +0 -0
  30. {sourcecode-2.4.0 → sourcecode-2.5.0}/.gitignore +0 -0
  31. {sourcecode-2.4.0 → sourcecode-2.5.0}/.ruff.toml +0 -0
  32. {sourcecode-2.4.0 → sourcecode-2.5.0}/CONTRIBUTING.md +0 -0
  33. {sourcecode-2.4.0 → sourcecode-2.5.0}/LICENSE +0 -0
  34. {sourcecode-2.4.0 → sourcecode-2.5.0}/SECURITY.md +0 -0
  35. {sourcecode-2.4.0 → sourcecode-2.5.0}/raw +0 -0
  36. {sourcecode-2.4.0 → sourcecode-2.5.0}/scripts/compare_integration_engines.py +0 -0
  37. {sourcecode-2.4.0 → sourcecode-2.5.0}/scripts/customer_smoke_test.sh +0 -0
  38. {sourcecode-2.4.0 → sourcecode-2.5.0}/scripts/generate_jdk_exports.py +0 -0
  39. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/adaptive_scanner.py +0 -0
  40. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/architecture_analyzer.py +0 -0
  41. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/architecture_summary.py +0 -0
  42. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/ast_extractor.py +0 -0
  43. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/cache.py +0 -0
  44. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/call_surface.py +0 -0
  45. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/caller_metrics.py +0 -0
  46. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/canonical_ir.py +0 -0
  47. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/cir_graphs.py +0 -0
  48. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/classifier.py +0 -0
  49. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/code_notes_analyzer.py +0 -0
  50. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/confidence_analyzer.py +0 -0
  51. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/context_cache.py +0 -0
  52. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/context_scorer.py +0 -0
  53. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/context_summarizer.py +0 -0
  54. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/contract_model.py +0 -0
  55. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/contract_pipeline.py +0 -0
  56. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/coverage_parser.py +0 -0
  57. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/dependency_analyzer.py +0 -0
  58. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/detectors/__init__.py +0 -0
  59. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/detectors/base.py +0 -0
  60. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/detectors/csproj_parser.py +0 -0
  61. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/detectors/dart.py +0 -0
  62. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/detectors/dotnet.py +0 -0
  63. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/detectors/elixir.py +0 -0
  64. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/detectors/go.py +0 -0
  65. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/detectors/heuristic.py +0 -0
  66. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/detectors/hybrid.py +0 -0
  67. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/detectors/java.py +0 -0
  68. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/detectors/jvm_ext.py +0 -0
  69. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/detectors/nodejs.py +0 -0
  70. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/detectors/parsers.py +0 -0
  71. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/detectors/php.py +0 -0
  72. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/detectors/project.py +0 -0
  73. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/detectors/python.py +0 -0
  74. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/detectors/ruby.py +0 -0
  75. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/detectors/rust.py +0 -0
  76. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/detectors/systems.py +0 -0
  77. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/detectors/terraform.py +0 -0
  78. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/detectors/tooling.py +0 -0
  79. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/doc_analyzer.py +0 -0
  80. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/dynamic_argument_surface.py +0 -0
  81. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/endpoint_literals.py +0 -0
  82. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/endpoint_metrics.py +0 -0
  83. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/entrypoint_classifier.py +0 -0
  84. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/env_analyzer.py +0 -0
  85. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/error_schema.py +0 -0
  86. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/evidence_provider.py +0 -0
  87. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/explain.py +0 -0
  88. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/file_chunker.py +0 -0
  89. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/file_classifier.py +0 -0
  90. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/format_contract.py +0 -0
  91. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/fqn_utils.py +0 -0
  92. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/git_analyzer.py +0 -0
  93. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/graph_analyzer.py +0 -0
  94. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/graph_evidence.py +0 -0
  95. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/hibernate_strat.py +0 -0
  96. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/jdk_exports.py +0 -0
  97. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/license.py +0 -0
  98. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/mcp/__init__.py +0 -0
  99. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/mcp/onboarding/__init__.py +0 -0
  100. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/mcp/onboarding/applier.py +0 -0
  101. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/mcp/onboarding/backup.py +0 -0
  102. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/mcp/onboarding/detector.py +0 -0
  103. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/mcp/onboarding/planner.py +0 -0
  104. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/mcp/orchestrator.py +0 -0
  105. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/mcp/registry.py +0 -0
  106. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/mcp/runner.py +0 -0
  107. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/mcp/server.py +0 -0
  108. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/mcp_nudge.py +0 -0
  109. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/metrics_analyzer.py +0 -0
  110. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/migrate_check.py +0 -0
  111. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/openapi_surface.py +0 -0
  112. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/output_budget.py +0 -0
  113. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/path_filters.py +0 -0
  114. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/pr_comment_renderer.py +0 -0
  115. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/pr_impact.py +0 -0
  116. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/prepare_context.py +0 -0
  117. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/progress.py +0 -0
  118. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/ranking_engine.py +0 -0
  119. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/redactor.py +0 -0
  120. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/relevance_scorer.py +0 -0
  121. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/rename_refactor.py +0 -0
  122. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/repo_classifier.py +0 -0
  123. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/ris.py +0 -0
  124. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/runtime_classifier.py +0 -0
  125. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/scanner.py +0 -0
  126. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/schema.py +0 -0
  127. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/security_posture.py +0 -0
  128. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/semantic_analyzer.py +0 -0
  129. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/semantic_impact_engine.py +0 -0
  130. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/semantic_integration_engine.py +0 -0
  131. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/semantic_services.py +0 -0
  132. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/serializer.py +0 -0
  133. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/spring_event_topology.py +0 -0
  134. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/spring_findings.py +0 -0
  135. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/spring_impact.py +0 -0
  136. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/spring_model.py +0 -0
  137. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/spring_security_audit.py +0 -0
  138. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/spring_semantic.py +0 -0
  139. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/spring_tx_analyzer.py +0 -0
  140. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/summarizer.py +0 -0
  141. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/telemetry/__init__.py +0 -0
  142. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/telemetry/config.py +0 -0
  143. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/telemetry/consent.py +0 -0
  144. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/telemetry/events.py +0 -0
  145. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/telemetry/filters.py +0 -0
  146. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/telemetry/transport.py +0 -0
  147. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/tree_utils.py +0 -0
  148. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/type_usage_surface.py +0 -0
  149. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/validation_inference.py +0 -0
  150. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/validation_surface.py +0 -0
  151. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/version_check.py +0 -0
  152. {sourcecode-2.4.0 → sourcecode-2.5.0}/src/sourcecode/workspace.py +0 -0
  153. {sourcecode-2.4.0 → sourcecode-2.5.0}/supabase/functions/README.md +0 -0
  154. {sourcecode-2.4.0 → sourcecode-2.5.0}/supabase/functions/get-license/index.ts +0 -0
  155. {sourcecode-2.4.0 → sourcecode-2.5.0}/supabase/functions/lemonsqueezy-webhook/index.ts +0 -0
  156. {sourcecode-2.4.0 → sourcecode-2.5.0}/supabase/functions/telemetry/index.ts +0 -0
  157. {sourcecode-2.4.0 → sourcecode-2.5.0}/supabase/sql/license_event_ordering.sql +0 -0
  158. {sourcecode-2.4.0 → sourcecode-2.5.0}/supabase/sql/licensing_schema.sql +0 -0
  159. {sourcecode-2.4.0 → sourcecode-2.5.0}/supabase/sql/telemetry_events.sql +0 -0
@@ -1,5 +1,58 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.5.0] — 2026-07-13
4
+
5
+ **Semantic Retrieval Engine v1 — a declarative, agent-ready query layer over ASK's
6
+ already-built knowledge.** Retrieval turns *"ask a typed question of the repository"*
7
+ into a first-class, reusable operation (Layer 3.5, above the Knowledge Layer, below any
8
+ presentation). It **queries** existing structured knowledge — it never extracts, parses,
9
+ or computes new evidence: every answer is a composition of existing engines acquired
10
+ through one shared, cached `KnowledgeContext`. Frozen as v1 in ADR-0004.
11
+
12
+ ### Added
13
+
14
+ - **Semantic Retrieval Engine** (`src/sourcecode/retrieval/`): a typed `RetrievalRequest`
15
+ → `IntentResolver` → `QueryPlanner` → declarative `KnowledgeQuery` (a closed, serializable
16
+ Step algebra) → generic `QueryPlanRuntime` → structured `KnowledgeResult` (entities,
17
+ evidence, observations, confidence, structured explanation, provenance, executed plan).
18
+ Adding an intent is enum + plan + registered steps — the generic Runtime is unchanged;
19
+ this held across 11 phases and **29 intents / 9 domains**.
20
+ - **29 experimental `ask retrieve …` intents** across Architecture, Impact, Transactions,
21
+ Security, Interfaces/Validation, Integrations, Subsystems, Dependencies, and Graph — each
22
+ a pure composition of an existing engine (ArchetypeClassifier, `compute_blast_radius`,
23
+ `SpringSemanticModel`, `run_tx_audit`, `run_security_audit`, `build_validation_surface`,
24
+ `SemanticIntegrationEngine`, `run_impact_chain`, the module graph). Cross-pack step reuse
25
+ (`ResolveTarget`, `ResolveEndpointRef`, `ResolveScope`, generic `BuildResult`).
26
+ - **Consolidation (B1–B4):** lazy SourceMap acquisition; per-acquisition timing surfaced in
27
+ the runtime report; impact-pack evidence parity; the `limit` option activated (default
28
+ unbounded). `ADR-0004` + `DESIGN-knowledge-provider-integration.md` document the frozen
29
+ contract and the pattern for adding future knowledge providers.
30
+ - **User guide — architecture chapters (EN + ES):** *How ASK works*, *The semantic engine*,
31
+ *Architectural intelligence*, *AI workflows* — the Semantic IR / Context Graph / Knowledge
32
+ Layer / evidence model that the guides previously did not cover.
33
+
34
+ ### Fixed
35
+
36
+ - **Cold-path performance / apparent hang:** `ContextGraph.relations()`/`symbols()` were
37
+ re-converting every edge and re-sorting every node on each call, and per-file consumers
38
+ call them once per file — an O(files × edges) blow-up that made cold `ask --agent` take
39
+ minutes on large repositories. Memoizing the projections cut jobrunr cold ~21 s → ~4 s and
40
+ BroadleafCommerce cold `--agent` from a multi-minute hang to ~54 s. Benefits every command
41
+ that reads the graph.
42
+ - **`archetype` library de-bias (P0):** consumable libraries were confidently labeled
43
+ `engine` (their internals are engine-like). Non-runnable artifacts (no app/server/servlet
44
+ entry) are now correctly distinguished from runnable engines — jobrunr `engine(high)` →
45
+ `library(low)`; real engines (Neo4j) unchanged. Implemented as transparent, auditable
46
+ evidence.
47
+ - **`fix-bug` argument consistency (P0):** now accepts the sibling-consistent
48
+ `fix-bug <symptom> <path>` form (mirroring `impact <target> <path>`) instead of failing
49
+ with a raw usage error; `--symptom` and path-only forms remain unchanged.
50
+
51
+ ### Removed
52
+
53
+ - All references to a proprietary third-party security annotation were scrubbed from code,
54
+ tests, and docs (ASK references nothing vendor-proprietary).
55
+
3
56
  ## [2.4.0] — 2026-07-12
4
57
 
5
58
  **AI Context Cache — a provider-agnostic cache for ASK's reusable Knowledge
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sourcecode
3
- Version: 2.4.0
3
+ Version: 2.5.0
4
4
  Summary: Persistent structural context and ultra-fast repeated analysis for AI coding agents
5
5
  License-File: LICENSE
6
6
  Keywords: agents,ai,codebase,context,developer-tools,llm
@@ -42,7 +42,7 @@ Description-Content-Type: text/markdown
42
42
 
43
43
  **Context · Impact · Migration · Architecture · Review — everything from one structural model.**
44
44
 
45
- ![Version](https://img.shields.io/badge/version-2.3.0-blue)
45
+ ![Version](https://img.shields.io/badge/version-2.5.0-blue)
46
46
  ![Python](https://img.shields.io/badge/python-3.9%2B-green)
47
47
 
48
48
  > **ASK Engine** is the product. The CLI command is **`ask`**. The legacy **`sourcecode`**
@@ -84,7 +84,7 @@ brew tap haroundominique/sourcecode && brew install sourcecode
84
84
  # pip / pipx
85
85
  pipx install sourcecode # or: pip install sourcecode
86
86
 
87
- ask version # ask 2.3.0
87
+ ask version # ask 2.5.0
88
88
  ```
89
89
 
90
90
  > **Package vs. command.** The install package is named `sourcecode` this release
@@ -218,7 +218,7 @@ repo root (otherwise they report `policy: "none_detected"`):
218
218
  ```json
219
219
  {
220
220
  "customSecurityAnnotations": [
221
- { "fullyQualifiedName": "com.example.security.M3FiltroSeguridad", "shortName": "M3FiltroSeguridad" }
221
+ { "fullyQualifiedName": "com.example.security.CustomSecurityAnnotation", "shortName": "CustomSecurityAnnotation" }
222
222
  ]
223
223
  }
224
224
  ```
@@ -4,7 +4,7 @@
4
4
 
5
5
  **Context · Impact · Migration · Architecture · Review — everything from one structural model.**
6
6
 
7
- ![Version](https://img.shields.io/badge/version-2.3.0-blue)
7
+ ![Version](https://img.shields.io/badge/version-2.5.0-blue)
8
8
  ![Python](https://img.shields.io/badge/python-3.9%2B-green)
9
9
 
10
10
  > **ASK Engine** is the product. The CLI command is **`ask`**. The legacy **`sourcecode`**
@@ -46,7 +46,7 @@ brew tap haroundominique/sourcecode && brew install sourcecode
46
46
  # pip / pipx
47
47
  pipx install sourcecode # or: pip install sourcecode
48
48
 
49
- ask version # ask 2.3.0
49
+ ask version # ask 2.5.0
50
50
  ```
51
51
 
52
52
  > **Package vs. command.** The install package is named `sourcecode` this release
@@ -180,7 +180,7 @@ repo root (otherwise they report `policy: "none_detected"`):
180
180
  ```json
181
181
  {
182
182
  "customSecurityAnnotations": [
183
- { "fullyQualifiedName": "com.example.security.M3FiltroSeguridad", "shortName": "M3FiltroSeguridad" }
183
+ { "fullyQualifiedName": "com.example.security.CustomSecurityAnnotation", "shortName": "CustomSecurityAnnotation" }
184
184
  ]
185
185
  }
186
186
  ```
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "sourcecode"
7
- version = "2.4.0"
7
+ version = "2.5.0"
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"
@@ -4,4 +4,4 @@ ASK Engine is the product. ``ask`` is the canonical CLI command; ``sourcecode``
4
4
  the legacy compatibility alias and the Python/PyPI package name. See
5
5
  docs/PRODUCT_IDENTITY.md (normative)."""
6
6
 
7
- __version__ = "2.4.0"
7
+ __version__ = "2.5.0"
@@ -80,6 +80,17 @@ _MIN_PRIMARY_SCORE = 0.05
80
80
  # A winner must clear this absolute score (not just the top-2 margin) to earn
81
81
  # medium/high confidence — a near-floor lone candidate stays "low".
82
82
  _MIN_CONFIDENT_SCORE = 0.5
83
+ # Fraction of engine's positive contribution discounted for a non-runnable artifact
84
+ # (P0 library de-bias): an engine-like internal core is expected of a library, so it is not
85
+ # discriminating. Tuned so a clear library (no app/server/servlet entry) is not confidently
86
+ # labeled an engine, while runnable systems (which never trigger the gate) are untouched.
87
+ _LIBRARY_ENGINE_DISCOUNT = 0.55
88
+ # Entry kinds that make a repo a runnable system (an app/server/servlet/daemon) rather
89
+ # than a consumable library. Used to gate the library de-bias (P0).
90
+ _RUNNABLE_ENTRY_KINDS = frozenset({
91
+ "application", "bootstrap", "main", "server", "daemon", "worker",
92
+ "mvc_controller", "jax_rs_controller", "servlet", "security_filter", "filter",
93
+ })
83
94
 
84
95
 
85
96
  @dataclass
@@ -389,6 +400,41 @@ class ArchetypeClassifier:
389
400
  f"{f.module_count} modules; distributed mass ≈ {cm['distributed']:.0%}",
390
401
  1.5, multi, max(cm["distributed"], 0.1))
391
402
  self._apply_graph_evidence("software_archetype", cands, f)
403
+ # ── Library de-bias (P0) ────────────────────────────────────────────────
404
+ # A consumable JVM artifact — `jar` packaging with no server/bootstrap/application
405
+ # entry — is a library, not a runnable system. But a library naturally exhibits
406
+ # engine-like topology: a few core API types with high fan-in, tightly-coupled
407
+ # internals (SCCs), hub concentration. Those graph metrics (`graph_*`) otherwise
408
+ # label every library an "engine" (observed: jobrunr → engine(high), library 0.3).
409
+ # Correct it transparently: (1) add a packaging-grounded library signal that does
410
+ # not depend on an `api/` package existing; (2) append a NAMED negative evidence row
411
+ # that discounts most of engine's graph-derived score, since topological hubness in
412
+ # a library is expected and therefore not discriminating for "engine".
413
+ # A runnable/web entry of ANY kind (an app bootstrap, an HTTP controller, a
414
+ # servlet, a daemon) means the repo is a system you run, not a library you depend
415
+ # on. Packaging is unreliable here (gradle libs report no packaging; maven
416
+ # aggregators report `pom`), so the entry-kind surface is the robust signal.
417
+ is_runnable = any(k in f.entry_kinds for k in _RUNNABLE_ENTRY_KINDS)
418
+ is_library_shaped = not is_runnable
419
+ if is_library_shaped:
420
+ add("library", "no_runnable_entry",
421
+ f"entry kinds {sorted(f.entry_kinds) or 'none'} — no app/server/servlet "
422
+ "bootstrap; a consumable artifact, not a runnable system",
423
+ 3.0, 1.0, 0.7)
424
+ # A library legitimately owns an engine-like core (storage/kernel mass, hub
425
+ # topology, SCCs) — that is what a library *is*. Discount most of engine's
426
+ # positive evidence for a non-runnable artifact so its internal machinery does
427
+ # not, alone, promote it to "engine". Transparent: a named negative row.
428
+ engine_positive = sum(max(0.0, e.contribution) for e in cands["engine"])
429
+ if engine_positive > 0:
430
+ discount = engine_positive * _LIBRARY_ENGINE_DISCOUNT
431
+ cands["engine"].append(Evidence(
432
+ "library_core_discount",
433
+ "non-runnable artifact: an engine-like internal core (storage/kernel "
434
+ "mass, hubs, SCCs) is expected of a library and is not, alone, evidence "
435
+ "of an engine product",
436
+ 1.0, 1.0, 1.0, -discount,
437
+ ))
392
438
  return self._resolve("software_archetype", cands, f)
393
439
 
394
440
  def _architectural_style(self, f: _Features) -> DimensionResult: