archctx-contracts 0.2.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/fixtures/boundary/architecture-node-extension.json +1 -1
  2. package/fixtures/boundary/explorer-projection-v2-budget.json +87 -0
  3. package/fixtures/invalid/architecture-snapshot-unknown-mode.json +22 -4
  4. package/fixtures/invalid/explorer-projection-query-v2-caller-scope.json +7 -0
  5. package/fixtures/invalid/explorer-projection-v2-derived-subject.json +101 -0
  6. package/fixtures/invalid/node-unknown-field.json +1 -1
  7. package/fixtures/valid/archctx-capabilities.json +14 -0
  8. package/fixtures/valid/architecture-flow.json +53 -0
  9. package/fixtures/valid/architecture-node.json +19 -2
  10. package/fixtures/valid/architecture-refresh-signal.json +35 -0
  11. package/fixtures/valid/architecture-snapshot.json +22 -4
  12. package/fixtures/valid/explorer-delta-query.json +11 -0
  13. package/fixtures/valid/explorer-projection-delta.json +32 -0
  14. package/fixtures/valid/explorer-projection-query-v2.json +6 -0
  15. package/fixtures/valid/explorer-projection-v2.json +138 -0
  16. package/fixtures/valid/product-version-manifest.json +7 -7
  17. package/fixtures/valid/projection-request.json +14 -0
  18. package/fixtures/valid/projection-result.json +47 -0
  19. package/package.json +1 -1
  20. package/schemas/repo/architecture-flow.schema.json +97 -0
  21. package/schemas/repo/architecture-node.schema.json +39 -2
  22. package/schemas/runtime/archctx-capabilities.schema.json +45 -0
  23. package/schemas/runtime/architecture-event.schema.json +172 -2
  24. package/schemas/runtime/architecture-refresh-signal.schema.json +88 -0
  25. package/schemas/runtime/architecture-snapshot.schema.json +37 -4
  26. package/schemas/runtime/changeset.schema.json +1 -1
  27. package/schemas/runtime/explorer-delta-query.schema.json +24 -0
  28. package/schemas/runtime/explorer-projection-delta.schema.json +79 -0
  29. package/schemas/runtime/explorer-projection-query-v2.schema.json +42 -0
  30. package/schemas/runtime/explorer-projection-v2.schema.json +538 -0
  31. package/schemas/runtime/projection-request.schema.json +61 -0
  32. package/schemas/runtime/projection-result.schema.json +162 -0
  33. package/src/architecture.ts +73 -0
  34. package/src/index.ts +2 -0
  35. package/src/ledger.ts +125 -3
  36. package/src/ports.ts +399 -32
  37. package/src/product-version.ts +5 -5
  38. package/src/projection.ts +301 -0
  39. package/src/schema.ts +3 -2
  40. package/src/validator.ts +70 -6
  41. package/fixtures/invalid/explorer-projection-write-field.json +0 -21
  42. package/fixtures/valid/explorer-projection.json +0 -53
  43. package/schemas/runtime/explorer-projection.schema.json +0 -92
