// SPEC: PJ2026-01060508 Web哨兵 draft-2026-06-25-p0-web-probe-sentinel. // Responsibility: Bounded CLI rendering for the observe wrapper contract. export function renderWebObserveWrapperContract(value: Record): string[] { const wrapper = nullableRecord(value.wrapper); if (wrapper === null) return []; const cli = record(wrapper.cli); const artifacts = record(wrapper.artifacts); const invariants = record(wrapper.invariants); return [ "Wrapper contract:", webObserveTable(["SPEC", "MODE", "VERB", "RUNNER", "ANALYZER", "STATE_DIR"], [[ webObserveShort(webObserveText(wrapper.specRef), 56), wrapper.mode, wrapper.action, invariants.reusesExistingObserveRunner === true && invariants.createsSecondPlaywrightRunner === false ? "existing" : "blocked", invariants.reusesExistingObserveAnalyzer === true && invariants.createsSecondAnalyzer === false ? "existing" : "blocked", webObserveShort(webObserveText(artifacts.stateDir), 88), ]]), ` cli: ${webObserveShort(webObserveText(cli.commandShape), 140)}`, "", ]; } function webObserveTable(headers: string[], rows: unknown[][]): string { const stringRows = rows.map((row) => headers.map((_, index) => webObserveCell(row[index]))); const widths = headers.map((header, index) => Math.max(header.length, ...stringRows.map((row) => row[index]?.length ?? 0))); const renderRow = (row: string[]) => row.map((cell, index) => cell.padEnd(widths[index] ?? cell.length)).join(" ").trimEnd(); return [renderRow(headers), ...stringRows.map(renderRow)].join("\n"); } function webObserveCell(value: unknown, maxLength = 96): string { if (value === null || value === undefined) return "-"; const text = typeof value === "string" ? value : String(value); const compact = text.replace(/\s+/gu, " ").trim(); if (compact.length === 0) return "-"; if (compact.length <= maxLength) return compact; return `${compact.slice(0, Math.max(1, maxLength - 1))}...`; } function webObserveText(value: unknown): string { if (value === null || value === undefined || value === "") return "-"; if (typeof value === "string") return value; if (typeof value === "number" || typeof value === "boolean") return String(value); return JSON.stringify(value); } function webObserveShort(value: string, maxLength: number): string { if (value.length <= maxLength) return value; if (maxLength <= 1) return value.slice(0, maxLength); return `${value.slice(0, maxLength - 1)}~`; } function record(value: unknown): Record { return value && typeof value === "object" && !Array.isArray(value) ? value as Record : {}; } function nullableRecord(value: unknown): Record | null { return value && typeof value === "object" && !Array.isArray(value) ? value as Record : null; }