@weftlet/toolkit 0.2.1 → 0.4.0
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 +80 -0
- package/dist/application/agent-context.d.ts +3 -1
- package/dist/application/agent-context.js +15 -6
- package/dist/application/application.js +7 -4
- package/dist/application/cache-adoption.d.ts +43 -0
- package/dist/application/cache-adoption.js +129 -0
- package/dist/application/extraction-identity.d.ts +6 -0
- package/dist/application/extraction-identity.js +15 -0
- package/dist/application/hydration-failure.d.ts +41 -0
- package/dist/application/hydration-failure.js +43 -0
- package/dist/application/hydration-plan.d.ts +54 -0
- package/dist/application/hydration-plan.js +71 -0
- package/dist/application/hydrator.d.ts +3 -5
- package/dist/application/hydrator.js +30 -61
- package/dist/application/overlay.js +10 -3
- package/dist/application/saved-evidence.d.ts +6 -3
- package/dist/application/saved-evidence.js +7 -1
- package/dist/application/semantic-artifact-store.d.ts +4 -0
- package/dist/application/semantic-artifact-store.js +7 -0
- package/dist/application/semantic-run.d.ts +29 -0
- package/dist/application/semantic-run.js +111 -0
- package/dist/application/semantic-scope.d.ts +13 -0
- package/dist/application/semantic-scope.js +12 -0
- package/dist/application/snapshot-checks.d.ts +2 -1
- package/dist/application/snapshot-checks.js +8 -1
- package/dist/configuration/cache.d.ts +6 -0
- package/dist/configuration/cache.js +18 -0
- package/dist/extraction/document.js +1 -1
- package/dist/extraction/providers.js +12 -5
- package/dist/extraction/repository-nodes.d.ts +2 -3
- package/dist/extraction/repository-nodes.js +5 -11
- package/dist/extraction/routing.d.ts +1 -1
- package/dist/extraction/routing.js +3 -6
- package/dist/extraction/semantic-cache.d.ts +13 -0
- package/dist/extraction/semantic-cache.js +66 -0
- package/dist/extraction/semantic-diagnostics.d.ts +9 -0
- package/dist/extraction/semantic-diagnostics.js +15 -0
- package/dist/extraction/semantic-identity.d.ts +7 -0
- package/dist/extraction/semantic-identity.js +29 -0
- package/dist/extraction/semantic-sources.d.ts +27 -0
- package/dist/extraction/semantic-sources.js +35 -0
- package/dist/extraction/semantic.d.ts +5 -1
- package/dist/extraction/semantic.js +47 -24
- package/dist/extraction/static.d.ts +13 -5
- package/dist/extraction/static.js +8 -15
- package/dist/governance/governance.js +11 -7
- package/dist/graph/query.js +2 -0
- package/dist/graph/rdf.d.ts +1 -1
- package/dist/graph/rdf.js +13 -28
- package/dist/graph/shacl-shapes.d.ts +5 -0
- package/dist/graph/shacl-shapes.js +27 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/interfaces/cli.js +86 -19
- package/dist/repository/git.d.ts +1 -1
- package/dist/repository/git.js +5 -1
- package/dist/storage/storage.d.ts +7 -1
- package/dist/storage/storage.js +15 -3
- package/dist/visualization/visualization.js +1 -0
- package/docs/ADR-016-hydration-preview.md +91 -0
- package/docs/ADR-017-shacl-validation-union.md +102 -0
- package/docs/ADR-018-operational-semantic-cache.md +100 -0
- package/docs/ADR-019-semantic-failure-diagnostics.md +82 -0
- package/docs/ADR-020-canonical-physical-file-producers.md +97 -0
- package/docs/PROVIDERS.md +51 -1
- package/docs/RELEASE-1.0-PLAN.md +148 -32
- package/docs/RELEASING.md +19 -6
- package/docs/ROADMAP.md +46 -5
- package/docs/VALIDATION.md +341 -3
- package/docs/WEFTLET-2.0-PLAN.md +9 -8
- package/docs/extraction-manifest.json +55 -23
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -67,6 +67,77 @@ the archive-byte, snapshot replacement and MCP startup regression suite also pas
|
|
|
67
67
|
Windows CI. Full native Windows release preparation remains separately unvalidated.
|
|
68
68
|
See the [validation record](docs/VALIDATION.md).
|
|
69
69
|
|
|
70
|
+
## Preview hydration before model work
|
|
71
|
+
|
|
72
|
+
`hydrate --plan` requires toolkit **0.3.0 or newer**. Releases through 0.2.1 do not support
|
|
73
|
+
this flag. With a supporting version installed, inspect a project's committed inputs:
|
|
74
|
+
|
|
75
|
+
```sh
|
|
76
|
+
pnpm exec weftlet hydrate --plan --config /path/to/project/context-graph.config.json --ref HEAD
|
|
77
|
+
pnpm exec weftlet hydrate --plan --json --config /path/to/project/context-graph.config.json --ref HEAD
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
The human summary and JSON identify the resolved commit, current local configuration, selected
|
|
81
|
+
documents and inclusion reasons, UTF-8 byte sizes, source approval, expected cache reuse and
|
|
82
|
+
extraction counts, budget violations, and working changes excluded from the committed input.
|
|
83
|
+
Selection uses configured repository file/directory paths; `approvedIntentSources` uses its
|
|
84
|
+
separate glob matcher. An explicit empty semantic source list selects no documents, fixing the
|
|
85
|
+
earlier accidental expansion to the whole repository.
|
|
86
|
+
|
|
87
|
+
Planning reads Git objects and existing artifacts without loading a model provider or repository
|
|
88
|
+
adapter, indexing code, collecting runtime evidence, validating the graph or writing snapshots.
|
|
89
|
+
It does not check credentials or estimate tokens or dollars. Cache hits depend on unchanged
|
|
90
|
+
inputs; corrupt or unreadable entries are reported separately from misses. `--force-semantic`
|
|
91
|
+
shows planned re-extraction without allocating or writing a forced revision.
|
|
92
|
+
|
|
93
|
+
A plan exits 0 when its source/cache/budget checks are ready. It exits 1 with the full plan when
|
|
94
|
+
errors block those checks or incomplete selection needs review. Missing/no-document selectors
|
|
95
|
+
and existing agent-selection limits are warnings; they do not add a new hydration gate that
|
|
96
|
+
would prevent removing the last document and invalidating its relationships. All selected
|
|
97
|
+
documents remain visible when budgets are exceeded.
|
|
98
|
+
|
|
99
|
+
Source approval does not approve model assertions. Validation-document labels reflect configured
|
|
100
|
+
evidence roots; selected validation documents still undergo semantic extraction today. Recursive
|
|
101
|
+
SOT traversal and default validation-document separation remain T07 work. See
|
|
102
|
+
[ADR 016](docs/ADR-016-hydration-preview.md) and the [1.0 task list](docs/RELEASE-1.0-PLAN.md).
|
|
103
|
+
|
|
104
|
+
Starting with **0.4.0**, preview also maps opaque diagnostic source IDs to local paths. Semantic
|
|
105
|
+
failures report completed/remaining work and recovery guidance; `hydrate --json --quiet` emits
|
|
106
|
+
their structured report on stderr. Built-in Codex can reuse completed artifacts after supported
|
|
107
|
+
operational changes such as increasing a timeout. See [provider recovery](docs/PROVIDERS.md#limits-and-reuse)
|
|
108
|
+
for preview, retry and explicit legacy-cache adoption instructions.
|
|
109
|
+
|
|
110
|
+
## SHACL validation and performance
|
|
111
|
+
|
|
112
|
+
Starting with 0.3.0, the toolkit indexes a temporary union to accelerate cold validation.
|
|
113
|
+
The toolkit uses JavaScript `rdf-validate-shacl` and an in-memory
|
|
114
|
+
N3 store. Each hydration validates the complete graph; semantic artifact reuse does not make
|
|
115
|
+
validation incremental, and there is no validation-result cache, Rust engine or GraphDB service.
|
|
116
|
+
Saved queries do not rerun SHACL.
|
|
117
|
+
|
|
118
|
+
The current shapes use subject/predicate/object values independently of graph names. Validation
|
|
119
|
+
now builds one temporary union graph so repeated property lookups avoid scanning every named
|
|
120
|
+
assertion graph. The same shapes and validator run against that union. The original named dataset,
|
|
121
|
+
assertion records and provenance remain the source for SPARQL, queries and serialization.
|
|
122
|
+
|
|
123
|
+
In bounded, single-run public experiments, 2,000 facts with unique subject/object nodes took
|
|
124
|
+
31.50 seconds in the original SHACL path, compared with 0.153 seconds to build the union and
|
|
125
|
+
0.467 seconds for SHACL on that union. A 10,000-fact union case used about 1.3 GiB process RSS;
|
|
126
|
+
the extra projection has a memory cost. These measurements do not reproduce the private consumer's
|
|
127
|
+
full generation run or guarantee a production duration. See [ADR 017](docs/ADR-017-shacl-validation-union.md)
|
|
128
|
+
for methodology, parity boundaries and remaining work. To run the bounded public benchmark from
|
|
129
|
+
a development checkout:
|
|
130
|
+
|
|
131
|
+
```sh
|
|
132
|
+
pnpm build
|
|
133
|
+
pnpm benchmark:shacl
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Current hydration progress reports phase boundaries. The validator performs synchronous work,
|
|
137
|
+
so an ordinary timer cannot provide an honest heartbeat while that work blocks Node's main
|
|
138
|
+
thread. Worker-based progress, early identity checks, validation-result reuse and incremental
|
|
139
|
+
validation remain separate T05 work; they do not delay the focused cold-validation release.
|
|
140
|
+
|
|
70
141
|
## Development
|
|
71
142
|
|
|
72
143
|
The development source is organized by responsibility; see
|
|
@@ -107,6 +178,15 @@ For tests excluded by the build config or workspace packages whose outputs are a
|
|
|
107
178
|
committed archives, configure an [explicit TypeScript source project](docs/ADR-010-committed-source-indexing.md)
|
|
108
179
|
with selected files and local package aliases.
|
|
109
180
|
|
|
181
|
+
Repository adapters using **0.4.0 or newer** should import `repositoryFileNode` from
|
|
182
|
+
`@weftlet/core` for physical-file nodes. It preserves canonical document IDs, spec/test Evidence
|
|
183
|
+
and production Component kinds, including test files containing mocked calls or decorators.
|
|
184
|
+
Keep business-concept nodes separate; see the [core API example](packages/core/README.md) and
|
|
185
|
+
[producer decision](docs/ADR-020-canonical-physical-file-producers.md). After upgrading, rebuild
|
|
186
|
+
the graph with compatible cached artifacts; historical snapshots remain queryable but cannot
|
|
187
|
+
satisfy current validation with old extraction versions. Consumer-owned adapters must be migrated
|
|
188
|
+
as well; the toolkit cannot correct nodes they still classify independently.
|
|
189
|
+
|
|
110
190
|
In a selected document such as `docs/intent.md`, link a responsibility to its sources:
|
|
111
191
|
|
|
112
192
|
```md
|
|
@@ -7,12 +7,14 @@ export interface AgentSemanticScope {
|
|
|
7
7
|
readonly semanticSources: readonly string[];
|
|
8
8
|
readonly headName: string;
|
|
9
9
|
readonly snapshotSuffix: string;
|
|
10
|
+
readonly omittedDocuments?: readonly string[];
|
|
11
|
+
readonly ignoredSearchTerms?: number;
|
|
10
12
|
}
|
|
11
13
|
export declare class AgentSemanticScopeResolver {
|
|
12
14
|
private readonly config;
|
|
13
15
|
private readonly repository;
|
|
14
16
|
constructor(config: ContextGraphConfig, repository: GitRepository);
|
|
15
|
-
resolve(request: ImpactScanRequest): Promise<AgentSemanticScope>;
|
|
17
|
+
resolve(request: ImpactScanRequest, ref?: string): Promise<AgentSemanticScope>;
|
|
16
18
|
}
|
|
17
19
|
export declare class PreparedImpactQueryService implements ImpactQueryService {
|
|
18
20
|
private readonly store;
|
|
@@ -16,13 +16,15 @@ export class AgentSemanticScopeResolver {
|
|
|
16
16
|
this.config = config;
|
|
17
17
|
this.repository = repository;
|
|
18
18
|
}
|
|
19
|
-
async resolve(request) {
|
|
19
|
+
async resolve(request, ref = 'HEAD') {
|
|
20
20
|
const agent = this.config.agentContext;
|
|
21
21
|
if (!agent)
|
|
22
22
|
throw new Error('Agent context preparation is not configured');
|
|
23
|
-
const commitSha = await this.repository.resolveRef(
|
|
23
|
+
const commitSha = await this.repository.resolveRef(ref);
|
|
24
24
|
const available = new Set((await this.repository.listFilesAt(commitSha, this.config.semanticSources)).filter((path) => /\.(?:md|mdx|txt)$/i.test(path)));
|
|
25
25
|
const selected = new Set();
|
|
26
|
+
const omitted = new Set();
|
|
27
|
+
let ignoredSearchTerms = 0;
|
|
26
28
|
for (const path of await this.repository.listFilesAt(commitSha, agent.alwaysSemanticSources)) {
|
|
27
29
|
if (available.has(path))
|
|
28
30
|
selected.add(path);
|
|
@@ -42,6 +44,8 @@ export class AgentSemanticScopeResolver {
|
|
|
42
44
|
.filter((path) => available.has(path));
|
|
43
45
|
for (const path of references.slice(0, agent.maxReferencedDocuments))
|
|
44
46
|
selected.add(path);
|
|
47
|
+
for (const path of references.slice(agent.maxReferencedDocuments))
|
|
48
|
+
omitted.add(path);
|
|
45
49
|
}
|
|
46
50
|
if (agent.includeMatchingEvidence) {
|
|
47
51
|
const ownerSlug = basename(ownerDocument).replace(/\.md$/i, '');
|
|
@@ -51,16 +55,19 @@ export class AgentSemanticScopeResolver {
|
|
|
51
55
|
}
|
|
52
56
|
}
|
|
53
57
|
else {
|
|
54
|
-
const
|
|
58
|
+
const requestedTerms = [
|
|
55
59
|
request.task,
|
|
56
60
|
...(request.checklistItems ?? []),
|
|
57
61
|
...(request.capabilities ?? []),
|
|
58
62
|
]
|
|
59
|
-
.filter((term) => Boolean(term))
|
|
60
|
-
|
|
61
|
-
|
|
63
|
+
.filter((term) => Boolean(term));
|
|
64
|
+
const terms = requestedTerms.slice(0, 8);
|
|
65
|
+
ignoredSearchTerms = requestedTerms.length - terms.length;
|
|
66
|
+
const matches = (await this.repository.findTextAt(commitSha, terms, this.config.semanticSources)).filter((match) => available.has(match.path));
|
|
62
67
|
for (const match of matches.slice(0, agent.maxReferencedDocuments))
|
|
63
68
|
selected.add(match.path);
|
|
69
|
+
for (const match of matches.slice(agent.maxReferencedDocuments))
|
|
70
|
+
omitted.add(match.path);
|
|
64
71
|
}
|
|
65
72
|
const semanticSources = [...selected].sort();
|
|
66
73
|
if (semanticSources.length === 0) {
|
|
@@ -72,6 +79,8 @@ export class AgentSemanticScopeResolver {
|
|
|
72
79
|
semanticSources,
|
|
73
80
|
headName: `agent-${scopeDigest}`,
|
|
74
81
|
snapshotSuffix: `agent-${scopeDigest}`,
|
|
82
|
+
omittedDocuments: [...omitted].filter((path) => !selected.has(path)).sort(),
|
|
83
|
+
ignoredSearchTerms,
|
|
75
84
|
};
|
|
76
85
|
}
|
|
77
86
|
}
|
|
@@ -10,11 +10,13 @@ import { OpenCaesarOntologyCompiler, DirectRdfOntologyCompiler } from "../extrac
|
|
|
10
10
|
import { SnapshotImpactQueryService } from "../graph/query.js";
|
|
11
11
|
import { SemanticHydrator } from "../extraction/semantic.js";
|
|
12
12
|
import { createSemanticExtractor } from "../extraction/providers.js";
|
|
13
|
-
import {
|
|
13
|
+
import { FileSnapshotStore } from "../storage/storage.js";
|
|
14
|
+
import { createSemanticArtifactStore } from './semantic-artifact-store.js';
|
|
14
15
|
import { RepositoryContractExtractor, RepositoryFileExtractor, ScipSymbolExtractor, ScipTypeScriptIndexer, } from "../extraction/static.js";
|
|
15
16
|
import { OtlpJsonRuntimeEvidenceProvider } from "../extraction/telemetry.js";
|
|
16
17
|
import { SnapshotChecks } from "./snapshot-checks.js";
|
|
17
18
|
import { resolveConsumerModule } from "../infrastructure/module-resolution.js";
|
|
19
|
+
import { requiredSnapshotExtractorVersions } from './extraction-identity.js';
|
|
18
20
|
const emptyAdapter = {
|
|
19
21
|
factExtractors: [],
|
|
20
22
|
invariantEvaluators: [],
|
|
@@ -45,7 +47,7 @@ export async function createContextGraphApplication(configPath) {
|
|
|
45
47
|
const repository = new GitRepository(repositoryRoot);
|
|
46
48
|
const adapter = await loadContextGraphAdapterModule(config.adapter, repository, repositoryRoot);
|
|
47
49
|
const snapshotStore = new FileSnapshotStore(storageRoot);
|
|
48
|
-
const artifactStore =
|
|
50
|
+
const artifactStore = createSemanticArtifactStore(repositoryRoot, config);
|
|
49
51
|
const semanticExtractor = createSemanticExtractor(config.semantic, repositoryRoot);
|
|
50
52
|
const semanticHydrator = new SemanticHydrator(config.semantic, artifactStore, semanticExtractor);
|
|
51
53
|
const staticIndexer = new ScipTypeScriptIndexer(config.scip, storageRoot);
|
|
@@ -75,7 +77,8 @@ export async function createContextGraphApplication(configPath) {
|
|
|
75
77
|
const rawQueryService = scopeResolver
|
|
76
78
|
? new PreparedImpactQueryService(snapshotStore, hydrator, scopeResolver)
|
|
77
79
|
: new SnapshotImpactQueryService(snapshotStore, headName);
|
|
78
|
-
const
|
|
80
|
+
const expectedExtractors = requiredSnapshotExtractorVersions(config);
|
|
81
|
+
const queryService = new SavedEvidenceQueryService(rawQueryService, repository, sha256(stableJson(config)), expectedExtractors);
|
|
79
82
|
return {
|
|
80
83
|
...loaded,
|
|
81
84
|
storageRoot,
|
|
@@ -84,7 +87,7 @@ export async function createContextGraphApplication(configPath) {
|
|
|
84
87
|
ontologyCompiler,
|
|
85
88
|
hydrator,
|
|
86
89
|
queryService,
|
|
87
|
-
snapshotChecks: new SnapshotChecks(snapshotStore, repository, hydrator, scopeResolver, sha256(stableJson(config))),
|
|
90
|
+
snapshotChecks: new SnapshotChecks(snapshotStore, repository, hydrator, scopeResolver, sha256(stableJson(config)), expectedExtractors),
|
|
88
91
|
scopeResolver,
|
|
89
92
|
headName,
|
|
90
93
|
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { ImpactScanRequest } from '@weftlet/core';
|
|
2
|
+
import { type SemanticInputIssue, type SemanticSelection } from '../extraction/semantic-sources.js';
|
|
3
|
+
import { type SemanticScope } from './semantic-scope.js';
|
|
4
|
+
export interface SemanticCacheAdoptionOptions {
|
|
5
|
+
readonly fromConfigPath: string;
|
|
6
|
+
readonly ref?: string;
|
|
7
|
+
readonly dryRun?: boolean;
|
|
8
|
+
readonly request?: ImpactScanRequest;
|
|
9
|
+
}
|
|
10
|
+
export type SemanticCacheAdoptionStatus = 'adopted' | 'reusable' | 'planned' | 'missing' | 'corrupt' | 'unavailable' | 'conflict';
|
|
11
|
+
export interface SemanticCacheAdoptionRecord {
|
|
12
|
+
readonly path: string;
|
|
13
|
+
readonly key: string;
|
|
14
|
+
readonly status: SemanticCacheAdoptionStatus;
|
|
15
|
+
readonly reason: string;
|
|
16
|
+
}
|
|
17
|
+
export interface SemanticCacheAdoption {
|
|
18
|
+
readonly schemaVersion: 1;
|
|
19
|
+
readonly kind: 'semantic-cache-adoption';
|
|
20
|
+
readonly repositoryId: string;
|
|
21
|
+
readonly ref: string;
|
|
22
|
+
readonly commitSha: string;
|
|
23
|
+
readonly configurationDigest: string;
|
|
24
|
+
readonly previousConfigurationDigest: string;
|
|
25
|
+
readonly dryRun: boolean;
|
|
26
|
+
readonly ready: boolean;
|
|
27
|
+
readonly scope: SemanticScope & {
|
|
28
|
+
readonly complete: boolean;
|
|
29
|
+
};
|
|
30
|
+
readonly records: readonly SemanticCacheAdoptionRecord[];
|
|
31
|
+
readonly counts: Readonly<Record<SemanticCacheAdoptionStatus, number>>;
|
|
32
|
+
readonly selections: readonly SemanticSelection[];
|
|
33
|
+
readonly budgets: {
|
|
34
|
+
readonly maxDocuments: number;
|
|
35
|
+
readonly maxSourceBytes: number;
|
|
36
|
+
readonly selectedDocuments: number;
|
|
37
|
+
readonly totalSourceBytes: number;
|
|
38
|
+
};
|
|
39
|
+
readonly issues: readonly SemanticInputIssue[];
|
|
40
|
+
readonly assumptions: readonly string[];
|
|
41
|
+
}
|
|
42
|
+
/** Explicitly adopts only committed-source artifacts from a compatible, named legacy profile. */
|
|
43
|
+
export declare function adoptSemanticCache(configPath: string, options: SemanticCacheAdoptionOptions): Promise<SemanticCacheAdoption>;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { loadConfig } from '../configuration/config.js';
|
|
2
|
+
import { resolveSemanticStorageRoots, resolveStorageRoot, semanticCachePartition } from '../configuration/cache.js';
|
|
3
|
+
import { inspectSemanticCache } from '../extraction/semantic-cache.js';
|
|
4
|
+
import { semanticProviderIdentity } from '../extraction/semantic-identity.js';
|
|
5
|
+
import { selectSemanticInputs } from '../extraction/semantic-sources.js';
|
|
6
|
+
import { sha256, stableJson } from '../infrastructure/util.js';
|
|
7
|
+
import { GitRepository } from '../repository/git.js';
|
|
8
|
+
import { SemanticArtifactStore } from '../storage/storage.js';
|
|
9
|
+
import { resolveSemanticScope } from './semantic-scope.js';
|
|
10
|
+
const problemStatuses = new Set(['corrupt', 'unavailable', 'conflict']);
|
|
11
|
+
function problem(inspection, source, location) {
|
|
12
|
+
if (inspection.status !== 'corrupt' && inspection.status !== 'unavailable')
|
|
13
|
+
return undefined;
|
|
14
|
+
return { path: source.path, key: inspection.key, status: inspection.status,
|
|
15
|
+
reason: `${location} cache: ${inspection.reason}` };
|
|
16
|
+
}
|
|
17
|
+
async function inspectCandidate(source, config, identity, previous, current) {
|
|
18
|
+
const [before, existing] = await Promise.all([
|
|
19
|
+
inspectSemanticCache(previous, config, source, identity),
|
|
20
|
+
inspectSemanticCache(current, config, source, identity),
|
|
21
|
+
]);
|
|
22
|
+
const failure = problem(existing, source, 'Current') ?? problem(before, source, 'Previous');
|
|
23
|
+
if (failure)
|
|
24
|
+
return { source, record: failure };
|
|
25
|
+
const base = { path: source.path, key: existing.key };
|
|
26
|
+
if (existing.status === 'hit') {
|
|
27
|
+
const conflict = before.status === 'hit' && before.artifact.outputDigest !== existing.artifact.outputDigest;
|
|
28
|
+
return { source, record: { ...base, status: conflict ? 'conflict' : 'reusable', reason: conflict
|
|
29
|
+
? 'Current and previous caches contain different valid artifacts for this key; neither was overwritten.'
|
|
30
|
+
: 'A validated artifact is already available in the current cache.' } };
|
|
31
|
+
}
|
|
32
|
+
if (before.status === 'miss')
|
|
33
|
+
return { source, record: { ...base, status: 'missing',
|
|
34
|
+
reason: 'The explicit previous profile has no complete artifact for this source and extraction contract.' } };
|
|
35
|
+
if (before.status !== 'hit' || existing.status !== 'miss')
|
|
36
|
+
throw new Error('Unexpected cache inspection state');
|
|
37
|
+
return { source, artifact: before.artifact, record: { ...base, status: 'planned',
|
|
38
|
+
reason: 'A validated previous artifact can be copied without extraction or changing its provenance.' } };
|
|
39
|
+
}
|
|
40
|
+
async function publishCandidate(candidate, config, identity, current) {
|
|
41
|
+
let publicationError;
|
|
42
|
+
let published = false;
|
|
43
|
+
try {
|
|
44
|
+
await current.write(candidate.artifact);
|
|
45
|
+
published = true;
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
publicationError = error;
|
|
49
|
+
}
|
|
50
|
+
// Reinspect even after a successful write: an immutable-key winner can have
|
|
51
|
+
// matching output but corrupt identity metadata. A digest match alone is not
|
|
52
|
+
// permission to report that artifact as reusable.
|
|
53
|
+
const existing = await inspectSemanticCache(current, config, candidate.source, identity);
|
|
54
|
+
const failure = problem(existing, candidate.source, 'Current');
|
|
55
|
+
if (failure)
|
|
56
|
+
return failure;
|
|
57
|
+
if (existing.status === 'hit' && existing.artifact.outputDigest !== candidate.artifact.outputDigest) {
|
|
58
|
+
return { ...candidate.record, status: 'conflict',
|
|
59
|
+
reason: 'A concurrent writer published a different valid artifact; neither artifact was overwritten.' };
|
|
60
|
+
}
|
|
61
|
+
if (!published) {
|
|
62
|
+
throw new Error('Unable to adopt a semantic artifact because storage publication failed.', { cause: publicationError });
|
|
63
|
+
}
|
|
64
|
+
if (existing.status !== 'hit')
|
|
65
|
+
return { ...candidate.record, status: 'unavailable',
|
|
66
|
+
reason: 'Published artifact is no longer readable; no successful adoption is claimed.' };
|
|
67
|
+
return { ...candidate.record, status: 'adopted',
|
|
68
|
+
reason: 'Validated artifact is available in the current cache; the previous artifact is unchanged.' };
|
|
69
|
+
}
|
|
70
|
+
/** Explicitly adopts only committed-source artifacts from a compatible, named legacy profile. */
|
|
71
|
+
export async function adoptSemanticCache(configPath, options) {
|
|
72
|
+
const [loaded, previous] = await Promise.all([loadConfig(configPath), loadConfig(options.fromConfigPath)]);
|
|
73
|
+
const { config, repositoryRoot } = loaded;
|
|
74
|
+
if (repositoryRoot !== previous.repositoryRoot) {
|
|
75
|
+
throw new Error('Cache adoption requires both configurations to resolve to the same checkout.');
|
|
76
|
+
}
|
|
77
|
+
if (semanticCachePartition(repositoryRoot, config) !== semanticCachePartition(repositoryRoot, previous.config)) {
|
|
78
|
+
throw new Error('Cache adoption requires matching non-operational configuration and provider contracts.');
|
|
79
|
+
}
|
|
80
|
+
const repository = new GitRepository(repositoryRoot);
|
|
81
|
+
const ref = options.ref ?? 'HEAD';
|
|
82
|
+
const commitSha = await repository.resolveRef(ref);
|
|
83
|
+
const scope = await resolveSemanticScope(config, repository, commitSha, options.request);
|
|
84
|
+
const selection = await selectSemanticInputs(repository, commitSha, scope.selectors, config.semantic);
|
|
85
|
+
const issues = [...selection.issues];
|
|
86
|
+
const limited = scope.omittedDocuments.length > 0 || scope.ignoredSearchTerms > 0;
|
|
87
|
+
const complete = !limited && selection.selections.every((item) => item.status === 'matched');
|
|
88
|
+
if (limited)
|
|
89
|
+
issues.push({ code: 'selection-limited', severity: 'warning',
|
|
90
|
+
message: `Existing agent selection limits omitted ${scope.omittedDocuments.length} documents and ${scope.ignoredSearchTerms} search terms; adoption describes only the selected scope.`,
|
|
91
|
+
paths: scope.omittedDocuments });
|
|
92
|
+
const dryRun = options.dryRun ?? false;
|
|
93
|
+
const records = [];
|
|
94
|
+
if (!issues.some((issue) => issue.severity === 'error')) {
|
|
95
|
+
const current = new SemanticArtifactStore(resolveSemanticStorageRoots(repositoryRoot, config).primary);
|
|
96
|
+
// Do not scan sibling profiles or infer ownership from an artifact key. The
|
|
97
|
+
// supplied old configuration proves the exact legacy location to inspect.
|
|
98
|
+
const old = new SemanticArtifactStore(resolveStorageRoot(repositoryRoot, previous.config));
|
|
99
|
+
const identity = semanticProviderIdentity(config.semantic);
|
|
100
|
+
for (const source of selection.sources) {
|
|
101
|
+
const candidate = await inspectCandidate(source, config.semantic, identity, old, current);
|
|
102
|
+
const result = candidate.artifact && !dryRun
|
|
103
|
+
? await publishCandidate(candidate, config.semantic, identity, current) : candidate.record;
|
|
104
|
+
records.push(result);
|
|
105
|
+
if (problemStatuses.has(result.status))
|
|
106
|
+
issues.push({ code: `cache-${result.status}`, severity: 'error',
|
|
107
|
+
message: result.reason, paths: [result.path] });
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
const counts = {
|
|
111
|
+
adopted: 0, reusable: 0, planned: 0, missing: 0, corrupt: 0, unavailable: 0, conflict: 0,
|
|
112
|
+
};
|
|
113
|
+
for (const record of records)
|
|
114
|
+
counts[record.status]++;
|
|
115
|
+
return {
|
|
116
|
+
schemaVersion: 1, kind: 'semantic-cache-adoption', repositoryId: config.repositoryId,
|
|
117
|
+
ref, commitSha, configurationDigest: sha256(stableJson(config)),
|
|
118
|
+
previousConfigurationDigest: sha256(stableJson(previous.config)), dryRun,
|
|
119
|
+
ready: complete && !issues.some((issue) => issue.severity === 'error'), scope: { ...scope, complete },
|
|
120
|
+
records, counts, selections: selection.selections, budgets: selection.budgets, issues,
|
|
121
|
+
assumptions: [
|
|
122
|
+
'Selection uses the same configured or bounded agent scope as hydration planning at the resolved commit; only expected keys in the explicitly named previous profile are inspected.',
|
|
123
|
+
'Missing or incomplete previous artifacts need later extraction. Corrupt or conflicting complete artifacts are retained for diagnosis.',
|
|
124
|
+
'Adoption preserves original artifact identity and provenance; it does not validate or publish a current snapshot.',
|
|
125
|
+
'Artifacts are adopted independently; earlier valid copies remain available if a later artifact or storage operation fails.',
|
|
126
|
+
'No provider, authentication, indexing, ontology or repository adapter is initialized. Dry runs do not write cache files.',
|
|
127
|
+
],
|
|
128
|
+
};
|
|
129
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ContextGraphConfig } from '../configuration/config.js';
|
|
2
|
+
export declare const graphAssemblyVersion = 7;
|
|
3
|
+
export declare const graphAssemblyIdentity = "standalone-graph-v7";
|
|
4
|
+
/** Runtime expectations are separate from source/configuration identity and artifact reuse. */
|
|
5
|
+
export declare function requiredSnapshotExtractorVersions(config?: Pick<ContextGraphConfig, 'routingSources'>): Readonly<Record<string, string>>;
|
|
6
|
+
export declare function incompatibleSnapshotExtractors(actual: Readonly<Record<string, string>> | undefined, expected: Readonly<Record<string, string>>): readonly string[];
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { repositoryContractExtractorIdentity, scipSymbolExtractorIdentity } from '../extraction/static.js';
|
|
2
|
+
import { routingExtractorIdentity } from '../extraction/routing.js';
|
|
3
|
+
export const graphAssemblyVersion = 7;
|
|
4
|
+
export const graphAssemblyIdentity = `standalone-graph-v${graphAssemblyVersion}`;
|
|
5
|
+
/** Runtime expectations are separate from source/configuration identity and artifact reuse. */
|
|
6
|
+
export function requiredSnapshotExtractorVersions(config) {
|
|
7
|
+
return { assembly: graphAssemblyIdentity,
|
|
8
|
+
[repositoryContractExtractorIdentity.id]: repositoryContractExtractorIdentity.version,
|
|
9
|
+
[scipSymbolExtractorIdentity.id]: scipSymbolExtractorIdentity.version,
|
|
10
|
+
...(config?.routingSources?.length ? { [routingExtractorIdentity.id]: routingExtractorIdentity.version } : {}),
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export function incompatibleSnapshotExtractors(actual, expected) {
|
|
14
|
+
return Object.keys(expected).filter((id) => actual?.[id] !== expected[id]).sort();
|
|
15
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { SemanticProviderError } from '../extraction/semantic-process.js';
|
|
2
|
+
import { SemanticPolicyError, type SemanticHydrationPhase } from '../extraction/semantic-diagnostics.js';
|
|
3
|
+
export type SemanticFailureCode = SemanticProviderError['code'] | SemanticPolicyError['code'] | 'cache-failure' | 'provider-failure';
|
|
4
|
+
export interface SemanticRunProgress {
|
|
5
|
+
readonly total: number;
|
|
6
|
+
readonly completed: number;
|
|
7
|
+
readonly extracted: number;
|
|
8
|
+
readonly reused: number;
|
|
9
|
+
readonly failed: number;
|
|
10
|
+
readonly cancelled: number;
|
|
11
|
+
readonly notStarted: number;
|
|
12
|
+
/** Includes failed, cancelled and not-started sources; it is not an extraction estimate. */
|
|
13
|
+
readonly remaining: number;
|
|
14
|
+
}
|
|
15
|
+
export interface SemanticHydrationFailure {
|
|
16
|
+
readonly schemaVersion: 1;
|
|
17
|
+
readonly kind: 'semantic-hydration-failure';
|
|
18
|
+
readonly code: SemanticFailureCode;
|
|
19
|
+
readonly category: 'timeout' | 'cancellation' | 'provider' | 'infrastructure' | 'extraction-gap';
|
|
20
|
+
readonly phase: SemanticHydrationPhase | 'semantic-scheduling';
|
|
21
|
+
/** Absent when cancellation occurs between sources, without one failing source. */
|
|
22
|
+
readonly sourceId?: string;
|
|
23
|
+
readonly commitSha: string;
|
|
24
|
+
readonly configurationDigest: string;
|
|
25
|
+
/** Processing time through failure, including cache checks/retries for a source. */
|
|
26
|
+
readonly elapsedMs: number;
|
|
27
|
+
readonly elapsedScope: 'source' | 'semantic-run';
|
|
28
|
+
readonly timeoutMs: number;
|
|
29
|
+
readonly timeoutScope: 'provider-attempt' | 'module-execution';
|
|
30
|
+
readonly progress: SemanticRunProgress;
|
|
31
|
+
readonly forced: boolean;
|
|
32
|
+
readonly recovery: readonly string[];
|
|
33
|
+
}
|
|
34
|
+
export declare function semanticFailureCode(error: unknown, phase: SemanticHydrationPhase, signal?: AbortSignal): SemanticFailureCode;
|
|
35
|
+
export declare function semanticFailureCategory(code: SemanticFailureCode): SemanticHydrationFailure['category'];
|
|
36
|
+
/** Public failure envelope deliberately excludes raw errors, causes and provider output. */
|
|
37
|
+
export declare class SemanticHydrationError extends Error {
|
|
38
|
+
readonly report: SemanticHydrationFailure;
|
|
39
|
+
readonly code: SemanticFailureCode;
|
|
40
|
+
constructor(report: SemanticHydrationFailure);
|
|
41
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { SemanticProviderError } from '../extraction/semantic-process.js';
|
|
2
|
+
import { SemanticPolicyError } from '../extraction/semantic-diagnostics.js';
|
|
3
|
+
export function semanticFailureCode(error, phase, signal) {
|
|
4
|
+
if (signal?.aborted && (error === signal.reason ||
|
|
5
|
+
(error instanceof Error && error.name === 'AbortError') ||
|
|
6
|
+
(phase === 'semantic-extract' && !(error instanceof SemanticProviderError))))
|
|
7
|
+
return 'cancelled';
|
|
8
|
+
if (error instanceof SemanticProviderError &&
|
|
9
|
+
['timeout', 'cancelled', 'unavailable', 'exit', 'invalid-output'].includes(error.code))
|
|
10
|
+
return error.code;
|
|
11
|
+
if (error instanceof SemanticPolicyError && ['unresolved', 'low-confidence'].includes(error.code))
|
|
12
|
+
return error.code;
|
|
13
|
+
if (phase === 'semantic-cache-read' || phase === 'semantic-cache-write')
|
|
14
|
+
return 'cache-failure';
|
|
15
|
+
return phase === 'semantic-validate' ? 'invalid-output' : 'provider-failure';
|
|
16
|
+
}
|
|
17
|
+
export function semanticFailureCategory(code) {
|
|
18
|
+
if (code === 'timeout')
|
|
19
|
+
return 'timeout';
|
|
20
|
+
if (code === 'cancelled')
|
|
21
|
+
return 'cancellation';
|
|
22
|
+
if (code === 'unavailable' || code === 'cache-failure')
|
|
23
|
+
return 'infrastructure';
|
|
24
|
+
if (code === 'invalid-output' || code === 'unresolved' || code === 'low-confidence')
|
|
25
|
+
return 'extraction-gap';
|
|
26
|
+
return 'provider';
|
|
27
|
+
}
|
|
28
|
+
/** Public failure envelope deliberately excludes raw errors, causes and provider output. */
|
|
29
|
+
export class SemanticHydrationError extends Error {
|
|
30
|
+
report;
|
|
31
|
+
code;
|
|
32
|
+
constructor(report) {
|
|
33
|
+
const p = report.progress;
|
|
34
|
+
super(`Semantic hydration ${report.code}: ${report.sourceId ?? 'between semantic sources'}; phase ${report.phase}; ` +
|
|
35
|
+
`${report.elapsedScope} elapsed ${report.elapsedMs} ms; configured ${report.timeoutScope} timeout ${report.timeoutMs} ms. ` +
|
|
36
|
+
`${p.completed}/${p.total} completed (${p.extracted} extracted, ${p.reused} reused); ` +
|
|
37
|
+
`${p.remaining} remaining (${p.failed} failed, ${p.cancelled} cancelled, ${p.notStarted} not started).\n` +
|
|
38
|
+
report.recovery.join('\n'));
|
|
39
|
+
this.report = report;
|
|
40
|
+
this.name = 'SemanticHydrationError';
|
|
41
|
+
this.code = report.code;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { ImpactScanRequest } from '@weftlet/core';
|
|
2
|
+
import { type SemanticCacheInspection } from '../extraction/semantic-cache.js';
|
|
3
|
+
import { type SemanticInputIssue, type SemanticSelection } from '../extraction/semantic-sources.js';
|
|
4
|
+
import { type SemanticScope } from './semantic-scope.js';
|
|
5
|
+
export interface HydrationPlanOptions {
|
|
6
|
+
readonly ref?: string;
|
|
7
|
+
readonly forceSemantic?: boolean;
|
|
8
|
+
readonly request?: ImpactScanRequest;
|
|
9
|
+
}
|
|
10
|
+
export interface HydrationPlanDocument {
|
|
11
|
+
readonly path: string;
|
|
12
|
+
/** Local mapping for opaque IDs in semantic progress and failure reports. */
|
|
13
|
+
readonly sourceId: string;
|
|
14
|
+
readonly stableSemanticId: string;
|
|
15
|
+
readonly sourceDigest: string;
|
|
16
|
+
readonly bytes: number;
|
|
17
|
+
readonly lines: number;
|
|
18
|
+
readonly selectedBy: readonly string[];
|
|
19
|
+
readonly role: 'semantic-document' | 'validation-evidence';
|
|
20
|
+
readonly sourceAuthority: 'declared' | 'inferred';
|
|
21
|
+
readonly approvedBy: readonly string[];
|
|
22
|
+
readonly extractionReview: 'unreviewed';
|
|
23
|
+
readonly cache: Omit<SemanticCacheInspection, 'artifact'>;
|
|
24
|
+
}
|
|
25
|
+
export interface HydrationPlan {
|
|
26
|
+
readonly schemaVersion: 1;
|
|
27
|
+
readonly kind: 'hydration-plan';
|
|
28
|
+
readonly repositoryId: string;
|
|
29
|
+
readonly ref: string;
|
|
30
|
+
readonly commitSha: string;
|
|
31
|
+
readonly configurationDigest: string;
|
|
32
|
+
readonly ready: boolean;
|
|
33
|
+
readonly scope: SemanticScope & {
|
|
34
|
+
readonly complete: boolean;
|
|
35
|
+
};
|
|
36
|
+
readonly documents: readonly HydrationPlanDocument[];
|
|
37
|
+
readonly selections: readonly SemanticSelection[];
|
|
38
|
+
readonly budgets: {
|
|
39
|
+
readonly maxDocuments: number;
|
|
40
|
+
readonly maxSourceBytes: number;
|
|
41
|
+
readonly selectedDocuments: number;
|
|
42
|
+
readonly totalSourceBytes: number;
|
|
43
|
+
};
|
|
44
|
+
readonly estimates: {
|
|
45
|
+
readonly reusableArtifacts: number;
|
|
46
|
+
readonly extractions: number;
|
|
47
|
+
readonly unknownArtifacts: number;
|
|
48
|
+
};
|
|
49
|
+
readonly issues: readonly SemanticInputIssue[];
|
|
50
|
+
readonly excludedWorkingChanges: readonly string[];
|
|
51
|
+
readonly assumptions: readonly string[];
|
|
52
|
+
}
|
|
53
|
+
/** Inspect only committed source objects, config and existing artifacts; never initialize a provider or adapter. */
|
|
54
|
+
export declare function planHydration(configPath: string, options?: HydrationPlanOptions): Promise<HydrationPlan>;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { loadConfig } from '../configuration/config.js';
|
|
2
|
+
import { GitRepository } from '../repository/git.js';
|
|
3
|
+
import { matchesRepositoryGlob } from '../repository/glob.js';
|
|
4
|
+
import { createSemanticArtifactStore } from './semantic-artifact-store.js';
|
|
5
|
+
import { inspectSemanticCache } from '../extraction/semantic-cache.js';
|
|
6
|
+
import { semanticProviderIdentity } from '../extraction/semantic-identity.js';
|
|
7
|
+
import { selectSemanticInputs } from '../extraction/semantic-sources.js';
|
|
8
|
+
import { sha256, stableJson } from '../infrastructure/util.js';
|
|
9
|
+
import { resolveSemanticScope } from './semantic-scope.js';
|
|
10
|
+
import { semanticSourceId } from '../extraction/semantic-diagnostics.js';
|
|
11
|
+
async function describeDocument(source, selections, config, evidencePaths, store, forceSemantic = false) {
|
|
12
|
+
const inspection = forceSemantic
|
|
13
|
+
? { status: 'forced', reason: 'Explicit force bypasses existing artifacts; a new revision is allocated only during hydration.' }
|
|
14
|
+
: await inspectSemanticCache(store, config.semantic, source, semanticProviderIdentity(config.semantic));
|
|
15
|
+
const { artifact: _artifact, ...cache } = inspection;
|
|
16
|
+
const approvedBy = (config.approvedIntentSources ?? []).filter((pattern) => matchesRepositoryGlob(source.path, pattern));
|
|
17
|
+
return { path: source.path, sourceId: semanticSourceId(config.repositoryId, source),
|
|
18
|
+
stableSemanticId: source.stableSemanticId, sourceDigest: source.digest,
|
|
19
|
+
bytes: Buffer.byteLength(source.content), lines: source.content.split('\n').length,
|
|
20
|
+
selectedBy: selections.filter((item) => item.paths.includes(source.path)).map((item) => item.selector),
|
|
21
|
+
role: evidencePaths.has(source.path) ? 'validation-evidence' : 'semantic-document',
|
|
22
|
+
sourceAuthority: approvedBy.length ? 'declared' : 'inferred', approvedBy,
|
|
23
|
+
extractionReview: 'unreviewed', cache };
|
|
24
|
+
}
|
|
25
|
+
/** Inspect only committed source objects, config and existing artifacts; never initialize a provider or adapter. */
|
|
26
|
+
export async function planHydration(configPath, options = {}) {
|
|
27
|
+
const { config, repositoryRoot } = await loadConfig(configPath);
|
|
28
|
+
const repository = new GitRepository(repositoryRoot);
|
|
29
|
+
const ref = options.ref ?? 'HEAD';
|
|
30
|
+
const commitSha = await repository.resolveRef(ref);
|
|
31
|
+
const scope = await resolveSemanticScope(config, repository, commitSha, options.request);
|
|
32
|
+
const selection = await selectSemanticInputs(repository, commitSha, scope.selectors, config.semantic);
|
|
33
|
+
const issues = [...selection.issues];
|
|
34
|
+
const { omittedDocuments, ignoredSearchTerms } = scope;
|
|
35
|
+
const limited = omittedDocuments.length > 0 || ignoredSearchTerms > 0;
|
|
36
|
+
const complete = !limited && selection.selections.every((item) => item.status === 'matched');
|
|
37
|
+
if (limited)
|
|
38
|
+
issues.push({ code: 'selection-limited', severity: 'warning',
|
|
39
|
+
message: `Existing agent selection limits omitted ${omittedDocuments.length} documents and ${ignoredSearchTerms} search terms; this plan describes only the selected scope.`,
|
|
40
|
+
paths: omittedDocuments });
|
|
41
|
+
const store = createSemanticArtifactStore(repositoryRoot, config);
|
|
42
|
+
const evidencePaths = new Set(await repository.listFilesAt(commitSha, config.evidenceRoots));
|
|
43
|
+
const documents = [];
|
|
44
|
+
for (const source of selection.sources) {
|
|
45
|
+
const document = await describeDocument(source, selection.selections, config, evidencePaths, store, options.forceSemantic);
|
|
46
|
+
const { cache } = document;
|
|
47
|
+
if (cache.status === 'corrupt' || cache.status === 'unavailable')
|
|
48
|
+
issues.push({
|
|
49
|
+
code: `cache-${cache.status}`, severity: 'error', message: cache.reason, paths: [source.path],
|
|
50
|
+
});
|
|
51
|
+
documents.push(document);
|
|
52
|
+
}
|
|
53
|
+
const count = (...states) => documents.filter((doc) => states.includes(doc.cache.status)).length;
|
|
54
|
+
return {
|
|
55
|
+
schemaVersion: 1, kind: 'hydration-plan', repositoryId: config.repositoryId, ref, commitSha,
|
|
56
|
+
configurationDigest: sha256(stableJson(config)), ready: complete && !issues.some((item) => item.severity === 'error'),
|
|
57
|
+
scope: { ...scope, complete },
|
|
58
|
+
documents, selections: selection.selections, budgets: selection.budgets,
|
|
59
|
+
estimates: { reusableArtifacts: count('hit'), extractions: count('miss', 'forced'), unknownArtifacts: count('corrupt', 'unavailable') },
|
|
60
|
+
issues, excludedWorkingChanges: await repository.workingChanges(),
|
|
61
|
+
assumptions: [
|
|
62
|
+
'Sources come from the resolved commit; configuration and cache are read from the current local environment.',
|
|
63
|
+
'Estimates require unchanged source, configuration, provider contract and readable artifacts; concurrent changes can invalidate them.',
|
|
64
|
+
'Document and per-document UTF-8 byte limits apply to all selected documents, including cache hits; no token or monetary estimate is made.',
|
|
65
|
+
'Ready describes semantic inputs and readable cache only. Providers, credentials, adapters, storage writes, indexing, runtime evidence, routing, ontology and graph validation have not been checked.',
|
|
66
|
+
'Roles reflect configured evidence roots, not inferred prose meaning. Selected validation documents still undergo semantic extraction today; source approval never approves extracted assertions.',
|
|
67
|
+
'Selection is the configured scope, optionally narrowed by existing bounded agent selection; recursive SOT traversal and complete product coverage are not claimed.',
|
|
68
|
+
'Unmatched selectors and bounded scope omissions need review. They do not introduce new hydration gates: removing the last document can still publish a graph with its relationships removed.',
|
|
69
|
+
],
|
|
70
|
+
};
|
|
71
|
+
}
|
|
@@ -4,13 +4,11 @@ import type { GitRepository } from "../repository/git.js";
|
|
|
4
4
|
import type { OntologyCompiler } from "../extraction/ontology.js";
|
|
5
5
|
import type { SemanticHydrator } from "../extraction/semantic.js";
|
|
6
6
|
import type { ScipIndexResult, StaticIndexer } from "../extraction/static.js";
|
|
7
|
+
import { type HydrationProgressEvent } from './semantic-run.js';
|
|
8
|
+
export type { HydrationProgressEvent } from './semantic-run.js';
|
|
7
9
|
export interface HydrationOptions {
|
|
8
10
|
readonly signal?: AbortSignal;
|
|
9
|
-
readonly onProgress?: (event:
|
|
10
|
-
phase: string;
|
|
11
|
-
completed?: number;
|
|
12
|
-
total?: number;
|
|
13
|
-
}) => void;
|
|
11
|
+
readonly onProgress?: (event: HydrationProgressEvent) => void;
|
|
14
12
|
readonly ref: string;
|
|
15
13
|
readonly headName: string;
|
|
16
14
|
readonly forceSemantic?: boolean;
|