@@ -0,0 +1,162 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://archcontext.dev/schemas/runtime/projection-result.schema.json",
4
+ "title": "ProjectionResultV1",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["schemaVersion", "requestId", "status", "inputSnapshot", "outputSnapshot", "affectedNodeIds", "files", "humanActions", "refreshSignals", "receiptDigest"],
8
+ "properties": {
9
+ "schemaVersion": { "const": "archcontext.projection-result/v1" },
10
+ "requestId": { "type": "string", "pattern": "^[a-zA-Z0-9_.:-]+$", "minLength": 1 },
11
+ "status": { "enum": ["adoption-required", "applied", "blocked", "human-action-required", "noop", "permanent-failure", "planned", "retryable-failure"] },
12
+ "inputSnapshot": { "$ref": "#/$defs/snapshot" },
13
+ "outputSnapshot": { "$ref": "#/$defs/snapshot" },
14
+ "affectedNodeIds": { "type": "array", "uniqueItems": true, "description": "Canonical wire order is lexicographic and is enforced by projectionResultInvariantIssues.", "items": { "type": "string", "minLength": 1 } },
15
+ "files": { "type": "array", "description": "Canonical wire order is by path and is enforced by projectionResultInvariantIssues.", "items": { "$ref": "#/$defs/file" } },
16
+ "humanActions": { "type": "array", "items": { "$ref": "#/$defs/humanAction" } },
17
+ "refreshSignals": { "type": "array", "description": "Canonical wire order is by signalId and cross-object receipt/snapshot bindings are enforced by projectionResultInvariantIssues.", "items": { "$ref": "#/$defs/refreshSignal" } },
18
+ "receiptDigest": { "$ref": "#/$defs/digest" }
19
+ },
20
+ "allOf": [
21
+ {
22
+ "if": { "properties": { "status": { "enum": ["adoption-required", "human-action-required"] } }, "required": ["status"] },
23
+ "then": { "properties": { "humanActions": { "minItems": 1 } } },
24
+ "else": { "properties": { "humanActions": { "maxItems": 0 } } }
25
+ }
26
+ ],
27
+ "$defs": {
28
+ "digest": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" },
29
+ "nullableDigest": { "type": ["string", "null"], "pattern": "^sha256:[a-f0-9]{64}$" },
30
+ "snapshot": {
31
+ "type": "object",
32
+ "additionalProperties": false,
33
+ "required": ["repositoryId", "workspaceId", "headSha", "baseHeadSha", "worktreeDigest", "sourceTreeDigest", "modelDigest", "codeGraphDigest", "indexedWorktreeDigest", "projectionInputDigest", "rendererVersion", "layoutVersion", "generatedFrom"],
34
+ "properties": {
35
+ "repositoryId": { "type": "string", "minLength": 1 },
36
+ "workspaceId": { "type": "string", "minLength": 1 },
37
+ "headSha": { "type": "string", "pattern": "^[a-f0-9]{40}$" },
38
+ "baseHeadSha": { "type": "string", "pattern": "^[a-f0-9]{40}$" },
39
+ "worktreeDigest": { "$ref": "#/$defs/digest" },
40
+ "sourceTreeDigest": { "$ref": "#/$defs/digest" },
41
+ "modelDigest": { "$ref": "#/$defs/digest" },
42
+ "codeGraphDigest": { "$ref": "#/$defs/digest" },
43
+ "indexedWorktreeDigest": { "$ref": "#/$defs/nullableDigest" },
44
+ "projectionInputDigest": { "$ref": "#/$defs/digest" },
45
+ "rendererVersion": { "const": "archcontext.docs-renderer/v2" },
46
+ "layoutVersion": { "const": "archcontext.docs-layout/v1" },
47
+ "generatedFrom": {
48
+ "type": "object",
49
+ "additionalProperties": false,
50
+ "required": ["codeGraphPackage", "codeGraphVersion", "codeGraphBinaryDigest", "codeGraphStatus"],
51
+ "properties": {
52
+ "codeGraphPackage": { "const": "@colbymchenry/codegraph" },
53
+ "codeGraphVersion": { "const": "1.5.0" },
54
+ "codeGraphBinaryDigest": { "$ref": "#/$defs/digest" },
55
+ "codeGraphStatus": { "enum": ["ready", "unavailable"] }
56
+ }
57
+ }
58
+ }
59
+ },
60
+ "file": {
61
+ "type": "object",
62
+ "additionalProperties": false,
63
+ "required": ["path", "action", "preimageDigest", "outputDigest"],
64
+ "properties": {
65
+ "path": {
66
+ "type": "string",
67
+ "minLength": 1,
68
+ "not": { "anyOf": [{ "pattern": "^/" }, { "pattern": "\\\\" }, { "pattern": "(^|/)\\.\\.(/|$)" }] }
69
+ },
70
+ "action": { "enum": ["create", "delete", "unchanged", "update"] },
71
+ "preimageDigest": { "$ref": "#/$defs/nullableDigest" },
72
+ "outputDigest": { "$ref": "#/$defs/nullableDigest" }
73
+ },
74
+ "allOf": [
75
+ {
76
+ "if": { "properties": { "action": { "const": "create" } }, "required": ["action"] },
77
+ "then": { "properties": { "preimageDigest": { "const": null }, "outputDigest": { "$ref": "#/$defs/digest" } } }
78
+ },
79
+ {
80
+ "if": { "properties": { "action": { "const": "delete" } }, "required": ["action"] },
81
+ "then": { "properties": { "preimageDigest": { "$ref": "#/$defs/digest" }, "outputDigest": { "const": null } } }
82
+ },
83
+ {
84
+ "if": { "properties": { "action": { "enum": ["unchanged", "update"] } }, "required": ["action"] },
85
+ "then": { "properties": { "preimageDigest": { "$ref": "#/$defs/digest" }, "outputDigest": { "$ref": "#/$defs/digest" } } }
86
+ }
87
+ ]
88
+ },
89
+ "humanAction": {
90
+ "type": "object",
91
+ "additionalProperties": false,
92
+ "required": ["reasonCode", "affectedNodeIds", "requestPayloadDigest"],
93
+ "properties": {
94
+ "reasonCode": { "enum": ["adoption-required", "manual-region-conflict", "target-collision", "unprovable-required-flow", "unresolved-major-change"] },
95
+ "affectedNodeIds": { "type": "array", "uniqueItems": true, "items": { "type": "string", "minLength": 1 } },
96
+ "requestPayloadDigest": { "$ref": "#/$defs/digest" }
97
+ }
98
+ },
99
+ "digestSet": {
100
+ "type": "object",
101
+ "additionalProperties": false,
102
+ "required": ["modelDigest", "sourceTreeDigest", "flowProofDigest", "projectionDigest"],
103
+ "properties": {
104
+ "modelDigest": { "$ref": "#/$defs/digest" },
105
+ "sourceTreeDigest": { "$ref": "#/$defs/digest" },
106
+ "flowProofDigest": { "$ref": "#/$defs/digest" },
107
+ "projectionDigest": { "$ref": "#/$defs/digest" }
108
+ }
109
+ },
110
+ "reasonCode": {
111
+ "enum": ["constraint-changed", "entrypoint-changed", "interface-changed", "lifecycle-changed", "node-added", "node-moved", "node-removed", "node-renamed", "ownership-changed", "relation-changed", "responsibility-changed", "risk-boundary-changed", "verified-flow-proof-changed"]
112
+ },
113
+ "refreshSignal": {
114
+ "type": "object",
115
+ "additionalProperties": false,
116
+ "required": ["schemaVersion", "signalId", "idempotencyKey", "mode", "repository", "worktree", "cause", "reasonCodes", "affectedNodeIds", "refreshTargets", "baseDigests", "resultingDigests", "projectionReceiptDigest"],
117
+ "properties": {
118
+ "schemaVersion": { "const": "archcontext.architecture-refresh-signal/v1" },
119
+ "signalId": { "$ref": "#/$defs/digest" },
120
+ "idempotencyKey": { "$ref": "#/$defs/digest" },
121
+ "mode": { "enum": ["human-action-required", "refresh-required"] },
122
+ "repository": { "type": "object", "additionalProperties": false, "required": ["repositoryId"], "properties": { "repositoryId": { "type": "string", "minLength": 1 } } },
123
+ "worktree": {
124
+ "type": "object",
125
+ "additionalProperties": false,
126
+ "required": ["workspaceId", "headSha", "worktreeDigest"],
127
+ "properties": {
128
+ "workspaceId": { "type": "string", "minLength": 1 },
129
+ "headSha": { "type": "string", "pattern": "^[a-f0-9]{40}$" },
130
+ "worktreeDigest": { "$ref": "#/$defs/digest" }
131
+ }
132
+ },
133
+ "cause": { "enum": ["accepted-semantic-delta", "unresolved-major-candidate", "verified-flow-proof-delta"] },
134
+ "acceptedChange": { "$ref": "#/$defs/acceptedChange" },
135
+ "reasonCodes": { "type": "array", "minItems": 1, "uniqueItems": true, "items": { "$ref": "#/$defs/reasonCode" } },
136
+ "affectedNodeIds": { "type": "array", "minItems": 1, "uniqueItems": true, "items": { "type": "string", "minLength": 1 } },
137
+ "refreshTargets": { "type": "array", "minItems": 1, "uniqueItems": true, "items": { "enum": ["architecture-contract-context", "architecture-readiness", "architecture-request-index", "capability-context", "capability-index"] } },
138
+ "baseDigests": { "$ref": "#/$defs/digestSet" },
139
+ "resultingDigests": { "$ref": "#/$defs/digestSet" },
140
+ "projectionReceiptDigest": { "$ref": "#/$defs/digest" }
141
+ },
142
+ "allOf": [
143
+ {
144
+ "if": { "properties": { "cause": { "const": "unresolved-major-candidate" } }, "required": ["cause"] },
145
+ "then": { "properties": { "mode": { "const": "human-action-required" } }, "not": { "required": ["acceptedChange"] } },
146
+ "else": { "properties": { "mode": { "const": "refresh-required" } }, "required": ["acceptedChange"] }
147
+ }
148
+ ]
149
+ },
150
+ "acceptedChange": {
151
+ "type": "object",
152
+ "additionalProperties": false,
153
+ "required": ["changeSetId", "eventId", "reasonCodes", "affectedNodeIds"],
154
+ "properties": {
155
+ "changeSetId": { "type": "string", "minLength": 1 },
156
+ "eventId": { "type": "string", "minLength": 1 },
157
+ "reasonCodes": { "type": "array", "minItems": 1, "uniqueItems": true, "items": { "$ref": "#/$defs/reasonCode" } },
158
+ "affectedNodeIds": { "type": "array", "minItems": 1, "uniqueItems": true, "items": { "type": "string", "minLength": 1 } }
159
+ }
160
+ }
161
+ }
162
+ }
@@ -0,0 +1,73 @@
1
+ export interface ArchitectureSinkSelectorV2 {
2
+ id: string;
3
+ path: string;
4
+ symbol: string;
5
+ }
6
+
7
+ export interface ArchitectureEntrypointSymbolV2 {
8
+ name: string;
9
+ sinks: ArchitectureSinkSelectorV2[];
10
+ }
11
+
12
+ export interface ArchitectureEntrypointV2 {
13
+ id: string;
14
+ path: string;
15
+ symbols: ArchitectureEntrypointSymbolV2[];
16
+ }
17
+
18
+ export interface ArchitectureNodeSourceV2 {
19
+ include?: string[];
20
+ exclude?: string[];
21
+ entrypoints?: ArchitectureEntrypointV2[];
22
+ }
23
+
24
+ export interface ArchitectureFlowEvidenceSelectorV1 {
25
+ entrypointId: string;
26
+ sourceSymbol: string;
27
+ sinkId: string;
28
+ }
29
+
30
+ export interface ArchitectureFlowParticipantV1 {
31
+ id: string;
32
+ nodeId: string;
33
+ }
34
+
35
+ export interface ArchitectureFlowStepV1 {
36
+ id: string;
37
+ from: string;
38
+ to: string;
39
+ label: string;
40
+ evidence: ArchitectureFlowEvidenceSelectorV1;
41
+ }
42
+
43
+ export interface ArchitectureFlowOutcomeV1 {
44
+ id: string;
45
+ kind: "success" | "error";
46
+ label: string;
47
+ steps: ArchitectureFlowStepV1[];
48
+ terminal: {
49
+ participant: string;
50
+ label: string;
51
+ };
52
+ }
53
+
54
+ export type ArchitectureFlowV1 = ArchitectureRequiredFlowV1 | ArchitectureNotApplicableFlowV1;
55
+
56
+ interface ArchitectureFlowBaseV1 {
57
+ schemaVersion: "archcontext.flow/v1";
58
+ id: string;
59
+ capabilityId: string;
60
+ name: string;
61
+ }
62
+
63
+ export interface ArchitectureRequiredFlowV1 extends ArchitectureFlowBaseV1 {
64
+ applicability: "required";
65
+ participants: ArchitectureFlowParticipantV1[];
66
+ steps: ArchitectureFlowStepV1[];
67
+ outcomes: ArchitectureFlowOutcomeV1[];
68
+ }
69
+
70
+ export interface ArchitectureNotApplicableFlowV1 extends ArchitectureFlowBaseV1 {
71
+ applicability: "not-applicable";
72
+ rationale: string;
73
+ }
package/src/index.ts CHANGED
@@ -1,9 +1,11 @@
1
1
  export * from "./control-plane-routes";
