@saptools/service-flow 0.1.51 β†’ 0.1.53

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 (56) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +16 -14
  3. package/TECHNICAL-NOTE.md +18 -6
  4. package/dist/{chunk-YZJKE5UX.js β†’ chunk-LFH7C46B.js} +4290 -1261
  5. package/dist/chunk-LFH7C46B.js.map +1 -0
  6. package/dist/cli.js +435 -515
  7. package/dist/cli.js.map +1 -1
  8. package/dist/index.d.ts +45 -7
  9. package/dist/index.js +1 -1
  10. package/package.json +1 -1
  11. package/src/cli/000-clean.ts +82 -0
  12. package/src/cli/001-doctor-projection.ts +140 -0
  13. package/src/cli/doctor.ts +20 -3
  14. package/src/cli.ts +75 -57
  15. package/src/db/connection.ts +1 -1
  16. package/src/db/migrations.ts +5 -3
  17. package/src/db/repositories.ts +130 -24
  18. package/src/db/schema.ts +7 -2
  19. package/src/indexer/repository-indexer.ts +57 -29
  20. package/src/indexer/workspace-indexer.ts +84 -6
  21. package/src/linker/000-implementation-candidates.ts +641 -0
  22. package/src/linker/001-implementation-evidence-projection.ts +119 -0
  23. package/src/linker/002-call-evidence.ts +226 -0
  24. package/src/linker/cross-repo-linker.ts +27 -441
  25. package/src/linker/dynamic-edge-resolver.ts +35 -0
  26. package/src/linker/external-http-target.ts +24 -3
  27. package/src/linker/helper-package-linker.ts +18 -2
  28. package/src/linker/service-resolver.ts +45 -2
  29. package/src/output/doctor-output.ts +13 -4
  30. package/src/output/table-output.ts +33 -5
  31. package/src/parsers/cds-parser.ts +8 -2
  32. package/src/parsers/decorator-parser.ts +382 -48
  33. package/src/parsers/handler-registration-parser.ts +38 -21
  34. package/src/parsers/imported-wrapper-parser.ts +18 -5
  35. package/src/parsers/outbound-call-parser.ts +25 -8
  36. package/src/parsers/package-json-parser.ts +36 -11
  37. package/src/parsers/service-binding-parser-helpers.ts +8 -1
  38. package/src/parsers/service-binding-parser.ts +6 -3
  39. package/src/parsers/symbol-parser.ts +13 -3
  40. package/src/parsers/ts-project.ts +54 -0
  41. package/src/trace/000-dynamic-target-types.ts +96 -0
  42. package/src/trace/001-dynamic-identity.ts +308 -0
  43. package/src/trace/002-trace-diagnostics.ts +54 -0
  44. package/src/trace/003-dynamic-references.ts +283 -0
  45. package/src/trace/004-dynamic-candidate-sources.ts +155 -0
  46. package/src/trace/005-implementation-selection.ts +187 -0
  47. package/src/trace/006-contextual-projection.ts +30 -0
  48. package/src/trace/007-implementation-start-diagnostic.ts +61 -0
  49. package/src/trace/dynamic-targets.ts +582 -306
  50. package/src/trace/evidence.ts +331 -46
  51. package/src/trace/implementation-hints.ts +148 -8
  52. package/src/trace/selectors.ts +551 -3
  53. package/src/trace/trace-engine.ts +129 -135
  54. package/src/types.ts +27 -1
  55. package/src/utils/000-bounded-projection.ts +161 -0
  56. package/dist/chunk-YZJKE5UX.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.53
