jenkins b66c762f5d hermes(webui): add HUX card UI models with contract-locked suites
Standalone per-card browser model/security/view modules for HUX-01..10
plus node+pytest suites that read the hux.v1 contract schemas directly.
Reconciled drift found on integration: the activity model now accepts
all 32 hux.event.v1 kinds (delegation.*, memory.suppressed,
memory.retrieval_removed, budget.exhausted, side_effect.*), the
autonomy model carries the external_side_effect capability, and the
foundation boundary test now asserts the shipped static HUX surface
exists on disk and that images never bake activated HUX_FLAGS.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BvMSXH8VH2tMWXanb8SJdf
2026-08-24 04:12:03 -03:00

80 lines
2.4 KiB
TypeScript

/**
* Same-origin endpoint descriptions for a future HUX-02 backend adapter.
* The server must derive identity from the authenticated session, compare it
* with each request's expectedIdentity, and echo it in list responses. A
* revision appends a proposed ledger entry; forget purges content while
* retaining audit metadata. These descriptors never perform a request.
*/
import { memoryControlEnabled } from "./model.ts";
import { isOpaqueMemoryId, normalizeIdentity } from "./security.ts";
import type {
HuxIdentity,
MemoryAction,
MemoryEndpoint,
MemoryEndpointContract,
} from "./types.ts";
interface FoundationClient {
apiVersion: string;
identity: HuxIdentity;
endpoint(path: string): string;
}
function endpoint(
method: MemoryEndpoint["method"],
path: string,
responseSchema: string,
): MemoryEndpoint {
return Object.freeze({ method, path, responseSchema });
}
/**
* Describe, but do not call, the backend interface. Returning null while any
* dependency flag is absent keeps HUX-02 inert and default-off.
*/
export function createMemoryEndpointContract(
client: FoundationClient,
flags?: Iterable<string>,
): MemoryEndpointContract | null {
if (!memoryControlEnabled(flags)) return null;
if (client.apiVersion !== "hux.v1") throw new TypeError("HUX v1 client required");
const identity = Object.freeze({ ...normalizeIdentity(client.identity) });
function itemPath(memoryId: string): string {
if (!isOpaqueMemoryId(memoryId)) throw new TypeError("Opaque memory id required");
return client.endpoint(`/memories/${memoryId}`);
}
return Object.freeze({
identity,
list: endpoint("GET", client.endpoint("/memories"), "hux.memory_page.v1"),
suggestOnly: endpoint(
"PUT",
client.endpoint("/memory-settings/suggest-only"),
"hux.memory_settings.v1",
),
doNotRemember: endpoint(
"POST",
client.endpoint("/memory-blocks"),
"hux.memory_block.v1",
),
action(memoryId: string, action: MemoryAction) {
if (!["approve", "reject", "forget"].includes(action))
throw new TypeError("Unsupported memory action");
return endpoint(
"POST",
`${itemPath(memoryId)}/${action}`,
"hux.memory.v1",
);
},
revise(memoryId: string) {
return endpoint(
"POST",
`${itemPath(memoryId)}/revisions`,
"hux.memory.v1",
);
},
});
}