archctx-contracts 0.2.2 → 0.3.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/fixtures/boundary/explorer-projection-v2-budget.json +87 -0
- package/fixtures/invalid/architecture-snapshot-unknown-mode.json +22 -4
- package/fixtures/invalid/explorer-projection-query-v2-caller-scope.json +7 -0
- package/fixtures/invalid/explorer-projection-v2-derived-subject.json +101 -0
- package/fixtures/valid/architecture-snapshot.json +22 -4
- package/fixtures/valid/explorer-delta-query.json +11 -0
- package/fixtures/valid/explorer-projection-delta.json +32 -0
- package/fixtures/valid/explorer-projection-query-v2.json +6 -0
- package/fixtures/valid/explorer-projection-v2.json +138 -0
- package/fixtures/valid/product-version-manifest.json +7 -7
- package/package.json +1 -1
- package/schemas/runtime/architecture-event.schema.json +172 -2
- package/schemas/runtime/architecture-snapshot.schema.json +37 -4
- package/schemas/runtime/explorer-delta-query.schema.json +24 -0
- package/schemas/runtime/explorer-projection-delta.schema.json +79 -0
- package/schemas/runtime/explorer-projection-query-v2.schema.json +42 -0
- package/schemas/runtime/explorer-projection-v2.schema.json +538 -0
- package/src/ledger.ts +125 -3
- package/src/ports.ts +399 -32
- package/src/product-version.ts +5 -5
- package/src/schema.ts +3 -2
- package/src/validator.ts +52 -5
- package/fixtures/invalid/explorer-projection-write-field.json +0 -21
- package/fixtures/valid/explorer-projection.json +0 -53
- package/schemas/runtime/explorer-projection.schema.json +0 -92
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/
|
|
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
|
|
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:
|
|
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
|
}
|
package/src/ports.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { digestJson, type Json } from "./schema";
|
|
2
2
|
import type {
|
|
3
3
|
AgentJobV1,
|
|
4
4
|
ArchitectureEventSource,
|
|
@@ -266,38 +266,371 @@ export interface ModelInteropImporter {
|
|
|
266
266
|
export type ExplorerVerificationStatus = "MATCHED" | "DRIFT" | "UNKNOWN" | "VERIFIED";
|
|
267
267
|
export type ExplorerPressureLevel = "low" | "medium" | "high";
|
|
268
268
|
|
|
269
|
-
export interface
|
|
269
|
+
export interface ExplorerServiceContract {
|
|
270
|
+
schemaVersion: "archcontext.explorer-service/v1";
|
|
271
|
+
bindHost: "127.0.0.1";
|
|
272
|
+
protocol: "http-loopback";
|
|
273
|
+
optIn: true;
|
|
274
|
+
defaultEnabled: false;
|
|
275
|
+
tokenTtlSeconds: number;
|
|
276
|
+
readOnly: true;
|
|
277
|
+
allowedMethods: ["GET"];
|
|
278
|
+
egress: "none";
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export const EXPLORER_VIEW_IDS = ["system-map", "task-impact", "drift-pressure", "data-flow", "external-integrations"] as const;
|
|
282
|
+
export type ExplorerViewIdV2 = typeof EXPLORER_VIEW_IDS[number];
|
|
283
|
+
export type ExplorerSemanticLevelV2 = "overview" | "context" | "detail";
|
|
284
|
+
export type ExplorerOccurrenceRoleV2 = "subject" | "derived-group";
|
|
285
|
+
export type ExplorerSubjectRefKindV2 =
|
|
286
|
+
| "architecture-entity"
|
|
287
|
+
| "architecture-relation"
|
|
288
|
+
| "architecture-constraint"
|
|
289
|
+
| "code-symbol";
|
|
290
|
+
|
|
291
|
+
export interface ExplorerExpectedCursorV2 {
|
|
292
|
+
headSha: string;
|
|
293
|
+
worktreeDigest: string;
|
|
294
|
+
graphDigest: string;
|
|
295
|
+
observedFactsDigest?: string;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
export interface ExplorerProjectionQueryV2 {
|
|
299
|
+
schemaVersion: "archcontext.explorer-projection-query/v2";
|
|
300
|
+
viewId: ExplorerViewIdV2;
|
|
301
|
+
semanticLevel?: ExplorerSemanticLevelV2;
|
|
302
|
+
taskSessionId?: string;
|
|
303
|
+
expectedCursor?: ExplorerExpectedCursorV2;
|
|
304
|
+
focus?: { subjectId: string };
|
|
305
|
+
expandedOccurrenceIds?: string[];
|
|
306
|
+
depth: 0 | 1 | 2;
|
|
307
|
+
budget: {
|
|
308
|
+
maxNodes: number;
|
|
309
|
+
maxRelations: number;
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
export interface ExplorerProjectionCursorV2 {
|
|
314
|
+
repository: ArchitectureRepositoryIdentityV1;
|
|
315
|
+
worktree: ArchitectureWorktreeIdentityV1;
|
|
316
|
+
authoritySource: "git" | "ledger";
|
|
317
|
+
authorityCursor: AuthorityCursorV1 | null;
|
|
318
|
+
evidenceAuthorityCursor: AuthorityCursorV1 | null;
|
|
319
|
+
inputManifestDigest: string;
|
|
320
|
+
compatibilityDigest: string;
|
|
321
|
+
graphDigest: string;
|
|
322
|
+
evidenceStateDigest: string;
|
|
323
|
+
observedFactsDigest: string;
|
|
324
|
+
viewDefinitionDigest: string;
|
|
325
|
+
compilerVersion: "archcontext.explorer-view-compiler/v1";
|
|
326
|
+
taskSessionDigest?: string;
|
|
327
|
+
observedAvailability: { status: "ready" | "unavailable"; reasonCode?: string };
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
export interface ProjectionInputManifestV1 {
|
|
331
|
+
schemaVersion: "archcontext.projection-input-manifest/v1";
|
|
332
|
+
repository: ArchitectureRepositoryIdentityV1;
|
|
333
|
+
worktree: ArchitectureWorktreeIdentityV1;
|
|
334
|
+
authoritySource: "git" | "ledger";
|
|
335
|
+
authorityCursor: AuthorityCursorV1 | null;
|
|
336
|
+
evidenceAuthorityCursor: AuthorityCursorV1 | null;
|
|
337
|
+
queryDigest: string;
|
|
338
|
+
graphDigest: string;
|
|
339
|
+
evidenceStateDigest: string;
|
|
340
|
+
observedFactsDigest: string;
|
|
341
|
+
observedAvailability: { status: "ready" | "unavailable"; reasonCode?: string };
|
|
342
|
+
bindingsDigest: string;
|
|
343
|
+
eventBacklinksDigest: string;
|
|
344
|
+
driftDigest: string | null;
|
|
345
|
+
pressureDigest: string | null;
|
|
346
|
+
taskSessionDigest: string | null;
|
|
347
|
+
readPlan: ProjectionReadPlanV1;
|
|
348
|
+
readSet: ProjectionReadSetV1;
|
|
349
|
+
inputDomains: Record<ProjectionInputDomainV1, ProjectionInputDomainStateV1>;
|
|
350
|
+
viewDefinitionDigest: string;
|
|
351
|
+
compilerVersion: "archcontext.explorer-view-compiler/v1";
|
|
352
|
+
tokenRequired: boolean;
|
|
353
|
+
compatibilityDigest: string;
|
|
354
|
+
manifestDigest: string;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
export type ProjectionInputDomainV1 =
|
|
358
|
+
| "authority"
|
|
359
|
+
| "graph"
|
|
360
|
+
| "evidence"
|
|
361
|
+
| "observed"
|
|
362
|
+
| "bindings"
|
|
363
|
+
| "event-backlinks"
|
|
364
|
+
| "drift"
|
|
365
|
+
| "pressure"
|
|
366
|
+
| "task-session";
|
|
367
|
+
|
|
368
|
+
export type ProjectionInputDomainStateV1 =
|
|
369
|
+
| { requirement: "required"; status: "ready"; digest: string }
|
|
370
|
+
| { requirement: "optional"; status: "ready"; digest: string }
|
|
371
|
+
| { requirement: "optional"; status: "unavailable"; digest: null; reasonCode: string }
|
|
372
|
+
| { requirement: "not-used"; status: "not-used"; digest: null };
|
|
373
|
+
|
|
374
|
+
export const EXPLORER_VIEW_INPUT_REQUIREMENTS = {
|
|
375
|
+
"system-map": {
|
|
376
|
+
authority: "required", graph: "required", evidence: "required", observed: "required", bindings: "required",
|
|
377
|
+
"event-backlinks": "optional", drift: "optional", pressure: "optional", "task-session": "optional"
|
|
378
|
+
},
|
|
379
|
+
"task-impact": {
|
|
380
|
+
authority: "required", graph: "required", evidence: "required", observed: "required", bindings: "required",
|
|
381
|
+
"event-backlinks": "optional", drift: "optional", pressure: "optional", "task-session": "required"
|
|
382
|
+
},
|
|
383
|
+
"drift-pressure": {
|
|
384
|
+
authority: "required", graph: "required", evidence: "required", observed: "required", bindings: "required",
|
|
385
|
+
"event-backlinks": "optional", drift: "required", pressure: "required", "task-session": "optional"
|
|
386
|
+
},
|
|
387
|
+
"data-flow": {
|
|
388
|
+
authority: "required", graph: "required", evidence: "required", observed: "required", bindings: "required",
|
|
389
|
+
"event-backlinks": "optional", drift: "optional", pressure: "optional", "task-session": "optional"
|
|
390
|
+
},
|
|
391
|
+
"external-integrations": {
|
|
392
|
+
authority: "required", graph: "required", evidence: "required", observed: "required", bindings: "required",
|
|
393
|
+
"event-backlinks": "optional", drift: "optional", pressure: "optional", "task-session": "optional"
|
|
394
|
+
}
|
|
395
|
+
} as const satisfies Record<ExplorerViewIdV2, Record<ProjectionInputDomainV1, ProjectionInputDomainStateV1["requirement"]>>;
|
|
396
|
+
|
|
397
|
+
export const PROJECTION_READ_PLANNER_VERSION = "archcontext.projection-read-planner/v1" as const;
|
|
398
|
+
export const EXPLORER_PROJECTION_CACHE_POLICY_SCHEMA_VERSION = "archcontext.explorer-cache-policy/v1" as const;
|
|
399
|
+
|
|
400
|
+
export interface ExplorerProjectionCachePolicyV1 {
|
|
401
|
+
schemaVersion: typeof EXPLORER_PROJECTION_CACHE_POLICY_SCHEMA_VERSION;
|
|
402
|
+
maxEntriesPerScope: number;
|
|
403
|
+
maxBytesPerScope: number;
|
|
404
|
+
maxAgeMs: number;
|
|
405
|
+
maxPinnedEntriesPerScope: number;
|
|
406
|
+
maxPinTtlMs: number;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
export interface ProjectionReadPlanV1 {
|
|
410
|
+
schemaVersion: "archcontext.projection-read-plan/v1";
|
|
411
|
+
plannerVersion: typeof PROJECTION_READ_PLANNER_VERSION;
|
|
412
|
+
kind: "overview-aggregate" | "bounded-context" | "focused-neighborhood";
|
|
413
|
+
source: "git-authority" | "verified-ledger-current";
|
|
414
|
+
queryDigest: string;
|
|
415
|
+
semanticLevel: ExplorerSemanticLevelV2;
|
|
416
|
+
focusSubjectId: string | null;
|
|
417
|
+
expandedKinds: string[];
|
|
418
|
+
depth: 0 | 1 | 2;
|
|
419
|
+
limits: {
|
|
420
|
+
maxEntities: number;
|
|
421
|
+
maxRelations: number;
|
|
422
|
+
maxConstraints: number;
|
|
423
|
+
maxBindings: number;
|
|
424
|
+
maxBacklinks: number;
|
|
425
|
+
maxGraphRows: number;
|
|
426
|
+
};
|
|
427
|
+
requiredDomains: ProjectionInputDomainV1[];
|
|
428
|
+
ordering: "canonical-id-asc";
|
|
429
|
+
truncation: "hard-limit-with-authoritative-totals";
|
|
430
|
+
planDigest: string;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
export interface ProjectionReadSetV1 {
|
|
434
|
+
schemaVersion: "archcontext.projection-read-set/v1";
|
|
435
|
+
planDigest: string;
|
|
436
|
+
selectedGraphDigest: string;
|
|
437
|
+
authoritativeTotals: { entities: number; relations: number; constraints: number };
|
|
438
|
+
entityKindTotals: Array<{ kind: string; count: number }>;
|
|
439
|
+
rowsRead: { entities: number; relations: number; constraints: number; bindings: number; backlinks: number };
|
|
440
|
+
truncated: boolean;
|
|
441
|
+
readSetDigest: string;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
export function explorerProjectionQueryDigestV2(query: ExplorerProjectionQueryV2): string {
|
|
445
|
+
return digestJson({
|
|
446
|
+
schemaVersion: query.schemaVersion,
|
|
447
|
+
viewId: query.viewId,
|
|
448
|
+
semanticLevel: query.semanticLevel ?? "context",
|
|
449
|
+
taskSessionId: query.taskSessionId ?? null,
|
|
450
|
+
focus: query.focus ?? null,
|
|
451
|
+
expandedOccurrenceIds: [...new Set(query.expandedOccurrenceIds ?? [])].sort(),
|
|
452
|
+
depth: query.depth,
|
|
453
|
+
budget: query.budget
|
|
454
|
+
} as unknown as Json);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
export function canonicalProjectionReadPlanV1(
|
|
458
|
+
query: ExplorerProjectionQueryV2,
|
|
459
|
+
source: ProjectionReadPlanV1["source"]
|
|
460
|
+
): ProjectionReadPlanV1 {
|
|
461
|
+
if (
|
|
462
|
+
query.schemaVersion !== "archcontext.explorer-projection-query/v2"
|
|
463
|
+
|| !(EXPLORER_VIEW_IDS as readonly string[]).includes(query.viewId)
|
|
464
|
+
|| !Number.isInteger(query.depth) || query.depth < 0 || query.depth > 2
|
|
465
|
+
|| !Number.isInteger(query.budget.maxNodes) || query.budget.maxNodes < 1 || query.budget.maxNodes > 1_000
|
|
466
|
+
|| !Number.isInteger(query.budget.maxRelations) || query.budget.maxRelations < 0 || query.budget.maxRelations > 5_000
|
|
467
|
+
) {
|
|
468
|
+
throw new Error("explorer-projection-query-invalid");
|
|
469
|
+
}
|
|
470
|
+
const semanticLevel = query.semanticLevel ?? "context";
|
|
471
|
+
const kind: ProjectionReadPlanV1["kind"] = semanticLevel === "overview"
|
|
472
|
+
? "overview-aggregate"
|
|
473
|
+
: query.focus
|
|
474
|
+
? "focused-neighborhood"
|
|
475
|
+
: "bounded-context";
|
|
476
|
+
const maxEntities = query.budget.maxNodes;
|
|
477
|
+
const maxRelations = query.budget.maxRelations;
|
|
478
|
+
const maxConstraints = Math.max(1, Math.min(2_000, maxEntities * 2));
|
|
479
|
+
const maxBindings = Math.max(1, Math.min(4_000, maxEntities * 4));
|
|
480
|
+
const maxBacklinks = Math.max(1, Math.min(8_000, maxEntities * 8));
|
|
481
|
+
const requirements = EXPLORER_VIEW_INPUT_REQUIREMENTS[query.viewId];
|
|
482
|
+
const withoutDigest = {
|
|
483
|
+
schemaVersion: "archcontext.projection-read-plan/v1" as const,
|
|
484
|
+
plannerVersion: PROJECTION_READ_PLANNER_VERSION,
|
|
485
|
+
kind,
|
|
486
|
+
source,
|
|
487
|
+
queryDigest: explorerProjectionQueryDigestV2(query),
|
|
488
|
+
semanticLevel,
|
|
489
|
+
focusSubjectId: query.focus?.subjectId ?? null,
|
|
490
|
+
expandedKinds: [...new Set((query.expandedOccurrenceIds ?? []).flatMap((id) => {
|
|
491
|
+
const prefix = `occurrence.${query.viewId}.group.kind.`;
|
|
492
|
+
return id.startsWith(prefix) ? [id.slice(prefix.length)] : [];
|
|
493
|
+
}))].sort(),
|
|
494
|
+
depth: query.depth,
|
|
495
|
+
limits: {
|
|
496
|
+
maxEntities,
|
|
497
|
+
maxRelations,
|
|
498
|
+
maxConstraints,
|
|
499
|
+
maxBindings,
|
|
500
|
+
maxBacklinks,
|
|
501
|
+
maxGraphRows: maxEntities + maxRelations + maxConstraints
|
|
502
|
+
},
|
|
503
|
+
requiredDomains: (Object.entries(requirements) as Array<[ProjectionInputDomainV1, ProjectionInputDomainStateV1["requirement"]]>)
|
|
504
|
+
.filter(([, requirement]) => requirement === "required")
|
|
505
|
+
.map(([domain]) => domain)
|
|
506
|
+
.sort(),
|
|
507
|
+
ordering: "canonical-id-asc" as const,
|
|
508
|
+
truncation: "hard-limit-with-authoritative-totals" as const
|
|
509
|
+
};
|
|
510
|
+
return { ...withoutDigest, planDigest: digestJson(withoutDigest as unknown as Json) };
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
export interface ExplorerSubjectRefV2 {
|
|
514
|
+
kind: ExplorerSubjectRefKindV2;
|
|
270
515
|
id: string;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
export interface ExplorerOccurrenceProvenanceV2 {
|
|
519
|
+
declaredEntityIds: string[];
|
|
520
|
+
observedSymbolIds: string[];
|
|
521
|
+
evidenceBindingIds: string[];
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
export type ExplorerAuthorityStateV2 = "BOUND" | "UNBOUND_OBSERVED" | "DECLARED_UNOBSERVED" | "DERIVED";
|
|
525
|
+
|
|
526
|
+
export interface ExplorerPressureEvaluationV2 {
|
|
527
|
+
evaluated: boolean;
|
|
528
|
+
level?: ExplorerPressureLevel;
|
|
529
|
+
score?: number;
|
|
530
|
+
signals: string[];
|
|
531
|
+
inputDigest?: string;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
export interface ExplorerInspectorV2 {
|
|
535
|
+
summary?: string;
|
|
536
|
+
responsibility?: string;
|
|
537
|
+
constraints: Array<{ id: string; kind: string; severity?: string; summary?: string }>;
|
|
538
|
+
decisions: Array<{ eventId: string; title?: string; rationale?: string }>;
|
|
539
|
+
historyEvents: Array<{ eventId: string; title?: string; rationale?: string }>;
|
|
540
|
+
sourceSelectors: SourceSelector[];
|
|
541
|
+
evidenceBindingIds: string[];
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
export interface ExplorerBacklinksV2 {
|
|
545
|
+
appearsInViews: ExplorerViewIdV2[];
|
|
546
|
+
affectedByTaskSessionIds: string[];
|
|
547
|
+
constrainedByIds: string[];
|
|
548
|
+
evidencedByBindingIds: string[];
|
|
549
|
+
changedByEventIds: string[];
|
|
550
|
+
decidedByEventIds: string[];
|
|
551
|
+
incomingRelationIds: string[];
|
|
552
|
+
outgoingRelationIds: string[];
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
export interface ExplorerSubjectOccurrenceV2 {
|
|
556
|
+
occurrenceId: string;
|
|
557
|
+
role: "subject";
|
|
558
|
+
parentOccurrenceId?: string;
|
|
559
|
+
subjectRefs: ExplorerSubjectRefV2[];
|
|
271
560
|
name: string;
|
|
272
561
|
kind: string;
|
|
273
|
-
|
|
562
|
+
childrenCount: number;
|
|
563
|
+
expandable: boolean;
|
|
274
564
|
verificationStatus: ExplorerVerificationStatus;
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
score: number;
|
|
278
|
-
signals: string[];
|
|
279
|
-
};
|
|
565
|
+
authorityState: ExplorerAuthorityStateV2;
|
|
566
|
+
pressure: ExplorerPressureEvaluationV2;
|
|
280
567
|
sourceSelectors: SourceSelector[];
|
|
568
|
+
provenance: ExplorerOccurrenceProvenanceV2;
|
|
569
|
+
inspector: ExplorerInspectorV2;
|
|
570
|
+
backlinks: ExplorerBacklinksV2;
|
|
281
571
|
}
|
|
282
572
|
|
|
283
|
-
export interface
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
573
|
+
export interface ExplorerDerivedGroupOccurrenceV2 {
|
|
574
|
+
occurrenceId: string;
|
|
575
|
+
role: "derived-group";
|
|
576
|
+
parentOccurrenceId?: string;
|
|
577
|
+
subjectRefs: [];
|
|
578
|
+
name: string;
|
|
579
|
+
kind: string;
|
|
580
|
+
childrenCount: number;
|
|
581
|
+
expandable: boolean;
|
|
582
|
+
verificationStatus: "UNKNOWN";
|
|
583
|
+
authorityState: "DERIVED";
|
|
584
|
+
pressure: ExplorerPressureEvaluationV2;
|
|
585
|
+
sourceSelectors: [];
|
|
586
|
+
provenance: ExplorerOccurrenceProvenanceV2;
|
|
587
|
+
derivation: {
|
|
588
|
+
ruleId: string;
|
|
589
|
+
inputDigest: string;
|
|
590
|
+
compilerVersion: "archcontext.explorer-view-compiler/v1";
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
export type ExplorerOccurrenceV2 = ExplorerSubjectOccurrenceV2 | ExplorerDerivedGroupOccurrenceV2;
|
|
595
|
+
|
|
596
|
+
export interface ExplorerRelationOccurrenceV2 {
|
|
597
|
+
occurrenceId: string;
|
|
598
|
+
sourceOccurrenceId: string;
|
|
599
|
+
targetOccurrenceId: string;
|
|
287
600
|
kind: string;
|
|
288
601
|
verificationStatus: ExplorerVerificationStatus;
|
|
602
|
+
provenance: {
|
|
603
|
+
declaredRelationIds: string[];
|
|
604
|
+
observedEdgeIds: string[];
|
|
605
|
+
evidenceBindingIds: string[];
|
|
606
|
+
};
|
|
289
607
|
}
|
|
290
608
|
|
|
291
|
-
export interface
|
|
292
|
-
schemaVersion: "archcontext.explorer-projection/
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
609
|
+
export interface ExplorerProjectionV2 {
|
|
610
|
+
schemaVersion: "archcontext.explorer-projection/v2";
|
|
611
|
+
view: {
|
|
612
|
+
id: ExplorerViewIdV2;
|
|
613
|
+
title: string;
|
|
614
|
+
question: string;
|
|
615
|
+
};
|
|
616
|
+
availableViews: Array<{ id: ExplorerViewIdV2; enabled: boolean; reason?: string }>;
|
|
617
|
+
semanticLevel: ExplorerSemanticLevelV2;
|
|
618
|
+
breadcrumbs: Array<{ occurrenceId: string; label: string }>;
|
|
619
|
+
cursor: ExplorerProjectionCursorV2;
|
|
620
|
+
inputManifest: ProjectionInputManifestV1;
|
|
621
|
+
occurrences: ExplorerOccurrenceV2[];
|
|
622
|
+
relations: ExplorerRelationOccurrenceV2[];
|
|
623
|
+
page: {
|
|
624
|
+
budget: { maxNodes: number; maxRelations: number };
|
|
625
|
+
totalNodes: number;
|
|
626
|
+
totalRelations: number;
|
|
627
|
+
returnedNodes: number;
|
|
628
|
+
returnedRelations: number;
|
|
629
|
+
truncated: boolean;
|
|
630
|
+
omittedNodeCount: number;
|
|
631
|
+
omittedRelationCount: number;
|
|
632
|
+
};
|
|
633
|
+
projectionDigest: string;
|
|
301
634
|
capabilities: {
|
|
302
635
|
readOnly: true;
|
|
303
636
|
mutationMode: "forbidden";
|
|
@@ -306,16 +639,50 @@ export interface ExplorerProjection {
|
|
|
306
639
|
};
|
|
307
640
|
}
|
|
308
641
|
|
|
309
|
-
export interface
|
|
310
|
-
schemaVersion: "archcontext.
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
642
|
+
export interface AuthorityCursorV1 {
|
|
643
|
+
schemaVersion: "archcontext.authority-cursor/v1";
|
|
644
|
+
repository: ArchitectureRepositoryIdentityV1;
|
|
645
|
+
worktree: ArchitectureWorktreeIdentityV1;
|
|
646
|
+
eventSequence: number;
|
|
647
|
+
eventId: string;
|
|
648
|
+
eventHash: string;
|
|
649
|
+
graphDigest: string;
|
|
650
|
+
evidenceStateDigest: string;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
export type ExplorerDeltaClassV2 = "architecture-fact" | "evidence" | "projection";
|
|
654
|
+
|
|
655
|
+
export type ExplorerDeltaFailureReasonV2 =
|
|
656
|
+
| "invalid-delta-query"
|
|
657
|
+
| "projection-cache-miss"
|
|
658
|
+
| "authority-event-missing"
|
|
659
|
+
| "authority-cursor-reversed"
|
|
660
|
+
| "projection-authority-mismatch"
|
|
661
|
+
| "projection-manifest-incompatible";
|
|
662
|
+
|
|
663
|
+
export interface ExplorerDeltaQueryV2 {
|
|
664
|
+
schemaVersion: "archcontext.explorer-delta-query/v2";
|
|
665
|
+
base: { eventId: string; projectionDigest: string };
|
|
666
|
+
head: { eventId: string; projectionDigest: string };
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
export interface ExplorerDeltaChangeV2 {
|
|
670
|
+
deltaClass: ExplorerDeltaClassV2;
|
|
671
|
+
subjectId: string;
|
|
672
|
+
change: "added" | "removed" | "changed";
|
|
673
|
+
fields: string[];
|
|
674
|
+
verificationTransition?: { from: ExplorerVerificationStatus; to: ExplorerVerificationStatus };
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
export interface ExplorerProjectionDeltaV2 {
|
|
678
|
+
schemaVersion: "archcontext.explorer-projection-delta/v2";
|
|
679
|
+
base: AuthorityCursorV1 & { projectionDigest: string; inputManifestDigest: string };
|
|
680
|
+
head: AuthorityCursorV1 & { projectionDigest: string; inputManifestDigest: string };
|
|
681
|
+
factChanges: ExplorerDeltaChangeV2[];
|
|
682
|
+
evidenceChanges: ExplorerDeltaChangeV2[];
|
|
683
|
+
projectionChanges: ExplorerDeltaChangeV2[];
|
|
684
|
+
counts: Record<ExplorerDeltaClassV2, number>;
|
|
685
|
+
deltaDigest: string;
|
|
319
686
|
}
|
|
320
687
|
|
|
321
688
|
export interface RetrievalConfig {
|
package/src/product-version.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export const ARCHCONTEXT_PRODUCT_NAME = "archctx";
|
|
2
|
-
export const ARCHCONTEXT_PRODUCT_VERSION = "0.
|
|
2
|
+
export const ARCHCONTEXT_PRODUCT_VERSION = "0.3.0";
|
|
3
3
|
export const ARCHCONTEXT_PACKAGE_MANAGER = "bun@1.3.10";
|
|
4
4
|
export const ARCHCONTEXT_NODE_RANGE = ">=24 <26";
|
|
5
5
|
export const LOCAL_RUNTIME_RPC_SCHEMA_VERSION = "archcontext.runtime-rpc/v1";
|
|
6
|
-
export const ARCHCONTEXT_SCHEMA_SET_VERSION = "2026-
|
|
6
|
+
export const ARCHCONTEXT_SCHEMA_SET_VERSION = "2026-07-11.explorer-view-v2";
|
|
7
7
|
|
|
8
8
|
export interface ProductVersionManifest {
|
|
9
9
|
schemaVersion: "archcontext.product-version-manifest/v1";
|
|
@@ -41,7 +41,7 @@ export interface ProductVersionManifest {
|
|
|
41
41
|
sqliteMigrations: string;
|
|
42
42
|
codeGraph: {
|
|
43
43
|
packageName: "@colbymchenry/codegraph";
|
|
44
|
-
requiredVersion: "1.0
|
|
44
|
+
requiredVersion: "1.4.0";
|
|
45
45
|
adapter: "codegraph-cli";
|
|
46
46
|
};
|
|
47
47
|
};
|
|
@@ -97,10 +97,10 @@ export function productVersionManifest(): ProductVersionManifest {
|
|
|
97
97
|
schemaVersion: LOCAL_RUNTIME_RPC_SCHEMA_VERSION,
|
|
98
98
|
protocol: "http-loopback"
|
|
99
99
|
},
|
|
100
|
-
sqliteMigrations: "0001_runtime_state..
|
|
100
|
+
sqliteMigrations: "0001_runtime_state..0012_explorer_projection_index",
|
|
101
101
|
codeGraph: {
|
|
102
102
|
packageName: "@colbymchenry/codegraph",
|
|
103
|
-
requiredVersion: "1.0
|
|
103
|
+
requiredVersion: "1.4.0",
|
|
104
104
|
adapter: "codegraph-cli"
|
|
105
105
|
}
|
|
106
106
|
}
|
package/src/schema.ts
CHANGED
|
@@ -36,6 +36,7 @@ export interface ArchContextError {
|
|
|
36
36
|
severity: Severity;
|
|
37
37
|
retryable: boolean;
|
|
38
38
|
action: string;
|
|
39
|
+
reasonCode?: string;
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
export interface JsonEnvelope<T extends Json = Json> {
|
|
@@ -71,12 +72,12 @@ export function okEnvelope<T extends Json>(requestId: string, data: T): JsonEnve
|
|
|
71
72
|
return { schemaVersion: "archcontext.envelope/v1", ok: true, requestId, data };
|
|
72
73
|
}
|
|
73
74
|
|
|
74
|
-
export function errorEnvelope(requestId: string, code: ArchContextErrorCode, message: string): JsonEnvelope {
|
|
75
|
+
export function errorEnvelope(requestId: string, code: ArchContextErrorCode, message: string, reasonCode?: string): JsonEnvelope {
|
|
75
76
|
return {
|
|
76
77
|
schemaVersion: "archcontext.envelope/v1",
|
|
77
78
|
ok: false,
|
|
78
79
|
requestId,
|
|
79
|
-
error: { ...ERROR_CATALOG[code], message }
|
|
80
|
+
error: { ...ERROR_CATALOG[code], message, ...(reasonCode ? { reasonCode } : {}) }
|
|
80
81
|
};
|
|
81
82
|
}
|
|
82
83
|
|