@weftlet/toolkit 0.4.0 → 0.5.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 CHANGED
@@ -109,6 +109,16 @@ for preview, retry and explicit legacy-cache adoption instructions.
109
109
 
110
110
  ## SHACL validation and performance
111
111
 
112
+ Starting with **0.5.0**, identity preflight runs before ontology/RDF work.
113
+ `hydrate --json --quiet` reports conflicts using opaque references; `--validation-details` explicitly
114
+ includes local identities, producer versions and citations. Validation emits phase-boundary times
115
+ and graph counts, without a percentage or live heartbeat. Full SHACL remains required after a
116
+ passing preflight. See [ADR 021](docs/ADR-021-identity-preflight-and-validation-timing.md).
117
+
118
+ Version 0.5.0 also accepts `semantic.timeoutMs: 600000` for an approved ten-minute extraction
119
+ attempt; the default remains two minutes. See [provider limits and reuse](docs/PROVIDERS.md#limits-and-reuse)
120
+ before retrying with compatible cached artifacts.
121
+
112
122
  Starting with 0.3.0, the toolkit indexes a temporary union to accelerate cold validation.
113
123
  The toolkit uses JavaScript `rdf-validate-shacl` and an in-memory
114
124
  N3 store. Each hydration validates the complete graph; semantic artifact reuse does not make
@@ -135,7 +145,7 @@ pnpm benchmark:shacl
135
145
 
136
146
  Current hydration progress reports phase boundaries. The validator performs synchronous work,
137
147
  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
148
+ thread. Worker-based progress, validation-result reuse and incremental
139
149
  validation remain separate T05 work; they do not delay the focused cold-validation release.
140
150
 
141
151
  ## Development
@@ -14,6 +14,8 @@ export interface HydrationOptions {
14
14
  readonly forceSemantic?: boolean;
15
15
  readonly snapshotSuffix?: string;
16
16
  readonly requireClean?: boolean;
17
+ /** Explicit local diagnostics may disclose repository identities, producers and citations. */
18
+ readonly validationDetails?: boolean;
17
19
  readonly semanticSources?: readonly string[];
18
20
  readonly runtimeEvidenceRevision?: RuntimeEvidenceRevision;
19
21
  }
@@ -12,6 +12,8 @@ import { extractRoutingDeclarations, routingExtractorIdentity } from '../extract
12
12
  import { SemanticProviderError } from '../extraction/semantic-process.js';
13
13
  import { hydrateSemanticSources } from './semantic-run.js';
14
14
  import { graphAssemblyVersion, graphAssemblyIdentity } from './extraction-identity.js';
15
+ import { assertGraphIdentities } from '../graph/identity-preflight.js';
16
+ import { measureValidationPhase } from '../graph/validation-progress.js';
15
17
  export class ContextGraphHydrator {
16
18
  dependencies;
17
19
  constructor(dependencies) {
@@ -157,11 +159,19 @@ export class ContextGraphHydrator {
157
159
  diagnostics.push(...documents.diagnostics);
158
160
  diagnostics.push(...routing.diagnostics);
159
161
  checkpoint();
160
- options.onProgress?.({ phase: 'compile-semantic-rdf' });
161
- const ontology = await this.dependencies.ontologyCompiler.compile(snapshotId, artifacts, context);
162
162
  const runtimeEvidence = runtimeRevision.references;
163
163
  const runtimeFacts = runtimeEvidenceFacts(context, runtimeEvidence);
164
164
  const facts = [...semanticFacts, ...documents.facts, ...extractorFacts, ...routing.facts, ...runtimeFacts].sort((left, right) => left.id.localeCompare(right.id));
165
+ const validationCounts = { factCount: facts.length };
166
+ await measureValidationPhase('validate-identities', validationCounts, options.onProgress, () => {
167
+ const report = assertGraphIdentities(facts, {
168
+ repositoryId: config.repositoryId, includeDetails: options.validationDetails,
169
+ });
170
+ validationCounts.nodeCount = report.nodeCount;
171
+ });
172
+ checkpoint();
173
+ options.onProgress?.({ phase: 'compile-semantic-rdf' });
174
+ const ontology = await this.dependencies.ontologyCompiler.compile(snapshotId, artifacts, context);
165
175
  const invariants = (await Promise.all(this.dependencies.invariantEvaluators.map((evaluator) => evaluator.evaluate(snapshotId, facts)))).flat();
166
176
  const failures = invariants.filter((invariant) => invariant.status === 'fail');
167
177
  if (failures.length > 0) {
@@ -231,8 +241,8 @@ export class ContextGraphHydrator {
231
241
  diagnostics,
232
242
  };
233
243
  checkpoint();
234
- options.onProgress?.({ phase: 'validate-shacl' });
235
- const validation = await new RdfEvidenceGraph(snapshot).validate();
244
+ const graph = await measureValidationPhase('build-rdf-evidence', validationCounts, options.onProgress, () => new RdfEvidenceGraph(snapshot));
245
+ const validation = await graph.validate({ onProgress: (event) => options.onProgress?.({ ...event, nodeCount: validationCounts.nodeCount }) });
236
246
  if (!validation.conforms) {
237
247
  throw new Error(`Graph extraction failed SHACL validation: ${JSON.stringify(validation.issues)}`);
238
248
  }
@@ -3,4 +3,6 @@ import type { GraphSnapshot } from "@weftlet/core";
3
3
  import { GitRepository } from "../repository/git.js";
4
4
  import { FileSnapshotStore } from "../storage/storage.js";
5
5
  /** Conservative code overlay: reindex implementation; invalidate changed prose, never synthesize intent. */
6
- export declare function buildWorkingOverlay(repository: GitRepository, config: ContextGraphConfig, store: FileSnapshotStore, storageRoot: string, baseSnapshotId: string, agent?: string): Promise<GraphSnapshot>;
6
+ export declare function buildWorkingOverlay(repository: GitRepository, config: ContextGraphConfig, store: FileSnapshotStore, storageRoot: string, baseSnapshotId: string, agent?: string, options?: {
7
+ readonly validationDetails?: boolean;
8
+ }): Promise<GraphSnapshot>;
@@ -12,13 +12,14 @@ import { inWorkingScope, readWorkingContent } from "../repository/working-conten
12
12
  import { extractRoutingDeclarations, routingExtractorIdentity } from '../extraction/routing.js';
13
13
  import { RdfEvidenceGraph } from '../graph/rdf.js';
14
14
  import { graphAssemblyIdentity } from './extraction-identity.js';
15
+ import { assertGraphIdentities } from '../graph/identity-preflight.js';
15
16
  const execute = promisify(execFile);
16
17
  const implementationExtractors = new Set([
17
18
  'repository-file-extractor', 'repository-contract-extractor', 'scip-symbol-extractor',
18
19
  routingExtractorIdentity.id,
19
20
  ]);
20
21
  /** Conservative code overlay: reindex implementation; invalidate changed prose, never synthesize intent. */
21
- export async function buildWorkingOverlay(repository, config, store, storageRoot, baseSnapshotId, agent = 'default') {
22
+ export async function buildWorkingOverlay(repository, config, store, storageRoot, baseSnapshotId, agent = 'default', options = {}) {
22
23
  const base = await store.read(baseSnapshotId);
23
24
  if (!base || base.manifest.overlayDigest)
24
25
  throw new Error('Overlay requires a committed base snapshot');
@@ -119,6 +120,7 @@ export async function buildWorkingOverlay(repository, config, store, storageRoot
119
120
  !affected.has(fact.provenance.path) &&
120
121
  ![fact.subject, fact.object].some((node) => [...affected].some((path) => node.id === `component:file:${path}` || node.id === `document:${path}` || node.label === path))).map((fact) => ({ ...fact, snapshotId }));
121
122
  const allFacts = [...retained, ...extracted.facts].sort((a, b) => a.id.localeCompare(b.id));
123
+ assertGraphIdentities(allFacts, { repositoryId: config.repositoryId, includeDetails: options.validationDetails });
122
124
  const overlay = {
123
125
  ...base,
124
126
  manifest: {
@@ -7,6 +7,9 @@ export interface HydrationProgressEvent {
7
7
  readonly total?: number;
8
8
  readonly sourceId?: string;
9
9
  readonly elapsedMs?: number;
10
+ readonly status?: 'started' | 'completed' | 'failed';
11
+ readonly factCount?: number;
12
+ readonly nodeCount?: number;
10
13
  }
11
14
  /** Settle active workers before reporting failure; never publish snapshots here. */
12
15
  export declare function hydrateSemanticSources(options: {
@@ -113,7 +113,7 @@ function validateConfig(value, absolutePath) {
113
113
  requireConfig(auth.apiKeyEnv === undefined || (typeof auth.apiKeyEnv === 'string' && /^[A-Za-z_][A-Za-z0-9_]*$/.test(auth.apiKeyEnv)), 'semantic.auth.apiKeyEnv must name an environment variable', absolutePath);
114
114
  }
115
115
  }
116
- for (const [field, max] of [['timeoutMs', 300_000], ['retries', 2], ['maxDocuments', 1000], ['maxSourceBytes', 1_048_576]]) {
116
+ for (const [field, max] of [['timeoutMs', 600_000], ['retries', 2], ['maxDocuments', 1000], ['maxSourceBytes', 1_048_576]]) {
117
117
  const item = value.semantic[field];
118
118
  if (item !== undefined)
119
119
  requireConfig(Number.isInteger(item) && Number(item) >= (field === 'retries' ? 0 : 1) && Number(item) <= max, `semantic.${field} exceeds supported bounds`, absolutePath);
@@ -0,0 +1,57 @@
1
+ import { type ExtractorIdentity, type GraphFact, type GraphNodeKind, type SourceSpan } from '@weftlet/core';
2
+ /** Diagnostic detail is an invocation option, not extraction policy or a cache identity input. */
3
+ export interface GraphIdentityPreflightOptions {
4
+ readonly repositoryId: string;
5
+ readonly includeDetails?: boolean;
6
+ }
7
+ export type ReportedIdentityKind = GraphNodeKind | `unknown-kind-${string}`;
8
+ export interface GraphIdentityOccurrenceDetails {
9
+ readonly nodeId: string;
10
+ readonly nodeKind: GraphNodeKind;
11
+ readonly factId: string;
12
+ readonly extractor: ExtractorIdentity;
13
+ readonly provenance: SourceSpan;
14
+ readonly confidence: number;
15
+ readonly authority?: GraphFact['authority'];
16
+ readonly sourceAuthority?: GraphFact['sourceAuthority'];
17
+ readonly extractionReview?: GraphFact['extractionReview'];
18
+ }
19
+ export interface GraphIdentityOccurrence {
20
+ readonly factIndex: number;
21
+ readonly side: 'subject' | 'object';
22
+ readonly kind: ReportedIdentityKind;
23
+ readonly factRef: string;
24
+ readonly sourceRef: string;
25
+ readonly extractorRef: string;
26
+ readonly details?: GraphIdentityOccurrenceDetails;
27
+ }
28
+ export interface GraphIdentityConflict {
29
+ readonly nodeRef: string;
30
+ readonly kinds: readonly ReportedIdentityKind[];
31
+ readonly occurrences: readonly GraphIdentityOccurrence[];
32
+ readonly details?: {
33
+ readonly nodeId: string;
34
+ };
35
+ }
36
+ export interface GraphIdentityPreflightReport {
37
+ readonly schemaVersion: 1;
38
+ readonly kind: 'graph-identity-preflight';
39
+ readonly category: 'extraction-gap';
40
+ readonly phase: 'validate-identities';
41
+ readonly passed: boolean;
42
+ /** A passing identity preflight never establishes full graph conformance. */
43
+ readonly shaclValidated: false;
44
+ readonly factCount: number;
45
+ readonly nodeCount: number;
46
+ readonly conflictCount: number;
47
+ readonly conflicts: readonly GraphIdentityConflict[];
48
+ }
49
+ /** Find the single-kind constraint's conflicts without constructing RDF or changing any fact. */
50
+ export declare function inspectGraphIdentities(facts: readonly GraphFact[], options: GraphIdentityPreflightOptions): GraphIdentityPreflightReport;
51
+ /** The message is safe even when the caller explicitly requested local report details. */
52
+ export declare class GraphIdentityConflictError extends Error {
53
+ readonly report: GraphIdentityPreflightReport;
54
+ readonly code = "node-kind-conflict";
55
+ constructor(report: GraphIdentityPreflightReport);
56
+ }
57
+ export declare function assertGraphIdentities(facts: readonly GraphFact[], options: GraphIdentityPreflightOptions): GraphIdentityPreflightReport;
@@ -0,0 +1,71 @@
1
+ import { sha256, stableJson } from '@weftlet/core';
2
+ const publicKinds = new Set([
3
+ 'Project', 'Document', 'Capability', 'Workflow', 'Component', 'Contract', 'Evidence',
4
+ 'Invariant', 'Snapshot', 'Provider', 'PersistenceModel', 'Scope',
5
+ ]);
6
+ /** Find the single-kind constraint's conflicts without constructing RDF or changing any fact. */
7
+ export function inspectGraphIdentities(facts, options) {
8
+ const identities = new Map();
9
+ for (const fact of facts)
10
+ for (const node of [fact.subject, fact.object]) {
11
+ let kinds = identities.get(node.id);
12
+ if (!kinds)
13
+ identities.set(node.id, kinds = new Set());
14
+ kinds.add(node.kind);
15
+ }
16
+ const ref = (domain, ...values) => `identity-${domain}-${sha256(stableJson(['graph-identity-preflight-v1', options.repositoryId, domain, ...values]))}`;
17
+ const reportedKind = (kind) => publicKinds.has(kind)
18
+ ? kind : `unknown-kind-${sha256(stableJson(['graph-identity-kind-v1', options.repositoryId, kind]))}`;
19
+ const conflicts = new Map();
20
+ for (const [id, kinds] of identities)
21
+ if (kinds.size > 1) {
22
+ conflicts.set(id, { nodeRef: ref('node', id), kinds: [...kinds].map(reportedKind), occurrences: [],
23
+ ...(options.includeDetails ? { details: { nodeId: id } } : {}) });
24
+ }
25
+ // The common conflict-free path allocates no evidence reports. Preserve every conflicting
26
+ // occurrence, including duplicate fact IDs and the two ends of a self-reference.
27
+ if (conflicts.size)
28
+ for (const [factIndex, fact] of facts.entries()) {
29
+ const sides = ['subject', 'object'].filter(side => conflicts.has(fact[side].id));
30
+ if (!sides.length)
31
+ continue;
32
+ const references = { factRef: ref('fact', fact.id), sourceRef: ref('source', fact.provenance.path),
33
+ extractorRef: ref('extractor', fact.extractor.id, fact.extractor.version) };
34
+ for (const side of sides) {
35
+ const node = fact[side];
36
+ conflicts.get(node.id).occurrences.push({ factIndex, side, kind: reportedKind(node.kind), ...references,
37
+ ...(options.includeDetails ? { details: {
38
+ nodeId: node.id, nodeKind: node.kind, factId: fact.id,
39
+ extractor: { id: fact.extractor.id, version: fact.extractor.version },
40
+ provenance: { path: fact.provenance.path, startLine: fact.provenance.startLine,
41
+ endLine: fact.provenance.endLine, digest: fact.provenance.digest, commitSha: fact.provenance.commitSha },
42
+ confidence: fact.confidence,
43
+ ...(fact.authority === undefined ? {} : { authority: fact.authority }),
44
+ ...(fact.sourceAuthority === undefined ? {} : { sourceAuthority: fact.sourceAuthority }),
45
+ ...(fact.extractionReview === undefined ? {} : { extractionReview: fact.extractionReview }),
46
+ } } : {}) });
47
+ }
48
+ }
49
+ return { schemaVersion: 1, kind: 'graph-identity-preflight', category: 'extraction-gap',
50
+ phase: 'validate-identities', passed: conflicts.size === 0, shaclValidated: false,
51
+ factCount: facts.length, nodeCount: identities.size, conflictCount: conflicts.size,
52
+ conflicts: [...conflicts.values()] };
53
+ }
54
+ /** The message is safe even when the caller explicitly requested local report details. */
55
+ export class GraphIdentityConflictError extends Error {
56
+ report;
57
+ code = 'node-kind-conflict';
58
+ constructor(report) {
59
+ super(`Graph identity preflight found ${report.conflictCount} node kind conflict(s) across ${report.factCount} facts. ` +
60
+ 'Full SHACL validation was not run. Use --validation-details for local node and cited evidence details. ' +
61
+ 'Correct the extractor or assertion identity disagreement, then retry; no graph facts were rewritten by this check.');
62
+ this.report = report;
63
+ this.name = 'GraphIdentityConflictError';
64
+ }
65
+ }
66
+ export function assertGraphIdentities(facts, options) {
67
+ const report = inspectGraphIdentities(facts, options);
68
+ if (!report.passed)
69
+ throw new GraphIdentityConflictError(report);
70
+ return report;
71
+ }
@@ -1,4 +1,5 @@
1
1
  import type { GraphFact, GraphSnapshot } from "@weftlet/core";
2
+ import { type GraphValidationProgress } from './validation-progress.js';
2
3
  export { CG } from './shacl-shapes.js';
3
4
  export declare const nodeIri: (id: string) => string;
4
5
  export declare const factIri: (id: string) => string;
@@ -7,7 +8,9 @@ export declare class RdfEvidenceGraph {
7
8
  readonly snapshot: GraphSnapshot;
8
9
  private readonly dataset;
9
10
  constructor(snapshot: GraphSnapshot);
10
- validate(): Promise<{
11
+ validate(options?: {
12
+ readonly onProgress?: (event: GraphValidationProgress) => void;
13
+ }): Promise<{
11
14
  conforms: boolean;
12
15
  issues: {
13
16
  category: "extraction-gap";
package/dist/graph/rdf.js CHANGED
@@ -5,6 +5,7 @@ import { contextPackEvidenceAuthority } from "./authority.js";
5
5
  import { stableJson } from "../infrastructure/util.js";
6
6
  import { createRequire } from 'node:module';
7
7
  import { CG, RDF, XSD, evidenceShapes } from './shacl-shapes.js';
8
+ import { measureValidationPhase } from './validation-progress.js';
8
9
  const { namedNode: iri, literal } = DataFactory;
9
10
  export { CG } from './shacl-shapes.js';
10
11
  export const nodeIri = (id) => `urn:context-graph:node:${encodeURIComponent(id)}`;
@@ -61,16 +62,19 @@ export class RdfEvidenceGraph {
61
62
  this.dataset.addQuad(iri('urn:context-graph:snapshot'), iri(CG + 'configurationDigest'), literal(snapshot.manifest.configurationDigest));
62
63
  }
63
64
  }
64
- async validate() {
65
+ async validate(options = {}) {
65
66
  // These graph-independent shapes already read the dataset as a union. Index
66
67
  // that union once so every property lookup avoids scanning one graph per fact.
67
68
  // Keep every triple; the original named dataset retains assertion provenance
68
69
  // and remains the source for queries and serialization.
69
- const validationGraph = new Store();
70
- for (const { subject, predicate, object } of this.dataset) {
71
- validationGraph.addQuad(subject, predicate, object);
72
- }
73
- const report = await new SHACLValidator(new Store(evidenceShapes)).validate(validationGraph);
70
+ const counts = { factCount: this.snapshot.facts.length };
71
+ const validationGraph = await measureValidationPhase('build-validation-union', counts, options.onProgress, () => {
72
+ const union = new Store();
73
+ for (const { subject, predicate, object } of this.dataset)
74
+ union.addQuad(subject, predicate, object);
75
+ return union;
76
+ });
77
+ const report = await measureValidationPhase('validate-shacl', counts, options.onProgress, () => new SHACLValidator(new Store(evidenceShapes)).validate(validationGraph));
74
78
  const issues = report.results.map((result) => ({
75
79
  category: 'extraction-gap',
76
80
  focus: result.focusNode?.value,
@@ -0,0 +1,14 @@
1
+ export type GraphValidationPhase = 'validate-identities' | 'build-rdf-evidence' | 'build-validation-union' | 'validate-shacl';
2
+ export interface GraphValidationProgress {
3
+ readonly phase: GraphValidationPhase;
4
+ readonly status: 'started' | 'completed' | 'failed';
5
+ /** Wall time for this phase, not a completion estimate or in-phase heartbeat. */
6
+ readonly elapsedMs: number;
7
+ readonly factCount: number;
8
+ readonly nodeCount?: number;
9
+ }
10
+ /** Phase boundaries remain observable even when an operation blocks same-thread timers. */
11
+ export declare function measureValidationPhase<T>(phase: GraphValidationPhase, counts: {
12
+ readonly factCount: number;
13
+ readonly nodeCount?: number;
14
+ }, onProgress: ((event: GraphValidationProgress) => void) | undefined, operation: () => T | Promise<T>): Promise<T>;
@@ -0,0 +1,18 @@
1
+ /** Phase boundaries remain observable even when an operation blocks same-thread timers. */
2
+ export async function measureValidationPhase(phase, counts, onProgress, operation) {
3
+ const started = performance.now();
4
+ const emit = (status) => onProgress?.({
5
+ phase, status, ...counts, elapsedMs: Math.max(0, Math.round(performance.now() - started)),
6
+ });
7
+ emit('started');
8
+ let result;
9
+ try {
10
+ result = await operation();
11
+ }
12
+ catch (error) {
13
+ emit('failed');
14
+ throw error;
15
+ }
16
+ emit('completed');
17
+ return result;
18
+ }
package/dist/index.d.ts CHANGED
@@ -13,3 +13,5 @@ export * from './application/hydration-plan.js';
13
13
  export * from './application/cache-adoption.js';
14
14
  export * from './application/hydration-failure.js';
15
15
  export * from './extraction/semantic-diagnostics.js';
16
+ export * from './graph/identity-preflight.js';
17
+ export * from './graph/validation-progress.js';
package/dist/index.js CHANGED
@@ -14,3 +14,5 @@ export * from './application/hydration-plan.js';
14
14
  export * from './application/cache-adoption.js';
15
15
  export * from './application/hydration-failure.js';
16
16
  export * from './extraction/semantic-diagnostics.js';
17
+ export * from './graph/identity-preflight.js';
18
+ export * from './graph/validation-progress.js';
@@ -18,6 +18,7 @@ import { loadConfig } from "../configuration/config.js";
18
18
  import { planHydration } from '../application/hydration-plan.js';
19
19
  import { adoptSemanticCache } from '../application/cache-adoption.js';
20
20
  import { SemanticHydrationError } from '../application/hydration-failure.js';
21
+ import { GraphIdentityConflictError } from '../graph/identity-preflight.js';
21
22
  function valueAfter(args, name) {
22
23
  const index = args.indexOf(name);
23
24
  return index >= 0 ? args[index + 1] : undefined;
@@ -82,7 +83,7 @@ function formatHydrationPlan(plan) {
82
83
  async function main() {
83
84
  const args = process.argv.slice(2);
84
85
  if (args.includes('--help') || !args.length) {
85
- process.stdout.write('weftlet init|config show|config validate|doctor|hydrate|cache adopt|overlay|impact scan|sparql|validate|govern|visualize|diagnostics show|invariant check|clean-compare|ontology compile\nUse --config <file>; queries accept --snapshot <id>. impact scan accepts --changed-file, --capability, --max-facts, --max-depth, --continuation.\nhydrate --plan [--json] [--ref <commit>] [--force-semantic] previews scope, cache and budgets without model calls or graph writes. Preview readiness is advisory and does not add a hydration gate.\nhydrate --json --quiet emits structured semantic failures on stderr with no progress lines; failure stdout stays empty. hydrate --plan maps opaque source IDs to local document paths.\ncache adopt --from-config <previous.json> [--config <current.json>] [--ref <commit>] [--dry-run] returns JSON and copies only validated compatible artifacts, without model calls or snapshot writes. --dry-run performs no cache writes. Agent configurations accept the same --owner-doc, --task and --capability selection as hydrate.\ninit [--yes] [--directory <project>] [--config <file>] [--repository-id <id>] [--code-root <path>] [--semantic-source <path>] [--evidence-root <path>] [--model <name>] [--no-gitignore]\nSource flags may be repeated. init never overwrites an existing config. See README.md for examples.\n');
86
+ process.stdout.write('weftlet init|config show|config validate|doctor|hydrate|cache adopt|overlay|impact scan|sparql|validate|govern|visualize|diagnostics show|invariant check|clean-compare|ontology compile\nUse --config <file>; queries accept --snapshot <id>. impact scan accepts --changed-file, --capability, --max-facts, --max-depth, --continuation.\nhydrate --plan [--json] [--ref <commit>] [--force-semantic] previews scope, cache and budgets without model calls or graph writes. Preview readiness is advisory and does not add a hydration gate.\nhydrate --json --quiet emits structured semantic failures on stderr with no progress lines; failure stdout stays empty. hydrate --plan maps opaque source IDs to local document paths.\nhydrate|overlay --validation-details explicitly includes local node/fact identities, extractor names and source citations in identity-conflict errors; default reports use opaque references. This flag writes no diagnostic file. Use --json --quiet for structured identity-conflict stderr and empty failure stdout. Validation timings report phase boundaries, not a live heartbeat or percentage.\ncache adopt --from-config <previous.json> [--config <current.json>] [--ref <commit>] [--dry-run] returns JSON and copies only validated compatible artifacts, without model calls or snapshot writes. --dry-run performs no cache writes. Agent configurations accept the same --owner-doc, --task and --capability selection as hydrate.\ninit [--yes] [--directory <project>] [--config <file>] [--repository-id <id>] [--code-root <path>] [--semantic-source <path>] [--evidence-root <path>] [--model <name>] [--no-gitignore]\nSource flags may be repeated. init never overwrites an existing config. See README.md for examples.\n');
86
87
  return;
87
88
  }
88
89
  if (args[0] === 'init') {
@@ -171,7 +172,7 @@ async function main() {
171
172
  const base = valueAfter(args, '--base-snapshot');
172
173
  if (!base)
173
174
  throw new Error('overlay requires --base-snapshot <committed snapshot ID>');
174
- const result = await buildWorkingOverlay(application.repository, application.config, application.snapshotStore, application.storageRoot, base, valueAfter(args, '--agent'));
175
+ const result = await buildWorkingOverlay(application.repository, application.config, application.snapshotStore, application.storageRoot, base, valueAfter(args, '--agent'), { validationDetails: args.includes('--validation-details') });
175
176
  process.stdout.write(`${JSON.stringify(result.manifest, null, 2)}\n`);
176
177
  return;
177
178
  }
@@ -187,8 +188,11 @@ async function main() {
187
188
  headName: scope?.headName ?? application.headName,
188
189
  semanticSources: scope?.semanticSources,
189
190
  forceSemantic: args.includes('--force-semantic'),
191
+ validationDetails: args.includes('--validation-details'),
190
192
  signal: controller.signal,
191
193
  onProgress: args.includes('--quiet') ? undefined : (event) => process.stderr.write(`[context-graph] ${event.phase}${event.total === undefined ? '' : ` ${event.completed}/${event.total}`}` +
194
+ `${event.status === undefined ? '' : ` ${event.status}`}` +
195
+ `${event.factCount === undefined ? '' : ` facts=${event.factCount}`}${event.nodeCount === undefined ? '' : ` nodes=${event.nodeCount}`}` +
192
196
  `${event.sourceId === undefined ? '' : ` ${event.sourceId}`}${event.elapsedMs === undefined ? '' : ` ${event.elapsedMs} ms`}\n`),
193
197
  });
194
198
  process.stdout.write(`${JSON.stringify({
@@ -257,8 +261,11 @@ async function main() {
257
261
  throw new Error('Usage: weftlet hydrate|clean-compare|impact scan|diagnostics show --snapshot <id>|invariant check|ontology compile|visualize --output <file.html|file.dot|file.svg>');
258
262
  }
259
263
  main().catch((error) => {
260
- process.stderr.write(`${error instanceof SemanticHydrationError
261
- ? process.argv.includes('--json') ? JSON.stringify(error.report, null, 2) : error.message
262
- : error instanceof Error ? (error.stack ?? error.message) : String(error)}\n`);
264
+ process.stderr.write(`${error instanceof GraphIdentityConflictError
265
+ ? process.argv.includes('--json') || process.argv.includes('--validation-details')
266
+ ? JSON.stringify(error.report, null, 2) : error.message
267
+ : error instanceof SemanticHydrationError
268
+ ? process.argv.includes('--json') ? JSON.stringify(error.report, null, 2) : error.message
269
+ : error instanceof Error ? (error.stack ?? error.message) : String(error)}\n`);
263
270
  process.exitCode = 1;
264
271
  });
@@ -1,7 +1,7 @@
1
1
  # ADR-018: Preserve Codex artifacts across operational configuration changes
2
2
 
3
- Status: accepted and implemented in development source after 0.3.0; release evidence is recorded
4
- in [validation](VALIDATION.md). This increment does not claim a new npm publication.
3
+ Status: accepted and shipped in 0.4.0; release and validation evidence is recorded in
4
+ [validation](VALIDATION.md).
5
5
 
6
6
  ## Problem
7
7
 
@@ -1,7 +1,7 @@
1
1
  # ADR-019: Safe semantic failure diagnostics and settled progress
2
2
 
3
- Status: implemented in development source after 0.3.0; validation and publication are recorded
4
- separately in [validation](VALIDATION.md). This decision does not change extraction identity.
3
+ Status: shipped in 0.4.0; validation and publication are recorded in [validation](VALIDATION.md).
4
+ This decision does not change extraction identity.
5
5
 
6
6
  ## Problem
7
7
 
@@ -1,7 +1,7 @@
1
1
  # ADR-020: One physical-file policy for deterministic producers and adapters
2
2
 
3
- Status: implemented in development source after 0.3.0; release/consumer acceptance is recorded
4
- separately in [validation](VALIDATION.md).
3
+ Status: upstream fix shipped in 0.4.0; release evidence and pending consumer adapter/hydration
4
+ acceptance are recorded separately in [validation](VALIDATION.md).
5
5
 
6
6
  ## Reported defect and ownership
7
7
 
@@ -0,0 +1,81 @@
1
+ # ADR-021: Early identity conflicts and honest validation phase timing
2
+
3
+ Status: implemented in development source after 0.4.0. Publication and consumer acceptance
4
+ are separate checkpoints in [validation](VALIDATION.md). This is the bounded T05a increment.
5
+
6
+ ## Decision
7
+
8
+ Before ontology compilation, invariant evaluation or RDF construction, scan every assembled
9
+ fact's subject and object identity for multiple kinds. The scan covers semantic, document,
10
+ static, adapter, routing and runtime facts, including conceptual identities. Working overlays
11
+ run the same check over retained and newly extracted facts before RDF construction/publication.
12
+ No fact, kind, ID, citation or authority is changed or discarded by the check.
13
+ This runs after semantic/static extraction; it is separate from no-model `hydrate --plan`.
14
+
15
+ `inspectGraphIdentities(facts, { repositoryId, includeDetails? })` returns a report;
16
+ `assertGraphIdentities` throws `GraphIdentityConflictError` on conflicts. Both are public toolkit
17
+ exports. A passing report has `passed: true` and **`shaclValidated: false`**. Consistent kinds
18
+ alone do not establish canonical classification, correct intent, valid citations or conformance.
19
+ The existing full RDF/SHACL path and shapes remain mandatory for successful publication. Direct
20
+ `RdfEvidenceGraph.validate()` and the saved `validate` command still run all checks and return
21
+ their existing verdict format. There is no validation cache, incremental validator or backend change.
22
+
23
+ The two-pass scan is linear in fact occurrences. The common conflict-free path creates no
24
+ per-evidence diagnostic records. On failure it reports every conflicting identity and occurrence,
25
+ including both ends of a self-reference, repeated fact IDs and late conflicts. Counts are complete;
26
+ there is no hidden document, hop or diagnostic cutoff. Reports retain input indices and side so
27
+ duplicate assertion IDs cannot conceal a producer's occurrence.
28
+
29
+ ## Privacy and attribution
30
+
31
+ There was no general configurable diagnostic privacy policy. This increment therefore makes
32
+ local detail an explicit invocation option, without adding an extraction/configuration field.
33
+ Default reports contain repository-scoped opaque node, fact, source and extractor references,
34
+ counts and recognized kind names. Unknown kind strings are hashed as well. References correlate
35
+ records; they are not encryption or proof that a low-entropy identifier cannot be guessed.
36
+
37
+ `hydrate --json --quiet` emits a typed identity-failure report on stderr with empty stdout.
38
+ Use `--validation-details` on `hydrate` or `overlay` only when local identities and citations
39
+ may be displayed. That option includes exact node/fact IDs, extractor identity/version, citation
40
+ path/lines/digest/commit, confidence and the original optional authority/review fields. It does
41
+ not include labels, node attributes, source text, prompts or raw provider output. Absent authority
42
+ fields stay absent; source approval is never promoted into assertion approval.
43
+
44
+ The programmatic equivalent is `HydrationOptions.validationDetails` or the overlay's final
45
+ options argument. Detail changes do not enter snapshot, provider or semantic-cache identities.
46
+ The error message stays safe even when its report includes explicitly requested local details.
47
+ No diagnostic file is written automatically. Existing non-identity SHACL errors retain their
48
+ existing detailed behavior; this is not a claim that every command/error has been redacted.
49
+
50
+ ## Timing and failure preservation
51
+
52
+ Hydration reports started/completed/failed boundaries and elapsed wall time for identity
53
+ preflight, RDF construction, union construction and full SHACL. Counts describe graph size,
54
+ not validator completion. A completed SHACL phase means the validator returned, including a
55
+ nonconforming verdict. `RdfEvidenceGraph.validate({ onProgress })` exposes its union/SHACL phases.
56
+
57
+ The synchronous JavaScript work can block same-thread timers. These events are not heartbeats,
58
+ percentages, new timeout controls or interruptible worker execution. Worker isolation remains a
59
+ separate decision. The public profiling harness records preflight and validation phase timings
60
+ alongside its existing construction, resource and runtime measurements.
61
+
62
+ Failure preserves completed semantic artifacts and prior snapshots/heads. Correcting and
63
+ versioning an adapter still requires a fresh assembly and full validation, but compatible
64
+ semantic artifacts can be reused. This preflight does not rewrite cached model assertions or
65
+ choose an authoritative business rule. Evidence disagreements must be resolved at their owner.
66
+
67
+ No extraction/assembly version changes are needed: accepted graph facts, cache identities,
68
+ RDF serialization and conformance constraints are unchanged. The check rejects an existing
69
+ single-kind violation earlier; it does not make old snapshots satisfy current validation.
70
+
71
+ ## Evidence and remaining work
72
+
73
+ Tests cover full cross-source attribution, conceptual and physical nodes, exact authority,
74
+ default privacy, late conflicts, duplicates/self-references, immutable artifacts/snapshots,
75
+ corrected retries and non-kind failures that still reach full SHACL. CLI and packed-consumer
76
+ cases use actual TypeScript SCIP and public adapters. Existing positive/negative named-dataset
77
+ SHACL equivalence tests remain unchanged except for an additional timing/parity case.
78
+
79
+ Broader T05 work remains: worker-based progress/cancellation, repeated/changed-input performance
80
+ evaluation, and evidence-driven decisions about conformance-result reuse or incremental/native
81
+ backends. This increment does not infer private consumer performance from public fixtures.
package/docs/PROVIDERS.md CHANGED
@@ -87,6 +87,13 @@ Codex attempt (or module execution), no retries, and the configured concurrency
87
87
  before any model call. `maxDocuments`, `maxSourceBytes`, `timeoutMs`, and `retries` may be configured
88
88
  within validated limits. Review scope and cost before raising them; these byte/document limits
89
89
  are not dollar or token estimates. Ask the operator before substantial paid runs.
90
+ Starting with 0.5.0, `semantic.timeoutMs` accepts integer values from 1 through **600000**
91
+ (ten minutes); 0.4.0 and earlier reject values above 300000. The default remains 120000.
92
+ For the approved ten-minute retry, set `"timeoutMs": 600000` inside the existing `semantic`
93
+ configuration, preview reuse with `hydrate --plan`, then rerun hydration without forcing
94
+ re-extraction. The limit applies to each Codex attempt, or the whole module execution, rather
95
+ than the entire hydration. Codex authentication/discovery checks retain their separate five-second
96
+ bounds. This setting does not raise a CI job's overall timeout or change retry policy.
90
97
  Only explicit transient exit status 75 is retryable, at most twice; authentication, invalid
91
98
  output, cancellation and ambiguous failures are not retried. Ctrl-C cancels live CLI extraction.
92
99
  Indexing cancellation is checked between phases, not inside the indexer process.
@@ -1,15 +1,20 @@
1
1
  # Consumer hardening and the 1.0 release plan
2
2
 
3
- Status: maintainer-directed work; release checkpoint on 2026-10-26 after verified 0.3.0 publication.
4
- **New adoption blocker: T08, deterministic physical-file kind conflicts.** This takes release
5
- priority over the remaining planned increments; T04 was completed first as requested.
6
- The report concerned `@weftlet/toolkit@0.2.0`. **T01's upstream patch shipped in 0.2.1**;
7
- genuine consumer acceptance remains pending. T02 and T05's focused cold-validation optimization
8
- shipped in 0.3.0. T03 and T04 are implemented in development source after that release. Broader T05
9
- follow-ups and T06 and T07 remain open. These tasks improve setup, reuse, diagnostics and document coverage
10
- without expanding the consumer's migration. An official 1.0
11
- follows this work and genuine consumer acceptance, with its exact release scope reviewed when
12
- the evidence is available.
3
+ Status: maintainer-directed work; release checkpoint on 2026-10-26 after verified 0.4.0 publication.
4
+ **T08's upstream deterministic physical-file fix has shipped; the maintainer reports the consumer
5
+ updated and working on 2026-10-27. Detailed full hydration/repeat evidence remains pending.** T04 was completed before
6
+ the T08 fix as requested.
7
+
8
+ **Release priority T09:** 0.4.0 rejects the approved ten-minute extraction timeout. Support for
9
+ `semantic.timeoutMs: 600000` is implemented for the next release alongside ready T05a work;
10
+ the consumer's ten-minute retry has not run. This bounded blocker precedes T06/T07.
11
+
12
+ The original report concerned `@weftlet/toolkit@0.2.0`. T01's upstream document-identity patch
13
+ shipped in 0.2.1; T02 and T05's focused cold-validation optimization shipped in 0.3.0.
14
+ T03 operational cache reuse, T04 semantic failure diagnostics and T08's public core file factory
15
+ shipped in 0.4.0. Broader T05 follow-ups, T06 documentation consistency and T07 document coverage
16
+ remain open. Official 1.0 follows the agreed remaining scope and genuine consumer acceptance,
17
+ with its exact release scope reviewed when the evidence is available.
13
18
 
14
19
  This is the near-term release task list. The [Weftlet 2.0 product plan](WEFTLET-2.0-PLAN.md)
15
20
  remains a separate future direction for generation, approvals, a companion website and hosted
@@ -36,21 +41,23 @@ integration. Consumer acceptance is reported separately from upstream determinis
36
41
 
37
42
  | ID | Task | Priority/status | Dependencies and release boundary |
38
43
  | --- | --- | --- | --- |
39
- | **T08** | Canonical physical-file kinds and public adapter factory | **Merged; local and hosted Ubuntu/Windows checks passed; release pending** | Neutral contract consumers conflict with test Evidence; consumer framework migration remains separately required |
44
+ | **T09** | Accept the approved ten-minute extraction timeout | **Source fix implemented; release pending** | Raise only the config ceiling to 600000; preserve defaults/cache/retry behavior; consumer retry has not run |
45
+ | **T08** | Canonical physical-file kinds and public adapter factory | **Shipped in 0.4.0; consumer reported working; detailed acceptance pending** | Public core factory and neutral producers agree; record consumer commit, adapter tests and full hydration/repeat evidence |
40
46
  | **T01** | Coherent repository-document identity and kind | **Upstream patch shipped in 0.2.1; consumer acceptance pending** | SHACL and assertions preserved; genuine consumer re-run is still required |
41
47
  | **T02** | No-model hydration/setup preview | Shipped in 0.3.0 | Shared selection/cache inspection, human/JSON plans; extend with T07 traversal coverage |
42
- | **T03** | Artifact reuse across operational configuration changes | Merged; local and hosted Ubuntu/Windows checks passed; unreleased | Built-in Codex user artifacts share five operational changes; custom providers remain conservative; exact legacy recovery without model calls |
43
- | **T04** | Actionable, privacy-safe timeout diagnostics | Merged; local and hosted Ubuntu/Windows checks passed; unreleased | Safe source IDs, settled counts, failure classification and T02/T03 recovery; no extraction/cache identity change |
44
- | **T05** | Early identity checks and validation progress/profiling | **Cold-validation fix shipped in 0.3.0; consumer acceptance pending** | Full validation preserved; early checks, detailed progress and validation reuse remain open |
48
+ | **T03** | Artifact reuse across operational configuration changes | Shipped in 0.4.0 | Built-in Codex user artifacts share five operational changes; custom providers remain conservative; exact legacy recovery without model calls |
49
+ | **T04** | Actionable, privacy-safe timeout diagnostics | Shipped in 0.4.0 | Safe source IDs, settled counts, failure classification and T02/T03 recovery; no extraction/cache identity change |
50
+ | **T05** | Early identity checks and validation progress/profiling | **Cold fix shipped in 0.3.0; T05a merged with local/hosted checks passing, unreleased** | Full validation preserved; worker progress, reuse and broader profiling remain separate |
45
51
  | **T06** | Packaged release-documentation consistency | Open; README version pins removed in 0.2.1 | Automated archive/version consistency check remains to be implemented |
46
52
  | **T07** | Coverage-aware traversal from SOT/roadmap entry points | Planned bounded feature work | Use canonical identity from T01, preview from T02 and incremental reuse from T03; split selection/classification/extraction changes |
47
53
 
48
- T02 and the focused T05 fix passed local publication checks and hosted Ubuntu/Windows checks,
49
- then shipped in [0.3.0](https://github.com/jchewitt/weftlet/releases/tag/%40weftlet/toolkit%400.3.0).
50
- Registry archives match the independently reviewed export; source commit, provenance and release
51
- tags are recorded in [validation](VALIDATION.md). T03, T04, T06 and T07 remain independently
52
- useful increments, separate from the optional platform work. A genuine consumer hydration and
53
- repeat against the current release remain required; upstream fixtures do not establish that result.
54
+ T02 and the focused T05 fix shipped in 0.3.0; T03, T04 and T08 shipped in
55
+ [0.4.0](https://github.com/jchewitt/weftlet/releases/tag/%40weftlet/toolkit%400.4.0), following
56
+ local/hosted checks, independent archive review and fresh packed/public-registry installation.
57
+ Source, registry integrity, provenance and release tags are recorded in [validation](VALIDATION.md).
58
+ Broader T05, T06 and T07 remain bounded follow-ups.
59
+ The consumer must migrate its framework adapter to the public core factory, then complete full
60
+ hydration and repeat reuse; upstream fixtures do not establish that result.
54
61
 
55
62
  ## T08 — Resolve deterministic physical-file kind conflicts
56
63
 
@@ -64,12 +71,12 @@ routes physical-file producers through one policy, preserves strict SHACL/proven
64
71
  and distinguishes historical graph versions from current validation. Public tests include real
65
72
  SCIP and actual extractor composition, plus negative overlay validation without routing.
66
73
 
67
- Release requires local publication checks, hosted Ubuntu/Windows checks, reviewed archives and
68
- fresh installed-package verification. Consumer acceptance then requires the published packages
69
- plus its own framework adapter migration and composed Prisma/DI/decorator spec/test regressions,
70
- followed by full hydration and repeat reuse. Neither an upstream-only release nor a local-only
71
- adapter patch closes both ownership boundaries. Do not rewrite semantic caches or force model
72
- work to work around the proven deterministic defect.
74
+ The 0.4.0 release passed local publication checks, hosted Ubuntu/Windows checks, independent archive
75
+ review and fresh packed/public-registry installation. Consumer acceptance still requires the
76
+ published packages plus its own framework adapter migration and composed Prisma/DI/decorator
77
+ spec/test regressions, followed by full hydration and repeat reuse.
78
+ Neither an upstream-only release nor a local-only adapter patch closes both ownership boundaries.
79
+ Do not rewrite semantic caches or force model work to work around the proven deterministic defect.
73
80
 
74
81
  ## T01 — Resolve repository-document identity conflicts
75
82
 
@@ -110,7 +117,8 @@ Upstream completion evidence:
110
117
  [validation record](VALIDATION.md) for commits, checks and result boundaries.
111
118
 
112
119
  The private consumer has not yet supplied a successful full hydration/repeat with the identity
113
- patch. Use the current 0.3.0 release, which also includes the cold-validation improvement.
120
+ patch. Use both 0.4.0 packages and migrate the framework adapter to the public core factory;
121
+ this release retains the cold-validation improvement and adds the T08 deterministic producer fix.
114
122
  Upstream publication and regression success do not close that acceptance gate or diagnose the
115
123
  separate full-graph validation latency observation.
116
124
 
@@ -126,9 +134,9 @@ Missing or unsupported-only selectors and bounded agent omissions remain visible
126
134
  incomplete plans need review and exit 1. They do not introduce new hydration gates that would
127
135
  break deletion of the last document. Budget, duplicate-ID and corrupt/unavailable cache errors
128
136
  block planning checks without truncating selected sources. An explicit empty source list selects
129
- none. Requested refs now govern agent scope; corrected snapshots use graph-v6 while valid 0.2.1
130
- semantic artifacts remain reusable. T03's operational cache changes and T07's traversal/default
131
- validation-document separation remain separate work.
137
+ none. Requested refs govern agent scope. Release 0.3.0 introduced graph-v6; 0.4.0 advances assembly
138
+ to graph-v7 for T08 while compatible semantic artifacts remain reusable. T03 operational cache
139
+ reuse shipped in 0.4.0; T07 traversal/default validation-document separation remains open.
132
140
 
133
141
  Acceptance:
134
142
 
@@ -143,8 +151,8 @@ Acceptance:
143
151
 
144
152
  ## T03 — Reuse valid artifacts after operational changes
145
153
 
146
- Merged in [PR 22](https://github.com/jchewitt/weftlet/pull/22) after 0.3.0, with local publication
147
- and hosted Ubuntu/Windows checks passing. This source checkpoint does not claim npm publication.
154
+ Shipped in 0.4.0 after merging [PR 22](https://github.com/jchewitt/weftlet/pull/22) and passing
155
+ local publication and hosted Ubuntu/Windows checks; release evidence is in [validation](VALIDATION.md).
148
156
  [ADR 018](ADR-018-operational-semantic-cache.md) separates built-in Codex user artifacts from
149
157
  full snapshot profiles. Timeout, retry, concurrency and document/byte limits can change without
150
158
  hiding completed artifacts. Model/policy/authentication descriptors and unknown fields remain
@@ -179,8 +187,8 @@ Acceptance:
179
187
 
180
188
  ## T04 — Explain timeouts and recovery
181
189
 
182
- Merged in [PR 25](https://github.com/jchewitt/weftlet/pull/25) after 0.3.0, with local publication
183
- and hosted Ubuntu/Windows checks passing. This development checkpoint does not claim npm publication.
190
+ Shipped in 0.4.0 after merging [PR 25](https://github.com/jchewitt/weftlet/pull/25) and passing
191
+ local publication and hosted Ubuntu/Windows checks; release evidence is in [validation](VALIDATION.md).
184
192
  [ADR 019](ADR-019-semantic-failure-diagnostics.md) records opaque source IDs and explicit local
185
193
  preview mapping, final counts after active workers settle, safe typed errors and recovery.
186
194
  Concurrent sibling cancellation preserves the initiating failure. Completed writes stay counted
@@ -205,17 +213,26 @@ Acceptance:
205
213
 
206
214
  ## T05 — Detect inexpensive conflicts early and explain validation work
207
215
 
216
+ T05a implements [early identity attribution and phase timing](ADR-021-identity-preflight-and-validation-timing.md)
217
+ after 0.4.0, merged with local and hosted Ubuntu/Windows checks passing but not yet published.
218
+ Hydration and overlays reject all conflicting subject/object kinds before RDF construction;
219
+ opaque default reports have explicit local detail opt-in.
220
+ Completed semantic artifacts and prior snapshots remain intact. Valid preflight results still
221
+ require full SHACL. Timings report actual phase boundaries, not in-phase heartbeat or percentage.
222
+ This does not close the broader evaluation/reuse/backend items below or claim publication.
223
+
208
224
  The implementation uses JavaScript on Node:
209
225
  `rdf-validate-shacl` validates an in-memory N3 dataset. Hydration constructs and validates the
210
226
  entire assembled graph, including when semantic artifacts were reused. There is no persistent
211
227
  GraphDB backend or incremental validation. Querying a saved snapshot does not rerun SHACL.
212
228
 
213
- The maintainer reports that validation pushes the consumer's overall generation beyond its
229
+ The maintainer originally reported that validation pushed the consumer's overall generation beyond its
214
230
  30-minute timeout, preventing snapshot publication and making adoption unusable. That report made
215
231
  cold validation a release priority ahead of the remaining 1.0 work. Upstream has measured a specific
216
232
  named-graph lookup cost in public synthetic fixtures, but has not measured that consumer graph or
217
233
  diagnosed its complete timeout. The focused cold-validation fix shipped in 0.3.0, ahead of the
218
- remaining 1.0 tasks. Consumer acceptance remains pending; broader T05 items stay open.
234
+ remaining 1.0 tasks. The consumer is now reported working after 0.4.0; exact performance and
235
+ repeat-hydration acceptance evidence remains unrecorded. Broader T05 items stay open.
219
236
 
220
237
  [ADR 017](ADR-017-shacl-validation-union.md) records the implemented cold-validation optimization:
221
238
  build a temporary union of every SPO triple for the same validator/shapes, while keeping original
@@ -226,15 +243,15 @@ took 0.467 seconds. A 10,000-fact unique-node union case used about 1.3 GiB proc
226
243
  are synthetic phase measurements, not a private consumer reproduction or end-to-end guarantee.
227
244
 
228
245
  The focused change still validates the whole graph each time. It does not add Rust, GraphDB,
229
- incremental validation or a validation-result cache. Early checks and broader observability/reuse
230
- remain follow-ups rather than reasons to delay the cold-path fix. Native code or a database does
246
+ incremental validation or a validation-result cache. T05a now adds early checks and phase timing;
247
+ worker progress and broader observability/reuse remain follow-ups. Native code or a database does
231
248
  not by itself establish faster or correct incremental SHACL.
232
249
 
233
250
  Acceptance:
234
251
 
235
- - Early errors identify the conflicting identity/kinds and relevant evidence using the configured
236
- privacy policy. Preserve all underlying assertions for diagnosis; early checks are not a
237
- substitute for RDF/SHACL validation.
252
+ - Early errors identify the conflicting identity/kinds and relevant evidence through opaque
253
+ defaults and explicit local detail opt-in. Preserve all underlying assertions for diagnosis;
254
+ early checks are not a substitute for RDF/SHACL validation.
238
255
  - Report elapsed time and honest progress for long validation. Current phase boundaries remain
239
256
  the supported progress signal: the synchronous validator blocks same-thread timers. Evaluate
240
257
  bounded worker execution before promising an in-phase heartbeat or cancellation; never display
package/docs/ROADMAP.md CHANGED
@@ -1,21 +1,25 @@
1
1
  # Delivery roadmap
2
2
 
3
- Release checkpoint: 2026-10-26, after verified 0.3.0 publication. Evidence is recorded in
3
+ Release checkpoint: 2026-10-26, after verified 0.4.0 publication. Evidence is recorded in
4
4
  [validation](VALIDATION.md); this roadmap is not a live registry status.
5
5
 
6
6
  Project: `jchewitt/weftlet`. Extraction provenance is recorded in the
7
7
  [source inventory](SOURCE-INVENTORY.md).
8
8
 
9
+ Current release priority: the consumer's approved ten-minute retry is blocked by 0.4.0's
10
+ five-minute configuration ceiling. T09 raises the accepted timeout to 600000 ms and will ship
11
+ with ready T05a work. The actual consumer retry has not run; this does not change default limits.
12
+
9
13
  Forward direction is captured in the [Weftlet 2.0 product plan](WEFTLET-2.0-PLAN.md):
10
14
  consumer hardening, cited code-derived drafts, scoped approvals and reconciliation, an optional
11
15
  review website, source publication, managed AI and guided setup. “2.0” is a planning label;
12
- the verified release at this checkpoint is 0.3.0. The received consumer findings are tracked in the
16
+ the verified release at this checkpoint is 0.4.0. The received consumer findings are tracked in the
13
17
  [consumer hardening and 1.0 task list](RELEASE-1.0-PLAN.md): the document-identity patch is
14
18
  published and passes upstream checks; genuine consumer acceptance remains pending. T02's
15
- no-model preview and T05's cold-validation improvement shipped in 0.3.0. Operational cache reuse
16
- and timeout diagnostics are development increments; document coverage and other acceptance work
17
- remain open before official 1.0.
18
- The 2.0 plan distinguishes proposed work from delivered capability.
19
+ no-model preview and T05's cold-validation improvement shipped in 0.3.0. T03 operational cache
20
+ reuse, T04 timeout diagnostics and T08 deterministic physical-file consistency shipped in 0.4.0.
21
+ Document coverage, broader validation follow-ups and genuine consumer acceptance remain open
22
+ before official 1.0. The 2.0 plan distinguishes proposed work from delivered capability.
19
23
 
20
24
  The maintainer reported SHACL pushing generation past a 30-minute timeout before graph
21
25
  publication. T02 and the focused T05 optimization shipped together in 0.3.0 through
@@ -32,25 +36,27 @@ in one temporary validation graph, preserving the same shapes and canonical name
32
36
  Bounded public experiments measured substantial cold-path improvement, alongside about 1.3 GiB
33
37
  RSS in the prototype at 10,000 unique-node facts; the production harness including serialization
34
38
  peaked near 1.6 GiB. They do not reproduce the private consumer's overall timeout.
35
- Early checks, in-phase progress, result reuse and incremental validation remain open; no Rust
36
- engine, graph database or validation-result cache is introduced by this focused release.
37
-
38
- [T03 operational cache reuse](ADR-018-operational-semantic-cache.md) is merged with local and
39
- hosted checks passing and is not part of published 0.3.0. Built-in Codex user
40
- artifacts can survive changes to timeout/retry/concurrency/document/byte limits while snapshots
41
- retain their full configuration identity. Exact legacy reads and explicit no-model adoption
42
- preserve prior artifacts; custom providers remain conservative.
43
- [T04 diagnostics](ADR-019-semantic-failure-diagnostics.md) add safe failure reports, opaque source
44
- mapping and accurate settled progress without changing extraction/cache identity. T04 is merged
45
- with local and hosted Ubuntu/Windows checks passing; release remains pending. Broader T05 and
46
- T06/T07 work remain open.
47
-
48
- A subsequent 0.3.0 consumer report makes [T08 physical-file kind consistency](ADR-020-canonical-physical-file-producers.md)
49
- the next release priority. Its neutral contract consumer fix and public core factory are merged
50
- with deterministic producer adoption, version guards and passing local/hosted Ubuntu/Windows
51
- checks. Publication is pending; the consumer's framework adapter migration and full acceptance
52
- remain consumer-owned.
53
- This fix preserves semantic artifacts and does not reinterpret model assertions to hide conflicts.
39
+ T05a adds [early identity checks and phase timing](ADR-021-identity-preflight-and-validation-timing.md)
40
+ after 0.4.0, merged with local/hosted checks passing and publication pending. Full validation
41
+ remains mandatory. In-phase worker progress, result reuse and incremental validation remain
42
+ open; no Rust engine, graph database or
43
+ validation-result cache is introduced by these increments.
44
+
45
+ [T03 operational cache reuse](ADR-018-operational-semantic-cache.md) shipped in 0.4.0. Built-in
46
+ Codex user artifacts can survive changes to timeout/retry/concurrency/document/byte limits while
47
+ snapshots retain their full configuration identity. Exact legacy reads and explicit no-model
48
+ adoption preserve prior artifacts; custom providers remain conservative.
49
+ [T04 diagnostics](ADR-019-semantic-failure-diagnostics.md) shipped in the same release, adding
50
+ safe failure reports, opaque source mapping and settled progress without changing extraction/cache
51
+ identity. Broader T05 and T06/T07 work remain open.
52
+
53
+ [T08 physical-file kind consistency](ADR-020-canonical-physical-file-producers.md) also shipped in
54
+ 0.4.0 after local/hosted Ubuntu/Windows checks, independent archive review and fresh packed and
55
+ public-registry installation. The public core factory and deterministic producers share one policy
56
+ under strict SHACL. Historical snapshots remain queryable, with version guards for current validation.
57
+ On 2026-10-27 the maintainer reported the consumer updated and working; exact adapter and full
58
+ hydration/repeat evidence remain unrecorded. This fix preserves semantic artifacts and
59
+ does not reinterpret model assertions to hide conflicts.
54
60
 
55
61
  | Milestone | Delivered and checked | Remaining limits |
56
62
  | --- | --- | --- |
@@ -8,6 +8,145 @@ The milestone entries below record the original cloud checks. Subsequent
8
8
  establishes live Codex success on Windows and the full deterministic checks on WSL,
9
9
  while identifying remaining native Windows issues.
10
10
 
11
+ ## Ten-minute timeout blocker, 2026-10-27
12
+
13
+ The maintainer reports that published 0.4.0 rejects the approved `semantic.timeoutMs: 600000`.
14
+ The consumer's ten-minute retry has **not run**. This is a configuration ceiling defect, separate
15
+ from the corrected physical-file kinds and earlier positive consumer update below.
16
+
17
+ The source patch raises only the accepted maximum from 300000 to 600000 ms. Omitted timeout
18
+ still defaults to 120000; finite positive integer validation, retries, cancellation and the
19
+ separate authentication/discovery limits are unchanged. No provider/prompt/artifact identity
20
+ changes or forced model re-extraction are introduced.
21
+
22
+ Focused checks pass: config acceptance/boundary rejection, Codex propagation across retries,
23
+ per-call override/cancellation, a cancellable module deadline, and real artifact reuse/preview
24
+ after an interrupted run switches to 600000. The provider tests use an injected runner/local
25
+ module and finish immediately; they are not a live ten-minute extraction. Independent review
26
+ found no blocker. Local `pnpm context-graph:publication-check` passed: 408 deterministic tests
27
+ (17 core, 391 toolkit), one optional OML skip, 13 unchanged advisory architecture findings,
28
+ inventory, licenses and fresh packed-consumer checks. The installed CLI accepts 600000 in
29
+ no-model preview and reports the same limit on an immediate missing-provider failure.
30
+ All 79 original source path/hash pairs remain intact. Hosted checks and publication are recorded
31
+ after completion; the consumer's live ten-minute retry remains unrun.
32
+
33
+ ## Consumer update after 0.4.0, 2026-10-27
34
+
35
+ The maintainer reports that the consumer updated and appears to be working. This is positive
36
+ consumer feedback after the T08 release. No exact consumer commit, graph scope, adapter test
37
+ report, full-run timing or repeated-hydration report was supplied with that update, so those
38
+ detailed acceptance results remain unrecorded. No private consumer files were inspected or changed.
39
+
40
+ ## T05a identity preflight and validation phase timing, 2026-10-27
41
+
42
+ Implemented in development source after 0.4.0; no new publication is claimed.
43
+ [ADR 021](ADR-021-identity-preflight-and-validation-timing.md) records the bounded scope:
44
+ complete identity/kind attribution before compilation/RDF, explicit local diagnostic detail,
45
+ and elapsed phase boundaries. Full SHACL shapes, accepted facts and cache identities are unchanged.
46
+
47
+ - Twelve pure preflight cases pass: both endpoints, cross-source kinds, conceptual IDs,
48
+ duplicates/self-references, all late conflicts, exact copied provenance/authority, absent
49
+ authority preservation and opaque defaults including unknown kinds. A pass explicitly says
50
+ `shaclValidated: false`; it does not infer canonical classification or approved intent.
51
+ - Two hydration composition cases pass with actual committed file/contract/document producers
52
+ and a deterministic semantic provider. A kind conflict skips compilation, invariants and RDF;
53
+ previous head/snapshot and completed artifact bytes remain intact. Correcting the fixture
54
+ reuses the artifact and runs full SHACL. Invalid confidence with consistent kinds still fails
55
+ real SHACL. Indexing is stubbed in these scheduling cases; real SCIP is covered separately.
56
+ - Four CLI subprocess cases pass with real SCIP and public adapters: default human/JSON privacy,
57
+ explicit exact attribution, empty failure stdout, preserved artifacts/snapshots, overlay detail
58
+ propagation and valid full-validation timing. The existing four semantic-failure CLI cases pass.
59
+ - All 26 full SHACL parity/timing cases pass, including original named-dataset positive/negative
60
+ equivalence and the 2,200-fact late failure. Phase events do not change verdicts or serialization;
61
+ completed means the operation returned, not that its graph conformed.
62
+ - Local `pnpm context-graph:publication-check` passed: 403 deterministic tests (17 core,
63
+ 386 toolkit), one optional OML skip, 13 unchanged advisory architecture findings, inventory,
64
+ licenses and fresh packed-consumer checks. The installed public API detects kind conflicts,
65
+ preserves exact opt-in citations, reports phase timing and still rejects the same pair under
66
+ full SHACL. All 79 original extraction source path/hash pairs remain intact.
67
+ - Independent runtime/test review found no blocker. No live model or private consumer
68
+ performance result is implied.
69
+
70
+ [PR 30](https://github.com/jchewitt/weftlet/pull/30) merged at
71
+ `c8db1f0b871f5e6f3d1d2e9eda1b045aa45469df`. Exact feature head
72
+ `dc01421aa3953963e411430266b9035f2852cfd8` passed hosted Ubuntu and native Windows checks
73
+ in [push run 40451305862](https://github.com/jchewitt/weftlet/actions/runs/40451305862) and
74
+ [PR run 40451332221](https://github.com/jchewitt/weftlet/actions/runs/40451332221).
75
+ T05a is merged but unpublished; npm 0.4.0 remains the verified public release.
76
+
77
+ A bounded public profile ran the unique-node fixture in three fresh processes: 500 facts,
78
+ the same 500 facts again, then 501 facts. Command: `node scripts/benchmark-shacl.mjs --counts 500
79
+ --topologies unique --modes optimized --deadline-ms 15000` (use 501 for the final case), after
80
+ `pnpm build`. Linux x64, Node 24.19.0, N3 2.7.2 and rdf-validate-shacl 0.6.5; built RDF module
81
+ SHA-256 `8a66e0266d812b742103d42de3572faf4ab9873d0f37424b563962ea7473fae1`.
82
+
83
+ | Facts / nodes | Preflight ms | RDF construction ms | Union ms | SHACL ms | Process peak RSS KiB |
84
+ | --- | ---: | ---: | ---: | ---: | ---: |
85
+ | 500 / 1,000 | 0.84 | 67.90 | 32 | 186 | 330,496 |
86
+ | 500 / 1,000 repeat | 0.74 | 57.15 | 32 | 174 | 334,356 |
87
+ | 501 / 1,002 | 0.74 | 59.88 | 54 | 185 | 333,584 |
88
+
89
+ All three ran full validation and preserved serialization; the repeated input's serialization
90
+ digest matched, and the added-fact digest differed. These single-run smoke measurements establish
91
+ phase visibility, not a speedup or production capacity. RSS includes imports, fixture and
92
+ serialization; no successful-result reuse or dependency-aware incremental validation was used.
93
+
94
+ ## 0.4.0 publication and installed-package checks, 2026-10-26
95
+
96
+ `@weftlet/core@0.4.0` and `@weftlet/toolkit@0.4.0` ship T03 operational cache reuse,
97
+ T04 semantic failure diagnostics and T08 canonical physical-file kinds. This is an upstream
98
+ release; private consumer adapter migration and full hydration acceptance remain pending.
99
+
100
+ [Release PR 23](https://github.com/jchewitt/weftlet/pull/23) merged at
101
+ `9c6c2625ce2f5d3a28d2be40610130c745b416d4`. Trusted publishing
102
+ [run 40421791942](https://github.com/jchewitt/weftlet/actions/runs/40421791942)
103
+ completed preparation, publication and release records on attempt 1. Both versions are public
104
+ and tagged `latest`; downloaded registry archives are byte-identical to the independently
105
+ reviewed archives. npm provenance identifies that merge commit and workflow attempt. The
106
+ [core](https://github.com/jchewitt/weftlet/releases/tag/%40weftlet/core%400.4.0) and
107
+ [toolkit](https://github.com/jchewitt/weftlet/releases/tag/%40weftlet/toolkit%400.4.0)
108
+ package tags and GitHub Releases resolve to the same commit.
109
+
110
+ - Exact reviewed version head `8ea26c7f538202b4acb67ceeda6adbf220a85e93` passed
111
+ `pnpm release:prepare`: 384 deterministic tests (17 core, 367 toolkit), one optional OML skip,
112
+ 13 advisory architecture findings, inventory, licenses and fresh packed-consumer checks.
113
+ Hosted Ubuntu and native Windows checks passed in
114
+ [run 40421253221](https://github.com/jchewitt/weftlet/actions/runs/40421253221).
115
+ - Independent source/archive review found no release blocker. Core contains 13 files/8,212 bytes;
116
+ toolkit contains 213 files/244,424 bytes. Archive digests match the reviewed manifest; all
117
+ non-manifest files match the reviewed checkout. Public exports, CLI/runtime assets, Apache-2.0
118
+ licenses and attribution are present. Core has no runtime dependencies; toolkit requires
119
+ core `^0.4.0`. No forbidden local-state entries or credential-signature matches were found.
120
+ All 79 original extraction source path/hash pairs are unchanged.
121
+ - A separate offline rehearsal installed those exact archives with lifecycle scripts disabled.
122
+ Its public fixture produced 54 facts, including four contract consumers, 24 SCIP facts and two
123
+ public adapter facts. Strict SHACL, immutable repeat reuse and provider-unavailable saved reads
124
+ passed. This rehearsal is distinct from public-registry acceptance.
125
+ - Fresh public-registry installation passed on Linux/Node 24.19.0 with lifecycle scripts disabled.
126
+ Its lockfile registry URLs and SHA-512 values match the reviewed archives. The committed public
127
+ fixture produced 54 total facts, including two semantic facts, four contract consumers, 24 real SCIP facts,
128
+ two public adapter facts and nine document facts; the impact query returned 53 facts.
129
+ Cold hydration extracted two artifacts; repeat hydration extracted zero and reused both with
130
+ identical snapshot identity, content digest and stored bytes. Removing the provider module
131
+ preserved no-model preview and saved queries, with no additional provider invocations.
132
+ Fixture commit: `41d0c4fa68f7a358d52471dbbd2a6186adb22fa5`; content digest:
133
+ `f5a8fbde346d070074164edf970bfd98246c4e34718b43f5850757501daf50ca`.
134
+
135
+ The installed-package fixture uses a deterministic public provider, actual contract/document
136
+ extractors, real TypeScript SCIP and a public adapter that imports only the core file factory.
137
+ It checks retained citations, digests and authority, strict RDF/SHACL, projection/query results,
138
+ repeat artifact reuse and unchanged snapshot bytes. It makes no live model calls and does not
139
+ establish private adapter correctness, semantic quality or the consumer's full-graph performance.
140
+ The T03/T04 test checkpoints below remain the evidence for operational Codex cache partitioning
141
+ and structured failure handling; ordinary fixture reuse is not a substitute for those tests.
142
+
143
+ Reviewed and public archive integrity:
144
+
145
+ | Package | SHA-512 integrity |
146
+ | --- | --- |
147
+ | `@weftlet/core@0.4.0` | `sha512-hNiLpfFaL/o+uQJlRdW+jN/cdMIY8QxTAgwTA7F1kN8f1KhHWH8qsxc4RgC8mP+4huLsWLk8m0v14xrq5prMdA==` |
148
+ | `@weftlet/toolkit@0.4.0` | `sha512-UrHRBuz3v7Olfqk0iaSyvZ1+9xnCHMAjh0ZGj+HWde4zAR0M2zEHjeOxkyC2B2d63gPAqttlQ5kzpauRdfd0Jg==` |
149
+
11
150
  ## T08 deterministic physical-file kinds, 2026-10-26
12
151
 
13
152
  Implemented after 0.3.0; this checkpoint does not claim npm publication or private consumer
@@ -108,7 +108,7 @@
108
108
  "destinationPath": "package.json",
109
109
  "sourceSha256": "a575dbb2fed8c554b95e8e9b3e03a0c21cab1be7249860bbebc18e046b2ff78d",
110
110
  "modified": true,
111
- "destinationSha256": "1e5ae982ffbb2cb02071bbf6c4f8040836dcc451c5e478f10b07cc5646f0e1eb"
111
+ "destinationSha256": "3e56a3b6a6200e15f684bb490360f2aec0d305dc6c475a176971b188ac5b725d"
112
112
  },
113
113
  {
114
114
  "sourcePath": "tools/context-graph/packages/core/LICENSE",
@@ -143,7 +143,7 @@
143
143
  "destinationPath": "packages/core/package.json",
144
144
  "sourceSha256": "2a29066eb8452f22fafcb06bb035a84dda93c5705dba32aba600a1b7e5aaf19c",
145
145
  "modified": true,
146
- "destinationSha256": "090d8d90cbf775e6edf1656215d75200f9961009ef75f2ab4de55fe5603814ea"
146
+ "destinationSha256": "cde075a193be99f3d50895d9f764e8fd5848f54a2e5acb0155ce69f454bf8623"
147
147
  },
148
148
  {
149
149
  "sourcePath": "tools/context-graph/packages/core/src/core.ts",
@@ -192,7 +192,7 @@
192
192
  "destinationPath": "scripts/check-publication.mjs",
193
193
  "sourceSha256": "88692c21d34cef2d2e5b20c92ab3ec26cbe6336889dbb7b534c681ded7f466b2",
194
194
  "modified": true,
195
- "destinationSha256": "2b92ad80a6a193b4628d4caec2bd29b6fbf3c6c97066bda2fe91ceb173d06158"
195
+ "destinationSha256": "6cc62cdbd4bed65d8eff4749fba7003b3fa59c2e5ddcf8e333950468c40986bf"
196
196
  },
197
197
  {
198
198
  "sourcePath": "tools/context-graph/scripts/generate-third-party-notices.mjs",
@@ -241,21 +241,21 @@
241
241
  "destinationPath": "src/interfaces/cli.ts",
242
242
  "sourceSha256": "c68f5f35a5325cc03811b0d4ffb6d58c31a9b4e6115fcb2c5e4fda9560a34714",
243
243
  "modified": true,
244
- "destinationSha256": "c333051df80a274410351b0ba1eef1a1e004f790fa457fd3ebb7909197c4ca29"
244
+ "destinationSha256": "21cdbc817983e788a5aac48ea8b32c55a7dda98868eb48b5df470c8d99eea44a"
245
245
  },
246
246
  {
247
247
  "sourcePath": "tools/context-graph/src/config.test.ts",
248
248
  "destinationPath": "src/configuration/config.test.ts",
249
249
  "sourceSha256": "70bcda6d6b48ff6fa03223c9420fe3e0e3e32c688e0a14f11034515e0707dee4",
250
250
  "modified": true,
251
- "destinationSha256": "ff4d15018ec35d21a95c589cf2c74bce2e340f9042b2d3ecaabca5889609e3aa"
251
+ "destinationSha256": "f9bedfd754d937023f7d06ff9a0fb8e9e4c9d122178446d2e70ac6914e184156"
252
252
  },
253
253
  {
254
254
  "sourcePath": "tools/context-graph/src/config.ts",
255
255
  "destinationPath": "src/configuration/config.ts",
256
256
  "sourceSha256": "e9ee8cf2134d274aa6f6a21545959fbec97e958181d9032c073293f28e04d6ca",
257
257
  "modified": true,
258
- "destinationSha256": "5e34e4dfa38219570bd6f13239609b432830e76162f44a768a929895f66dc02a"
258
+ "destinationSha256": "7c79bcd696102f89d3dcadaf01ab2311f68b37172b54b21a667de7f15bdec69a"
259
259
  },
260
260
  {
261
261
  "sourcePath": "tools/context-graph/src/core.ts",
@@ -318,14 +318,14 @@
318
318
  "destinationPath": "src/application/hydrator.ts",
319
319
  "sourceSha256": "bb41c5b53b26da10274d8b967b99c78ff12b485df16bfc66445252e35c94fb9d",
320
320
  "modified": true,
321
- "destinationSha256": "1833e788ca0c162947c626ff611f724d53f349b8d1dc019f204bd433726f9be9"
321
+ "destinationSha256": "ef6e21f322915b3bf25589d748f379becea5a0ef188bf875caaca10cc479cd2c"
322
322
  },
323
323
  {
324
324
  "sourcePath": "tools/context-graph/src/index.ts",
325
325
  "destinationPath": "src/index.ts",
326
326
  "sourceSha256": "a3545649f67fc0bf0496298e3f1dca1e91aa7cb68ec112c34b99a5785fa83f3c",
327
327
  "modified": true,
328
- "destinationSha256": "2dff4c9bca049dc1607cce7cf709494aae24a7f27b05fcb9353dd19de4546fac"
328
+ "destinationSha256": "b185467e660715806fc914bef5db068e90199ee32b0226452d4adb4c09991d8b"
329
329
  },
330
330
  {
331
331
  "sourcePath": "tools/context-graph/src/mcp-facade.ts",
@@ -613,6 +613,7 @@
613
613
  "docs/ADR-018-operational-semantic-cache.md",
614
614
  "docs/ADR-019-semantic-failure-diagnostics.md",
615
615
  "docs/ADR-020-canonical-physical-file-producers.md",
616
+ "docs/ADR-021-identity-preflight-and-validation-timing.md",
616
617
  "docs/CLOUD-ENVIRONMENT.md",
617
618
  "docs/CONSUMER-TRIAL.md",
618
619
  "docs/ENVIRONMENT-VALIDATION.md",
@@ -778,15 +779,19 @@
778
779
  "src/governance/governance.ts",
779
780
  "src/governance/physical-file-kinds.test.ts",
780
781
  "src/graph/authority.ts",
782
+ "src/graph/identity-preflight.test.ts",
783
+ "src/graph/identity-preflight.ts",
781
784
  "src/graph/ranking.test.ts",
782
785
  "src/graph/ranking.ts",
783
786
  "src/graph/rdf.ts",
784
787
  "src/graph/shacl-shapes.ts",
788
+ "src/graph/validation-progress.ts",
785
789
  "src/infrastructure/module-resolution.ts",
786
790
  "src/interfaces/cache-adoption.test.ts",
787
791
  "src/interfaces/doctor.ts",
788
792
  "src/interfaces/hydration-failure.test.ts",
789
793
  "src/interfaces/hydration-plan.test.ts",
794
+ "src/interfaces/identity-preflight.test.ts",
790
795
  "src/interfaces/init.test.ts",
791
796
  "src/interfaces/init.ts",
792
797
  "src/mcp.ts",
@@ -802,6 +807,7 @@
802
807
  "tests/extractor-compatibility.test.ts",
803
808
  "tests/hydration-failure.test.ts",
804
809
  "tests/hydration-plan.test.ts",
810
+ "tests/identity-preflight.test.ts",
805
811
  "tests/module-boundaries.test.ts",
806
812
  "tests/physical-file-kinds.test.ts",
807
813
  "tests/rdf-ontology.test.ts",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weftlet/toolkit",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
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",
@@ -63,7 +63,7 @@
63
63
  "n3": "2.7.2",
64
64
  "rdf-validate-shacl": "0.6.5",
65
65
  "sparqljs": "3.7.4",
66
- "@weftlet/core": "^0.4.0"
66
+ "@weftlet/core": "^0.5.0"
67
67
  },
68
68
  "devDependencies": {
69
69
  "@changesets/cli": "3.0.3",