archgraph-argo 0.10.43 → 0.10.44

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.
Files changed (35) hide show
  1. package/LICENSE +201 -201
  2. package/argo/package.json +8 -8
  3. package/argo/schema/ImplementationToCodingHandoff.schema.json +251 -251
  4. package/argo/schema/ImplementationToIntentTraceProposal.schema.json +180 -180
  5. package/argo/schema/IntentToImplementationHandoff.schema.json +74 -74
  6. package/argo/schema/SystemArchitecture.schema.json +378 -378
  7. package/argo/schema/archimate3.2.md +7153 -7153
  8. package/argo/scripts/archimate32-rules.js +12301 -12301
  9. package/argo/scripts/generateArchitectureDiffPlantuml.js +466 -466
  10. package/argo/scripts/graph-rag/ARCHITECTURE.md +192 -192
  11. package/argo/scripts/graph-rag/canonicalProjectionAuthority.js +45 -45
  12. package/argo/scripts/graph-rag/embeddingQualificationGate.js +59 -59
  13. package/argo/scripts/graph-rag/externalProductionConfig.js +74 -74
  14. package/argo/scripts/graph-rag/liveEmbeddingProviderClient.js +49 -49
  15. package/argo/scripts/graph-rag/neo4jNativeRetrieval.js +37 -37
  16. package/argo/scripts/graph-rag/semantic-persistence/ARCHITECTURE.md +51 -51
  17. package/argo/scripts/graph-rag/semantic-persistence/productionSemanticCheckpointStore.js +99 -99
  18. package/argo/scripts/graph-rag/semantic-persistence/productionSemanticProjectionStore.js +171 -171
  19. package/argo/scripts/graph-rag/semanticOperatorError.js +38 -38
  20. package/argo/scripts/graph-rag/semanticOperatorJourney.js +459 -459
  21. package/argo/scripts/graph-rag/semanticReadinessAttestationStore.js +398 -398
  22. package/argo/scripts/graph-rag/systemMetadataCommandAdapter.js +269 -269
  23. package/argo/scripts/graph-semantics.js +220 -220
  24. package/argo/scripts/repositoryArgoEnvironment.js +101 -101
  25. package/argo/scripts/runArchitectureTests.js +583 -583
  26. package/argo/scripts/semanticOperatorJourneyCli.js +91 -91
  27. package/argo/scripts/syncSystemArchitectureToNeo4j.js +66 -66
  28. package/argo/scripts/test-executors/_template.js +58 -58
  29. package/argo/scripts/test-executors/default.js +199 -199
  30. package/argo/scripts/validateStageHandoff.js +458 -458
  31. package/argo/scripts/validateSystemArchitecture.js +253 -253
  32. package/argo/scripts/validateTraceProposal.js +181 -181
  33. package/bin/argo-deploy.js +12 -12
  34. package/install-argo.ps1 +27 -8
  35. package/package.json +1 -1