4
+
5
+ - Validated dynamic routes from the outbound call's selected service binding, including helper-return provenance, exact template matches, and explicit alias/destination conflicts that now fail closed with structured no-match evidence.
6
+ - Kept deterministic identity inference attached to the concrete service route owner while allowing a separately validated helper implementation for inherited operations.
7
+ - Bounded persisted call, implementation, parser-alternative, trace, selector, and strict-doctor candidate projections with stable count and omission metadata while retaining canonical SQLite facts for decisions and scoped hints.
8
+
9
+ ## 0.1.52
10
+
11
+ - Narrowed dynamic targets before ranking, scoped strong evidence by exact repository IDs, required workspace-wide identity uniqueness, refused conflicting/incomplete/margin-bound inference, shell-quoted suggestions, and bounded all candidate projections.
12
+ - Indexed supported zero-argument CAP lifecycle decorators with runtime import provenance, kept lifecycle/event methods out of operation implementation matching, and added fail-closed repository, operation, handler, and no-executable-method diagnostics.
13
+ - Coordinated index and clean writers with recoverable owner metadata and actionable lock failures while preserving atomic last-good publication, including backward-safe index creation during migration.
14
+ - Reused immutable package/source text and TypeScript AST snapshots during sequential preparation, and added deterministic table/JSON, workspace-scope, integrity, concurrency, migration, and parse-failure coverage.
15
+
3
16
  ## 0.1.51
4
17
 
5
18
  - Added trace and graph `--dynamic-mode strict|candidates|infer` with capped `--max-dynamic-candidates` exploration for runtime-dependent remote targets.
package/README.md CHANGED
@@ -56,15 +56,21 @@ npm install @saptools/service-flow
56
56
 
57
57
  - Runtime `--var` values are considered only for dynamic, ambiguous, or unresolved **remote** graph edges whose alias, destination, service path, or operation path expressions contain supplied placeholders. Placeholder keys are the full trimmed expression inside `${...}`, so keys such as `domainInfo.serviceName`, `domainInfo.shortName?.toLowerCase()`, and `items[0].service` can be supplied literally without JavaScript evaluation. Local database, external HTTP, event, and already resolved static edges keep their persisted status, target, reason, and confidence. Partial substitutions remain dynamic and report the missing placeholder names.
58
58
  - `trace` and `graph` both accept repeatable `--var key=value` options. Effective substitutions are rendered in trace evidence without mutating the persisted graph. Confidence values are bounded to `[0, 1]`.
59
- - Dynamic target exploration is explicit. Default `--dynamic-mode strict` keeps missing-runtime-variable edges unresolved, but diagnostics summarize ranked candidates and copyable `--var` sets when indexed evidence can derive likely values. `--dynamic-mode candidates` renders capped exploratory candidate branches without selecting or traversing them. `--dynamic-mode infer` traverses only when all missing placeholders are derived from deterministic indexed evidence and one candidate is uniquely strongest.
60
- - Repository selectors on list, trace, graph, and inspect commands narrow scope. Unknown selectors return empty machine-readable diagnostics instead of falling back to the whole workspace.
59
+ - Dynamic target exploration is explicit. Default `--dynamic-mode strict` keeps every target with unresolved runtime variables fail-closed, but diagnostics can provide complete copyable `--var` sets. `--dynamic-mode candidates` renders only viable, capped, explicitly unselected branches while the route remains unresolved, never enters their handler bodies, and adds no exploratory branch once complete explicit values resolve the route. `--dynamic-mode infer` traverses only when the top viable, complete candidate scores at least `0.85` and exceeds the runner-up by more than `0.05`; exact ties, candidates exactly on the margin, conflicts, duplicate identities, incomplete leaders, and weaker scores stay unresolved.
60
+ - Explicit variables are applied before candidate ranking. When a call has one selected binding, its original service-path, alias, and destination templates are matched against each concrete candidate before any repository-wide fallback; a package-level require is considered only when its alias matches that binding in the same caller repository. A conflict between a supplied value and a value derived from one of those validated signals rejects the candidate and yields `no_candidate_after_runtime_substitution` rather than a resolver-only target.
61
+ - Identity fallback removes an npm scope, splits camel case, lowercases, folds non-alphanumeric separator runs to `_`, and trims edge separators. It requires the complete normalized concrete route-owner package basename or repository name to match one placeholder with literal prefix and suffix, a resolved implementation for that effective operation, and workspace-wide unique identity/value evidence. A helper-owned implementation is valid evidence for an inherited operation, but helper and base-model names are never used as route identity. It never uses substrings, duplicate names, or discovery order. Generated commands shell-quote expression keys and values when required.
62
+ - `--max-dynamic-candidates` bounds candidate branches, viable and rejected suggestions, variable sets, nested derivation/conflict evidence, and projected persisted candidate arrays in table and JSON output. Link-time and doctor candidate-like arrays carry stable total/shown/omitted metadata; canonical SQLite facts, rather than a displayed prefix, remain the source for trace inference and implementation hints. `omittedCandidateCount` means omitted **viable** candidates; rejected candidates have separate total, shown, and omitted counts.
63
+ - Repository selectors on list, trace, graph, and inspect commands narrow scope by workspace and exact repository ID. Unknown selectors return empty machine-readable diagnostics instead of falling back to another workspace or the whole database.
61
64
  - Helper-package dependency edges prefer exact indexed package names. Duplicate package-name candidates are persisted as ambiguous evidence rather than silently selecting one repository.
