@sentropic/h2a 0.96.1 → 0.97.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/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +98 -29
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +12 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/runtime/drive/cluster-mesh-outer.d.ts +44 -0
- package/dist/runtime/drive/cluster-mesh-outer.d.ts.map +1 -0
- package/dist/runtime/drive/cluster-mesh-outer.js +70 -0
- package/dist/runtime/drive/cluster-mesh-outer.js.map +1 -0
- package/dist/runtime/drive/inbox-wake.d.ts +5 -0
- package/dist/runtime/drive/inbox-wake.d.ts.map +1 -1
- package/dist/runtime/drive/inbox-wake.js +4 -1
- package/dist/runtime/drive/inbox-wake.js.map +1 -1
- package/dist/runtime/drive/index.d.ts +4 -0
- package/dist/runtime/drive/index.d.ts.map +1 -1
- package/dist/runtime/drive/index.js +12 -0
- package/dist/runtime/drive/index.js.map +1 -1
- package/dist/runtime/drive/pty-actuator.d.ts +54 -0
- package/dist/runtime/drive/pty-actuator.d.ts.map +1 -0
- package/dist/runtime/drive/pty-actuator.js +371 -0
- package/dist/runtime/drive/pty-actuator.js.map +1 -0
- package/dist/runtime/local-files/paths.js +1 -1
- package/dist/runtime/local-files/paths.js.map +1 -1
- package/dist/runtime/local-files/presence.d.ts.map +1 -1
- package/dist/runtime/local-files/presence.js +10 -1
- package/dist/runtime/local-files/presence.js.map +1 -1
- package/dist/runtime/loop/engine/adapters.d.ts +7 -1
- package/dist/runtime/loop/engine/adapters.d.ts.map +1 -1
- package/dist/runtime/loop/engine/adapters.js +43 -11
- package/dist/runtime/loop/engine/adapters.js.map +1 -1
- package/dist/runtime/loop/engine/decision.d.ts +5 -1
- package/dist/runtime/loop/engine/decision.d.ts.map +1 -1
- package/dist/runtime/loop/engine/decision.js +9 -3
- package/dist/runtime/loop/engine/decision.js.map +1 -1
- package/dist/runtime/loop/index.d.ts +2 -0
- package/dist/runtime/loop/index.d.ts.map +1 -1
- package/dist/runtime/loop/index.js +11 -3
- package/dist/runtime/loop/index.js.map +1 -1
- package/dist/runtime/mcp/agent-launch.d.ts +2 -1
- package/dist/runtime/mcp/agent-launch.d.ts.map +1 -1
- package/dist/runtime/mcp/agent-launch.js +51 -8
- package/dist/runtime/mcp/agent-launch.js.map +1 -1
- package/dist/runtime/mcp/handlers.d.ts.map +1 -1
- package/dist/runtime/mcp/handlers.js +17 -0
- package/dist/runtime/mcp/handlers.js.map +1 -1
- package/dist/runtime/mcp/stdio.d.ts +2 -0
- package/dist/runtime/mcp/stdio.d.ts.map +1 -1
- package/dist/runtime/mcp/stdio.js +8 -5
- package/dist/runtime/mcp/stdio.js.map +1 -1
- package/dist/runtime/mcp/tools.d.ts.map +1 -1
- package/dist/runtime/mcp/tools.js +19 -6
- package/dist/runtime/mcp/tools.js.map +1 -1
- package/dist/runtime/memory/admit-client.d.ts +30 -0
- package/dist/runtime/memory/admit-client.d.ts.map +1 -0
- package/dist/runtime/memory/admit-client.js +44 -0
- package/dist/runtime/memory/admit-client.js.map +1 -0
- package/dist/runtime/memory/d11-ceremony.d.ts +731 -0
- package/dist/runtime/memory/d11-ceremony.d.ts.map +1 -0
- package/dist/runtime/memory/d11-ceremony.js +1282 -0
- package/dist/runtime/memory/d11-ceremony.js.map +1 -0
- package/dist/runtime/memory/graphify-contracts-v2.vendored.d.ts +922 -0
- package/dist/runtime/memory/graphify-contracts-v2.vendored.d.ts.map +1 -0
- package/dist/runtime/memory/graphify-contracts-v2.vendored.js +2 -0
- package/dist/runtime/memory/graphify-contracts-v2.vendored.js.map +1 -0
- package/dist/runtime/memory/note-builder.d.ts +83 -0
- package/dist/runtime/memory/note-builder.d.ts.map +1 -0
- package/dist/runtime/memory/note-builder.js +89 -0
- package/dist/runtime/memory/note-builder.js.map +1 -0
- package/dist/runtime/memory/port-v1.d.ts +235 -0
- package/dist/runtime/memory/port-v1.d.ts.map +1 -0
- package/dist/runtime/memory/port-v1.js +129 -0
- package/dist/runtime/memory/port-v1.js.map +1 -0
- package/dist/runtime/memory/port-v2-adapter.d.ts +117 -0
- package/dist/runtime/memory/port-v2-adapter.d.ts.map +1 -0
- package/dist/runtime/memory/port-v2-adapter.js +140 -0
- package/dist/runtime/memory/port-v2-adapter.js.map +1 -0
- package/dist/runtime/memory/port-v2-compat.d.ts +50 -0
- package/dist/runtime/memory/port-v2-compat.d.ts.map +1 -0
- package/dist/runtime/memory/port-v2-compat.js +102 -0
- package/dist/runtime/memory/port-v2-compat.js.map +1 -0
- package/dist/runtime/memory/preflight.d.ts +17 -0
- package/dist/runtime/memory/preflight.d.ts.map +1 -0
- package/dist/runtime/memory/preflight.js +18 -0
- package/dist/runtime/memory/preflight.js.map +1 -0
- package/dist/runtime/memory/promote-client.d.ts +172 -0
- package/dist/runtime/memory/promote-client.d.ts.map +1 -0
- package/dist/runtime/memory/promote-client.js +168 -0
- package/dist/runtime/memory/promote-client.js.map +1 -0
- package/dist/runtime/memory/recall-client.d.ts +74 -0
- package/dist/runtime/memory/recall-client.d.ts.map +1 -0
- package/dist/runtime/memory/recall-client.js +91 -0
- package/dist/runtime/memory/recall-client.js.map +1 -0
- package/dist/session.d.ts +4 -0
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +7 -0
- package/dist/session.js.map +1 -1
- package/package.json +7 -4
- package/skills/h2a-run/SKILL.md +39 -6
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* V1→V2 adapter (path V) — pure request BUILDERS + outcome MAPPERS between the
|
|
3
|
+
* h2a memory clients' internal V1 shapes and graphify's `MemoryPortV2`
|
|
4
|
+
* (vendored, types-only, in `./graphify-contracts-v2.vendored.ts`). See
|
|
5
|
+
* docs/specs/2026-09-05-SPEC_v1v2-adapter... for the full mapping + the 6 gaps.
|
|
6
|
+
*
|
|
7
|
+
* SCOPE of THIS module (additive, correctness-critical): the pure functions that
|
|
8
|
+
* turn an h2a input (a `MemoryNoteInput`, a `PromotionEvidence`, a
|
|
9
|
+
* `TombstoneTarget`, a `MemoryRecallQuery`) into the corresponding V2 request,
|
|
10
|
+
* and the V2 responses back into the h2a outcome shapes. It imports ZERO
|
|
11
|
+
* graphify runtime — only the vendored V2 TYPES — so the anti-cycle holds.
|
|
12
|
+
*
|
|
13
|
+
* The 6 GAPS (G1..G6 in the spec) are NOT resolved here: they are INJECTED as a
|
|
14
|
+
* `V2GapResolvers` bundle — exactly like the port itself was injected. Their
|
|
15
|
+
* real implementations (tenancy → opaque scope/purpose refs, a per-call
|
|
16
|
+
* principal credential, the closed component/type vocabularies, the D11-evidence
|
|
17
|
+
* → authorization binding, valid_time) are go-live wiring (graphify/h-arch);
|
|
18
|
+
* here they are one interface a caller supplies, and a test stubs.
|
|
19
|
+
*
|
|
20
|
+
* The client CUTOVER (wiring admit/recall/promote/tombstone-client + the
|
|
21
|
+
* fixtures onto these builders + the V2 port) is deliberately NOT in this file —
|
|
22
|
+
* it is the mechanical, high-volume step deferred to codex (the fixture rewrite
|
|
23
|
+
* touches ~1385 lines). This module is the de-risked, tested foundation that
|
|
24
|
+
* cutover builds on: if the field mapping is wrong, THESE tests go red first.
|
|
25
|
+
*/
|
|
26
|
+
import type { MemoryContext, MemoryNoteInput, MemoryRecallQuery, PromotionEvidence, TombstoneTarget, TombstoneAuthorization, AdmissionOutcome, PromotionOutcome, TombstoneOutcome } from "./port-v1.js";
|
|
27
|
+
import type { AdmissionOutcomeV1, AdmissionRequestV1, AuthorizationContextV1, CaptureAcknowledgementV1, CaptureRequestV2, CitationV1, Cursor, EvidenceBundleV1, IdempotencyKey, Instant, LifecycleCommandV1, LifecycleEventAnchorV1, LifecycleReceiptV1, MemoryComponentV2, OpaqueRef, RecallCapabilityPolicyV1, RecallRequestV2, ReconciliationConsentV1, RetentionV1, ValidIntervalV1 } from "./graphify-contracts-v2.vendored.js";
|
|
28
|
+
/**
|
|
29
|
+
* The injected resolvers for the 6 gaps. Every field the V2 contract requires
|
|
30
|
+
* that the h2a V1 note does NOT already carry in the right shape is produced
|
|
31
|
+
* here — never fabricated inline in a builder. A test supplies canned values;
|
|
32
|
+
* the real wiring (tenancy/identity/policy) lands at go-live.
|
|
33
|
+
*/
|
|
34
|
+
export interface V2GapResolvers {
|
|
35
|
+
/** G1: {principal_owner, scope} → an opaque scope reference (tenancy). */
|
|
36
|
+
scopeRef(input: {
|
|
37
|
+
readonly principal_owner: string;
|
|
38
|
+
readonly scope: string;
|
|
39
|
+
}): OpaqueRef;
|
|
40
|
+
/** G1: purpose → an opaque purpose reference; required for EVERY capture (default for non-human). */
|
|
41
|
+
purposeRef(input: {
|
|
42
|
+
readonly subject: string;
|
|
43
|
+
readonly purpose?: string;
|
|
44
|
+
}): OpaqueRef;
|
|
45
|
+
/** G3: an event-kind label → an opaque type reference. */
|
|
46
|
+
typeRef(kind: string): OpaqueRef;
|
|
47
|
+
/** G3: the note's content → V2 components + which one is primary. */
|
|
48
|
+
components(note: MemoryNoteInput): {
|
|
49
|
+
readonly components: ReadonlyArray<MemoryComponentV2>;
|
|
50
|
+
readonly primary_component_id: string;
|
|
51
|
+
};
|
|
52
|
+
/** G3: the note's provenance → V2 citations (the primary event's citation is one of these). */
|
|
53
|
+
citations(note: MemoryNoteInput): {
|
|
54
|
+
readonly citations: ReadonlyArray<CitationV1>;
|
|
55
|
+
readonly primary_citation_id: string;
|
|
56
|
+
};
|
|
57
|
+
/** G6: the note's temporal anchor → a bi-temporal valid interval. */
|
|
58
|
+
validTime(note: MemoryNoteInput): ValidIntervalV1;
|
|
59
|
+
/** retention/TTL → V2 retention (default "retain" for non-human). */
|
|
60
|
+
retention(note: MemoryNoteInput): RetentionV1;
|
|
61
|
+
/** reconciliation consent (co-spec C1). */
|
|
62
|
+
reconciliation(note: MemoryNoteInput): ReconciliationConsentV1;
|
|
63
|
+
/** the evidence a note carries; the verifier derives the trust class from it (earned-not-asserted). */
|
|
64
|
+
evidenceBundle(note: MemoryNoteInput): EvidenceBundleV1;
|
|
65
|
+
/** G2: ctx → a per-call authorization credential (dynamic principal, never static). */
|
|
66
|
+
authorization(ctx: MemoryContext): AuthorizationContextV1;
|
|
67
|
+
/**
|
|
68
|
+
* G4: the D11 evidence + ctx → the admission authorization. The two verdict
|
|
69
|
+
* refs + attestation ref are recorded h2a-side and carried by
|
|
70
|
+
* `AuthorizationContextV1.context_ref` (an opaque ref to the ceremony
|
|
71
|
+
* receipt) — graphify applies on a valid authorization; h2a holds the
|
|
72
|
+
* auditable D11 artifact. See spec G4/G5 (single admission authority).
|
|
73
|
+
*/
|
|
74
|
+
admissionAuthorization(input: {
|
|
75
|
+
readonly ctx: MemoryContext;
|
|
76
|
+
readonly evidence: PromotionEvidence;
|
|
77
|
+
}): AuthorizationContextV1;
|
|
78
|
+
/** a fresh idempotency key for a capture. */
|
|
79
|
+
idempotencyKey(): IdempotencyKey;
|
|
80
|
+
/** a deadline for a request. */
|
|
81
|
+
deadlineAt(): Instant;
|
|
82
|
+
/** capture source-order: which source, what sequence. */
|
|
83
|
+
sourceOrder(note: MemoryNoteInput): {
|
|
84
|
+
readonly source_ref: OpaqueRef;
|
|
85
|
+
readonly sequence: Cursor;
|
|
86
|
+
};
|
|
87
|
+
/** a cancellation ref for a capture. */
|
|
88
|
+
cancellationRef(): OpaqueRef;
|
|
89
|
+
/** RecallRequestV2 budgets + capability policy (new surface, no V1 analogue). */
|
|
90
|
+
recallBudgets(): RecallRequestV2["budgets"];
|
|
91
|
+
recallCapabilityPolicy(): RecallCapabilityPolicyV1;
|
|
92
|
+
recallPurposeRef(query: MemoryRecallQuery, ctx: MemoryContext): OpaqueRef;
|
|
93
|
+
/** a lifecycle command's fresh event id. */
|
|
94
|
+
lifecycleEventId(): IdempotencyKey;
|
|
95
|
+
/** a lifecycle command's reason ref. */
|
|
96
|
+
reasonRef(input: {
|
|
97
|
+
readonly ctx: MemoryContext;
|
|
98
|
+
readonly auth: TombstoneAuthorization;
|
|
99
|
+
}): OpaqueRef;
|
|
100
|
+
/** a lifecycle command's event anchor. */
|
|
101
|
+
lifecycleEventAnchor(): LifecycleEventAnchorV1;
|
|
102
|
+
}
|
|
103
|
+
/** `admitMemoryNote(note)` → `capture(CaptureRequestV2)`. `committed_pending` = the V1 `pending`. */
|
|
104
|
+
export declare function buildCaptureRequest(note: MemoryNoteInput, ctx: MemoryContext, r: V2GapResolvers): CaptureRequestV2;
|
|
105
|
+
/** `promoteNote(noteId, evidence)` → `requestAdmission(AdmissionRequestV1)` — the D11 verdict APPLIES here. */
|
|
106
|
+
export declare function buildAdmissionRequest(noteId: string, evidence: PromotionEvidence, ctx: MemoryContext, r: V2GapResolvers): AdmissionRequestV1;
|
|
107
|
+
/** `requestTombstone(target)` → `transition({operation:"tombstone", record_id})`. Node targets only; an edge target refuses fail-closed (NB-01). */
|
|
108
|
+
export declare function buildTombstoneCommand(target: TombstoneTarget, auth: TombstoneAuthorization, ctx: MemoryContext, r: V2GapResolvers): LifecycleCommandV1;
|
|
109
|
+
/** `recallMemory(query)` → `recall(RecallRequestV2)`. `asOf`/`window` → `as_of`; budgets/policy are new. */
|
|
110
|
+
export declare function buildRecallRequest(query: MemoryRecallQuery, ctx: MemoryContext, r: V2GapResolvers): RecallRequestV2;
|
|
111
|
+
/** `CaptureAcknowledgementV1` → `AdmissionOutcome`. `committed_pending`/`duplicate_exact` = admitted; else refused. */
|
|
112
|
+
export declare function mapCaptureAcknowledgement(ack: CaptureAcknowledgementV1): AdmissionOutcome;
|
|
113
|
+
/** `AdmissionOutcomeV1` → `PromotionOutcome`. `accepted` (with a record_id) = promoted; else refused. */
|
|
114
|
+
export declare function mapAdmissionOutcome(outcome: AdmissionOutcomeV1): PromotionOutcome;
|
|
115
|
+
/** `LifecycleReceiptV1` → `TombstoneOutcome`. Applied iff the transition reached the `tombstoned` state. */
|
|
116
|
+
export declare function mapLifecycleReceipt(receipt: LifecycleReceiptV1): TombstoneOutcome;
|
|
117
|
+
//# sourceMappingURL=port-v2-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"port-v2-adapter.d.ts","sourceRoot":"","sources":["../../../src/runtime/memory/port-v2-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* V1→V2 adapter (path V) — pure request BUILDERS + outcome MAPPERS between the
|
|
3
|
+
* h2a memory clients' internal V1 shapes and graphify's `MemoryPortV2`
|
|
4
|
+
* (vendored, types-only, in `./graphify-contracts-v2.vendored.ts`). See
|
|
5
|
+
* docs/specs/2026-09-05-SPEC_v1v2-adapter... for the full mapping + the 6 gaps.
|
|
6
|
+
*
|
|
7
|
+
* SCOPE of THIS module (additive, correctness-critical): the pure functions that
|
|
8
|
+
* turn an h2a input (a `MemoryNoteInput`, a `PromotionEvidence`, a
|
|
9
|
+
* `TombstoneTarget`, a `MemoryRecallQuery`) into the corresponding V2 request,
|
|
10
|
+
* and the V2 responses back into the h2a outcome shapes. It imports ZERO
|
|
11
|
+
* graphify runtime — only the vendored V2 TYPES — so the anti-cycle holds.
|
|
12
|
+
*
|
|
13
|
+
* The 6 GAPS (G1..G6 in the spec) are NOT resolved here: they are INJECTED as a
|
|
14
|
+
* `V2GapResolvers` bundle — exactly like the port itself was injected. Their
|
|
15
|
+
* real implementations (tenancy → opaque scope/purpose refs, a per-call
|
|
16
|
+
* principal credential, the closed component/type vocabularies, the D11-evidence
|
|
17
|
+
* → authorization binding, valid_time) are go-live wiring (graphify/h-arch);
|
|
18
|
+
* here they are one interface a caller supplies, and a test stubs.
|
|
19
|
+
*
|
|
20
|
+
* The client CUTOVER (wiring admit/recall/promote/tombstone-client + the
|
|
21
|
+
* fixtures onto these builders + the V2 port) is deliberately NOT in this file —
|
|
22
|
+
* it is the mechanical, high-volume step deferred to codex (the fixture rewrite
|
|
23
|
+
* touches ~1385 lines). This module is the de-risked, tested foundation that
|
|
24
|
+
* cutover builds on: if the field mapping is wrong, THESE tests go red first.
|
|
25
|
+
*/
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// WRITE-side builders: h2a input → V2 request. Pure; every gap comes from `r`.
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
/** `admitMemoryNote(note)` → `capture(CaptureRequestV2)`. `committed_pending` = the V1 `pending`. */
|
|
30
|
+
export function buildCaptureRequest(note, ctx, r) {
|
|
31
|
+
const { components, primary_component_id } = r.components(note);
|
|
32
|
+
const { citations, primary_citation_id } = r.citations(note);
|
|
33
|
+
const payload = {
|
|
34
|
+
schema_version: 2,
|
|
35
|
+
scope_ref: r.scopeRef({ principal_owner: note.principal_owner, scope: note.scope }),
|
|
36
|
+
purpose_ref: r.purposeRef({ subject: note.subject, purpose: note.purpose }),
|
|
37
|
+
valid_time: r.validTime(note),
|
|
38
|
+
components,
|
|
39
|
+
primary_component_id,
|
|
40
|
+
primary_event: { at: note.event.at, type_ref: r.typeRef(note.event.kind), citation_id: primary_citation_id },
|
|
41
|
+
citations,
|
|
42
|
+
retention: r.retention(note),
|
|
43
|
+
reconciliation: r.reconciliation(note)
|
|
44
|
+
};
|
|
45
|
+
return {
|
|
46
|
+
schema_version: 2,
|
|
47
|
+
idempotency_key: r.idempotencyKey(),
|
|
48
|
+
payload,
|
|
49
|
+
evidence: r.evidenceBundle(note),
|
|
50
|
+
authorization: r.authorization(ctx),
|
|
51
|
+
source_order: r.sourceOrder(note),
|
|
52
|
+
deadline_at: r.deadlineAt(),
|
|
53
|
+
cancellation_ref: r.cancellationRef()
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/** `promoteNote(noteId, evidence)` → `requestAdmission(AdmissionRequestV1)` — the D11 verdict APPLIES here. */
|
|
57
|
+
export function buildAdmissionRequest(noteId, evidence, ctx, r) {
|
|
58
|
+
return {
|
|
59
|
+
candidate_id: noteId,
|
|
60
|
+
authorization: r.admissionAuthorization({ ctx, evidence }),
|
|
61
|
+
deadline_at: r.deadlineAt()
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/** `requestTombstone(target)` → `transition({operation:"tombstone", record_id})`. Node targets only; an edge target refuses fail-closed (NB-01). */
|
|
65
|
+
export function buildTombstoneCommand(target, auth, ctx, r) {
|
|
66
|
+
// NB-01: only a node target carries a single record_id, which is what the V2
|
|
67
|
+
// lifecycle surface transitions. An edge target's own record/projection id must
|
|
68
|
+
// be resolved from the edge triple (the edge-tombstone sub-gap, a go-live
|
|
69
|
+
// concern). Mapping an edge to `target.source` — as an earlier revision did —
|
|
70
|
+
// would transition the WHOLE source node (and every other edge on it), not the
|
|
71
|
+
// single edge A→B: a destructive mis-target. Refuse fail-closed here rather than
|
|
72
|
+
// invent a record_id; the compat port turns this throw into an {applied:false}
|
|
73
|
+
// outcome, so no edge tombstone can silently destroy a shared node.
|
|
74
|
+
if (target.kind !== "node") {
|
|
75
|
+
throw new Error("edge tombstone is not supported by the V1→V2 adapter yet — needs edge→record_id resolution (NB-01); refusing rather than tombstoning the source node");
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
event_id: r.lifecycleEventId(),
|
|
79
|
+
reason_ref: r.reasonRef({ ctx, auth }),
|
|
80
|
+
event_anchor: r.lifecycleEventAnchor(),
|
|
81
|
+
authorization: r.authorization(ctx),
|
|
82
|
+
deadline_at: r.deadlineAt(),
|
|
83
|
+
operation: "tombstone",
|
|
84
|
+
record_id: target.id
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/** `recallMemory(query)` → `recall(RecallRequestV2)`. `asOf`/`window` → `as_of`; budgets/policy are new. */
|
|
88
|
+
export function buildRecallRequest(query, ctx, r) {
|
|
89
|
+
const as_of = typeof query.asOf === "number"
|
|
90
|
+
? { valid_time: query.asOf }
|
|
91
|
+
: query.window && query.window.untilMs !== null
|
|
92
|
+
? { valid_time: query.window.untilMs }
|
|
93
|
+
: undefined;
|
|
94
|
+
return {
|
|
95
|
+
// The V1 query carried no free-text; the wake-recall query string is the
|
|
96
|
+
// caller's — the cutover threads it. Empty string is a valid "recall all
|
|
97
|
+
// live for this principal/purpose" under the budgets below.
|
|
98
|
+
query: "",
|
|
99
|
+
purpose_ref: r.recallPurposeRef(query, ctx),
|
|
100
|
+
...(as_of ? { as_of } : {}),
|
|
101
|
+
authorization: r.authorization(ctx),
|
|
102
|
+
capability_policy: r.recallCapabilityPolicy(),
|
|
103
|
+
budgets: r.recallBudgets()
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
// ---------------------------------------------------------------------------
|
|
107
|
+
// READ-side / outcome MAPPERS: V2 response → h2a outcome. Fail-closed on refusal.
|
|
108
|
+
// ---------------------------------------------------------------------------
|
|
109
|
+
/** `CaptureAcknowledgementV1` → `AdmissionOutcome`. `committed_pending`/`duplicate_exact` = admitted; else refused. */
|
|
110
|
+
export function mapCaptureAcknowledgement(ack) {
|
|
111
|
+
// A fresh commit must return its candidate_id.
|
|
112
|
+
if (ack.status === "committed_pending" && typeof ack.candidate_id === "string") {
|
|
113
|
+
return { admitted: true, id: ack.candidate_id };
|
|
114
|
+
}
|
|
115
|
+
// NB-02: `duplicate_exact` is an idempotent success — the store already holds
|
|
116
|
+
// this exact payload. `candidate_id` is OPTIONAL on CaptureAcknowledgementV1, so
|
|
117
|
+
// fall back to the `record_digest` as the stable id when it is omitted: refusing
|
|
118
|
+
// a recognized duplicate merely because candidate_id is absent would break dedup
|
|
119
|
+
// idempotency on a retried admission. Still fail closed if the store returned
|
|
120
|
+
// neither identifier.
|
|
121
|
+
if (ack.status === "duplicate_exact") {
|
|
122
|
+
const id = ack.candidate_id ?? ack.record_digest;
|
|
123
|
+
if (typeof id === "string")
|
|
124
|
+
return { admitted: true, id };
|
|
125
|
+
}
|
|
126
|
+
return { admitted: false, reason: `capture not committed — status "${ack.status}"` };
|
|
127
|
+
}
|
|
128
|
+
/** `AdmissionOutcomeV1` → `PromotionOutcome`. `accepted` (with a record_id) = promoted; else refused. */
|
|
129
|
+
export function mapAdmissionOutcome(outcome) {
|
|
130
|
+
if (outcome.status === "accepted" && typeof outcome.record_id === "string") {
|
|
131
|
+
return { promoted: true, id: outcome.record_id };
|
|
132
|
+
}
|
|
133
|
+
return { promoted: false, reason: `admission not accepted — status "${outcome.status}"` };
|
|
134
|
+
}
|
|
135
|
+
/** `LifecycleReceiptV1` → `TombstoneOutcome`. Applied iff the transition reached the `tombstoned` state. */
|
|
136
|
+
export function mapLifecycleReceipt(receipt) {
|
|
137
|
+
const applied = receipt.to_state === "tombstoned";
|
|
138
|
+
return applied ? { applied: true } : { applied: false, reason: `transition landed in "${receipt.to_state}", not tombstoned` };
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=port-v2-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"port-v2-adapter.js","sourceRoot":"","sources":["../../../src/runtime/memory/port-v2-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* V1→V2 anti-corruption port (path V, the cutover). `createV1CompatPort` wraps a
|
|
3
|
+
* real `MemoryPortV2` (+ the injected `V2GapResolvers`) and EXPOSES the V1
|
|
4
|
+
* `MemoryProducerPort & MemoryRecallPort` the h2a clients already consume — so
|
|
5
|
+
* admit-client / promote-client / tombstone-client / recall-client + all their
|
|
6
|
+
* fixtures (including the 1656-line D11 ceremony suite) stay UNCHANGED, and their
|
|
7
|
+
* anti-fabrication coverage is preserved by construction (nothing rewritten).
|
|
8
|
+
*
|
|
9
|
+
* This is the ACL between h2a's stable V1-facing internal API and graphify's V2
|
|
10
|
+
* contract: the clients speak V1; this port maps each call to V2 via the proven
|
|
11
|
+
* builders (`./port-v2-adapter.ts`) and maps the V2 responses back. At go-live,
|
|
12
|
+
* h2a constructs `createV1CompatPort(realGraphifyV2Port, realResolvers, realReverse)`
|
|
13
|
+
* and hands it to the clients — that IS the V2 wiring. Imports ZERO graphify
|
|
14
|
+
* runtime (only vendored types) — anti-cycle holds.
|
|
15
|
+
*
|
|
16
|
+
* The 6 gaps stay injected (`V2GapResolvers`); the recall RESPONSE reverse-mapping
|
|
17
|
+
* needs the fields V2 does not carry back flat (subject, scope, principal_owner,
|
|
18
|
+
* review_status), supplied by an injected `V2RecallReverseResolvers` — the same
|
|
19
|
+
* go-live wiring point.
|
|
20
|
+
*/
|
|
21
|
+
import type { MemoryProducerPort, MemoryRecallPort, MemoryRecallResultView, MemoryScope, RecalledMemoryNoteView } from "./port-v1.js";
|
|
22
|
+
import type { MemoryPortV2, MemoryRecordV2, RecallPacketV2 } from "./graphify-contracts-v2.vendored.js";
|
|
23
|
+
import { type V2GapResolvers } from "./port-v2-adapter.js";
|
|
24
|
+
/**
|
|
25
|
+
* Recover the V1 view fields a `MemoryRecordV2` does not carry back in the flat
|
|
26
|
+
* V1 shape (V2 dropped a top-level `subject`, and encodes tenancy as opaque
|
|
27
|
+
* refs). Injected — the real resolution (scope_ref → {principal_owner, scope},
|
|
28
|
+
* the record's state → review_status) is graphify/go-live wiring.
|
|
29
|
+
*/
|
|
30
|
+
export interface V2RecallReverseResolvers {
|
|
31
|
+
subject(record: MemoryRecordV2): string;
|
|
32
|
+
scope(record: MemoryRecordV2): MemoryScope;
|
|
33
|
+
principalOwner(record: MemoryRecordV2): string;
|
|
34
|
+
reviewStatus(record: MemoryRecordV2): string;
|
|
35
|
+
/** An event-kind label recovered from the primary event's opaque `type_ref`. */
|
|
36
|
+
eventKind(record: MemoryRecordV2): string;
|
|
37
|
+
}
|
|
38
|
+
/** Map one V2 record to the V1 projected view. Pure; the recovered fields come from `rev`. */
|
|
39
|
+
export declare function mapRecordToView(record: MemoryRecordV2, rev: V2RecallReverseResolvers): RecalledMemoryNoteView;
|
|
40
|
+
/** Map a `RecallPacketV2` to the V1 recall result view (notes-only). */
|
|
41
|
+
export declare function mapRecallPacket(packet: RecallPacketV2, rev: V2RecallReverseResolvers, requestingPrincipal: string): MemoryRecallResultView;
|
|
42
|
+
/**
|
|
43
|
+
* Build a V1 `MemoryProducerPort & MemoryRecallPort` backed by a V2 port. Each V1
|
|
44
|
+
* call maps to V2 via the proven builders; a V2 `Result` error becomes the V1
|
|
45
|
+
* fail-closed refusal shape the clients already handle (a producer error → an
|
|
46
|
+
* `{admitted/promoted/applied:false, reason}`; a recall error THROWS, which
|
|
47
|
+
* `recall-client` catches into its own refusal, matching the V1 recall contract).
|
|
48
|
+
*/
|
|
49
|
+
export declare function createV1CompatPort(v2: MemoryPortV2, resolvers: V2GapResolvers, recallReverse: V2RecallReverseResolvers): MemoryProducerPort & MemoryRecallPort;
|
|
50
|
+
//# sourceMappingURL=port-v2-compat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"port-v2-compat.d.ts","sourceRoot":"","sources":["../../../src/runtime/memory/port-v2-compat.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAKV,kBAAkB,EAClB,gBAAgB,EAEhB,sBAAsB,EACtB,WAAW,EAGX,sBAAsB,EAKvB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAsB,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AAC5H,OAAO,EAQL,KAAK,cAAc,EACpB,MAAM,sBAAsB,CAAC;AAE9B;;;;;GAKG;AACH,MAAM,WAAW,wBAAwB;IACvC,OAAO,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAAC;IACxC,KAAK,CAAC,MAAM,EAAE,cAAc,GAAG,WAAW,CAAC;IAC3C,cAAc,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAAC;IAC/C,YAAY,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAAC;IAC7C,gFAAgF;IAChF,SAAS,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAAC;CAC3C;AAED,8FAA8F;AAC9F,wBAAgB,eAAe,CAAC,MAAM,EAAE,cAAc,EAAE,GAAG,EAAE,wBAAwB,GAAG,sBAAsB,CAsB7G;AAED,wEAAwE;AACxE,wBAAgB,eAAe,CAC7B,MAAM,EAAE,cAAc,EACtB,GAAG,EAAE,wBAAwB,EAC7B,mBAAmB,EAAE,MAAM,GAC1B,sBAAsB,CASxB;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,EAAE,EAAE,YAAY,EAChB,SAAS,EAAE,cAAc,EACzB,aAAa,EAAE,wBAAwB,GACtC,kBAAkB,GAAG,gBAAgB,CAmCvC"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* V1→V2 anti-corruption port (path V, the cutover). `createV1CompatPort` wraps a
|
|
3
|
+
* real `MemoryPortV2` (+ the injected `V2GapResolvers`) and EXPOSES the V1
|
|
4
|
+
* `MemoryProducerPort & MemoryRecallPort` the h2a clients already consume — so
|
|
5
|
+
* admit-client / promote-client / tombstone-client / recall-client + all their
|
|
6
|
+
* fixtures (including the 1656-line D11 ceremony suite) stay UNCHANGED, and their
|
|
7
|
+
* anti-fabrication coverage is preserved by construction (nothing rewritten).
|
|
8
|
+
*
|
|
9
|
+
* This is the ACL between h2a's stable V1-facing internal API and graphify's V2
|
|
10
|
+
* contract: the clients speak V1; this port maps each call to V2 via the proven
|
|
11
|
+
* builders (`./port-v2-adapter.ts`) and maps the V2 responses back. At go-live,
|
|
12
|
+
* h2a constructs `createV1CompatPort(realGraphifyV2Port, realResolvers, realReverse)`
|
|
13
|
+
* and hands it to the clients — that IS the V2 wiring. Imports ZERO graphify
|
|
14
|
+
* runtime (only vendored types) — anti-cycle holds.
|
|
15
|
+
*
|
|
16
|
+
* The 6 gaps stay injected (`V2GapResolvers`); the recall RESPONSE reverse-mapping
|
|
17
|
+
* needs the fields V2 does not carry back flat (subject, scope, principal_owner,
|
|
18
|
+
* review_status), supplied by an injected `V2RecallReverseResolvers` — the same
|
|
19
|
+
* go-live wiring point.
|
|
20
|
+
*/
|
|
21
|
+
import { buildAdmissionRequest, buildCaptureRequest, buildRecallRequest, buildTombstoneCommand, mapAdmissionOutcome, mapCaptureAcknowledgement, mapLifecycleReceipt } from "./port-v2-adapter.js";
|
|
22
|
+
/** Map one V2 record to the V1 projected view. Pure; the recovered fields come from `rev`. */
|
|
23
|
+
export function mapRecordToView(record, rev) {
|
|
24
|
+
const primary = record.components.find((c) => c.component_id === record.primary_component_id) ?? record.components[0];
|
|
25
|
+
const primaryCitation = record.citations.find((c) => c.citation_id === record.primary_event.citation_id);
|
|
26
|
+
const view = {
|
|
27
|
+
id: record.record_id,
|
|
28
|
+
node_type: "MemoryNote",
|
|
29
|
+
memory_kind: (primary?.kind ?? "context"),
|
|
30
|
+
subject: rev.subject(record),
|
|
31
|
+
t: record.valid_time.t,
|
|
32
|
+
trust: record.trust.class,
|
|
33
|
+
review_status: rev.reviewStatus(record),
|
|
34
|
+
scope: rev.scope(record),
|
|
35
|
+
principal_owner: rev.principalOwner(record),
|
|
36
|
+
provenance: { cited: primary?.text ?? "", source: primaryCitation?.locator.value ?? "" },
|
|
37
|
+
event: {
|
|
38
|
+
at: record.primary_event.at,
|
|
39
|
+
kind: rev.eventKind(record),
|
|
40
|
+
ref: primaryCitation?.locator.value ?? ""
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
if (record.valid_time.t_end !== undefined)
|
|
44
|
+
view.t_end = record.valid_time.t_end;
|
|
45
|
+
return view;
|
|
46
|
+
}
|
|
47
|
+
/** Map a `RecallPacketV2` to the V1 recall result view (notes-only). */
|
|
48
|
+
export function mapRecallPacket(packet, rev, requestingPrincipal) {
|
|
49
|
+
return {
|
|
50
|
+
schema: "memory-recall/v2-compat",
|
|
51
|
+
notes: packet.records.map((r) => mapRecordToView(r.record, rev)),
|
|
52
|
+
projection: "notes-only",
|
|
53
|
+
requestingPrincipal,
|
|
54
|
+
freshness: "unverified",
|
|
55
|
+
unpaged: true
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Build a V1 `MemoryProducerPort & MemoryRecallPort` backed by a V2 port. Each V1
|
|
60
|
+
* call maps to V2 via the proven builders; a V2 `Result` error becomes the V1
|
|
61
|
+
* fail-closed refusal shape the clients already handle (a producer error → an
|
|
62
|
+
* `{admitted/promoted/applied:false, reason}`; a recall error THROWS, which
|
|
63
|
+
* `recall-client` catches into its own refusal, matching the V1 recall contract).
|
|
64
|
+
*/
|
|
65
|
+
export function createV1CompatPort(v2, resolvers, recallReverse) {
|
|
66
|
+
return {
|
|
67
|
+
async admitMemoryNote(note, ctx) {
|
|
68
|
+
const res = await v2.capture(buildCaptureRequest(note, ctx, resolvers));
|
|
69
|
+
if (!res.ok)
|
|
70
|
+
return { admitted: false, reason: `${res.error.code}: ${res.error.message}` };
|
|
71
|
+
return mapCaptureAcknowledgement(res.value);
|
|
72
|
+
},
|
|
73
|
+
async promoteNote(noteId, evidence, ctx) {
|
|
74
|
+
const res = await v2.requestAdmission(buildAdmissionRequest(noteId, evidence, ctx, resolvers));
|
|
75
|
+
if (!res.ok)
|
|
76
|
+
return { promoted: false, reason: `${res.error.code}: ${res.error.message}` };
|
|
77
|
+
return mapAdmissionOutcome(res.value);
|
|
78
|
+
},
|
|
79
|
+
async requestTombstone(target, auth, ctx) {
|
|
80
|
+
let command;
|
|
81
|
+
try {
|
|
82
|
+
command = buildTombstoneCommand(target, auth, ctx, resolvers);
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
// NB-01: an unbuildable command (e.g. an edge target with no resolvable
|
|
86
|
+
// record_id) fails closed rather than mis-targeting a node.
|
|
87
|
+
return { applied: false, reason: err instanceof Error ? err.message : String(err) };
|
|
88
|
+
}
|
|
89
|
+
const res = await v2.transition(command);
|
|
90
|
+
if (!res.ok)
|
|
91
|
+
return { applied: false, reason: `${res.error.code}: ${res.error.message}` };
|
|
92
|
+
return mapLifecycleReceipt(res.value);
|
|
93
|
+
},
|
|
94
|
+
async recallMemory(query, ctx) {
|
|
95
|
+
const res = await v2.recall(buildRecallRequest(query, ctx, resolvers));
|
|
96
|
+
if (!res.ok)
|
|
97
|
+
throw new Error(`recall refused by V2 port — ${res.error.code}: ${res.error.message}`);
|
|
98
|
+
return mapRecallPacket(res.value, recallReverse, ctx.principal_owner);
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=port-v2-compat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"port-v2-compat.js","sourceRoot":"","sources":["../../../src/runtime/memory/port-v2-compat.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local pre-flight — WP11 slice 3 (build brief). Runs the VENDORED
|
|
3
|
+
* `validateMemoryNoteShape` (see `./port-v1.ts`) BEFORE a note is dispatched, so
|
|
4
|
+
* a malformed note never reaches the wire. This module does not reimplement the
|
|
5
|
+
* check: it calls the shared predicate the port publishes, so h2a's local reject
|
|
6
|
+
* stays byte-for-byte the same rule the graphify gate re-checks on admission
|
|
7
|
+
* (minus `verifyVerbatim`, the citation check, which needs source resolution and
|
|
8
|
+
* therefore stays gate-side — see the port's own doc comment).
|
|
9
|
+
*/
|
|
10
|
+
import { type MemoryNoteInput, type ShapeCheck } from "./port-v1.js";
|
|
11
|
+
export type PreflightResult = ShapeCheck;
|
|
12
|
+
/**
|
|
13
|
+
* Cheap, local, structural rejection of a malformed note. NOT the admission
|
|
14
|
+
* decision — the gate remains authoritative and re-checks on receipt.
|
|
15
|
+
*/
|
|
16
|
+
export declare function preflightMemoryNote(note: MemoryNoteInput): PreflightResult;
|
|
17
|
+
//# sourceMappingURL=preflight.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preflight.d.ts","sourceRoot":"","sources":["../../../src/runtime/memory/preflight.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAA2B,KAAK,eAAe,EAAE,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAE9F,MAAM,MAAM,eAAe,GAAG,UAAU,CAAC;AAEzC;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,eAAe,GAAG,eAAe,CAE1E"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local pre-flight — WP11 slice 3 (build brief). Runs the VENDORED
|
|
3
|
+
* `validateMemoryNoteShape` (see `./port-v1.ts`) BEFORE a note is dispatched, so
|
|
4
|
+
* a malformed note never reaches the wire. This module does not reimplement the
|
|
5
|
+
* check: it calls the shared predicate the port publishes, so h2a's local reject
|
|
6
|
+
* stays byte-for-byte the same rule the graphify gate re-checks on admission
|
|
7
|
+
* (minus `verifyVerbatim`, the citation check, which needs source resolution and
|
|
8
|
+
* therefore stays gate-side — see the port's own doc comment).
|
|
9
|
+
*/
|
|
10
|
+
import { validateMemoryNoteShape } from "./port-v1.js";
|
|
11
|
+
/**
|
|
12
|
+
* Cheap, local, structural rejection of a malformed note. NOT the admission
|
|
13
|
+
* decision — the gate remains authoritative and re-checks on receipt.
|
|
14
|
+
*/
|
|
15
|
+
export function preflightMemoryNote(note) {
|
|
16
|
+
return validateMemoryNoteShape(note);
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=preflight.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preflight.js","sourceRoot":"","sources":["../../../src/runtime/memory/preflight.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,uBAAuB,EAAyC,MAAM,cAAc,CAAC;AAI9F;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAqB;IACvD,OAAO,uBAAuB,CAAC,IAAI,CAAC,CAAC;AACvC,CAAC"}
|