@@ -1,45 +1,45 @@
1
- function enforceCanonicalProjectionAuthority(input) {
2
- const canonicalGraph = input && input.canonicalGraph;
3
- const projection = input && input.projection;
4
- if (!canonicalGraph || !projection) {
5
- throw projectionConflict('Canonical graph and projection evidence are required');
6
- }
7
-
8
- const canonicalIds = collectCanonicalIds(canonicalGraph);
9
- const projectionIds = new Set(
10
- Array.isArray(projection.seeds)
11
- ? projection.seeds.map(seed => seed && seed.id).filter(Boolean)
12
- : [],
13
- );
14
- const versionAligned = projection.canonicalVersion === canonicalGraph.version;
15
- const identitiesAligned = [...projectionIds].every(id => canonicalIds.has(id));
16
-
17
- if (!versionAligned || !identitiesAligned) {
18
- throw projectionConflict('Neo4j projection conflicts with canonical intent');
19
- }
20
-
21
- return {
22
- status: 'passed',
23
- canonicalAuthority: 'canonical',
24
- document: canonicalGraph,
25
- projection,
26
- };
27
- }
28
-
29
- function collectCanonicalIds(graph) {
30
- return new Set([
31
- ...(graph.elements || []).map(entry => entry.id),
32
- ...(graph.relationships || []).map(entry => entry.id),
33
- ...(graph.views || []).map(entry => entry.view_id),
34
- ].filter(Boolean));
35
- }
36
-
37
- function projectionConflict(message) {
38
- const error = new Error(message);
39
- error.category = 'CANONICAL_PROJECTION_CONFLICT';
40
- return error;
41
- }
42
-
43
- module.exports = {
44
- enforceCanonicalProjectionAuthority,
45
- };
1
+ function enforceCanonicalProjectionAuthority(input) {
2
+ const canonicalGraph = input && input.canonicalGraph;
3
+ const projection = input && input.projection;
4
+ if (!canonicalGraph || !projection) {
5
+ throw projectionConflict('Canonical graph and projection evidence are required');
6
+ }
7
+
8
+ const canonicalIds = collectCanonicalIds(canonicalGraph);
9
+ const projectionIds = new Set(
10
+ Array.isArray(projection.seeds)
11
+ ? projection.seeds.map(seed => seed && seed.id).filter(Boolean)
12
+ : [],
13
+ );
14
+ const versionAligned = projection.canonicalVersion === canonicalGraph.version;
15
+ const identitiesAligned = [...projectionIds].every(id => canonicalIds.has(id));
16
+
17
+ if (!versionAligned || !identitiesAligned) {
18
+ throw projectionConflict('Neo4j projection conflicts with canonical intent');
19
+ }
20
+
21
+ return {
22
+ status: 'passed',
23
+ canonicalAuthority: 'canonical',
24
+ document: canonicalGraph,
25
+ projection,
26
+ };
27
+ }
28
+
29
+ function collectCanonicalIds(graph) {
30
+ return new Set([
31
+ ...(graph.elements || []).map(entry => entry.id),
32
+ ...(graph.relationships || []).map(entry => entry.id),
33
+ ...(graph.views || []).map(entry => entry.view_id),
34
+ ].filter(Boolean));
35
+ }
36
+
37
+ function projectionConflict(message) {
38
+ const error = new Error(message);
39
+ error.category = 'CANONICAL_PROJECTION_CONFLICT';
40
+ return error;
41
+ }
42
+
43
+ module.exports = {
44
+ enforceCanonicalProjectionAuthority,
45
+ };
@@ -1,59 +1,59 @@
1
- function evaluateEmbeddingQualification(qualification) {
2
- const supplied = qualification && typeof qualification === 'object'
3
- ? qualification
4
- : {};
5
-
6
- if (supplied.approvedByHuman !== true) {
7
- throw blockingError(
8
- 'EMBEDDING_QUALIFICATION_REQUIRED',
9
- 'Embedding configuration requires explicit human approval',
10
- 'approvedByHuman',
11
- );
12
- }
13
-
14
- if (supplied.source === 'implicit-default') {
15
- throw blockingError(
16
- 'IMPLICIT_EMBEDDING_DEFAULT_PROHIBITED',
17
- 'Implicit embedding defaults cannot qualify index delivery',
18
- 'source',
19
- );
20
- }
21
-
22
- for (const field of ['provider', 'model', 'version']) {
23
- if (typeof supplied[field] !== 'string' || supplied[field].trim().length === 0) {
24
- throw blockingError(
25
- 'EMBEDDING_CONFIGURATION_REQUIRED',
26
- `${field} must be explicitly supplied`,
27
- field,
28
- );
29
- }
30
- }
31
-
32
- if (!Number.isInteger(supplied.dimensions) || supplied.dimensions <= 0) {
33
- throw blockingError(
34
- 'EMBEDDING_CONFIGURATION_REQUIRED',
35
- 'dimensions must be an explicitly supplied positive integer',
36
- 'dimensions',
37
- );
38
- }
39
-
40
- return {
41
- status: 'approved',
42
- approvedByHuman: true,
43
- provider: supplied.provider.trim(),
44
- model: supplied.model.trim(),
45
- version: supplied.version.trim(),
46
- dimensions: supplied.dimensions,
47
- };
48
- }
49
-
50
- function blockingError(category, message, field) {
51
- const error = new Error(message);
52
- error.category = category;
53
- error.field = field;
54
- return error;
55
- }
56
-
57
- module.exports = {
58
- evaluateEmbeddingQualification,
59
- };
1
+ function evaluateEmbeddingQualification(qualification) {
2
+ const supplied = qualification && typeof qualification === 'object'
3
+ ? qualification
4
+ : {};
5
+
6
+ if (supplied.approvedByHuman !== true) {
7
+ throw blockingError(
8
+ 'EMBEDDING_QUALIFICATION_REQUIRED',
9
+ 'Embedding configuration requires explicit human approval',
10
+ 'approvedByHuman',
11
+ );
12
+ }
13
+
14
+ if (supplied.source === 'implicit-default') {
15
+ throw blockingError(
16
+ 'IMPLICIT_EMBEDDING_DEFAULT_PROHIBITED',
17
+ 'Implicit embedding defaults cannot qualify index delivery',
18
+ 'source',
19
+ );
20
+ }
21
+
22
+ for (const field of ['provider', 'model', 'version']) {
23
+ if (typeof supplied[field] !== 'string' || supplied[field].trim().length === 0) {
24
+ throw blockingError(
25
+ 'EMBEDDING_CONFIGURATION_REQUIRED',
26
+ `${field} must be explicitly supplied`,
27
+ field,
28
+ );
29
+ }
30
+ }
31
+
32
+ if (!Number.isInteger(supplied.dimensions) || supplied.dimensions <= 0) {
33
+ throw blockingError(
34
+ 'EMBEDDING_CONFIGURATION_REQUIRED',
35
+ 'dimensions must be an explicitly supplied positive integer',
36
+ 'dimensions',
37
+ );
38
+ }
39
+
40
+ return {
41
+ status: 'approved',
42
+ approvedByHuman: true,
43
+ provider: supplied.provider.trim(),
44
+ model: supplied.model.trim(),
45
+ version: supplied.version.trim(),
46
+ dimensions: supplied.dimensions,
47
+ };
48
+ }
49
+
50
+ function blockingError(category, message, field) {
51
+ const error = new Error(message);
52
+ error.category = category;
53
+ error.field = field;
54
+ return error;
55
+ }
56
+
57
+ module.exports = {
58
+ evaluateEmbeddingQualification,
59
+ };
@@ -1,74 +1,74 @@
1
- const REQUIRED_FIELDS = [
2
- 'neo4jUri',
3
- 'neo4jUsername',
4
- 'neo4jPassword',
5
- 'embeddingCredential',
6
- ];
7
- const APPROVED_SOURCE_KEYS = new Map([
8
- ['neo4jUri', 'ARGO_NEO4J_DATABASE_URL'],
9
- ['neo4jUsername', 'ARGO_NEO4J_DATABASE_USERNAME'],
10
- ['neo4jPassword', 'ARGO_NEO4J_DATABASE_PASSWORD'],
11
- ['embeddingCredential', 'QWEN_KEY'],
12
- ]);
13
-
14
- function resolveExternalProductionConfig(configuration, context = {}) {
15
- const supplied = configuration && typeof configuration === 'object'
16
- ? configuration
17
- : {};
18
- validateApprovedSourceKeys(context.sourceKeys);
19
-
20
- for (const field of REQUIRED_FIELDS) {
21
- const value = supplied[field];
22
- if (typeof value !== 'string' || value.trim().length === 0) {
23
- throw blockingError(
24
- 'EXTERNAL_CREDENTIALS_REQUIRED',
25
- `${field} is required for ${context.operation || 'production operation'}`,
26
- field,
27
- );
28
- }
29
- }
30
-
31
- return {
32
- neo4jUri: supplied.neo4jUri.trim(),
33
- neo4jUsername: supplied.neo4jUsername.trim(),
34
- neo4jPassword: supplied.neo4jPassword,
35
- embeddingCredential: supplied.embeddingCredential,
36
- ...(supplied.neo4jDatabase === undefined
37
- ? {}
38
- : { neo4jDatabase: supplied.neo4jDatabase }),
39
- };
40
- }
41
-
42
- function validateApprovedSourceKeys(sourceKeys) {
43
- if (sourceKeys === undefined) {
44
- return;
45
- }
46
- if (!(sourceKeys instanceof Map)) {
47
- throw blockingError(
48
- 'UNAPPROVED_RUNTIME_CONFIG_SOURCE',
49
- 'runtime configuration source provenance is invalid',
50
- 'sourceKeys',
51
- );
52
- }
53
-
54
- for (const field of REQUIRED_FIELDS) {
55
- if (sourceKeys.get(field) !== APPROVED_SOURCE_KEYS.get(field)) {
56
- throw blockingError(
57
- 'UNAPPROVED_RUNTIME_CONFIG_SOURCE',
58
- `${field} is not resolved from its approved source`,
59
- field,
60
- );
61
- }
62
- }
63
- }
64
-
65
- function blockingError(category, message, field) {
66
- const error = new Error(message);
67
- error.category = category;
68
- error.field = field;
69
- return error;
70
- }
71
-
72
- module.exports = {
73
- resolveExternalProductionConfig,
74
- };
1
+ const REQUIRED_FIELDS = [
2
+ 'neo4jUri',
3
+ 'neo4jUsername',
4
+ 'neo4jPassword',
5
+ 'embeddingCredential',
6
+ ];
7
+ const APPROVED_SOURCE_KEYS = new Map([
8
+ ['neo4jUri', 'ARGO_NEO4J_DATABASE_URL'],
9
+ ['neo4jUsername', 'ARGO_NEO4J_DATABASE_USERNAME'],
10
+ ['neo4jPassword', 'ARGO_NEO4J_DATABASE_PASSWORD'],
11
+ ['embeddingCredential', 'QWEN_KEY'],
12
+ ]);
13
+
14
+ function resolveExternalProductionConfig(configuration, context = {}) {
15
+ const supplied = configuration && typeof configuration === 'object'
16
+ ? configuration
17
+ : {};
18
+ validateApprovedSourceKeys(context.sourceKeys);
19
+
20
+ for (const field of REQUIRED_FIELDS) {
21
+ const value = supplied[field];
22
+ if (typeof value !== 'string' || value.trim().length === 0) {
23
+ throw blockingError(
24
+ 'EXTERNAL_CREDENTIALS_REQUIRED',
25
+ `${field} is required for ${context.operation || 'production operation'}`,
26
+ field,
27
+ );
28
+ }
29
+ }
30
+
31
+ return {
32
+ neo4jUri: supplied.neo4jUri.trim(),
33
+ neo4jUsername: supplied.neo4jUsername.trim(),
34
+ neo4jPassword: supplied.neo4jPassword,
35
+ embeddingCredential: supplied.embeddingCredential,
36
+ ...(supplied.neo4jDatabase === undefined
37
+ ? {}
38
+ : { neo4jDatabase: supplied.neo4jDatabase }),
39
+ };
40
+ }
41
+
42
+ function validateApprovedSourceKeys(sourceKeys) {
43
+ if (sourceKeys === undefined) {
44
+ return;
45
+ }
46
+ if (!(sourceKeys instanceof Map)) {
47
+ throw blockingError(
48
+ 'UNAPPROVED_RUNTIME_CONFIG_SOURCE',
49
+ 'runtime configuration source provenance is invalid',
50
+ 'sourceKeys',
51
+ );
52
+ }
53
+
54
+ for (const field of REQUIRED_FIELDS) {
55
+ if (sourceKeys.get(field) !== APPROVED_SOURCE_KEYS.get(field)) {
56
+ throw blockingError(
57
+ 'UNAPPROVED_RUNTIME_CONFIG_SOURCE',
58
+ `${field} is not resolved from its approved source`,
59
+ field,
60
+ );
61
+ }
62
+ }
63
+ }
64
+
65
+ function blockingError(category, message, field) {
66
+ const error = new Error(message);
67
+ error.category = category;
68
+ error.field = field;
69
+ return error;
70
+ }
71
+
72
+ module.exports = {
73
+ resolveExternalProductionConfig,
74
+ };
@@ -1,49 +1,49 @@
1
- function createLiveEmbeddingProviderClient({ configuration, transport }) {
2
- if (!configuration || !transport || typeof transport.request !== 'function') {
3
- throw safeError('LIVE_PROVIDER_CONFIGURATION_REQUIRED');
4
- }
5
- return Object.freeze({
6
- async embed(input) {
7
- let response;
8
- try {
9
- response = await transport.request(
10
- `${configuration.embeddingBaseUrl}/embeddings`,
11
- {
12
- method: 'POST',
13
- headers: {
14
- Authorization: `Bearer ${configuration.qwenKey}`,
15
- 'Content-Type': 'application/json',
16
- },
17
- body: JSON.stringify({
18
- input,
19
- model: configuration.embeddingModel,
20
- dimensions: configuration.embeddingDimensions,
21
- }),
22
- },
23
- );
24
- } catch {
25
- throw safeError('LIVE_PROVIDER_REQUEST_FAILED');
26
- }
27
- if (!response || response.ok !== true || typeof response.json !== 'function') {
28
- throw safeError('LIVE_PROVIDER_REQUEST_FAILED');
29
- }
30
- let payload;
31
- try {
32
- payload = await response.json();
33
- } catch {
34
- throw safeError('LIVE_PROVIDER_RESPONSE_INVALID');
35
- }
36
- const vector = payload && payload.data && payload.data[0] && payload.data[0].embedding;
37
- if (!Array.isArray(vector)) throw safeError('LIVE_PROVIDER_RESPONSE_INVALID');
38
- return vector;
39
- },
40
- });
41
- }
42
-
43
- function safeError(category) {
44
- const error = new Error(category);
45
- error.category = category;
46
- return error;
47
- }
48
-
49
- module.exports = { createLiveEmbeddingProviderClient };
1
+ function createLiveEmbeddingProviderClient({ configuration, transport }) {
2
+ if (!configuration || !transport || typeof transport.request !== 'function') {
3
+ throw safeError('LIVE_PROVIDER_CONFIGURATION_REQUIRED');
4
+ }
5
+ return Object.freeze({
6
+ async embed(input) {
7
+ let response;
8
+ try {
9
+ response = await transport.request(
10
+ `${configuration.embeddingBaseUrl}/embeddings`,
11
+ {
12
+ method: 'POST',
13
+ headers: {
14
+ Authorization: `Bearer ${configuration.qwenKey}`,
15
+ 'Content-Type': 'application/json',
16
+ },
17
+ body: JSON.stringify({
18
+ input,
19
+ model: configuration.embeddingModel,
20
+ dimensions: configuration.embeddingDimensions,
21
+ }),
22
+ },
23
+ );
24
+ } catch {
25
+ throw safeError('LIVE_PROVIDER_REQUEST_FAILED');
26
+ }
27
+ if (!response || response.ok !== true || typeof response.json !== 'function') {
28
+ throw safeError('LIVE_PROVIDER_REQUEST_FAILED');
29
+ }
30
+ let payload;
31
+ try {
32
+ payload = await response.json();
33
+ } catch {
34
+ throw safeError('LIVE_PROVIDER_RESPONSE_INVALID');
35
+ }
36
+ const vector = payload && payload.data && payload.data[0] && payload.data[0].embedding;
37
+ if (!Array.isArray(vector)) throw safeError('LIVE_PROVIDER_RESPONSE_INVALID');
38
+ return vector;
39
+ },
40
+ });
41
+ }
42
+
43
+ function safeError(category) {
44
+ const error = new Error(category);
45
+ error.category = category;
46
+ return error;
47
+ }
48
+
49
+ module.exports = { createLiveEmbeddingProviderClient };
@@ -1,37 +1,37 @@
1
- function createNeo4jNativeRetrieval(dependencies = {}) {
2
- const queryBoundary = dependencies.queryBoundary;
3
- if (!queryBoundary || typeof queryBoundary.query !== 'function') {
4
- throw new TypeError('queryBoundary.query is required');
5
- }
6
-
7
- return {
8
- async retrieve(request) {
9
- return queryBoundary.query(request);
10
- },
11
-
12
- async retrieveThresholdCandidates(request) {
13
- if (typeof queryBoundary.queryThresholdCandidates === 'function') {
14
- return queryBoundary.queryThresholdCandidates(request);
15
- }
16
- const result = await queryBoundary.query(request);
17
- if (Array.isArray(result)) {
18
- return result;
19
- }
20
- if (Array.isArray(result && result.thresholdCandidates)) {
21
- return result.thresholdCandidates;
22
- }
23
- if (Array.isArray(result && result.seeds)) {
24
- return result.seeds.map(seed => ({
25
- objectType: seed.objectType,
26
- id: seed.id,
27
- score: typeof seed.score === 'number' ? seed.score : 1,
28
- }));
29
- }
30
- return [];
31
- },
32
- };
33
- }
34
-
35
- module.exports = {
36
- createNeo4jNativeRetrieval,
37
- };
1
+ function createNeo4jNativeRetrieval(dependencies = {}) {
2
+ const queryBoundary = dependencies.queryBoundary;
3
+ if (!queryBoundary || typeof queryBoundary.query !== 'function') {
4
+ throw new TypeError('queryBoundary.query is required');
5
+ }
6
+
7
+ return {
8
+ async retrieve(request) {
9
+ return queryBoundary.query(request);
10
+ },
11
+
12
+ async retrieveThresholdCandidates(request) {
13
+ if (typeof queryBoundary.queryThresholdCandidates === 'function') {
14
+ return queryBoundary.queryThresholdCandidates(request);
15
+ }
16
+ const result = await queryBoundary.query(request);
17
+ if (Array.isArray(result)) {
18
+ return result;
19
+ }
20
+ if (Array.isArray(result && result.thresholdCandidates)) {
21
+ return result.thresholdCandidates;
22
+ }
23
+ if (Array.isArray(result && result.seeds)) {
24
+ return result.seeds.map(seed => ({
25
+ objectType: seed.objectType,
26
+ id: seed.id,
27
+ score: typeof seed.score === 'number' ? seed.score : 1,
28
+ }));
29
+ }
30
+ return [];
31
+ },
32
+ };
33
+ }
34
+
35
+ module.exports = {
36
+ createNeo4jNativeRetrieval,
37
+ };
@@ -1,51 +1,51 @@
1
- # Production Semantic Persistence Contract
2
-
3
- This local contract refines `OVERALL_ARCHITECTURE.md` and the parent `.argo/scripts/graph-rag/ARCHITECTURE.md`.
4
-
5
- ## Responsibilities
6
-
7
- - `productionSemanticBackfill.js` owns the explicit WP-P1 backfill use case through `createProductionSemanticBackfill(dependencies).execute({ explicitOptIn })`.
8
- - Backfill begins only after the injected structural-projection boundary proves the same canonical version complete. Structural projection is a prerequisite, not semantic readiness.
9
- - Backfill reads one immutable canonical snapshot and independently enumerates every Element, ArchitectureRelationship, and View. It never fabricates a canonical mutation to trigger embedding generation.
10
- - Work is bounded by an explicit positive batch size. Every channel has durable totals, completed counts, cursor, canonical version, retry, and isolated-failure checkpoints.
11
- - Resume starts from durable channel checkpoints and does not repeat completed work. Acceptance independently compares provider and durable-upsert canonical identities before and after interruption; an implementation-reported resume flag is not evidence. Rerun performs stable-identity upserts and is idempotent for unchanged canonical/content/index/provider/model/version/dimensions/vector evidence.
12
- - A record failure is observable and isolated from other records. Partial or failed channels remain non-Aligned. Alignment may become `Aligned` only after Element, ArchitectureRelationship, and View channels all report complete for the same canonical version.
13
- - `productionSemanticProjectionStore.js` owns `createProductionSemanticProjectionStore(dependencies)` and exposes only `upsertRecords(records)`, `deleteTombstones(tombstones)`, `readRecords()`, and `close()`.
14
- - `productionSemanticNeo4jAdapter.js` owns `createProductionSemanticNeo4jAdapter(dependencies)` as the concrete durable production projection adapter. `productionSemanticCheckpointStore.js` owns `createProductionSemanticCheckpointStore(dependencies)` as the concrete durable per-channel checkpoint adapter. Deterministic tests inject only a recording raw Neo4j driver beneath these production factories; they do not substitute an in-memory projection or checkpoint implementation.
15
- - The production store validates stable canonical identity and complete channel, canonical/content/index, provider/model/model-version/dimensions, and vector metadata before persistence.
16
- - The production store depends inward on a durable Neo4j persistence adapter. It must MERGE/upsert changed records by stable canonical identity and delete tombstones by that identity.
17
- - Production records have no `runId`; a `runId`-bearing record is rejected before persistence. The store's complete callable public surface is exactly `upsertRecords`, `deleteTombstones`, `readRecords`, and `close`: no cleanup, runId-delete, truncate, clear, or reset API is permitted. Production never imports or delegates to `liveEmbeddingNeo4jBoundary.js`.
18
- - Existing live E2E runId cleanup remains test-only and unchanged. It cannot select or delete production semantic projection labels or identities.
19
- - The same four-method production store is the only durable target for automatic incremental indexing. Successful batch and focused Element, ArchitectureRelationship, and View add/update/remove writes provide exact touched identities: add/update records use `upsertRecords`, removed identities use `deleteTombstones`, and unrelated records remain unchanged across restart. Incremental records carry the same complete canonical/content/index/provider/model/model-version/dimensions/vector contract as full reconciliation.
20
- - Readiness invalidation belongs to the canonical-write orchestration boundary and occurs before this store or provider is called. This directory may report persistence success/failure but cannot mark Aligned; queryability and global coherence are later outer checks.
21
- - External Neo4j and provider credentials use the existing approved external configuration and qualification boundaries. Missing configuration or provider qualification blocks before provider, projection, checkpoint, or index side effects. Missing `neo4jUri` blocks startup; tests never invent synchronization evidence.
22
- - Canonical JSON remains authority at `design/KG/SystemArchitecture.json`. The durable Neo4j records are subordinate projection/index state and have no API that writes canonical JSON.
23
-
24
- ## Public interface
25
-
26
- - `createProductionSemanticBackfill(dependencies)` requires canonical-source, structural-projection, qualified-provider, durable projection-store, checkpoint-store, external configuration, qualification, and bounded-batch dependencies; it returns `execute({ explicitOptIn })`.
27
- - `createProductionSemanticProjectionStore(dependencies)` requires the concrete durable adapter, canonical-authority policy, external configuration, and qualified-provider evidence; it returns exactly the four store methods listed above.
28
- - `createProductionSemanticNeo4jAdapter(dependencies)` and `createProductionSemanticCheckpointStore(dependencies)` translate store/checkpoint operations to the configured durable Neo4j driver boundary.
29
- - The parent runtime exposes `runSemanticBackfill(request)` and composes the concrete adapter, store, checkpoint store, and backfill from `semanticPersistence` production dependencies.
30
- - The parent durable incremental lifecycle composes the existing projection store directly for exact touched upsert/tombstone operations. It does not reuse live-E2E `writeEvidence(runId, ...)` or cleanup APIs.
31
- - Canonical argo init privately delegates to `runtime.runSemanticBackfill(request)` after its exact enabled/valid gate decision. No standalone MCP backfill route is exposed. The private composition must exist without Harness injection; missing internal consent fails `SP01_EXPLICIT_OPT_IN_REQUIRED`, and structural/canonical mismatch fails `SP01_STRUCTURAL_VERSION_MISMATCH`, both before provider or durable effects. Structural mutation uses the incremental lifecycle and never fakes a full-backfill trigger.
32
-
33
- ## Local dependencies
34
-
35
- - MCP gateway → production Graph RAG composition → semantic backfill → canonical/structural/provider/store/checkpoint ports.
36
- - Semantic backfill may depend on provider and projection interfaces; provider and store adapters must not depend outward on backfill orchestration.
37
- - Production semantic persistence may depend on the approved Neo4j JavaScript driver adapter and existing external configuration/qualification modules.
38
- - No file in this directory may depend on `tests/`, Python, Neo4j GenAI procedures, the live-E2E evidence boundary, or mutable canonical-write internals.
39
- - Checkpoint persistence and semantic projection persistence are durable production state. Neither is a process-local map in production composition.
40
-
41
- ## Owned tests
42
-
43
- - `tests/harness/productionSemanticPersistenceHarness.js`
44
- - `tests/explicit/entries/runProductionSemanticBackfill.js` — SP-01 control point: shipped non-injected JSON-RPC `tools/call` plus explicit backfill after structural projection. Observation: the default MCP path owns production composition and fails closed before secrets/Neo4j, while the deterministic injected raw-driver scenario proves independent complete channels, bounded checkpoints, interruption/resume, isolated failure, idempotent rerun, complete metadata, no fake mutation, and alignment only after all channels complete.
45
- - `tests/explicit/entries/runPersistentSemanticProjectionLifecycle.js` — SP-02 control point: durable projection across restart, changed-record upsert, tombstone deletion, and unrelated live-E2E cleanup. Observation: stable identity and metadata survive, production has no runId cleanup, canonical authority remains intact, and Neo4j remains subordinate.
46
- - `tests/architecture/production-semantic-persistence/architecture-boundary.guard.js` — `ArchitectureBoundaryGuard`.
47
- - `tests/architecture/production-semantic-persistence/dependency-direction.guard.js` — `DependencyDirectionGuard`.
48
- - `tests/architecture/production-semantic-persistence/explicit-entrypoint-correctness.guard.js` — `ExplicitEntrypointCorrectnessGuard`.
49
- - `tests/architecture/production-semantic-persistence/implementation-traceability.guard.js` — `KeyImplementationTraceabilityGuard`.
50
-
51
- All owned Harness, explicit entrypoints, guards, this contract, the root and parent contracts, incoming intent handoff, runner failure records, and canonical graph are frozen during Coding/Repair. The protected fixture is `canonicalThreeChannelFixture`; the protected baseline is the committed WP-P1 pre-coding full-run result in `design/KG/test-failure-records.json`.
1
+ # Production Semantic Persistence Contract
2
+
3
+ This local contract refines `OVERALL_ARCHITECTURE.md` and the parent `.argo/scripts/graph-rag/ARCHITECTURE.md`.
4
+
5
+ ## Responsibilities
6
+
7
+ - `productionSemanticBackfill.js` owns the explicit WP-P1 backfill use case through `createProductionSemanticBackfill(dependencies).execute({ explicitOptIn })`.
8
+ - Backfill begins only after the injected structural-projection boundary proves the same canonical version complete. Structural projection is a prerequisite, not semantic readiness.
9
+ - Backfill reads one immutable canonical snapshot and independently enumerates every Element, ArchitectureRelationship, and View. It never fabricates a canonical mutation to trigger embedding generation.
10
+ - Work is bounded by an explicit positive batch size. Every channel has durable totals, completed counts, cursor, canonical version, retry, and isolated-failure checkpoints.
11
+ - Resume starts from durable channel checkpoints and does not repeat completed work. Acceptance independently compares provider and durable-upsert canonical identities before and after interruption; an implementation-reported resume flag is not evidence. Rerun performs stable-identity upserts and is idempotent for unchanged canonical/content/index/provider/model/version/dimensions/vector evidence.
12
+ - A record failure is observable and isolated from other records. Partial or failed channels remain non-Aligned. Alignment may become `Aligned` only after Element, ArchitectureRelationship, and View channels all report complete for the same canonical version.
13
+ - `productionSemanticProjectionStore.js` owns `createProductionSemanticProjectionStore(dependencies)` and exposes only `upsertRecords(records)`, `deleteTombstones(tombstones)`, `readRecords()`, and `close()`.
14
+ - `productionSemanticNeo4jAdapter.js` owns `createProductionSemanticNeo4jAdapter(dependencies)` as the concrete durable production projection adapter. `productionSemanticCheckpointStore.js` owns `createProductionSemanticCheckpointStore(dependencies)` as the concrete durable per-channel checkpoint adapter. Deterministic tests inject only a recording raw Neo4j driver beneath these production factories; they do not substitute an in-memory projection or checkpoint implementation.
15
+ - The production store validates stable canonical identity and complete channel, canonical/content/index, provider/model/model-version/dimensions, and vector metadata before persistence.
16
+ - The production store depends inward on a durable Neo4j persistence adapter. It must MERGE/upsert changed records by stable canonical identity and delete tombstones by that identity.
17
+ - Production records have no `runId`; a `runId`-bearing record is rejected before persistence. The store's complete callable public surface is exactly `upsertRecords`, `deleteTombstones`, `readRecords`, and `close`: no cleanup, runId-delete, truncate, clear, or reset API is permitted. Production never imports or delegates to `liveEmbeddingNeo4jBoundary.js`.
18
+ - Existing live E2E runId cleanup remains test-only and unchanged. It cannot select or delete production semantic projection labels or identities.
19
+ - The same four-method production store is the only durable target for automatic incremental indexing. Successful batch and focused Element, ArchitectureRelationship, and View add/update/remove writes provide exact touched identities: add/update records use `upsertRecords`, removed identities use `deleteTombstones`, and unrelated records remain unchanged across restart. Incremental records carry the same complete canonical/content/index/provider/model/model-version/dimensions/vector contract as full reconciliation.
20
+ - Readiness invalidation belongs to the canonical-write orchestration boundary and occurs before this store or provider is called. This directory may report persistence success/failure but cannot mark Aligned; queryability and global coherence are later outer checks.
21
+ - External Neo4j and provider credentials use the existing approved external configuration and qualification boundaries. Missing configuration or provider qualification blocks before provider, projection, checkpoint, or index side effects. Missing `neo4jUri` blocks startup; tests never invent synchronization evidence.
22
+ - Canonical JSON remains authority at `design/KG/SystemArchitecture.json`. The durable Neo4j records are subordinate projection/index state and have no API that writes canonical JSON.
23
+
24
+ ## Public interface
25
+
26
+ - `createProductionSemanticBackfill(dependencies)` requires canonical-source, structural-projection, qualified-provider, durable projection-store, checkpoint-store, external configuration, qualification, and bounded-batch dependencies; it returns `execute({ explicitOptIn })`.
27
+ - `createProductionSemanticProjectionStore(dependencies)` requires the concrete durable adapter, canonical-authority policy, external configuration, and qualified-provider evidence; it returns exactly the four store methods listed above.
28
+ - `createProductionSemanticNeo4jAdapter(dependencies)` and `createProductionSemanticCheckpointStore(dependencies)` translate store/checkpoint operations to the configured durable Neo4j driver boundary.
29
+ - The parent runtime exposes `runSemanticBackfill(request)` and composes the concrete adapter, store, checkpoint store, and backfill from `semanticPersistence` production dependencies.
30
+ - The parent durable incremental lifecycle composes the existing projection store directly for exact touched upsert/tombstone operations. It does not reuse live-E2E `writeEvidence(runId, ...)` or cleanup APIs.
31
+ - Canonical argo init privately delegates to `runtime.runSemanticBackfill(request)` after its exact enabled/valid gate decision. No standalone MCP backfill route is exposed. The private composition must exist without Harness injection; missing internal consent fails `SP01_EXPLICIT_OPT_IN_REQUIRED`, and structural/canonical mismatch fails `SP01_STRUCTURAL_VERSION_MISMATCH`, both before provider or durable effects. Structural mutation uses the incremental lifecycle and never fakes a full-backfill trigger.
32
+
33
+ ## Local dependencies
34
+
35
+ - MCP gateway → production Graph RAG composition → semantic backfill → canonical/structural/provider/store/checkpoint ports.
36
+ - Semantic backfill may depend on provider and projection interfaces; provider and store adapters must not depend outward on backfill orchestration.
37
+ - Production semantic persistence may depend on the approved Neo4j JavaScript driver adapter and existing external configuration/qualification modules.
38
+ - No file in this directory may depend on `tests/`, Python, Neo4j GenAI procedures, the live-E2E evidence boundary, or mutable canonical-write internals.
39
+ - Checkpoint persistence and semantic projection persistence are durable production state. Neither is a process-local map in production composition.
40
+
41
+ ## Owned tests
42
+
43
+ - `tests/harness/productionSemanticPersistenceHarness.js`
44
+ - `tests/explicit/entries/runProductionSemanticBackfill.js` — SP-01 control point: shipped non-injected JSON-RPC `tools/call` plus explicit backfill after structural projection. Observation: the default MCP path owns production composition and fails closed before secrets/Neo4j, while the deterministic injected raw-driver scenario proves independent complete channels, bounded checkpoints, interruption/resume, isolated failure, idempotent rerun, complete metadata, no fake mutation, and alignment only after all channels complete.
45
+ - `tests/explicit/entries/runPersistentSemanticProjectionLifecycle.js` — SP-02 control point: durable projection across restart, changed-record upsert, tombstone deletion, and unrelated live-E2E cleanup. Observation: stable identity and metadata survive, production has no runId cleanup, canonical authority remains intact, and Neo4j remains subordinate.
46
+ - `tests/architecture/production-semantic-persistence/architecture-boundary.guard.js` — `ArchitectureBoundaryGuard`.
47
+ - `tests/architecture/production-semantic-persistence/dependency-direction.guard.js` — `DependencyDirectionGuard`.
48
+ - `tests/architecture/production-semantic-persistence/explicit-entrypoint-correctness.guard.js` — `ExplicitEntrypointCorrectnessGuard`.
49
+ - `tests/architecture/production-semantic-persistence/implementation-traceability.guard.js` — `KeyImplementationTraceabilityGuard`.
50
+
51
+ All owned Harness, explicit entrypoints, guards, this contract, the root and parent contracts, incoming intent handoff, runner failure records, and canonical graph are frozen during Coding/Repair. The protected fixture is `canonicalThreeChannelFixture`; the protected baseline is the committed WP-P1 pre-coding full-run result in `design/KG/test-failure-records.json`.