@weftlet/toolkit 0.7.1 → 0.7.3
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/README.md +10 -4
- package/dist/application/saved-paths.d.ts +1 -1
- package/dist/graph/impact-order.d.ts +18 -0
- package/dist/graph/impact-order.js +77 -0
- package/dist/graph/impact-signals.d.ts +8 -0
- package/dist/graph/impact-signals.js +54 -0
- package/dist/graph/path-search.d.ts +6 -4
- package/dist/graph/path-search.js +50 -24
- package/dist/graph/paths-renderer.js +1 -1
- package/dist/graph/paths.d.ts +1 -1
- package/dist/graph/paths.js +2 -2
- package/dist/graph/query.js +1 -1
- package/dist/graph/ranking.d.ts +1 -1
- package/dist/graph/ranking.js +13 -19
- package/dist/interfaces/graph-paths.js +1 -1
- package/dist/visualization/viewer-interaction.js +1 -1
- package/docs/1.0-WORK-QUEUE.md +16 -0
- package/docs/ADR-012-impact-ranking.md +2 -1
- package/docs/ADR-030-bounded-evidence-paths.md +21 -18
- package/docs/ADR-041-bounded-relationship-retrieval.md +78 -0
- package/docs/ADR-042-indirect-local-relationships.md +59 -0
- package/docs/RELEASING.md +3 -3
- package/docs/VALIDATION.md +81 -0
- package/docs/extraction-manifest.json +26 -5
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ Proposed future capabilities are recorded in the [Weftlet 2.0 product plan](docs
|
|
|
14
14
|
## Set up a project
|
|
15
15
|
|
|
16
16
|
<!-- weftlet:release:start -->
|
|
17
|
-
Package versions in this checkout/archive: `@weftlet/toolkit@0.7.
|
|
17
|
+
Package versions in this checkout/archive: `@weftlet/toolkit@0.7.3` and `@weftlet/core@0.7.3`.
|
|
18
18
|
<!-- weftlet:release:end -->
|
|
19
19
|
|
|
20
20
|
Weftlet uses `@weftlet/toolkit`; its neutral `@weftlet/core` dependency is installed
|
|
@@ -468,7 +468,9 @@ the search's total ceiling is 100,000 examinations. Responses report replay work
|
|
|
468
468
|
Follow `search.continuation` with identical inputs even if a work page contains no completed
|
|
469
469
|
path. Depth cuts and total-work exhaustion remain explicit without pretending all dependencies
|
|
470
470
|
were checked; inspect `frontier` and restart with greater depth or narrower endpoints/relations.
|
|
471
|
-
Paths
|
|
471
|
+
Paths enumerate shorter cited routes first, prioritizing a direct connection before unrelated branches.
|
|
472
|
+
They are associations, not proof of business compatibility. Pending frontiers report exact counts
|
|
473
|
+
and up to 32 examples with explicit omissions; candidate-work and depth limits still apply.
|
|
472
474
|
The HTML viewer uses the same engine and continuation on its displayed facts and selected layers.
|
|
473
475
|
See [path semantics and limits](docs/ADR-030-bounded-evidence-paths.md).
|
|
474
476
|
|
|
@@ -484,9 +486,13 @@ pending re-extraction. Queries compare captured file digests with current workin
|
|
|
484
486
|
report subsequent edits separately from captured and excluded changes. Older overlays without
|
|
485
487
|
capture metadata have unknown freshness. Historical or draft evidence cannot validate a current diff.
|
|
486
488
|
|
|
487
|
-
Impact queries [
|
|
489
|
+
Impact queries [give near and indirect relationships bounded turns](docs/ADR-042-indirect-local-relationships.md)
|
|
488
490
|
ahead of repeated detail and shared-import context. Ranking changes ordering, not saved facts or
|
|
489
|
-
the reachable scope.
|
|
491
|
+
the reachable scope. Calls, cross-file references (including those without call proof) and file
|
|
492
|
+
consumers share turns across distance groups, with source diversity within each group. Local
|
|
493
|
+
detail has its own turns; unindexed symbol hubs follow local evidence unless explicitly queried.
|
|
494
|
+
These are ordering signals, not new assertions or proof of execution. All evidence remains in
|
|
495
|
+
the reachable set. Responses identify the ranking version; after a ranking upgrade, restart
|
|
490
496
|
scans whose old continuation tokens are rejected. No snapshot refresh is needed for new ordering.
|
|
491
497
|
|
|
492
498
|
The published toolkit includes a [coverage reporting correction](docs/ADR-024-implementation-coverage.md)
|
|
@@ -37,7 +37,7 @@ export declare class SavedGraphPathService implements GraphPathQueryService {
|
|
|
37
37
|
diagnostics: import("@weftlet/core").ContextPack["diagnostics"];
|
|
38
38
|
search: {
|
|
39
39
|
readonly version: string;
|
|
40
|
-
readonly order: "fact-id-depth-first";
|
|
40
|
+
readonly order: "fact-id-depth-first" | "shortest-first-target-first";
|
|
41
41
|
readonly direction: import("@weftlet/core").GraphDirection;
|
|
42
42
|
readonly predicates: readonly import("@weftlet/core").GraphPredicate[];
|
|
43
43
|
readonly maxDepth: number;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { GraphFact } from '@weftlet/core';
|
|
2
|
+
export interface ImpactOrderRow {
|
|
3
|
+
readonly fact: GraphFact;
|
|
4
|
+
readonly proximity: number;
|
|
5
|
+
readonly relationshipOrder: number;
|
|
6
|
+
readonly contextOnly: boolean;
|
|
7
|
+
readonly focus: number;
|
|
8
|
+
readonly tie: string;
|
|
9
|
+
}
|
|
10
|
+
/** Ordering waves preserve evidence-lane balancing in the query facade. Near
|
|
11
|
+
* and indirect relationships each get turns (two slots for calls, references
|
|
12
|
+
* and consumers, one for other relations); local detail also gets one slot
|
|
13
|
+
* per wave. Unindexed/shared-import context follows local evidence unless it
|
|
14
|
+
* was explicitly queried. No assertion, citation or authority is rewritten. */
|
|
15
|
+
export declare function orderImpactRows(rows: ImpactOrderRow[]): {
|
|
16
|
+
fact: GraphFact;
|
|
17
|
+
score: number;
|
|
18
|
+
}[];
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/** Fixed distance bands prevent thousands of first-hop sources from exhausting
|
|
2
|
+
* every page before any second-hop evidence gets a turn. They do not bound scope. */
|
|
3
|
+
function distanceBand(distance) {
|
|
4
|
+
return distance < 4 ? distance : distance < 8 ? 4 : 5;
|
|
5
|
+
}
|
|
6
|
+
function family(fact) {
|
|
7
|
+
if (fact.predicate === 'calls' || fact.predicate === 'references' || fact.predicate === 'consumes')
|
|
8
|
+
return fact.predicate;
|
|
9
|
+
return 'other';
|
|
10
|
+
}
|
|
11
|
+
const lexical = (a, b) => a < b ? -1 : a > b ? 1 : 0;
|
|
12
|
+
const compare = (a, b) => b.focus - a.focus ||
|
|
13
|
+
a.proximity - b.proximity || lexical(a.tie, b.tie) || lexical(a.fact.id, b.fact.id);
|
|
14
|
+
/** One source per turn within a distance/family bucket, without adding an
|
|
15
|
+
* unbounded source ordinal to graph distance. Every input row is retained. */
|
|
16
|
+
function sourceQueue(rows) {
|
|
17
|
+
const sources = new Map();
|
|
18
|
+
for (const row of rows.sort(compare)) {
|
|
19
|
+
const group = sources.get(row.fact.provenance.path) ?? [];
|
|
20
|
+
group.push(row);
|
|
21
|
+
sources.set(row.fact.provenance.path, group);
|
|
22
|
+
}
|
|
23
|
+
let active = [...sources.values()].map(rows => ({ rows, offset: 0 }));
|
|
24
|
+
let cursor = 0;
|
|
25
|
+
return () => {
|
|
26
|
+
if (!active.length)
|
|
27
|
+
return undefined;
|
|
28
|
+
if (cursor === active.length) {
|
|
29
|
+
active = active.filter(source => source.offset < source.rows.length);
|
|
30
|
+
cursor = 0;
|
|
31
|
+
}
|
|
32
|
+
const source = active[cursor++];
|
|
33
|
+
return source?.rows[source.offset++];
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/** Ordering waves preserve evidence-lane balancing in the query facade. Near
|
|
37
|
+
* and indirect relationships each get turns (two slots for calls, references
|
|
38
|
+
* and consumers, one for other relations); local detail also gets one slot
|
|
39
|
+
* per wave. Unindexed/shared-import context follows local evidence unless it
|
|
40
|
+
* was explicitly queried. No assertion, citation or authority is rewritten. */
|
|
41
|
+
export function orderImpactRows(rows) {
|
|
42
|
+
const result = [];
|
|
43
|
+
let wave = 0;
|
|
44
|
+
for (const contextOnly of [false, true]) {
|
|
45
|
+
const selected = rows.filter(row => row.contextOnly === contextOnly);
|
|
46
|
+
const buckets = new Map();
|
|
47
|
+
const details = [];
|
|
48
|
+
for (const row of selected) {
|
|
49
|
+
if (row.relationshipOrder > 0) {
|
|
50
|
+
details.push(row);
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
const key = `${distanceBand(row.proximity)}:${family(row.fact)}`;
|
|
54
|
+
const bucket = buckets.get(key) ?? [];
|
|
55
|
+
bucket.push(row);
|
|
56
|
+
buckets.set(key, bucket);
|
|
57
|
+
}
|
|
58
|
+
const queues = [...buckets].sort(([a], [b]) => lexical(a, b))
|
|
59
|
+
.map(([key, group]) => ({ next: sourceQueue(group), slots: key.endsWith(':other') ? 1 : 2 }));
|
|
60
|
+
if (details.length)
|
|
61
|
+
queues.push({ next: sourceQueue(details), slots: 1 });
|
|
62
|
+
let remaining = selected.length;
|
|
63
|
+
while (remaining > 0) {
|
|
64
|
+
for (const { next, slots } of queues) {
|
|
65
|
+
for (let slot = 0; slot < slots; slot++) {
|
|
66
|
+
const row = next();
|
|
67
|
+
if (row) {
|
|
68
|
+
result.push({ fact: row.fact, score: wave });
|
|
69
|
+
remaining--;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
wave++;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return result;
|
|
77
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { GraphFact, GraphNode } from '@weftlet/core';
|
|
2
|
+
/** Query-order signals from saved evidence, never new assertions or authority. */
|
|
3
|
+
export declare function impactRankingSignals(facts: readonly GraphFact[], anchorTerms: readonly string[]): {
|
|
4
|
+
penalty: (fact: GraphFact) => 0 | 8;
|
|
5
|
+
seedNodes: (fact: GraphFact) => GraphNode[];
|
|
6
|
+
relationshipOrder: (fact: GraphFact) => 0 | 2;
|
|
7
|
+
contextOnly: (fact: GraphFact) => boolean;
|
|
8
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/** Query-order signals from saved evidence, never new assertions or authority. */
|
|
2
|
+
export function impactRankingSignals(facts, anchorTerms) {
|
|
3
|
+
const definitions = new Map();
|
|
4
|
+
const callsiteReferences = new Set();
|
|
5
|
+
const localCall = (fact) => fact.predicate === 'calls' && fact.codeCall !== undefined &&
|
|
6
|
+
fact.codeCall.target !== 'external' && fact.codeCall.targetDefinitions.length > 0;
|
|
7
|
+
for (const fact of facts) {
|
|
8
|
+
if (fact.codeOccurrence?.role === 'definition' && fact.predicate === 'definedBy') {
|
|
9
|
+
const paths = definitions.get(fact.subject.id) ?? new Set();
|
|
10
|
+
paths.add(fact.provenance.path);
|
|
11
|
+
definitions.set(fact.subject.id, paths);
|
|
12
|
+
}
|
|
13
|
+
if (localCall(fact)) {
|
|
14
|
+
for (const proof of fact.codeCall.targetOccurrences)
|
|
15
|
+
callsiteReferences.add(proof.factId);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
const explicit = (node) => anchorTerms.some(term => `${node.id} ${node.label} ${node.codeSymbol?.nativeSymbol ?? ''}`.toLowerCase().includes(term));
|
|
19
|
+
const unindexed = (node) => node.kind === 'CodeSymbol' &&
|
|
20
|
+
node.codeSymbol?.resolution === 'no-indexed-definition';
|
|
21
|
+
const hub = (node) => unindexed(node) && !explicit(node);
|
|
22
|
+
const penalty = (fact) => [fact.subject, fact.object].some(hub) ? 8 : 0;
|
|
23
|
+
const seedNodes = (fact) => {
|
|
24
|
+
const eligible = [fact.subject, fact.object].filter(node => node.kind !== 'Project');
|
|
25
|
+
const matching = eligible.filter(explicit);
|
|
26
|
+
if (matching.length)
|
|
27
|
+
return matching;
|
|
28
|
+
// A cited local operation's library references must not turn those shared
|
|
29
|
+
// library identities into zero-distance anchors for all their co-users.
|
|
30
|
+
const local = eligible.filter(node => !unindexed(node));
|
|
31
|
+
return local.length ? local : eligible;
|
|
32
|
+
};
|
|
33
|
+
const relationshipOrder = (fact) => {
|
|
34
|
+
if (localCall(fact) || callsiteReferences.has(fact.id))
|
|
35
|
+
return 0;
|
|
36
|
+
if (fact.codeOccurrence?.role === 'reference') {
|
|
37
|
+
if (explicit(fact.object))
|
|
38
|
+
return 0;
|
|
39
|
+
const targetPaths = definitions.get(fact.object.id);
|
|
40
|
+
// A saved reference across repository files is useful without a native
|
|
41
|
+
// call proof. This only changes its query order, never its predicate.
|
|
42
|
+
if (targetPaths && [...targetPaths].some(path => path !== fact.provenance.path))
|
|
43
|
+
return 0;
|
|
44
|
+
}
|
|
45
|
+
if (fact.codeOccurrence || fact.codeCall)
|
|
46
|
+
return 2;
|
|
47
|
+
if (fact.predicate === 'contains' && (fact.subject.kind === 'Project' ||
|
|
48
|
+
fact.object.kind === 'CodeSymbol' || fact.object.id.startsWith('symbol:scip:')))
|
|
49
|
+
return 2;
|
|
50
|
+
return 0; // Keep intent, queue/data contracts, validation and legacy adapter relations available.
|
|
51
|
+
};
|
|
52
|
+
const contextOnly = (fact) => [fact.subject, fact.object].some(node => hub(node) || (node.id.startsWith('contract:module:') && !explicit(node)));
|
|
53
|
+
return { penalty, seedNodes, relationshipOrder, contextOnly };
|
|
54
|
+
}
|
|
@@ -16,11 +16,13 @@ export declare function searchEvidencePaths(edges: readonly PathEdge[], start: s
|
|
|
16
16
|
paths: EvidencePath[];
|
|
17
17
|
frontier: {
|
|
18
18
|
pending: {
|
|
19
|
-
nodeId: string;
|
|
20
|
-
viaFactIds: string[];
|
|
21
|
-
nextFactId: string;
|
|
22
|
-
remainingCandidates: number;
|
|
19
|
+
readonly nodeId: string;
|
|
20
|
+
readonly viaFactIds: readonly string[];
|
|
21
|
+
readonly nextFactId: string;
|
|
22
|
+
readonly remainingCandidates: number;
|
|
23
23
|
}[];
|
|
24
|
+
pendingCount: number;
|
|
25
|
+
omittedPending: number;
|
|
24
26
|
depthLimited: {
|
|
25
27
|
count: number;
|
|
26
28
|
examples: {
|
|
@@ -14,7 +14,10 @@ export function searchEvidencePaths(edges, start, target, options, knownNodeIds)
|
|
|
14
14
|
validateBounds();
|
|
15
15
|
const adjacency = new Map();
|
|
16
16
|
const nodeIds = new Set();
|
|
17
|
-
|
|
17
|
+
// Building adjacency already visits every input edge. Prefer closing edges in
|
|
18
|
+
// that index; candidate examination below still counts every selected edge.
|
|
19
|
+
for (const edge of [...edges].sort((a, b) => Number(b.to === target) - Number(a.to === target) ||
|
|
20
|
+
(a.id < b.id ? -1 : a.id > b.id ? 1 : 0))) {
|
|
18
21
|
const entries = adjacency.get(edge.from) ?? [];
|
|
19
22
|
entries.push(edge);
|
|
20
23
|
adjacency.set(edge.from, entries);
|
|
@@ -22,40 +25,55 @@ export function searchEvidencePaths(edges, start, target, options, knownNodeIds)
|
|
|
22
25
|
nodeIds.add(edge.to);
|
|
23
26
|
}
|
|
24
27
|
const paths = [];
|
|
25
|
-
|
|
28
|
+
// At most one prefix is allocated per examined edge, bounded by searchLimit.
|
|
29
|
+
// Parent links retain distinct simple paths without copying whole path arrays.
|
|
30
|
+
const queue = nodeIds.has(start) && nodeIds.has(target) && start !== target
|
|
31
|
+
? [{ nodeId: start, next: 0, depth: 0 }] : [];
|
|
32
|
+
let head = 0;
|
|
26
33
|
const depthExamples = [];
|
|
27
34
|
let depthCount = 0;
|
|
28
35
|
let totalSteps = 0;
|
|
29
36
|
const trim = () => {
|
|
30
|
-
while (
|
|
31
|
-
|
|
37
|
+
while (head < queue.length && queue[head].next >= (adjacency.get(queue[head].nodeId)?.length ?? 0))
|
|
38
|
+
head++;
|
|
39
|
+
};
|
|
40
|
+
const prefixPath = (frame) => {
|
|
41
|
+
const nodeIds = [], factIds = [];
|
|
42
|
+
for (let cursor = frame; cursor; cursor = cursor.parent) {
|
|
43
|
+
nodeIds.push(cursor.nodeId);
|
|
44
|
+
if (cursor.via !== undefined)
|
|
45
|
+
factIds.push(cursor.via);
|
|
46
|
+
}
|
|
47
|
+
return { nodeIds: nodeIds.reverse(), factIds: factIds.reverse() };
|
|
32
48
|
};
|
|
33
49
|
const step = () => {
|
|
34
|
-
const frame =
|
|
50
|
+
const frame = queue[head];
|
|
35
51
|
const edge = adjacency.get(frame.nodeId)[frame.next++];
|
|
36
52
|
totalSteps++;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
53
|
+
for (let cursor = frame; cursor; cursor = cursor.parent) {
|
|
54
|
+
if (cursor.nodeId === edge.to)
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (frame.depth === options.maxDepth) {
|
|
41
58
|
depthCount++;
|
|
42
59
|
if (depthExamples.length < 20)
|
|
43
|
-
depthExamples.push({ nodeId: frame.nodeId, viaFactIds,
|
|
60
|
+
depthExamples.push({ nodeId: frame.nodeId, viaFactIds: prefixPath(frame).factIds,
|
|
44
61
|
nextFactId: edge.id, nextNodeId: edge.to });
|
|
45
62
|
}
|
|
46
63
|
else if (edge.to === target) {
|
|
47
|
-
|
|
64
|
+
const path = prefixPath(frame);
|
|
65
|
+
return { nodeIds: [...path.nodeIds, target], factIds: [...path.factIds, edge.id] };
|
|
48
66
|
}
|
|
49
|
-
else {
|
|
50
|
-
|
|
67
|
+
else if (adjacency.has(edge.to)) {
|
|
68
|
+
queue.push({ nodeId: edge.to, next: 0, depth: frame.depth + 1, via: edge.id, parent: frame });
|
|
51
69
|
}
|
|
52
70
|
};
|
|
53
71
|
trim();
|
|
54
|
-
// Reconstruct
|
|
72
|
+
// Reconstruct bounded search state; never accept a caller-supplied queue or facts.
|
|
55
73
|
const replay = () => {
|
|
56
74
|
let replayPageSteps = 0;
|
|
57
75
|
let replayPagePaths = 0;
|
|
58
|
-
while (totalSteps < offset &&
|
|
76
|
+
while (totalSteps < offset && head < queue.length) {
|
|
59
77
|
if (step())
|
|
60
78
|
replayPagePaths++;
|
|
61
79
|
replayPageSteps++;
|
|
@@ -65,26 +83,33 @@ export function searchEvidencePaths(edges, start, target, options, knownNodeIds)
|
|
|
65
83
|
}
|
|
66
84
|
trim();
|
|
67
85
|
}
|
|
68
|
-
if (totalSteps !== offset || (offset && (
|
|
86
|
+
if (totalSteps !== offset || (offset && (head === queue.length || replayPagePaths || replayPageSteps))) {
|
|
69
87
|
throw new Error('Invalid path continuation boundary');
|
|
70
88
|
}
|
|
71
89
|
};
|
|
72
90
|
replay();
|
|
73
91
|
if (!offset && start === target && (nodeIds.has(start) || knownNodeIds?.has(start)))
|
|
74
92
|
paths.push({ nodeIds: [start], factIds: [] });
|
|
75
|
-
while (
|
|
93
|
+
while (head < queue.length && paths.length < options.maxPaths && totalSteps - offset < options.maxSteps && totalSteps < searchLimit) {
|
|
76
94
|
const path = step();
|
|
77
95
|
if (path)
|
|
78
96
|
paths.push(path);
|
|
79
97
|
trim();
|
|
80
98
|
}
|
|
81
|
-
const pending =
|
|
99
|
+
const pending = [];
|
|
100
|
+
let pendingCount = 0;
|
|
101
|
+
for (let index = head; index < queue.length; index++) {
|
|
102
|
+
const frame = queue[index];
|
|
82
103
|
const entries = adjacency.get(frame.nodeId) ?? [];
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
104
|
+
if (frame.next >= entries.length)
|
|
105
|
+
continue;
|
|
106
|
+
pendingCount++;
|
|
107
|
+
if (pending.length < 32)
|
|
108
|
+
pending.push({ nodeId: frame.nodeId,
|
|
109
|
+
viaFactIds: prefixPath(frame).factIds, nextFactId: entries[frame.next].id,
|
|
110
|
+
remainingCandidates: entries.length - frame.next });
|
|
111
|
+
}
|
|
112
|
+
const exhaustedWithinDepth = head === queue.length;
|
|
88
113
|
const stopReason = () => {
|
|
89
114
|
if (exhaustedWithinDepth)
|
|
90
115
|
return 'exhausted';
|
|
@@ -94,7 +119,8 @@ export function searchEvidencePaths(edges, start, target, options, knownNodeIds)
|
|
|
94
119
|
return 'path-page-limit';
|
|
95
120
|
return 'work-page-limit';
|
|
96
121
|
};
|
|
97
|
-
return { paths, frontier: { pending,
|
|
122
|
+
return { paths, frontier: { pending, pendingCount, omittedPending: pendingCount - pending.length,
|
|
123
|
+
depthLimited: { count: depthCount, examples: depthExamples,
|
|
98
124
|
omitted: depthCount - depthExamples.length } }, search: { searchLimit, replayedSteps: offset,
|
|
99
125
|
examinedSteps: totalSteps - offset, totalSteps, stopReason: stopReason(), exhaustedWithinDepth,
|
|
100
126
|
depthLimitReached: depthCount > 0, truncated: !exhaustedWithinDepth || depthCount > 0 } };
|
|
@@ -16,7 +16,7 @@ export function renderGraphPaths(result) {
|
|
|
16
16
|
`Direction: ${search.direction}; predicates: ${search.predicates.join(', ') || 'all'}; order: ${search.order}`,
|
|
17
17
|
`Depth: ${search.maxDepth}; paths on page: ${result.paths.length}/${search.maxPaths}; stop: ${search.stopReason}; truncated: ${search.truncated}`,
|
|
18
18
|
`Candidate steps: ${search.examinedSteps} new + ${search.replayedSteps} replay; ${search.totalSteps}/${search.searchLimit} total ceiling.`,
|
|
19
|
-
`Unexamined prefixes: ${frontier.pending.length}; depth-limited extensions: ${frontier.depthLimited.count} (${frontier.depthLimited.omitted} examples omitted).`,
|
|
19
|
+
`Unexamined prefixes: ${frontier.pendingCount ?? frontier.pending.length} (${frontier.omittedPending ?? 0} examples omitted); depth-limited extensions: ${frontier.depthLimited.count} (${frontier.depthLimited.omitted} examples omitted).`,
|
|
20
20
|
...(search.continuation ? [`Continuation (same request): ${search.continuation}`] : []),
|
|
21
21
|
...(search.depthLimitReached ? ['Depth limit reached: restart with a larger maxDepth or explore a frontier node. Continuation does not lift the depth bound.'] : []),
|
|
22
22
|
...(search.stopReason === 'search-limit' ? ['Total search limit reached: narrow the relations or explore an intermediate node; no further continuation is available.'] : []),
|
package/dist/graph/paths.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { GraphPathQueryService, GraphPaths, GraphPathsRequest, SnapshotStore } from '@weftlet/core';
|
|
2
|
-
export declare const GRAPH_PATHS_VERSION = "simple-evidence-paths-
|
|
2
|
+
export declare const GRAPH_PATHS_VERSION = "simple-evidence-paths-v2";
|
|
3
3
|
export declare class SnapshotGraphPathService implements GraphPathQueryService {
|
|
4
4
|
private readonly store;
|
|
5
5
|
constructor(store: Pick<SnapshotStore, 'read'>);
|
package/dist/graph/paths.js
CHANGED
|
@@ -6,7 +6,7 @@ import { selectDiagnostics } from './diagnostics.js';
|
|
|
6
6
|
import { parseGraphPathsRequest } from './path-request.js';
|
|
7
7
|
import { searchEvidencePaths } from './path-search.js';
|
|
8
8
|
import { renderGraphPaths } from './paths-renderer.js';
|
|
9
|
-
export const GRAPH_PATHS_VERSION = 'simple-evidence-paths-
|
|
9
|
+
export const GRAPH_PATHS_VERSION = 'simple-evidence-paths-v2';
|
|
10
10
|
function continuationOffset(token, binding) {
|
|
11
11
|
if (!token)
|
|
12
12
|
return 0;
|
|
@@ -65,7 +65,7 @@ export class SnapshotGraphPathService {
|
|
|
65
65
|
paths: result.paths, facts, coverage: coverageForFacts(facts, saved),
|
|
66
66
|
diagnostics: selectDiagnostics(saved, {}, facts, [], [], new Set([request.fromNodeId, request.toNodeId,
|
|
67
67
|
...facts.flatMap(fact => [fact.subject.id, fact.object.id])])),
|
|
68
|
-
search: { version: GRAPH_PATHS_VERSION, order: '
|
|
68
|
+
search: { version: GRAPH_PATHS_VERSION, order: 'shortest-first-target-first', direction: request.direction,
|
|
69
69
|
predicates: request.predicates, maxDepth: request.maxDepth, maxPaths: request.maxPaths, maxSteps: request.maxSteps,
|
|
70
70
|
...result.search, ...(next ? { continuation: next } : {}) }, frontier: result.frontier,
|
|
71
71
|
};
|
package/dist/graph/query.js
CHANGED
|
@@ -203,7 +203,7 @@ export class SnapshotImpactQueryService {
|
|
|
203
203
|
tier.push(fact);
|
|
204
204
|
tiers.set(score, tier);
|
|
205
205
|
}
|
|
206
|
-
// Balance evidence lanes
|
|
206
|
+
// Balance evidence lanes within each ordering wave; retain the scorer's wave boundaries.
|
|
207
207
|
const allBalanced = [...tiers.values()].flatMap((tier) => [
|
|
208
208
|
...selectBalancedFacts(tier, tier.length),
|
|
209
209
|
...tier.filter((fact) => contextPackLaneForFact(fact) === undefined),
|
package/dist/graph/ranking.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { GraphFact } from '@weftlet/core';
|
|
2
2
|
/** Binds continuation offsets to the ordering policy; changing this requires restarting a scan. */
|
|
3
|
-
export declare const IMPACT_RANKING_VERSION = "
|
|
3
|
+
export declare const IMPACT_RANKING_VERSION = "local-relationship-waves-v3";
|
|
4
4
|
export declare function factSearchText(fact: GraphFact): string;
|
|
5
5
|
export interface RankedImpactFact {
|
|
6
6
|
readonly fact: GraphFact;
|
package/dist/graph/ranking.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { stableJson } from '../infrastructure/util.js';
|
|
2
|
+
import { impactRankingSignals } from './impact-signals.js';
|
|
3
|
+
import { orderImpactRows } from './impact-order.js';
|
|
2
4
|
/** Binds continuation offsets to the ordering policy; changing this requires restarting a scan. */
|
|
3
|
-
export const IMPACT_RANKING_VERSION = '
|
|
5
|
+
export const IMPACT_RANKING_VERSION = 'local-relationship-waves-v3';
|
|
4
6
|
export function factSearchText(fact) {
|
|
5
7
|
return [fact.subject.id, fact.subject.label, fact.predicate, fact.object.id,
|
|
6
8
|
fact.object.label, fact.provenance.path].join(' ').toLowerCase();
|
|
@@ -24,6 +26,9 @@ function stableTie(fact) {
|
|
|
24
26
|
}
|
|
25
27
|
/** Order an already bounded reachable set. No facts are pruned and no authority is changed. */
|
|
26
28
|
export function rankImpactFacts(facts, direct, anchorTerms, focus) {
|
|
29
|
+
const signals = impactRankingSignals(facts, anchorTerms);
|
|
30
|
+
const costs = new Map(facts.map(fact => [fact, signals.penalty(fact)]));
|
|
31
|
+
const cost = (fact, forward) => Math.max(edgeCost(fact, forward), costs.get(fact));
|
|
27
32
|
const adjacent = new Map();
|
|
28
33
|
const connect = (from, to, cost) => {
|
|
29
34
|
if (from.kind === 'Project' || to.kind === 'Project')
|
|
@@ -33,8 +38,8 @@ export function rankImpactFacts(facts, direct, anchorTerms, focus) {
|
|
|
33
38
|
adjacent.set(from.id, edges);
|
|
34
39
|
};
|
|
35
40
|
for (const fact of facts) {
|
|
36
|
-
connect(fact.subject, fact.object,
|
|
37
|
-
connect(fact.object, fact.subject,
|
|
41
|
+
connect(fact.subject, fact.object, cost(fact, true));
|
|
42
|
+
connect(fact.object, fact.subject, cost(fact, false));
|
|
38
43
|
}
|
|
39
44
|
const distance = new Map();
|
|
40
45
|
// Integer edge costs permit a bucket queue: O(edges + maximum path cost), without a heap dependency.
|
|
@@ -46,10 +51,8 @@ export function rankImpactFacts(facts, direct, anchorTerms, focus) {
|
|
|
46
51
|
(pending[cost] ??= []).push(id);
|
|
47
52
|
};
|
|
48
53
|
for (const fact of direct) {
|
|
49
|
-
const eligible = [fact.subject, fact.object].filter((node) => node.kind !== 'Project');
|
|
50
|
-
const matching = eligible.filter((node) => anchorTerms.some((term) => `${node.id} ${node.label}`.toLowerCase().includes(term)));
|
|
51
54
|
// Some adapters only identify an anchor through its citation. Keep those queries supported.
|
|
52
|
-
for (const node of
|
|
55
|
+
for (const node of signals.seedNodes(fact))
|
|
53
56
|
enqueue(node.id, 0);
|
|
54
57
|
}
|
|
55
58
|
for (let cost = 0; cost < pending.length; cost++) {
|
|
@@ -65,21 +68,12 @@ export function rankImpactFacts(facts, direct, anchorTerms, focus) {
|
|
|
65
68
|
const text = factSearchText(fact);
|
|
66
69
|
return {
|
|
67
70
|
fact,
|
|
68
|
-
proximity: directIds.has(fact.id) ? 0 : Math.min((distance.get(fact.subject.id) ?? Infinity) +
|
|
71
|
+
proximity: costs.get(fact) + (directIds.has(fact.id) ? 0 : Math.min((distance.get(fact.subject.id) ?? Infinity) + cost(fact, true), (distance.get(fact.object.id) ?? Infinity) + cost(fact, false))),
|
|
72
|
+
relationshipOrder: signals.relationshipOrder(fact),
|
|
73
|
+
contextOnly: signals.contextOnly(fact),
|
|
69
74
|
focus: focus.filter((term) => text.includes(term)).length,
|
|
70
75
|
tie: stableTie(fact),
|
|
71
76
|
};
|
|
72
77
|
});
|
|
73
|
-
|
|
74
|
-
const compare = (a, b) => b.focus - a.focus || lexical(a.tie, b.tie) || lexical(a.fact.id, b.fact.id);
|
|
75
|
-
rows.sort((a, b) => a.proximity - b.proximity || compare(a, b));
|
|
76
|
-
const counts = new Map();
|
|
77
|
-
const diverse = rows.map((row) => {
|
|
78
|
-
const seen = counts.get(row.fact.provenance.path) ?? 0;
|
|
79
|
-
counts.set(row.fact.provenance.path, seen + 1);
|
|
80
|
-
// Each additional fact from one source costs one ordinary edge. Details stay on later pages.
|
|
81
|
-
return { ...row, score: row.proximity + seen };
|
|
82
|
-
});
|
|
83
|
-
return diverse.sort((a, b) => a.score - b.score || compare(a, b))
|
|
84
|
-
.map(({ fact, score }) => ({ fact, score }));
|
|
78
|
+
return orderImpactRows(rows);
|
|
85
79
|
}
|
|
@@ -3,7 +3,7 @@ import { graphPredicates } from '@weftlet/core';
|
|
|
3
3
|
import { parseGraphPathsRequest } from '../graph/path-request.js';
|
|
4
4
|
export const graphPathsTool = {
|
|
5
5
|
name: 'graph.paths',
|
|
6
|
-
description: 'Explore simple cited paths between exact node IDs in an explicit saved snapshot.
|
|
6
|
+
description: 'Explore simple cited paths between exact node IDs in an explicit saved snapshot. Shortest-first traversal, prioritizing edges to the exact target; static paths are not proof of causality. Follow continuation with identical selectors; inspect depth/work limits and unexplored frontier. No hydration or model calls.',
|
|
7
7
|
inputSchema: {
|
|
8
8
|
type: 'object', additionalProperties: false, required: ['snapshotId', 'fromNodeId', 'toNodeId'],
|
|
9
9
|
properties: {
|
|
@@ -102,7 +102,7 @@ export function viewerScript() {
|
|
|
102
102
|
if (!nextPath.disabled) status.textContent += ' Continue to examine remaining branches.';
|
|
103
103
|
if (result.search.depthLimitReached) status.textContent += ' Depth limit reached; increase depth and restart.';
|
|
104
104
|
if (result.search.stopReason === 'search-limit') status.textContent += ' Narrow the selection or choose an intermediate node.';
|
|
105
|
-
status.textContent += ' Pending prefixes: ' + result.frontier.
|
|
105
|
+
status.textContent += ' Pending prefixes: ' + result.frontier.pendingCount + ' (' + result.frontier.omittedPending + ' examples omitted); depth-limited extensions: ' + result.frontier.depthLimited.count + '.';
|
|
106
106
|
search.value = ''; cluster.value = ''; document.getElementById('neighbors-only').checked = false;
|
|
107
107
|
update();
|
|
108
108
|
} catch (error) { clearPath(); status.textContent = error.message; update(); }
|
package/docs/1.0-WORK-QUEUE.md
CHANGED
|
@@ -21,6 +21,22 @@ strict SHACL/publication. [ADR 040](ADR-040-bounded-graph-io.md) tracks the hash
|
|
|
21
21
|
RDF/query and bounded-validation patch. Its public large-corpus lifecycle and hosted Linux/Windows checks
|
|
22
22
|
pass; patch publication and private acceptance remain separate steps. No 1.0 approval is implied.
|
|
23
23
|
|
|
24
|
+
Consumer follow-up: **0.7.1 is published**. The maintainer reports successful strict hydration,
|
|
25
|
+
persistence/reload and unchanged repeat of 561,777 facts / 174,710 nodes with all 18 cached
|
|
26
|
+
artifacts preserved. That capacity blocker is resolved in the reported run. B6b remains open:
|
|
27
|
+
known direct paths and specific worker `references`/`consumes` assertions were displaced outside
|
|
28
|
+
fixed retrieval budgets. [ADR 041](ADR-041-bounded-relationship-retrieval.md) tracks the bounded
|
|
29
|
+
query-order patch and its public regression; no extraction refresh is needed for that patch.
|
|
30
|
+
|
|
31
|
+
0.7.2 private replay: **direct-path acceptance is closed**; exact stored single-edge references
|
|
32
|
+
and calls surface at the original budget. Keep **one indirect-ranking ticket open**: retrieve
|
|
33
|
+
second-hop local references and legacy consumers without a saved call proof despite broad local
|
|
34
|
+
competition. Library share and file discovery improved, but neither private target reached the
|
|
35
|
+
first three 60-fact pages. Preserve extraction, authority, reachable totals and immutable evidence;
|
|
36
|
+
record public and private denominators separately. See the latest [validation record](VALIDATION.md).
|
|
37
|
+
The [ADR 042 patch](ADR-042-indirect-local-relationships.md) retrieves both exact public targets
|
|
38
|
+
on the first page with the same saved evidence; private acceptance still requires the original replay.
|
|
39
|
+
|
|
24
40
|
All three public 554,516-fact strict SHACL passes succeeded but took about 35–37 minutes each
|
|
25
41
|
in this cloud. This is a capacity result, not a 30-minute hydration qualification. B6b must record
|
|
26
42
|
full hydration and agent-query latency on the consumer workload as well as correctness.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# ADR 012: order impact evidence by proximity and source diversity
|
|
2
2
|
|
|
3
|
-
Status:
|
|
3
|
+
Status: historical v1 query heuristic. [ADR 041](ADR-041-bounded-relationship-retrieval.md)
|
|
4
|
+
records the v2 library-hub and relationship-priority revision. Neither is product policy or an evidence gate.
|
|
4
5
|
|
|
5
6
|
The self-repository evaluation found distractions connected through common imports such as
|
|
6
7
|
`node:fs/promises`. The previous ordering prioritized keyword counts, then Codex/document-link
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# ADR 030: bounded cited dependency paths
|
|
2
2
|
|
|
3
|
-
Status: B1b
|
|
4
|
-
|
|
3
|
+
Status: B1b shipped in 0.7.0. The query-order revision in [ADR 041](ADR-041-bounded-relationship-retrieval.md)
|
|
4
|
+
replaces depth-first enumeration; publication and consumer acceptance are recorded separately.
|
|
5
5
|
|
|
6
6
|
## Meaning and scope
|
|
7
7
|
|
|
@@ -18,8 +18,8 @@ An empty predicate list selects all relations; a nonempty list is an OR filter.
|
|
|
18
18
|
cited associations, not causality, compatible business obligations or behavior verification.
|
|
19
19
|
They preserve authority, review state, source citations and node variants on every returned fact.
|
|
20
20
|
|
|
21
|
-
Read the same lossless RDF/SPARQL projection as other queries.
|
|
22
|
-
100,000-fact projection ceiling
|
|
21
|
+
Read the same lossless RDF/SPARQL projection as other queries. The 0.7.1 streaming changes
|
|
22
|
+
removed the former 100,000-fact projection ceiling without truncating evidence. No model,
|
|
23
23
|
indexer, SHACL rerun or graph write is involved. Duplicate fact IDs and mismatched stored snapshot
|
|
24
24
|
IDs fail. Responses reuse coverage, scoped diagnostic and checkout/overlay-state helpers.
|
|
25
25
|
Coverage describes the page's supporting evidence, not a repository completion percentage;
|
|
@@ -28,9 +28,10 @@ in snapshot metadata. An exhausted search says nothing about excluded or unextra
|
|
|
28
28
|
|
|
29
29
|
## Enumeration, work and continuation
|
|
30
30
|
|
|
31
|
-
Use deterministic
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
Use deterministic breadth-first traversal. Within each adjacency list, edges ending at the
|
|
32
|
+
requested target precede other edges, followed by assertion ID order independent of locale.
|
|
33
|
+
Completed paths arrive in nondecreasing edge count; a known direct connection is considered
|
|
34
|
+
first even on a high-branching source. This is not relevance, causality or a preferred design.
|
|
34
35
|
|
|
35
36
|
Defaults are depth 8 (maximum 32), five paths per page (maximum 20) and 1,000 new candidate-edge
|
|
36
37
|
examinations per page (maximum 10,000). Every considered edge counts, including cycles and depth
|
|
@@ -40,10 +41,11 @@ candidate count. Adjacency sorts are O(E log E); the existing RDF projection als
|
|
|
40
41
|
There is no wall-clock latency guarantee.
|
|
41
42
|
|
|
42
43
|
Continuations bind the operation version, normalized selectors and page budgets, saved manifest,
|
|
43
|
-
actual facts and diagnostics. A cursor carries only a step offset, never an external
|
|
44
|
+
actual facts and diagnostics. A cursor carries only a step offset, never an external queue or
|
|
44
45
|
assertions. Bounded replay reconstructs state and verifies the offset is a valid page boundary.
|
|
45
|
-
Responses report replayed and new steps separately. Replay is at most the total ceiling
|
|
46
|
-
|
|
46
|
+
Responses report replayed and new steps separately. Replay is at most the total ceiling.
|
|
47
|
+
At most one queued prefix is allocated per examined edge (100,001 including the root); parent
|
|
48
|
+
links share path prefixes, whose depth is bounded by 32. This trades repeated CPU work for stateless continuation
|
|
47
49
|
without snapshot/cache writes or a large serialized queue. Tokens provide query consistency,
|
|
48
50
|
not authentication. Changing selectors, depth, budgets or saved evidence requires restarting.
|
|
49
51
|
Cumulative cost over many tiny pages can exceed one search's ceiling because replay is repeated;
|
|
@@ -53,8 +55,9 @@ The page includes only its completed paths and the union of their unchanged supp
|
|
|
53
55
|
Work-limited pages may be empty and still have a continuation. Returned path count is not a
|
|
54
56
|
count of all possible paths. A continuation can lead to a final empty page after dead ends/cycles.
|
|
55
57
|
|
|
56
|
-
Report
|
|
57
|
-
|
|
58
|
+
Report the exact pending-prefix count and up to 32 examples with fact-ID prefixes, next
|
|
59
|
+
candidate fact IDs and remaining adjacency-candidate counts. Report the omitted example count
|
|
60
|
+
explicitly. These are not counts of valid paths. Depth cuts retain a total count,
|
|
58
61
|
up to 20 concrete extension examples and an explicit omitted-example count. Frontier IDs refer
|
|
59
62
|
to saved assertions; use `graph.neighbors` at that node/snapshot to retrieve their full citations.
|
|
60
63
|
|
|
@@ -73,9 +76,9 @@ path controls use one result per page, 1,000 new examinations, selectable direct
|
|
|
73
76
|
and the same total ceiling. Changing selection resets continuation. Targets show exact IDs next
|
|
74
77
|
to labels. Each highlighted edge is an unchanged fact from that displayed pack.
|
|
75
78
|
|
|
76
|
-
The
|
|
77
|
-
|
|
78
|
-
|
|
79
|
+
The viewer and service share this deterministic enumeration; labels say "cited path".
|
|
80
|
+
ADR 041 separately revises `impact.scan` ranking; `graph.neighbors` is unchanged.
|
|
81
|
+
No extraction identity, semantic artifact/cache key,
|
|
79
82
|
snapshot format, dependency, rule policy or language support changes.
|
|
80
83
|
|
|
81
84
|
## Validation boundary
|
|
@@ -92,6 +95,6 @@ fresh installed CLI/MCP assets and continuation. Execute rendered viewer control
|
|
|
92
95
|
DOM test harness and compare every highlighted path with the RDF service; this is script and
|
|
93
96
|
projection parity, not interactive browser rendering or autonomous-agent usefulness evidence.
|
|
94
97
|
|
|
95
|
-
B1a/B1b mechanisms are implemented; qualification and live product usefulness remain B6.
|
|
96
|
-
|
|
97
|
-
|
|
98
|
+
B1a/B1b mechanisms are implemented; qualification and live product usefulness remain B6.
|
|
99
|
+
No backend replacement or business compatibility inference is implied by paths through the
|
|
100
|
+
existing evidence graph.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# ADR 041: useful relationships within bounded retrieval
|
|
2
|
+
|
|
3
|
+
Status: query-only patch; validation and publication status are recorded in VALIDATION.md.
|
|
4
|
+
Impact ordering is superseded by [ADR 042](ADR-042-indirect-local-relationships.md); path ordering remains in effect.
|
|
5
|
+
|
|
6
|
+
## Evidence and scope
|
|
7
|
+
|
|
8
|
+
The maintainer reports successful 0.7.1 hydration, strict validation, persistence/reload and
|
|
9
|
+
unchanged repeat on the consumer's 561,777-fact graph, preserving all 18 cached artifacts.
|
|
10
|
+
Two subsequent failures concern retrieval: a known direct path was displaced by deep branches,
|
|
11
|
+
and specific consumer assertions were displaced by standard-library references.
|
|
12
|
+
|
|
13
|
+
The consumer independently confirmed that the missing `references` and `consumes` assertions
|
|
14
|
+
exist in the same snapshot and are reachable in expansion round two. Their calculated balanced
|
|
15
|
+
positions were 24,801 and 69,207, outside three pages of 60 assertions at depth three. The
|
|
16
|
+
diagnostic reproduced all 180 original result IDs in order without fetching larger pages or
|
|
17
|
+
modifying evidence. This is ranking displacement for those assertions, not missing extraction.
|
|
18
|
+
No private source, artifact or prompt was imported into this repository.
|
|
19
|
+
|
|
20
|
+
## Path order
|
|
21
|
+
|
|
22
|
+
Replace fact-ID depth-first traversal with breadth-first traversal. Adjacency preparation places
|
|
23
|
+
edges closing on the exact target first, then sorts by fact ID. A known direct edge therefore
|
|
24
|
+
appears before unrelated branches consume the first page. All distinct simple paths and parallel
|
|
25
|
+
assertions remain eligible; no global visited-node pruning is introduced. Completed paths are
|
|
26
|
+
ordered by nondecreasing edge count, not business importance or causal confidence.
|
|
27
|
+
|
|
28
|
+
Retain the existing depth, page, candidate-step and cumulative work limits, including counted
|
|
29
|
+
cycle/depth-cut examinations. Graph loading/indexing is still outside the candidate-step budget.
|
|
30
|
+
The FIFO queue allocates at most one parent-linked prefix per examined edge, bounded by 100,001
|
|
31
|
+
including the root. Return exact pending counts, 32 pending-prefix examples and an explicit
|
|
32
|
+
omitted count; retain the existing bounded depth-cut examples. Stateless replay validates page
|
|
33
|
+
boundaries. `simple-evidence-paths-v2` rejects old cursors; the shared HTML engine uses the same
|
|
34
|
+
search. No full-graph completeness or latency guarantee is added.
|
|
35
|
+
|
|
36
|
+
## Impact order
|
|
37
|
+
|
|
38
|
+
Keep the reachable set, extraction, depth semantics and evidence-lane balancing unchanged.
|
|
39
|
+
The `local-relationships-diversity-v2` policy revises the existing weighted-distance/source
|
|
40
|
+
diversity heuristic:
|
|
41
|
+
|
|
42
|
+
- A citation-only match seeds local endpoints before unresolved symbol endpoints. Referencing a
|
|
43
|
+
common library symbol in a changed function must not make all its co-users distance-zero peers.
|
|
44
|
+
- Edges touching a `CodeSymbol` with `no-indexed-definition` cost at least eight, and assertions
|
|
45
|
+
touching such a symbol receive eight additional ordering points. Explicit node/label/native-symbol
|
|
46
|
+
anchor-text matches exempt that node. Missing definitions are not classified as proven libraries;
|
|
47
|
+
omitted repository code can also be unindexed. All those assertions remain retrievable.
|
|
48
|
+
- Allocate early slots within each provenance source to saved local `calls`, their exact cited
|
|
49
|
+
reference proofs, and legacy file-to-symbol consumers matching saved local callable identities.
|
|
50
|
+
Other cross-file references follow before local occurrence detail. Existing product intent,
|
|
51
|
+
queue/data contracts, validation and adapter assertions retain their ordinary category.
|
|
52
|
+
- Within these categories use distance, focus and stable semantic tie keys. Add the per-source
|
|
53
|
+
ordinal to the distance score, then retain the existing evidence-lane balancing among equal
|
|
54
|
+
scores. Distant relationships still pay distance; local variable repetition cannot consume
|
|
55
|
+
all of a file's early slots before its consumer relationship is considered.
|
|
56
|
+
|
|
57
|
+
These are explainable ordering signals, not business rules or authority changes. A file-level
|
|
58
|
+
`consumes` relationship still does not establish invocation; a saved static call does not prove
|
|
59
|
+
runtime execution. Explicit library-symbol queries remain supported. Pagination retains every
|
|
60
|
+
reachable assertion exactly once; old ranking cursors fail with restart instructions.
|
|
61
|
+
|
|
62
|
+
## Acceptance and compatibility
|
|
63
|
+
|
|
64
|
+
The frozen [public protocol](../evaluations/relationship-retrieval/protocol.md) uses three actual
|
|
65
|
+
TypeScript producer/queue/worker/test flows, real SCIP and call extraction, and deterministic
|
|
66
|
+
cited prose. It scores 36 specific calls, callsite references and legacy consumers separately
|
|
67
|
+
from 12-file discovery. The budget remains depth three, three pages of 60, all 540 assertions
|
|
68
|
+
in the denominator. Compare the same immutable saved snapshot and unchanged reachable counts.
|
|
69
|
+
Report standard-library share independently of the production unindexed-symbol heuristic.
|
|
70
|
+
|
|
71
|
+
Also check a 1,500-branch direct-edge case at 1,000 steps, every directed four-node graph against
|
|
72
|
+
an exhaustive path oracle, continuation/replay, incoming/both directions, authority/citation
|
|
73
|
+
preservation, shared viewer parity, explicit library queries and strict extraction/publication.
|
|
74
|
+
|
|
75
|
+
No extractor/assembly identity, semantic cache, persisted encoding, RDF constraints or snapshot
|
|
76
|
+
content changes. Existing 0.7.1 snapshots use the new ordering without hydration or model calls.
|
|
77
|
+
The 0.7.1 streaming/canonical-hash fixes remain intact. This public regression does not close
|
|
78
|
+
private consumer acceptance; TradePilot must retry the original cases with unchanged budgets.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# ADR 042: indirect local relationships under broad anchors
|
|
2
|
+
|
|
3
|
+
Status: query-only patch. Qualification and consumer status are recorded in VALIDATION.md.
|
|
4
|
+
Supersedes ADR 041's impact ordering; its shortest-first path search is unchanged.
|
|
5
|
+
|
|
6
|
+
## Evidence
|
|
7
|
+
|
|
8
|
+
The 0.7.2 private replay closes the direct-path report and confirms improved file discovery
|
|
9
|
+
and library share. It does **not** close relationship recall: two exact second-hop assertions
|
|
10
|
+
remain outside the original 180-fact budget despite zero hub penalty. One is a symbol reference
|
|
11
|
+
without a saved call proof; the other is a legacy file consumer. No extraction loss is reported.
|
|
12
|
+
|
|
13
|
+
The frozen [public regression](../evaluations/indirect-retrieval/protocol.md) independently
|
|
14
|
+
reproduces this shape with actual extraction, broad catalog anchors and 192 competing local
|
|
15
|
+
setup files. Both assertions exist and are reachable in round two. The baseline returns
|
|
16
|
+
178 provenance files but misses both assertions. Per-source diversity alone is insufficient.
|
|
17
|
+
|
|
18
|
+
## Decision
|
|
19
|
+
|
|
20
|
+
Use `local-relationship-waves-v3` ordering over the **unchanged reachable set**:
|
|
21
|
+
|
|
22
|
+
- Retain weighted graph distance and explicit-anchor exceptions from ADR 041. A saved cross-file
|
|
23
|
+
reference with an indexed definition receives the relationship category even without native
|
|
24
|
+
call proof. Do not change its predicate, confidence, authority or citations.
|
|
25
|
+
- Separate relationships by weighted distance (0, 1, 2, 3, 4–7, 8+) and predicate family
|
|
26
|
+
(`calls`, `references`, `consumes`, other). Each wave takes two assertions from each populated
|
|
27
|
+
code-relationship bucket and one from each other-relationship bucket. Distances 0–3 each get
|
|
28
|
+
turns so broad near-anchor competition cannot consume every turn before indirect evidence.
|
|
29
|
+
- Round-robin provenance sources **within** each bucket. Order each source by focus match,
|
|
30
|
+
distance and stable semantic tie key. Remove the unbounded per-source ordinal added to graph
|
|
31
|
+
distance in v2. All saved facts remain eligible, including repeated-source assertions.
|
|
32
|
+
- Local symbol occurrence/definition and project/file membership detail get a separate single
|
|
33
|
+
slot per wave. Unindexed-symbol and generic module-import context follow local evidence unless
|
|
34
|
+
explicitly queried. These are retrieval signals, not proof that an unindexed symbol is external.
|
|
35
|
+
- Give every assertion in a wave the same ordering score, then retain the query facade's existing
|
|
36
|
+
evidence-lane balancing. The score is now a wave number, not a distance-plus-diversity value.
|
|
37
|
+
Version continuation tokens and reject prior policies with instructions to restart the scan.
|
|
38
|
+
|
|
39
|
+
There are no consumer names, target IDs or corpus-specific file selectors in the scorer.
|
|
40
|
+
The fixed bucket proportions are a retrieval heuristic, not a universal relevance guarantee.
|
|
41
|
+
Larger or equally competitive buckets can still displace relevant assertions. Intent, contracts
|
|
42
|
+
and validation retain their evidence lanes; the returned page is not complete product coverage.
|
|
43
|
+
|
|
44
|
+
## Tradeoffs and boundaries
|
|
45
|
+
|
|
46
|
+
The same 9,038-fact saved public graph now returns the exact reference at position 17 and consumer
|
|
47
|
+
at 15. All 180 output slots remain in the denominator. Source diversity falls from 178 to 71 files;
|
|
48
|
+
that is an explicit tradeoff for relationship recall, not lost reachable evidence. Both facts
|
|
49
|
+
remain as originally stored, including omitted authority fields on the legacy consumer. The
|
|
50
|
+
reference still has no saved call proof; do not describe it as proven invocation or execution.
|
|
51
|
+
|
|
52
|
+
The existing 36-target call-backed regression and direct-path acceptance remain separate checks.
|
|
53
|
+
The private two-target ranking ticket stays open until the original queries are replayed at their
|
|
54
|
+
original budgets. Public success cannot establish the private result positions.
|
|
55
|
+
|
|
56
|
+
No extractor, assembly, semantic-cache, snapshot, persistence, RDF or strict-validation identity
|
|
57
|
+
changes. Existing snapshots can be queried immediately without hydration or model calls. The
|
|
58
|
+
0.7.1 capacity fix remains intact. The MCP path description is corrected to shortest-first with
|
|
59
|
+
exact-target priority, retaining its static-path/non-causality warning.
|
package/docs/RELEASING.md
CHANGED
|
@@ -202,14 +202,14 @@ Verify the matching public version in a fresh disposable project after publicati
|
|
|
202
202
|
|
|
203
203
|
```sh
|
|
204
204
|
npm init -y
|
|
205
|
-
npx --yes @weftlet/toolkit@0.7.
|
|
206
|
-
npx --yes @weftlet/toolkit@0.7.
|
|
205
|
+
npx --yes @weftlet/toolkit@0.7.3 init --yes
|
|
206
|
+
npx --yes @weftlet/toolkit@0.7.3 config validate
|
|
207
207
|
```
|
|
208
208
|
|
|
209
209
|
For local installation, use both prepared archives from the same reviewed release:
|
|
210
210
|
|
|
211
211
|
```sh
|
|
212
|
-
npm install --save-dev "/path/to/weftlet/.release/weftlet-core-0.7.
|
|
212
|
+
npm install --save-dev "/path/to/weftlet/.release/weftlet-core-0.7.3.tgz" "/path/to/weftlet/.release/weftlet-toolkit-0.7.3.tgz"
|
|
213
213
|
```
|
|
214
214
|
<!-- weftlet:release:end -->
|
|
215
215
|
|
package/docs/VALIDATION.md
CHANGED
|
@@ -1,5 +1,86 @@
|
|
|
1
1
|
# Validation evidence
|
|
2
2
|
|
|
3
|
+
## Indirect-ranking patch: public comparison, 2026-11-03
|
|
4
|
+
|
|
5
|
+
[ADR 042](ADR-042-indirect-local-relationships.md) and the
|
|
6
|
+
[frozen comparison](../evaluations/indirect-retrieval/README.md) cover the remaining query-only
|
|
7
|
+
ranking change. Actual TypeScript extraction produces both second-hop assertions without a
|
|
8
|
+
saved call proof for the reference. At unchanged depth three / 3 × 60 facts, their ranks move
|
|
9
|
+
from 3,704 / 1,760 to **17 / 15**. The 9,038 stored/reachable assertions and 150 direct matches
|
|
10
|
+
are unchanged. All 180 results remain in the denominator; source diversity changes from 178
|
|
11
|
+
to 71 files. The four saved evidence files retain exact bytes during the comparison. No private
|
|
12
|
+
source, semantic/model calls, new extraction or larger query budgets enter that comparison.
|
|
13
|
+
|
|
14
|
+
The prior 36-target call-backed regression and direct-path/exhaustive-oracle/viewer parity tests
|
|
15
|
+
pass locally. The MCP path description now reflects shortest-first traversal with exact-target
|
|
16
|
+
priority and retains the warning that static paths are not causality. Full release qualification
|
|
17
|
+
is recorded separately on the change PR. **Private two-target ranking acceptance stays open.**
|
|
18
|
+
Existing snapshots and caches need no refresh; impact continuation must restart after upgrading.
|
|
19
|
+
|
|
20
|
+
## 0.7.2 private replay: paths closed, indirect ranking open, 2026-11-03
|
|
21
|
+
|
|
22
|
+
The maintainer reports that the same saved endpoints now return two exact stored single-edge
|
|
23
|
+
paths (`references` and `calls`) on page one at outgoing depth three / 1,000 steps. The CLI and
|
|
24
|
+
fresh stdio MCP agree, and truncation/continuation remains truthful. **Close the direct-path
|
|
25
|
+
consumer report.** This establishes cited static paths, not exhaustive discovery or runtime causality.
|
|
26
|
+
|
|
27
|
+
The remaining ranking ticket concerns second-hop local `references` and legacy file `consumes`
|
|
28
|
+
assertions without a saved call whose target-occurrence proof cites the reference. Both still
|
|
29
|
+
exist and are reachable in expansion round two. Neither receives the unindexed-symbol penalty.
|
|
30
|
+
Do not invent a `calls` fact or change extraction to address this query-order finding.
|
|
31
|
+
|
|
32
|
+
On unchanged private inputs and budgets, 0.7.1 → 0.7.2 improves page-one file suggestion/source
|
|
33
|
+
citation from 11/12 to 12/12 and library assertions from 378/540 to 0/540. The two target
|
|
34
|
+
assertions remain absent from the first 180 PM results. Their calculated ranks improve from
|
|
35
|
+
24,801 / 69,207 to 23,052 / 3,447; v2 scores are 34 / 9, relationship-order values 1 / 0, and
|
|
36
|
+
22,791 / 3,295 assertions have strictly lower scores. The first 180 cover 158 provenance files.
|
|
37
|
+
These measurements implicate the interaction of distance, relationship category and source
|
|
38
|
+
diversity under broad local competition; they do not identify one scoring term as the sole cause.
|
|
39
|
+
|
|
40
|
+
The consumer reproduced all 180 CLI fact IDs in order, with 360 direct matches and 420,837
|
|
41
|
+
reachable assertions. All three queries retain their prior reachable counts. All 20 stored-file
|
|
42
|
+
fingerprints match; no rehydration, model calls or extra pages were used. This private two-target
|
|
43
|
+
case is distinct from the earlier public 36-relationship denominator, which remains valid for its
|
|
44
|
+
call-backed fixture. A new public regression must include broad anchors, many local competitor
|
|
45
|
+
files, and both exact second-hop assertions without call proof at depth three / 3 × 60 facts.
|
|
46
|
+
|
|
47
|
+
## 0.7.1 consumer follow-up and bounded retrieval patch, 2026-11-03
|
|
48
|
+
|
|
49
|
+
**Maintainer-reported consumer pass:** the published 0.7.1 toolkit hydrates, strictly validates,
|
|
50
|
+
persists and reloads TradePilot's 561,777 facts / 174,710 nodes. Unchanged repeat preserves the
|
|
51
|
+
snapshot and all 18 semantic artifacts. This closes the reported whole-string capacity blocker
|
|
52
|
+
for that workload; it is not general query-usefulness or official 1.0 acceptance.
|
|
53
|
+
|
|
54
|
+
**Maintainer-reported remaining defect:** a direct connection was absent from a work-limited
|
|
55
|
+
path page, and relevant worker `references`/`consumes` assertions were absent from three 60-fact
|
|
56
|
+
impact pages at depth three. A read-only consumer diagnostic independently reproduced all
|
|
57
|
+
180 query IDs and the 420,837 reachable count. Both assertions exist in that same snapshot,
|
|
58
|
+
are reached in expansion round two, and were ranked at 24,801 and 69,207. This establishes
|
|
59
|
+
ranking displacement for those assertions. No private source or graph was accessed here.
|
|
60
|
+
|
|
61
|
+
**Public patch evidence:** [ADR 041](ADR-041-bounded-relationship-retrieval.md) and the
|
|
62
|
+
[frozen comparison](../evaluations/relationship-retrieval/README.md) record query-only changes.
|
|
63
|
+
On the same strictly validated 15,549-fact public TypeScript snapshot, both policies retain
|
|
64
|
+
5,128 reachable assertions per case and the full 540 returned-assertion denominator. Expected
|
|
65
|
+
call, callsite-reference and legacy-consumer retrieval improves from **0/36 to 36/36**;
|
|
66
|
+
12/12 file discovery is unchanged. TypeScript standard-library references change from
|
|
67
|
+
450/540 to 0/540 on those bounded pages. Library facts remain stored/reachable, and explicit
|
|
68
|
+
library-symbol queries pass. Seven evidence files, including all three semantic artifacts,
|
|
69
|
+
retain their exact byte digests after rescoring. No hydration or model calls occur in comparison.
|
|
70
|
+
|
|
71
|
+
A fresh public extraction/strict-publication test passes with all 36 targets, exact repeated
|
|
72
|
+
page IDs and unchanged evidence bytes. The high-branching query-service regression returns the
|
|
73
|
+
same cited direct edge as impact.scan on page one at depth three, three paths and 1,000 steps,
|
|
74
|
+
with explicit pending/omitted frontier counts. Exhaustive four-node path and shared viewer
|
|
75
|
+
parity checks pass. Extraction/assembly identities, canonical hashing, storage and strict SHACL
|
|
76
|
+
constraints are unchanged. Old query cursors require restart; old snapshots need no refresh.
|
|
77
|
+
|
|
78
|
+
Exact-head release qualification and hosted platform results are recorded on
|
|
79
|
+
[PR 67](https://github.com/jchewitt/weftlet/pull/67); the evidence above records the local focused checks.
|
|
80
|
+
Private fixed-budget retrieval acceptance remains open; the public comparison is not a claim
|
|
81
|
+
about TradePilot's new result positions. Browser interaction and live provider quality retain
|
|
82
|
+
their existing separate validation status.
|
|
83
|
+
|
|
3
84
|
## 0.7.0 large-graph field blocker follow-up, 2026-11-02
|
|
4
85
|
|
|
5
86
|
Status: public capacity qualification and hosted Linux/Windows checks pass; patch release pending.
|
|
@@ -108,7 +108,7 @@
|
|
|
108
108
|
"destinationPath": "package.json",
|
|
109
109
|
"sourceSha256": "a575dbb2fed8c554b95e8e9b3e03a0c21cab1be7249860bbebc18e046b2ff78d",
|
|
110
110
|
"modified": true,
|
|
111
|
-
"destinationSha256": "
|
|
111
|
+
"destinationSha256": "f331a6f0f0f0183466e5a9bb97a856d66522417f3c357d2ff825f348ac0410c1"
|
|
112
112
|
},
|
|
113
113
|
{
|
|
114
114
|
"sourcePath": "tools/context-graph/packages/core/LICENSE",
|
|
@@ -129,7 +129,7 @@
|
|
|
129
129
|
"destinationPath": "packages/core/README.md",
|
|
130
130
|
"sourceSha256": "6044bf7b9a3dc793f41e2ff048546ed11938957d10a5b143eb1739ac4cd7477c",
|
|
131
131
|
"modified": true,
|
|
132
|
-
"destinationSha256": "
|
|
132
|
+
"destinationSha256": "b49357185e5c1cd44e76a77ba4134e70002eeb3399983a7d9e4dd737a9dad9d8"
|
|
133
133
|
},
|
|
134
134
|
{
|
|
135
135
|
"sourcePath": "tools/context-graph/packages/core/THIRD_PARTY_NOTICES.md",
|
|
@@ -143,7 +143,7 @@
|
|
|
143
143
|
"destinationPath": "packages/core/package.json",
|
|
144
144
|
"sourceSha256": "2a29066eb8452f22fafcb06bb035a84dda93c5705dba32aba600a1b7e5aaf19c",
|
|
145
145
|
"modified": true,
|
|
146
|
-
"destinationSha256": "
|
|
146
|
+
"destinationSha256": "afd324effa694d0f753d99be367434d1d3355eacfc68cc27813a5279267dbf94"
|
|
147
147
|
},
|
|
148
148
|
{
|
|
149
149
|
"sourcePath": "tools/context-graph/packages/core/src/core.ts",
|
|
@@ -388,14 +388,14 @@
|
|
|
388
388
|
"destinationPath": "src/graph/query.test.ts",
|
|
389
389
|
"sourceSha256": "ba07c52566da979fcbb451b0c0c99b466521993cb49415ff8b35df2b01d4ecaf",
|
|
390
390
|
"modified": true,
|
|
391
|
-
"destinationSha256": "
|
|
391
|
+
"destinationSha256": "4a87d3be19769dee26ffafc1b876d877f39dec921ffa89dcd011c7a3cfb9667e"
|
|
392
392
|
},
|
|
393
393
|
{
|
|
394
394
|
"sourcePath": "tools/context-graph/src/query.ts",
|
|
395
395
|
"destinationPath": "src/graph/query.ts",
|
|
396
396
|
"sourceSha256": "4d67f87ca660cefe9686fb5b775f86a997a25d539819ea81d321c8bd1e0aaa39",
|
|
397
397
|
"modified": true,
|
|
398
|
-
"destinationSha256": "
|
|
398
|
+
"destinationSha256": "8c13b32499f0b830cd02bfc281c37c32fd6387aa3b98a325e6a60d3706b64528"
|
|
399
399
|
},
|
|
400
400
|
{
|
|
401
401
|
"sourcePath": "tools/context-graph/src/request.test.ts",
|
|
@@ -634,6 +634,8 @@
|
|
|
634
634
|
"docs/ADR-038-monorepo-code-coverage.md",
|
|
635
635
|
"docs/ADR-039-mapping-proposals.md",
|
|
636
636
|
"docs/ADR-040-bounded-graph-io.md",
|
|
637
|
+
"docs/ADR-041-bounded-relationship-retrieval.md",
|
|
638
|
+
"docs/ADR-042-indirect-local-relationships.md",
|
|
637
639
|
"docs/CLOUD-ENVIRONMENT.md",
|
|
638
640
|
"docs/CONSUMER-TRIAL.md",
|
|
639
641
|
"docs/ENVIRONMENT-VALIDATION.md",
|
|
@@ -747,6 +749,10 @@
|
|
|
747
749
|
"evaluations/dispatch/routing-baseline.json",
|
|
748
750
|
"evaluations/dispatch/routing-protocol.md",
|
|
749
751
|
"evaluations/dispatch/routing.config.json",
|
|
752
|
+
"evaluations/indirect-retrieval/README.md",
|
|
753
|
+
"evaluations/indirect-retrieval/baseline.json",
|
|
754
|
+
"evaluations/indirect-retrieval/candidate.json",
|
|
755
|
+
"evaluations/indirect-retrieval/protocol.md",
|
|
750
756
|
"evaluations/mapping-gaps/README.md",
|
|
751
757
|
"evaluations/mapping-gaps/inputs.lock.json",
|
|
752
758
|
"evaluations/mapping-gaps/project/.gitattributes",
|
|
@@ -779,6 +785,10 @@
|
|
|
779
785
|
"evaluations/mapping-proposals/inputs.lock.json",
|
|
780
786
|
"evaluations/mapping-proposals/protocol.json",
|
|
781
787
|
"evaluations/monorepo-coverage/README.md",
|
|
788
|
+
"evaluations/relationship-retrieval/README.md",
|
|
789
|
+
"evaluations/relationship-retrieval/baseline.json",
|
|
790
|
+
"evaluations/relationship-retrieval/candidate.json",
|
|
791
|
+
"evaluations/relationship-retrieval/protocol.md",
|
|
782
792
|
"evaluations/static-calls/README.md",
|
|
783
793
|
"evaluations/static-calls/results/2026-10-29.json",
|
|
784
794
|
"evaluations/weftlet/baseline.json",
|
|
@@ -867,6 +877,8 @@
|
|
|
867
877
|
"scripts/evaluation/score.ts",
|
|
868
878
|
"scripts/git-content.d.mts",
|
|
869
879
|
"scripts/git-content.mjs",
|
|
880
|
+
"scripts/indirect-retrieval-study/measure.ts",
|
|
881
|
+
"scripts/indirect-retrieval-study/run.ts",
|
|
870
882
|
"scripts/inventory.test.ts",
|
|
871
883
|
"scripts/large-graph/lifecycle.ts",
|
|
872
884
|
"scripts/large-graph/run.ts",
|
|
@@ -894,6 +906,8 @@
|
|
|
894
906
|
"scripts/release-records.test.ts",
|
|
895
907
|
"scripts/release.mjs",
|
|
896
908
|
"scripts/restore-publication-state.mjs",
|
|
909
|
+
"scripts/retrieval-study/preservation.ts",
|
|
910
|
+
"scripts/retrieval-study/run.ts",
|
|
897
911
|
"scripts/smoke-mapping-proposals.mjs",
|
|
898
912
|
"scripts/smoke-traversal.mjs",
|
|
899
913
|
"scripts/update-inventory.mjs",
|
|
@@ -1012,6 +1026,9 @@
|
|
|
1012
1026
|
"src/graph/evidence-description.ts",
|
|
1013
1027
|
"src/graph/identity-preflight.test.ts",
|
|
1014
1028
|
"src/graph/identity-preflight.ts",
|
|
1029
|
+
"src/graph/impact-order.test.ts",
|
|
1030
|
+
"src/graph/impact-order.ts",
|
|
1031
|
+
"src/graph/impact-signals.ts",
|
|
1015
1032
|
"src/graph/neighborhood-renderer.ts",
|
|
1016
1033
|
"src/graph/neighborhood-request.ts",
|
|
1017
1034
|
"src/graph/neighborhood.test.ts",
|
|
@@ -1090,11 +1107,13 @@
|
|
|
1090
1107
|
"tests/fixtures/code-evidence-project.ts",
|
|
1091
1108
|
"tests/fixtures/compatibility-cases.ts",
|
|
1092
1109
|
"tests/fixtures/compatibility-project.ts",
|
|
1110
|
+
"tests/fixtures/indirect-retrieval-project.ts",
|
|
1093
1111
|
"tests/fixtures/large-typescript-project.ts",
|
|
1094
1112
|
"tests/fixtures/mapping-project.ts",
|
|
1095
1113
|
"tests/fixtures/monorepo-project.ts",
|
|
1096
1114
|
"tests/fixtures/obligation-project.ts",
|
|
1097
1115
|
"tests/fixtures/rdf-070-reference.ts",
|
|
1116
|
+
"tests/fixtures/relationship-retrieval-project.ts",
|
|
1098
1117
|
"tests/fixtures/shacl.ts",
|
|
1099
1118
|
"tests/fixtures/static-call-project.ts",
|
|
1100
1119
|
"tests/fixtures/symbol-bindings.ts",
|
|
@@ -1103,6 +1122,7 @@
|
|
|
1103
1122
|
"tests/hydration-plan.test.ts",
|
|
1104
1123
|
"tests/identity-preflight.test.ts",
|
|
1105
1124
|
"tests/implementation-coverage.test.ts",
|
|
1125
|
+
"tests/indirect-retrieval.test.ts",
|
|
1106
1126
|
"tests/large-graph-lifecycle.test.ts",
|
|
1107
1127
|
"tests/mapping-proposals.test.ts",
|
|
1108
1128
|
"tests/module-boundaries.test.ts",
|
|
@@ -1111,6 +1131,7 @@
|
|
|
1111
1131
|
"tests/rdf-ontology.test.ts",
|
|
1112
1132
|
"tests/rdf-scaling-parity.test.ts",
|
|
1113
1133
|
"tests/rdf.test.ts",
|
|
1134
|
+
"tests/relationship-retrieval.test.ts",
|
|
1114
1135
|
"tests/routing.test.ts",
|
|
1115
1136
|
"tests/runtime.test.ts",
|
|
1116
1137
|
"tests/semantic-cache-reuse.test.ts",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@weftlet/toolkit",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.3",
|
|
4
4
|
"description": "Evidence-backed context graphs for AI development agents: product intent, contracts, code, tests and runtime behavior",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"rdf-validate-shacl": "0.6.5",
|
|
67
67
|
"sparqljs": "3.7.4",
|
|
68
68
|
"typescript": "5.5.4",
|
|
69
|
-
"@weftlet/core": "^0.7.
|
|
69
|
+
"@weftlet/core": "^0.7.3"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@changesets/cli": "3.0.3",
|
|
@@ -121,6 +121,7 @@
|
|
|
121
121
|
"release:prepare": "pnpm context-graph:publication-check && node scripts/release.mjs --prepare",
|
|
122
122
|
"release:publish": "node scripts/release.mjs --publish",
|
|
123
123
|
"govern": "tsx src/cli.ts govern --policy architecture.policy.json --output .context-graph/architecture-report.json",
|
|
124
|
+
"evaluate:retrieval": "tsx scripts/retrieval-study/run.ts",
|
|
124
125
|
"evaluate:impact": "tsx scripts/evaluation/run.ts",
|
|
125
126
|
"evaluate:code:check": "node scripts/code-graph-study/check.mjs",
|
|
126
127
|
"benchmark:shacl": "node scripts/benchmark-shacl.mjs",
|
|
@@ -130,6 +131,7 @@
|
|
|
130
131
|
"benchmark:validation": "node scripts/validation-benchmark/run.mjs",
|
|
131
132
|
"evaluate:mappings": "tsx scripts/mapping-study/run.ts",
|
|
132
133
|
"evaluate:calls": "tsx scripts/call-study/run.ts",
|
|
133
|
-
"evaluate:proposals": "tsx scripts/mapping-proposal-study/run.ts"
|
|
134
|
+
"evaluate:proposals": "tsx scripts/mapping-proposal-study/run.ts",
|
|
135
|
+
"evaluate:indirect": "tsx scripts/indirect-retrieval-study/run.ts"
|
|
134
136
|
}
|
|
135
137
|
}
|