62
65
  - Handler registration parsing is AST-based for common `createCombinedHandler({ handler: ... })` forms: direct arrays, arrays assembled with spreads, non-`handlers` array names, aliased class imports, default-imported arrays, named exported arrays, and safe relative re-exports. Class-level rows keep registration file/line and import evidence.
66
+ - Zero-argument CAP lifecycle method decorators in the supported `OnCreate/Read/Update/Delete`, `Before*`, and `After*` families are indexed only with runtime (not type-only) handler/import evidence. Nonzero arguments, missing bodies, and unsupported shapes remain non-executable with raw resolution evidence. Lifecycle phase, event, canonical decorator, and source location remain distinct from CDS action/function implementation evidence. A known handler with no executable method reports `handler_methods_not_indexed`; a mixed class reports `handler_decorators_not_indexed` while its supported methods remain traceable.
63
67
  - Implementation edges require both operation compatibility and registration evidence. Decorator operation signals are stronger than method-name fallback; common generated names such as `FuncGetConfiguration` and `ActionGetConfiguration` are normalized before comparison, and a contradictory decorator rejects the candidate even when the TypeScript method name collides. Same-repository registrations do not need a self-dependency edge; cross-package matches use registration or handler-package dependencies on the model package. Duplicate strong candidates are stored as ambiguous implementation edges.
64
68
  - Traces render persisted `OPERATION_IMPLEMENTED_BY_HANDLER` hops after static or runtime remote operation resolution, including terminal handler nodes and ambiguous or unresolved implementation evidence when traversal cannot continue.
65
69
  - Repository fingerprints include source content, package name/version, dependencies and devDependencies, scripts, normalized `cds.requires` (including nested credentials), package file content, and the analyzer version. Metadata-only changes therefore trigger reindexing.
66
70
  - Index publication is designed around the last-good snapshot: failed parse or persistence attempts are recorded as diagnostics and must not be mixed with older graph facts. After indexing changes, relink before relying on graph/trace output; doctor reports stale or inconsistent stores where detectable.
67
71
  - Source discovery, file reads, hashing, parsing, and publication are all inside the repository-level protected indexing flow. A failed read keeps the previous fingerprint and facts, marks the repository failed, and records a `source_read_failed` diagnostic; a later successful index clears superseded read-failure diagnostics during fact publication.
72
+ - Index preparation remains deterministic and sequential. Each source file and `package.json` is read once into a repository-scoped immutable snapshot, and all TypeScript parser entrypoints share one lazy AST for that file. Source snapshots are released after repository preparation; prepared facts still publish together in the existing workspace transaction.
73
+ - Index writers are coordinated per SQLite database with a short atomic claim. A second writer fails with `index_writer_active`; a claim that remains SQLite-locked past the bounded wait reports `index_writer_coordination_failed`. A dead owner or sufficiently old legacy ownerless row is reconciled before a new claim. `clean`, including `--db-only`, uses the same claim and removes only exact SQLite sidecar files. Normal failures finalize their run row, while read-only list, trace, inspect, and doctor commands remain usable whenever the short publication transaction is not active.
68
74
  - Normal successful database commands on supported Node 24 runtimes suppress the known `node:sqlite` experimental warning so JSON stdout remains parseable and stderr-clean. Real service-flow errors still use stderr and non-zero exit codes.
69
75
  - Doctor treats a `running` index run as abandoned only after 60 minutes and includes the run id/start time. Active short-lived concurrent runs are not default warnings.
