@saptools/service-flow 0.1.68 → 0.1.70
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.
- package/CHANGELOG.md +14 -0
- package/README.md +11 -5
- package/TECHNICAL-NOTE.md +13 -0
- package/dist/{chunk-AEM4JY22.js → chunk-GSLFY6J2.js} +6986 -5503
- package/dist/chunk-GSLFY6J2.js.map +1 -0
- package/dist/cli.js +334 -122
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/cli/{002-doctor-lifecycle.ts → doctor-lifecycle.ts} +1 -1
- package/src/cli/{001-doctor-projection.ts → doctor-projection.ts} +1 -1
- package/src/cli/doctor.ts +5 -5
- package/src/cli/index-summary.ts +22 -0
- package/src/cli.ts +155 -91
- package/src/db/{009-binding-fact-semantics.ts → binding-fact-semantics.ts} +6 -1
- package/src/db/binding-helper-provenance.ts +17 -0
- package/src/db/{012-binding-reference-proof.ts → binding-reference-proof.ts} +4 -0
- package/src/db/{000-call-fact-repository.ts → call-fact-repository.ts} +49 -23
- package/src/db/{003-current-fact-semantics.ts → current-fact-semantics.ts} +5 -4
- package/src/db/{001-fact-lifecycle.ts → fact-lifecycle.ts} +3 -3
- package/src/db/index-publication-failure.ts +91 -0
- package/src/db/{007-package-fact-semantics.ts → package-fact-semantics.ts} +6 -6
- package/src/db/{010-package-symbol-surface-semantics.ts → package-symbol-surface-semantics.ts} +2 -2
- package/src/db/{004-package-target-invalidation.ts → package-target-invalidation.ts} +11 -1
- package/src/db/{008-relative-fact-semantics.ts → relative-fact-semantics.ts} +9 -6
- package/src/db/{006-relative-symbol-resolution.ts → relative-symbol-resolution.ts} +28 -7
- package/src/db/repositories.ts +24 -7
- package/src/db/{011-symbol-call-semantics.ts → symbol-call-semantics.ts} +1 -1
- package/src/index.ts +3 -3
- package/src/indexer/cds-extension-resolver.ts +27 -3
- package/src/indexer/repository-indexer.ts +70 -9
- package/src/indexer/workspace-indexer.ts +142 -30
- package/src/linker/call-edge-insertion.ts +568 -0
- package/src/linker/{002-call-evidence.ts → call-evidence.ts} +2 -2
- package/src/linker/cross-repo-linker.ts +6 -169
- package/src/linker/dynamic-edge-resolver.ts +1 -1
- package/src/linker/{004-event-subscription-handler-linker.ts → event-subscription-handler-linker.ts} +32 -11
- package/src/linker/event-template-link.ts +72 -0
- package/src/linker/external-http-target.ts +1 -1
- package/src/linker/helper-package-linker.ts +1 -1
- package/src/linker/{000-implementation-candidates.ts → implementation-candidates.ts} +1 -1
- package/src/linker/{001-implementation-evidence-projection.ts → implementation-evidence-projection.ts} +1 -1
- package/src/linker/odata-path-normalizer.ts +1 -1
- package/src/linker/{005-odata-path-structure.ts → odata-path-structure.ts} +1 -1
- package/src/linker/{003-package-import-symbol-resolver.ts → package-import-symbol-resolver.ts} +3 -3
- package/src/linker/service-resolver.ts +2 -2
- package/src/output/{001-compact-json-output.ts → compact-json-output.ts} +1 -1
- package/src/parsers/{006-binding-identity.ts → binding-identity.ts} +9 -4
- package/src/parsers/{011-binding-lexical-scope.ts → binding-lexical-scope.ts} +1 -1
- package/src/parsers/{021-binding-visibility.ts → binding-visibility.ts} +18 -2
- package/src/parsers/{000-direct-query-execution.ts → direct-query-execution.ts} +11 -0
- package/src/parsers/{005-event-subscription-facts.ts → event-subscription-facts.ts} +2 -2
- package/src/parsers/{016-local-symbol-reference.ts → local-symbol-reference.ts} +2 -2
- package/src/parsers/operation-path-analysis.ts +1 -1
- package/src/parsers/outbound-call-classifier.ts +692 -0
- package/src/parsers/outbound-call-parser.ts +146 -509
- package/src/parsers/outbound-expression-analysis.ts +700 -0
- package/src/parsers/{018-package-commonjs-syntax.ts → package-commonjs-syntax.ts} +1 -1
- package/src/parsers/{012-package-fact-contract.ts → package-fact-contract.ts} +3 -3
- package/src/parsers/{010-package-public-surface-analysis.ts → package-public-surface-analysis.ts} +2 -2
- package/src/parsers/{003-package-public-surface.ts → package-public-surface.ts} +3 -3
- package/src/parsers/{008-package-surface-publication.ts → package-surface-publication.ts} +1 -1
- package/src/parsers/{001-query-entity-resolution.ts → query-entity-resolution.ts} +1 -1
- package/src/parsers/{015-service-binding-collector.ts → service-binding-collector.ts} +3 -3
- package/src/parsers/{014-service-binding-helper-flow.ts → service-binding-helper-flow.ts} +72 -6
- package/src/parsers/service-binding-parser-helpers.ts +1 -1
- package/src/parsers/service-binding-parser.ts +2 -2
- package/src/parsers/{007-source-fact-reconciliation.ts → source-fact-reconciliation.ts} +3 -3
- package/src/parsers/{020-stable-local-value.ts → stable-local-value.ts} +2 -2
- package/src/parsers/{009-symbol-call-facts.ts → symbol-call-facts.ts} +3 -3
- package/src/parsers/{017-symbol-derived-contexts.ts → symbol-derived-contexts.ts} +2 -2
- package/src/parsers/symbol-parser.ts +43 -11
- package/src/trace/{014-compact-contract.ts → compact-contract.ts} +6 -0
- package/src/trace/{021-compact-decision-normalization.ts → compact-decision-normalization.ts} +77 -11
- package/src/trace/{020-compact-field-projection.ts → compact-field-projection.ts} +77 -4
- package/src/trace/{024-compact-observation-decision.ts → compact-observation-decision.ts} +10 -5
- package/src/trace/{016-compact-projector.ts → compact-projector.ts} +6 -7
- package/src/trace/{018-compact-trace.ts → compact-trace.ts} +3 -3
- package/src/trace/{006-contextual-projection.ts → contextual-projection.ts} +1 -1
- package/src/trace/{008-contextual-runtime-state.ts → contextual-runtime-state.ts} +1 -1
- package/src/trace/{001-dynamic-identity.ts → dynamic-identity.ts} +2 -2
- package/src/trace/{003-dynamic-references.ts → dynamic-references.ts} +2 -2
- package/src/trace/dynamic-targets.ts +6 -6
- package/src/trace/event-runtime-resolution.ts +151 -0
- package/src/trace/{011-event-subscriber-traversal.ts → event-subscriber-traversal.ts} +101 -9
- package/src/trace/evidence.ts +2 -2
- package/src/trace/implementation-hints.ts +10 -7
- package/src/trace/{005-implementation-selection.ts → implementation-selection.ts} +2 -2
- package/src/trace/{007-implementation-start-diagnostic.ts → implementation-start-diagnostic.ts} +1 -0
- package/src/trace/local-call-expansion.ts +37 -0
- package/src/trace/{009-selected-handler-provenance.ts → selected-handler-provenance.ts} +1 -1
- package/src/trace/selectors.ts +2 -1
- package/src/trace/{017-trace-context.ts → trace-context.ts} +2 -2
- package/src/trace/{015-trace-edge-recorder.ts → trace-edge-recorder.ts} +62 -5
- package/src/trace/{019-trace-edge-semantics.ts → trace-edge-semantics.ts} +9 -13
- package/src/trace/trace-engine.ts +10 -10
- package/src/trace/{022-trace-fact-preflight.ts → trace-fact-preflight.ts} +2 -2
- package/src/trace/{025-trace-implementation-scope.ts → trace-implementation-scope.ts} +1 -1
- package/src/trace/{028-trace-operation-execution.ts → trace-operation-execution.ts} +10 -10
- package/src/trace/{013-trace-root-scopes.ts → trace-root-scopes.ts} +5 -6
- package/src/trace/{027-trace-scope-execution.ts → trace-scope-execution.ts} +44 -44
- package/src/trace/{029-trace-start-implementation.ts → trace-start-implementation.ts} +7 -7
- package/src/trace/{026-trace-start-scope.ts → trace-start-scope.ts} +6 -5
- package/src/trace/{010-traversal-scope.ts → traversal-scope.ts} +1 -1
- package/src/types.ts +2 -1
- package/src/version.ts +1 -1
- package/dist/chunk-AEM4JY22.js.map +0 -1
- /package/src/cli/{000-clean.ts → clean.ts} +0 -0
- /package/src/cli/{003-doctor-package-resolution.ts → doctor-package-resolution.ts} +0 -0
- /package/src/db/{002-fact-json-inventory.ts → fact-json-inventory.ts} +0 -0
- /package/src/db/{005-schema-structure.ts → schema-structure.ts} +0 -0
- /package/src/output/{000-stdout-policy.ts → stdout-policy.ts} +0 -0
- /package/src/parsers/{019-binding-assignment-targets.ts → binding-assignment-targets.ts} +0 -0
- /package/src/parsers/{013-executable-body-eligibility.ts → executable-body-eligibility.ts} +0 -0
- /package/src/parsers/{004-fact-identity.ts → fact-identity.ts} +0 -0
- /package/src/parsers/{002-symbol-import-bindings.ts → symbol-import-bindings.ts} +0 -0
- /package/src/trace/{004-dynamic-candidate-sources.ts → dynamic-candidate-sources.ts} +0 -0
- /package/src/trace/{000-dynamic-target-types.ts → dynamic-target-types.ts} +0 -0
- /package/src/trace/{023-nested-event-scopes.ts → nested-event-scopes.ts} +0 -0
- /package/src/trace/{002-trace-diagnostics.ts → trace-diagnostics.ts} +0 -0
- /package/src/trace/{012-trace-graph-lookups.ts → trace-graph-lookups.ts} +0 -0
- /package/src/utils/{000-bounded-projection.ts → bounded-projection.ts} +0 -0
- /package/src/utils/{001-placeholders.ts → placeholders.ts} +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ImplementationHint } from '../types.js';
|
|
2
|
-
import { projectBounded } from '../utils/
|
|
2
|
+
import { projectBounded } from '../utils/bounded-projection.js';
|
|
3
|
+
import { compareBinary } from './traversal-scope.js';
|
|
3
4
|
|
|
4
5
|
interface Candidate {
|
|
5
6
|
accepted?: boolean;
|
|
@@ -106,6 +107,7 @@ export function implementationHintSuggestions(rawEvidence: Record<string, unknow
|
|
|
106
107
|
|
|
107
108
|
export function implementationHintSuggestionProjection(
|
|
108
109
|
rawEvidence: Record<string, unknown>,
|
|
110
|
+
limit?: number,
|
|
109
111
|
): ImplementationHintSuggestionProjection {
|
|
110
112
|
const evidence = asEvidence(rawEvidence);
|
|
111
113
|
const accepted = (evidence.candidates ?? []).filter((candidate) => candidate.accepted);
|
|
@@ -119,7 +121,7 @@ export function implementationHintSuggestionProjection(
|
|
|
119
121
|
}
|
|
120
122
|
const repos = selectableRepositories(accepted);
|
|
121
123
|
const repositoryProjection = projectBounded(
|
|
122
|
-
repos,
|
|
124
|
+
repos, compareBinary, limit,
|
|
123
125
|
);
|
|
124
126
|
const suggestions = accepted
|
|
125
127
|
.flatMap((candidate) => {
|
|
@@ -142,7 +144,7 @@ export function implementationHintSuggestionProjection(
|
|
|
142
144
|
cli: `--implementation-hint ${hintString(hint)}`,
|
|
143
145
|
}];
|
|
144
146
|
});
|
|
145
|
-
const projection = projectBounded(suggestions, compareSuggestion);
|
|
147
|
+
const projection = projectBounded(suggestions, compareSuggestion, limit);
|
|
146
148
|
return {
|
|
147
149
|
suggestions: projection.items,
|
|
148
150
|
suggestionCount: projection.totalCount,
|
|
@@ -170,15 +172,16 @@ function projectedSuggestions(value: unknown): ImplementationHintSuggestionProje
|
|
|
170
172
|
}
|
|
171
173
|
|
|
172
174
|
function compareHints(left: ImplementationHint, right: ImplementationHint): number {
|
|
173
|
-
return hintString(left)
|
|
175
|
+
return compareBinary(hintString(left), hintString(right));
|
|
174
176
|
}
|
|
175
177
|
|
|
176
178
|
function compareSuggestion(
|
|
177
179
|
left: Record<string, unknown>,
|
|
178
180
|
right: Record<string, unknown>,
|
|
179
181
|
): number {
|
|
180
|
-
return String(left.cli ?? '')
|
|
181
|
-
||
|
|
182
|
+
return compareBinary(String(left.cli ?? ''), String(right.cli ?? ''))
|
|
183
|
+
|| compareBinary(
|
|
184
|
+
String(left.implementationRepo ?? ''),
|
|
182
185
|
String(right.implementationRepo ?? ''),
|
|
183
186
|
);
|
|
184
187
|
}
|
|
@@ -202,7 +205,7 @@ function selectableRepositories(candidates: Candidate[]): string[] {
|
|
|
202
205
|
const repos = new Set(candidates.flatMap((candidate) => candidate.handlerPackage?.name ? [candidate.handlerPackage.name] : []));
|
|
203
206
|
return [...repos]
|
|
204
207
|
.filter((repo) => candidates.filter((candidate) => candidateMatchesRepo(candidate, repo)).length === 1)
|
|
205
|
-
.sort();
|
|
208
|
+
.sort(compareBinary);
|
|
206
209
|
}
|
|
207
210
|
|
|
208
211
|
function assignHintField(hint: Partial<ImplementationHint>, key: string, value: string): void {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Db } from '../db/connection.js';
|
|
2
|
-
import { canonicalImplementationEvidence } from '../linker/
|
|
2
|
+
import { canonicalImplementationEvidence } from '../linker/implementation-candidates.js';
|
|
3
3
|
import type { ImplementationHint } from '../types.js';
|
|
4
|
-
import { projectBounded } from '../utils/
|
|
4
|
+
import { projectBounded } from '../utils/bounded-projection.js';
|
|
5
5
|
import {
|
|
6
6
|
selectImplementation,
|
|
7
7
|
type ImplementationSelection,
|
package/src/trace/{007-implementation-start-diagnostic.ts → implementation-start-diagnostic.ts}
RENAMED
|
@@ -15,6 +15,7 @@ export function implementationStartDiagnostic(
|
|
|
15
15
|
message: `Indexed operation matched but implementation edge is ${String(
|
|
16
16
|
edge.status ?? 'unresolved',
|
|
17
17
|
)}`,
|
|
18
|
+
selectorKind: 'operation',
|
|
18
19
|
resolutionStage: 'implementation',
|
|
19
20
|
resolutionStatus: edge.status === 'ambiguous'
|
|
20
21
|
? 'ambiguous_implementation'
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Db } from '../db/connection.js';
|
|
2
|
+
import {
|
|
3
|
+
type ContextBinding,
|
|
4
|
+
} from './contextual-runtime-state.js';
|
|
5
|
+
import {
|
|
6
|
+
type TraversalScheduleDecision,
|
|
7
|
+
type TraversalScopeScheduler,
|
|
8
|
+
type TraversalScopeState,
|
|
9
|
+
} from './traversal-scope.js';
|
|
10
|
+
import { contextForSymbolCall } from './trace-context.js';
|
|
11
|
+
|
|
12
|
+
export interface LocalCallExpansion {
|
|
13
|
+
repoId: number;
|
|
14
|
+
files: Set<string>;
|
|
15
|
+
symbols: Set<number>;
|
|
16
|
+
context: Map<string, ContextBinding>;
|
|
17
|
+
scheduling: TraversalScheduleDecision;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function planLocalCallExpansion(
|
|
21
|
+
db: Db,
|
|
22
|
+
scheduler: TraversalScopeScheduler,
|
|
23
|
+
workspaceId: number | undefined,
|
|
24
|
+
parent: TraversalScopeState,
|
|
25
|
+
row: Record<string, unknown>,
|
|
26
|
+
bindings: Map<string, ContextBinding>,
|
|
27
|
+
symbolId: number,
|
|
28
|
+
): LocalCallExpansion {
|
|
29
|
+
const symbols = new Set([symbolId]);
|
|
30
|
+
const files = new Set([String(row.calleeFile)]);
|
|
31
|
+
const repoId = Number(row.calleeRepoId);
|
|
32
|
+
const context = contextForSymbolCall(db, row, bindings);
|
|
33
|
+
const scheduling = scheduler.schedule({
|
|
34
|
+
workspaceId, repoId, files, symbolIds: symbols, context,
|
|
35
|
+
}, parent);
|
|
36
|
+
return { repoId, files, symbols, context, scheduling };
|
|
37
|
+
}
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
selectedHandlerProvenance,
|
|
4
4
|
type SelectedHandlerProvenance,
|
|
5
5
|
type SelectedHandlerSource,
|
|
6
|
-
} from '../linker/
|
|
6
|
+
} from '../linker/implementation-evidence-projection.js';
|
|
7
7
|
|
|
8
8
|
export interface HandlerMethodNode extends Record<string, unknown> {
|
|
9
9
|
id: string;
|
package/src/trace/selectors.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { TraceStart } from '../types.js';
|
|
|
3
3
|
import {
|
|
4
4
|
projectBounded,
|
|
5
5
|
type BoundedProjection,
|
|
6
|
-
} from '../utils/
|
|
6
|
+
} from '../utils/bounded-projection.js';
|
|
7
7
|
|
|
8
8
|
export interface SelectorSourceScope {
|
|
9
9
|
files?: Set<string>;
|
|
@@ -550,6 +550,7 @@ export function ambiguousStartDiagnostic(
|
|
|
550
550
|
severity: 'warning',
|
|
551
551
|
code: 'trace_start_ambiguous',
|
|
552
552
|
message,
|
|
553
|
+
selectorKind: 'operation',
|
|
553
554
|
normalizedSelectorValue: requested,
|
|
554
555
|
resolutionStage: 'operation',
|
|
555
556
|
resolutionStatus: 'ambiguous_operation',
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Db } from '../db/connection.js';
|
|
2
2
|
import { extractPlaceholders } from '../linker/dynamic-edge-resolver.js';
|
|
3
|
-
import { boundCandidateLikeEvidence } from '../utils/
|
|
4
|
-
import type { ContextBinding } from './
|
|
3
|
+
import { boundCandidateLikeEvidence } from '../utils/bounded-projection.js';
|
|
4
|
+
import type { ContextBinding } from './contextual-runtime-state.js';
|
|
5
5
|
|
|
6
6
|
export interface TraceContextCall extends Record<string, unknown> {
|
|
7
7
|
service_binding_id?: number;
|
|
@@ -7,7 +7,13 @@ import type {
|
|
|
7
7
|
CompactSourceSite,
|
|
8
8
|
CompactStatus,
|
|
9
9
|
CompactTraceObserver,
|
|
10
|
-
} from './
|
|
10
|
+
} from './compact-contract.js';
|
|
11
|
+
import { implementationHintSuggestionProjection } from
|
|
12
|
+
'./implementation-hints.js';
|
|
13
|
+
import {
|
|
14
|
+
isSafeCompactReferenceName,
|
|
15
|
+
projectCompactReferenceGroup,
|
|
16
|
+
} from './compact-decision-normalization.js';
|
|
11
17
|
|
|
12
18
|
export interface TraceEdgeSemantics {
|
|
13
19
|
source: CompactSemanticEndpoint;
|
|
@@ -111,8 +117,7 @@ export function semanticGraphTarget(
|
|
|
111
117
|
): CompactSemanticEndpoint {
|
|
112
118
|
if (row.to_kind === 'event') return {
|
|
113
119
|
kind: 'event', workspaceId,
|
|
114
|
-
eventName:
|
|
115
|
-
? call.event_name_expr : row.to_id,
|
|
120
|
+
eventName: row.to_id,
|
|
116
121
|
};
|
|
117
122
|
const id = positiveNumber(row.to_id);
|
|
118
123
|
if (row.to_kind === 'operation')
|
|
@@ -198,7 +203,7 @@ export function compactDecisionFromEvidence(
|
|
|
198
203
|
const authoritativeMissingCount = finiteNumber(
|
|
199
204
|
dynamic.missingVariableCount ?? evidence.missingVariableCount,
|
|
200
205
|
);
|
|
201
|
-
|
|
206
|
+
const decision: CompactDecisionInput = {
|
|
202
207
|
effectiveResolutionStatus: stringValue(effective.status),
|
|
203
208
|
effectiveTarget: targetSummary(effective),
|
|
204
209
|
persistedResolutionStatus: stringValue(persisted.status),
|
|
@@ -221,7 +226,7 @@ export function compactDecisionFromEvidence(
|
|
|
221
226
|
implementationGuided: booleanValue(implementation.guided),
|
|
222
227
|
implementationContextual: booleanValue(
|
|
223
228
|
evidence.contextualImplementationSelected),
|
|
224
|
-
reasonCode:
|
|
229
|
+
reasonCode: compactEvidenceReasonCode(evidence),
|
|
225
230
|
eventMatchStrategy: stringValue(evidence.matchStrategy),
|
|
226
231
|
dispatchCertainty: stringValue(evidence.dispatchCertainty),
|
|
227
232
|
associationStatus: stringValue(evidence.associationStatus),
|
|
@@ -233,6 +238,7 @@ export function compactDecisionFromEvidence(
|
|
|
233
238
|
bodyExpansion: stringValue(evidence.bodyExpansion),
|
|
234
239
|
...overrides,
|
|
235
240
|
};
|
|
241
|
+
return decisionWithTiedCandidates(evidence, decision);
|
|
236
242
|
}
|
|
237
243
|
|
|
238
244
|
export function compactRefs(
|
|
@@ -334,3 +340,54 @@ function firstNumber(...values: unknown[]): number | undefined {
|
|
|
334
340
|
}
|
|
335
341
|
return undefined;
|
|
336
342
|
}
|
|
343
|
+
|
|
344
|
+
export function compactEvidenceReasonCode(
|
|
345
|
+
evidence: Record<string, unknown>,
|
|
346
|
+
): string | undefined {
|
|
347
|
+
return stringValue(evidence.reasonCode ?? evidence.cycleReason)
|
|
348
|
+
?? parserWarningReason(evidence.parserWarning);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
function parserWarningReason(value: unknown): string | undefined {
|
|
352
|
+
const warning = recordValue(value);
|
|
353
|
+
const code = stringValue(warning.code);
|
|
354
|
+
if (code && code !== 'parser_warning') return code;
|
|
355
|
+
return stringValue(warning.message);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
function tiedCandidateRepositoryGroup(
|
|
359
|
+
evidence: Record<string, unknown>,
|
|
360
|
+
decision: CompactDecisionInput,
|
|
361
|
+
): CompactDecisionInput['tiedCandidateRepos'] {
|
|
362
|
+
if (decision.effectiveResolutionStatus !== 'ambiguous'
|
|
363
|
+
|| (decision.candidateCount ?? 0) <= 1) return undefined;
|
|
364
|
+
const persisted = Array.isArray(evidence.implementationHintSuggestions)
|
|
365
|
+
? evidence.implementationHintSuggestions.filter(
|
|
366
|
+
(value): value is Record<string, unknown> =>
|
|
367
|
+
Boolean(value && typeof value === 'object' && !Array.isArray(value)),
|
|
368
|
+
)
|
|
369
|
+
: [];
|
|
370
|
+
const projection = persisted.length > 0 ? {
|
|
371
|
+
suggestions: persisted,
|
|
372
|
+
suggestionCount: finiteNumber(
|
|
373
|
+
evidence.implementationHintSuggestionCount,
|
|
374
|
+
) ?? persisted.length,
|
|
375
|
+
} : implementationHintSuggestionProjection(
|
|
376
|
+
evidence, Number.MAX_SAFE_INTEGER,
|
|
377
|
+
);
|
|
378
|
+
const repos = projection.suggestions.flatMap((suggestion) =>
|
|
379
|
+
typeof suggestion.implementationRepo === 'string'
|
|
380
|
+
? [suggestion.implementationRepo] : []);
|
|
381
|
+
const group = projectCompactReferenceGroup(
|
|
382
|
+
repos, projection.suggestionCount, isSafeCompactReferenceName,
|
|
383
|
+
);
|
|
384
|
+
return group && group.total > 1 ? group : undefined;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
function decisionWithTiedCandidates(
|
|
388
|
+
evidence: Record<string, unknown>,
|
|
389
|
+
decision: CompactDecisionInput,
|
|
390
|
+
): CompactDecisionInput {
|
|
391
|
+
const tiedCandidateRepos = tiedCandidateRepositoryGroup(evidence, decision);
|
|
392
|
+
return tiedCandidateRepos ? { ...decision, tiedCandidateRepos } : decision;
|
|
393
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { TraceEdge } from '../types.js';
|
|
2
|
-
import type { CompactSemanticEndpoint, CompactStatus } from './
|
|
2
|
+
import type { CompactSemanticEndpoint, CompactStatus } from './compact-contract.js';
|
|
3
3
|
import {
|
|
4
4
|
compactDecisionFromEvidence,
|
|
5
|
+
compactEvidenceReasonCode,
|
|
5
6
|
compactEventStatus,
|
|
6
7
|
compactGraphStatus,
|
|
7
8
|
compactRefs,
|
|
@@ -16,8 +17,8 @@ import {
|
|
|
16
17
|
type SemanticCallRow,
|
|
17
18
|
type SemanticTargetRow,
|
|
18
19
|
type TraceEdgeRecorder,
|
|
19
|
-
} from './
|
|
20
|
-
import type { PlannedEventSubscriberTransition } from './
|
|
20
|
+
} from './trace-edge-recorder.js';
|
|
21
|
+
import type { PlannedEventSubscriberTransition } from './event-subscriber-traversal.js';
|
|
21
22
|
import type { DynamicCandidateBranch } from './dynamic-branches.js';
|
|
22
23
|
|
|
23
24
|
interface ImplementationObservation {
|
|
@@ -157,11 +158,11 @@ export function recordOutboundObservation(
|
|
|
157
158
|
source, target,
|
|
158
159
|
status: compactGraphStatus(input.row, input.evidence,
|
|
159
160
|
input.unresolvedReason, input.dynamicMode),
|
|
160
|
-
decision: compactDecisionFromEvidence(input.evidence,
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
161
|
+
decision: compactDecisionFromEvidence(input.evidence,
|
|
162
|
+
input.unresolvedReason ? {
|
|
163
|
+
reasonCode: compactEvidenceReasonCode(input.evidence)
|
|
164
|
+
?? 'outbound_target_unresolved',
|
|
165
|
+
} : {}),
|
|
165
166
|
refs: compactRefs({
|
|
166
167
|
graphEdgeId: positiveId(input.evidence.persistedGraphEdgeId),
|
|
167
168
|
outboundCallId: input.call.id,
|
|
@@ -295,11 +296,6 @@ function eventSite(
|
|
|
295
296
|
endOffset: plan.transition.callSiteEndOffset });
|
|
296
297
|
}
|
|
297
298
|
|
|
298
|
-
function safeReasonCode(value: unknown, fallback: string): string {
|
|
299
|
-
return typeof value === 'string' && /^[a-z][a-z0-9_.-]{0,79}$/.test(value)
|
|
300
|
-
? value : fallback;
|
|
301
|
-
}
|
|
302
|
-
|
|
303
299
|
function positiveId(value: unknown): number | string | undefined {
|
|
304
300
|
if (typeof value === 'number') return Number.isFinite(value) && value > 0
|
|
305
301
|
? value : undefined;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Db } from '../db/connection.js';
|
|
2
|
-
import { schemaLifecycleDiagnostic } from '../db/
|
|
2
|
+
import { schemaLifecycleDiagnostic } from '../db/fact-lifecycle.js';
|
|
3
3
|
import type {
|
|
4
4
|
TraceEdge,
|
|
5
5
|
TraceOptions,
|
|
@@ -13,21 +13,21 @@ import {
|
|
|
13
13
|
import {
|
|
14
14
|
loadTraceDiagnostics,
|
|
15
15
|
prependTraceDiagnostic,
|
|
16
|
-
} from './
|
|
17
|
-
import { TraversalScopeScheduler } from './
|
|
18
|
-
import { createTraceRootPlan } from './
|
|
19
|
-
import type { CompactTraceObserver } from './
|
|
20
|
-
import { TraceEdgeRecorder } from './
|
|
21
|
-
import type { ImplementationHintOptions } from './
|
|
16
|
+
} from './trace-diagnostics.js';
|
|
17
|
+
import { TraversalScopeScheduler } from './traversal-scope.js';
|
|
18
|
+
import { createTraceRootPlan } from './trace-root-scopes.js';
|
|
19
|
+
import type { CompactTraceObserver } from './compact-contract.js';
|
|
20
|
+
import { TraceEdgeRecorder } from './trace-edge-recorder.js';
|
|
21
|
+
import type { ImplementationHintOptions } from './trace-implementation-scope.js';
|
|
22
22
|
import {
|
|
23
23
|
resolveTraceStartScope,
|
|
24
24
|
type TraceStartScope,
|
|
25
|
-
} from './
|
|
25
|
+
} from './trace-start-scope.js';
|
|
26
26
|
import {
|
|
27
27
|
executeTraceScopes,
|
|
28
28
|
type TraceExecutionRuntime,
|
|
29
|
-
} from './
|
|
30
|
-
import { recordTraceStartImplementation } from './
|
|
29
|
+
} from './trace-scope-execution.js';
|
|
30
|
+
import { recordTraceStartImplementation } from './trace-start-implementation.js';
|
|
31
31
|
import { selectorNotFoundDiagnostic } from './selectors.js';
|
|
32
32
|
|
|
33
33
|
const compactObserverKey = Symbol('service-flow.compact-trace-observer');
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Db } from '../db/connection.js';
|
|
2
|
-
import { currentFactLifecycleDiagnostic } from '../db/
|
|
3
|
-
import { resolveTraversalWorkspaceId } from './
|
|
2
|
+
import { currentFactLifecycleDiagnostic } from '../db/fact-lifecycle.js';
|
|
3
|
+
import { resolveTraversalWorkspaceId } from './traversal-scope.js';
|
|
4
4
|
|
|
5
5
|
function workspaceScopeIsAmbiguous(db: Db): boolean {
|
|
6
6
|
const rows = db.prepare(`SELECT DISTINCT workspace_id workspaceId
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Db } from '../db/connection.js';
|
|
2
2
|
import type { ImplementationHint } from '../types.js';
|
|
3
|
-
import type { TraceGraphEdgeRow } from './
|
|
3
|
+
import type { TraceGraphEdgeRow } from './trace-graph-lookups.js';
|
|
4
4
|
|
|
5
5
|
export interface ImplementationHintOptions {
|
|
6
6
|
implementationRepo?: string;
|
|
@@ -1,34 +1,34 @@
|
|
|
1
1
|
import type { Db } from '../db/connection.js';
|
|
2
2
|
import type { TraceEdge } from '../types.js';
|
|
3
3
|
import { implementationHintDiagnostic } from './implementation-hints.js';
|
|
4
|
-
import { contextualImplementationSelection } from './
|
|
5
|
-
import type { ContextBinding } from './
|
|
4
|
+
import { contextualImplementationSelection } from './implementation-selection.js';
|
|
5
|
+
import type { ContextBinding } from './contextual-runtime-state.js';
|
|
6
6
|
import {
|
|
7
7
|
handlerMethodNode,
|
|
8
8
|
withSelectedHandlerProvenance,
|
|
9
9
|
type SelectedHandlerEvidence,
|
|
10
|
-
} from './
|
|
11
|
-
import type { TraversalScopeState } from './
|
|
12
|
-
import type { TraceGraphEdgeRow } from './
|
|
10
|
+
} from './selected-handler-provenance.js';
|
|
11
|
+
import type { TraversalScopeState } from './traversal-scope.js';
|
|
12
|
+
import type { TraceGraphEdgeRow } from './trace-graph-lookups.js';
|
|
13
13
|
import {
|
|
14
14
|
enqueueCausalScope,
|
|
15
15
|
type TraceQueueScope,
|
|
16
|
-
} from './
|
|
17
|
-
import { parseTraceEvidence } from './
|
|
16
|
+
} from './trace-root-scopes.js';
|
|
17
|
+
import { parseTraceEvidence } from './trace-context.js';
|
|
18
18
|
import {
|
|
19
19
|
recordCycleObservation,
|
|
20
20
|
recordImplementationObservation,
|
|
21
|
-
} from './
|
|
21
|
+
} from './trace-edge-semantics.js';
|
|
22
22
|
import {
|
|
23
23
|
handlerFilesForOperation,
|
|
24
24
|
handlerScope,
|
|
25
25
|
implementationScope,
|
|
26
|
-
} from './
|
|
26
|
+
} from './trace-implementation-scope.js';
|
|
27
27
|
import type {
|
|
28
28
|
CallRow,
|
|
29
29
|
EffectiveOutbound,
|
|
30
30
|
TraceExecutionRuntime,
|
|
31
|
-
} from './
|
|
31
|
+
} from './trace-scope-execution.js';
|
|
32
32
|
|
|
33
33
|
interface OperationSelection {
|
|
34
34
|
implementation: ReturnType<typeof implementationScope>;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { Db } from '../db/connection.js';
|
|
2
|
-
import { currentFactLifecycleDiagnostic } from '../db/
|
|
3
|
-
import type { ContextBinding } from './
|
|
2
|
+
import { currentFactLifecycleDiagnostic } from '../db/fact-lifecycle.js';
|
|
3
|
+
import type { ContextBinding } from './contextual-runtime-state.js';
|
|
4
4
|
import {
|
|
5
5
|
resolveTraversalWorkspaceId,
|
|
6
6
|
type TraversalScopeScheduler,
|
|
7
7
|
type TraversalScopeState,
|
|
8
|
-
} from './
|
|
8
|
+
} from './traversal-scope.js';
|
|
9
9
|
|
|
10
10
|
export interface TraceQueueScope {
|
|
11
11
|
repoId?: number;
|
|
@@ -253,12 +253,11 @@ function hasExactDispatch(db: Db, calls: RootCallRow[]): boolean {
|
|
|
253
253
|
AND subscriber.generation=emitted.generation
|
|
254
254
|
AND subscriber.edge_type='EVENT_SUBSCRIPTION_HANDLED_BY'
|
|
255
255
|
AND subscriber.from_kind='event'
|
|
256
|
-
AND subscriber.from_id COLLATE BINARY
|
|
256
|
+
AND subscriber.from_id COLLATE BINARY=emitted.to_id COLLATE BINARY)
|
|
257
257
|
LIMIT 1`);
|
|
258
258
|
return calls.some((call) => call.callType === 'async_emit'
|
|
259
|
-
&& typeof call.eventName === 'string'
|
|
260
259
|
&& Boolean(match.get(call.workspaceId, call.graphGeneration,
|
|
261
|
-
String(call.id)
|
|
260
|
+
String(call.id))));
|
|
262
261
|
}
|
|
263
262
|
|
|
264
263
|
function workspaceAmbiguityDiagnostic(db: Db): Record<string, unknown> {
|
|
@@ -12,36 +12,32 @@ import {
|
|
|
12
12
|
type ContextBinding,
|
|
13
13
|
type ContextualGraphRow,
|
|
14
14
|
type ContextualRuntimeResolution,
|
|
15
|
-
} from './
|
|
15
|
+
} from './contextual-runtime-state.js';
|
|
16
16
|
import {
|
|
17
17
|
TraversalScopeScheduler,
|
|
18
18
|
type TraversalScopeState,
|
|
19
|
-
} from './
|
|
20
|
-
import {
|
|
21
|
-
planEventSubscriberTransitions,
|
|
22
|
-
type PlannedEventSubscriberTransition,
|
|
23
|
-
} from './011-event-subscriber-traversal.js';
|
|
19
|
+
} from './traversal-scope.js';
|
|
20
|
+
import type { PlannedEventSubscriberTransition } from './event-subscriber-traversal.js';
|
|
24
21
|
import {
|
|
25
22
|
graphForCalls,
|
|
26
23
|
operationNode,
|
|
27
24
|
symbolNode,
|
|
28
25
|
type TraceGraphEdgeRow,
|
|
29
|
-
} from './
|
|
26
|
+
} from './trace-graph-lookups.js';
|
|
30
27
|
import {
|
|
31
28
|
enqueueCausalScope,
|
|
32
29
|
nextPendingRoot,
|
|
33
30
|
type PendingTraceRootScope,
|
|
34
31
|
type TraceQueueScope,
|
|
35
|
-
} from './
|
|
36
|
-
import type { CompactSemanticEndpoint } from './
|
|
37
|
-
import { TraceEdgeRecorder } from './
|
|
32
|
+
} from './trace-root-scopes.js';
|
|
33
|
+
import type { CompactSemanticEndpoint } from './compact-contract.js';
|
|
34
|
+
import { TraceEdgeRecorder } from './trace-edge-recorder.js';
|
|
38
35
|
import {
|
|
39
|
-
contextForSymbolCall,
|
|
40
36
|
knownBindingsForCalls,
|
|
41
37
|
knownBindingsForScope,
|
|
42
38
|
parseTraceEvidence,
|
|
43
39
|
receiverFromTraceEvidence,
|
|
44
|
-
} from './
|
|
40
|
+
} from './trace-context.js';
|
|
45
41
|
import {
|
|
46
42
|
recordCycleObservation,
|
|
47
43
|
recordDynamicBranchObservation,
|
|
@@ -49,10 +45,12 @@ import {
|
|
|
49
45
|
recordEventCycleObservation,
|
|
50
46
|
recordLocalCallObservation,
|
|
51
47
|
recordOutboundObservation,
|
|
52
|
-
} from './
|
|
53
|
-
import { outboundScopeSymbolIds } from './
|
|
54
|
-
import type { ImplementationHintOptions } from './
|
|
55
|
-
import { processOperationTarget } from './
|
|
48
|
+
} from './trace-edge-semantics.js';
|
|
49
|
+
import { outboundScopeSymbolIds } from './nested-event-scopes.js';
|
|
50
|
+
import type { ImplementationHintOptions } from './trace-implementation-scope.js';
|
|
51
|
+
import { processOperationTarget } from './trace-operation-execution.js';
|
|
52
|
+
import { runtimeEventResolution, runtimeEventSubscriberPlans } from './event-runtime-resolution.js';
|
|
53
|
+
import { planLocalCallExpansion } from './local-call-expansion.js';
|
|
56
54
|
|
|
57
55
|
export interface CallRow extends Record<string, unknown> {
|
|
58
56
|
id: number;
|
|
@@ -226,20 +224,10 @@ function processLocalCall(
|
|
|
226
224
|
bindings: Map<string, ContextBinding>,
|
|
227
225
|
row: Record<string, unknown>,
|
|
228
226
|
): void {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
const
|
|
232
|
-
|
|
233
|
-
const repoId = Number(row.calleeRepoId);
|
|
234
|
-
const context = contextForSymbolCall(runtime.db, row, bindings);
|
|
235
|
-
const scheduling = runtime.scheduler.schedule({
|
|
236
|
-
workspaceId: runtime.workspaceId,
|
|
237
|
-
repoId,
|
|
238
|
-
files,
|
|
239
|
-
symbolIds: symbols,
|
|
240
|
-
context,
|
|
241
|
-
}, current.state);
|
|
242
|
-
const node = symbolNode(runtime.db, symbolId);
|
|
227
|
+
const symbolId = row.callee_symbol_id
|
|
228
|
+
? Number(row.callee_symbol_id) : undefined;
|
|
229
|
+
const node = symbolId === undefined
|
|
230
|
+
? undefined : symbolNode(runtime.db, symbolId);
|
|
243
231
|
if (node) runtime.nodes.set(String(node.id), node);
|
|
244
232
|
const evidence = localCallEvidence(row, node);
|
|
245
233
|
const unresolvedReason = localCallUnresolvedReason(row);
|
|
@@ -247,6 +235,12 @@ function processLocalCall(
|
|
|
247
235
|
const target = recordLocalCallObservation(runtime.recorder, edge, {
|
|
248
236
|
symbolCall: row, evidence, unresolvedReason,
|
|
249
237
|
});
|
|
238
|
+
if (symbolId === undefined || row.status !== 'resolved' || !node) return;
|
|
239
|
+
const { repoId, files, symbols, context, scheduling } =
|
|
240
|
+
planLocalCallExpansion(
|
|
241
|
+
runtime.db, runtime.scheduler, runtime.workspaceId, current.state,
|
|
242
|
+
row, bindings, symbolId,
|
|
243
|
+
);
|
|
250
244
|
if (scheduling.kind === 'cycle')
|
|
251
245
|
recordLocalCycle(runtime, current, row, target, scheduling.state,
|
|
252
246
|
repoId, files, symbols);
|
|
@@ -291,7 +285,8 @@ function localTraceEdge(
|
|
|
291
285
|
type: 'local_symbol_call',
|
|
292
286
|
from: String(row.callee_expression),
|
|
293
287
|
to: node?.label
|
|
294
|
-
? String(node.label)
|
|
288
|
+
? String(node.label)
|
|
289
|
+
: `${String(row.status)}:${String(row.callee_expression)}`,
|
|
295
290
|
evidence,
|
|
296
291
|
confidence: Number(row.confidence ?? 0.8),
|
|
297
292
|
unresolvedReason,
|
|
@@ -390,11 +385,12 @@ function recordEffectiveOutbound(
|
|
|
390
385
|
): EffectiveOutbound {
|
|
391
386
|
const persisted = parseTraceEvidence(row.evidence_json);
|
|
392
387
|
const raw = baseTraceEvidence(row, call, persisted, contextual.evidence);
|
|
393
|
-
const effective =
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
388
|
+
const effective = runtimeEventResolution(row, raw, runtime.options.vars)
|
|
389
|
+
?? runtimeResolution(runtime.db, row, raw, {
|
|
390
|
+
vars: runtime.options.vars,
|
|
391
|
+
dynamicMode: runtime.options.dynamicMode ?? 'strict',
|
|
392
|
+
maxDynamicCandidates: runtime.options.maxDynamicCandidates,
|
|
393
|
+
}, call.workspaceId, contextual.state);
|
|
398
394
|
const target = `${effective.row.to_kind}:${effective.row.to_id}`;
|
|
399
395
|
const operation = effective.row.to_kind === 'operation'
|
|
400
396
|
? operationNode(runtime.db, effective.row.to_id) : undefined;
|
|
@@ -461,15 +457,19 @@ function processEventTransitions(
|
|
|
461
457
|
): void {
|
|
462
458
|
if (!runtime.options.includeAsync || call.call_type !== 'async_emit'
|
|
463
459
|
|| effective.row.edge_type !== 'HANDLER_EMITS_EVENT'
|
|
464
|
-
||
|
|
465
|
-
const
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
460
|
+
|| effective.row.to_kind !== 'event') return;
|
|
461
|
+
const planned = runtimeEventSubscriberPlans(
|
|
462
|
+
runtime.db, {
|
|
463
|
+
workspaceId: runtime.workspaceId ?? call.workspaceId,
|
|
464
|
+
graphGeneration: call.graphGeneration,
|
|
465
|
+
eventName: effective.row.to_id,
|
|
466
|
+
vars: runtime.options.vars ?? {},
|
|
467
|
+
}, runtime.scheduler, current.state, current.depth, runtime.maxDepth,
|
|
468
|
+
);
|
|
469
|
+
if (planned.diagnostic) runtime.diagnostics.push(planned.diagnostic);
|
|
470
|
+
for (const plan of planned.plans)
|
|
471
471
|
recordEventTransition(runtime, current, plan,
|
|
472
|
-
effective.semanticWorkspaceId, plans.length);
|
|
472
|
+
effective.semanticWorkspaceId, planned.plans.length);
|
|
473
473
|
}
|
|
474
474
|
|
|
475
475
|
function recordEventTransition(
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import type { Db } from '../db/connection.js';
|
|
2
2
|
import type { TraceEdge } from '../types.js';
|
|
3
|
-
import { hintedImplementationSelection } from './
|
|
3
|
+
import { hintedImplementationSelection } from './implementation-selection.js';
|
|
4
4
|
import {
|
|
5
5
|
handlerMethodNode,
|
|
6
6
|
withSelectedHandlerProvenance,
|
|
7
7
|
type SelectedHandlerEvidence,
|
|
8
|
-
} from './
|
|
8
|
+
} from './selected-handler-provenance.js';
|
|
9
9
|
import {
|
|
10
10
|
operationNode,
|
|
11
11
|
type TraceGraphEdgeRow,
|
|
12
|
-
} from './
|
|
13
|
-
import { parseTraceEvidence } from './
|
|
14
|
-
import { recordImplementationObservation } from './
|
|
12
|
+
} from './trace-graph-lookups.js';
|
|
13
|
+
import { parseTraceEvidence } from './trace-context.js';
|
|
14
|
+
import { recordImplementationObservation } from './trace-edge-semantics.js';
|
|
15
15
|
import {
|
|
16
16
|
handlerScope,
|
|
17
17
|
implementationScope,
|
|
18
|
-
} from './
|
|
19
|
-
import type { TraceExecutionRuntime } from './
|
|
18
|
+
} from './trace-implementation-scope.js';
|
|
19
|
+
import type { TraceExecutionRuntime } from './trace-scope-execution.js';
|
|
20
20
|
|
|
21
21
|
interface StartImplementationSelection {
|
|
22
22
|
edge: TraceGraphEdgeRow;
|