2
+ export * from "./architecture";
2
3
  export * from "./external-docs";
3
4
  export * from "./github-governance";
4
5
  export * from "./ledger";
5
6
  export * from "./ports";
6
7
  export * from "./practices";
8
+ export * from "./projection";
7
9
  export * from "./product-version";
8
10
  export * from "./schema";
9
11
  export * from "./validator";
package/src/ledger.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { digestJson, type Json } from "./schema";
2
2
 
3
3
  export const ARCHITECTURE_EVENT_SCHEMA_VERSION = "archcontext.architecture-event/v1" as const;
4
- export const ARCHITECTURE_SNAPSHOT_SCHEMA_VERSION = "archcontext.architecture-snapshot/v1" as const;
4
+ export const ARCHITECTURE_SNAPSHOT_SCHEMA_VERSION = "archcontext.architecture-snapshot/v2" as const;
5
5
  export const EVIDENCE_ITEM_SCHEMA_VERSION = "archcontext.evidence-item/v2" as const;
6
6
  export const EVIDENCE_BINDING_SCHEMA_VERSION = "archcontext.evidence-binding/v1" as const;
7
7
  export const RECOMMENDATION_RUN_SCHEMA_VERSION = "archcontext.recommendation-run/v1" as const;
@@ -172,17 +172,25 @@ export interface ArchitectureEventV1 {
172
172
  extensions?: Record<string, Json>;
173
173
  }