70
76
  - Fresh databases include foreign keys for key graph, run, and diagnostic tables. Migrated legacy stores that still lack that metadata are reported by doctor with `legacy_schema_weaker_foreign_keys`; rebuild into a fresh database if strict structural parity is required.
@@ -72,7 +78,7 @@ npm install @saptools/service-flow
72
78
  - Persisted graph rows take precedence during `trace` and `graph`: resolved call edges keep their `graph_edges.id`, `outbound_calls.id`, call-site file/line, outbound parser evidence, linker status/reason, and selected target evidence. Contextual runtime resolution can enrich evidence but does not replace an already resolved persisted target. Terminal start diagnostics such as ambiguous operations or rejected implementations return zero nodes and zero edges by default; candidates remain in structured diagnostics for automation.
73
79
  - OData entity paths are conservative terminal remote entity edges. Reads, mutations, deletes, navigation paths, media-stream paths such as `/Documents(ID)/content`, and uppercase unknown entity-set candidates do not inflate unresolved operation counts. Lowercase action/function-style paths remain eligible for indexed operation resolution.
74
80
  - External HTTP destinations are static only when a safe literal or local const literal proves the value. Identifier, property-read, function-call, and arbitrary destination expressions are dynamic with stable `destination:dynamic:<hash>` ids and neutral labels; conditional literal branches expose only safe candidate names.
75
- - Schema version 7 uses an explicit reindex-required upgrade policy for legacy schema drift. `doctor --strict` reports `schema_legacy_columns_present`, `external_target_columns_missing_data`, and `reindex_required_after_upgrade` with remediation when relink alone cannot make an upgraded database equivalent to a fresh index.
81
+ - Schema version 11 preserves the earlier reindex-required policy for legacy graph evidence and adds nullable writer-owner metadata without dropping prior run history. `doctor --strict` reports schema and analyzer drift when relink alone cannot make an upgraded database equivalent to a fresh index.
76
82
 
77
83
 
78
84
  ## πŸš€ Quick Start
@@ -191,7 +197,7 @@ service-flow trace --workspace /path/to/workspace --service /FacadeService --pat
191
197
  | `--implementation-hint <scope>` | Select one implementation for a matching hop; repeatable fields are `service`, `operation`, `package`, `repository`, `family`, and required `repo` |
192
198
  | `--var <key=value>` | Apply runtime values to dynamic destinations/service paths; repeatable |
193
199
  | `--dynamic-mode <mode>` | `strict`, `candidates`, or `infer`; defaults to `strict` |
194
- | `--max-dynamic-candidates <n>` | Cap dynamic candidate suggestions and exploratory branches; defaults to `5` |
200
+ | `--max-dynamic-candidates <n>` | Cap viable/rejected suggestions, exploratory branches, variable sets, and nested candidate evidence; defaults to `5` |
195
201
 
196
202
  ### πŸ—ΊοΈ `service-flow graph`
197
203
 
@@ -214,7 +220,7 @@ service-flow graph --workspace /path/to/workspace --repo facade-service --operat
214
220
  | `--implementation-hint <scope>` | Apply a repeatable scoped implementation selection |
215
221
  | `--var <key=value>` | Apply repeatable runtime substitutions |
216
222
  | `--dynamic-mode <mode>` | `strict`, `candidates`, or `infer`; defaults to `strict` |
217
- | `--max-dynamic-candidates <n>` | Cap dynamic candidate suggestions and exploratory branches; defaults to `5` |
223
+ | `--max-dynamic-candidates <n>` | Cap viable/rejected suggestions, exploratory branches, variable sets, and nested candidate evidence; defaults to `5` |
218
224
 
219
225
  ### πŸ“š `service-flow list ...`
220
226
 
@@ -295,11 +301,11 @@ service-flow doctor --workspace /path/to/workspace --strict --format json
295
301
  service-flow doctor --workspace /path/to/workspace --strict --format table
