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
313 lines
10 KiB
TypeScript
313 lines
10 KiB
TypeScript
/** Fail-closed HUX-06 intent validation and HUX foundation adapter. */
|
|
|
|
import type {
|
|
AdvancedRouteChoice,
|
|
FriendlyModeIntent,
|
|
FriendlyModeName,
|
|
FriendlyModesAdapter,
|
|
HuxFoundationClient,
|
|
ModeConstraints,
|
|
ModeEffort,
|
|
ModeProvider,
|
|
RawAdvancedRouteChoice,
|
|
RawModeIntent,
|
|
RawResolvedRoute,
|
|
ResolvedRouteDisclosure,
|
|
} from "./types.ts";
|
|
|
|
export const FOUNDATION_FLAG = "hux.foundation";
|
|
export const FRIENDLY_MODES_FLAG = "hux.friendly_modes";
|
|
export const MODE_ORDER: readonly FriendlyModeName[] = [
|
|
"fast",
|
|
"thoughtful",
|
|
"research",
|
|
"create",
|
|
"private",
|
|
];
|
|
|
|
const MODE_LABELS: Readonly<Record<FriendlyModeName, string>> = {
|
|
fast: "Fast",
|
|
thoughtful: "Thoughtful",
|
|
research: "Research",
|
|
create: "Create",
|
|
private: "Private",
|
|
};
|
|
const PROVIDERS = new Set<ModeProvider>(["codex", "claude", "local"]);
|
|
const EFFORTS: readonly ModeEffort[] = ["low", "medium", "high", "xhigh"];
|
|
const ROUTE = /^atlas\/(auto|manual|fallback|worker)\/[a-z0-9/-]+$/;
|
|
const MANUAL_ROUTE = /^atlas\/manual\/[a-z0-9/-]+$/;
|
|
const REMOTE_PROVIDER_NAME = /\b(?:anthropic|claude|codex|openai)\b/i;
|
|
|
|
function record(value: unknown): Record<string, unknown> | null {
|
|
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
return value as Record<string, unknown>;
|
|
}
|
|
|
|
function exactKeys(
|
|
value: Record<string, unknown>,
|
|
required: readonly string[],
|
|
optional: readonly string[] = [],
|
|
): boolean {
|
|
const allowed = new Set([...required, ...optional]);
|
|
return (
|
|
required.every((key) => Object.prototype.hasOwnProperty.call(value, key)) &&
|
|
Object.keys(value).every((key) => allowed.has(key))
|
|
);
|
|
}
|
|
|
|
function boundedString(value: unknown, min: number, max: number): value is string {
|
|
return typeof value === "string" && value.length >= min && value.length <= max;
|
|
}
|
|
|
|
function oneOf<T extends string>(value: unknown, values: readonly T[]): value is T {
|
|
return typeof value === "string" && values.includes(value as T);
|
|
}
|
|
|
|
function normalizeConstraints(value: unknown): ModeConstraints | null {
|
|
const constraints = record(value);
|
|
const required = [
|
|
"providers",
|
|
"local_only",
|
|
"effort",
|
|
"tools",
|
|
"memory",
|
|
"citations_required",
|
|
"retention",
|
|
];
|
|
if (!constraints || !exactKeys(constraints, required)) return null;
|
|
if (!Array.isArray(constraints.providers) || constraints.providers.length < 1)
|
|
return null;
|
|
const providers = constraints.providers;
|
|
if (
|
|
providers.some((provider) => !PROVIDERS.has(provider as ModeProvider)) ||
|
|
new Set(providers).size !== providers.length ||
|
|
typeof constraints.local_only !== "boolean"
|
|
)
|
|
return null;
|
|
|
|
const effort = record(constraints.effort);
|
|
const tools = record(constraints.tools);
|
|
const memory = record(constraints.memory);
|
|
if (
|
|
!effort ||
|
|
!exactKeys(effort, ["min", "max"]) ||
|
|
!oneOf(effort.min, EFFORTS) ||
|
|
!oneOf(effort.max, EFFORTS) ||
|
|
EFFORTS.indexOf(effort.min) > EFFORTS.indexOf(effort.max)
|
|
)
|
|
return null;
|
|
if (
|
|
!tools ||
|
|
!exactKeys(tools, ["web", "shell", "artifacts", "delegate"]) ||
|
|
!oneOf(tools.web, ["required", "allowed", "denied"] as const) ||
|
|
!oneOf(tools.shell, ["allowed", "denied"] as const) ||
|
|
!oneOf(tools.artifacts, ["encouraged", "allowed", "denied"] as const) ||
|
|
!oneOf(tools.delegate, ["allowed", "denied"] as const)
|
|
)
|
|
return null;
|
|
if (
|
|
!memory ||
|
|
!exactKeys(memory, ["read", "write"]) ||
|
|
typeof memory.read !== "boolean" ||
|
|
typeof memory.write !== "boolean" ||
|
|
typeof constraints.citations_required !== "boolean" ||
|
|
!oneOf(constraints.retention, ["default", "ephemeral"] as const)
|
|
)
|
|
return null;
|
|
|
|
// Provider arrays are semantically sets. Canonical ordering prevents their
|
|
// transport order from becoming an accidental routing preference.
|
|
const canonicalProviders = (["codex", "claude", "local"] as const).filter(
|
|
(provider) => providers.includes(provider),
|
|
);
|
|
return {
|
|
providers: [...canonicalProviders],
|
|
local_only: constraints.local_only,
|
|
effort: { min: effort.min, max: effort.max },
|
|
tools: {
|
|
web: tools.web,
|
|
shell: tools.shell,
|
|
artifacts: tools.artifacts,
|
|
delegate: tools.delegate,
|
|
},
|
|
memory: { read: memory.read, write: memory.write },
|
|
citations_required: constraints.citations_required,
|
|
retention: constraints.retention,
|
|
};
|
|
}
|
|
|
|
function modeSemanticsAreSafe(
|
|
mode: FriendlyModeName,
|
|
constraints: ModeConstraints,
|
|
routeId: string,
|
|
): boolean {
|
|
const providers = new Set(constraints.providers);
|
|
if (mode === "private") {
|
|
return (
|
|
constraints.local_only &&
|
|
providers.size === 1 &&
|
|
providers.has("local") &&
|
|
routeId.startsWith("atlas/auto/")
|
|
);
|
|
}
|
|
return (
|
|
!constraints.local_only &&
|
|
providers.has("codex") &&
|
|
providers.has("claude") &&
|
|
!REMOTE_PROVIDER_NAME.test(routeId.replaceAll("/", " ")) &&
|
|
routeId.startsWith("atlas/auto/")
|
|
);
|
|
}
|
|
|
|
export function friendlyModesEnabled(flags?: Iterable<string>): boolean {
|
|
if (!flags) return false;
|
|
const enabled = new Set(flags);
|
|
return enabled.has(FOUNDATION_FLAG) && enabled.has(FRIENDLY_MODES_FLAG);
|
|
}
|
|
|
|
export function normalizeMode(raw: RawModeIntent): FriendlyModeIntent | null {
|
|
const root = record(raw);
|
|
if (
|
|
!root ||
|
|
!exactKeys(root, ["schema", "mode", "label", "intent", "constraints", "switchyard"]) ||
|
|
root.schema !== "hux.mode.v1" ||
|
|
!oneOf(root.mode, MODE_ORDER) ||
|
|
root.label !== MODE_LABELS[root.mode] ||
|
|
!boundedString(root.intent, 1, 400) ||
|
|
REMOTE_PROVIDER_NAME.test(root.intent)
|
|
)
|
|
return null;
|
|
const constraints = normalizeConstraints(root.constraints);
|
|
const switchyard = record(root.switchyard);
|
|
if (
|
|
!constraints ||
|
|
!switchyard ||
|
|
!exactKeys(switchyard, ["route_id"]) ||
|
|
typeof switchyard.route_id !== "string" ||
|
|
!ROUTE.test(switchyard.route_id) ||
|
|
!modeSemanticsAreSafe(root.mode, constraints, switchyard.route_id)
|
|
)
|
|
return null;
|
|
return {
|
|
schema: "hux.mode.v1",
|
|
mode: root.mode,
|
|
label: root.label,
|
|
intent: root.intent,
|
|
constraints,
|
|
switchyard: { route_id: switchyard.route_id },
|
|
};
|
|
}
|
|
|
|
export function normalizeModeCatalog(raw: unknown): FriendlyModeIntent[] | null {
|
|
if (!Array.isArray(raw) || raw.length !== MODE_ORDER.length) return null;
|
|
const modes = raw.map((value) => normalizeMode(value as RawModeIntent));
|
|
if (modes.some((mode) => mode === null)) return null;
|
|
const byName = new Map(
|
|
(modes as FriendlyModeIntent[]).map((mode) => [mode.mode, mode]),
|
|
);
|
|
if (byName.size !== MODE_ORDER.length) return null;
|
|
return MODE_ORDER.map((name) => byName.get(name) as FriendlyModeIntent);
|
|
}
|
|
|
|
export function normalizeAdvancedRoutes(raw: unknown): AdvancedRouteChoice[] {
|
|
if (!Array.isArray(raw)) return [];
|
|
const seen = new Set<string>();
|
|
const choices: AdvancedRouteChoice[] = [];
|
|
for (const value of raw.slice(0, 100)) {
|
|
const choice = record(value as RawAdvancedRouteChoice);
|
|
if (
|
|
!choice ||
|
|
!exactKeys(choice, ["route_id", "label", "provider", "effort", "local_only"]) ||
|
|
typeof choice.route_id !== "string" ||
|
|
!MANUAL_ROUTE.test(choice.route_id) ||
|
|
seen.has(choice.route_id) ||
|
|
!boundedString(choice.label, 1, 80) ||
|
|
!PROVIDERS.has(choice.provider as ModeProvider) ||
|
|
!oneOf(choice.effort, EFFORTS) ||
|
|
typeof choice.local_only !== "boolean"
|
|
)
|
|
continue;
|
|
seen.add(choice.route_id);
|
|
choices.push({
|
|
routeId: choice.route_id,
|
|
label: choice.label,
|
|
provider: choice.provider as ModeProvider,
|
|
effort: choice.effort,
|
|
localOnly: choice.local_only,
|
|
});
|
|
}
|
|
return choices;
|
|
}
|
|
|
|
export function buildModeRequest(
|
|
mode: FriendlyModeIntent,
|
|
advancedRouteId?: string,
|
|
choices: readonly AdvancedRouteChoice[] = [],
|
|
): FriendlyModeIntent | null {
|
|
const normalized = normalizeMode(mode);
|
|
if (!normalized) return null;
|
|
if (advancedRouteId === undefined) return normalized;
|
|
const choice = choices.find((item) => item.routeId === advancedRouteId);
|
|
if (!choice || !MANUAL_ROUTE.test(advancedRouteId)) return null;
|
|
const allowed = normalized.constraints.providers.includes(choice.provider);
|
|
const privateSafe =
|
|
normalized.mode !== "private" ||
|
|
(choice.localOnly && choice.provider === "local");
|
|
const automaticSafe =
|
|
normalized.mode === "private" || (!choice.localOnly && allowed);
|
|
if (!allowed || !privateSafe || !automaticSafe) return null;
|
|
return {
|
|
...normalized,
|
|
switchyard: {
|
|
route_id: normalized.switchyard.route_id,
|
|
override_route_id: advancedRouteId,
|
|
},
|
|
};
|
|
}
|
|
|
|
export function normalizeResolvedRoute(raw: unknown): ResolvedRouteDisclosure | null {
|
|
const route = record(raw as RawResolvedRoute);
|
|
if (!route || !exactKeys(route, ["requested"], ["resolved_target", "provider", "effort"]))
|
|
return null;
|
|
if (!boundedString(route.requested, 1, 120)) return null;
|
|
if (
|
|
route.resolved_target !== undefined &&
|
|
!boundedString(route.resolved_target, 1, 120)
|
|
)
|
|
return null;
|
|
if (route.provider !== undefined && !PROVIDERS.has(route.provider as ModeProvider))
|
|
return null;
|
|
if (route.effort !== undefined && !oneOf(route.effort, EFFORTS)) return null;
|
|
return {
|
|
requested: route.requested,
|
|
target: route.resolved_target as string | undefined,
|
|
provider: route.provider as ModeProvider | undefined,
|
|
effort: route.effort as ModeEffort | undefined,
|
|
};
|
|
}
|
|
|
|
export function createFriendlyModesAdapter(
|
|
foundation: HuxFoundationClient,
|
|
): FriendlyModesAdapter {
|
|
if (
|
|
!foundation ||
|
|
foundation.apiVersion !== "hux.v1" ||
|
|
typeof foundation.enabled !== "function" ||
|
|
typeof foundation.endpoint !== "function"
|
|
)
|
|
throw new TypeError("A hux.v1 foundation client is required");
|
|
return Object.freeze({
|
|
apiVersion: "hux.v1" as const,
|
|
enabled: () =>
|
|
foundation.enabled(FOUNDATION_FLAG) && foundation.enabled(FRIENDLY_MODES_FLAG),
|
|
endpoint: () => foundation.endpoint("/modes"),
|
|
adaptCatalog: normalizeModeCatalog,
|
|
adaptResolvedRoute: normalizeResolvedRoute,
|
|
buildRequest: (
|
|
mode: FriendlyModeIntent,
|
|
advancedRouteId?: string,
|
|
choices?: readonly AdvancedRouteChoice[],
|
|
) => buildModeRequest(mode, advancedRouteId, choices),
|
|
});
|
|
}
|