Add full shell, replaceable Omics adapter and bilingual interaction

Implement approved specification #32 and tickets #33-#37. Keep host authentication server-verified and pin session interaction language. Compile scoped base selectors for browser compatibility and retain full gutters during CSS pruning.
This commit is contained in:
Codex
2026-09-13 14:26:39 +02:00
parent 2d1b714ebe
commit d8a29bfbdd
207 changed files with 8570 additions and 2164 deletions
+18 -15
View File
@@ -1,9 +1,7 @@
import { Type } from "typebox";
import { installRepairGate } from "./repair.js";
// Compatibility note: reviewer labels move verbatim from the composition root.
// Tickets #22 and #23 require observable parity; translating existing chrome is a
// separate product behavior change rather than part of these extractions.
// The composition root supplies manifest language; only deterministic chrome is localized.
function normalizedText(value) {
return String(value ?? "").trim().replace(/\s+/g, " ").toLowerCase();
@@ -31,7 +29,7 @@ function memoryOptionKey(option) {
}
function normalizeMemoryOptions(options) {
function normalizeMemoryOptions(options, locale, gateText) {
const seen = new Set();
const out = [];
for (const option of options) {
@@ -47,7 +45,7 @@ function normalizeMemoryOptions(options) {
].join(" ").match(MEMORY_ID_RE)?.[0]?.toLowerCase();
const fallbackDetail = [
option.decision?.type && option.decision?.subject
? `Decisione ${option.decision.type}: ${option.decision.subject}`
? `${gateText(locale, "decision")} ${option.decision.type}: ${option.decision.subject}`
: "",
option.decision?.detail ?? "",
].filter(Boolean).join("\n");
@@ -62,12 +60,15 @@ function normalizeMemoryOptions(options) {
}
function memorySelectionWidgetProps(options) {
function memorySelectionWidgetProps(options, locale, gateText) {
return {
title: "Seleziona le memory da applicare alla domanda",
title: gateText(locale, "memoryTitle"),
titleI18n: gateText("en", "memoryTitle"),
selected: options.filter((option) => option.recommended).map((option) => option.id),
selectionLabel: "memory da applicare",
confirmLabel: "Applica le memory selezionate",
selectionLabel: gateText(locale, "memorySelection"),
confirmLabel: gateText(locale, "memoryApply"),
selectionLabelI18n: gateText("en", "memorySelection"),
confirmLabelI18n: gateText("en", "memoryApply"),
};
}
@@ -78,10 +79,11 @@ function shouldSkipEmptyRecall({ meritCount, allowEmpty, advance }) {
async function reviewRecall(ctx, params, phase, dependencies) {
const { workflow, ledger, reviewer, waitForReviewer, toTextResult } = dependencies;
const { workflow, ledger, reviewer, waitForReviewer, toTextResult, languageFor, gateText } = dependencies;
try {
const { session, advance } = params;
const options = normalizeMemoryOptions(params.options);
const locale = languageFor(ctx, session);
const options = normalizeMemoryOptions(params.options, locale, gateText);
const typeError = ledger.validate(ctx, options, session);
if (typeError) return toTextResult(typeError);
const meritOptions = options
@@ -99,7 +101,7 @@ async function reviewRecall(ctx, params, phase, dependencies) {
advance,
})) {
await ctx.ui.notify(
"Nessuna memory riutilizzabile per questa domanda — passo alla fase successiva.",
gateText(locale, "memoryEmpty"),
"info",
);
workflow.advance(ctx, session);
@@ -113,7 +115,7 @@ async function reviewRecall(ctx, params, phase, dependencies) {
phase,
allowEmpty: params.allow_empty ?? false,
options: meritOptions,
...memorySelectionWidgetProps(options),
...memorySelectionWidgetProps(options, locale, gateText),
});
const response = await waitForReviewer(ctx, widget);
if (response.control === "freetext") {
@@ -161,7 +163,7 @@ async function reviewRecall(ctx, params, phase, dependencies) {
}
function installMemoryGate(pi, { workflow, memory, ledger, waitForReviewer, toTextResult }) {
function installMemoryGate(pi, { workflow, memory, ledger, waitForReviewer, toTextResult, languageFor, gateText }) {
pi.registerTool({
name: "reviewer_memory_promote",
label: "Review Memory summary",
@@ -188,7 +190,8 @@ function installMemoryGate(pi, { workflow, memory, ledger, waitForReviewer, toTe
}
const response = await waitForReviewer(ctx, {
id: `u${Date.now()}`, schema_version: 1, phase: phase.id,
widget: "memory-review", title: "Memory for future questions",
widget: "memory-review", title: gateText(languageFor(ctx, session), "memorySummary"),
title_i18n: gateText("en", "memorySummary"),
summary, reserved: ["other", "back", "exit"],
});
if (response.control) return toTextResult(
+6 -3
View File
@@ -1,6 +1,6 @@
import { Type } from "typebox";
export function installRepairGate(pi, { workflow, memory, waitForReviewer, toTextResult }) {
export function installRepairGate(pi, { workflow, memory, waitForReviewer, toTextResult, languageFor, gateText }) {
pi.registerTool({
name: "reviewer_archive_repair",
label: "Resolve Memory / Evidence conflict",
@@ -26,6 +26,7 @@ export function installRepairGate(pi, { workflow, memory, waitForReviewer, toTex
try {
if (!!params.repair_id === !!params.proposal)
return toTextResult("Supply either a new proposal or an existing repair_id.");
const locale = languageFor(ctx, params.session);
const run = args => JSON.parse(memory.execute(ctx,
[...args, "--session", params.session, "--json"]));
let repair = params.repair_id
@@ -36,7 +37,9 @@ export function installRepairGate(pi, { workflow, memory, waitForReviewer, toTex
const response = await waitForReviewer(ctx, {
id: `u${Date.now()}`, schema_version: 1,
phase: workflow.phase(ctx, params.session).id,
widget: "archive-repair", title: "Resolve archive conflict",
widget: "archive-repair", title: gateText(locale, "archiveRepair"),
title_i18n: gateText("en", "archiveRepair"),
...(error ? { error_i18n: gateText("en", "repairError") } : {}),
repair, error, reserved: ["other", "back", "exit"],
});
if (response.control) return toTextResult(response.control === "freetext"
@@ -62,7 +65,7 @@ export function installRepairGate(pi, { workflow, memory, waitForReviewer, toTex
return toTextResult("All repair proposals were rejected as inadequate. " +
"No archive was changed. Reformulate the options for the reviewer.");
} catch (failure) {
error = "The correction could not complete. Review the current archive state before retrying.";
error = gateText(locale, "repairError");
repair = run(["repair-show", "--repair-id", repair.repair_id]);
}
}