296
302
  ```
297
303
 
298
- `--format json` always returns a JSON array, including `[]` for clean workspaces. `--format table` prints a concise human-readable table with capped copyable hint lines; use JSON when automation needs every field or every hint alternative. Omit `--format` when relying on the pre-0.1.48 compatible output contract.
304
+ `--format json` always returns a JSON array, including `[]` for clean workspaces. `--format table` prints a concise human-readable table with capped copyable hint lines; use JSON when automation needs structured fields, then use a scoped selector or implementation hint for a precise follow-up. Omit `--format` when relying on the pre-0.1.48 compatible output contract.
299
305
 
300
- Strict output keeps stable category, count, severity, and capped example fields. Use `--detail` to include full `expandedExamples` for implementation candidate, parameter metadata, and dynamic wrapper categories.
306
+ Strict output keeps stable category, count, severity, and capped example fields. `--detail` adds useful fields but keeps candidate-like and example arrays capped; use the provided scoped selectors or implementation hints for a precise follow-up.
301
307
 
302
- Strict binding diagnostics group remote sends into `direct_binding_missing`, `contextual_binding_recoverable`, `ambiguous_binding_candidates`, `unrecoverable_binding`, and `missing_symbol_parameter_metadata`. Candidate chains remain in JSON evidence, while table output stays capped and copyable.
308
+ Strict binding diagnostics group remote sends into `direct_binding_missing`, `contextual_binding_recoverable`, `ambiguous_binding_candidates`, `unrecoverable_binding`, and `missing_symbol_parameter_metadata`. Candidate chains remain as bounded JSON projections with count metadata, while table output stays capped and copyable.
303
309
 
304
310
  ### 🧹 `service-flow clean`
305
311
 
@@ -355,9 +361,9 @@ When a concrete target exists after variable substitution, the trace shows both
355
361
 
356
362
  When runtime values are missing, strict trace output includes the missing variable names plus bounded candidate guidance when indexed operations and routing metadata can derive values. JSON includes `dynamicTargetExploration`, `dynamicTargetCandidates`, `dynamicTargetCandidateSuggestions`, `suggestedVarSets`, and `dynamicTargetInference`; table output shows compact candidate counts and copyable `--var` examples. Use `--dynamic-mode candidates` to render capped exploratory branches, or `--dynamic-mode infer` to continue only through a unique fully-derived candidate.
357
363
 
358
- Direct sends and same-file or imported wrappers share one path-candidate analysis. Literals and immutable aliases resolve; conditional or branch-assigned static alternatives remain ambiguous with all raw and normalized candidates; dynamic reassignments remain dynamic with the exact runtime identifier. Wrapper definition sends are treated as templates when a concrete caller-site edge can be indexed.
364
+ Direct sends and same-file or imported wrappers share one path-candidate analysis. Literals and immutable aliases resolve; conditional or branch-assigned static alternatives remain ambiguous with bounded raw and normalized candidate projections plus counts; dynamic reassignments remain dynamic with the exact runtime identifier. Wrapper definition sends are treated as templates when a concrete caller-site edge can be indexed.
359
365
 
360
- Service binding evidence distinguishes a directly persisted binding from caller-to-callee contextual recovery. Persisted binding selection never uses a declaration after the call and does not choose among different mutable client assignments. Contextual trace evidence carries caller and callee sites, argument/property and parameter/local names, original binding location, routing expressions, candidate ties, and selection status.
366
+ Service binding evidence distinguishes a directly persisted binding from caller-to-callee contextual recovery. A call with a selected binding uses that exact binding as its routing context, including helper-return provenance, rather than combining unrelated client definitions from the repository. When no binding is selected, fallback references remain marked as fallback; multiple distinct fallback bindings are not combined into one inferred route. Persisted binding selection never uses a declaration after the call and does not choose among different mutable client assignments. Contextual trace evidence carries caller and callee sites, argument/property and parameter/local names, original binding location, routing expressions, candidate ties, and selection status.
361
367
 
362
368
  OData evidence preserves the raw path, query-free path, normalized invocation path, invocation arguments, placeholder keys, classifier reason, indexed operation candidate count, and entity-versus-operation precedence decision. Entity keys, navigation paths, media/property paths, and query reads remain entity access unless indexed operation evidence and strong service context prove an operation.
363
369
 
@@ -492,10 +498,6 @@ The e2e tests use fixture CAP workspaces and fake-backed flows. They do not need
492
498
 
493
499
  ---
494
500
 
495
- ## πŸ‘¨β€πŸ’» Author
496
-
497
- **dongtran** ✨
498
-
499
501
  ## πŸ“„ License
500
502
 
501
503
  MIT
package/TECHNICAL-NOTE.md CHANGED
@@ -1,18 +1,30 @@
1
1
  # Service Flow Resolution Notes
2
2
 
3
- ## 0.1.51 dynamic target exploration notes
3
+ ## 0.1.53 call-scoped dynamic routing and bounded evidence notes
4
+
5
+ - Runtime routing starts from the outbound call's selected binding when one exists. Its service path, alias, destination, source location, and helper-return chain form one call-scoped context; fallback repository references are marked as fallback and cannot override a selected binding. Multiple distinct fallback bindings are never combined into one derived route.
6
+ - Template matching substitutes only explicit `--var` values, then matches the original template exactly against a concrete service target. A concrete mismatch rejects the candidate. Alias and destination evidence is evaluated only from that same validated binding or an alias-matched package require in the caller repository.
7
+ - Explicit values remain authoritative only when compatible. A deterministic value derived from a selected binding signal or concrete route-owner identity conflicts with an incompatible supplied value, rejects that candidate, and reports `no_candidate_after_runtime_substitution` instead of permitting generic service-path resolution.
8
+ - Identity derivation is tied to the repository that owns the concrete service path. Inherited operations may use a resolved helper implementation as implementation evidence, but neither helper nor base-model identity is a fallback source. Provenance retains the route owner, effective/base operation relationship, implementation status, normalized identity, and rule.
9
+ - Persisted graph and strict-doctor evidence project every candidate-like collection through the fixed cap with total, shown, and omitted metadata. Dynamic and implementation decisions query canonical SQLite facts before ranking or applying hints, so a capped JSON prefix is never treated as the complete search space. Detail output remains bounded.
10
+
11
+ ## 0.1.52 dynamic target, lifecycle, and indexing notes
4
12
 
5
13
  - Persisted graph storage remains conservative. Runtime-dependent remote targets still link as dynamic or unresolved graph edges unless static evidence is strong enough.
6
- - Trace and graph now accept `--dynamic-mode strict|candidates|infer`. Strict is the default and does not traverse missing-runtime-variable candidates. Candidates mode renders capped exploratory candidate branches that are explicitly unselected. Infer mode resolves only when all required placeholders are derived from deterministic indexed evidence and the selected candidate is unique above threshold.
7
- - Dynamic candidate evidence is derived from indexed operation paths, service-path templates, alias/destination templates, `cds.requires`, service-binding facts, and implementation-edge availability. Candidate `reasons` are arrays, and rejected candidates explain mismatches, missing runtime variables, or tied scores.
8
- - Missing-variable diagnostics retain the copyable `--var key=<value>` placeholders and add bounded candidate suggestions, suggested var sets, candidate counts, and omitted counts for human and CI consumers.
14
+ - Trace and graph accept `--dynamic-mode strict|candidates|infer`. Strict is the default and never traverses a target that still needs runtime values. Candidates mode emits only viable, explicitly unselected exploratory branches. Infer mode resolves only when the top viable candidate has every required value, scores at least `0.85`, exceeds the runner-up by more than `0.05`, and has no conflicting strong derivation.
15
+ - Explicit variables are substituted first and remain authoritative. Concrete service, operation, alias, or destination contradictions reject a candidate before viable counts or branch creation. A conflicting derived value is retained as conflict evidence and cannot replace the explicit value.
16
+ - Identity normalization removes an npm scope, splits camel case, lowercases, folds separator runs to `_`, and trims edge separators. Fallback then requires an exact whole-name template match with literal text on both sides of one placeholder, the concrete service route owner, a resolved implementation for the effective operation, and workspace-wide unique repository/package identity and derived value. Provenance records the matched source name, normalized form, and rule; substring, duplicate-name, discovery-order, and same-operation-name guesses remain ineligible.
17
+ - `--max-dynamic-candidates` bounds viable and rejected candidates, branches, suggestions, variable sets, nested provenance/conflict lists, and duplicate persisted candidate projections. `omittedCandidateCount` is always relative to viable candidates; rejected shown/omitted counts are separate.
18
+ - Supported zero-argument `OnCreate/Read/Update/Delete`, `Before*`, and `After*` method decorators require runtime imports and retain their original expression, canonical import evidence, lifecycle phase/event, and source location. Type-only imports, nonzero arguments, unsupported shapes, and body-less methods stay non-executable. Lifecycle and event rows are not CDS operation implementations without real operation facts; supported methods in a mixed class remain traceable with structured warnings.
19
+ - Schema version 11 adds nullable index-writer owner metadata. A short `BEGIN IMMEDIATE` claim serializes writers for one database, dead owners are recoverable, active owners fail with `index_writer_active`, and read-only commands remain available outside the short claim/publication transactions.
20
+ - Repository preparation stays sequential. Each discovered source and package metadata file is read once into a repository-scoped immutable snapshot; TypeScript parsers share one lazy AST per file. Publication remains one atomic transaction, and discovery/read/parse failures retain the last-good facts and fingerprint.
9
21
 
10
22
  ## 0.1.33 trace, entity, destination, and upgrade notes
11
23
 
12
24
  - Trace and graph rendering use persisted resolved graph rows as authoritative base edges. Runtime/contextual resolution may add evidence such as substitutions or binding propagation, but persisted graph edge ids, outbound call ids, call-site file/line, parser evidence, linker status, selected target id, and target evidence remain present in effective edges.
13
25
  - The trace-start machine contract is fail-closed: terminal start diagnostics produce zero graph nodes and zero graph edges by default. Candidate operations, implementation candidates, rejected edges, and selected ids are diagnostics-only evidence.
14
26
  - Service-client OData entity paths are separated from action/function invocations. Entity reads, mutations, deletes, navigation, media stream calls, and uppercase entity-set candidates become terminal remote entity graph edges; lowercase operation-looking paths still go through operation resolution when indexed evidence exists.
15
- - External HTTP destination extraction uses conservative static evaluation. Literals and safe local const literals are static; all other expressions stay dynamic unless a conditional has all-static branches, in which case only the candidate literals and sanitized expression shape are persisted.
27
+ - External HTTP destination extraction uses conservative static evaluation. Literals and safe local const literals are static; all other expressions stay dynamic unless a conditional has all-static branches, in which case a bounded safe candidate-literal projection, counts, and a sanitized expression shape are persisted.
16
28
  - Schema version 7 follows an explicit reindex-required upgrade policy. Legacy external-target columns on `symbols` or missing queryable external metadata are strict doctor warnings with rebuild/reindex remediation instead of silent relink-only drift.
17
29
 
18
30
  ## 0.1.31 selector and external target notes
@@ -134,7 +146,7 @@ Schema version 6 adds queryable external target metadata columns to `outbound_ca
134
146
 
135
147
  - Runtime resolution now has an explicit eligibility gate: only remote dynamic/ambiguous/unresolved graph edges with affected placeholders are re-resolved in memory. Terminal and resolved static edges are copied through unchanged, and substitutions keep original expressions, effective values, supplied variables, and missing variables separate.
136
148
  - Operation candidate scores are clamped into `[0, 1]` before graph or trace rendering.
137
- - Helper package linking uses exact `repositories.package_name` matches before normalized directory-name fallback. Ambiguous package names are represented as ambiguous graph edges with all candidates in evidence.
149
+ - Helper package linking uses exact `repositories.package_name` matches before normalized directory-name fallback. Ambiguous package names are represented as ambiguous graph edges with bounded candidate projections and count metadata.
138
150
  - Fingerprints hash normalized package facts and package bytes in addition to source file paths/content and analyzer version.
139
151
  - The CLI version imports package metadata, so package metadata, `service-flow --version`, changelog, and analyzer/fingerprint version share one release source.
140
152
  - Supported runtime is Node.js 24+ with `node:sqlite` validation; older runtimes should fail with a compatibility message instead of a late `DatabaseSync` error.