@weftlet/toolkit 0.6.1 → 0.7.1
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 +191 -18
- package/THIRD_PARTY_NOTICES.md +3 -1
- package/dist/application/application.d.ts +10 -0
- package/dist/application/application.js +20 -0
- package/dist/application/document-code-bindings.d.ts +11 -0
- package/dist/application/document-code-bindings.js +25 -0
- package/dist/application/document-obligations.d.ts +8 -0
- package/dist/application/document-obligations.js +11 -0
- package/dist/application/draft-facts.d.ts +3 -0
- package/dist/application/draft-facts.js +37 -0
- package/dist/application/extraction-identity.d.ts +2 -2
- package/dist/application/extraction-identity.js +7 -1
- package/dist/application/extractor-results.d.ts +6 -0
- package/dist/application/extractor-results.js +6 -0
- package/dist/application/hydrator.js +38 -18
- package/dist/application/mapping-proposals.d.ts +108 -0
- package/dist/application/mapping-proposals.js +142 -0
- package/dist/application/mapping-service.d.ts +2 -0
- package/dist/application/mapping-service.js +5 -0
- package/dist/application/overlay.js +43 -29
- package/dist/application/saved-code-coverage.d.ts +40 -0
- package/dist/application/saved-code-coverage.js +20 -0
- package/dist/application/saved-compatibility.d.ts +38 -0
- package/dist/application/saved-compatibility.js +20 -0
- package/dist/application/saved-evidence.d.ts +17 -11
- package/dist/application/saved-evidence.js +44 -40
- package/dist/application/saved-exploration.d.ts +57 -0
- package/dist/application/saved-exploration.js +21 -0
- package/dist/application/saved-paths.d.ts +58 -0
- package/dist/application/saved-paths.js +20 -0
- package/dist/application/semantic-run.d.ts +1 -1
- package/dist/extraction/call-syntax.d.ts +18 -0
- package/dist/extraction/call-syntax.js +61 -0
- package/dist/extraction/canonical-document-links.d.ts +5 -1
- package/dist/extraction/canonical-document-links.js +4 -4
- package/dist/extraction/code-inventory.d.ts +6 -0
- package/dist/extraction/code-inventory.js +26 -0
- package/dist/extraction/document-code-bindings.d.ts +14 -0
- package/dist/extraction/document-code-bindings.js +121 -0
- package/dist/extraction/document-obligations.d.ts +12 -0
- package/dist/extraction/document-obligations.js +112 -0
- package/dist/extraction/mapping-candidates.d.ts +13 -0
- package/dist/extraction/mapping-candidates.js +46 -0
- package/dist/extraction/mapping-output.d.ts +75 -0
- package/dist/extraction/mapping-output.js +53 -0
- package/dist/extraction/mapping-plan.d.ts +7 -0
- package/dist/extraction/mapping-plan.js +117 -0
- package/dist/extraction/mapping-prompt.d.ts +2 -0
- package/dist/extraction/mapping-prompt.js +17 -0
- package/dist/extraction/mapping-provider.d.ts +15 -0
- package/dist/extraction/mapping-provider.js +60 -0
- package/dist/extraction/mapping-request.d.ts +3 -0
- package/dist/extraction/mapping-request.js +32 -0
- package/dist/extraction/ontology.d.ts +2 -0
- package/dist/extraction/ontology.js +28 -13
- package/dist/extraction/routing.js +5 -20
- package/dist/extraction/scip-occurrences.d.ts +3 -0
- package/dist/extraction/scip-occurrences.js +102 -0
- package/dist/extraction/scip-ranges.d.ts +6 -0
- package/dist/extraction/scip-ranges.js +31 -0
- package/dist/extraction/scip-runtime.d.ts +39 -0
- package/dist/extraction/scip-runtime.js +8 -0
- package/dist/extraction/scip-symbols.d.ts +21 -0
- package/dist/extraction/scip-symbols.js +91 -0
- package/dist/extraction/semantic.d.ts +1 -1
- package/dist/extraction/semantic.js +5 -17
- package/dist/extraction/static-calls.d.ts +10 -0
- package/dist/extraction/static-calls.js +133 -0
- package/dist/extraction/static.d.ts +3 -20
- package/dist/extraction/static.js +8 -84
- package/dist/extraction/symbol-resolution.d.ts +12 -0
- package/dist/extraction/symbol-resolution.js +51 -0
- package/dist/extraction/symbol-selectors.d.ts +11 -0
- package/dist/extraction/symbol-selectors.js +51 -0
- package/dist/graph/binding-rdf.d.ts +7 -0
- package/dist/graph/binding-rdf.js +109 -0
- package/dist/graph/call-rdf.d.ts +4 -0
- package/dist/graph/call-rdf.js +94 -0
- package/dist/graph/call-shapes.d.ts +2 -0
- package/dist/graph/call-shapes.js +28 -0
- package/dist/graph/code-coverage-projection.d.ts +9 -0
- package/dist/graph/code-coverage-projection.js +117 -0
- package/dist/graph/code-coverage-renderer.d.ts +2 -0
- package/dist/graph/code-coverage-renderer.js +15 -0
- package/dist/graph/code-coverage-request.d.ts +6 -0
- package/dist/graph/code-coverage-request.js +19 -0
- package/dist/graph/code-coverage.d.ts +6 -0
- package/dist/graph/code-coverage.js +54 -0
- package/dist/graph/code-description.d.ts +4 -0
- package/dist/graph/code-description.js +24 -0
- package/dist/graph/code-rdf.d.ts +6 -0
- package/dist/graph/code-rdf.js +79 -0
- package/dist/graph/compatibility-context.d.ts +2 -0
- package/dist/graph/compatibility-context.js +18 -0
- package/dist/graph/compatibility-renderer.d.ts +2 -0
- package/dist/graph/compatibility-renderer.js +45 -0
- package/dist/graph/compatibility-request.d.ts +3 -0
- package/dist/graph/compatibility-request.js +18 -0
- package/dist/graph/compatibility.d.ts +7 -0
- package/dist/graph/compatibility.js +67 -0
- package/dist/graph/constraint-comparison.d.ts +7 -0
- package/dist/graph/constraint-comparison.js +49 -0
- package/dist/graph/coverage.d.ts +2 -2
- package/dist/graph/coverage.js +8 -3
- package/dist/graph/diagnostics.d.ts +1 -1
- package/dist/graph/diagnostics.js +10 -6
- package/dist/graph/evidence-description.d.ts +3 -0
- package/dist/graph/evidence-description.js +13 -0
- package/dist/graph/identity-preflight.js +1 -1
- package/dist/graph/neighborhood-renderer.d.ts +2 -0
- package/dist/graph/neighborhood-renderer.js +38 -0
- package/dist/graph/neighborhood-request.d.ts +9 -0
- package/dist/graph/neighborhood-request.js +37 -0
- package/dist/graph/neighborhood.d.ts +8 -0
- package/dist/graph/neighborhood.js +100 -0
- package/dist/graph/obligation-rdf.d.ts +5 -0
- package/dist/graph/obligation-rdf.js +67 -0
- package/dist/graph/obligation-shapes.d.ts +2 -0
- package/dist/graph/obligation-shapes.js +32 -0
- package/dist/graph/partitioned-shacl.d.ts +14 -0
- package/dist/graph/partitioned-shacl.js +66 -0
- package/dist/graph/path-request.d.ts +11 -0
- package/dist/graph/path-request.js +24 -0
- package/dist/graph/path-search.d.ts +45 -0
- package/dist/graph/path-search.js +101 -0
- package/dist/graph/paths-renderer.d.ts +2 -0
- package/dist/graph/paths-renderer.js +36 -0
- package/dist/graph/paths.d.ts +7 -0
- package/dist/graph/paths.js +74 -0
- package/dist/graph/query.js +23 -6
- package/dist/graph/rdf-partitions.d.ts +24 -0
- package/dist/graph/rdf-partitions.js +170 -0
- package/dist/graph/rdf-projection.d.ts +7 -0
- package/dist/graph/rdf-projection.js +27 -0
- package/dist/graph/rdf-records.d.ts +12 -0
- package/dist/graph/rdf-records.js +90 -0
- package/dist/graph/rdf.d.ts +10 -10
- package/dist/graph/rdf.js +84 -89
- package/dist/graph/shacl-shapes.js +70 -0
- package/dist/graph/snapshot-context.d.ts +3 -0
- package/dist/graph/snapshot-context.js +8 -0
- package/dist/graph/validation-progress.d.ts +4 -1
- package/dist/index.d.ts +23 -0
- package/dist/index.js +22 -0
- package/dist/infrastructure/json-digest.d.ts +3 -0
- package/dist/infrastructure/json-digest.js +3 -0
- package/dist/infrastructure/unique-json.d.ts +2 -0
- package/dist/infrastructure/unique-json.js +20 -0
- package/dist/interfaces/cli.js +33 -1
- package/dist/interfaces/code-coverage.d.ts +46 -0
- package/dist/interfaces/code-coverage.js +18 -0
- package/dist/interfaces/graph-compatibility.d.ts +35 -0
- package/dist/interfaces/graph-compatibility.js +21 -0
- package/dist/interfaces/graph-exploration.d.ts +59 -0
- package/dist/interfaces/graph-exploration.js +27 -0
- package/dist/interfaces/graph-paths.d.ts +77 -0
- package/dist/interfaces/graph-paths.js +31 -0
- package/dist/interfaces/graph-query-args.d.ts +2 -0
- package/dist/interfaces/graph-query-args.js +25 -0
- package/dist/interfaces/mapping-proposals.d.ts +204 -0
- package/dist/interfaces/mapping-proposals.js +74 -0
- package/dist/interfaces/mcp.js +31 -3
- package/dist/storage/mapping-proposals.d.ts +9 -0
- package/dist/storage/mapping-proposals.js +42 -0
- package/dist/storage/storage.d.ts +3 -0
- package/dist/storage/storage.js +37 -13
- package/dist/storage/streaming-json.d.ts +5 -0
- package/dist/storage/streaming-json.js +45 -0
- package/dist/visualization/evidence-sources.d.ts +6 -0
- package/dist/visualization/evidence-sources.js +19 -0
- package/dist/visualization/viewer-interaction.d.ts +5 -8
- package/dist/visualization/viewer-interaction.js +46 -44
- package/dist/visualization/visualization.js +14 -5
- package/docs/1.0-WORK-QUEUE.md +48 -0
- package/docs/ADR-029-exact-graph-neighborhoods.md +70 -0
- package/docs/ADR-030-bounded-evidence-paths.md +97 -0
- package/docs/ADR-031-code-extractor-selection.md +91 -0
- package/docs/ADR-032-scip-code-evidence.md +73 -0
- package/docs/ADR-033-document-symbol-bindings.md +83 -0
- package/docs/ADR-034-mapping-gaps.md +80 -0
- package/docs/ADR-035-static-call-evidence.md +78 -0
- package/docs/ADR-036-contract-obligation-declarations.md +124 -0
- package/docs/ADR-037-selected-contract-compatibility.md +93 -0
- package/docs/ADR-038-monorepo-code-coverage.md +105 -0
- package/docs/ADR-039-mapping-proposals.md +119 -0
- package/docs/ADR-040-bounded-graph-io.md +90 -0
- package/docs/GRAPHIFY-EVALUATION.md +21 -4
- package/docs/PRE-1.0-BASELINE.md +49 -2
- package/docs/RELEASE-1.0-PLAN.md +14 -2
- package/docs/RELEASING.md +3 -3
- package/docs/ROADMAP.md +27 -6
- package/docs/VALIDATION.md +521 -14
- package/docs/benchmarks/large-graph-2026-11-02/result.json +156 -0
- package/docs/extraction-manifest.json +266 -23
- package/package.json +10 -4
- package/templates/context-graph-development/SKILL.md +30 -1
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { renderCodeCoverage } from '../graph/code-coverage-renderer.js';
|
|
2
|
+
import { inspectSavedEvidence } from './saved-evidence.js';
|
|
3
|
+
export class SavedCodeCoverageService {
|
|
4
|
+
queries;
|
|
5
|
+
repository;
|
|
6
|
+
configurationDigest;
|
|
7
|
+
expectedExtractors;
|
|
8
|
+
constructor(queries, repository, configurationDigest, expectedExtractors) {
|
|
9
|
+
this.queries = queries;
|
|
10
|
+
this.repository = repository;
|
|
11
|
+
this.configurationDigest = configurationDigest;
|
|
12
|
+
this.expectedExtractors = expectedExtractors;
|
|
13
|
+
}
|
|
14
|
+
async coverage(request) {
|
|
15
|
+
const report = await this.queries.coverage(request);
|
|
16
|
+
const evidenceState = await inspectSavedEvidence(report.snapshot, this.repository, this.configurationDigest, this.expectedExtractors);
|
|
17
|
+
const result = { ...report, evidenceState };
|
|
18
|
+
return { ...result, markdown: renderCodeCoverage(result) };
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ContractCompatibilityRequest, ContractCompatibilityService } from '@weftlet/core';
|
|
2
|
+
import type { GitRepository } from '../repository/git.js';
|
|
3
|
+
export declare class SavedContractCompatibilityService implements ContractCompatibilityService {
|
|
4
|
+
private readonly queries;
|
|
5
|
+
private readonly repository;
|
|
6
|
+
private readonly configurationDigest;
|
|
7
|
+
private readonly expectedExtractors?;
|
|
8
|
+
constructor(queries: ContractCompatibilityService, repository: GitRepository, configurationDigest: string, expectedExtractors?: Readonly<Record<string, string>> | undefined);
|
|
9
|
+
assess(request: ContractCompatibilityRequest): Promise<{
|
|
10
|
+
markdown: string;
|
|
11
|
+
evidenceState: {
|
|
12
|
+
readonly currentCommit?: string;
|
|
13
|
+
readonly excludedWorkingChanges: readonly string[];
|
|
14
|
+
readonly capturedWorkingChanges?: readonly string[];
|
|
15
|
+
readonly changedSinceCapture?: readonly string[];
|
|
16
|
+
readonly overlayFreshness?: "current" | "stale" | "unknown";
|
|
17
|
+
readonly stale: boolean;
|
|
18
|
+
readonly configurationMatches: boolean;
|
|
19
|
+
readonly extractionCompatible?: boolean;
|
|
20
|
+
readonly incompatibleExtractors?: readonly string[];
|
|
21
|
+
readonly eligibleForCurrentDiffValidation: false;
|
|
22
|
+
};
|
|
23
|
+
snapshot: import("@weftlet/core").ContextPack["snapshot"];
|
|
24
|
+
selection: ContractCompatibilityRequest;
|
|
25
|
+
facts: readonly import("@weftlet/core").GraphFact[];
|
|
26
|
+
coverage: import("@weftlet/core").ContextPack["coverage"];
|
|
27
|
+
assessment: import("@weftlet/core").ContractCompatibilityAssessment;
|
|
28
|
+
context: {
|
|
29
|
+
readonly contractNodeIds: readonly string[];
|
|
30
|
+
readonly endpointNodeIds: readonly string[];
|
|
31
|
+
readonly otherIncidentFacts: number;
|
|
32
|
+
readonly competingFactIds: readonly string[];
|
|
33
|
+
readonly competingFacts: number;
|
|
34
|
+
readonly omittedCompetingFacts: number;
|
|
35
|
+
};
|
|
36
|
+
diagnostics: import("@weftlet/core").DiagnosticReport;
|
|
37
|
+
}>;
|
|
38
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { renderContractCompatibility } from '../graph/compatibility-renderer.js';
|
|
2
|
+
import { inspectSavedEvidence } from './saved-evidence.js';
|
|
3
|
+
export class SavedContractCompatibilityService {
|
|
4
|
+
queries;
|
|
5
|
+
repository;
|
|
6
|
+
configurationDigest;
|
|
7
|
+
expectedExtractors;
|
|
8
|
+
constructor(queries, repository, configurationDigest, expectedExtractors) {
|
|
9
|
+
this.queries = queries;
|
|
10
|
+
this.repository = repository;
|
|
11
|
+
this.configurationDigest = configurationDigest;
|
|
12
|
+
this.expectedExtractors = expectedExtractors;
|
|
13
|
+
}
|
|
14
|
+
async assess(request) {
|
|
15
|
+
const report = await this.queries.assess(request);
|
|
16
|
+
const evidenceState = await inspectSavedEvidence(report.snapshot, this.repository, this.configurationDigest, this.expectedExtractors);
|
|
17
|
+
const result = { ...report, evidenceState };
|
|
18
|
+
return { ...result, markdown: renderContractCompatibility(result) };
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ImpactQueryService, ImpactScanRequest } from "@weftlet/core";
|
|
1
|
+
import type { ContextPack, ImpactQueryService, ImpactScanRequest } from "@weftlet/core";
|
|
2
2
|
import type { GitRepository } from "../repository/git.js";
|
|
3
3
|
/** Read-side metadata; never calls an indexer, model, compiler, or refresh operation. */
|
|
4
4
|
export declare class SavedEvidenceQueryService implements ImpactQueryService {
|
|
@@ -10,16 +10,16 @@ export declare class SavedEvidenceQueryService implements ImpactQueryService {
|
|
|
10
10
|
scan(request: ImpactScanRequest): Promise<{
|
|
11
11
|
markdown: string;
|
|
12
12
|
evidenceState: {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
13
|
+
readonly currentCommit?: string;
|
|
14
|
+
readonly excludedWorkingChanges: readonly string[];
|
|
15
|
+
readonly capturedWorkingChanges?: readonly string[];
|
|
16
|
+
readonly changedSinceCapture?: readonly string[];
|
|
17
|
+
readonly overlayFreshness?: "current" | "stale" | "unknown";
|
|
18
|
+
readonly stale: boolean;
|
|
19
|
+
readonly configurationMatches: boolean;
|
|
20
|
+
readonly extractionCompatible?: boolean;
|
|
21
|
+
readonly incompatibleExtractors?: readonly string[];
|
|
22
|
+
readonly eligibleForCurrentDiffValidation: false;
|
|
23
23
|
};
|
|
24
24
|
snapshot: Pick<import("@weftlet/core").SnapshotManifest, "snapshotId" | "commitSha" | "contentDigest" | "configurationDigest" | "scope" | "baseSha" | "overlayDigest" | "overlayCapture"> & Partial<Pick<import("@weftlet/core").SnapshotManifest, "extractorVersions" | "documentSelection">>;
|
|
25
25
|
capabilities: readonly import("@weftlet/core").GraphNode[];
|
|
@@ -31,6 +31,10 @@ export declare class SavedEvidenceQueryService implements ImpactQueryService {
|
|
|
31
31
|
diagnostics: import("@weftlet/core").DiagnosticReport;
|
|
32
32
|
exploration?: {
|
|
33
33
|
readonly rankingVersion?: string;
|
|
34
|
+
readonly codeTraversalVersion?: string;
|
|
35
|
+
readonly unexpandedCodeTargets?: readonly string[];
|
|
36
|
+
readonly unexpandedCodeTargetCount?: number;
|
|
37
|
+
readonly unexpandedCodeTargetsTruncated?: boolean;
|
|
34
38
|
readonly returned: number;
|
|
35
39
|
readonly reachableFacts: number;
|
|
36
40
|
readonly maxDepth: number;
|
|
@@ -40,3 +44,5 @@ export declare class SavedEvidenceQueryService implements ImpactQueryService {
|
|
|
40
44
|
};
|
|
41
45
|
}>;
|
|
42
46
|
}
|
|
47
|
+
/** Shared read-side state for impact scans and exact-node exploration. */
|
|
48
|
+
export declare function inspectSavedEvidence(snapshot: ContextPack['snapshot'], repository: GitRepository, configurationDigest: string, expectedExtractors?: Readonly<Record<string, string>>): Promise<NonNullable<ContextPack['evidenceState']>>;
|
|
@@ -16,50 +16,54 @@ export class SavedEvidenceQueryService {
|
|
|
16
16
|
}
|
|
17
17
|
async scan(request) {
|
|
18
18
|
const pack = await this.queries.scan(request);
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
19
|
+
const evidenceState = await inspectSavedEvidence(pack.snapshot, this.repository, this.configurationDigest, this.expectedExtractors);
|
|
20
|
+
const result = { ...pack, evidenceState };
|
|
21
|
+
return { ...result, markdown: new MarkdownContextPackRenderer().render(result) };
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/** Shared read-side state for impact scans and exact-node exploration. */
|
|
25
|
+
export async function inspectSavedEvidence(snapshot, repository, configurationDigest, expectedExtractors) {
|
|
26
|
+
const currentCommit = await repository.resolveRef('HEAD').catch(() => undefined);
|
|
27
|
+
const workingChanges = await repository.workingChanges();
|
|
28
|
+
const capturedWorkingChanges = [];
|
|
29
|
+
const changedSinceCapture = new Set();
|
|
30
|
+
let overlayFreshness;
|
|
31
|
+
if (snapshot.overlayDigest) {
|
|
32
|
+
overlayFreshness = 'unknown';
|
|
33
|
+
const capture = snapshot.overlayCapture;
|
|
34
|
+
if (capture) {
|
|
35
|
+
overlayFreshness = 'current';
|
|
36
|
+
for (const file of capture.files) {
|
|
37
|
+
try {
|
|
38
|
+
const content = await readWorkingContent(repository.root, file.path);
|
|
39
|
+
if ((content === null ? null : sha256(content)) === file.digest)
|
|
40
|
+
capturedWorkingChanges.push(file.path);
|
|
41
|
+
else
|
|
39
42
|
changedSinceCapture.add(file.path);
|
|
40
|
-
}
|
|
41
43
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
catch {
|
|
45
|
+
overlayFreshness = 'unknown';
|
|
46
|
+
changedSinceCapture.add(file.path);
|
|
45
47
|
}
|
|
46
|
-
if (changedSinceCapture.size && overlayFreshness !== 'unknown')
|
|
47
|
-
overlayFreshness = 'stale';
|
|
48
48
|
}
|
|
49
|
+
for (const path of workingChanges) {
|
|
50
|
+
if (!capturedWorkingChanges.includes(path) && inWorkingScope(path, capture.sourcePatterns))
|
|
51
|
+
changedSinceCapture.add(path);
|
|
52
|
+
}
|
|
53
|
+
if (changedSinceCapture.size && overlayFreshness !== 'unknown')
|
|
54
|
+
overlayFreshness = 'stale';
|
|
49
55
|
}
|
|
50
|
-
const excludedWorkingChanges = workingChanges.filter((path) => !capturedWorkingChanges.includes(path));
|
|
51
|
-
const incompatibleExtractors = this.expectedExtractors
|
|
52
|
-
? incompatibleSnapshotExtractors(pack.snapshot.extractorVersions, this.expectedExtractors) : undefined;
|
|
53
|
-
const evidenceState = {
|
|
54
|
-
currentCommit,
|
|
55
|
-
excludedWorkingChanges,
|
|
56
|
-
...(overlayFreshness ? { overlayFreshness, capturedWorkingChanges, changedSinceCapture: [...changedSinceCapture].sort() } : {}),
|
|
57
|
-
stale: currentCommit !== pack.snapshot.commitSha || (overlayFreshness !== undefined && overlayFreshness !== 'current'),
|
|
58
|
-
configurationMatches: pack.snapshot.configurationDigest === this.configurationDigest,
|
|
59
|
-
...(incompatibleExtractors ? { extractionCompatible: incompatibleExtractors.length === 0, incompatibleExtractors } : {}),
|
|
60
|
-
eligibleForCurrentDiffValidation: false,
|
|
61
|
-
};
|
|
62
|
-
const result = { ...pack, evidenceState };
|
|
63
|
-
return { ...result, markdown: new MarkdownContextPackRenderer().render(result) };
|
|
64
56
|
}
|
|
57
|
+
const excludedWorkingChanges = workingChanges.filter((path) => !capturedWorkingChanges.includes(path));
|
|
58
|
+
const incompatibleExtractors = expectedExtractors
|
|
59
|
+
? incompatibleSnapshotExtractors(snapshot.extractorVersions, expectedExtractors) : undefined;
|
|
60
|
+
return {
|
|
61
|
+
currentCommit,
|
|
62
|
+
excludedWorkingChanges,
|
|
63
|
+
...(overlayFreshness ? { overlayFreshness, capturedWorkingChanges, changedSinceCapture: [...changedSinceCapture].sort() } : {}),
|
|
64
|
+
stale: currentCommit !== snapshot.commitSha || (overlayFreshness !== undefined && overlayFreshness !== 'current'),
|
|
65
|
+
configurationMatches: snapshot.configurationDigest === configurationDigest,
|
|
66
|
+
...(incompatibleExtractors ? { extractionCompatible: incompatibleExtractors.length === 0, incompatibleExtractors } : {}),
|
|
67
|
+
eligibleForCurrentDiffValidation: false,
|
|
68
|
+
};
|
|
65
69
|
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { GraphExplorationService, GraphNeighborsRequest } from '@weftlet/core';
|
|
2
|
+
import type { GitRepository } from '../repository/git.js';
|
|
3
|
+
/** Adds checkout/overlay state without extracting, refreshing or changing a saved graph. */
|
|
4
|
+
export declare class SavedGraphExplorationService implements GraphExplorationService {
|
|
5
|
+
private readonly queries;
|
|
6
|
+
private readonly repository;
|
|
7
|
+
private readonly configurationDigest;
|
|
8
|
+
private readonly expectedExtractors?;
|
|
9
|
+
constructor(queries: GraphExplorationService, repository: GitRepository, configurationDigest: string, expectedExtractors?: Readonly<Record<string, string>> | undefined);
|
|
10
|
+
neighbors(request: GraphNeighborsRequest): Promise<{
|
|
11
|
+
markdown: string;
|
|
12
|
+
evidenceState: {
|
|
13
|
+
readonly currentCommit?: string;
|
|
14
|
+
readonly excludedWorkingChanges: readonly string[];
|
|
15
|
+
readonly capturedWorkingChanges?: readonly string[];
|
|
16
|
+
readonly changedSinceCapture?: readonly string[];
|
|
17
|
+
readonly overlayFreshness?: "current" | "stale" | "unknown";
|
|
18
|
+
readonly stale: boolean;
|
|
19
|
+
readonly configurationMatches: boolean;
|
|
20
|
+
readonly extractionCompatible?: boolean;
|
|
21
|
+
readonly incompatibleExtractors?: readonly string[];
|
|
22
|
+
readonly eligibleForCurrentDiffValidation: false;
|
|
23
|
+
};
|
|
24
|
+
snapshot: import("@weftlet/core").ContextPack["snapshot"];
|
|
25
|
+
focus: {
|
|
26
|
+
readonly nodeId: string;
|
|
27
|
+
readonly status: "present" | "absent-from-snapshot";
|
|
28
|
+
};
|
|
29
|
+
facts: readonly import("@weftlet/core").GraphFact[];
|
|
30
|
+
coverage: import("@weftlet/core").ContextPack["coverage"];
|
|
31
|
+
diagnostics: import("@weftlet/core").ContextPack["diagnostics"];
|
|
32
|
+
selection: {
|
|
33
|
+
readonly version: string;
|
|
34
|
+
readonly direction: import("@weftlet/core").GraphDirection;
|
|
35
|
+
readonly predicates: readonly import("@weftlet/core").GraphPredicate[];
|
|
36
|
+
readonly maxFacts: number;
|
|
37
|
+
readonly incidentFacts: number;
|
|
38
|
+
readonly matchingFacts: number;
|
|
39
|
+
readonly filteredFacts: number;
|
|
40
|
+
readonly offset: number;
|
|
41
|
+
readonly returnedFacts: number;
|
|
42
|
+
readonly remainingFacts: number;
|
|
43
|
+
readonly truncated: boolean;
|
|
44
|
+
readonly continuation?: string;
|
|
45
|
+
};
|
|
46
|
+
frontier: {
|
|
47
|
+
readonly scope: "selected-one-hop-neighborhood";
|
|
48
|
+
readonly totalNeighbors: number;
|
|
49
|
+
readonly remainingNeighbors: number;
|
|
50
|
+
readonly neighbors: readonly {
|
|
51
|
+
readonly nodeId: string;
|
|
52
|
+
readonly factIds: readonly string[];
|
|
53
|
+
readonly otherIncidentFacts: number;
|
|
54
|
+
}[];
|
|
55
|
+
};
|
|
56
|
+
}>;
|
|
57
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { renderGraphNeighborhood } from '../graph/neighborhood-renderer.js';
|
|
2
|
+
import { inspectSavedEvidence } from './saved-evidence.js';
|
|
3
|
+
/** Adds checkout/overlay state without extracting, refreshing or changing a saved graph. */
|
|
4
|
+
export class SavedGraphExplorationService {
|
|
5
|
+
queries;
|
|
6
|
+
repository;
|
|
7
|
+
configurationDigest;
|
|
8
|
+
expectedExtractors;
|
|
9
|
+
constructor(queries, repository, configurationDigest, expectedExtractors) {
|
|
10
|
+
this.queries = queries;
|
|
11
|
+
this.repository = repository;
|
|
12
|
+
this.configurationDigest = configurationDigest;
|
|
13
|
+
this.expectedExtractors = expectedExtractors;
|
|
14
|
+
}
|
|
15
|
+
async neighbors(request) {
|
|
16
|
+
const result = await this.queries.neighbors(request);
|
|
17
|
+
const evidenceState = await inspectSavedEvidence(result.snapshot, this.repository, this.configurationDigest, this.expectedExtractors);
|
|
18
|
+
const withState = { ...result, evidenceState };
|
|
19
|
+
return { ...withState, markdown: renderGraphNeighborhood(withState) };
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { GraphPathQueryService, GraphPathsRequest } from '@weftlet/core';
|
|
2
|
+
import type { GitRepository } from '../repository/git.js';
|
|
3
|
+
export declare class SavedGraphPathService implements GraphPathQueryService {
|
|
4
|
+
private readonly queries;
|
|
5
|
+
private readonly repository;
|
|
6
|
+
private readonly configurationDigest;
|
|
7
|
+
private readonly expectedExtractors?;
|
|
8
|
+
constructor(queries: GraphPathQueryService, repository: GitRepository, configurationDigest: string, expectedExtractors?: Readonly<Record<string, string>> | undefined);
|
|
9
|
+
paths(request: GraphPathsRequest): Promise<{
|
|
10
|
+
markdown: string;
|
|
11
|
+
evidenceState: {
|
|
12
|
+
readonly currentCommit?: string;
|
|
13
|
+
readonly excludedWorkingChanges: readonly string[];
|
|
14
|
+
readonly capturedWorkingChanges?: readonly string[];
|
|
15
|
+
readonly changedSinceCapture?: readonly string[];
|
|
16
|
+
readonly overlayFreshness?: "current" | "stale" | "unknown";
|
|
17
|
+
readonly stale: boolean;
|
|
18
|
+
readonly configurationMatches: boolean;
|
|
19
|
+
readonly extractionCompatible?: boolean;
|
|
20
|
+
readonly incompatibleExtractors?: readonly string[];
|
|
21
|
+
readonly eligibleForCurrentDiffValidation: false;
|
|
22
|
+
};
|
|
23
|
+
snapshot: import("@weftlet/core").ContextPack["snapshot"];
|
|
24
|
+
endpoints: {
|
|
25
|
+
readonly from: {
|
|
26
|
+
readonly nodeId: string;
|
|
27
|
+
readonly status: "present" | "absent-from-snapshot";
|
|
28
|
+
};
|
|
29
|
+
readonly to: {
|
|
30
|
+
readonly nodeId: string;
|
|
31
|
+
readonly status: "present" | "absent-from-snapshot";
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
paths: readonly import("@weftlet/core").EvidencePath[];
|
|
35
|
+
facts: readonly import("@weftlet/core").GraphFact[];
|
|
36
|
+
coverage: import("@weftlet/core").ContextPack["coverage"];
|
|
37
|
+
diagnostics: import("@weftlet/core").ContextPack["diagnostics"];
|
|
38
|
+
search: {
|
|
39
|
+
readonly version: string;
|
|
40
|
+
readonly order: "fact-id-depth-first";
|
|
41
|
+
readonly direction: import("@weftlet/core").GraphDirection;
|
|
42
|
+
readonly predicates: readonly import("@weftlet/core").GraphPredicate[];
|
|
43
|
+
readonly maxDepth: number;
|
|
44
|
+
readonly maxPaths: number;
|
|
45
|
+
readonly maxSteps: number;
|
|
46
|
+
readonly searchLimit: number;
|
|
47
|
+
readonly replayedSteps: number;
|
|
48
|
+
readonly examinedSteps: number;
|
|
49
|
+
readonly totalSteps: number;
|
|
50
|
+
readonly stopReason: "exhausted" | "path-page-limit" | "work-page-limit" | "search-limit";
|
|
51
|
+
readonly exhaustedWithinDepth: boolean;
|
|
52
|
+
readonly depthLimitReached: boolean;
|
|
53
|
+
readonly truncated: boolean;
|
|
54
|
+
readonly continuation?: string;
|
|
55
|
+
};
|
|
56
|
+
frontier: import("@weftlet/core").PathFrontier;
|
|
57
|
+
}>;
|
|
58
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { renderGraphPaths } from '../graph/paths-renderer.js';
|
|
2
|
+
import { inspectSavedEvidence } from './saved-evidence.js';
|
|
3
|
+
export class SavedGraphPathService {
|
|
4
|
+
queries;
|
|
5
|
+
repository;
|
|
6
|
+
configurationDigest;
|
|
7
|
+
expectedExtractors;
|
|
8
|
+
constructor(queries, repository, configurationDigest, expectedExtractors) {
|
|
9
|
+
this.queries = queries;
|
|
10
|
+
this.repository = repository;
|
|
11
|
+
this.configurationDigest = configurationDigest;
|
|
12
|
+
this.expectedExtractors = expectedExtractors;
|
|
13
|
+
}
|
|
14
|
+
async paths(request) {
|
|
15
|
+
const result = await this.queries.paths(request);
|
|
16
|
+
const evidenceState = await inspectSavedEvidence(result.snapshot, this.repository, this.configurationDigest, this.expectedExtractors);
|
|
17
|
+
const withState = { ...result, evidenceState };
|
|
18
|
+
return { ...withState, markdown: renderGraphPaths(withState) };
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -7,7 +7,7 @@ export interface HydrationProgressEvent {
|
|
|
7
7
|
readonly total?: number;
|
|
8
8
|
readonly sourceId?: string;
|
|
9
9
|
readonly elapsedMs?: number;
|
|
10
|
-
readonly status?: 'started' | 'completed' | 'failed';
|
|
10
|
+
readonly status?: 'started' | 'completed' | 'failed' | 'progress';
|
|
11
11
|
readonly factCount?: number;
|
|
12
12
|
readonly nodeCount?: number;
|
|
13
13
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
import type { GraphFact, SourceSpan } from '@weftlet/core';
|
|
3
|
+
export type Callable = ts.FunctionDeclaration | ts.FunctionExpression | ts.ArrowFunction | ts.MethodDeclaration | ts.GetAccessorDeclaration | ts.SetAccessorDeclaration | ts.ConstructorDeclaration;
|
|
4
|
+
export declare const isCallable: (node: ts.Node) => node is Callable;
|
|
5
|
+
export declare function callableName(node: Callable): ts.Node | undefined;
|
|
6
|
+
/** Ambient declarations may occur in .ts namespaces too; they supply no runtime body. */
|
|
7
|
+
export declare function isAmbient(node: ts.Node): boolean;
|
|
8
|
+
export declare function syntaxSpan(node: ts.Node, source: ts.SourceFile, digest: string, commitSha: string): SourceSpan;
|
|
9
|
+
export declare const positionKey: (span: SourceSpan) => string;
|
|
10
|
+
export declare function calleeToken(expression: ts.Expression): ts.Node | undefined;
|
|
11
|
+
export interface ParsedCallSource {
|
|
12
|
+
readonly source: ts.SourceFile;
|
|
13
|
+
readonly digest: string;
|
|
14
|
+
readonly byPosition: ReadonlyMap<string, readonly GraphFact[]>;
|
|
15
|
+
readonly parseErrors: readonly ts.Diagnostic[];
|
|
16
|
+
}
|
|
17
|
+
export declare function parseCallSource(path: string, text: string, digest: string, facts: readonly GraphFact[]): ParsedCallSource;
|
|
18
|
+
export declare function factsAt(node: ts.Node | undefined, parsed: ParsedCallSource, commitSha: string, role: 'definition' | 'reference'): GraphFact[];
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
export const isCallable = (node) => ts.isFunctionDeclaration(node) ||
|
|
3
|
+
ts.isFunctionExpression(node) || ts.isArrowFunction(node) || ts.isMethodDeclaration(node) ||
|
|
4
|
+
ts.isGetAccessorDeclaration(node) || ts.isSetAccessorDeclaration(node) || ts.isConstructorDeclaration(node);
|
|
5
|
+
export function callableName(node) {
|
|
6
|
+
if ('name' in node && node.name)
|
|
7
|
+
return node.name;
|
|
8
|
+
if (ts.isConstructorDeclaration(node))
|
|
9
|
+
return node.getFirstToken();
|
|
10
|
+
const parent = node.parent;
|
|
11
|
+
if ((ts.isVariableDeclaration(parent) || ts.isPropertyDeclaration(parent) || ts.isPropertyAssignment(parent)) &&
|
|
12
|
+
parent.initializer === node && (ts.isIdentifier(parent.name) || ts.isPrivateIdentifier(parent.name)))
|
|
13
|
+
return parent.name;
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
/** Ambient declarations may occur in .ts namespaces too; they supply no runtime body. */
|
|
17
|
+
export function isAmbient(node) {
|
|
18
|
+
if (node.getSourceFile().isDeclarationFile)
|
|
19
|
+
return true;
|
|
20
|
+
for (let current = node; current; current = current.parent) {
|
|
21
|
+
if (ts.canHaveModifiers(current) && ts.getModifiers(current)?.some(modifier => modifier.kind === ts.SyntaxKind.DeclareKeyword))
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
export function syntaxSpan(node, source, digest, commitSha) {
|
|
27
|
+
const start = source.getLineAndCharacterOfPosition(node.getStart(source));
|
|
28
|
+
const end = source.getLineAndCharacterOfPosition(node.getEnd());
|
|
29
|
+
return { path: source.fileName, startLine: start.line + 1, startColumn: start.character + 1,
|
|
30
|
+
endLine: end.line + 1, endColumn: end.character + 1, columnEncoding: 'utf-16', digest, commitSha };
|
|
31
|
+
}
|
|
32
|
+
export const positionKey = (span) => `${span.path}:${span.startLine}:${span.startColumn}:${span.endLine}:${span.endColumn}`;
|
|
33
|
+
export function calleeToken(expression) {
|
|
34
|
+
while (ts.isParenthesizedExpression(expression) || ts.isNonNullExpression(expression) ||
|
|
35
|
+
ts.isAsExpression(expression) || ts.isTypeAssertionExpression(expression) || ts.isSatisfiesExpression(expression))
|
|
36
|
+
expression = expression.expression;
|
|
37
|
+
if (ts.isIdentifier(expression) || expression.kind === ts.SyntaxKind.SuperKeyword)
|
|
38
|
+
return expression;
|
|
39
|
+
if (ts.isPropertyAccessExpression(expression))
|
|
40
|
+
return expression.name;
|
|
41
|
+
if (ts.isElementAccessExpression(expression) && ts.isStringLiteral(expression.argumentExpression))
|
|
42
|
+
return expression.argumentExpression;
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
export function parseCallSource(path, text, digest, facts) {
|
|
46
|
+
const source = ts.createSourceFile(path, text, ts.ScriptTarget.Latest, true, path.endsWith('.tsx') ? ts.ScriptKind.TSX : ts.ScriptKind.TS);
|
|
47
|
+
const byPosition = new Map();
|
|
48
|
+
for (const fact of facts) {
|
|
49
|
+
const key = positionKey(fact.provenance), group = byPosition.get(key) ?? [];
|
|
50
|
+
group.push(fact);
|
|
51
|
+
byPosition.set(key, group);
|
|
52
|
+
}
|
|
53
|
+
return { source, digest, byPosition,
|
|
54
|
+
parseErrors: source.parseDiagnostics };
|
|
55
|
+
}
|
|
56
|
+
export function factsAt(node, parsed, commitSha, role) {
|
|
57
|
+
if (!node)
|
|
58
|
+
return [];
|
|
59
|
+
return (parsed.byPosition.get(positionKey(syntaxSpan(node, parsed.source, parsed.digest, commitSha))) ?? [])
|
|
60
|
+
.filter(fact => fact.codeOccurrence?.role === role);
|
|
61
|
+
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
export interface CanonicalDocumentDefinition {
|
|
2
2
|
readonly target: string;
|
|
3
|
+
readonly title?: string;
|
|
3
4
|
readonly startLine: number;
|
|
4
5
|
readonly endLine: number;
|
|
5
6
|
}
|
|
6
7
|
export interface CanonicalDocumentLink {
|
|
7
8
|
readonly kind: 'link' | 'ambiguous-reference';
|
|
9
|
+
readonly title?: string;
|
|
8
10
|
readonly target?: string;
|
|
9
11
|
readonly startLine: number;
|
|
10
12
|
readonly endLine: number;
|
|
@@ -15,7 +17,9 @@ export interface CanonicalDocumentLink {
|
|
|
15
17
|
readonly referenceEndLine?: number;
|
|
16
18
|
}
|
|
17
19
|
/** Explicit Markdown links only: this deliberately does not change the graph linker's policy. */
|
|
18
|
-
export declare function canonicalDocumentLinks(content: string
|
|
20
|
+
export declare function canonicalDocumentLinks(content: string, options?: {
|
|
21
|
+
readonly includeTitles?: boolean;
|
|
22
|
+
}): readonly CanonicalDocumentLink[];
|
|
19
23
|
export type CanonicalDocumentLinkResolution = {
|
|
20
24
|
readonly kind: 'path';
|
|
21
25
|
readonly path: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { posix } from 'node:path';
|
|
2
2
|
import { fromMarkdown } from 'mdast-util-from-markdown';
|
|
3
3
|
/** Explicit Markdown links only: this deliberately does not change the graph linker's policy. */
|
|
4
|
-
export function canonicalDocumentLinks(content) {
|
|
4
|
+
export function canonicalDocumentLinks(content, options = {}) {
|
|
5
5
|
const tree = fromMarkdown(content);
|
|
6
6
|
const definitions = new Map();
|
|
7
7
|
const collect = (node) => {
|
|
@@ -18,20 +18,20 @@ export function canonicalDocumentLinks(content) {
|
|
|
18
18
|
const links = [];
|
|
19
19
|
const visit = (node) => {
|
|
20
20
|
if (node.type === 'link' && node.position) {
|
|
21
|
-
links.push({ kind: 'link', target: node.url,
|
|
21
|
+
links.push({ kind: 'link', target: node.url, ...(options.includeTitles && node.title ? { title: node.title } : {}),
|
|
22
22
|
startLine: node.position.start.line, endLine: node.position.end.line });
|
|
23
23
|
return;
|
|
24
24
|
}
|
|
25
25
|
if (node.type === 'linkReference' && node.position) {
|
|
26
26
|
const declared = (definitions.get(node.identifier) ?? []).flatMap(definition => definition.position
|
|
27
|
-
? [{ target: definition.url, startLine: definition.position.start.line, endLine: definition.position.end.line }]
|
|
27
|
+
? [{ target: definition.url, ...(options.includeTitles && definition.title ? { title: definition.title } : {}), startLine: definition.position.start.line, endLine: definition.position.end.line }]
|
|
28
28
|
: []);
|
|
29
29
|
const first = declared[0];
|
|
30
30
|
if (!first)
|
|
31
31
|
return;
|
|
32
32
|
const reference = { identifier: node.identifier,
|
|
33
33
|
referenceStartLine: node.position.start.line, referenceEndLine: node.position.end.line };
|
|
34
|
-
if (new Set(declared.map(definition => definition.target)).size > 1) {
|
|
34
|
+
if (new Set(declared.map(definition => JSON.stringify([definition.target, definition.title]))).size > 1) {
|
|
35
35
|
// Never silently choose the first conflicting definition, as normal Markdown rendering does.
|
|
36
36
|
links.push({ kind: 'ambiguous-reference', ...reference,
|
|
37
37
|
startLine: node.position.start.line, endLine: node.position.end.line, definitions: declared });
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { CodeInventory } from '@weftlet/core';
|
|
2
|
+
import type { GitTreeEntry } from '../repository/git.js';
|
|
3
|
+
import type { ScipSourceProject } from '../configuration/scip-project.js';
|
|
4
|
+
import type { ScipIndexResult } from './scip-runtime.js';
|
|
5
|
+
/** No package contents, dependencies or active checkout are read. Boundary names are physical paths. */
|
|
6
|
+
export declare function buildCodeInventory(entries: readonly GitTreeEntry[], selectedPaths: readonly string[], codeRoots: readonly string[], project: ScipSourceProject | undefined, index: ScipIndexResult): CodeInventory;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { matchesRepositoryGlob } from '../repository/glob.js';
|
|
2
|
+
import { sha256, stableJson } from '../infrastructure/util.js';
|
|
3
|
+
/** No package contents, dependencies or active checkout are read. Boundary names are physical paths. */
|
|
4
|
+
export function buildCodeInventory(entries, selectedPaths, codeRoots, project, index) {
|
|
5
|
+
const regular = entries.filter(entry => entry.type === 'blob' && ['100644', '100755'].includes(entry.mode));
|
|
6
|
+
const manifests = regular.filter(entry => entry.path === 'package.json' || entry.path.endsWith('/package.json'));
|
|
7
|
+
const roots = new Map(manifests.map(entry => [entry.path === 'package.json' ? '.' : entry.path.slice(0, -'/package.json'.length),
|
|
8
|
+
{ path: entry.path, blobId: entry.objectId }]));
|
|
9
|
+
const orderedRoots = [...roots.keys()].filter(root => root !== '.').sort((a, b) => b.length - a.length || a.localeCompare(b));
|
|
10
|
+
const indexed = index.indexedPaths === undefined ? undefined : new Set(index.indexedPaths);
|
|
11
|
+
const selected = new Set(selectedPaths);
|
|
12
|
+
const files = regular.filter(entry => /\.(?:[cm]?ts|tsx)$/.test(entry.path)).map(entry => ({
|
|
13
|
+
path: entry.path, blobId: entry.objectId, projectRoot: orderedRoots.find(root => entry.path.startsWith(`${root}/`)) ?? '.',
|
|
14
|
+
codeRootSelected: selected.has(entry.path),
|
|
15
|
+
requested: project ? project.include.some(pattern => matchesRepositoryGlob(entry.path, pattern)) ? 'included' : 'excluded' : 'unknown',
|
|
16
|
+
...(indexed ? { indexed: indexed.has(entry.path) } : {}),
|
|
17
|
+
})).sort((a, b) => a.path.localeCompare(b.path));
|
|
18
|
+
const projects = [...new Set(['.', ...roots.keys()])].sort().map(root => ({ root, ...(roots.has(root) ? { manifest: roots.get(root) } : {}) }));
|
|
19
|
+
const known = new Set(files.map(file => file.path));
|
|
20
|
+
const plain = { version: 'committed-code-inventory-v1', scipIndexDigest: index.digest,
|
|
21
|
+
selection: project ? 'source-project' : 'indexer-command',
|
|
22
|
+
indexObservation: indexed ? 'recorded' : 'unavailable', codeRoots: [...codeRoots],
|
|
23
|
+
...(project ? { includePatterns: [...project.include] } : {}), projects, files,
|
|
24
|
+
...(indexed ? { otherIndexedFiles: [...indexed].filter(path => !known.has(path)).length } : {}) };
|
|
25
|
+
return { ...plain, digest: sha256(stableJson(plain)) };
|
|
26
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ExtractionContext, GraphDiagnostic, GraphFact, SemanticSource } from '@weftlet/core';
|
|
2
|
+
import type { GitRepository } from '../repository/git.js';
|
|
3
|
+
export declare const documentCodeBindingIdentity: {
|
|
4
|
+
readonly id: "document-code-binding-extractor";
|
|
5
|
+
readonly version: "1.0.0";
|
|
6
|
+
};
|
|
7
|
+
export interface BindingSource extends SemanticSource {
|
|
8
|
+
readonly metadata: Pick<GraphFact, 'sourceAuthority' | 'sourceRole' | 'sourceOwnership' | 'sourcePolicyDigest'>;
|
|
9
|
+
}
|
|
10
|
+
/** Resolve only explicit declarations against current indexed evidence; no provider, checkout or basename search. */
|
|
11
|
+
export declare function extractDocumentCodeBindings(repository: Pick<GitRepository, 'listEntriesAt' | 'readFileAt'>, context: ExtractionContext, sources: readonly BindingSource[], codeFacts: readonly GraphFact[], subjectFacts: readonly GraphFact[]): Promise<{
|
|
12
|
+
facts: readonly GraphFact[];
|
|
13
|
+
diagnostics: readonly GraphDiagnostic[];
|
|
14
|
+
}>;
|