// // VerifyHarness.swift // Zyquo Atlas // // Author: Simon-Pierre Boucher // Mail: contact@spboucher.ai // // Phase 7 verification. Exercises the *Atlas* stack against live APIs with real // keys: (1) content extraction on real pages, (2) a grounded summarize across // every catalog model through the ported provider clients, (3) the core AI // action matrix, and (4) cancel-on-navigation. Results → stdout + docs/ // VERIFICATION.md. Keys come from the environment (source .env.keys) and are // never logged or persisted. `--load-vault` seeds the vault; `--quick` runs one // model per provider. // import Foundation import WebKit import AppKit @MainActor enum VerifyHarness { static let environmentKeys: [ProviderID: String] = [ .openai: "OPENAI_API_KEY", .anthropic: "ANTHROPIC_API_KEY", .xai: "XAI_API_KEY", .mistral: "MISTRAL_API_KEY", .gemini: "GEMINI_API_KEY", .qwen: "DASHSCOPE_API_KEY", .deepseek: "DEEPSEEK_API_KEY", .kimi: "MOONSHOT_API_KEY", .perplexity: "PERPLEXITY_API_KEY", .together: "TOGETHER_API_KEY", .deepinfra: "DEEPINFRA_API_KEY", .cerebras: "CEREBRAS_API_KEY", ] struct Result { let section: String let provider: String let subject: String let test: String let passed: Bool let latency: TimeInterval? let detail: String } // MARK: - Entry static func run(arguments: [String]) async -> Int32 { let quick = arguments.contains("--quick") let onlyProvider = value(after: "--provider", in: arguments).flatMap { ProviderID(rawValue: $0) } let catalog = ModelCatalog() print("Zyquo Atlas — Phase 7 verification\(quick ? " (quick)" : "")\n") var results: [Result] = [] // 1) Extraction-quality suite (headless real pages). let (extraction, sample) = await verifyExtraction() results += extraction // A grounded PageContext for the model sweep + action matrix. Trim so // every one of 170 model calls stays cheap and fast while still grounded. let context = trimmed(sample) ?? fallbackContext() // 2) Grounded summarize across every catalog model. results += await verifyModels(catalog: catalog, context: context, quick: quick, onlyProvider: onlyProvider) // 3) Core AI action matrix (against one live model per available provider). results += await verifyActions(catalog: catalog, context: context, onlyProvider: onlyProvider) // 4) Cancellation + privacy. results += await verifyCancellation(catalog: catalog, context: context) report(results) return results.contains { !$0.passed } ? 1 : 0 } // MARK: - 1. Extraction suite private static let extractionPages: [(name: String, url: String, selectFirstPara: Bool)] = [ ("article", "https://en.wikipedia.org/wiki/Cartography", false), ("docs", "https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch", false), ("long-article", "https://en.wikipedia.org/wiki/World_War_II", false), ("js-app", "https://react.dev/", false), ("selection", "https://en.wikipedia.org/wiki/Map", true), ] private static func verifyExtraction() async -> ([Result], PageContext?) { print("— Content extraction —") var results: [Result] = [] var sample: PageContext? let config = ProfileStore.shared.makeConfiguration(for: .defaultProfile) let loader = PageLoader(configuration: config) for page in extractionPages { guard let url = URL(string: page.url) else { continue } let start = Date() do { try await loader.load(url) try? await Task.sleep(nanoseconds: 1_500_000_000) if page.selectFirstPara { // Select the first real paragraph so the extractor captures it. _ = try? await loader.webView.evaluateJavaScript( "(function(){var p=Array.from(document.querySelectorAll('p')).find(function(e){return e.textContent.trim().length>80});if(!p)return false;var r=document.createRange();r.selectNodeContents(p);var s=getSelection();s.removeAllRanges();s.addRange(r);return true;})();", in: nil, contentWorld: .page) try? await Task.sleep(nanoseconds: 400_000_000) } let ctx = try await ContentExtractor.extract(from: loader.webView) let ok: Bool let detail: String if page.selectFirstPara { ok = (ctx.selection?.text.isEmpty == false) detail = "selection=\(ctx.selection?.text.prefix(40).description ?? "nil"), words=\(ctx.wordCount)" } else { ok = ctx.wordCount > 80 && !ctx.markdown.isEmpty detail = "quality=\(ctx.quality.rawValue), words=\(ctx.wordCount), ~\(ctx.estimatedTokens)tok, headings=\(ctx.headings.count)" } results.append(Result(section: "Extraction", provider: "—", subject: page.name, test: "extract", passed: ok, latency: Date().timeIntervalSince(start), detail: detail)) if page.name == "article" { sample = ctx } print(" \(ok ? "✓" : "✗") \(page.name): \(detail)") } catch { results.append(Result(section: "Extraction", provider: "—", subject: page.name, test: "extract", passed: false, latency: nil, detail: error.localizedDescription)) print(" ✗ \(page.name): \(error.localizedDescription)") } } return (results, sample) } // MARK: - 2. Model sweep (grounded summarize on every model) private static func verifyModels(catalog: ModelCatalog, context: PageContext, quick: Bool, onlyProvider: ProviderID?) async -> [Result] { print("\n— AI summarize across all catalog models —") var results: [Result] = [] let providers = ProviderID.builtIn.filter { onlyProvider == nil || $0 == onlyProvider } for provider in providers { guard let key = apiKey(for: provider) else { print(" ⚠︎ \(provider.rawValue): no key — skipped"); continue } var models = catalog.models(for: provider) if quick { models = Array(models.prefix(1)) } let serial = provider == .cerebras || provider == .mistral if serial { for model in models { results.append(await summarizeTest(model: model, context: context, key: key)) // Cerebras free tier: 5 req/min. try? await Task.sleep(nanoseconds: provider == .cerebras ? 13_000_000_000 : 1_100_000_000) } } else { results += await limitedConcurrent(models, limit: 3) { model in await summarizeTest(model: model, context: context, key: key) } } let pass = results.filter { $0.section == "Models" && $0.provider == provider.displayName && $0.passed }.count let total = results.filter { $0.section == "Models" && $0.provider == provider.displayName }.count print(" \(pass == total ? "✓" : "✗") \(provider.displayName): \(pass)/\(total) models") } return results } private static func summarizeTest(model: AIModel, context: PageContext, key: String) async -> Result { let start = Date() let client = ProviderRegistry.client(for: model) // Reasoning models stream hidden thinking first; give them room to reach text. var params = ChatParameters(maxTokens: model.capabilities.reasoning ? 8000 : 256) if model.parameterSupport.reasoningEffort { params.reasoningEffort = "low" } let request = ChatRequest( model: model, systemPrompt: AIAction.summarize.systemGuidance, messages: [Message(role: .user, text: AIAction.summarize.userPrompt(for: context))], parameters: params) do { var deltas = 0, text = "" for try await event in client.streamChat(request, apiKey: key) { if case .textDelta(let d) = event { deltas += 1; text += d } } let ok = deltas >= 1 && !text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty return Result(section: "Models", provider: model.provider.displayName, subject: model.id, test: "summarize", passed: ok, latency: Date().timeIntervalSince(start), detail: ok ? "deltas=\(deltas)" : "empty response") } catch { return Result(section: "Models", provider: model.provider.displayName, subject: model.id, test: "summarize", passed: false, latency: Date().timeIntervalSince(start), detail: error.localizedDescription) } } // MARK: - 3. Action matrix private static func verifyActions(catalog: ModelCatalog, context: PageContext, onlyProvider: ProviderID?) async -> [Result] { print("\n— Core AI action matrix —") // Pick the first provider with a key (or the requested one). let providers = ProviderID.builtIn.filter { onlyProvider == nil || $0 == onlyProvider } guard let provider = providers.first(where: { apiKey(for: $0) != nil }), let model = catalog.cheapestModel(for: provider) ?? catalog.models(for: provider).first, let key = apiKey(for: provider) else { print(" ⚠︎ no keyed provider for action matrix"); return [] } var results: [Result] = [] func record(_ name: String, _ system: String?, _ user: String) async { let start = Date() let client = ProviderRegistry.client(for: model) var p = ChatParameters(maxTokens: 256) if model.parameterSupport.reasoningEffort { p.reasoningEffort = "low" } let req = ChatRequest(model: model, systemPrompt: system, messages: [Message(role: .user, text: user)], parameters: p) do { var text = "" for try await ev in client.streamChat(req, apiKey: key) { if case .textDelta(let d) = ev { text += d } } let ok = !text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty results.append(Result(section: "Actions", provider: model.provider.displayName, subject: name, test: "action", passed: ok, latency: Date().timeIntervalSince(start), detail: ok ? "" : "empty")) print(" \(ok ? "✓" : "✗") \(name)") } catch { results.append(Result(section: "Actions", provider: model.provider.displayName, subject: name, test: "action", passed: false, latency: nil, detail: error.localizedDescription)) print(" ✗ \(name): \(error.localizedDescription)") } } let selText = "Cartography is the study and practice of making and using maps." await record("omnibox-ask", "You answer grounded in the page.", AIAction.ask.userPrompt(for: context, extra: "What is this page about?")) await record("summarize", AIAction.summarize.systemGuidance, AIAction.summarize.userPrompt(for: context)) await record("chat-followup", AIAction.ask.systemGuidance, AIAction.ask.userPrompt(for: context, extra: "List two key facts.")) await record("selection-explain", AIAction.explainSelection.selectionPrompt(selText).system, AIAction.explainSelection.selectionPrompt(selText).user) await record("selection-translate", AIAction.translate.selectionPrompt(selText, language: "French").system, AIAction.translate.selectionPrompt(selText, language: "French").user) await record("selection-rewrite", AIAction.rewrite.selectionPrompt(selText).system, AIAction.rewrite.selectionPrompt(selText).user) await record("multi-tab-compare", "You compare multiple web pages.", "Compare these two pages briefly:\n\nA) \(context.title)\n\(context.markdown.prefix(800))\n\nB) A blank page.") return results } // MARK: - 4. Cancellation + privacy private static func verifyCancellation(catalog: ModelCatalog, context: PageContext) async -> [Result] { print("\n— Cancellation & privacy —") guard let provider = ProviderID.builtIn.first(where: { apiKey(for: $0) != nil }), let model = catalog.cheapestModel(for: provider) ?? catalog.models(for: provider).first, let key = apiKey(for: provider) else { return [] } let service = AIService() service.run(.summarize, on: context, model: model, apiKey: key) try? await Task.sleep(nanoseconds: 300_000_000) service.cancel() try? await Task.sleep(nanoseconds: 400_000_000) let stopped = !service.isStreaming print(" \(stopped ? "✓" : "✗") cancel-on-navigation stops the stream") // Privacy invariant: a fresh service sends nothing until run() is called. let idle = AIService() let noSend = idle.output.isEmpty && !idle.isStreaming print(" \(noSend ? "✓" : "✗") no content leaves the device without a user action") return [ Result(section: "Privacy", provider: "—", subject: "cancel-on-navigation", test: "cancel", passed: stopped, latency: nil, detail: stopped ? "stream cancelled" : "still streaming"), Result(section: "Privacy", provider: "—", subject: "no-send-without-action", test: "privacy", passed: noSend, latency: nil, detail: "AIService idle until run()"), ] } // MARK: - Reporting private static func report(_ results: [Result]) { let fails = results.filter { !$0.passed } var lines = ["", "", "# Zyquo Atlas — Phase 7 Verification", "", "**\(results.count) checks · \(results.count - fails.count) passed · \(fails.count) failed**", "", "Exercises the Atlas stack (ContentExtractor + AIService + ported provider clients)", "against live APIs with real keys. Page content is sent only on an AI action; keys", "come from the environment and are never logged.", ""] func table(_ section: String, cols: [String]) { let rows = results.filter { $0.section == section } guard !rows.isEmpty else { return } lines.append("## \(section)") lines.append("") lines.append("| " + cols.joined(separator: " | ") + " |") lines.append("|" + cols.map { _ in "---" }.joined(separator: "|") + "|") for r in rows.sorted(by: { ($0.provider, $0.subject) < ($1.provider, $1.subject) }) { let lat = r.latency.map { String(format: "%.1fs", $0) } ?? "—" let d = r.detail.replacingOccurrences(of: "|", with: "\\|") lines.append("| \(r.provider) | `\(r.subject)` | \(r.test) | \(r.passed ? "✅" : "❌") | \(lat) | \(d) |") } lines.append("") } table("Extraction", cols: ["Source", "Page", "Test", "Result", "Latency", "Detail"]) table("Models", cols: ["Provider", "Model", "Test", "Result", "Latency", "Detail"]) table("Actions", cols: ["Provider", "Action", "Test", "Result", "Latency", "Detail"]) table("Privacy", cols: ["—", "Check", "Test", "Result", "Latency", "Detail"]) let doc = lines.joined(separator: "\n") let url = URL(fileURLWithPath: FileManager.default.currentDirectoryPath) .appendingPathComponent("docs/VERIFICATION.md") try? doc.data(using: .utf8)?.write(to: url) print("\n" + String(repeating: "—", count: 64)) for f in fails { print("❌ [\(f.section)] \(f.provider) \(f.subject) [\(f.test)] — \(f.detail)") } print(String(repeating: "—", count: 64)) print("\(results.count) checks · \(results.count - fails.count) passed · \(fails.count) failed") print("Full table: docs/VERIFICATION.md") } // MARK: - Vault seeding static func loadVault() { let store = SecureKeyStore() var loaded: [String] = [] for (provider, name) in environmentKeys { if let key = ProcessInfo.processInfo.environment[name], !key.isEmpty { try? store.setKey(key, for: provider) loaded.append(provider.rawValue) } } print("Vault updated with keys for: \(loaded.sorted().joined(separator: ", "))") } // MARK: - Helpers static func apiKey(for provider: ProviderID) -> String? { guard let name = environmentKeys[provider] else { return nil } let value = ProcessInfo.processInfo.environment[name] return (value?.isEmpty ?? true) ? nil : value } private static func value(after flag: String, in args: [String]) -> String? { guard let i = args.firstIndex(of: flag), i + 1 < args.count else { return nil } return args[i + 1] } /// Trims a PageContext's markdown so 170 model calls stay cheap but grounded. private static func trimmed(_ ctx: PageContext?) -> PageContext? { guard let ctx, !ctx.markdown.isEmpty else { return nil } let short = String(ctx.markdown.prefix(1800)) return PageContext(cloning: ctx, markdown: short) } /// A baked context if extraction failed entirely (keeps the sweep runnable). private static func fallbackContext() -> PageContext { PageContext(bakedTitle: "Cartography", url: "https://en.wikipedia.org/wiki/Cartography", markdown: "# Cartography\n\nCartography is the study and practice of making and using maps. Combining science, aesthetics and technique, it builds on the premise that reality can be modeled in ways that communicate spatial information effectively.") } private static func limitedConcurrent( _ items: [AIModel], limit: Int, _ op: @escaping @Sendable (AIModel) async -> T ) async -> [T] { await withTaskGroup(of: (Int, T).self) { group in var out: [(Int, T)] = [] var it = items.enumerated().makeIterator() var inFlight = 0 func addNext() { if let (i, m) = it.next() { inFlight += 1; group.addTask { (i, await op(m)) } } } for _ in 0.. 0 { if let r = await group.next() { out.append(r); inFlight -= 1; addNext() } } return out.sorted { $0.0 < $1.0 }.map { $0.1 } } } }