174
174
 
175
- export interface ArchitectureSnapshotV1 {
175
+ export interface ArchitectureSnapshotV2 {
176
176
  schemaVersion: typeof ARCHITECTURE_SNAPSHOT_SCHEMA_VERSION;
177
177
  snapshotId: string;
178
178
  repository: ArchitectureRepositoryIdentityV1;
179
179
  worktree: ArchitectureWorktreeIdentityV1;
180
180
  sourceMode: ArchitectureLedgerMode;
181
181
  eventCursor: {
182
+ eventCount: number;
183
+ lastEventSequence: number;
182
184
  lastEventId: string;
183
185
  lastEventHash: string;
184
186
  };
185
187
  graphDigest: string;
188
+ evidenceDigest: string;
189
+ stateDigest: string;
190
+ state: {
191
+ graph: Json;
192
+ evidence: EvidenceStateAtCursorV1;
193
+ };
186
194
  projectionDigest: string;
187
195
  entityCount: number;
188
196
  relationCount: number;
@@ -240,6 +248,120 @@ export interface EvidenceBindingV1 {
240
248
  extensions?: Record<string, Json>;
241
249
  }
242
250
 
251
+ export type EvidenceLifecycleTargetV1 = "item" | "binding";
252
+ export type EvidenceLifecycleActionV1 = "create" | "update" | "remove";
253
+
254
+ export type EvidenceLifecycleOperationV1 =
255
+ | {
256
+ target: "item";
257
+ action: "create";
258
+ evidenceId: string;
259
+ value: EvidenceItemV2;
260
+ }
261
+ | {
262
+ target: "item";
263
+ action: "update";
264
+ evidenceId: string;
265
+ previousDigest: string;
266
+ value: EvidenceItemV2;
267
+ }
268
+ | {
269
+ target: "item";
270
+ action: "remove";
271
+ evidenceId: string;
272
+ previousDigest: string;
273
+ reasonCode: string;
274
+ }
275
+ | {
276
+ target: "binding";
277
+ action: "create";
278
+ bindingId: string;
279
+ value: EvidenceBindingV1;
280
+ }
281
+ | {
282
+ target: "binding";
283
+ action: "update";
284
+ bindingId: string;
285
+ previousDigest: string;
286
+ value: EvidenceBindingV1;
287
+ }
288
+ | {
289
+ target: "binding";
290
+ action: "remove";
291
+ bindingId: string;
292
+ previousDigest: string;
293
+ reasonCode: string;
294
+ };
295
+
296
+ export interface EvidenceLifecycleTombstoneV1 {
297
+ target: EvidenceLifecycleTargetV1;
298
+ id: string;
299
+ previousDigest: string;
300
+ reasonCode: string;
301
+ removedByEventId: string;
302
+ }
303
+
304
+ export interface EvidenceStateAtCursorV1 {
305
+ schemaVersion: "archcontext.evidence-state-at-cursor/v1";
306
+ evidenceItems: EvidenceItemV2[];
307
+ evidenceBindings: EvidenceBindingV1[];
308
+ tombstones: EvidenceLifecycleTombstoneV1[];
309
+ stateDigest: string;
310
+ }
311
+
312
+ export type ArchitectureAffectedSubjectAuthorityClassV1 = "architecture-fact" | "evidence";
313
+ export type ArchitectureAffectedSubjectKindV1 =
314
+ | "entity"
315
+ | "relation"
316
+ | "constraint"
317
+ | "evidence-item"
318
+ | "evidence-binding"
319
+ | "subject";
320
+ export type ArchitectureAffectedSubjectOperationV1 = "create" | "update" | "remove" | "upsert" | "delete" | "reference";
321
+
322
+ export interface ArchitectureAffectedSubjectV1 {
323
+ authorityClass: ArchitectureAffectedSubjectAuthorityClassV1;
324
+ subjectKind: ArchitectureAffectedSubjectKindV1;
325
+ subjectId: string;
326
+ operation: ArchitectureAffectedSubjectOperationV1;
327
+ }
328
+
329
+ export interface ArchitectureChangeFeedRecordV1 {
330
+ schemaVersion: "archcontext.architecture-change-feed-record/v1";
331
+ feedSequence: number;
332
+ repository: ArchitectureRepositoryIdentityV1;
333
+ worktree: ArchitectureWorktreeIdentityV1;
334
+ eventSequence: number;
335
+ eventId: string;
336
+ eventHash: string;
337
+ title?: string;
338
+ rationale?: string;
339
+ affectedSubjects: ArchitectureAffectedSubjectV1[];
340
+ subjectsDigest: string;
341
+ changedInputDigests: {
342
+ graphBefore: string;
343
+ graphAfter: string;
344
+ evidenceBefore: string;
345
+ evidenceAfter: string;
346
+ };
347
+ committedAt: string;
348
+ }
349
+
350
+ export interface ArchitectureChangeFeedBatchV1 {
351
+ schemaVersion: "archcontext.architecture-change-feed-batch/v1";
352
+ consumerId: string;
353
+ checkpoint: number;
354
+ records: ArchitectureChangeFeedRecordV1[];
355
+ hasMore: boolean;
356
+ }
357
+
358
+ export interface ArchitectureEventBacklinkV1 {
359
+ eventId: string;
360
+ subjectIds: string[];
361
+ title?: string;
362
+ rationale?: string;
363
+ }
364
+
243
365
  export interface ArchitectureSubjectSelectorV1 {
244
366
  schemaVersion: typeof ARCHITECTURE_SUBJECT_SELECTOR_SCHEMA_VERSION;
245
367
  selectorId: string;
@@ -618,7 +740,7 @@ export function architectureEventHash(event: ArchitectureEventV1): string {
618
740
  return digestJson(hashable as unknown as Json);
619
741
  }
620
742
 
621
- export function architectureSnapshotDigest(snapshot: ArchitectureSnapshotV1): string {
743
+ export function architectureSnapshotDigest(snapshot: ArchitectureSnapshotV2): string {
622
744
  const { snapshotId: _snapshotId, createdAt: _createdAt, extensions: _extensions, ...hashable } = snapshot;
623
745
  return digestJson(hashable as unknown as Json);
624
746
  }