token-harness 0.1.25 → 0.1.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/README.md +132 -443
  2. package/package.json +1 -1
  3. package/sbom.json +3 -3
  4. package/token-harness.mjs +1027 -450
package/token-harness.mjs CHANGED
@@ -9862,7 +9862,7 @@ var TOOL_VERSION;
9862
9862
  var init_version2 = __esm({
9863
9863
  "apps/cli/dist/src/version.js"() {
9864
9864
  "use strict";
9865
- TOOL_VERSION = "0.1.25";
9865
+ TOOL_VERSION = "0.1.27";
9866
9866
  }
9867
9867
  });
9868
9868
 
@@ -11923,6 +11923,50 @@ var init_windows_command_line = __esm({
11923
11923
  import { spawn } from "node:child_process";
11924
11924
  import { win32 as win324 } from "node:path";
11925
11925
  import process3 from "node:process";
11926
+ function launchGuidedApplication(input) {
11927
+ return new Promise((resolve, reject) => {
11928
+ const child = spawn(input.executable, [input.entryScript, "ui", "--no-open"], {
11929
+ cwd: input.cwd,
11930
+ env: minimalChildEnvironment({ facts: input.facts, ambient: input.env }),
11931
+ shell: false,
11932
+ windowsHide: true,
11933
+ detached: true,
11934
+ stdio: ["ignore", "ignore", "ignore", "ipc"]
11935
+ });
11936
+ let settled = false;
11937
+ const finish5 = (url) => {
11938
+ if (settled)
11939
+ return;
11940
+ settled = true;
11941
+ clearTimeout(timer);
11942
+ if (child.connected)
11943
+ child.disconnect();
11944
+ if (url === null) {
11945
+ child.kill();
11946
+ reject(new Error("The updated app could not start. The current dashboard remains open."));
11947
+ } else {
11948
+ child.unref();
11949
+ resolve(url);
11950
+ }
11951
+ };
11952
+ const timer = setTimeout(() => finish5(null), input.timeoutMs ?? 2e4);
11953
+ child.once("error", () => finish5(null));
11954
+ child.once("exit", () => finish5(null));
11955
+ child.on("message", (message) => {
11956
+ if (message === null || typeof message !== "object")
11957
+ return;
11958
+ const value3 = message;
11959
+ if (value3["type"] !== "token-harness-guide-ready" || typeof value3["url"] !== "string")
11960
+ return;
11961
+ try {
11962
+ const url = new URL(value3["url"]);
11963
+ if (url.protocol === "http:" && url.hostname === "127.0.0.1" && url.port !== "" && url.pathname === "/" && url.search === "" && url.hash === "" && url.username === "" && url.password === "")
11964
+ finish5(url.href);
11965
+ } catch {
11966
+ }
11967
+ });
11968
+ });
11969
+ }
11926
11970
  function boundedCapture(limit) {
11927
11971
  const chunks = [];
11928
11972
  let size = 0;
@@ -14819,7 +14863,7 @@ function record5(value3) {
14819
14863
  function tuple(event, matcher, command) {
14820
14864
  return JSON.stringify([event, matcher, command]);
14821
14865
  }
14822
- async function readCodexHookEnablement(context, config) {
14866
+ async function readCodexHookEnablement(context, config, routingOnly = false) {
14823
14867
  const expected = [];
14824
14868
  try {
14825
14869
  const stat3 = await context.fs.stat(config.path);
@@ -14831,8 +14875,15 @@ async function readCodexHookEnablement(context, config) {
14831
14875
  return null;
14832
14876
  for (const [event, native] of [
14833
14877
  ["PreToolUse", "preToolUse"],
14834
- ["PostToolUse", "postToolUse"]
14878
+ ["PostToolUse", "postToolUse"],
14879
+ ...routingOnly ? [
14880
+ ["UserPromptSubmit", "userPromptSubmit"],
14881
+ ["SubagentStart", "subagentStart"],
14882
+ ["SubagentStop", "subagentStop"]
14883
+ ] : []
14835
14884
  ]) {
14885
+ if (routingOnly && !["UserPromptSubmit", "SubagentStart", "SubagentStop"].includes(event))
14886
+ continue;
14836
14887
  const entries = parsed["hooks"][event];
14837
14888
  if (!Array.isArray(entries))
14838
14889
  continue;
@@ -14841,7 +14892,7 @@ async function readCodexHookEnablement(context, config) {
14841
14892
  continue;
14842
14893
  const matcher = typeof entry["matcher"] === "string" ? entry["matcher"] : null;
14843
14894
  for (const handler of entry["hooks"]) {
14844
- if (record5(handler) && handler["type"] === "command" && typeof handler["command"] === "string") {
14895
+ if (record5(handler) && handler["type"] === "command" && typeof handler["command"] === "string" && (!routingOnly || handler["command"].includes("__internal-prompt-router"))) {
14845
14896
  expected.push(tuple(native, matcher, handler["command"]));
14846
14897
  }
14847
14898
  }
@@ -16737,7 +16788,13 @@ var init_pi = __esm({
16737
16788
  });
16738
16789
 
16739
16790
  // packages/adapters/dist/src/harnesses/native-prompt-routing.js
16740
- function nativePromptRoutingHookEntries(harness, executable = "token-harness") {
16791
+ function nativePromptRoutingVersionSupported(harness, version3) {
16792
+ const parsed = version3 === null ? null : parseSemanticVersion(version3);
16793
+ if (parsed === null || parsed.prerelease !== null)
16794
+ return false;
16795
+ return harness === "codex" ? parsed.major === 0 && (parsed.minor === 159 && parsed.patch <= 1 || parsed.minor === 160 && parsed.patch === 0) : harness === "claude" && parsed.major === 2 && parsed.minor === 1 && parsed.patch >= 274 && parsed.patch <= 288;
16796
+ }
16797
+ function nativePromptRoutingHookEntries(harness, executable = "token-harness", platform = "linux") {
16741
16798
  return NATIVE_PROMPT_ROUTING_EVENTS.map(({ eventName, commandEvent }) => {
16742
16799
  if (harness === "codex") {
16743
16800
  const command = `${executable} __internal-prompt-router codex ${commandEvent}`;
@@ -16751,7 +16808,11 @@ function nativePromptRoutingHookEntries(harness, executable = "token-harness") {
16751
16808
  handler2["additionalContextLimit"] = 500;
16752
16809
  return { eventName, value: { hooks: [handler2] } };
16753
16810
  }
16754
- const handler = {
16811
+ const handler = platform === "windows" ? {
16812
+ type: "command",
16813
+ command: `${executable} __internal-prompt-router claude ${commandEvent}`,
16814
+ timeout: 10
16815
+ } : {
16755
16816
  type: "command",
16756
16817
  command: executable,
16757
16818
  args: ["__internal-prompt-router", "claude", commandEvent],
@@ -16764,6 +16825,7 @@ var NATIVE_PROMPT_ROUTING_EVENTS;
16764
16825
  var init_native_prompt_routing = __esm({
16765
16826
  "packages/adapters/dist/src/harnesses/native-prompt-routing.js"() {
16766
16827
  "use strict";
16828
+ init_src();
16767
16829
  NATIVE_PROMPT_ROUTING_EVENTS = [
16768
16830
  { eventName: "UserPromptSubmit", commandEvent: "prompt-submit" },
16769
16831
  { eventName: "SubagentStart", commandEvent: "subagent-start" },
@@ -16797,6 +16859,7 @@ var init_harnesses = __esm({
16797
16859
  init_pi();
16798
16860
  init_claude();
16799
16861
  init_native_prompt_routing();
16862
+ init_codex_hooks();
16800
16863
  HARNESS_ADAPTERS = [
16801
16864
  claudeAdapter,
16802
16865
  codexAdapter,
@@ -20343,7 +20406,20 @@ ${help.stderr}`) : { compact: false, json: false };
20343
20406
  detail: ready ? `mcptoon ${version3} exposes the compact/JSON CLI surfaces used by the managed integration` : `mcptoon ${version3} no longer advertises the compact/JSON CLI surfaces required by the managed integration`
20344
20407
  };
20345
20408
  }
20346
- function mcptoonInstallAction() {
20409
+ async function mcptoonInstallChannel(context) {
20410
+ for (const channel of ["pipx", "uv"]) {
20411
+ const result6 = await context.runner.run({
20412
+ executable: channel,
20413
+ args: ["--version"],
20414
+ cwd: context.projectRoot,
20415
+ timeoutMs: 2e4
20416
+ });
20417
+ if (result6.failure === null && result6.exitCode === 0)
20418
+ return channel;
20419
+ }
20420
+ return null;
20421
+ }
20422
+ function mcptoonInstallAction(channel) {
20347
20423
  return {
20348
20424
  kind: "package-manager-install",
20349
20425
  id: `mcptoon:install:${MCPTOON_REVIEWED_INSTALL_VERSION}`,
@@ -20351,12 +20427,14 @@ function mcptoonInstallAction() {
20351
20427
  requiresNetwork: true,
20352
20428
  requiresElevation: false,
20353
20429
  affectedPaths: [],
20354
- affectedProcesses: ["pipx"],
20355
- preconditions: ["pipx remains runnable and the reviewed mcptoon release remains installable"],
20356
- postconditions: [`mcptoon ${MCPTOON_REVIEWED_INSTALL_VERSION} is installed through pipx`],
20430
+ affectedProcesses: [channel],
20431
+ preconditions: [
20432
+ `${channel} remains runnable and the reviewed mcptoon release remains installable`
20433
+ ],
20434
+ postconditions: [`mcptoon ${MCPTOON_REVIEWED_INSTALL_VERSION} is installed through ${channel}`],
20357
20435
  rollbackData: "package-inventory",
20358
- explanation: `Install reviewed mcptoon ${MCPTOON_REVIEWED_INSTALL_VERSION} in an isolated pipx environment`,
20359
- packageManager: "pipx",
20436
+ explanation: `Install reviewed mcptoon ${MCPTOON_REVIEWED_INSTALL_VERSION} in an isolated ${channel} environment`,
20437
+ packageManager: channel,
20360
20438
  packageName: "mcptoon",
20361
20439
  version: MCPTOON_REVIEWED_INSTALL_VERSION
20362
20440
  };
@@ -20577,13 +20655,8 @@ async function planMcptoonManagedActivation(context, harness) {
20577
20655
  if (activation.actions.length === 0 && !activationSatisfied) {
20578
20656
  return activation;
20579
20657
  }
20580
- const pipx = await context.runner.run({
20581
- executable: "pipx",
20582
- args: ["--version"],
20583
- cwd: context.projectRoot,
20584
- timeoutMs: 2e4
20585
- });
20586
- if (pipx.failure !== null || pipx.exitCode !== 0) {
20658
+ const channel = await mcptoonInstallChannel(context);
20659
+ if (channel === null) {
20587
20660
  return {
20588
20661
  harness,
20589
20662
  target: activation.target,
@@ -20594,22 +20667,22 @@ async function planMcptoonManagedActivation(context, harness) {
20594
20667
  severity: "warning",
20595
20668
  code: "mcptoon-pipx-unavailable",
20596
20669
  subject: harness,
20597
- message: "mcptoon is absent and the isolated pipx installer is not available",
20598
- remediation: "Install pipx, then refresh Token Harness; Token Harness will not bootstrap a Python package manager implicitly"
20670
+ message: "mcptoon needs an isolated installer: pipx or uv",
20671
+ remediation: "Install pipx or uv, then Refresh to enable Install mcptoon. See Installation options for the platform instructions."
20599
20672
  })
20600
20673
  ]
20601
20674
  };
20602
20675
  }
20603
20676
  return {
20604
20677
  ...activation,
20605
- actions: [mcptoonInstallAction(), ...activation.actions],
20678
+ actions: [mcptoonInstallAction(channel), ...activation.actions],
20606
20679
  diagnostics: [
20607
20680
  ...activation.diagnostics,
20608
20681
  diagnostic({
20609
20682
  severity: "info",
20610
20683
  code: "mcptoon-managed-install-planned",
20611
20684
  subject: harness,
20612
- message: `mcptoon is absent; install reviewed ${MCPTOON_REVIEWED_INSTALL_VERSION} through pipx before enabling agent guidance`,
20685
+ message: `mcptoon is absent; install reviewed ${MCPTOON_REVIEWED_INSTALL_VERSION} through ${channel} before enabling agent guidance`,
20613
20686
  remediation: null
20614
20687
  })
20615
20688
  ]
@@ -20743,20 +20816,15 @@ async function mcptoonDetection(context) {
20743
20816
  configuredHarnesses.push(harness);
20744
20817
  }
20745
20818
  }
20746
- const pipx = observation.absent ? await context.runner.run({
20747
- executable: "pipx",
20748
- args: ["--version"],
20749
- cwd: context.projectRoot,
20750
- timeoutMs: 2e4
20751
- }) : null;
20752
- const canInstall = observation.absent && pipx !== null && pipx.failure === null && pipx.exitCode === 0;
20819
+ const channel = observation.absent ? await mcptoonInstallChannel(context) : null;
20820
+ const canInstall = observation.absent && channel !== null;
20753
20821
  const warnings = observation.absent && !canInstall ? [
20754
20822
  diagnostic({
20755
20823
  severity: "warning",
20756
20824
  code: "mcptoon-pipx-unavailable",
20757
20825
  subject: "mcptoon",
20758
- message: "mcptoon is not installed and pipx is not available in this terminal",
20759
- remediation: "Install pipx or make it available on PATH, then refresh. Token Harness will use it to install the reviewed mcptoon build."
20826
+ message: "mcptoon is not installed; pipx or uv is required",
20827
+ remediation: "Install pipx or uv, then Refresh to enable Install mcptoon. Open Installation options for your platform."
20760
20828
  })
20761
20829
  ] : !observation.absent && !observation.ready ? [warning("mcptoon-provider-capability-unavailable", "mcptoon", observation.detail)] : [];
20762
20830
  return {
@@ -20764,7 +20832,7 @@ async function mcptoonDetection(context) {
20764
20832
  state: observation.absent ? "absent" : configuredHarnesses.length > 0 ? "configured" : "installed",
20765
20833
  version: observation.version,
20766
20834
  executable: observation.executable,
20767
- installationChannel: observation.absent ? "pipx" : null,
20835
+ installationChannel: observation.absent ? channel : null,
20768
20836
  versionVerdict: versionVerdict(observation.version, MCPTOON_REVIEWED_BENCHMARK_VERSION),
20769
20837
  configuredHarnesses,
20770
20838
  unmanagedHarnessesConfigured: [],
@@ -20975,6 +21043,16 @@ var init_managed_optimization_tools = __esm({
20975
21043
  requiresNetwork: true,
20976
21044
  requiresElevation: false,
20977
21045
  digestAvailable: false
21046
+ },
21047
+ {
21048
+ id: "uv",
21049
+ packageId: "mcptoon",
21050
+ kind: "uv",
21051
+ priority: 1,
21052
+ platforms: ["windows", "macos", "linux"],
21053
+ requiresNetwork: true,
21054
+ requiresElevation: false,
21055
+ digestAvailable: false
20978
21056
  }
20979
21057
  ],
20980
21058
  metrics: { source: "none", mode: "unavailable", locations: [] },
@@ -22989,9 +23067,6 @@ var init_argv = __esm({
22989
23067
  function isHarness(value3) {
22990
23068
  return value3 === "claude" || value3 === "codex";
22991
23069
  }
22992
- function expectedVersions(harness) {
22993
- return harness === "codex" ? ["0.159.0", "0.160.0"] : ["2.1.274", "2.1.288"];
22994
- }
22995
23070
  function configTarget(input) {
22996
23071
  if (!isHarness(input.harness) || input.home === null)
22997
23072
  return null;
@@ -23013,8 +23088,8 @@ function configTarget(input) {
23013
23088
  fileContext
23014
23089
  };
23015
23090
  }
23016
- function hookEntries(harness) {
23017
- return nativePromptRoutingHookEntries(harnessId(harness), "token-harness");
23091
+ function hookEntries(harness, platform = "linux") {
23092
+ return nativePromptRoutingHookEntries(harnessId(harness), "token-harness", platform);
23018
23093
  }
23019
23094
  function asRecord(value3) {
23020
23095
  return typeof value3 === "object" && value3 !== null && !Array.isArray(value3) ? value3 : null;
@@ -23054,13 +23129,13 @@ function containsRouterCommand(value3, harness) {
23054
23129
  if (harness === "codex")
23055
23130
  return [handler["command"], handler["commandWindows"]].some((command) => typeof command === "string" && command.includes(ROUTE_MARKER));
23056
23131
  const args = handler["args"];
23057
- return handler["command"] === "token-harness" && Array.isArray(args) && args[0] === ROUTE_MARKER;
23132
+ return typeof handler["command"] === "string" && handler["command"].includes(ROUTE_MARKER) || handler["command"] === "token-harness" && Array.isArray(args) && args[0] === ROUTE_MARKER;
23058
23133
  });
23059
23134
  }
23060
- function configHasExactRouter(hooks, harness) {
23135
+ function configHasExactRouter(hooks, harness, platform) {
23061
23136
  let exactCount = 0;
23062
23137
  let routeCount = 0;
23063
- for (const expected of hookEntries(harness)) {
23138
+ for (const expected of hookEntries(harness, platform)) {
23064
23139
  const live = hooks[expected.eventName];
23065
23140
  const entries = Array.isArray(live) ? live : [];
23066
23141
  const routeEntries = entries.filter((entry) => containsRouterCommand(entry, harness));
@@ -23069,13 +23144,13 @@ function configHasExactRouter(hooks, harness) {
23069
23144
  exactCount += 1;
23070
23145
  }
23071
23146
  return {
23072
- complete: exactCount === hookEntries(harness).length,
23073
- partial: routeCount > 0 && exactCount !== hookEntries(harness).length,
23147
+ complete: exactCount === hookEntries(harness, platform).length,
23148
+ partial: routeCount > 0 && exactCount !== hookEntries(harness, platform).length,
23074
23149
  conflict: routeCount > exactCount
23075
23150
  };
23076
23151
  }
23077
- function routerOwnedArtifacts(journals, path, harness) {
23078
- const expected = hookEntries(harness);
23152
+ function routerOwnedArtifacts(journals, path, harness, platform) {
23153
+ const expected = hookEntries(harness, platform);
23079
23154
  for (const journal of journals) {
23080
23155
  const disabledHere = journal.entries.some((entry) => entry.actionId.startsWith(`native-prompt-routing:${harness}:disable:`) && entry.snapshots.some((snapshot) => snapshot.path === path));
23081
23156
  if (disabledHere && journal.outcome === "committed")
@@ -23114,14 +23189,14 @@ async function planNativePromptRoutingInstall(input) {
23114
23189
  }));
23115
23190
  return { target: null, actions: [], diagnostics };
23116
23191
  }
23117
- if (!expectedVersions(target.harness).includes(target.version ?? "")) {
23192
+ if (!nativePromptRoutingVersionSupported(harnessId(target.harness), target.version)) {
23118
23193
  diagnostics.push(diagnostic({
23119
23194
  severity: "warning",
23120
23195
  code: "prompt-routing-version-unverified",
23121
23196
  subject: target.harness,
23122
- message: `Native prompt routing has no hook fixture for ${target.harness} ${target.version ?? "unknown"}`,
23197
+ message: `Routing is not supported for ${target.harness} ${target.version ?? "(version unknown)"}. Check Token Harness updates in Health and updates, then retry.`,
23123
23198
  path: target.path,
23124
- remediation: "Refresh Token Harness after the installed harness hook schema is fixture-tested"
23199
+ remediation: "Check for Token Harness updates; this agent version needs a verified hook fixture"
23125
23200
  }));
23126
23201
  return { target: target.path, actions: [], diagnostics };
23127
23202
  }
@@ -23171,7 +23246,7 @@ async function planNativePromptRoutingInstall(input) {
23171
23246
  }
23172
23247
  hooks = parsed.hooks;
23173
23248
  }
23174
- const existing = configHasExactRouter(hooks, target.harness);
23249
+ const existing = configHasExactRouter(hooks, target.harness, input.facts.os);
23175
23250
  if (existing.complete) {
23176
23251
  diagnostics.push(diagnostic({
23177
23252
  severity: "info",
@@ -23183,7 +23258,10 @@ async function planNativePromptRoutingInstall(input) {
23183
23258
  }));
23184
23259
  return { target: target.path, actions: [], diagnostics };
23185
23260
  }
23186
- if (existing.partial || existing.conflict) {
23261
+ const legacy = target.harness === "claude" && input.facts.os === "windows" ? configHasExactRouter(hooks, target.harness, "linux") : null;
23262
+ const legacyOwned = legacy?.complete && !legacy.conflict ? routerOwnedArtifacts(await journalsFor({ fs: input.fs, stateRoot: input.stateRoot ?? null }), target.path, target.harness, "linux") : [];
23263
+ const repair = legacyOwned.length === 3;
23264
+ if ((existing.partial || existing.conflict) && !repair) {
23187
23265
  diagnostics.push(diagnostic({
23188
23266
  severity: "error",
23189
23267
  code: "prompt-routing-existing-hook-conflict",
@@ -23194,7 +23272,7 @@ async function planNativePromptRoutingInstall(input) {
23194
23272
  }));
23195
23273
  return { target: target.path, actions: [], diagnostics };
23196
23274
  }
23197
- const entries = hookEntries(target.harness);
23275
+ const entries = hookEntries(target.harness, input.facts.os);
23198
23276
  const action = {
23199
23277
  kind: "merge-json",
23200
23278
  id: actionId(target.harness, "enable", "all"),
@@ -23220,7 +23298,8 @@ async function planNativePromptRoutingInstall(input) {
23220
23298
  })),
23221
23299
  createIfMissing: true
23222
23300
  };
23223
- return { target: target.path, actions: [action], diagnostics };
23301
+ const removals = repair ? await planNativePromptRoutingRemoval({ ...input, stateRoot: input.stateRoot ?? null }) : null;
23302
+ return { target: target.path, actions: [...removals?.actions ?? [], action], diagnostics };
23224
23303
  }
23225
23304
  async function planNativePromptRoutingRemoval(input) {
23226
23305
  const diagnostics = [];
@@ -23235,9 +23314,13 @@ async function planNativePromptRoutingRemoval(input) {
23235
23314
  }));
23236
23315
  return { target: target?.path ?? null, actions: [], diagnostics };
23237
23316
  }
23238
- const expected = hookEntries(target.harness);
23317
+ let expected = hookEntries(target.harness, input.facts.os);
23239
23318
  const journals = await journalsFor({ fs: input.fs, stateRoot: input.stateRoot });
23240
- const artifacts = routerOwnedArtifacts(journals, target.path, target.harness);
23319
+ let artifacts = routerOwnedArtifacts(journals, target.path, target.harness, input.facts.os);
23320
+ if (artifacts.length === 0 && target.harness === "claude" && input.facts.os === "windows") {
23321
+ expected = hookEntries(target.harness, "linux");
23322
+ artifacts = routerOwnedArtifacts(journals, target.path, target.harness, "linux");
23323
+ }
23241
23324
  const actions = expected.flatMap((entry) => {
23242
23325
  const pointer = `hooks.${entry.eventName}`;
23243
23326
  const targetArtifact = artifacts.find((artifact) => artifact.kind === "owned-json-entry" && artifact.pointer === pointer && artifact.valueDigest === jsonValueDigest(entry.value));
@@ -23381,7 +23464,9 @@ async function observeNativePromptRouting(input) {
23381
23464
  subagentsStopped: 0,
23382
23465
  reportedModels: [],
23383
23466
  lastObservedAt: null,
23384
- receiptState: "unavailable"
23467
+ receiptState: "unavailable",
23468
+ enablement: "unknown",
23469
+ verificationTier: "config-only"
23385
23470
  };
23386
23471
  const target = configTarget({ ...input, harness: input.harness });
23387
23472
  if (target === null)
@@ -23442,7 +23527,23 @@ async function observeNativePromptRouting(input) {
23442
23527
  receiptState: eventResult.state
23443
23528
  };
23444
23529
  }
23445
- const match = configHasExactRouter(hooks, harness);
23530
+ const match = configHasExactRouter(hooks, harness, input.facts.os);
23531
+ if (harness === "claude" && input.facts.os === "windows" && (match.partial || match.conflict)) {
23532
+ const legacy = configHasExactRouter(hooks, harness, "linux");
23533
+ const owned = routerOwnedArtifacts(await journalsFor(input), target.path, harness, "linux");
23534
+ if (legacy.complete && !legacy.conflict && owned.length === 3)
23535
+ return {
23536
+ ...base,
23537
+ ...summary,
23538
+ state: "managed",
23539
+ label: "Repair required",
23540
+ configured: false,
23541
+ configPath: target.path,
23542
+ needsRepair: true,
23543
+ receiptState: eventResult.state,
23544
+ detail: "The installed routing hook cannot launch the Windows npm command. Choose Repair routing once; future prompts run automatically."
23545
+ };
23546
+ }
23446
23547
  if (match.conflict || match.partial) {
23447
23548
  return {
23448
23549
  ...base,
@@ -23466,16 +23567,54 @@ async function observeNativePromptRouting(input) {
23466
23567
  receiptState: eventResult.state
23467
23568
  };
23468
23569
  }
23469
- const artifacts = routerOwnedArtifacts(await journalsFor(input), target.path, harness);
23470
- const state = artifacts.length === hookEntries(harness).length ? "managed" : "external";
23570
+ const artifacts = routerOwnedArtifacts(await journalsFor(input), target.path, harness, input.facts.os);
23571
+ const state = artifacts.length === hookEntries(harness, input.facts.os).length ? "managed" : "external";
23471
23572
  const hasRuntimeReceipt = summary.promptSubmissions > 0;
23472
- const label = state === "external" ? hasRuntimeReceipt ? "Runtime observed \xB7 external" : "Enabled externally" : hasRuntimeReceipt ? "Runtime observed" : harness === "codex" ? "Configured \xB7 trust or runtime pending" : "Configured \xB7 runtime pending";
23473
- const detail2 = summary.promptSubmissions > 0 ? `${String(summary.promptSubmissions)} prompt hook(s), ${String(summary.subagentsStarted)} native agent start(s), ${String(summary.subagentsStopped)} stop(s) observed in this project during the last 30 days.${eventResult.state === "limited" ? " Counts are partial because the local receipt scan reached its safety limit." : eventResult.state === "unavailable" ? " Local runtime receipts could not be read." : ""}` : harness === "codex" ? "The hook is configured. Review and trust it in Codex with /hooks, then submit a prompt to produce a runtime receipt." : "The hook is configured. Start a new Claude Code session, submit a prompt, and Token Harness will show the runtime receipt.";
23573
+ let enablement = "unknown";
23574
+ if (harness === "codex") {
23575
+ const declaration = findHarnessAdapter(harnessId(harness)).manifest.configFiles.find((file) => file.parser === "json" && file.scope === "user");
23576
+ const check = await readCodexHookEnablement(target.fileContext, {
23577
+ declaration,
23578
+ path: target.path,
23579
+ exists: true,
23580
+ parsed: true,
23581
+ configuredPoints: [],
23582
+ matchers: [],
23583
+ commands: []
23584
+ }, true);
23585
+ if (check?.status === "pass")
23586
+ enablement = "enabled";
23587
+ else if (check?.status === "fail")
23588
+ enablement = /[1-9]\d* untrusted/.test(check.summary) ? "untrusted" : "disabled";
23589
+ } else {
23590
+ const adapter = findHarnessAdapter(harnessId(harness));
23591
+ let disabled = false;
23592
+ let readable = true;
23593
+ for (const declaration of adapter.manifest.configFiles) {
23594
+ const path = resolveConfigPath(declaration, target.fileContext);
23595
+ if ((await input.fs.stat(path))?.kind !== "file")
23596
+ continue;
23597
+ try {
23598
+ const doc = asRecord(JSON.parse(DECODER4.decode(await input.fs.readFile(path))));
23599
+ if (typeof doc?.["disableAllHooks"] === "boolean")
23600
+ disabled = doc["disableAllHooks"];
23601
+ } catch {
23602
+ readable = false;
23603
+ }
23604
+ }
23605
+ enablement = readable ? disabled ? "disabled" : "enabled" : "unknown";
23606
+ }
23607
+ const blocked = enablement === "untrusted" || enablement === "disabled";
23608
+ const label = blocked ? enablement === "untrusted" ? "Authorization required" : "Hooks disabled" : hasRuntimeReceipt ? "Runtime observed" : enablement === "enabled" ? "Ready \xB7 awaiting prompt" : "Configured \xB7 check authorization";
23609
+ const scope = input.projectId === null ? "across projects" : "in this project";
23610
+ const detail2 = blocked ? harness === "codex" ? "Open Codex /hooks. Enable and trust the three Token Harness routing hooks once, then send a prompt." : "Hooks are disabled in Claude settings. Enable hooks in /hooks, then send a prompt." : hasRuntimeReceipt ? `${String(summary.promptSubmissions)} prompt callbacks, ${String(summary.subagentsStarted)} agent starts, ${String(summary.subagentsStopped)} stops ${scope} in the last 30 days. Routing runs automatically on each prompt.${eventResult.state === "limited" ? " Counts are partial." : ""}` : enablement === "enabled" ? "Ready. Send a prompt in a new session; the first callback will appear here automatically. No skill or command is needed per prompt." : harness === "codex" ? "Open Codex /hooks and check the three Token Harness routing hooks are enabled and trusted. Do this once, then send a prompt in a new session." : "Check the Claude hook settings can be read and hooks are enabled in /hooks, then send a prompt in a new session.";
23474
23611
  return {
23475
23612
  ...base,
23476
23613
  state,
23477
23614
  label,
23478
23615
  detail: detail2,
23616
+ enablement,
23617
+ verificationTier: hasRuntimeReceipt && !blocked ? "runtime-observed" : "config-only",
23479
23618
  configPath: target.path,
23480
23619
  configured: true,
23481
23620
  ...summary,
@@ -27376,7 +27515,7 @@ async function runApply(context) {
27376
27515
  now: context.now,
27377
27516
  verifyPostconditions: async () => [
27378
27517
  ...await verifyManagedIntegrationPostconditions(context, computed.managedIntegrations),
27379
- ...await verifyNativePromptRoutingPostconditions(context, actions)
27518
+ ...await verifyNativePromptRoutingPostconditions(planningContext, actions)
27380
27519
  ]
27381
27520
  });
27382
27521
  diagnostics.push(...transaction.diagnostics);
@@ -35504,7 +35643,7 @@ function guideSetupTargets(report, harness) {
35504
35643
  function explainGuideIssue(diagnostics, fallback) {
35505
35644
  const known = diagnostics.find((entry) => entry.severity === "error" && ISSUE_COPY[entry.code] !== void 0) ?? diagnostics.find((entry) => entry.severity === "warning" && ISSUE_COPY[entry.code] !== void 0) ?? diagnostics.find((entry) => entry.severity === "info" && ISSUE_COPY[entry.code] !== void 0);
35506
35645
  if (known !== void 0)
35507
- return ISSUE_COPY[known.code];
35646
+ return known.code === "prompt-routing-version-unverified" ? known.message : ISSUE_COPY[known.code];
35508
35647
  const blocked = diagnostics.find((entry) => /compatibility|unsupported|unreviewed|no-row/.test(entry.code));
35509
35648
  if (blocked !== void 0)
35510
35649
  return "The required automatic capability or safety precondition is not available in the current runtime. Your current settings are preserved.";
@@ -35853,7 +35992,7 @@ var init_guided = __esm({
35853
35992
  "codex-native-policy-shadowed": "A project or profile overrides this Codex setting. That setting belongs to you and will not be replaced.",
35854
35993
  "no-providers-registered": "No optimization provider was selected for this operation.",
35855
35994
  "prompt-routing-target-unavailable": "Token Harness could not locate a supported user-level prompt-hook settings file for this agent.",
35856
- "prompt-routing-version-unverified": "Automatic routing is not available for this agent version until its prompt-hook format has been verified.",
35995
+ "prompt-routing-version-unverified": "Update Token Harness in Health and updates, then retry routing. This agent version is not supported by this copy.",
35857
35996
  "prompt-routing-runtime-unavailable": "The Token Harness hook command could not run from this dashboard environment. Make Token Harness available on PATH, then review routing again.",
35858
35997
  "prompt-routing-target-not-file": "A non-file occupies the agent hook settings path, so Token Harness left it unchanged.",
35859
35998
  "prompt-routing-settings-unmergeable": "The current hook settings cannot be merged safely. Repair the JSON or review the hook manually.",
@@ -35947,6 +36086,8 @@ var init_guided = __esm({
35947
36086
  loading = null;
35948
36087
  readSequence = 0;
35949
36088
  busy = false;
36089
+ restartVersion = null;
36090
+ restartApplication;
35950
36091
  lastApplied = null;
35951
36092
  reading = null;
35952
36093
  cached = null;
@@ -35959,12 +36100,13 @@ var init_guided = __esm({
35959
36100
  random;
35960
36101
  observeGuidance;
35961
36102
  observeRouting;
35962
- constructor(call, now, random, observeGuidance = null, observeRouting = null) {
36103
+ constructor(call, now, random, observeGuidance = null, observeRouting = null, restartApplication = null) {
35963
36104
  this.call = call;
35964
36105
  this.now = now;
35965
36106
  this.random = random;
35966
36107
  this.observeGuidance = observeGuidance;
35967
36108
  this.observeRouting = observeRouting;
36109
+ this.restartApplication = restartApplication;
35968
36110
  }
35969
36111
  status() {
35970
36112
  return {
@@ -36604,21 +36746,40 @@ var init_guided = __esm({
36604
36746
  }
36605
36747
  this.lastApplied = null;
36606
36748
  this.invalidateObservedState();
36749
+ this.record("Re-checking health after the update.", "working");
36750
+ let health;
36751
+ try {
36752
+ health = await this.verifyIntegrations();
36753
+ } catch {
36754
+ health = {
36755
+ ok: false,
36756
+ title: "Health check needs attention",
36757
+ messages: ["Update installed; automatic health check could not finish."],
36758
+ appliedPlans: 0
36759
+ };
36760
+ }
36761
+ if (applicationTarget !== void 0)
36762
+ this.restartVersion = applicationTarget.version;
36607
36763
  const versions = approvedUpdates.map((target) => `${guideUpdateTargetName(target)} ${target.version}`).join(", ");
36608
36764
  const messages2 = [
36609
36765
  appliedCount > 0 ? `Installed and verified the approved update${approvedUpdates.length === 1 ? "" : "s"}: ${versions}.` : `The approved update${approvedUpdates.length === 1 ? " was" : "s were"} already at the target version: ${versions}.`,
36610
- ...applicationTarget === void 0 ? [] : ["Token Harness is updated on disk. Restart this app to load the new version."],
36766
+ ...applicationTarget === void 0 ? [] : [
36767
+ "Token Harness is updated. Choose Restart and re-check to load it and discover new capabilities."
36768
+ ],
36611
36769
  ...providerTargets.length === 0 ? [] : [
36612
36770
  "The active optimizer runtimes were re-read after the operation and match the approved targets.",
36613
36771
  "Reopen a coding agent if an updated optimizer requires it."
36614
36772
  ]
36615
36773
  ];
36774
+ messages2.push(health.ok ? "Health re-check completed automatically." : "Update installed; health needs attention.", ...health.messages);
36616
36775
  this.record(appliedCount > 0 ? "Approved updates installed and verified." : "Approved updates are already at their target versions.", "success");
36617
36776
  return {
36618
36777
  ok: true,
36619
36778
  title: applicationTarget !== void 0 ? "Token Harness updated" : appliedCount > 0 ? "Optimizers updated" : "Approved versions already active",
36620
36779
  messages: messages2,
36621
- appliedPlans: appliedCount
36780
+ appliedPlans: appliedCount,
36781
+ ...health.stack === void 0 ? {} : { stack: health.stack },
36782
+ restartRequired: applicationTarget !== void 0
36622
36783
  };
36623
36784
  }
36624
36785
  if (approval.operation === "candidate-apply" || approval.operation === "candidate-uninstall") {
@@ -36774,6 +36935,34 @@ var init_guided = __esm({
36774
36935
  };
36775
36936
  });
36776
36937
  }
36938
+ async routing() {
36939
+ if (this.observeRouting === null)
36940
+ return { agents: [] };
36941
+ const agents = await Promise.all(["claude", "codex"].map(async (id) => ({
36942
+ id,
36943
+ promptRouting: await this.observeRouting(id)
36944
+ })));
36945
+ if (this.cached !== null) {
36946
+ for (const agent of this.cached.value.agents) {
36947
+ const live = agents.find((item) => item.id === agent.id);
36948
+ if (live !== void 0)
36949
+ agent.promptRouting = live.promptRouting;
36950
+ }
36951
+ }
36952
+ return { agents };
36953
+ }
36954
+ async restart() {
36955
+ return this.exclusive(async () => {
36956
+ if (this.restartVersion === null || this.restartApplication === null)
36957
+ throw new GuideError(409, "Restart is available after a verified Token Harness update.");
36958
+ const installed2 = await this.call(["update"]);
36959
+ if (!sameGuideVersion(installed2.data?.application?.installed ?? null, this.restartVersion))
36960
+ throw new GuideError(409, "The installation changed. Check updates again before restarting.");
36961
+ const url = await this.restartApplication();
36962
+ this.restartVersion = null;
36963
+ return { url };
36964
+ });
36965
+ }
36777
36966
  async checkUpdates() {
36778
36967
  return this.exclusive(async () => {
36779
36968
  this.approval = null;
@@ -36892,89 +37081,90 @@ var init_guided = __esm({
36892
37081
  });
36893
37082
  }
36894
37083
  async verify() {
36895
- return this.exclusive(async () => {
36896
- this.record("Checking the configured integrations without changing them.", "working");
36897
- const messages = [];
36898
- const results = [];
36899
- let ok = true;
36900
- let healthyAtDeclaredTier = true;
36901
- const inventory = await this.call(["doctor"]);
36902
- const present = (inventory.data?.harnesses ?? []).filter((item) => item.state !== "absent" && ["claude", "codex"].includes(item.harnessId));
36903
- if (inventory.data === null) {
37084
+ return this.exclusive(() => this.verifyIntegrations());
37085
+ }
37086
+ async verifyIntegrations() {
37087
+ this.record("Checking the configured integrations without changing them.", "working");
37088
+ const messages = [];
37089
+ const results = [];
37090
+ let ok = true;
37091
+ let healthyAtDeclaredTier = true;
37092
+ const inventory = await this.call(["doctor"]);
37093
+ const present = (inventory.data?.harnesses ?? []).filter((item) => item.state !== "absent" && ["claude", "codex"].includes(item.harnessId));
37094
+ if (inventory.data === null) {
37095
+ ok = false;
37096
+ healthyAtDeclaredTier = false;
37097
+ messages.push("The installed-agent inventory could not be read. Refresh and check the local installation.");
37098
+ }
37099
+ if (present.length === 0) {
37100
+ ok = false;
37101
+ healthyAtDeclaredTier = false;
37102
+ messages.push("No supported installed agent was detected, so no integration was checked.");
37103
+ }
37104
+ for (const agent of present) {
37105
+ const harness = agent.harnessId;
37106
+ this.record(`Checking ${name(harness)} configuration and available execution evidence. No settings changed.`, "working");
37107
+ const result6 = await this.call(["verify", "--harness", harness]);
37108
+ const healthy = result6.data?.healthyAtDeclaredTier === true;
37109
+ const versionWarnings = result6.diagnostics.filter((entry) => entry.severity === "warning" && (entry.code === "harness-version-unknown-newer" || entry.code === "provider-version-unknown-newer"));
37110
+ const failed = result6.data === null || result6.exitCode !== 0 || result6.diagnostics.some((entry) => entry.severity === "error" || entry.severity === "warning" && !versionWarnings.includes(entry)) || result6.data.results.some((entry) => entry.status === "degraded" || entry.status === "failed");
37111
+ if (failed)
36904
37112
  ok = false;
37113
+ if (!healthy)
36905
37114
  healthyAtDeclaredTier = false;
36906
- messages.push("The installed-agent inventory could not be read. Refresh and check the local installation.");
37115
+ if (result6.data !== null)
37116
+ results.push(...result6.data.results);
37117
+ const prefix = `${name(harness)}: `;
37118
+ if (result6.data === null) {
37119
+ messages.push(prefix + "the verification report could not be read. Refresh and check the local installation.");
37120
+ } else if (healthy) {
37121
+ messages.push(prefix + "the available integration checks passed. This is not proof that every command was reduced.");
37122
+ } else if (failed) {
37123
+ messages.push(prefix + "a known integration check failed. Review the specific check before changing setup.");
37124
+ } else if (result6.data.results.length === 0) {
37125
+ messages.push(prefix + "the agent is detected, but no managed optimizer connection is present to verify. Review setup only if you want to connect one.");
37126
+ } else {
37127
+ const pendingProviders = [
37128
+ ...new Set(result6.data.results.filter((entry) => entry.status === "not-applicable").map((entry) => name(entry.providerId)))
37129
+ ];
37130
+ const subject = pendingProviders.length > 0 ? pendingProviders.join(" and ") : "Some integrations";
37131
+ messages.push(`${prefix}${subject} have not produced enough attributable runtime evidence for ${name(harness)} yet. This is an evidence gap, not a finding that the setup is broken. If you do not use this agent on this machine, no action is required.`);
36907
37132
  }
36908
- if (present.length === 0) {
36909
- ok = false;
36910
- healthyAtDeclaredTier = false;
36911
- messages.push("No supported installed agent was detected, so no integration was checked.");
37133
+ if (versionWarnings.length > 0) {
37134
+ messages.push(prefix + "the installed version is newer than Token Harness\u2019s recorded compatibility sample; read-only checks can continue, but review the version before changing its integration.");
36912
37135
  }
36913
- for (const agent of present) {
36914
- const harness = agent.harnessId;
36915
- this.record(`Checking ${name(harness)} configuration and available execution evidence. No settings changed.`, "working");
36916
- const result6 = await this.call(["verify", "--harness", harness]);
36917
- const healthy = result6.data?.healthyAtDeclaredTier === true;
36918
- const versionWarnings = result6.diagnostics.filter((entry) => entry.severity === "warning" && (entry.code === "harness-version-unknown-newer" || entry.code === "provider-version-unknown-newer"));
36919
- const failed = result6.data === null || result6.exitCode !== 0 || result6.diagnostics.some((entry) => entry.severity === "error" || entry.severity === "warning" && !versionWarnings.includes(entry)) || result6.data.results.some((entry) => entry.status === "degraded" || entry.status === "failed");
36920
- if (failed)
36921
- ok = false;
36922
- if (!healthy)
36923
- healthyAtDeclaredTier = false;
36924
- if (result6.data !== null)
36925
- results.push(...result6.data.results);
36926
- const prefix = `${name(harness)}: `;
36927
- if (result6.data === null) {
36928
- messages.push(prefix + "the verification report could not be read. Refresh and check the local installation.");
36929
- } else if (healthy) {
36930
- messages.push(prefix + "the available integration checks passed. This is not proof that every command was reduced.");
36931
- } else if (failed) {
36932
- messages.push(prefix + "a known integration check failed. Review the specific check before changing setup.");
36933
- } else if (result6.data.results.length === 0) {
36934
- messages.push(prefix + "the agent is detected, but no managed optimizer connection is present to verify. Review setup only if you want to connect one.");
36935
- } else {
36936
- const pendingProviders = [
36937
- ...new Set(result6.data.results.filter((entry) => entry.status === "not-applicable").map((entry) => name(entry.providerId)))
36938
- ];
36939
- const subject = pendingProviders.length > 0 ? pendingProviders.join(" and ") : "Some integrations";
36940
- messages.push(`${prefix}${subject} have not produced enough attributable runtime evidence for ${name(harness)} yet. This is an evidence gap, not a finding that the setup is broken. If you do not use this agent on this machine, no action is required.`);
36941
- }
36942
- if (versionWarnings.length > 0) {
36943
- messages.push(prefix + "the installed version is newer than Token Harness\u2019s recorded compatibility sample; read-only checks can continue, but review the version before changing its integration.");
37136
+ }
37137
+ if (inventory.data !== null) {
37138
+ const fingerprint = stackFingerprint(inventory.data);
37139
+ this.verification = {
37140
+ fingerprint,
37141
+ report: {
37142
+ receiptId: null,
37143
+ appliedAt: null,
37144
+ results,
37145
+ healthyAtDeclaredTier: healthyAtDeclaredTier && present.length > 0
36944
37146
  }
36945
- }
36946
- if (inventory.data !== null) {
36947
- const fingerprint = stackFingerprint(inventory.data);
36948
- this.verification = {
36949
- fingerprint,
36950
- report: {
36951
- receiptId: null,
36952
- appliedAt: null,
36953
- results,
36954
- healthyAtDeclaredTier: healthyAtDeclaredTier && present.length > 0
36955
- }
36956
- };
36957
- this.stackBase = {
36958
- detections: [...inventory.data.providers],
36959
- metrics: this.stackBase?.metrics ?? null,
36960
- drift: this.stackBase?.drift ?? [],
36961
- fingerprint
36962
- };
36963
- } else {
36964
- this.verification = null;
36965
- }
36966
- const stack = this.stackSnapshot();
36967
- if (this.cached !== null)
36968
- this.cached.value = { ...this.cached.value, stack };
36969
- this.record("Integration checks completed. No settings changed.", ok ? "success" : "attention");
36970
- return {
36971
- ok,
36972
- title: ok ? healthyAtDeclaredTier ? "Integration checks passed" : "Configuration checks complete; runtime evidence pending" : "Integration checks need attention",
36973
- messages,
36974
- appliedPlans: 0,
36975
- stack
36976
37147
  };
36977
- });
37148
+ this.stackBase = {
37149
+ detections: [...inventory.data.providers],
37150
+ metrics: this.stackBase?.metrics ?? null,
37151
+ drift: this.stackBase?.drift ?? [],
37152
+ fingerprint
37153
+ };
37154
+ } else {
37155
+ this.verification = null;
37156
+ }
37157
+ const stack = this.stackSnapshot();
37158
+ if (this.cached !== null)
37159
+ this.cached.value = { ...this.cached.value, stack };
37160
+ this.record("Integration checks completed. No settings changed.", ok ? "success" : "attention");
37161
+ return {
37162
+ ok,
37163
+ title: ok ? healthyAtDeclaredTier ? "Integration checks passed" : "Configuration checks complete; runtime evidence pending" : "Integration checks need attention",
37164
+ messages,
37165
+ appliedPlans: 0,
37166
+ stack
37167
+ };
36978
37168
  }
36979
37169
  };
36980
37170
  }
@@ -38565,7 +38755,6 @@ var init_guided_capabilities_client = __esm({
38565
38755
  return element;
38566
38756
  };
38567
38757
  const originalFetch = window.fetch.bind(window);
38568
- const managedProviders = new Set(['rtk', 'harnesstrim']);
38569
38758
  const HELP = {
38570
38759
  'claude-effort': ['Change reasoning in Claude', 'Inside Claude Code, use /effort. Token Harness keeps difficult work above its quality floor.', '/effort'],
38571
38760
  'codex-effort': ['Change reasoning in Codex', 'Inside Codex, use /model to review model and reasoning settings.', '/model'],
@@ -38848,44 +39037,16 @@ var init_guided_capabilities_client = __esm({
38848
39037
  if (!root.children.length) root.append(node('p', 'Agent details appear after a supported coding agent is detected.', 'empty'));
38849
39038
  }
38850
39039
 
38851
- function renderRemovalControls(data) {
38852
- const root = $('managed-removal-actions');
38853
- if (!root) return;
38854
- root.replaceChildren();
38855
- const removable = (data.stack?.components || []).filter(component =>
38856
- managedProviders.has(component.providerId) && (component.managedByTokenHarness || component.configured),
38857
- );
38858
- if (!removable.length) {
38859
- root.append(node('p', 'No managed configuration is currently eligible for removal.', 'caption'));
38860
- return;
38861
- }
38862
- for (const component of removable) {
38863
- const row = node('div', undefined, 'maintenance-row');
38864
- const text = node('div');
38865
- const name = component.displayName || (component.providerId === 'rtk' ? 'RTK' : 'HarnessTrim');
38866
- text.append(
38867
- node('strong', name),
38868
- node('p', component.managedByTokenHarness
38869
- ? 'Review removal of Token Harness-owned integration changes.'
38870
- : 'Check whether Token Harness owns any removable changes. The provider installation remains user-owned.', 'caption'),
38871
- );
38872
- row.append(
38873
- text,
38874
- actionButton('Review removal', () => preview(
38875
- { action: 'remove', provider: component.providerId },
38876
- 'Review removal for ' + name,
38877
- 'Remove managed integration',
38878
- 'Integration removed',
38879
- ), 'secondary'),
38880
- );
38881
- root.append(row);
38882
- }
38883
- }
39040
+ window.tokenHarnessReviewRemoval = (provider, name) => preview(
39041
+ { action: 'remove', provider },
39042
+ 'Review removal for ' + name,
39043
+ 'Remove managed setup',
39044
+ 'Managed setup removed',
39045
+ );
38884
39046
 
38885
39047
  function consumeOverview(data) {
38886
39048
  if (!data || !Array.isArray(data.agents)) return;
38887
39049
  renderAgentCapabilities(data);
38888
- renderRemovalControls(data);
38889
39050
  }
38890
39051
 
38891
39052
  window.fetch = async (...args) => {
@@ -38964,8 +39125,8 @@ var init_guided_product_client = __esm({
38964
39125
  const count = value => new Intl.NumberFormat(undefined, { maximumFractionDigits: 1 }).format(value);
38965
39126
  const date = value => value ? new Date(value).toLocaleString() : 'not recorded';
38966
39127
  const VIEWS = {
38967
- dashboard: ['Overview', 'Your coding agents, optimization stack, health and measured results in one place.'],
38968
- results: ['Results', 'A dashboard of optimizer results, coding-app links, quality information, and recent activity.'],
39128
+ dashboard: ['Overview', 'Your setup, results and next steps.'],
39129
+ results: ['Results', 'See what changed and the evidence behind it.'],
38969
39130
  };
38970
39131
  const TOOL_INFO = {
38971
39132
  rtk: {
@@ -39014,6 +39175,8 @@ var init_guided_product_client = __esm({
39014
39175
  let selectedView = 'dashboard';
39015
39176
  let modalRun = 0;
39016
39177
  let pendingTicket = null;
39178
+ let updateCheckStarted = false;
39179
+ let latestUpdateCheck = null;
39017
39180
  const periodCache = new Map();
39018
39181
 
39019
39182
  async function request(path, body) {
@@ -39046,7 +39209,7 @@ var init_guided_product_client = __esm({
39046
39209
 
39047
39210
  function setBusy(value, applying = false) {
39048
39211
  busy = value;
39049
- document.querySelectorAll('[data-action],#refresh,#period').forEach(element => {
39212
+ document.querySelectorAll('[data-action],#refresh,#period,#evidence-filter,#evidence-type,#evidence-sort').forEach(element => {
39050
39213
  element.disabled = value;
39051
39214
  });
39052
39215
  $('live-status').textContent = value
@@ -39066,7 +39229,10 @@ var init_guided_product_client = __esm({
39066
39229
  $('view-title').textContent = VIEWS[view][0];
39067
39230
  $('view-description').textContent = VIEWS[view][1];
39068
39231
  if (view === 'results') loadActivity();
39069
- if (focus) $('tab-' + view).focus();
39232
+ if (focus) {
39233
+ $('tab-' + view).focus();
39234
+ $('main').scrollIntoView({ block: 'start' });
39235
+ }
39070
39236
  }
39071
39237
 
39072
39238
  function navigateButton(label, view, cls = 'secondary') {
@@ -39182,7 +39348,7 @@ var init_guided_product_client = __esm({
39182
39348
 
39183
39349
  function optimizerIds() {
39184
39350
  const ids = (current?.stack?.components || []).map(component => component.providerId).filter(Boolean);
39185
- return ids.length ? [...new Set(ids)] : Object.keys(TOOL_INFO);
39351
+ return [...new Set([...Object.keys(TOOL_INFO), ...ids])];
39186
39352
  }
39187
39353
 
39188
39354
  function configuredProviders() {
@@ -39269,7 +39435,7 @@ var init_guided_product_client = __esm({
39269
39435
  const quality = current?.value?.quality;
39270
39436
  if (quality?.state === 'regressed') return { value: 'Regression detected', detail: 'Savings claims are blocked until quality is recovered.', cls: 'warn' };
39271
39437
  if (quality?.state === 'preserved') return { value: 'Preserved', detail: count(quality.pairs) + ' paired benchmark(s) support this result.', cls: 'good' };
39272
- return { value: 'Not measured yet', detail: 'Quality is never inferred from token savings alone.', cls: '' };
39438
+ return { value: 'Not measured yet', detail: 'Quality needs paired benchmarks; output savings alone are not proof.', cls: '' };
39273
39439
  }
39274
39440
 
39275
39441
  function allowanceSummary() {
@@ -39281,7 +39447,7 @@ var init_guided_product_client = __esm({
39281
39447
  if (five?.state === 'measured' && five.savedPercent !== null) parts.push('5h ' + count(five.savedPercent) + '%');
39282
39448
  if (weekly?.state === 'measured' && weekly.savedPercent !== null) parts.push('7d ' + count(weekly.savedPercent) + '%');
39283
39449
  if (parts.length) return { value: parts.join(' · '), detail: 'Based only on authoritative paired allowance evidence.', cls: 'good' };
39284
- return { value: 'Not measured yet', detail: 'Plan savings appear only when before/after allowance evidence exists.', cls: '' };
39450
+ return { value: 'Not measured yet', detail: 'Needs paired before/after allowance readings.', cls: '' };
39285
39451
  }
39286
39452
 
39287
39453
  function metricCard(title, value, detail, cls = '') {
@@ -39307,9 +39473,20 @@ var init_guided_product_client = __esm({
39307
39473
  label: 'Needs attention',
39308
39474
  cls: 'warn',
39309
39475
  title: 'Measured quality needs attention',
39310
- detail: 'A paired benchmark favored the baseline. Token Harness is not crediting the affected savings.',
39476
+ detail: 'A paired benchmark favored the baseline. Affected savings are not credited.',
39311
39477
  action: 'results',
39312
39478
  };
39479
+ const routingAttention = agents.filter(agent => agent.promptRouting?.needsRepair ||
39480
+ (agent.promptRouting?.configured === true && ['untrusted', 'disabled', 'unknown'].includes(agent.promptRouting.enablement)));
39481
+ if (routingAttention.length)
39482
+ return {
39483
+ label: 'Routing action required',
39484
+ cls: 'warn',
39485
+ title: 'Automatic routing needs attention',
39486
+ detail: routingAttention.map(agent => agent.name + ': ' + (agent.promptRouting.detail ||
39487
+ (agent.promptRouting.enablement === 'untrusted' ? 'Trust the hook in /hooks, then submit a prompt.' : 'Review the hook status in the coding app.'))).join(' '),
39488
+ action: 'routing',
39489
+ };
39313
39490
  if (stack?.state === 'attention')
39314
39491
  return {
39315
39492
  label: 'Needs attention',
@@ -39322,8 +39499,8 @@ var init_guided_product_client = __esm({
39322
39499
  return {
39323
39500
  label: 'Setup available',
39324
39501
  cls: 'warn',
39325
- title: 'Your optimization stack has available setup options',
39326
- detail: 'Choose an optimizer and the coding apps to set it up for. Token Harness shows measured results separately from detected setup.',
39502
+ title: 'Connect your optimization stack',
39503
+ detail: 'Review the recommended optimizers for your coding apps.',
39327
39504
  action: 'configure',
39328
39505
  };
39329
39506
  const unavailable = baselineUnavailableAgents();
@@ -39332,7 +39509,7 @@ var init_guided_product_client = __esm({
39332
39509
  label: 'Setup unavailable',
39333
39510
  cls: '',
39334
39511
  title: 'No automatic optimizer setup is currently available',
39335
- detail: 'The installed providers do not currently expose a compatible managed connection for these coding agents. This is a capability limitation, not unfinished setup.',
39512
+ detail: 'The installed optimizers do not offer a compatible managed connection for these apps.',
39336
39513
  action: 'none',
39337
39514
  };
39338
39515
  if (!(current?.savings?.rows || []).length)
@@ -39340,14 +39517,14 @@ var init_guided_product_client = __esm({
39340
39517
  label: 'Setup detected',
39341
39518
  cls: 'good',
39342
39519
  title: 'Recommended setup is complete',
39343
- detail: 'Setup has been detected. This does not prove an optimizer ran or recorded a result; check the Results page for evidence linked to each agent.',
39520
+ detail: 'Use your coding apps normally. Results will show recorded activity; setup alone is not runtime proof.',
39344
39521
  action: 'results',
39345
39522
  };
39346
39523
  return {
39347
39524
  label: 'Ready',
39348
39525
  cls: 'good',
39349
39526
  title: 'Your setup has been checked',
39350
- detail: 'No setup action is required. The summary below shows which results Token Harness has actually recorded.',
39527
+ detail: 'No setup action required. Open Results to inspect recorded changes.',
39351
39528
  action: 'results',
39352
39529
  };
39353
39530
  }
@@ -39369,8 +39546,13 @@ var init_guided_product_client = __esm({
39369
39546
  const actions = node('div', undefined, 'inline-actions');
39370
39547
  if (assessment.action === 'verify') {
39371
39548
  actions.append(actionButton('Re-check health', () => readOnlyOperation('verify')));
39549
+ } else if (assessment.action === 'routing') {
39550
+ actions.append(actionButton('Review routing', () => $('coding-agents').scrollIntoView({ block: 'start' })));
39372
39551
  } else if (assessment.action === 'results') {
39373
- actions.append(navigateButton('View detailed results', 'results'));
39552
+ if (current?.value?.quality?.state === 'regressed')
39553
+ actions.append(navigateButton('Review quality evidence', 'results', ''));
39554
+ } else if (assessment.action === 'configure') {
39555
+ actions.append(actionButton('Review recommended setup', () => reviewSetup()));
39374
39556
  }
39375
39557
  if (actions.children.length) main.append(actions);
39376
39558
  $('dashboard-status').append(main, pill(assessment.label, assessment.cls));
@@ -39380,10 +39562,9 @@ var init_guided_product_client = __esm({
39380
39562
  const quality = qualitySummary();
39381
39563
  $('dashboard-metrics').replaceChildren(
39382
39564
  reduction
39383
- ? metricCard('Measured output', reduction.impact.headline, reduction.provider + ' · ' + reduction.measurement, 'positive')
39384
- : metricCard('Measured output', 'No result yet', 'Missing measurements are not reported as zero savings.'),
39565
+ ? metricCard('Recorded output', reduction.impact.headline, reduction.provider + ' · ' + reduction.measurement + ' · changed outputs only', 'positive')
39566
+ : metricCard('Recorded output', 'No result yet', 'Use a connected app to start recording results.'),
39385
39567
  metricCard('5h / 7d allowance', allowance.value, allowance.detail, allowance.cls),
39386
- metricCard('API cost', 'Not measured yet', 'Requires billed-token evidence and a verified price basis.'),
39387
39568
  metricCard('Quality', quality.value, quality.detail, quality.cls),
39388
39569
  );
39389
39570
  }
@@ -39464,7 +39645,7 @@ var init_guided_product_client = __esm({
39464
39645
  ' can be set up from the Optimization stack below.'
39465
39646
  : baseline.state === 'unavailable'
39466
39647
  ? 'No managed baseline connection is currently available for this agent.'
39467
- : 'This card shows detected setup. It does not confirm that an optimizer ran or recorded results.';
39648
+ : 'Optimizer setup detected. Recorded activity appears in Results.';
39468
39649
  card.append(head, node('p', detail));
39469
39650
  card.append(
39470
39651
  node(
@@ -39476,27 +39657,40 @@ var init_guided_product_client = __esm({
39476
39657
  ),
39477
39658
  );
39478
39659
  const routing = agent.promptRouting;
39660
+ const routingConfigured = routing?.configured === true || routing?.enablement === 'enabled' || routing?.enablement === 'untrusted' || (!routing?.enablement && routing?.state === 'managed');
39661
+ const routingObserved = routing?.verificationTier === 'runtime-observed';
39662
+ const routingLabel = routingObserved ? 'Active · callback seen' : routing?.needsRepair ? 'Repair required' : routing?.enablement === 'untrusted' ? 'Trust required' : routing?.enablement === 'disabled' ? 'Hooks disabled' : routing?.configured !== false && routing?.enablement === 'unknown' ? 'Authorization unknown' : routingConfigured ? 'Enabled · awaiting callback' : routing?.state === 'external' ? 'Managed elsewhere' : 'Not enabled';
39479
39663
  const routingCard = node('div', undefined, 'routing-feature');
39480
39664
  const routingHead = node('div', undefined, 'tool-head');
39481
39665
  routingHead.append(
39482
39666
  node('strong', 'Automatic prompt routing'),
39483
- pill(routing?.label || 'Not verified', routing?.state === 'managed' ? 'good' : routing?.state === 'absent' ? '' : 'warn'),
39667
+ pill(routingLabel, routingObserved ? 'good' : routingConfigured || routing?.needsRepair ? 'warn' : ''),
39484
39668
  );
39485
39669
  routingCard.append(
39486
39670
  routingHead,
39487
39671
  node(
39488
39672
  'p',
39489
- routing?.detail || 'A native hook can inject the routing policy on every submitted prompt. Setup and runtime activity are tracked separately.',
39673
+ routing?.detail || (routing?.enablement === 'untrusted'
39674
+ ? 'Open /hooks in Codex and trust this hook. Then submit a prompt to verify the callback.'
39675
+ : routing?.needsRepair
39676
+ ? routing.detail || 'Review and repair the Token Harness routing hook.'
39677
+ : routing?.enablement === 'unknown'
39678
+ ? routing.detail || 'Token Harness could not determine whether this hook is authorized.'
39679
+ : routingConfigured
39680
+ ? routingObserved ? 'Automatic routing is running on submitted prompts.' : 'Configured; submit a prompt and Token Harness will show the callback when it arrives.'
39681
+ : 'Enable once. The native hook then checks every submitted prompt automatically.'),
39490
39682
  'caption',
39491
39683
  ),
39492
39684
  );
39493
39685
  const routingActions = node('div', undefined, 'inline-actions');
39494
- if (routing?.state === 'absent') {
39495
- routingActions.append(actionButton('Enable routing', () => reviewPromptRouting(agent.id, true), 'secondary'));
39496
- } else if (routing?.state === 'managed') {
39497
- routingActions.append(actionButton('Disable routing', () => reviewPromptRouting(agent.id, false), 'secondary'));
39686
+ if (routing?.needsRepair) {
39687
+ routingActions.append(actionButton('Repair routing', () => reviewPromptRouting(agent.id, true), 'secondary'));
39498
39688
  } else if (routing?.state === 'external') {
39499
39689
  routingActions.append(node('span', 'Managed elsewhere · left untouched', 'caption'));
39690
+ } else if (!routingConfigured) {
39691
+ routingActions.append(actionButton('Enable routing', () => reviewPromptRouting(agent.id, true), 'secondary'));
39692
+ } else if (routingConfigured) {
39693
+ routingActions.append(actionButton('Disable routing', () => reviewPromptRouting(agent.id, false), 'secondary'));
39500
39694
  }
39501
39695
  if (routingActions.children.length) routingCard.append(routingActions);
39502
39696
  card.append(routingCard);
@@ -39622,13 +39816,17 @@ var init_guided_product_client = __esm({
39622
39816
  if (!(data.changes || []).length)
39623
39817
  $('modal-content').append(messageBox('No change proposed', (data.notices || []).join(' ') || 'The current routing state or ownership evidence does not support a safe change.'));
39624
39818
  for (const notice of data.notices || []) $('modal-content').append(node('p', notice, 'notice-row'));
39625
- if (data.ticket) $('modal-content').append(messageBox(
39626
- agentId === 'codex' ? 'Codex trust step' : 'When it takes effect',
39627
- agentId === 'codex'
39628
- ? 'After Apply, review and trust the UserPromptSubmit hook in Codex using /hooks. Until a callback is observed, the dashboard will show it as configured but not runtime verified.'
39629
- : 'After Apply, start a new Claude Code session. The dashboard will show configured state first and runtime activity after the next prompt callback.',
39630
- 'safe',
39631
- ));
39819
+ if (data.ticket) {
39820
+ const observed = activeAgents().find(agent => agent.id === agentId)?.promptRouting;
39821
+ const needsTrust = agentId === 'codex' && observed?.enablement === 'untrusted';
39822
+ $('modal-content').append(messageBox(
39823
+ needsTrust ? 'Trust required' : 'When it takes effect',
39824
+ needsTrust
39825
+ ? 'Open /hooks in Codex and trust this hook. Then send a prompt.'
39826
+ : 'Send a prompt in a new session. Token Harness will show the callback when it arrives.',
39827
+ 'safe',
39828
+ ));
39829
+ }
39632
39830
  $('modal-actions').replaceChildren(modalClose(data.ticket ? 'Cancel' : 'Done'));
39633
39831
  if (data.ticket) $('modal-actions').append(actionButton(enabled ? 'Apply routing hook' : 'Remove owned routing hook', () => applyTicket(data.ticket)));
39634
39832
  })
@@ -39724,6 +39922,12 @@ var init_guided_product_client = __esm({
39724
39922
  await ensureSession();
39725
39923
  const result = await request('/api/apply', { ticket });
39726
39924
  if (run !== modalRun) return;
39925
+ if (result.restartRequired) {
39926
+ $('modal-title').textContent = result.title || 'Token Harness update installed';
39927
+ $('modal-content').replaceChildren(messageBox('Restart to finish', (result.messages || []).join(' ') || 'Token Harness must restart before it can check the updated installation.', 'safe'));
39928
+ $('modal-actions').replaceChildren(modalClose('Later'), actionButton('Restart and re-check', restartAndRecheck));
39929
+ return;
39930
+ }
39727
39931
  $('modal-title').textContent = result.title || (result.ok ? 'Setup completed' : 'Setup needs attention');
39728
39932
  $('modal-content').replaceChildren(
39729
39933
  messageBox(result.ok ? 'Applied' : 'Needs attention', (result.messages || []).join(' '), result.ok ? 'safe' : 'warn'),
@@ -39768,6 +39972,24 @@ var init_guided_product_client = __esm({
39768
39972
  }
39769
39973
  }
39770
39974
 
39975
+ async function restartAndRecheck() {
39976
+ if (busy) return;
39977
+ setBusy(true, true);
39978
+ $('modal-content').replaceChildren(progress('Restarting Token Harness', 'The updated app will run its health check when it opens again.'));
39979
+ $('modal-actions').replaceChildren(modalClose('Restarting…', true));
39980
+ try {
39981
+ await ensureSession();
39982
+ const result = await request('/api/restart', {});
39983
+ if (!result.ok) throw new Error((result.messages || []).join(' ') || 'Restart did not complete.');
39984
+ setTimeout(() => window.location.reload(), 700);
39985
+ } catch (error) {
39986
+ $('modal-error').textContent = error.message;
39987
+ $('modal-error').hidden = false;
39988
+ $('modal-actions').replaceChildren(modalClose('Close'));
39989
+ setBusy(false, false);
39990
+ }
39991
+ }
39992
+
39771
39993
  function connectionPresentation(target) {
39772
39994
  if (!target) return { label: 'Not targeted', cls: '' };
39773
39995
  if (target.state === 'connected') return { label: 'Setup detected', cls: 'good' };
@@ -39776,6 +39998,26 @@ var init_guided_product_client = __esm({
39776
39998
  return { label: 'Not applicable', cls: '' };
39777
39999
  }
39778
40000
 
40001
+ function mcptoonInstallOptions() {
40002
+ modal('Install mcptoon prerequisites');
40003
+ $('modal-content').append(
40004
+ node('p', 'Token Harness can install mcptoon after pipx or uv is available. Install one, then Refresh and choose Install & connect.'),
40005
+ );
40006
+ const links = node('div', undefined, 'inline-actions');
40007
+ for (const [label, href] of [
40008
+ ['pipx installation', 'https://pipx.pypa.io/stable/installation/'],
40009
+ ['uv installation', 'https://docs.astral.sh/uv/getting-started/installation/'],
40010
+ ]) {
40011
+ const link = node('a', label, 'button secondary');
40012
+ link.href = href;
40013
+ link.target = '_blank';
40014
+ link.rel = 'noreferrer noopener';
40015
+ links.append(link);
40016
+ }
40017
+ $('modal-content').append(links);
40018
+ $('modal-actions').append(modalClose('Done'));
40019
+ }
40020
+
39779
40021
  function renderConnectionOverview() {
39780
40022
  const root = $('connection-overview');
39781
40023
  if (!root) return;
@@ -39791,7 +40033,7 @@ var init_guided_product_client = __esm({
39791
40033
  const summaryText = node('div');
39792
40034
  summaryText.append(
39793
40035
  node('strong', ids.length + ' optimizer' + (ids.length === 1 ? '' : 's') + ' · ' + agents.length + ' coding agent' + (agents.length === 1 ? '' : 's')),
39794
- node('p', 'This matrix shows where setup was detected, not proof that an optimizer ran. Measured results are shown separately on the Results page.', 'caption'),
40036
+ node('p', 'RTK + HarnessTrim are the recommended baseline. Other optimizers are optional.', 'caption'),
39795
40037
  );
39796
40038
  summary.append(summaryText);
39797
40039
  const baselineActionable = ['rtk', 'harnesstrim'].some(id =>
@@ -39827,7 +40069,7 @@ var init_guided_product_client = __esm({
39827
40069
  const target = setupTarget(agent.id, id);
39828
40070
  const state = connectionPresentation(target);
39829
40071
  const cell = node('div', undefined, 'connection-cell');
39830
- cell.append(pill(state.label, state.cls));
40072
+ cell.append(node('span', agent.name, 'connection-app-label'), pill(state.label, state.cls));
39831
40073
  row.append(cell);
39832
40074
  actionable ||= target?.state === 'actionable';
39833
40075
  }
@@ -39839,8 +40081,18 @@ var init_guided_product_client = __esm({
39839
40081
  () => reviewSetup(id),
39840
40082
  'secondary',
39841
40083
  ),
39842
- );
39843
- else action.append(node('span', 'No action', 'caption'));
40084
+ );
40085
+ const mcptoonUnavailable = id === 'mcptoon' && agents.some(agent => setupTarget(agent.id, id)?.state === 'unavailable');
40086
+ if (mcptoonUnavailable)
40087
+ action.append(actionButton('Installation options', mcptoonInstallOptions, 'secondary'));
40088
+ if (component?.managedByTokenHarness || component?.configured) {
40089
+ const remove = actionButton('Remove managed setup', () => {
40090
+ window.tokenHarnessReviewRemoval?.(id, info.name);
40091
+ }, 'text-button');
40092
+ remove.disabled = busy || typeof window.tokenHarnessReviewRemoval !== 'function';
40093
+ action.append(remove);
40094
+ }
40095
+ if (!action.children.length) action.append(node('span', 'No action', 'caption'));
39844
40096
  row.append(action);
39845
40097
  table.append(row);
39846
40098
  }
@@ -39963,7 +40215,7 @@ var init_guided_product_client = __esm({
39963
40215
  messageBox('Optional candidate lifecycle', 'This is an explicit evaluation setup, not production-stack setup. Token Harness does not silently install or activate candidates.'),
39964
40216
  );
39965
40217
  if (candidate.id === 'mcptoon')
39966
- $('modal-content').append(messageBox('Prerequisites stay yours', 'An approved setup may install the exact reviewed mcptoon build only through an already-installed pipx. Token Harness does not install Python, pipx or administrator prerequisites.'));
40218
+ $('modal-content').append(messageBox('Prerequisites stay yours', 'An approved setup may install the exact reviewed mcptoon build through an already-installed pipx or uv. Token Harness does not install Python, pipx, uv or administrator prerequisites.'));
39967
40219
  if (candidate.id === 'gitnexus')
39968
40220
  $('modal-content').append(messageBox('Index stays yours', 'GitNexus must already be installed on the exact reviewed row. Token Harness can register only the reviewed Claude MCP entry; it never creates or refreshes the repository index.'));
39969
40221
  const agents = activeAgents().filter(agent => supported.includes(agent.id));
@@ -40189,7 +40441,7 @@ var init_guided_product_client = __esm({
40189
40441
  'p',
40190
40442
  current?.stack?.state === 'attention'
40191
40443
  ? 'Something changed or could not be verified. Re-check the configured integrations for details.'
40192
- : 'Setup is already complete. Re-check only when troubleshooting or after external changes.',
40444
+ : 'Re-check integrations after external changes or when troubleshooting.',
40193
40445
  'caption',
40194
40446
  ),
40195
40447
  );
@@ -40213,7 +40465,7 @@ var init_guided_product_client = __esm({
40213
40465
  'p',
40214
40466
  available.length
40215
40467
  ? available.map(component => (TOOL_INFO[component.providerId]?.name || component.providerId) + ' has an update ready.').join(' ')
40216
- : 'Checks Token Harness and installed optimizer versions. If an update is available, install it from the same dialog; restart this app after updating Token Harness.',
40468
+ : 'Check available versions and review updates before installing.',
40217
40469
  'caption',
40218
40470
  ),
40219
40471
  );
@@ -40243,44 +40495,197 @@ var init_guided_product_client = __esm({
40243
40495
  renderMaintenance();
40244
40496
  }
40245
40497
 
40246
- function renderSavings() {
40247
- const root = $('result-savings');
40248
- root.replaceChildren();
40249
- const rows = current?.savings?.rows || [];
40250
- if (!rows.length) {
40251
- root.append(sectionEmpty('No measured optimizer output has been recorded for this period. Missing data is not zero savings.'));
40252
- return;
40498
+ function addEvidenceRow(body, type, name, scope, signals, amount, sections) {
40499
+ const row = node('li', undefined, 'evidence-item');
40500
+ row.dataset.type = type;
40501
+ row.dataset.name = name.toLocaleLowerCase();
40502
+ row.dataset.amount = String(amount || 0);
40503
+ const disclosure = node('details', undefined, 'evidence-disclosure');
40504
+ disclosure.dataset.key = type + ':' + name;
40505
+ const summary = node('summary', undefined, 'evidence-summary');
40506
+ const identity = node('span', undefined, 'evidence-identity');
40507
+ const types = { optimizer: 'Optimizer', routing: 'Routing', harness: 'Coding app', candidate: 'Experiment' };
40508
+ identity.append(node('span', types[type], 'evidence-kind'), node('strong', name), node('span', scope, 'caption'));
40509
+ const results = node('span', undefined, 'evidence-signals');
40510
+ for (const signal of signals) {
40511
+ const result = node('span', undefined, 'evidence-signal ' + (signal.tone || ''));
40512
+ result.append(node('strong', signal.value), node('span', signal.label, 'caption'));
40513
+ results.append(result);
40514
+ }
40515
+ const cue = node('span', 'Details', 'evidence-cue');
40516
+ const chevron = node('span', '›', 'evidence-chevron');
40517
+ chevron.setAttribute('aria-hidden', 'true');
40518
+ cue.append(chevron);
40519
+ summary.append(identity, results, cue);
40520
+ const detailBody = node('div', undefined, 'evidence-detail-body');
40521
+ detailBody.append(...sections);
40522
+ disclosure.append(summary, detailBody);
40523
+ row.append(disclosure);
40524
+ // Search includes provenance, so a class/unit or linked app can be found while collapsed.
40525
+ row.dataset.search = [type, types[type], name, scope, row.textContent].join(' ').toLocaleLowerCase();
40526
+ body.append(row);
40527
+ return row;
40528
+ }
40529
+
40530
+ function evidenceSection(title, facts = [], note = '') {
40531
+ const section = node('section', undefined, 'evidence-section');
40532
+ section.append(node('h3', title));
40533
+ if (facts.length) {
40534
+ const list = node('dl', undefined, 'evidence-fact-grid');
40535
+ for (const [label, value] of facts) {
40536
+ const fact = node('div');
40537
+ fact.append(node('dt', label), node('dd', value));
40538
+ list.append(fact);
40539
+ }
40540
+ section.append(list);
40541
+ }
40542
+ if (note) section.append(node('p', note, 'caption'));
40543
+ return section;
40544
+ }
40545
+
40546
+ function optimizerSignal(row, includeProvider = false) {
40547
+ const impact = row.impact;
40548
+ const value = impact && impact.kind !== 'unavailable'
40549
+ ? impact.headline
40550
+ : count(Math.abs(row.saved)) + ' ' + row.unit + (row.saved < 0 ? ' added' : row.saved > 0 ? ' saved' : ' net change');
40551
+ return {
40552
+ value,
40553
+ label: (includeProvider ? row.provider + ' · ' : '') + row.measurement + ' · ' + row.unit,
40554
+ tone: impact?.kind === 'growth' ? 'warn' : impact?.kind === 'reduction' ? 'good' : '',
40555
+ };
40556
+ }
40557
+
40558
+ function optimizerEvidenceDetail(row, includeProvider = false) {
40559
+ const volume = value => value === null || value === undefined ? 'Not recorded' : count(value) + ' ' + row.unit;
40560
+ return evidenceSection((includeProvider ? row.provider + ' · ' : '') + row.measurement + ' · ' + row.unit, [
40561
+ ['Before', volume(row.before)],
40562
+ ['After', volume(row.after)],
40563
+ [row.saved < 0 ? 'Added' : 'Saved', volume(Math.abs(row.saved))],
40564
+ ['Changed outputs', count(row.operations)],
40565
+ ['Recorded app', row.agents?.length ? row.agents.join(', ') : 'Not attributed'],
40566
+ ], (row.impact?.detail || 'A comparable before/after pair is needed to report a percentage.') +
40567
+ (!row.agents?.length ? ' These records do not identify which coding app ran the command.' : ''));
40568
+ }
40569
+
40570
+ function routingDetails(agent) {
40571
+ const routing = agent.promptRouting || {};
40572
+ const lines = [];
40573
+ const tier = routing.verificationTier;
40574
+ if (routing.enablement === 'untrusted') lines.push('Action required: open /hooks in Codex and trust this hook, then submit a prompt.');
40575
+ else if (tier === 'runtime-observed') lines.push('Runtime callback observed. Automatic routing runs on submitted prompts.');
40576
+ else if (routing.configured !== false && routing.enablement === 'unknown') lines.push('Authorization is unknown; check the hook status in the coding app.');
40577
+ else if (routing.enablement === 'disabled') lines.push('Hooks are disabled for this coding app.');
40578
+ else if (routing.enablement === 'enabled' || (!routing.enablement && routing.state === 'managed')) lines.push('Configured; waiting for the first runtime callback after a prompt.');
40579
+ else if (routing.state === 'external') lines.push('Routing is managed elsewhere; Token Harness leaves it unchanged.');
40580
+ else lines.push('Automatic routing is not enabled for this coding app.');
40581
+ const facts = [['Verification', tier === 'runtime-observed' ? 'Runtime callback observed' : tier === 'config-only' ? 'Configuration only' : 'Not verified']];
40582
+ if (Number.isFinite(routing.promptSubmissions)) facts.push(['Prompt callbacks', count(routing.promptSubmissions)]);
40583
+ if (Number.isFinite(routing.subagentsStarted)) facts.push(['Subagents started', count(routing.subagentsStarted)]);
40584
+ if (Number.isFinite(routing.subagentsStopped)) facts.push(['Subagents stopped', count(routing.subagentsStopped)]);
40585
+ if (routing.reportedModels?.length) facts.push(['Reported models', routing.reportedModels.join(', ')]);
40586
+ if (routing.lastObservedAt) facts.push(['Last callback', date(routing.lastObservedAt)]);
40587
+ return evidenceSection(agent.name + ' · routing activity', facts, lines[0]);
40588
+ }
40589
+
40590
+ function renderEvidence() {
40591
+ const body = $('result-evidence');
40592
+ const openKeys = new Set([...body.querySelectorAll('details[open]')].map(item => item.dataset.key));
40593
+ body.replaceChildren();
40594
+ const savings = current?.savings?.rows || [];
40595
+ for (const id of optimizerIds()) {
40596
+ const info = optimizerInfo(id);
40597
+ const component = managedComponent(id);
40598
+ const measured = savings.filter(row => row.providerId === id);
40599
+ const scope = component?.configuredHarnesses?.length
40600
+ ? 'Setup: ' + component.configuredHarnesses.map(agentName).join(', ')
40601
+ : 'No setup detected';
40602
+ const signals = measured.length
40603
+ ? measured.map(row => optimizerSignal(row))
40604
+ : [{ value: 'No results yet', label: 'No output recorded for this period' }];
40605
+ const sections = measured.map(row => optimizerEvidenceDetail(row));
40606
+ if (!measured.length) {
40607
+ const nextStep = evidenceSection('Start recording results', [], component?.configured
40608
+ ? 'Use a connected coding app normally, then Refresh. Detected setup alone does not prove that the optimizer ran.'
40609
+ : 'Review this optimizer in Overview to see available connections.');
40610
+ nextStep.append(navigateButton('Open Overview', 'dashboard'));
40611
+ sections.push(nextStep);
40612
+ }
40613
+ addEvidenceRow(body, 'optimizer', info.name, scope, signals, measured.length, sections);
40253
40614
  }
40615
+
40616
+ const routing = current?.value?.routing;
40617
+ const routingAgents = activeAgents();
40618
+ const blocked = routing?.state === 'blocked-by-quality';
40619
+ const routeSignals = [];
40620
+ if (blocked) routeSignals.push({ value: 'Not credited', label: 'Quality gate did not pass', tone: 'warn' });
40621
+ else {
40622
+ if (routing?.savedLocalTokens !== null && routing?.savedLocalTokens !== undefined)
40623
+ routeSignals.push({
40624
+ value: count(Math.abs(routing.savedLocalTokens)) + (routing.savedLocalTokens < 0 ? ' tokens added' : ' tokens saved'),
40625
+ label: 'Paired end-to-end local usage',
40626
+ tone: routing.savedLocalTokens < 0 ? 'warn' : routing.savedLocalTokens > 0 ? 'good' : '',
40627
+ });
40628
+ for (const [key, label] of [['allowance5h', '5h allowance'], ['allowance7d', '7d allowance']]) {
40629
+ const evidence = routing?.[key];
40630
+ if (evidence?.state === 'measured' && evidence.savedPercent !== null && evidence.savedPercent !== undefined)
40631
+ routeSignals.push({ value: count(evidence.savedPercent) + '%', label: label + ' saved · paired evidence', tone: evidence.savedPercent < 0 ? 'warn' : 'good' });
40632
+ }
40633
+ if (!routeSignals.length) routeSignals.push({ value: 'Not measured yet', label: 'Needs paired, quality-passed runs' });
40634
+ }
40635
+ const routingSections = [evidenceSection('Savings verification', [['Quality-passed pairs', count(routing?.pairs || 0)]],
40636
+ blocked ? 'A quality regression blocks the savings claim.' : 'Callback activity proves the hook ran. Savings require paired runs with a passing quality gate.')];
40637
+ for (const agent of routingAgents)
40638
+ routingSections.push(routingDetails(agent));
40639
+ addEvidenceRow(body, 'routing', 'Automatic prompt routing', routingAgents.map(agent => agent.name).join(', ') || 'No coding app detected', routeSignals, routing?.pairs || 0, routingSections);
40640
+
40641
+ for (const agent of routingAgents) {
40642
+ const linked = savings.filter(row => row.harnesses?.includes(agent.id));
40643
+ const configured = configuredProviders().filter(component => component.configuredHarnesses?.includes(agent.id)).map(component => optimizerInfo(component.providerId).name);
40644
+ const sections = [evidenceSection('App attribution', [['Detected setup', configured.join(', ') || 'None']],
40645
+ linked.length ? 'These are the same optimizer records shown above, linked to this app. They are not additional savings.' : 'No optimizer record identifies this app for the selected period. Unattributed records stay under their optimizer.')];
40646
+ sections.push(...linked.map(row => optimizerEvidenceDetail(row, true)));
40647
+ addEvidenceRow(body, 'harness', agent.name, agent.version ? 'v' + agent.version : 'Version unavailable',
40648
+ linked.length ? linked.map(row => optimizerSignal(row, true)) : [{ value: 'No linked results', label: 'No output attributed to this app' }], linked.length, sections);
40649
+ }
40650
+
40651
+ for (const item of current?.value?.candidates || []) {
40652
+ if (!(item.pairs > 0)) continue;
40653
+ const candidate = (current?.optimizationCandidates || []).find(entry => entry.id === item.candidateId);
40654
+ const name = candidate?.name || item.candidateId;
40655
+ addEvidenceRow(body, 'candidate', name, 'Experimental', [{ value: count(item.pairs) + ' paired results', label: 'Evaluation evidence' }], item.pairs, [
40656
+ evidenceSection('Paired evaluation', [
40657
+ ['Optimized better', count(item.optimizedBetter || 0)],
40658
+ ['Baseline better', count(item.baselineBetter || 0)],
40659
+ ], 'Evaluation does not automatically promote or activate this optimizer.'),
40660
+ ]);
40661
+ }
40662
+ for (const details of body.querySelectorAll('details')) details.open = openKeys.has(details.dataset.key);
40663
+ applyEvidenceFilters();
40664
+ }
40665
+
40666
+ function applyEvidenceFilters() {
40667
+ const body = $('result-evidence');
40668
+ if (!body) return;
40669
+ const filter = $('evidence-filter').value.trim().toLocaleLowerCase();
40670
+ const type = $('evidence-type').value;
40671
+ const sort = $('evidence-sort').value;
40672
+ const rows = [...body.children].filter(row => row.dataset.type);
40673
+ const sourceOrder = { optimizer: 0, routing: 1, harness: 2, candidate: 3 };
40674
+ rows.sort((a, b) => sort === 'evidence'
40675
+ ? Number(Number(b.dataset.amount) > 0) - Number(Number(a.dataset.amount) > 0)
40676
+ || sourceOrder[a.dataset.type] - sourceOrder[b.dataset.type]
40677
+ || Number(b.dataset.amount) - Number(a.dataset.amount) || a.dataset.name.localeCompare(b.dataset.name)
40678
+ : sort === 'type'
40679
+ ? a.dataset.type.localeCompare(b.dataset.type) || a.dataset.name.localeCompare(b.dataset.name)
40680
+ : a.dataset.name.localeCompare(b.dataset.name));
40254
40681
  for (const row of rows) {
40255
- const card = node('article', undefined, 'evidence-row');
40256
- const head = node('div', undefined, 'evidence-head');
40257
- head.append(node('h3', row.provider), pill(row.measurement));
40258
- card.append(head, node('strong', row.impact?.headline || count(row.saved) + ' ' + row.unit, 'evidence-value'), node('p', row.impact?.detail || 'Recorded optimization output.'));
40259
- const facts = node('dl', undefined, 'evidence-facts');
40260
- const values = [
40261
- ['Recorded change', row.before !== null && row.after !== null ? count(row.before) + ' → ' + count(row.after) + ' ' + row.unit : count(Math.abs(row.saved)) + ' ' + row.unit],
40262
- ['Operations', count(row.operations)],
40263
- ['Coding agent', row.agents?.length ? row.agents.join(', ') : 'Not linked to an agent'],
40264
- ];
40265
- for (const [label, value] of values) {
40266
- const wrap = node('div');
40267
- wrap.append(node('dt', label), node('dd', value));
40268
- facts.append(wrap);
40269
- }
40270
- card.append(facts);
40271
- if (!row.agents?.length) {
40272
- card.append(
40273
- node(
40274
- 'p',
40275
- row.providerId === 'rtk'
40276
- ? 'RTK records these reductions but does not record whether Codex or Claude ran each command. The result is real, but Token Harness cannot assign it to either agent.'
40277
- : 'The source did not include a coding-agent identity, so Token Harness keeps this result unassigned.',
40278
- 'caption',
40279
- ),
40280
- );
40281
- }
40282
- root.append(card);
40682
+ row.hidden = !((type === 'all' || row.dataset.type === type) && (!filter || row.dataset.search.includes(filter)));
40683
+ body.append(row);
40283
40684
  }
40685
+ const visible = rows.filter(row => !row.hidden).length;
40686
+ $('evidence-count').textContent = visible + ' of ' + rows.length + ' sources';
40687
+ $('evidence-empty').hidden = visible > 0;
40688
+ $('evidence-reset').hidden = !filter && type === 'all';
40284
40689
  }
40285
40690
 
40286
40691
  function measurementHelp() {
@@ -40295,191 +40700,47 @@ var init_guided_product_client = __esm({
40295
40700
  $('modal-actions').append(modalClose('Done'));
40296
40701
  }
40297
40702
 
40298
- function renderCandidateResults() {
40299
- const root = $('candidate-results');
40300
- root.replaceChildren();
40301
- const evidence = current?.value?.candidates || [];
40302
- if (!evidence.some(item => item.pairs > 0)) {
40303
- root.append(sectionEmpty('No experimental candidate has completed paired evidence yet. Experimental tools are optional and do not affect managed setup.'));
40304
- return;
40305
- }
40306
- for (const item of evidence.filter(entry => entry.pairs > 0)) {
40307
- const candidate = EXPERIMENTAL.find(entry => entry.id === item.candidateId);
40308
- if (!candidate) continue;
40309
- const card = node('article', undefined, 'evidence-row');
40310
- card.append(node('h3', candidate.name), node('strong', count(item.pairs) + ' paired result(s)', 'evidence-value'));
40311
- card.append(node('p', count(item.optimizedBetter || 0) + ' optimized better · ' + count(item.baselineBetter || 0) + ' baseline better. This is evaluation evidence, not automatic promotion.'));
40312
- root.append(card);
40313
- }
40314
- }
40315
-
40316
- function renderResultOptimizers() {
40317
- const root = $('result-optimizers');
40318
- if (!root) return;
40319
- root.replaceChildren();
40320
- const rows = current?.savings?.rows || [];
40321
- for (const id of optimizerIds()) {
40322
- const component = managedComponent(id);
40323
- const info = optimizerInfo(id);
40324
- const state = componentState(id, component);
40325
- const card = node('article', undefined, 'tool-card result-overview-card');
40326
- const head = node('div', undefined, 'tool-head');
40327
- head.append(node('h3', info.name), pill(state.label, state.cls));
40328
- card.append(head, node('p', info.role));
40329
- const facts = node('div', undefined, 'tool-facts');
40330
- facts.append(
40331
- node('span', 'Setup detected for'),
40332
- node('strong', component?.configuredHarnesses?.length ? component.configuredHarnesses.map(agentName).join(', ') : 'No detected agent'),
40333
- );
40334
- const measured = rows.filter(row => row.providerId === id);
40335
- card.append(facts);
40336
- if (!measured.length) {
40337
- card.append(
40338
- node(
40339
- 'p',
40340
- component?.configured
40341
- ? 'Setup is detected, but no result was recorded in the selected period.'
40342
- : 'No result was recorded for this optimizer in the selected period.',
40343
- 'caption',
40344
- ),
40345
- );
40346
- } else {
40347
- for (const row of measured) {
40348
- const evidence = node('div', undefined, 'result-signal');
40349
- evidence.append(
40350
- node('span', row.measurement, 'caption'),
40351
- node('strong', row.impact?.headline || count(row.saved) + ' ' + row.unit),
40352
- node('span', count(row.operations) + ' operation' + (row.operations === 1 ? '' : 's'), 'caption'),
40353
- );
40354
- card.append(evidence);
40355
- }
40356
- }
40357
- root.append(card);
40358
- }
40359
- }
40360
-
40361
- function renderResultAgents() {
40362
- const root = $('result-agents');
40363
- if (!root) return;
40364
- root.replaceChildren();
40365
- const rows = current?.savings?.rows || [];
40366
- if (!activeAgents().length) {
40367
- root.append(sectionEmpty('No supported coding agent is currently detected.'));
40368
- return;
40369
- }
40370
- for (const agent of activeAgents()) {
40371
- const setupDetected = configuredProviders().filter(component =>
40372
- component.configuredHarnesses?.includes(agent.id),
40373
- );
40374
- const measured = rows.filter(row => row.harnesses?.includes(agent.id));
40375
- const rtkUnattributed = rows.some(row =>
40376
- row.providerId === 'rtk' && !row.agents?.length,
40377
- );
40378
- const notes = [];
40379
- if (
40380
- setupDetected.some(component => component.providerId === 'rtk') &&
40381
- !measured.some(row => row.providerId === 'rtk')
40382
- ) {
40383
- notes.push(
40384
- rtkUnattributed
40385
- ? 'RTK has saved command-output data, but its history does not say whether Codex or Claude ran each command. Token Harness keeps those results under RTK instead of guessing.'
40386
- : 'RTK setup is detected, but no RTK result can be linked to this agent in the selected period.',
40387
- );
40388
- }
40389
- if (
40390
- setupDetected.some(component => component.providerId === 'harnesstrim') &&
40391
- !measured.some(row => row.providerId === 'harnesstrim')
40392
- ) {
40393
- notes.push(
40394
- 'HarnessTrim setup is detected, but no HarnessTrim result is linked to this app in the selected period. Setup alone does not mean it was used.',
40395
- );
40396
- }
40397
- if (!setupDetected.length && !measured.length) {
40398
- notes.push('No optimizer setup or agent-linked result was found for this coding app.');
40399
- }
40400
- const card = node('article', undefined, 'tool-card result-overview-card');
40401
- const head = node('div', undefined, 'tool-head');
40402
- head.append(node('h3', agent.name), pill(setupDetected.length ? 'Setup detected' : 'No setup', setupDetected.length ? 'good' : ''));
40403
- card.append(
40404
- head,
40405
- node('p', agent.version ? 'v' + agent.version : 'Version unavailable', 'caption'),
40406
- );
40407
- const facts = node('div', undefined, 'tool-facts');
40408
- facts.append(
40409
- node('span', 'Setup found'),
40410
- node('strong', setupDetected.length ? setupDetected.map(component => optimizerInfo(component.providerId).name).join(', ') : 'None'),
40411
- node('span', 'Results linked to this agent'),
40412
- node('strong', measured.length ? measured.map(row => row.provider).join(', ') : 'None in this period'),
40413
- );
40414
- card.append(facts);
40415
- for (const note of notes) card.append(node('p', note, 'caption'));
40416
- root.append(card);
40417
- }
40418
- }
40419
-
40420
40703
  function renderResults() {
40421
40704
  const allowance = allowanceSummary();
40422
40705
  const quality = qualitySummary();
40423
- const configured = configuredProviders();
40424
- const connectionCount = configured.reduce(
40425
- (total, component) => total + (component.configuredHarnesses?.length || 0),
40426
- 0,
40427
- );
40428
- const measuredProviders = new Set(
40429
- (current?.savings?.rows || []).map(row => row.providerId).filter(Boolean),
40430
- );
40706
+ const savings = current?.savings?.rows || [];
40707
+ const reduction = bestReduction();
40431
40708
  $('result-summary').replaceChildren(
40432
- metricCard('Configured optimizers', count(configured.length), optimizerIds().length + ' optimizer(s) tracked in the stack.', configured.length ? 'positive' : ''),
40433
- metricCard('Setups detected', count(connectionCount), 'Detected optimizer setup links; this is not proof of measured activity.', connectionCount ? 'positive' : ''),
40434
- metricCard('Optimizers with results', count(measuredProviders.size), 'Providers with recorded measurements in the selected period.'),
40709
+ reduction
40710
+ ? metricCard('Recorded output', reduction.impact.headline, reduction.provider + ' · ' + reduction.measurement + ' · changed outputs only', 'positive')
40711
+ : metricCard('Recorded output', savings.length ? count(savings.length) + ' measurement groups' : 'No records yet', savings.length ? 'Open Evidence for each source and unit.' : 'Use a connected app, then Refresh.'),
40435
40712
  metricCard('5h / 7d allowance', allowance.value, allowance.detail, allowance.cls),
40436
40713
  metricCard('Quality', quality.value, quality.detail, quality.cls),
40437
40714
  );
40438
40715
  const routed = current?.value?.routing;
40439
- const quotaParts = [];
40440
- if (routed?.allowance5h?.state === 'measured' && routed.allowance5h.savedPercent !== null)
40441
- quotaParts.push(routed.allowance5h.savedPercent >= 0
40442
- ? '5h saved ' + count(routed.allowance5h.savedPercent) + '%'
40443
- : '5h use +' + count(Math.abs(routed.allowance5h.savedPercent)) + '%');
40444
- if (routed?.allowance7d?.state === 'measured' && routed.allowance7d.savedPercent !== null)
40445
- quotaParts.push(routed.allowance7d.savedPercent >= 0
40446
- ? '7d saved ' + count(routed.allowance7d.savedPercent) + '%'
40447
- : '7d use +' + count(Math.abs(routed.allowance7d.savedPercent)) + '%');
40448
- const routingValue = routed?.state === 'blocked-by-quality'
40716
+ const routeStatus = routed?.state === 'blocked-by-quality'
40449
40717
  ? 'Not credited'
40450
40718
  : routed?.savedLocalTokens !== null && routed?.savedLocalTokens !== undefined
40451
- ? (routed.savedLocalTokens >= 0
40452
- ? count(routed.savedLocalTokens) + ' tokens saved' + (routed.localTokenSavingPercent === null ? '' : ' · ' + count(routed.localTokenSavingPercent) + '%')
40453
- : count(Math.abs(routed.savedLocalTokens)) + ' tokens added' + (routed.localTokenSavingPercent === null ? '' : ' · ' + count(Math.abs(routed.localTokenSavingPercent)) + '%'))
40454
- : quotaParts.length ? 'Allowance measured' : routed?.state === 'measured' ? 'Usage unavailable' : 'Not measured yet';
40455
- const routingDetail = routed?.state === 'blocked-by-quality'
40456
- ? routed.basis
40457
- : (quotaParts.length ? quotaParts.join(' · ') + '. ' : '') +
40458
- (routed?.pairs ? count(routed.pairs) + ' quality-passed routed pair(s). ' : '') +
40459
- 'Local tokens and allowance percentages are separate measurements. Actual child model is not exposed by every harness hook.';
40460
- $('result-summary').append(metricCard('Automatic routing', routingValue, routingDetail, routed?.state === 'measured' ? 'positive' : ''));
40461
- renderResultOptimizers();
40462
- renderResultAgents();
40463
- renderSavings();
40464
- renderCandidateResults();
40719
+ ? count(Math.abs(routed.savedLocalTokens)) + (routed.savedLocalTokens < 0 ? ' tokens added' : ' tokens saved')
40720
+ : routed?.state === 'measured' ? 'Allowance measured' : 'Not measured yet';
40721
+ $('result-summary').append(metricCard('Automatic routing', routeStatus, routed?.pairs ? count(routed.pairs) + ' quality-passed pairs · local usage' : 'Needs paired runs with a passing quality gate.', routed?.state === 'blocked-by-quality' || routed?.savedLocalTokens < 0 ? 'warn' : routed?.state === 'measured' ? 'positive' : ''));
40722
+ renderEvidence();
40465
40723
  $('results-period-note').textContent = current?.savings?.firstRecordedAt
40466
- ? 'Recorded from ' + date(current.savings.firstRecordedAt) + ' through ' + date(current.savings.lastRecordedAt)
40467
- : 'No recorded result dates for this period.';
40724
+ ? 'All locally recorded projects · ' + new Date(current.savings.firstRecordedAt).toLocaleDateString() + ' – ' + new Date(current.savings.lastRecordedAt).toLocaleDateString()
40725
+ : 'All locally recorded projects · no results for this period.';
40726
+ if (current?.savings?.errors) $('results-period-note').textContent += ' · ' + count(current.savings.errors) + ' records could not be read';
40468
40727
  }
40469
40728
 
40470
40729
  function renderActivity() {
40471
40730
  const root = $('activity');
40472
40731
  root.replaceChildren();
40473
- const rows = activityState?.activity || [];
40732
+ const rows = [...(activityState?.activity || [])].sort((a, b) => new Date(b.at).getTime() - new Date(a.at).getTime());
40474
40733
  if (!rows.length) {
40475
40734
  root.append(sectionEmpty('No checks or changes have been recorded in this app session.'));
40476
40735
  return;
40477
40736
  }
40478
- for (const item of rows) {
40737
+ const visible = rows.slice(0, 8);
40738
+ for (const item of visible) {
40479
40739
  const row = node('div', undefined, 'activity-row');
40480
40740
  row.append(pill(item.state === 'success' ? 'Done' : item.state === 'attention' ? 'Attention' : 'Working', item.state === 'success' ? 'good' : item.state === 'attention' ? 'warn' : ''), node('span', item.message), node('time', date(item.at), 'caption'));
40481
40741
  root.append(row);
40482
40742
  }
40743
+ if (rows.length > visible.length) root.prepend(node('p', 'Showing the latest ' + visible.length + ' of ' + rows.length + ' entries.', 'caption'));
40483
40744
  }
40484
40745
 
40485
40746
  async function loadActivity() {
@@ -40498,6 +40759,82 @@ var init_guided_product_client = __esm({
40498
40759
  }
40499
40760
  }
40500
40761
 
40762
+ function reviewUpdate(result) {
40763
+ if (!result?.ticket || busy) return;
40764
+ modal('Review Token Harness update');
40765
+ $('modal-content').append(
40766
+ messageBox('Update available', (result.messages || []).join(' ') || result.title || 'A reviewed Token Harness update is ready.'),
40767
+ messageBox('Health re-check', 'After installation, Token Harness will re-check optimizer health automatically.'),
40768
+ );
40769
+ $('modal-actions').append(modalClose('Cancel'), actionButton('Install updates', () => applyTicket(result.ticket)));
40770
+ }
40771
+
40772
+ async function checkUpdatesOnStartup() {
40773
+ if (updateCheckStarted) return;
40774
+ if ($('modal').open) {
40775
+ $('modal').addEventListener('close', checkUpdatesOnStartup, { once: true });
40776
+ return;
40777
+ }
40778
+ if (busy || reading) {
40779
+ setTimeout(checkUpdatesOnStartup, 1000);
40780
+ return;
40781
+ }
40782
+ updateCheckStarted = true;
40783
+ try {
40784
+ await ensureSession();
40785
+ const result = await request('/api/update-check', { period: $('period').value });
40786
+ if (busy || reading || $('modal').open) {
40787
+ updateCheckStarted = false;
40788
+ if ($('modal').open) $('modal').addEventListener('close', checkUpdatesOnStartup, { once: true });
40789
+ else setTimeout(checkUpdatesOnStartup, 1000);
40790
+ return;
40791
+ }
40792
+ latestUpdateCheck = result;
40793
+ if (result.stack && current) {
40794
+ current = { ...current, stack: result.stack };
40795
+ renderDashboard();
40796
+ renderSetup();
40797
+ renderResults();
40798
+ }
40799
+ const root = $('update-notice');
40800
+ root.replaceChildren();
40801
+ if (!result.ticket) {
40802
+ root.hidden = true;
40803
+ return;
40804
+ }
40805
+ const copy = node('div');
40806
+ copy.append(node('strong', result.title || 'Token Harness update available'), node('p', (result.messages || []).join(' ') || 'Review and install the available update.', 'caption'));
40807
+ root.append(copy, actionButton('Review update', () => reviewUpdate(latestUpdateCheck), 'secondary'));
40808
+ root.hidden = false;
40809
+ } catch {
40810
+ // The startup version check is supplementary; Refresh and Health and updates remain available.
40811
+ }
40812
+ }
40813
+
40814
+ async function pollRouting() {
40815
+ if (document.hidden || busy || reading || $('modal').open || !current) return;
40816
+ try {
40817
+ const result = await request('/api/routing');
40818
+ if (busy || reading || $('modal').open || document.activeElement?.closest('#setup-agents, #result-evidence')) return;
40819
+ if (!Array.isArray(result.agents)) return;
40820
+ const byId = new Map(result.agents.map(agent => [agent.id, agent.promptRouting]));
40821
+ const previous = new Map((current.agents || []).map(agent => [agent.id, agent.promptRouting]));
40822
+ const changed = [...byId].some(([id, routing]) => JSON.stringify(previous.get(id)) !== JSON.stringify(routing));
40823
+ if (!changed) return;
40824
+ current = {
40825
+ ...current,
40826
+ agents: (current.agents || []).map(agent => byId.has(agent.id)
40827
+ ? { ...agent, promptRouting: byId.get(agent.id) }
40828
+ : agent),
40829
+ };
40830
+ renderDashboard();
40831
+ renderAgentSetup();
40832
+ renderResults();
40833
+ } catch {
40834
+ // Runtime receipts are supplementary; the overview remains usable if this read fails.
40835
+ }
40836
+ }
40837
+
40501
40838
  function render() {
40502
40839
  renderNotices();
40503
40840
  renderDashboard();
@@ -40522,7 +40859,7 @@ var init_guided_product_client = __esm({
40522
40859
  $('stale-state').textContent = '';
40523
40860
  render();
40524
40861
  await loadActivity();
40525
- setStatus('Checked at ' + new Date(current.generatedAt).toLocaleTimeString() + '. Full checks run again only when you choose Refresh.', false);
40862
+ setStatus('Updated at ' + new Date(current.generatedAt).toLocaleTimeString(), false);
40526
40863
  } catch (error) {
40527
40864
  setError(error.name === 'TimeoutError' ? 'The check took too long. Existing results were kept; choose Refresh to try again.' : error.message);
40528
40865
  setStatus('Check needs attention.', false);
@@ -40530,6 +40867,7 @@ var init_guided_product_client = __esm({
40530
40867
  clearInterval(progressTimer);
40531
40868
  reading = false;
40532
40869
  $('refresh').disabled = false;
40870
+ if (current && !updateCheckStarted) checkUpdatesOnStartup();
40533
40871
  }
40534
40872
  }
40535
40873
 
@@ -40568,8 +40906,28 @@ var init_guided_product_client = __esm({
40568
40906
  document.querySelectorAll('[data-view]').forEach(button => {
40569
40907
  button.addEventListener('click', () => selectView(button.dataset.view, true));
40570
40908
  });
40909
+ document.querySelector('.view-tabs').addEventListener('keydown', event => {
40910
+ const views = Object.keys(VIEWS);
40911
+ const index = views.indexOf(selectedView);
40912
+ const next = event.key === 'Home' ? 0 : event.key === 'End' ? views.length - 1
40913
+ : event.key === 'ArrowRight' ? (index + 1) % views.length
40914
+ : event.key === 'ArrowLeft' ? (index + views.length - 1) % views.length : null;
40915
+ if (next === null) return;
40916
+ event.preventDefault();
40917
+ selectView(views[next], true);
40918
+ });
40919
+ $('overview-results').addEventListener('click', () => selectView('results', true));
40571
40920
  $('refresh').addEventListener('click', () => refresh(true));
40572
40921
  $('period').addEventListener('change', changePeriod);
40922
+ $('evidence-filter').addEventListener('input', applyEvidenceFilters);
40923
+ $('evidence-type').addEventListener('change', applyEvidenceFilters);
40924
+ $('evidence-sort').addEventListener('change', applyEvidenceFilters);
40925
+ $('evidence-reset').addEventListener('click', () => {
40926
+ $('evidence-filter').value = '';
40927
+ $('evidence-type').value = 'all';
40928
+ applyEvidenceFilters();
40929
+ $('evidence-filter').focus();
40930
+ });
40573
40931
  $('measurement-help').addEventListener('click', measurementHelp);
40574
40932
  $('theme').addEventListener('change', () => {
40575
40933
  const value = $('theme').value;
@@ -40585,6 +40943,8 @@ var init_guided_product_client = __esm({
40585
40943
  selectView('dashboard');
40586
40944
  refresh(false);
40587
40945
  setInterval(() => { if (!document.hidden) loadActivity(); }, 4000);
40946
+ setInterval(pollRouting, 15000);
40947
+ document.addEventListener('visibilitychange', () => { if (!document.hidden) pollRouting(); });
40588
40948
  })();
40589
40949
  `;
40590
40950
  }
@@ -40598,22 +40958,208 @@ var init_guided_product_styles = __esm({
40598
40958
  GUIDE_PRODUCT_CSS = String.raw`
40599
40959
  [hidden]{display:none!important}
40600
40960
  .eyebrow{display:block;color:var(--muted);font-size:.72rem;font-weight:900;letter-spacing:.08em;margin-bottom:.35rem}
40601
- .dashboard-status{display:flex;align-items:flex-start;justify-content:space-between;gap:1rem;background:linear-gradient(145deg,var(--panel),var(--panel-soft));border:1px solid var(--line);border-radius:var(--radius);padding:1.35rem;box-shadow:var(--shadow);margin:1rem 0}.dashboard-status h2{margin:.15rem 0 .45rem;font-size:1.35rem}.dashboard-status p{color:var(--muted);margin:.25rem 0 1rem;max-width:720px}
40602
- .dashboard-columns{display:grid;grid-template-columns:minmax(0,1fr) minmax(300px,.55fr);gap:.9rem;margin:1rem 0}.dashboard-columns>.panel h2{margin-top:0}.status-list{display:grid;gap:.15rem}.status-row{display:flex;justify-content:space-between;gap:1rem;align-items:center;padding:.72rem 0;border-bottom:1px solid var(--line)}.status-row:last-child{border-bottom:0}
40603
- .checklist{display:grid;gap:.25rem}.check-row{display:grid;grid-template-columns:28px 1fr;gap:.5rem;padding:.55rem 0}.check-row p{margin:.15rem 0}.check-icon{display:grid;place-items:center;width:24px;height:24px;border:1px solid var(--line);border-radius:999px;color:var(--muted);font-weight:900}.check-icon.done{background:var(--good-soft);border-color:color-mix(in srgb,var(--good) 35%,var(--line));color:var(--good)}
40604
- .setup-intro{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:1rem;align-items:start;background:var(--accent-soft);border:1px solid color-mix(in srgb,var(--accent) 30%,var(--line));border-radius:var(--radius);padding:1rem 1.15rem;margin:1rem 0}.setup-intro h2{margin:.1rem 0 .3rem}.setup-intro p{margin:.2rem 0;color:var(--muted)}
40605
- .setup-step{margin:1.6rem 0}.step-heading{display:grid;grid-template-columns:34px 1fr;gap:.65rem;align-items:start;margin-bottom:.7rem}.step-number{display:grid;place-items:center;width:32px;height:32px;border-radius:9px;background:var(--accent);color:#fff;font-weight:900}.step-heading h2{margin:0}.step-heading p{margin:.2rem 0;color:var(--muted)}
40606
- .connection-overview{display:grid;gap:.75rem}.connection-summary{display:flex;align-items:center;justify-content:space-between;gap:1rem;background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);padding:1rem}.connection-summary p{margin:.15rem 0 0}.connection-scroll{overflow-x:auto;border:1px solid var(--line);border-radius:var(--radius);background:var(--panel)}.connection-table{min-width:max(720px,100%)}.connection-row{display:grid;grid-template-columns:minmax(170px,1.25fr) repeat(var(--connection-columns),minmax(130px,1fr)) minmax(155px,.8fr);align-items:center;gap:.6rem;padding:.72rem .8rem;border-bottom:1px solid var(--line)}.connection-row:last-child{border-bottom:0}.connection-head{background:var(--panel-soft);color:var(--muted);font-size:.8rem}.connection-name{display:grid;gap:.12rem}.connection-cell,.connection-action{min-width:0}.connection-action{display:flex;justify-content:flex-end}.tool-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.8rem}.candidate-comparison-toolbar{grid-column:1/-1;justify-content:flex-end;align-self:start}.tool-card{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);padding:1rem;box-shadow:var(--shadow)}.tool-card.experimental{border-style:dashed}.tool-card.compact{box-shadow:none}.tool-card>p{color:var(--muted);margin:.65rem 0}.tool-head{display:flex;align-items:flex-start;justify-content:space-between;gap:.75rem}.tool-head h3{margin:0}.tool-facts{display:grid;grid-template-columns:auto 1fr;gap:.3rem .75rem;border-top:1px solid var(--line);border-bottom:1px solid var(--line);padding:.65rem 0;margin:.65rem 0}.tool-facts span{color:var(--muted);font-size:.8rem}.tool-facts strong{font-size:.85rem}
40607
- .connection-role{max-width:28ch}.setup-choice-list{display:grid;gap:.55rem;margin:.9rem 0}.setup-choice-list h3{margin:.25rem 0 0}.setup-choice{display:grid;grid-template-columns:auto 1fr;align-items:start;gap:.7rem;padding:.8rem;border:1px solid var(--line);border-radius:12px;background:var(--panel);cursor:pointer}.setup-choice:hover{border-color:var(--accent);background:var(--accent-soft)}.setup-choice input{inline-size:1.1rem;block-size:1.1rem;margin:.15rem 0 0;accent-color:var(--accent)}.setup-choice-copy{display:grid;gap:.2rem}.setup-choice-limitation{color:var(--muted)}
40608
- .routing-feature{margin:.8rem 0;padding:.8rem;border:1px solid var(--line);border-radius:12px;background:var(--panel-soft)}.routing-feature .tool-head{align-items:center}.routing-feature p{margin:.55rem 0;color:var(--muted)}
40609
- .managed-action-box{margin-top:.8rem;background:var(--panel-soft);border:1px solid var(--line);border-radius:12px;padding:.85rem}.managed-action-box p{margin:.1rem 0 .65rem}
40610
- .maintenance-list{display:grid;gap:.55rem}.maintenance-row{display:flex;align-items:center;justify-content:space-between;gap:1rem;background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:.8rem}.maintenance-row p{margin:.15rem 0}
40611
- .explain-box{background:var(--panel-soft);border:1px solid var(--line);border-radius:12px;padding:.8rem;margin:.6rem 0}.explain-box p{margin:.25rem 0;color:var(--muted)}.explain-box.warn{background:var(--warn-soft);border-color:color-mix(in srgb,var(--warn) 35%,var(--line))}.explain-box.safe{background:var(--good-soft);border-color:color-mix(in srgb,var(--good) 30%,var(--line))}.operation-progress{margin:.75rem 0;padding:.8rem;border:1px solid var(--line);border-radius:12px}.operation-progress p{margin:.35rem 0 0}
40612
- .choice-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.6rem;margin:.8rem 0}.choice-button{display:flex;flex-direction:column;align-items:flex-start;text-align:left;gap:.25rem;background:var(--panel);color:var(--text);border:1px solid var(--line);padding:.8rem}.choice-button:hover:not(:disabled){border-color:var(--accent);background:var(--accent-soft)}.choice-button .caption{font-weight:500}
40613
- .result-signal{display:grid;gap:.2rem;border-top:1px solid var(--line);padding:.65rem 0}.result-signal strong{font-size:1rem}.results-header{display:flex;justify-content:space-between;gap:1rem;align-items:end;margin:1rem 0}.results-header h2{margin:0}.results-header p{margin:.2rem 0;color:var(--muted)}
40614
- #modal{width:min(720px,calc(100vw - 2rem));max-height:calc(100vh - 2rem);overflow:auto}#modal-content h3{margin:1rem 0 .4rem}#modal-actions{display:flex;justify-content:flex-end;gap:.5rem;flex-wrap:wrap;margin-top:1rem}
40615
- @media(max-width:900px){.dashboard-columns{grid-template-columns:1fr}.tool-grid{grid-template-columns:1fr}.setup-intro{grid-template-columns:1fr}}
40616
- @media(max-width:640px){.dashboard-status{flex-direction:column}.choice-grid{grid-template-columns:1fr}.connection-summary{align-items:flex-start;flex-direction:column}.connection-action{justify-content:flex-start}.maintenance-row{align-items:flex-start;flex-direction:column}.results-header{align-items:flex-start;flex-direction:column}}
40961
+ .dashboard-status{display:flex;align-items:flex-start;justify-content:space-between;gap:1rem;background:linear-gradient(145deg,var(--panel),var(--panel-soft));border:1px solid var(--line);border-radius:var(--radius);padding:1.35rem;box-shadow:var(--shadow);margin:1rem 0}
40962
+ .dashboard-status h2{margin:.15rem 0 .45rem;font-size:1.35rem}
40963
+ .dashboard-status p{color:var(--muted);margin:.25rem 0 1rem;max-width:720px}
40964
+ .dashboard-columns{display:grid;grid-template-columns:minmax(0,1fr) minmax(300px,.55fr);gap:.9rem;margin:1rem 0}
40965
+ .dashboard-columns>.panel h2{margin-top:0}
40966
+ .status-list{display:grid;gap:.15rem}
40967
+ .status-row{display:flex;justify-content:space-between;gap:1rem;align-items:center;padding:.72rem 0;border-bottom:1px solid var(--line)}
40968
+ .status-row:last-child{border-bottom:0}
40969
+ .checklist{display:grid;gap:.25rem}
40970
+ .check-row{display:grid;grid-template-columns:28px 1fr;gap:.5rem;padding:.55rem 0}
40971
+ .check-row p{margin:.15rem 0}
40972
+ .check-icon{display:grid;place-items:center;width:24px;height:24px;border:1px solid var(--line);border-radius:999px;color:var(--muted);font-weight:900}
40973
+ .check-icon.done{background:var(--good-soft);border-color:color-mix(in srgb,var(--good) 35%,var(--line));color:var(--good)}
40974
+ .setup-intro{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:1rem;align-items:start;background:var(--accent-soft);border:1px solid color-mix(in srgb,var(--accent) 30%,var(--line));border-radius:var(--radius);padding:1rem 1.15rem;margin:1rem 0}
40975
+ .setup-intro h2{margin:.1rem 0 .3rem}
40976
+ .setup-intro p{margin:.2rem 0;color:var(--muted)}
40977
+ .setup-step{margin:1.6rem 0}
40978
+ .step-heading{display:grid;grid-template-columns:34px 1fr;gap:.65rem;align-items:start;margin-bottom:.7rem}
40979
+ .step-number{display:grid;place-items:center;width:32px;height:32px;border-radius:9px;background:var(--accent);color:#fff;font-weight:900}
40980
+ .step-heading h2{margin:0}
40981
+ .step-heading p{margin:.2rem 0;color:var(--muted)}
40982
+ .connection-overview{display:grid;gap:.75rem}
40983
+ .connection-summary{display:flex;align-items:center;justify-content:space-between;gap:1rem;background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);padding:1rem}
40984
+ .connection-summary p{margin:.15rem 0 0}
40985
+ .connection-scroll{overflow-x:auto;border:1px solid var(--line);border-radius:var(--radius);background:var(--panel)}
40986
+ .connection-table{min-width:max(720px,100%)}
40987
+ .connection-row{display:grid;grid-template-columns:minmax(170px,1.25fr) repeat(var(--connection-columns),minmax(130px,1fr)) minmax(155px,.8fr);align-items:center;gap:.6rem;padding:.72rem .8rem;border-bottom:1px solid var(--line)}
40988
+ .connection-row:last-child{border-bottom:0}
40989
+ .connection-head{background:var(--panel-soft);color:var(--muted);font-size:.8rem}
40990
+ .connection-name{display:grid;gap:.12rem}
40991
+ .connection-cell,.connection-action{min-width:0}
40992
+ .connection-action{display:flex;justify-content:flex-end}
40993
+ .tool-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.8rem}
40994
+ .candidate-comparison-toolbar{grid-column:1/-1;justify-content:flex-end;align-self:start}
40995
+ .tool-card{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);padding:1rem;box-shadow:var(--shadow)}
40996
+ .tool-card.experimental{border-style:dashed}
40997
+ .tool-card.compact{box-shadow:none}
40998
+ .tool-card>p{color:var(--muted);margin:.65rem 0}
40999
+ .tool-head{display:flex;align-items:flex-start;justify-content:space-between;gap:.75rem}
41000
+ .tool-head h3{margin:0}
41001
+ .tool-facts{display:grid;grid-template-columns:auto 1fr;gap:.3rem .75rem;border-top:1px solid var(--line);border-bottom:1px solid var(--line);padding:.65rem 0;margin:.65rem 0}
41002
+ .tool-facts span{color:var(--muted);font-size:.8rem}
41003
+ .tool-facts strong{font-size:.85rem}
41004
+ .connection-role{max-width:28ch}
41005
+ .setup-choice-list{display:grid;gap:.55rem;margin:.9rem 0}
41006
+ .setup-choice-list h3{margin:.25rem 0 0}
41007
+ .setup-choice{display:grid;grid-template-columns:auto 1fr;align-items:start;gap:.7rem;padding:.8rem;border:1px solid var(--line);border-radius:12px;background:var(--panel);cursor:pointer}
41008
+ .setup-choice:hover{border-color:var(--accent);background:var(--accent-soft)}
41009
+ .setup-choice input{inline-size:1.1rem;block-size:1.1rem;margin:.15rem 0 0;accent-color:var(--accent)}
41010
+ .setup-choice-copy{display:grid;gap:.2rem}
41011
+ .setup-choice-limitation{color:var(--muted)}
41012
+ .routing-feature{margin:.8rem 0;padding:.8rem;border:1px solid var(--line);border-radius:12px;background:var(--panel-soft)}
41013
+ .routing-feature .tool-head{align-items:center}
41014
+ .routing-feature p{margin:.55rem 0;color:var(--muted)}
41015
+ .managed-action-box{margin-top:.8rem;background:var(--panel-soft);border:1px solid var(--line);border-radius:12px;padding:.85rem}
41016
+ .managed-action-box p{margin:.1rem 0 .65rem}
41017
+ .maintenance-list{display:grid;gap:.55rem}
41018
+ .maintenance-row{display:flex;align-items:center;justify-content:space-between;gap:1rem;background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:.8rem}
41019
+ .maintenance-row p{margin:.15rem 0}
41020
+ .explain-box{background:var(--panel-soft);border:1px solid var(--line);border-radius:12px;padding:.8rem;margin:.6rem 0}
41021
+ .explain-box p{margin:.25rem 0;color:var(--muted)}
41022
+ .explain-box.warn{background:var(--warn-soft);border-color:color-mix(in srgb,var(--warn) 35%,var(--line))}
41023
+ .explain-box.safe{background:var(--good-soft);border-color:color-mix(in srgb,var(--good) 30%,var(--line))}
41024
+ .operation-progress{margin:.75rem 0;padding:.8rem;border:1px solid var(--line);border-radius:12px}
41025
+ .operation-progress p{margin:.35rem 0 0}
41026
+ .choice-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.6rem;margin:.8rem 0}
41027
+ .choice-button{display:flex;flex-direction:column;align-items:flex-start;text-align:left;gap:.25rem;background:var(--panel);color:var(--text);border:1px solid var(--line);padding:.8rem}
41028
+ .choice-button:hover:not(:disabled){border-color:var(--accent);background:var(--accent-soft)}
41029
+ .choice-button .caption{font-weight:500}
41030
+ .result-signal{display:grid;gap:.2rem;border-top:1px solid var(--line);padding:.65rem 0}
41031
+ .result-signal strong{font-size:1rem}
41032
+ .results-header{display:flex;justify-content:space-between;gap:1rem;align-items:end;margin:1rem 0}
41033
+ .results-header h2{margin:0}
41034
+ .results-header p{margin:.2rem 0;color:var(--muted)}
41035
+ .update-notice{display:flex;align-items:center;justify-content:space-between;gap:1rem;padding:.8rem 1rem;margin:.8rem 0;border:1px solid color-mix(in srgb,var(--accent) 40%,var(--line));border-radius:var(--radius);background:var(--accent-soft)}
41036
+ .update-notice p{margin:.2rem 0 0;color:var(--muted)}
41037
+ .inline-actions a.secondary{display:inline-flex;align-items:center;padding:.68rem 1rem;border-radius:10px;text-decoration:none;font-weight:700}
41038
+ /* Shared form controls, including search, use the same sizing and theme tokens. */
41039
+ input:not([type="checkbox"]):not([type="radio"]),select,textarea{font:inherit;color:var(--text);background:var(--panel);border:1px solid var(--control-line);border-radius:10px;padding:.65rem .75rem;min-height:44px;max-width:100%}input::placeholder{color:var(--muted);opacity:1}input:focus-visible,select:focus-visible,button:focus-visible,summary:focus-visible,a:focus-visible{outline:2px solid var(--accent);outline-offset:3px}button{min-height:44px}h2,h3{line-height:1.25;text-wrap:balance}p{overflow-wrap:anywhere}
41040
+ :root{--on-accent:#fff;--control-line:#8190a5;--muted:#596579;--shadow:0 2px 8px rgba(28,39,61,.03)}:root[data-theme="dark"]{--on-accent:#101a30;--control-line:#5f7088;--muted:#a6b0c0;--shadow:none}
41041
+ @media(prefers-color-scheme:dark){:root:not([data-theme="light"]){--on-accent:#101a30;--control-line:#5f7088;--muted:#a6b0c0;--shadow:none}}button:not(.secondary):not(.text-button):not(.choice-button):not([role="tab"]),.brand-mark{color:var(--on-accent)}
41042
+ .page-heading h1{font-size:1.8rem}
41043
+ .page-heading p{font-size:.95rem}
41044
+ .status-line{font-size:.8rem}
41045
+ .dashboard-status{background:var(--panel);padding:1.15rem;align-items:center;box-shadow:none}
41046
+ .dashboard-status>div{min-width:0}
41047
+ .dashboard-status h2{font-size:1.2rem}
41048
+ .dashboard-status p{max-width:64ch;margin:.35rem 0 .8rem}
41049
+ .dashboard-status>.pill{flex-shrink:0}
41050
+ .section-title h2,.results-header h2{font-size:1.15rem}
41051
+ .section-title p,.results-header p{font-size:.88rem;max-width:75ch}
41052
+ .metric-card{min-height:132px;box-shadow:none;padding:1rem}
41053
+ .metric-value{font-size:1.25rem;line-height:1.3;overflow-wrap:anywhere}
41054
+ .metric-card.positive .metric-value,.metric-card.good .metric-value{color:var(--good)}
41055
+ .metric-card.warn .metric-value{color:var(--warn)}
41056
+ .metric-help{font-size:.8rem}
41057
+ .advanced-disclosure{border:1px solid var(--line);border-radius:12px;background:var(--panel);padding:.8rem 1rem}
41058
+ .advanced-disclosure>summary{font-size:.88rem}
41059
+ .advanced-disclosure[open]>summary{margin-bottom:1rem}
41060
+ main,.setup-step{scroll-margin-top:7rem}
41061
+ .connection-summary{padding:.8rem 1rem}
41062
+ .connection-action{gap:.4rem;flex-wrap:wrap}
41063
+ .connection-action .text-button{font-size:.78rem}
41064
+ .connection-app-label{display:none}
41065
+ .tool-card{box-shadow:none}
41066
+ .tool-head{flex-wrap:wrap}
41067
+ .routing-feature .tool-head{gap:.4rem}
41068
+ .routing-feature .tool-head strong{font-size:.88rem}
41069
+ .routing-feature{background:var(--panel-soft)}
41070
+ .maintenance-row{padding:1rem}
41071
+ .maintenance-row>div{min-width:0}
41072
+ .maintenance-row button{flex-shrink:0}
41073
+ .maintenance-list{grid-template-columns:repeat(2,minmax(0,1fr))}
41074
+ .maintenance-row{align-items:flex-start;flex-direction:column}
41075
+ .brand small{font-weight:400}
41076
+ .evidence-panel{padding:0;overflow:hidden;box-shadow:none}
41077
+ .evidence-controls{display:grid;grid-template-columns:minmax(220px,1fr) minmax(150px,.4fr) minmax(150px,.4fr);gap:.75rem;padding:1rem;background:var(--panel-soft);border-bottom:1px solid var(--line)}
41078
+ .evidence-field{display:grid;gap:.4rem;min-width:0}
41079
+ .evidence-controls label{color:var(--muted);font-size:.78rem;font-weight:600}
41080
+ .evidence-controls input,.evidence-controls select{width:100%;font-size:.9rem}
41081
+ .evidence-list-meta{display:flex;align-items:center;justify-content:space-between;gap:.75rem;padding:.5rem 1rem;min-height:48px;border-bottom:1px solid var(--line)}
41082
+ .evidence-list-meta p{margin:0}
41083
+ .evidence-list-meta button{font-size:.8rem}
41084
+ .result-evidence{list-style:none;margin:0;padding:0}
41085
+ .evidence-item{border-bottom:1px solid var(--line)}
41086
+ .evidence-item:last-child{border-bottom:0}
41087
+ .evidence-summary{display:grid;grid-template-columns:minmax(180px,.8fr) minmax(0,1.6fr) auto;align-items:center;gap:1.5rem;padding:1.15rem 1rem;list-style:none;font-weight:400}
41088
+ .evidence-summary::-webkit-details-marker{display:none}
41089
+ .evidence-summary:hover{background:var(--panel-soft)}
41090
+ .evidence-identity{display:grid;gap:.3rem;min-width:0}
41091
+ .evidence-identity>strong{font-size:.98rem;line-height:1.3}
41092
+ .evidence-kind{font-size:.7rem;color:var(--muted);font-weight:700;text-transform:uppercase;letter-spacing:.05em}
41093
+ .evidence-signals{display:grid;gap:.75rem;min-width:0}
41094
+ .evidence-signal{display:grid;gap:.2rem;line-height:1.4}
41095
+ .evidence-signal strong{font-size:1rem;font-weight:650}
41096
+ .evidence-signal.good strong{color:var(--good)}
41097
+ .evidence-signal.warn strong{color:var(--warn)}
41098
+ .evidence-cue{display:flex;align-items:center;gap:.6rem;font-size:.8rem;color:var(--accent);font-weight:700;white-space:nowrap}
41099
+ .evidence-chevron{font-size:1.5rem;font-weight:400;line-height:1}
41100
+ .evidence-disclosure[open]>.evidence-summary{background:var(--panel-soft)}
41101
+ .evidence-disclosure[open] .evidence-chevron{transform:rotate(90deg)}
41102
+ .evidence-detail-body{display:grid;gap:1rem;padding:0 1rem 1.15rem;background:var(--panel-soft)}
41103
+ .evidence-section{background:var(--panel);border:1px solid var(--line);border-radius:10px;padding:1rem}
41104
+ .evidence-section h3{margin:0 0 .7rem;font-size:.88rem}
41105
+ .evidence-section button{margin-top:.75rem}
41106
+ .evidence-section p{margin:.75rem 0 0;max-width:90ch;line-height:1.6}
41107
+ .evidence-fact-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(125px,1fr));gap:1rem;margin:0}
41108
+ .evidence-fact-grid dt{color:var(--muted);font-size:.75rem}
41109
+ .evidence-fact-grid dd{margin:.25rem 0 0;font-size:.88rem;font-weight:600;overflow-wrap:anywhere}
41110
+ .evidence-empty{padding:2rem 1rem;text-align:center}
41111
+ .evidence-empty p{margin:.5rem 0 0;color:var(--muted);font-size:.9rem}
41112
+ .result-evidence>.empty{padding:1rem}
41113
+ .activity-scroll{max-height:24rem;overflow-y:auto;overscroll-behavior:contain}
41114
+ .activity-scroll .activity-row{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:.75rem;padding:.65rem 0;border-bottom:1px solid var(--line)}
41115
+ #modal{width:min(720px,calc(100vw - 2rem));max-height:calc(100vh - 2rem);overflow:auto}
41116
+ #modal-content h3{margin:1rem 0 .4rem}
41117
+ #modal-actions{display:flex;justify-content:flex-end;gap:.5rem;flex-wrap:wrap;margin-top:1rem}
41118
+ @media(max-width:900px){.dashboard-columns{grid-template-columns:1fr}
41119
+ .tool-grid{grid-template-columns:1fr}
41120
+ .setup-intro{grid-template-columns:1fr}}
41121
+ @media(max-width:640px){.dashboard-status{flex-direction:column}
41122
+ .choice-grid{grid-template-columns:1fr}
41123
+ .connection-summary{align-items:flex-start;flex-direction:column}
41124
+ .connection-action{justify-content:flex-start}
41125
+ .maintenance-row{align-items:flex-start;flex-direction:column}
41126
+ .results-header{align-items:flex-start;flex-direction:column}
41127
+ .update-notice{align-items:flex-start;flex-direction:column}
41128
+ .activity-scroll .activity-row{grid-template-columns:auto minmax(0,1fr)}
41129
+ .activity-scroll .activity-row time{grid-column:2}}
41130
+ @media(max-width:800px){.evidence-summary{grid-template-columns:minmax(130px,.8fr) minmax(0,1.4fr);gap:1rem}
41131
+ .evidence-cue{grid-column:2}
41132
+ .evidence-controls{grid-template-columns:repeat(2,minmax(0,1fr))}
41133
+ .evidence-search{grid-column:1/-1}
41134
+ .connection-scroll{overflow:visible;border:0;background:transparent}
41135
+ .connection-table{min-width:0;display:grid;gap:.75rem}
41136
+ .connection-row{display:flex;flex-wrap:wrap;gap:.75rem;border:1px solid var(--line);border-radius:12px;background:var(--panel);padding:1rem}
41137
+ .connection-head{display:none}
41138
+ .connection-name{width:100%;gap:.25rem}
41139
+ .connection-role{max-width:none}
41140
+ .connection-cell{display:flex;align-items:center;gap:.5rem}
41141
+ .connection-app-label{display:inline;color:var(--muted);font-size:.8rem}
41142
+ .connection-action{width:100%;justify-content:flex-start;padding-top:.65rem;border-top:1px solid var(--line)}}
41143
+ @media(max-width:640px){.evidence-summary{grid-template-columns:1fr auto;gap:.85rem;padding:1rem}
41144
+ .evidence-identity{grid-column:1}
41145
+ .evidence-cue{grid-column:2;grid-row:1;align-self:start}
41146
+ .evidence-signals{grid-column:1/-1}
41147
+ .evidence-fact-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
41148
+ .evidence-section{padding:.8rem}
41149
+ .evidence-controls{gap:.65rem;padding:.85rem}
41150
+ .evidence-controls input,.evidence-controls select{font-size:.85rem}
41151
+ .maintenance-list{grid-template-columns:1fr}
41152
+ .dashboard-status{align-items:flex-start}
41153
+ .brand small{display:none}
41154
+ .section-title{align-items:center}
41155
+ .section-title>button{flex-shrink:0}
41156
+ .impact-grid{grid-template-columns:1fr}
41157
+ .metric-card{min-height:0}
41158
+ .header-tools select{display:block;max-width:90px;font-size:.8rem}
41159
+ .header-tools{gap:.35rem}
41160
+ .brand{gap:.5rem;font-size:.9rem}
41161
+ .header-inner{gap:.6rem}
41162
+ .header-tools button{padding:.65rem .65rem;font-size:.85rem}}
40617
41163
  `;
40618
41164
  }
40619
41165
  });
@@ -41270,27 +41816,26 @@ ${GUIDE_CANDIDATE_READINESS_JS}`;
41270
41816
  <div class="header-tools"><label><span class="sr-only">Appearance</span><select id="theme" aria-label="Appearance"><option value="system">System</option><option value="light">Light</option><option value="dark">Dark</option></select></label><button id="refresh" class="secondary" type="button">Refresh</button></div>
41271
41817
  </div></header>
41272
41818
  <main id="main">
41273
- <div class="page-heading"><div><h1 id="view-title">Overview</h1><p id="view-description">Your coding agents, optimization stack, health and measured results in one place.</p></div></div>
41819
+ <div class="page-heading"><div><h1 id="view-title">Overview</h1><p id="view-description">Your setup, results and next steps.</p></div></div>
41274
41820
  <div class="status-line"><span class="read-status" role="status"><span id="reading-spinner" class="spinner" aria-hidden="true"></span><span id="updated">Checking your setup\u2026</span></span><span id="live-status" class="caption">Nothing changes without your approval</span></div>
41275
41821
  <div id="stale-state" class="stale-state" hidden></div><div id="error" class="error" role="alert" hidden></div><div id="notices"></div>
41822
+ <div id="update-notice" class="update-notice" role="status" hidden></div>
41276
41823
 
41277
41824
  <section id="view-dashboard" role="tabpanel" aria-labelledby="tab-dashboard" tabindex="0">
41278
41825
  <section id="dashboard-status" class="dashboard-status"><div><span class="eyebrow">CURRENT STATUS</span><h2>Checking your machine\u2026</h2><p>Finding Claude Code, Codex, recommended optimizers and measured results.</p></div><span class="pill">Checking</span></section>
41279
41826
 
41280
- <div class="section-title"><div><h2>Measured impact</h2><p>A summary of what Token Harness can actually prove. Open Results for the detailed evidence.</p></div></div>
41827
+ <div class="section-title"><div><h2>Measured impact</h2><p>Recorded output, allowance and quality.</p></div><button id="overview-results" class="secondary" type="button">View results</button></div>
41281
41828
  <div id="dashboard-metrics" class="impact-grid" aria-label="Efficiency summary">
41282
- <article class="metric-card"><span class="metric-label">Measured output</span><strong class="metric-value">Checking\u2026</strong><p class="metric-help">Recorded optimizer output.</p></article>
41829
+ <article class="metric-card"><span class="metric-label">Recorded output</span><strong class="metric-value">Checking\u2026</strong><p class="metric-help">Recorded optimizer output.</p></article>
41283
41830
  <article class="metric-card"><span class="metric-label">5h / 7d allowance</span><strong class="metric-value">Checking\u2026</strong><p class="metric-help">Shown only when measured.</p></article>
41284
- <article class="metric-card"><span class="metric-label">API cost</span><strong class="metric-value">Checking\u2026</strong><p class="metric-help">Shown only from billing evidence.</p></article>
41285
41831
  <article class="metric-card"><span class="metric-label">Quality</span><strong class="metric-value">Checking\u2026</strong><p class="metric-help">Measured separately from savings.</p></article>
41286
41832
  </div>
41287
41833
 
41288
41834
  <section class="setup-step" id="coding-agents">
41289
- <div class="section-title"><div><h2>Coding agents</h2><p>Enable automatic per-prompt routing here for each detected coding app. The card distinguishes hook configuration from callbacks actually observed at runtime.</p></div></div>
41835
+ <div class="section-title"><div><h2>Coding agents</h2><p>Manage automatic routing for each app.</p></div></div>
41290
41836
  <div id="setup-agents" class="tool-grid"><article class="tool-card"><h3>Checking agents\u2026</h3></article></div>
41291
41837
  <details class="disclosure advanced-disclosure">
41292
- <summary>Agent details and optional reasoning settings</summary>
41293
- <p class="caption">Allowance, tool observations and reasoning preferences are advanced information. They are not required to finish optimizer setup.</p>
41838
+ <summary>Agent details &amp; reasoning settings</summary>
41294
41839
  <div id="agent-capabilities" class="tool-grid"><article class="tool-card"><h3>Checking agent details\u2026</h3></article></div>
41295
41840
  <div class="subsection-heading"><h3>Optional reasoning settings</h3><p class="caption">Persistent agent preferences are separate from optimizer setup.</p></div>
41296
41841
  <div id="agent-tuning" class="tool-grid"><article class="tool-card"><h3>Checking reasoning controls\u2026</h3></article></div>
@@ -41298,30 +41843,34 @@ ${GUIDE_CANDIDATE_READINESS_JS}`;
41298
41843
  </section>
41299
41844
 
41300
41845
  <section class="setup-step" id="optimizers">
41301
- <div class="section-title"><div><h2>Optimizer setup</h2><p>This matrix shows which optimizer setup Token Harness detected for each coding app. It does not confirm runtime activity; measured results appear separately when evidence is recorded.</p></div></div>
41846
+ <div class="section-title"><div><h2>Optimizer setup</h2><p>Connections detected for each app. Setup alone does not prove runtime activity.</p></div></div>
41302
41847
  <div id="connection-overview" class="connection-overview"><p class="empty">Checking optimizer connections\u2026</p></div>
41303
- <details class="disclosure"><summary>Remove Token Harness-managed configuration</summary><p class="caption">Removal is reviewed first. Token Harness removes only configuration it owns; installed provider software and user-owned configuration may remain.</p><div id="managed-removal-actions" class="maintenance-list"><p class="caption">Checking managed ownership\u2026</p></div></details>
41304
41848
  </section>
41305
41849
 
41306
41850
  <section class="setup-step" id="maintenance">
41307
- <div class="section-title"><div><h2>Health and updates</h2><p>These are maintenance actions, not onboarding steps. Setup already performs its own safety checks.</p></div></div>
41851
+ <div class="section-title"><div><h2>Health and updates</h2></div></div>
41308
41852
  <div id="maintenance-actions" class="maintenance-list"><p class="empty">Checking\u2026</p></div>
41309
41853
  </section>
41310
41854
  </section>
41311
41855
 
41312
41856
  <section id="view-results" role="tabpanel" aria-labelledby="tab-results" tabindex="0" hidden>
41313
- <div class="results-header"><div><h2>Results dashboard</h2><p>See which optimizer setups Token Harness found and which results it actually recorded for each coding app.</p></div><div class="filter-row"><label for="period">Period</label><select id="period"><option value="all">All</option><option value="7d">7 days</option><option value="30d">30 days</option></select><button id="measurement-help" class="secondary" type="button">How results are recorded</button></div></div>
41314
- <div id="result-summary" class="impact-grid" aria-label="Results overview"><article class="metric-card"><span class="metric-label">Optimization stack</span><strong class="metric-value">Checking\u2026</strong></article></div>
41315
- <div class="section-title"><div><h2>By optimizer</h2><p>Detected setup and recorded results for every optimizer in the stack.</p></div></div>
41316
- <div id="result-optimizers" class="tool-grid"><article class="tool-card"><h3>Checking optimizer results\u2026</h3></article></div>
41317
- <div class="section-title"><div><h2>By coding agent</h2><p>Which optimizer setups were detected for each app and which measured results can be linked to it.</p></div></div>
41318
- <div id="result-agents" class="tool-grid"><article class="tool-card"><h3>Checking results by coding app\u2026</h3></article></div>
41319
- <div class="section-title"><div><h2>Measurement evidence</h2><p id="results-period-note">Checking recorded dates\u2026</p></div></div><section class="panel"><div id="result-savings" class="evidence-list"><p class="empty">Checking recorded results\u2026</p></div></section>
41320
- <div class="section-title"><div><h2>Experimental benchmark results</h2><p>Candidate evidence is evaluation only; it never promotes a tool automatically.</p></div></div><section class="panel"><div id="candidate-results" class="evidence-list"><p class="empty">Checking candidate evidence\u2026</p></div></section>
41321
- <div class="section-title"><div><h2>Recent activity</h2><p>Checks and changes from this local app session.</p></div></div><section class="panel"><div id="activity"><p class="empty">No activity yet.</p></div></section>
41857
+ <div class="results-header"><div><h2>Measured impact</h2><p>Each result keeps its source and measurement type.</p></div><div class="filter-row"><label for="period" class="sr-only">Results period</label><select id="period"><option value="all">All recorded history</option><option value="7d">Last 7 days</option><option value="30d">Last 30 days</option></select><button id="measurement-help" class="secondary" type="button">How to read results</button></div></div>
41858
+ <div id="result-summary" class="impact-grid" aria-label="Results overview"><article class="metric-card"><span class="metric-label">Measured evidence</span><strong class="metric-value">Checking\u2026</strong></article></div>
41859
+ <div class="section-title"><div><h2>Evidence</h2><p id="results-period-note">Checking recorded dates\u2026</p></div></div>
41860
+ <section class="panel evidence-panel">
41861
+ <div class="evidence-controls">
41862
+ <div class="evidence-field evidence-search"><label for="evidence-filter">Search evidence</label><input id="evidence-filter" type="search" placeholder="Search sources, apps or measurements" autocomplete="off"></div>
41863
+ <div class="evidence-field"><label for="evidence-type">Source type</label><select id="evidence-type"><option value="all">All sources</option><option value="optimizer">Optimizers</option><option value="routing">Routing</option><option value="harness">Coding apps</option><option value="candidate">Experiments</option></select></div>
41864
+ <div class="evidence-field"><label for="evidence-sort">Sort by</label><select id="evidence-sort"><option value="evidence">With results first</option><option value="name">Name</option><option value="type">Source type</option></select></div>
41865
+ </div>
41866
+ <div class="evidence-list-meta"><p id="evidence-count" class="caption" role="status"></p><button id="evidence-reset" class="text-button" type="button" hidden>Clear filters</button></div>
41867
+ <ul id="result-evidence" class="result-evidence" aria-label="Evidence by source"><li class="empty">Checking recorded results\u2026</li></ul>
41868
+ <div id="evidence-empty" class="evidence-empty" hidden><strong>No matching sources</strong><p>Try a different search or clear the filters.</p></div>
41869
+ </section>
41870
+ <div class="section-title"><div><h2>Recent activity</h2><p>Latest checks and changes from this app session.</p></div></div><section class="panel"><div id="activity" class="activity-scroll"><p class="empty">No activity yet.</p></div></section>
41322
41871
  </section>
41323
41872
 
41324
- <footer><span>Local data. No account required.</span><span>Full overview refresh runs only when you choose Refresh.</span></footer>
41873
+ <footer><span>Local data. No account required.</span></footer>
41325
41874
  </main>
41326
41875
  <dialog id="modal" aria-labelledby="modal-title"><div class="dialog-body"><div class="dialog-heading"><h2 id="modal-title">Review</h2></div><div id="modal-content"></div><div id="modal-error" class="error" role="alert" hidden></div><div id="modal-actions" class="dialog-actions"></div></div></dialog>
41327
41876
  <script src="/guide.js" defer></script></body></html>`;
@@ -41506,6 +42055,10 @@ function createGuideHandler(input) {
41506
42055
  send(200, JSON.stringify(input.service.status()));
41507
42056
  return;
41508
42057
  }
42058
+ if (url.pathname === "/api/routing") {
42059
+ send(200, JSON.stringify(await input.service.routing()));
42060
+ return;
42061
+ }
41509
42062
  if (url.pathname === "/api/candidate-campaign") {
41510
42063
  if (input.candidateCampaign === void 0)
41511
42064
  throw new GuideError(404, "Candidate campaign status is unavailable.");
@@ -41563,6 +42116,12 @@ function createGuideHandler(input) {
41563
42116
  send(200, JSON.stringify(result6));
41564
42117
  return;
41565
42118
  }
42119
+ if (url.pathname === "/api/restart") {
42120
+ if (body === null || typeof body !== "object" || Array.isArray(body) || Object.keys(body).length !== 0)
42121
+ throw new GuideError(400, "Restart accepts no commands or paths.");
42122
+ send(200, JSON.stringify(await input.service.restart()));
42123
+ return;
42124
+ }
41566
42125
  if (url.pathname === "/api/update-check") {
41567
42126
  if (body === null || typeof body !== "object" || Array.isArray(body))
41568
42127
  throw new GuideError(400, "Only an optional reporting period is accepted.");
@@ -42106,6 +42665,7 @@ async function runGuidedUi(options, base) {
42106
42665
  }
42107
42666
  return result6;
42108
42667
  };
42668
+ const entryScript = base.adapters === null || base.adapters === void 0 || base.applicationEntryScript === void 0 || base.applicationEntryScript === null ? null : await base.adapters.fs.canonicalPath?.(base.applicationEntryScript) ?? null;
42109
42669
  const service = new GuideService(guideCall, () => Date.now(), () => randomBytes2(32).toString("hex"), async (harness) => {
42110
42670
  if (base.adapters === null || base.adapters === void 0) {
42111
42671
  return {
@@ -42147,8 +42707,23 @@ async function runGuidedUi(options, base) {
42147
42707
  facts: base.platform,
42148
42708
  paths: base.adapters.paths,
42149
42709
  projectRoot: base.cwd,
42150
- projectId: base.adapters.projectIdFor(base.cwd)
42710
+ projectId: null
42711
+ });
42712
+ }, async () => {
42713
+ if (entryScript === null || base.adapters === null || base.adapters === void 0 || base.platform === null)
42714
+ throw new Error("The installed app entry could not be verified.");
42715
+ const current = await base.adapters.fs.canonicalPath?.(base.applicationEntryScript);
42716
+ if (current !== entryScript || (await base.adapters.fs.stat(entryScript))?.kind !== "file")
42717
+ throw new Error("The app entry changed. Check the installation before restarting.");
42718
+ const url2 = await launchGuidedApplication({
42719
+ executable: process5.execPath,
42720
+ entryScript,
42721
+ cwd: base.cwd,
42722
+ facts: base.platform,
42723
+ env: process5.env
42151
42724
  });
42725
+ setTimeout(() => server.close(), 1e3);
42726
+ return url2;
42152
42727
  });
42153
42728
  const token = randomBytes2(32).toString("hex");
42154
42729
  let authority = "";
@@ -42177,6 +42752,8 @@ async function runGuidedUi(options, base) {
42177
42752
  }
42178
42753
  authority = `127.0.0.1:${address.port}`;
42179
42754
  const url = `http://${authority}/`;
42755
+ if (process5.send !== void 0)
42756
+ process5.send({ type: "token-harness-guide-ready", url });
42180
42757
  process5.stdout.write(`Token Harness is ready: ${url}
42181
42758
 
42182
42759
  Use the browser to review setup, see recorded savings and read the active rules.