token-harness 0.1.7 → 0.1.8

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.
package/README.md CHANGED
@@ -3,13 +3,13 @@
3
3
  **Make Claude Code and Codex easier to understand and use efficiently.**
4
4
 
5
5
  Token Harness checks your coding agents, shows subscription allowance when it can be
6
- observed reliably, reduces avoidable context overhead, and recommends one useful next
7
- action. It runs locally and never presents local token estimates as subscription quota.
6
+ observed reliably, reduces avoidable context overhead, and recommends useful actions.
7
+ It runs locally and never presents local token estimates as subscription quota.
8
8
 
9
9
  ## The easy path
10
10
 
11
11
  You need [Node.js 22.13 or newer](https://nodejs.org/) and at least one signed-in coding
12
- agent: Claude Code or Codex.
12
+ agent such as Claude Code or Codex.
13
13
 
14
14
  Open a terminal and paste:
15
15
 
@@ -21,7 +21,7 @@ token-harness setup
21
21
  That is the whole first-time check. `setup` tells you:
22
22
 
23
23
  - which coding agents it found;
24
- - whether an optimization provider is active;
24
+ - which optimizers are already active;
25
25
  - whether the current setup works;
26
26
  - what it changed, if anything;
27
27
  - exactly one next step.
@@ -44,16 +44,60 @@ After setup, run:
44
44
  token-harness ui
45
45
  ```
46
46
 
47
- The dashboard opens in your browser and shows harness status, active providers,
48
- allowance windows, the main recommendation, and the next action. It is a small local
49
- web page served only on `127.0.0.1`: no Electron app, account, or cloud service.
47
+ The dashboard opens in your browser and answers three questions in this order:
50
48
 
51
- Use `Ctrl+C` in the terminal to close it. If you do not want it to open a browser:
49
+ 1. **Can I work normally right now?**
50
+ 2. **What is actually active and useful?**
51
+ 3. **Is there one action worth taking?**
52
+
53
+ It shows active/relevant coding agents first, their optimization providers, observable
54
+ allowance windows, and task guidance. Tools that are absent do not get large cards;
55
+ secondary detected tools are kept out of the main path.
56
+
57
+ The page is served only on `127.0.0.1`: no Electron app, account, or cloud service.
58
+
59
+ ### What happens after the dashboard?
60
+
61
+ Usually: **nothing else. You are done.**
62
+
63
+ Token Harness is not a launcher and it does not need to stay between you and your coding
64
+ agent. Continue exactly as you normally would:
65
+
66
+ ```sh
67
+ claude
68
+ codex
69
+ opencode
70
+ ```
71
+
72
+ Use whichever of those you already use. RTK, HarnessTrim, or another configured provider
73
+ runs automatically through that coding agent's integration. You do **not** need a special
74
+ `token-harness run` command.
75
+
76
+ You can close the dashboard whenever you want. Use `Ctrl+C` in the terminal to stop its
77
+ local web server. Closing it does not disable configured optimizers.
78
+
79
+ Open it again later with `token-harness ui` when you want a status check. If you do not
80
+ want it to open a browser:
52
81
 
53
82
  ```sh
54
83
  token-harness ui --no-open
55
84
  ```
56
85
 
86
+ ## Daily use
87
+
88
+ There is no mandatory command loop. These are tools you use when they answer a question:
89
+
90
+ | When you want to know... | Run |
91
+ | --- | --- |
92
+ | Is everything still connected? | `token-harness ui` |
93
+ | What should I do before a demanding task? | `token-harness optimize --task hard --profile quality` |
94
+ | Is an integration actually working? | `token-harness verify` |
95
+ | How much reducer saving has been measured? | `token-harness metrics --since 7d` |
96
+ | Are safer provider updates available? | `token-harness update` |
97
+
98
+ If a command finishes with **no action required**, stop there and use your coding agent
99
+ normally. Token Harness should not send you around a `ui → optimize → ui` loop.
100
+
57
101
  ## Ask your AI to install Token Harness
58
102
 
59
103
  You can give this prompt to Claude Code or Codex:
@@ -67,8 +111,10 @@ Explain the setup result in plain language: what was detected, what already work
67
111
  what would change, and the single next step. Do not expose credentials, cookies,
68
112
  tokens, raw home paths, or private project contents. If setup proposes a supported
69
113
  configuration change, show me the short plan and ask before running
70
- `token-harness setup --yes`. After an approved change, verify it and start
71
- `token-harness ui`. If anything is unsupported, stop safely and explain why.
114
+ `token-harness setup --yes`. After an approved change, verify it and open
115
+ `token-harness ui` once. Then tell me clearly that setup is complete and that I should
116
+ continue using my normal coding-agent command. Do not invent additional Token Harness
117
+ steps when no action is required.
72
118
  ```
73
119
 
74
120
  The AI should ask before the `--yes` step because that is the point where coding-agent
@@ -76,25 +122,37 @@ configuration may change.
76
122
 
77
123
  ## What normal output looks like
78
124
 
79
- Human output is intentionally short:
125
+ A healthy final check is intentionally short:
80
126
 
81
127
  ```text
82
128
  TOKEN HARNESS - READY
83
129
 
84
- DETECTED
85
- Claude Code: detected
86
- Codex: configured
87
- harnesstrim: active on Codex
130
+ WHAT WORKS
131
+ Codex: configured (0.146.0)
132
+ HarnessTrim: active on Codex
88
133
 
89
134
  CHANGES
90
135
  Nothing changed.
91
136
 
92
137
  NEXT STEP
93
- token-harness ui
94
- Open the dashboard to see status, allowance, and advice.
138
+ Use your coding agent normally; configured optimizers run automatically.
139
+ ```
140
+
141
+ A newer-than-tested combination is not presented as if the whole setup were broken:
142
+
143
+ ```text
144
+ TOKEN HARNESS - READY WITH LIMITATIONS
145
+
146
+ WHAT WORKS
147
+ Claude Code: configured
148
+ RTK: active on Claude Code
149
+
150
+ NEXT STEP
151
+ token-harness verify
152
+ You can keep working; verify the active integrations when convenient.
95
153
  ```
96
154
 
97
- Need the evidence behind the summary? Add `--verbose`:
155
+ Need the evidence behind a summary? Add `--verbose`:
98
156
 
99
157
  ```sh
100
158
  token-harness doctor --verbose
@@ -120,7 +178,7 @@ token-harness optimize
120
178
  | Command | Answer |
121
179
  | --- | --- |
122
180
  | `setup` | Is Token Harness ready, and what is my one next step? |
123
- | `ui` | What is active, how much allowance is visible, and what should I do? |
181
+ | `ui` | What is active, how much allowance is visible, and do I need to do anything? |
124
182
  | `optimize` | What is the best evidence-based action for the task I am starting? |
125
183
 
126
184
  For example:
@@ -141,13 +199,15 @@ Token Harness is conservative by design:
141
199
  - existing files are backed up before a managed write;
142
200
  - only exact Token Harness-owned entries are removed by `uninstall`;
143
201
  - newer or untested combinations are reported, not guessed;
202
+ - an available provider update outside reviewed compatibility is kept out rather than
203
+ forced, and the installed working version stays in place;
144
204
  - the dashboard binds only to the local loopback address and provides no mutation API;
145
205
  - source code, prompts, command contents, credentials, and cookies are not sent to a
146
206
  Token Harness service.
147
207
 
148
208
  Plans, receipts, metrics, and backups stay in the local Token Harness state directory.
149
- See [RFC 0004](docs/rfcs/0004-execution-safety-ownership-update.md) for the execution
150
- model and [RFC 0006](docs/rfcs/0006-cli-contract.md) for CLI/JSON guarantees.
209
+ See [RFC 0004](docs/rfcs/0004-safety-and-installation.md) for the execution model and
210
+ [RFC 0006](docs/rfcs/0006-cli-contract.md) for CLI/JSON guarantees.
151
211
 
152
212
  ## Supported optimizations
153
213
 
@@ -183,7 +243,7 @@ Most people do not need this section. Run `token-harness <command> --help` for d
183
243
  | `verify` | Check the declared integration tier | No |
184
244
  | `metrics` | Report attributable reducer savings | No |
185
245
  | `status` | Report pipelines, drift, and importer modes | No |
186
- | `update` | Check/update installed providers | Yes, only with `--yes` |
246
+ | `update` | Check/update installed providers; unreviewed targets stay installed | Yes, only with `--yes` |
187
247
  | `rollback` | Restore the latest transaction snapshot | Yes, only with `--yes` |
188
248
  | `uninstall` | Remove owned integration entries | Yes, only with `--yes` |
189
249
  | `schedule` | Compare Claude Code and Codex using available evidence | No |
@@ -214,6 +274,13 @@ token-harness doctor --verbose
214
274
  Do not force an unsupported plan. Open an issue with the redacted `--json` result if
215
275
  you believe the combination should be supported.
216
276
 
277
+ ### `update` finds a newer version but keeps the installed one
278
+
279
+ That is normally a safety decision, not a failed installation. Token Harness found a
280
+ newer provider release but does not yet have reviewed compatibility evidence for the
281
+ active provider × harness × platform combination. Keep using the installed version; no
282
+ manual upgrade is required.
283
+
217
284
  ### Verification says `not-exercised`
218
285
 
219
286
  Restart the coding agent, use it for one normal command, and run:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "token-harness",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "Quota-aware efficiency layer for Claude Code and Codex subscription limits.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
package/sbom.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "bomFormat": "CycloneDX",
3
3
  "specVersion": "1.5",
4
- "serialNumber": "urn:uuid:e8f87991-af2b-4ce8-a0eb-db80b10befbe",
4
+ "serialNumber": "urn:uuid:dfdf5e8b-aba7-10dd-1c9d-dd9a38f31fb3",
5
5
  "version": 1,
6
6
  "metadata": {
7
7
  "component": {
8
8
  "type": "application",
9
9
  "bom-ref": "token-harness",
10
10
  "name": "token-harness",
11
- "version": "0.1.7",
11
+ "version": "0.1.8",
12
12
  "description": "Quota-aware efficiency layer for Claude Code and Codex subscription limits.",
13
13
  "licenses": [
14
14
  {
@@ -20,7 +20,7 @@
20
20
  "hashes": [
21
21
  {
22
22
  "alg": "SHA-256",
23
- "content": "e8f87991af2b4ce8a0ebdb80b10befbe435aee3d71c2309e20b093ef4a8c27e5"
23
+ "content": "dfdf5e8baba710dd1c9ddd9a38f31fb3aded525ea28f8b15a0fc5cff743444c6"
24
24
  }
25
25
  ]
26
26
  },
package/token-harness.mjs CHANGED
@@ -6867,7 +6867,7 @@ var TOOL_VERSION;
6867
6867
  var init_version2 = __esm({
6868
6868
  "apps/cli/dist/src/version.js"() {
6869
6869
  "use strict";
6870
- TOOL_VERSION = "0.1.7";
6870
+ TOOL_VERSION = "0.1.8";
6871
6871
  }
6872
6872
  });
6873
6873
 
@@ -15074,7 +15074,7 @@ function contextEvidence(context, harness) {
15074
15074
  const hasUnknownTools = harness.mcpServers.some((server) => server.toolCount === null);
15075
15075
  const evidence2 = [];
15076
15076
  let score = 0;
15077
- if (harness.projectDocMaxBytes !== null && harness.projectDocMaxBytes > 0) {
15077
+ if (harness.projectDocMaxBytes !== null && harness.projectDocMaxBytes > 0 && instructionBytes > 0) {
15078
15078
  const ratio = instructionBytes / harness.projectDocMaxBytes;
15079
15079
  if (ratio >= 0.75)
15080
15080
  score = Math.max(score, 2);
@@ -17636,7 +17636,9 @@ async function runSetup(context, operations = DEFAULT_OPERATIONS) {
17636
17636
  diagnostics: doctor.diagnostics
17637
17637
  });
17638
17638
  }
17639
- if (doctor.exitCode !== EXIT_CODES.ok || baseDoctor.problemCount > 0) {
17639
+ const setupHarnessIds = new Set(detectedHarnesses.map((harness) => harness.harnessId));
17640
+ const hasBrokenSetupIntegration = detectedHarnesses.some((harness) => harness.state === "broken") || baseDoctor.providers.some((provider) => provider.state === "broken" && provider.configuredHarnesses.some((harness) => setupHarnessIds.has(harness)));
17641
+ if (hasBrokenSetupIntegration) {
17640
17642
  return commandResult({
17641
17643
  command: "setup",
17642
17644
  exitCode: EXIT_CODES["problems-found"],
@@ -17650,7 +17652,7 @@ async function runSetup(context, operations = DEFAULT_OPERATIONS) {
17650
17652
  budget: null,
17651
17653
  nextStep: {
17652
17654
  command: "token-harness doctor --verbose",
17653
- description: "Review the detected problem before changing configuration."
17655
+ description: "Review the broken active integration before changing configuration."
17654
17656
  }
17655
17657
  },
17656
17658
  diagnostics: doctor.diagnostics
@@ -17679,7 +17681,7 @@ async function runSetup(context, operations = DEFAULT_OPERATIONS) {
17679
17681
  budget: budget2.data,
17680
17682
  nextStep: healthy2 ? {
17681
17683
  command: "token-harness ui",
17682
- description: "Open the dashboard to see status, allowance, and advice."
17684
+ description: "Open the dashboard once to review status; then use your coding agent normally."
17683
17685
  } : {
17684
17686
  command: "token-harness verify --verbose",
17685
17687
  description: "Review the failed integration check."
@@ -17775,7 +17777,7 @@ async function runSetup(context, operations = DEFAULT_OPERATIONS) {
17775
17777
  budget: budget.data,
17776
17778
  nextStep: healthy ? {
17777
17779
  command: "token-harness ui",
17778
- description: "Open the dashboard to see status, allowance, and advice."
17780
+ description: "Open the dashboard once to review status; then use your coding agent normally."
17779
17781
  } : {
17780
17782
  command: "token-harness verify --verbose",
17781
17783
  description: "Review the failed integration check."
@@ -17862,8 +17864,6 @@ function upgradeAction(input) {
17862
17864
  return {
17863
17865
  kind: "package-manager-install",
17864
17866
  id: digest.slice(digest.indexOf(":") + 1, digest.indexOf(":") + 9),
17865
- // The same class the install action uses, for the same reason: an installed package is not
17866
- // reversed by restoring a file.
17867
17867
  riskClass: "delegated",
17868
17868
  requiresNetwork: input.requiresNetwork,
17869
17869
  requiresElevation: input.requiresElevation,
@@ -17874,21 +17874,10 @@ function upgradeAction(input) {
17874
17874
  `${input.packageName} is installed at ${input.installed}`
17875
17875
  ],
17876
17876
  postconditions: [`${input.packageName} reports ${input.target}`],
17877
- /**
17878
- * `package-inventory` where the channel can report what is installed, `none` otherwise.
17879
- *
17880
- * An update replaces a binary. Rolling the transaction back restores files and leaves the new
17881
- * version in place, so the executor's receipt is not boilerplate here — it is the difference
17882
- * between the machine being restored and the *configuration* being restored. With an
17883
- * inventory-capturing channel the rollback also reinstalls the previous version, and the
17884
- * receipt says per package whether that reinstall took.
17885
- */
17886
17877
  rollbackData: channelCanReportInventory(input.channel) ? "package-inventory" : "none",
17887
17878
  explanation: `Update ${input.packageName} from ${input.installed} to ${input.target} through ${input.channel}`,
17888
17879
  packageManager: input.channel,
17889
17880
  packageName: input.packageName,
17890
- // Pinned to the exact version the channel reported, not left open. An unpinned upgrade would
17891
- // install whatever is newest at execution time, which is not the version the dry run showed.
17892
17881
  version: input.target
17893
17882
  };
17894
17883
  }
@@ -17898,8 +17887,6 @@ async function runUpdate(context) {
17898
17887
  const finish3 = (exitCode, data) => commandResult({
17899
17888
  command: "update",
17900
17889
  exitCode,
17901
- // RFC 0006: `data` is null when the status is `error`, and the human renderer must read the
17902
- // same object it serializes — the defect `apply` already had to fix.
17903
17890
  data: statusForExitCode(exitCode) === "error" ? null : data,
17904
17891
  diagnostics
17905
17892
  });
@@ -17916,23 +17903,27 @@ async function runUpdate(context) {
17916
17903
  const providerAdapters = listProviderAdapters().filter((adapter) => context.provider === null || adapter.manifest.id === context.provider);
17917
17904
  const managedState = await managedIntegrations(context);
17918
17905
  const managed = managedState.integrations;
17906
+ const harnessAdapters = listHarnessAdapters();
17919
17907
  const managedHarnessIds = new Set(managed.map((entry) => entry.harnessId));
17908
+ if (managedState.legacyOwnershipUnknown) {
17909
+ for (const harness of harnessAdapters)
17910
+ managedHarnessIds.add(harness.manifest.id);
17911
+ }
17912
+ const harnessContext = {
17913
+ fs: adapters.fs,
17914
+ runner: adapters.runner,
17915
+ facts: context.platform,
17916
+ paths: adapters.paths,
17917
+ projectRoot: context.projectRoot
17918
+ };
17920
17919
  const harnessVersions = /* @__PURE__ */ new Map();
17921
- if (managedHarnessIds.size > 0) {
17922
- const harnessContext = {
17923
- fs: adapters.fs,
17924
- runner: adapters.runner,
17925
- facts: context.platform,
17926
- paths: adapters.paths,
17927
- projectRoot: context.projectRoot
17928
- };
17929
- for (const harness of listHarnessAdapters()) {
17930
- if (!managedHarnessIds.has(harness.manifest.id))
17931
- continue;
17932
- const detection = await harness.detect(harnessContext);
17933
- harnessVersions.set(harness.manifest.id, detection.version);
17934
- }
17920
+ for (const harness of harnessAdapters) {
17921
+ if (!managedHarnessIds.has(harness.manifest.id))
17922
+ continue;
17923
+ const detection = await harness.detect(harnessContext);
17924
+ harnessVersions.set(harness.manifest.id, detection.version);
17935
17925
  }
17926
+ const recoveryHarnessConfigs = managedState.legacyOwnershipUnknown ? (await Promise.all(harnessAdapters.map(async (harness) => (await harness.inspect(harnessContext)).summaries))).flat() : [];
17936
17927
  const pins = context.stateRoot === null ? { pins: /* @__PURE__ */ new Map(), unhonoredProjectPinPath: null, diagnostics: [] } : await readPins({
17937
17928
  fs: adapters.fs,
17938
17929
  stateRoot: context.stateRoot,
@@ -17945,7 +17936,7 @@ async function runUpdate(context) {
17945
17936
  facts: context.platform,
17946
17937
  paths: adapters.paths,
17947
17938
  projectRoot: context.projectRoot,
17948
- harnessConfigs: [],
17939
+ harnessConfigs: recoveryHarnessConfigs,
17949
17940
  now: context.now,
17950
17941
  localDatabase: adapters.localDatabase,
17951
17942
  projectIdFor: adapters.projectIdFor
@@ -18008,22 +17999,18 @@ async function runUpdate(context) {
18008
17999
  report.providers.push(row2);
18009
18000
  continue;
18010
18001
  }
18011
- const managedHarnesses = managed.filter((entry) => entry.providerId === adapter.manifest.id);
18012
- let updateAdmitted = !managedState.legacyOwnershipUnknown;
18002
+ const compatibilityHarnessIds = new Set(managed.filter((entry) => entry.providerId === adapter.manifest.id).map((entry) => entry.harnessId));
18013
18003
  if (managedState.legacyOwnershipUnknown) {
18014
- blockedUpdates.push({
18015
- providerId: adapter.manifest.id,
18016
- target: query.version,
18017
- harnessId: "legacy-owned-state",
18018
- missing: "a committed pre-attribution journal owns configuration but does not identify its provider and harness"
18019
- });
18004
+ for (const harnessId2 of detection.configuredHarnesses)
18005
+ compatibilityHarnessIds.add(harnessId2);
18020
18006
  }
18021
- for (const integration of managedHarnesses) {
18007
+ let updateAdmitted = true;
18008
+ for (const harnessId2 of compatibilityHarnessIds) {
18022
18009
  const admission = admitManagedMutation(context.compatibilityRows ?? COMPATIBILITY_ROWS, {
18023
18010
  provider: adapter.manifest.id,
18024
18011
  providerVersion: query.version,
18025
- harness: integration.harnessId,
18026
- harnessVersion: harnessVersions.get(integration.harnessId) ?? null,
18012
+ harness: harnessId2,
18013
+ harnessVersion: harnessVersions.get(harnessId2) ?? null,
18027
18014
  os: context.platform.os,
18028
18015
  wsl: context.platform.isWsl
18029
18016
  });
@@ -18032,8 +18019,9 @@ async function runUpdate(context) {
18032
18019
  updateAdmitted = false;
18033
18020
  blockedUpdates.push({
18034
18021
  providerId: adapter.manifest.id,
18022
+ installed: detection.version,
18035
18023
  target: query.version,
18036
- harnessId: integration.harnessId,
18024
+ harnessId: harnessId2,
18037
18025
  missing: admission.missing
18038
18026
  });
18039
18027
  }
@@ -18055,20 +18043,25 @@ async function runUpdate(context) {
18055
18043
  }));
18056
18044
  }
18057
18045
  report.network = [...destinations].sort();
18058
- const blockedIsOutcome = blockedUpdates.length > 0 && actions.length === 0;
18059
18046
  for (const blocked of blockedUpdates) {
18060
18047
  diagnostics.push(diagnostic({
18061
- severity: blockedIsOutcome ? "error" : "warning",
18048
+ severity: "info",
18062
18049
  code: "managed-update-blocked",
18063
- message: `update refuses ${blocked.providerId} ${blocked.target} on managed ${blocked.harnessId}: ${blocked.missing}`,
18064
- remediation: "Record a compatibility row and fixture for the target version before updating this managed integration"
18050
+ message: `${blocked.providerId} ${blocked.target} is available but is not validated for ${blocked.harnessId}; keeping ${blocked.installed ?? "the installed version"}`,
18051
+ remediation: "No action is required; Token Harness will allow the update after this combination has reviewed compatibility evidence"
18052
+ }));
18053
+ diagnostics.push(diagnostic({
18054
+ severity: "info",
18055
+ code: "managed-update-blocked-detail",
18056
+ message: `${blocked.providerId} ${blocked.target} compatibility evidence is missing: ${blocked.missing}`,
18057
+ remediation: null
18065
18058
  }));
18066
18059
  }
18067
18060
  if (pins.unhonoredProjectPinPath !== null) {
18068
18061
  }
18069
18062
  if (actions.length === 0 && blockedUpdates.length > 0) {
18070
- report.execution = emptyExecution("rejected");
18071
- return finish3(EXIT_CODES["unsupported-environment"], report);
18063
+ report.execution = emptyExecution("nothing-to-do");
18064
+ return finish3(EXIT_CODES.ok, report);
18072
18065
  }
18073
18066
  if (actions.length === 0) {
18074
18067
  report.execution = emptyExecution("nothing-to-do");
@@ -18085,7 +18078,6 @@ async function runUpdate(context) {
18085
18078
  diagnostics.push(diagnostic({
18086
18079
  severity: "error",
18087
18080
  code: "confirmation-required",
18088
- // In the message and not only in `data`: exit 8 is an `error` status, so `data` is null.
18089
18081
  message: `Would update ${summary}`,
18090
18082
  remediation: "Re-run with `--yes` to apply it"
18091
18083
  }));
@@ -18136,8 +18128,6 @@ async function runUpdate(context) {
18136
18128
  planId: null,
18137
18129
  transactionId,
18138
18130
  fromStoredPlan: false,
18139
- // Mapped the way `apply` maps it: `in-progress` is not a terminal outcome a report may
18140
- // carry, and anything that is not one of the three known ends is a rejection.
18141
18131
  outcome: transaction.journal.outcome === "committed" ? "committed" : transaction.journal.outcome === "rolled-back" ? "rolled-back" : transaction.journal.outcome === "dirty" ? "dirty" : "rejected",
18142
18132
  results: transaction.journal.entries.map((entry) => ({
18143
18133
  actionId: entry.actionId,
@@ -19421,32 +19411,53 @@ function harnessName(id) {
19421
19411
  return "Codex";
19422
19412
  if (id === "opencode")
19423
19413
  return "OpenCode";
19414
+ if (id === "pi")
19415
+ return "Pi";
19416
+ if (id === "hermes")
19417
+ return "Hermes";
19418
+ return id;
19419
+ }
19420
+ function providerName(id) {
19421
+ if (id === "rtk")
19422
+ return "RTK";
19423
+ if (id === "harnesstrim")
19424
+ return "HarnessTrim";
19424
19425
  return id;
19425
19426
  }
19427
+ function normalWork() {
19428
+ return "Use your coding agent normally; configured optimizers run automatically.";
19429
+ }
19430
+ function usefulEvidence(evidence2) {
19431
+ const useful = evidence2.find((item) => !/^0B known loaded of /i.test(item.summary) && !/^0 MCP servers/i.test(item.summary) && !/^0B of instruction candidates/i.test(item.summary));
19432
+ return useful?.summary ?? evidence2[0]?.summary ?? null;
19433
+ }
19426
19434
  function renderSimpleDoctor(report) {
19427
19435
  const present = report.harnesses.filter((item) => item.state !== "absent");
19428
19436
  const active = report.providers.filter((item) => item.state === "configured" && item.configuredHarnesses.length > 0);
19429
- const state = report.problemCount > 0 ? "attention needed" : present.length > 0 ? "ready" : "setup needed";
19437
+ const broken = present.some((item) => item.state === "broken") || report.providers.some((item) => item.state === "broken");
19438
+ const newerThanTested = [...present, ...report.providers].some((item) => item.versionVerdict === "unknown-newer");
19439
+ const state = broken ? "attention needed" : newerThanTested ? "ready with limitations" : present.length > 0 ? "ready" : "setup needed";
19430
19440
  const lines = [...title(state), "WHAT WORKS"];
19431
19441
  if (present.length === 0)
19432
19442
  lines.push(" No supported coding harness was found.");
19433
- for (const item of report.harnesses) {
19434
- const stateText = item.state === "absent" ? "not found" : item.state;
19435
- lines.push(` ${harnessName(item.harnessId)}: ${stateText}${item.version ? ` (${item.version})` : ""}`);
19443
+ for (const item of present) {
19444
+ lines.push(` ${harnessName(item.harnessId)}: ${item.state}${item.version ? ` (${item.version})` : ""}`);
19436
19445
  }
19437
- if (report.providers.length === 0)
19438
- lines.push(" Providers: none detected");
19439
- for (const item of report.providers) {
19446
+ if (active.length === 0)
19447
+ lines.push(" Optimization provider: none active");
19448
+ for (const item of active) {
19440
19449
  const connected = item.configuredHarnesses.map(harnessName).join(", ");
19441
- lines.push(truncate(` ${item.providerId}: ${connected === "" ? item.state : `active on ${connected}`}`, MAX_WIDTH));
19450
+ lines.push(truncate(` ${providerName(item.providerId)}: active on ${connected}`, MAX_WIDTH));
19442
19451
  }
19443
19452
  lines.push(...changeLine(false));
19444
- if (report.problemCount > 0) {
19445
- lines.push(...next("token-harness doctor --verbose", "Review the technical findings."));
19453
+ if (broken) {
19454
+ lines.push(...next("token-harness doctor --verbose", "Review the integration that needs attention."));
19446
19455
  } else if (present.length === 0 || active.length === 0) {
19447
19456
  lines.push(...next("token-harness setup", "Finish the guided setup."));
19457
+ } else if (newerThanTested) {
19458
+ lines.push(...next("token-harness verify", "You can keep working; verify the active integrations when convenient."));
19448
19459
  } else {
19449
- lines.push(...next("token-harness ui", "Open the dashboard."));
19460
+ lines.push(...next(null, normalWork()));
19450
19461
  }
19451
19462
  return document(lines);
19452
19463
  }
@@ -19463,7 +19474,7 @@ function renderSimpleSetup(report, context) {
19463
19474
  if (active.length === 0)
19464
19475
  lines.push(" Optimization provider: not active");
19465
19476
  for (const provider of active) {
19466
- lines.push(truncate(` ${provider.providerId}: active on ${provider.configuredHarnesses.map(harnessName).join(", ")}`, MAX_WIDTH));
19477
+ lines.push(truncate(` ${providerName(provider.providerId)}: active on ${provider.configuredHarnesses.map(harnessName).join(", ")}`, MAX_WIDTH));
19467
19478
  }
19468
19479
  if (report.plan !== null && report.apply === null && report.plan.actions.length > 0) {
19469
19480
  lines.push("", "SAFE PLAN");
@@ -19473,7 +19484,7 @@ function renderSimpleSetup(report, context) {
19473
19484
  }
19474
19485
  }
19475
19486
  lines.push(...changeLine(report.changed, report.apply?.results.some((item) => item.status === "applied") ? "Safe configuration applied and checked." : void 0));
19476
- lines.push(...next(report.nextStep.command, report.nextStep.description));
19487
+ lines.push(...next(report.nextStep.command, report.stage === "ready" && report.nextStep.command === "token-harness ui" ? "Open the dashboard once to review status; after that use your coding agent normally." : report.nextStep.description));
19477
19488
  return document(lines);
19478
19489
  }
19479
19490
  function renderVerboseSetup(report, context) {
@@ -19546,7 +19557,7 @@ function renderSimpleBudget(report) {
19546
19557
  }
19547
19558
  }
19548
19559
  lines.push(...changeLine(false));
19549
- lines.push(...next(observed.length > 0 ? "token-harness optimize" : "token-harness setup", observed.length > 0 ? "See the best action for the current allowance." : "Check the local installation and connections."));
19560
+ lines.push(...next(observed.length > 0 ? "token-harness optimize" : "token-harness setup", observed.length > 0 ? "Get advice for the task you are about to start." : "Check the local installation and connections."));
19550
19561
  return document(lines);
19551
19562
  }
19552
19563
  function renderSimpleContext(report) {
@@ -19567,7 +19578,7 @@ function renderSimpleMcp(report) {
19567
19578
  lines.push(` ${harnessName(harness.harnessId)}: ${harness.servers.length} servers, ${harness.knownToolCount} known tools`);
19568
19579
  }
19569
19580
  lines.push(...changeLine(false));
19570
- lines.push(...next(attention ? "token-harness mcp --verbose" : "token-harness optimize", attention ? "Review the server that needs attention." : "See whether context can be simplified."));
19581
+ lines.push(...next(attention ? "token-harness mcp --verbose" : "token-harness optimize", attention ? "Review the server that needs attention." : "See whether context can be simplified for the next task."));
19571
19582
  return document(lines);
19572
19583
  }
19573
19584
  function renderSimpleOptimize(report) {
@@ -19579,15 +19590,15 @@ function renderSimpleOptimize(report) {
19579
19590
  if (advice.length === 0)
19580
19591
  lines.push(" No supported harness could be assessed.");
19581
19592
  for (const harness of advice) {
19582
- const recommendation = harness.recommendations.find((item) => item.priority === "first") ?? harness.recommendations[0];
19593
+ const recommendation = harness.recommendations.find((item) => item.priority === "first") ?? harness.recommendations.find((item) => item.priority === "next");
19583
19594
  lines.push(truncate(` ${harnessName(harness.harnessId)}: ${recommendation?.action ?? "No change recommended."}`, MAX_WIDTH));
19584
- const evidence2 = recommendation?.evidence[0]?.summary;
19595
+ const evidence2 = recommendation === void 0 ? null : usefulEvidence(recommendation.evidence);
19585
19596
  if (evidence2)
19586
19597
  lines.push(truncate(` Why: ${evidence2}`, MAX_WIDTH));
19587
19598
  }
19588
19599
  lines.push(...changeLine(false));
19589
19600
  const canPlan = advice.some((item) => item.recommendedEffort !== item.currentEffort || item.recommendedVerbosity !== item.currentVerbosity);
19590
- lines.push(...next(canPlan ? "token-harness plan --native-policy" : "token-harness ui", canPlan ? "Review the reversible recommended policy change." : "Keep the dashboard open for the next decision."));
19601
+ lines.push(...next(canPlan ? "token-harness plan --native-policy" : null, canPlan ? "Review the reversible recommended policy change." : "No change is required now. " + normalWork()));
19591
19602
  return document(lines);
19592
19603
  }
19593
19604
  function renderSimplePlan(report, context) {
@@ -19616,9 +19627,9 @@ function renderSimplePlan(report, context) {
19616
19627
  else if (report.actions.length > 0 && report.persisted && report.planId !== null)
19617
19628
  lines.push(...next(`token-harness apply --plan ${report.planId} --yes`, "Apply exactly this stored plan."));
19618
19629
  else if (report.actions.length === 0)
19619
- lines.push(...next("token-harness setup", "Check detection and finish guided setup."));
19630
+ lines.push(...report.pipelineId === null ? next("token-harness setup", "Check detection and finish guided setup.") : next(null, normalWork()));
19620
19631
  else
19621
- lines.push(...next("token-harness ui", "Open the dashboard."));
19632
+ lines.push(...next("token-harness ui", "Open the dashboard to review the current state."));
19622
19633
  return document(lines);
19623
19634
  }
19624
19635
  function renderSimpleApply(report, command) {
@@ -19633,7 +19644,7 @@ function renderSimpleApply(report, command) {
19633
19644
  lines.push(` Transaction: ${report.transactionId ?? "none"}`);
19634
19645
  lines.push(...changeLine(changed, command === "uninstall" ? "Owned configuration removed." : command === "rollback" ? "Previous configuration restored." : "Configuration applied and committed."));
19635
19646
  const confirmationCommand = command === "apply" && report.planId !== null ? `token-harness apply --plan ${report.planId} --yes` : `token-harness ${command} --yes`;
19636
- lines.push(...next(okay ? "token-harness verify" : report.outcome === "confirmation-required" ? confirmationCommand : `token-harness ${command} --verbose`, okay ? "Check that the integration works." : report.outcome === "confirmation-required" ? "Apply the reviewed change." : "Review the technical result."));
19647
+ lines.push(...next(okay ? "token-harness verify" : report.outcome === "confirmation-required" ? confirmationCommand : `token-harness ${command} --verbose`, okay ? "Check that the integration works; a successful verify is the end of setup." : report.outcome === "confirmation-required" ? "Apply the reviewed change." : "Review the technical result."));
19637
19648
  return document(lines);
19638
19649
  }
19639
19650
  function renderSimpleVerify(report) {
@@ -19644,9 +19655,9 @@ function renderSimpleVerify(report) {
19644
19655
  if (report.results.length === 0)
19645
19656
  lines.push(" Nothing is configured to verify yet.");
19646
19657
  for (const item of report.results)
19647
- lines.push(truncate(` ${item.providerId} on ${harnessName(item.harnessId)}: ${item.status}`, MAX_WIDTH));
19658
+ lines.push(truncate(` ${providerName(item.providerId)} on ${harnessName(item.harnessId)}: ${item.status}`, MAX_WIDTH));
19648
19659
  lines.push(...changeLine(false));
19649
- lines.push(...next(report.healthyAtDeclaredTier ? "token-harness ui" : "token-harness verify --verbose", report.healthyAtDeclaredTier ? "Open the dashboard." : "Review the failed check and suggested fix."));
19660
+ lines.push(...next(report.healthyAtDeclaredTier ? null : "token-harness verify --verbose", report.healthyAtDeclaredTier ? normalWork() : "Review the failed check and suggested fix."));
19650
19661
  return document(lines);
19651
19662
  }
19652
19663
  function renderSimpleStatus(report) {
@@ -19655,11 +19666,11 @@ function renderSimpleStatus(report) {
19655
19666
  lines.push(" No Token Harness pipeline is active.");
19656
19667
  for (const pipeline of report.pipelines) {
19657
19668
  const providers = [...new Set(pipeline.owners.map((owner) => owner.owner))];
19658
- lines.push(truncate(` ${harnessName(pipeline.harness)}: ${providers.join(" -> ") || "no provider"}`, MAX_WIDTH));
19669
+ lines.push(truncate(` ${harnessName(pipeline.harness)}: ${providers.map(providerName).join(" -> ") || "no provider"}`, MAX_WIDTH));
19659
19670
  }
19660
19671
  lines.push(` Drift: ${report.drift.length === 0 ? "none" : report.drift.length}`);
19661
19672
  lines.push(...changeLine(false));
19662
- lines.push(...next(report.problemCount === 0 ? report.pipelines.length === 0 ? "token-harness setup" : "token-harness ui" : "token-harness status --verbose", report.problemCount === 0 ? report.pipelines.length === 0 ? "Finish the guided setup." : "Open the dashboard." : "Review the drift before making changes."));
19673
+ lines.push(...next(report.problemCount === 0 ? report.pipelines.length === 0 ? "token-harness setup" : null : "token-harness status --verbose", report.problemCount === 0 ? report.pipelines.length === 0 ? "Finish the guided setup." : normalWork() : "Review the drift before making changes."));
19663
19674
  return document(lines);
19664
19675
  }
19665
19676
  function renderSimpleMetrics(report) {
@@ -19671,7 +19682,7 @@ function renderSimpleMetrics(report) {
19671
19682
  lines.push(` ${item.class}: ${formatCount(item.saved ?? 0)} ${item.unit ?? ""} saved`);
19672
19683
  lines.push(` Errors: ${report.errors}`);
19673
19684
  lines.push(...changeLine(false));
19674
- lines.push(...next("token-harness optimize", "Get the next evidence-based recommendation."));
19685
+ lines.push(...next(null, "Measurement is complete. Use optimize before a task only when you want fresh advice."));
19675
19686
  return document(lines);
19676
19687
  }
19677
19688
  function renderSimpleHistory(report) {
@@ -19681,9 +19692,26 @@ function renderSimpleHistory(report) {
19681
19692
  for (const item of report.harnesses)
19682
19693
  lines.push(` ${harnessName(item.harnessId)}: ${formatCount(item.totalTokens)} tokens, trend ${item.burnTrend.state}`);
19683
19694
  lines.push(...changeLine(false));
19684
- lines.push(...next("token-harness optimize", "Use the history in the next recommendation."));
19695
+ lines.push(...next(null, "History is informational. Run token-harness optimize when you want task-specific advice."));
19685
19696
  return document(lines);
19686
19697
  }
19698
+ function updateStatus(item) {
19699
+ if (item.verdict === "current")
19700
+ return `${item.installed ?? "installed"} is current`;
19701
+ if (item.verdict === "pinned")
19702
+ return `kept at ${item.pin ?? item.installed ?? "installed"} (pinned)`;
19703
+ if (item.verdict === "blocked-unreviewed")
19704
+ return `${item.available ?? "newer version"} available; keeping ${item.installed ?? "installed"} until validated`;
19705
+ if (item.verdict === "upgradable")
19706
+ return `${item.installed ?? "installed"} -> ${item.available ?? "newer version"} ready`;
19707
+ if (item.verdict === "not-installed")
19708
+ return "not installed";
19709
+ if (item.verdict === "no-channel")
19710
+ return "installed; no supported update channel";
19711
+ if (item.verdict === "unavailable")
19712
+ return "installed; update check unavailable";
19713
+ return "installed; update status unknown";
19714
+ }
19687
19715
  function renderSimpleUpdate(report) {
19688
19716
  const execution = report.execution;
19689
19717
  const changed = execution?.outcome === "committed" && execution.results.some((item) => item.status === "applied");
@@ -19691,10 +19719,11 @@ function renderSimpleUpdate(report) {
19691
19719
  if (report.providers.length === 0)
19692
19720
  lines.push(" No provider was detected.");
19693
19721
  for (const item of report.providers)
19694
- lines.push(truncate(` ${item.providerId}: ${item.verdict}`, MAX_WIDTH));
19722
+ lines.push(truncate(` ${providerName(item.providerId)}: ${updateStatus(item)}`, MAX_WIDTH));
19695
19723
  lines.push(...changeLine(changed, "Provider update applied."));
19696
19724
  const pending = report.providers.some((item) => item.verdict === "upgradable");
19697
- lines.push(...next(pending && execution?.outcome === "confirmation-required" ? "token-harness update --yes" : "token-harness verify", pending && execution?.outcome === "confirmation-required" ? "Apply the reviewed provider update." : "Check that integrations still work."));
19725
+ const deferred = report.providers.some((item) => item.verdict === "blocked-unreviewed");
19726
+ lines.push(...next(pending && execution?.outcome === "confirmation-required" ? "token-harness update --yes" : changed ? "token-harness verify" : null, pending && execution?.outcome === "confirmation-required" ? "Apply the reviewed provider update." : changed ? "Check that the updated integrations still work." : deferred ? "No action required. The installed versions stay active until newer ones are validated." : normalWork()));
19698
19727
  return document(lines);
19699
19728
  }
19700
19729
  var init_simple = __esm({
@@ -20463,59 +20492,129 @@ function nameOf(id) {
20463
20492
  return "Codex";
20464
20493
  if (id === "opencode")
20465
20494
  return "OpenCode";
20495
+ if (id === "pi")
20496
+ return "Pi";
20497
+ if (id === "hermes")
20498
+ return "Hermes";
20499
+ return id;
20500
+ }
20501
+ function providerName2(id) {
20502
+ if (id === "harnesstrim")
20503
+ return "HarnessTrim";
20504
+ if (id === "rtk")
20505
+ return "RTK";
20466
20506
  return id;
20467
20507
  }
20508
+ function usefulReason(evidence2) {
20509
+ const useful = evidence2.find((item) => !/^0B known loaded of /i.test(item.summary) && !/^0 MCP servers/i.test(item.summary) && !/^0B of instruction candidates/i.test(item.summary));
20510
+ return useful?.summary ?? evidence2[0]?.summary ?? null;
20511
+ }
20468
20512
  function buildDashboardModel(input) {
20469
20513
  const present = input.doctor.harnesses.filter((item) => item.state !== "absent");
20470
- const configured = input.doctor.providers.filter((item) => item.state === "configured" && item.configuredHarnesses.length > 0);
20471
- const hasProblems = input.doctor.problemCount > 0 || input.status.problemCount > 0;
20472
- const state = hasProblems ? "attention" : present.length === 0 || configured.length === 0 ? "setup-needed" : "ready";
20473
- const recommendation = input.optimize.harnesses.flatMap((harness) => harness.recommendations.map((item) => ({
20514
+ const connectedProviders = input.doctor.providers.filter((item) => item.configuredHarnesses.length > 0);
20515
+ const configuredProviders = connectedProviders.filter((item) => item.state === "configured");
20516
+ const relevantHarnessIds = /* @__PURE__ */ new Set();
20517
+ for (const provider of connectedProviders) {
20518
+ for (const harness of provider.configuredHarnesses)
20519
+ relevantHarnessIds.add(harness);
20520
+ }
20521
+ for (const item of input.budget.harnesses) {
20522
+ if (item.windows.length > 0)
20523
+ relevantHarnessIds.add(item.harnessId);
20524
+ }
20525
+ for (const pipeline of input.status.pipelines)
20526
+ relevantHarnessIds.add(pipeline.harness);
20527
+ const relevantHarnesses = present.filter((harness) => relevantHarnessIds.has(harness.harnessId));
20528
+ const broken = relevantHarnesses.some((item) => item.state === "broken") || connectedProviders.some((item) => item.state === "broken");
20529
+ const newerThanTested = relevantHarnesses.some((item) => item.versionVerdict === "unknown-newer") || connectedProviders.some((item) => item.versionVerdict === "unknown-newer");
20530
+ const state = present.length === 0 ? "setup-needed" : broken || input.status.problemCount > 0 ? "action-needed" : configuredProviders.length === 0 ? "setup-needed" : newerThanTested ? "limited" : "ready";
20531
+ const rankedRecommendations = input.optimize.harnesses.filter((harness) => harness.state !== "absent" && relevantHarnessIds.has(harness.harnessId)).flatMap((harness) => harness.recommendations.map((item) => ({
20474
20532
  harness: harness.harnessId,
20475
20533
  priority: item.priority,
20476
20534
  action: item.action,
20477
- reason: item.evidence[0]?.summary ?? null
20535
+ reason: usefulReason(item.evidence)
20478
20536
  }))).sort((left, right) => {
20479
20537
  const rank = { first: 0, next: 1, optional: 2 };
20480
20538
  return rank[left.priority] - rank[right.priority];
20481
- })[0];
20482
- const nextStep = state === "setup-needed" ? { command: "token-harness setup", description: "Finish the guided setup." } : state === "attention" ? {
20483
- command: "token-harness doctor --verbose",
20484
- description: "Review the detected problem before changing anything."
20539
+ });
20540
+ const recommendation = rankedRecommendations.find((item) => item.priority !== "optional");
20541
+ const harnesses = relevantHarnesses.map((harness) => {
20542
+ const providerIds = configuredProviders.filter((provider) => provider.configuredHarnesses.includes(harness.harnessId)).map((provider) => provider.providerId);
20543
+ const budget = input.budget.harnesses.find((item) => item.harnessId === harness.harnessId);
20544
+ const health = harness.state === "broken" ? "attention" : harness.versionVerdict === "unknown-newer" ? "limited" : "active";
20545
+ const statusLabel = health === "attention" ? "Needs attention" : health === "limited" ? "Works \xB7 newer than tested" : providerIds.length > 0 ? "Optimized" : "Available";
20546
+ return {
20547
+ id: harness.harnessId,
20548
+ name: nameOf(harness.harnessId),
20549
+ health,
20550
+ statusLabel,
20551
+ version: harness.version,
20552
+ providers: providerIds.map(providerName2),
20553
+ allowance: (budget?.windows ?? []).map((window) => ({
20554
+ label: window.bucketName ?? window.scope,
20555
+ remainingPercent: window.remainingPercent,
20556
+ resetsAt: window.resetsAt,
20557
+ confidence: window.confidence
20558
+ }))
20559
+ };
20560
+ });
20561
+ const otherHarnesses = present.filter((harness) => !relevantHarnessIds.has(harness.harnessId)).map((harness) => ({ name: nameOf(harness.harnessId), version: harness.version }));
20562
+ const providers = configuredProviders.map((provider) => ({
20563
+ id: provider.providerId,
20564
+ name: providerName2(provider.providerId),
20565
+ harnesses: provider.configuredHarnesses.map(nameOf)
20566
+ }));
20567
+ const copy = state === "ready" ? {
20568
+ statusLabel: "READY",
20569
+ headline: "Everything important is connected.",
20570
+ summary: "Token Harness is already active through your configured integrations. This dashboard is for status and guidance; it is not a launcher.",
20571
+ nextStep: {
20572
+ command: null,
20573
+ title: "Use your coding agent normally",
20574
+ description: "Open Claude Code, Codex, or OpenCode exactly as you normally do. RTK and HarnessTrim run automatically where they are configured."
20575
+ }
20576
+ } : state === "limited" ? {
20577
+ statusLabel: "READY WITH LIMITATIONS",
20578
+ headline: "You can keep working.",
20579
+ summary: "An active integration uses a version newer than the tested range. Token Harness will keep working read-only and stay conservative about changes.",
20580
+ nextStep: {
20581
+ command: "token-harness verify",
20582
+ title: "Verify the active integrations",
20583
+ description: "Keep using your coding agents normally. Run this check when you want evidence that the configured interception still works."
20584
+ }
20585
+ } : state === "action-needed" ? {
20586
+ statusLabel: "ACTION NEEDED",
20587
+ headline: "One active integration needs attention.",
20588
+ summary: "Do not change providers yet. Review the live pipeline or configuration issue first; your other working integrations can remain untouched.",
20589
+ nextStep: {
20590
+ command: input.status.problemCount > 0 ? "token-harness status --verbose" : "token-harness doctor --verbose",
20591
+ title: "Review the specific problem",
20592
+ description: "The detailed command is only for the integration that needs attention. It is not part of the normal daily workflow."
20593
+ }
20485
20594
  } : {
20486
- command: "token-harness optimize",
20487
- description: "Refresh advice for the task you are about to start."
20595
+ statusLabel: "SETUP NEEDED",
20596
+ headline: "Finish the one-time setup.",
20597
+ summary: "A supported coding agent was not found with an active optimization provider yet.",
20598
+ nextStep: {
20599
+ command: "token-harness setup",
20600
+ title: "Continue guided setup",
20601
+ description: "Token Harness will detect what is available and propose only supported changes."
20602
+ }
20488
20603
  };
20489
20604
  return {
20490
20605
  generatedAt: input.generatedAt,
20491
20606
  state,
20492
- headline: state === "ready" ? "Your coding harnesses are connected." : state === "attention" ? "One or more checks need attention." : "Finish setup to activate Token Harness.",
20493
- harnesses: input.doctor.harnesses.map((harness) => {
20494
- const budget = input.budget.harnesses.find((item) => item.harnessId === harness.harnessId);
20495
- return {
20496
- id: harness.harnessId,
20497
- name: nameOf(harness.harnessId),
20498
- state: harness.state,
20499
- version: harness.version,
20500
- providers: input.doctor.providers.filter((provider) => provider.configuredHarnesses.includes(harness.harnessId)).map((provider) => provider.providerId),
20501
- allowance: (budget?.windows ?? []).map((window) => ({
20502
- label: window.bucketName ?? window.scope,
20503
- remainingPercent: window.remainingPercent,
20504
- resetsAt: window.resetsAt,
20505
- confidence: window.confidence
20506
- }))
20507
- };
20508
- }),
20509
- providers: input.doctor.providers.map((provider) => ({
20510
- id: provider.providerId,
20511
- state: provider.state,
20512
- harnesses: provider.configuredHarnesses.map(nameOf)
20513
- })),
20607
+ statusLabel: copy.statusLabel,
20608
+ headline: copy.headline,
20609
+ summary: copy.summary,
20610
+ harnesses,
20611
+ otherHarnesses,
20612
+ providers,
20514
20613
  recommendation: recommendation === void 0 ? null : {
20515
20614
  action: `${nameOf(recommendation.harness)}: ${recommendation.action}`,
20516
20615
  reason: recommendation.reason
20517
20616
  },
20518
- nextStep
20617
+ nextStep: copy.nextStep
20519
20618
  };
20520
20619
  }
20521
20620
  function uiAsset(path, model) {
@@ -20537,40 +20636,86 @@ var UI_USAGE, DASHBOARD_HTML, DASHBOARD_CSS, DASHBOARD_JS;
20537
20636
  var init_ui = __esm({
20538
20637
  "apps/cli/dist/src/ui.js"() {
20539
20638
  "use strict";
20540
- UI_USAGE = `token-harness ui \u2014 open a simple local dashboard
20639
+ UI_USAGE = `token-harness ui \u2014 open the local status and guidance dashboard
20541
20640
 
20542
20641
  Usage
20543
20642
  token-harness ui [--no-open] [--port <number>] [--json]
20544
20643
 
20545
- The dashboard listens only on 127.0.0.1 and reads the same reports as the CLI.
20546
- It does not send data anywhere and cannot change configuration. Close it with
20547
- Ctrl+C. Use --json for one complete dashboard snapshot without starting a server.`;
20644
+ The dashboard listens only on 127.0.0.1 and is read-only.
20645
+ It does not send data anywhere and cannot change configuration.
20646
+ It shows what is active, what needs attention, and what to do next. When the setup is ready,
20647
+ keep using Claude Code, Codex, or OpenCode normally \u2014 Token Harness does not replace their
20648
+ launch commands. Close the local dashboard server with Ctrl+C.`;
20548
20649
  DASHBOARD_HTML = `<!doctype html>
20549
20650
  <html lang="en">
20550
20651
  <head>
20551
20652
  <meta charset="utf-8">
20552
20653
  <meta name="viewport" content="width=device-width, initial-scale=1">
20553
- <meta name="color-scheme" content="dark">
20654
+ <meta name="color-scheme" content="light dark">
20554
20655
  <title>Token Harness</title>
20555
20656
  <link rel="stylesheet" href="/app.css">
20556
20657
  </head>
20557
20658
  <body>
20558
20659
  <a class="skip" href="#main">Skip to dashboard</a>
20559
- <header><div class="brand"><span class="mark">TH</span><span>Token Harness</span></div><button id="refresh" type="button">Refresh</button></header>
20660
+ <header class="topbar">
20661
+ <div class="brand"><span class="mark" aria-hidden="true">TH</span><span>Token Harness</span></div>
20662
+ <button id="refresh" class="secondary-button" type="button">Refresh</button>
20663
+ </header>
20560
20664
  <main id="main">
20561
- <section class="hero" aria-labelledby="headline"><p class="eyebrow">LOCAL STATUS</p><h1 id="headline">Checking your harnesses...</h1><p id="updated" class="muted" aria-live="polite"></p></section>
20562
- <section id="harnesses" class="grid" aria-label="Harness status"></section>
20563
- <section class="panel recommendation"><p class="eyebrow">RECOMMENDATION</p><h2 id="recommendation">Waiting for observations...</h2><p id="reason" class="muted"></p></section>
20564
- <section class="panel next"><div><p class="eyebrow">NEXT STEP</p><code id="command">token-harness setup</code><p id="description" class="muted"></p></div><button id="copy" type="button">Copy command</button></section>
20565
- <section class="panel"><p class="eyebrow">PROVIDERS</p><div id="providers" class="provider-list"></div></section>
20665
+ <section class="hero" aria-labelledby="headline">
20666
+ <div id="status" class="status-chip">CHECKING</div>
20667
+ <h1 id="headline">Checking your setup...</h1>
20668
+ <p id="summary" class="hero-copy">Reading local status and guidance.</p>
20669
+ <p id="updated" class="timestamp" aria-live="polite"></p>
20670
+ </section>
20671
+
20672
+ <section class="action-card" aria-labelledby="next-title">
20673
+ <div class="action-copy">
20674
+ <p class="eyebrow">WHAT TO DO NOW</p>
20675
+ <h2 id="next-title">Checking the next step...</h2>
20676
+ <p id="description" class="supporting"></p>
20677
+ </div>
20678
+ <div id="command-row" class="command-row" hidden>
20679
+ <code id="command"></code>
20680
+ <button id="copy" class="primary-button" type="button">Copy command</button>
20681
+ </div>
20682
+ </section>
20683
+
20684
+ <section class="section" aria-labelledby="active-title">
20685
+ <div class="section-heading">
20686
+ <div><p class="eyebrow">ACTIVE SETUP</p><h2 id="active-title">What is working</h2></div>
20687
+ <p class="section-note">Only active or relevant tools are shown here.</p>
20688
+ </div>
20689
+ <div id="harnesses" class="harness-grid" aria-live="polite"></div>
20690
+ </section>
20691
+
20692
+ <section id="recommendation-panel" class="recommendation-card" aria-labelledby="recommendation-title" hidden>
20693
+ <p class="eyebrow">USEFUL NOW</p>
20694
+ <h2 id="recommendation-title">Recommendation</h2>
20695
+ <p id="recommendation" class="recommendation-action"></p>
20696
+ <p id="reason" class="supporting"></p>
20697
+ </section>
20698
+
20699
+ <section id="providers-panel" class="compact-panel" aria-labelledby="providers-title" hidden>
20700
+ <div><p class="eyebrow">ACTIVE OPTIMIZERS</p><h2 id="providers-title">Providers</h2></div>
20701
+ <ul id="providers" class="provider-list"></ul>
20702
+ </section>
20703
+
20704
+ <details id="other-panel" class="details-panel" hidden>
20705
+ <summary id="other-summary">Other detected tools</summary>
20706
+ <ul id="other-harnesses" class="secondary-list"></ul>
20707
+ </details>
20708
+
20566
20709
  <p id="error" class="error" role="alert"></p>
20567
20710
  </main>
20568
- <footer>Private by design. Served only from this computer.</footer>
20711
+ <footer>
20712
+ <strong>Local and read-only.</strong> You can close this page whenever you want. Configured optimizers keep working through their normal harness integrations.
20713
+ </footer>
20569
20714
  <script src="/app.js" defer></script>
20570
20715
  </body>
20571
20716
  </html>`;
20572
- DASHBOARD_CSS = `:root{font-family:Inter,ui-sans-serif,system-ui,-apple-system,sans-serif;color:#f8fafc;background:#0f172a;font-synthesis:none}*{box-sizing:border-box}body{margin:0;min-height:100vh;background:radial-gradient(circle at 90% 0,#172554 0,transparent 32rem),#0f172a}button{min-height:44px;border:1px solid #475569;border-radius:10px;background:#1e293b;color:#f8fafc;padding:0 1rem;font:inherit;font-weight:700;cursor:pointer}button:hover{background:#334155}button:focus-visible,a:focus-visible{outline:3px solid #38bdf8;outline-offset:3px}.skip{position:absolute;left:-999px;top:1rem;color:#fff}.skip:focus{left:1rem}header,main,footer{width:min(1120px,calc(100% - 2rem));margin-inline:auto}header{height:76px;display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid #334155}.brand{display:flex;align-items:center;gap:.75rem;font-weight:800}.mark{display:grid;place-items:center;width:38px;height:38px;border-radius:10px;background:#22c55e;color:#052e16;font:800 14px ui-monospace,monospace}.hero{padding:4.5rem 0 2rem}.eyebrow{margin:0 0 .65rem;color:#22c55e;font:700 .75rem ui-monospace,monospace;letter-spacing:.12em}.hero h1{max-width:760px;margin:0 0 .8rem;font-size:clamp(2rem,5vw,4.4rem);line-height:1.02;letter-spacing:-.045em}.muted{color:#94a3b8;line-height:1.6}.grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:1rem}.panel,.card{border:1px solid #334155;border-radius:16px;background:#172033;padding:1.4rem;box-shadow:0 16px 40px #02061733}.card-top,.next{display:flex;align-items:flex-start;justify-content:space-between;gap:1rem}.badge{border-radius:999px;padding:.35rem .65rem;background:#334155;color:#cbd5e1;font:700 .72rem ui-monospace,monospace}.badge.ready{background:#14532d;color:#bbf7d0}.badge.attention{background:#713f12;color:#fef3c7}.card h2,.panel h2{margin:.15rem 0;font-size:1.25rem}.meta{margin:.35rem 0 1.2rem;color:#94a3b8}.quota{margin-top:1rem}.quota-row{display:flex;justify-content:space-between;gap:1rem;margin-bottom:.45rem;font-size:.9rem}.quota-meta{margin:.45rem 0 0;color:#64748b;font-size:.78rem}.track{height:8px;border-radius:999px;background:#334155;overflow:hidden}.fill{height:100%;background:#22c55e;border-radius:inherit}.recommendation{margin-top:1rem}.next{margin-top:1rem;align-items:center}.next code{display:block;color:#e2e8f0;font-size:1rem;overflow-wrap:anywhere}.provider-list{display:flex;flex-wrap:wrap;gap:.65rem}.provider{border:1px solid #475569;border-radius:10px;padding:.65rem .8rem;color:#cbd5e1}.panel{margin-top:1rem}.error{color:#fecaca}.empty{color:#94a3b8}footer{padding:2.5rem 0;color:#64748b;font-size:.85rem}@media(max-width:720px){.grid{grid-template-columns:1fr}.hero{padding-top:3rem}.next{align-items:stretch;flex-direction:column}.next button{width:100%}}@media(prefers-reduced-motion:reduce){*{scroll-behavior:auto!important}}`;
20573
- DASHBOARD_JS = `const byId=(id)=>document.getElementById(id);const text=(id,value)=>{byId(id).textContent=value};function badgeState(state){return state==='configured'||state==='detected'?'ready':state==='broken'?'attention':''}function render(model){text('headline',model.headline);text('updated','Updated '+new Date(model.generatedAt).toLocaleString());const harnesses=byId('harnesses');harnesses.replaceChildren();for(const item of model.harnesses){const card=document.createElement('article');card.className='card';const top=document.createElement('div');top.className='card-top';const heading=document.createElement('h2');heading.textContent=item.name;const badge=document.createElement('span');badge.className='badge '+badgeState(item.state);badge.textContent=item.state;top.append(heading,badge);card.append(top);const meta=document.createElement('p');meta.className='meta';meta.textContent=(item.version?'Version '+item.version+' \xB7 ':'')+(item.providers.length?item.providers.join(', ')+' active':'no provider active');card.append(meta);if(item.allowance.length===0){const empty=document.createElement('p');empty.className='empty';empty.textContent='Allowance unavailable';card.append(empty)}for(const quota of item.allowance){const box=document.createElement('div');box.className='quota';const row=document.createElement('div');row.className='quota-row';const label=document.createElement('span');label.textContent=quota.label;const value=document.createElement('strong');value.textContent=quota.remainingPercent===null?'Unknown':quota.remainingPercent+'% left';row.append(label,value);const track=document.createElement('div');track.className='track';track.setAttribute('role','progressbar');track.setAttribute('aria-label',item.name+' '+quota.label);track.setAttribute('aria-valuemin','0');track.setAttribute('aria-valuemax','100');if(quota.remainingPercent!==null){track.setAttribute('aria-valuenow',String(quota.remainingPercent));track.setAttribute('aria-valuetext',quota.remainingPercent+'% remaining')}const fill=document.createElement('div');fill.className='fill';fill.style.width=(quota.remainingPercent===null?0:Math.max(0,Math.min(100,quota.remainingPercent)))+'%';track.append(fill);const reset=document.createElement('p');reset.className='quota-meta';reset.textContent=(quota.resetsAt?'Resets '+new Date(quota.resetsAt).toLocaleString():'Reset unknown')+' \xB7 '+quota.confidence;box.append(row,track,reset);card.append(box)}harnesses.append(card)}text('recommendation',model.recommendation?model.recommendation.action:'No recommendation yet.');text('reason',model.recommendation?.reason||'More observations are needed before Token Harness recommends a change.');text('command',model.nextStep.command);text('description',model.nextStep.description);const providers=byId('providers');providers.replaceChildren();if(model.providers.length===0){const empty=document.createElement('span');empty.className='empty';empty.textContent='No provider detected';providers.append(empty)}for(const item of model.providers){const node=document.createElement('span');node.className='provider';node.textContent=item.id+' \xB7 '+(item.harnesses.length?'active on '+item.harnesses.join(', '):item.state);providers.append(node)}text('error','')}async function load(){byId('refresh').disabled=true;try{const response=await fetch('/api/status',{cache:'no-store'});if(!response.ok)throw new Error('Dashboard data is unavailable');render(await response.json())}catch(error){text('error',error instanceof Error?error.message:String(error))}finally{byId('refresh').disabled=false}}byId('refresh').addEventListener('click',load);byId('copy').addEventListener('click',async()=>{await navigator.clipboard.writeText(byId('command').textContent||'');text('updated','Command copied')});load();setInterval(()=>{if(!document.hidden)load()},30000);`;
20717
+ DASHBOARD_CSS = `:root{font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;font-synthesis:none;--bg:#f6f8fb;--surface:#ffffff;--surface-2:#f1f5f9;--text:#111827;--muted:#5b6472;--subtle:#7b8492;--border:#dce2ea;--accent:#0f766e;--accent-strong:#115e59;--accent-soft:#ccfbf1;--warning:#92400e;--warning-soft:#fef3c7;--danger:#b42318;--danger-soft:#fee4e2;--shadow:0 14px 34px rgba(15,23,42,.08);--focus:#2563eb}*{box-sizing:border-box}html{background:var(--bg)}body{margin:0;min-height:100vh;background:linear-gradient(180deg,rgba(15,118,110,.045),transparent 240px),var(--bg);color:var(--text);font-size:16px;line-height:1.5}button{font:inherit}button:focus-visible,a:focus-visible,summary:focus-visible{outline:3px solid var(--focus);outline-offset:3px}.skip{position:absolute;left:-999px;top:1rem;z-index:10;background:var(--text);color:var(--surface);padding:.6rem .8rem;border-radius:8px}.skip:focus{left:1rem}.topbar,main,footer{width:min(1040px,calc(100% - 32px));margin-inline:auto}.topbar{height:68px;display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid var(--border)}.brand{display:flex;align-items:center;gap:.7rem;font-weight:800;letter-spacing:-.01em}.mark{display:grid;place-items:center;width:36px;height:36px;border-radius:10px;background:var(--accent);color:#fff;font:800 13px ui-monospace,SFMono-Regular,Consolas,monospace}.secondary-button,.primary-button{min-height:44px;border-radius:10px;padding:0 1rem;font-weight:750;cursor:pointer}.secondary-button{border:1px solid var(--border);background:var(--surface);color:var(--text)}.secondary-button:hover{background:var(--surface-2)}.primary-button{border:1px solid var(--accent-strong);background:var(--accent);color:#fff}.primary-button:hover{background:var(--accent-strong)}button:disabled{cursor:wait;opacity:.62}.hero{padding:54px 0 28px;max-width:780px}.status-chip{display:inline-flex;align-items:center;min-height:28px;padding:0 .65rem;border-radius:999px;background:var(--accent-soft);color:var(--accent-strong);font-size:.76rem;font-weight:850;letter-spacing:.08em}.status-chip.limited{background:var(--warning-soft);color:var(--warning)}.status-chip.action-needed{background:var(--danger-soft);color:var(--danger)}.status-chip.setup-needed{background:var(--surface-2);color:var(--muted)}.hero h1{margin:14px 0 10px;font-size:clamp(2.05rem,5vw,3.65rem);line-height:1.04;letter-spacing:-.045em}.hero-copy{margin:0;max-width:720px;color:var(--muted);font-size:1.08rem}.timestamp{margin:12px 0 0;color:var(--subtle);font-size:.82rem}.action-card{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:24px;align-items:center;padding:24px;border:1px solid color-mix(in srgb,var(--accent) 28%,var(--border));border-radius:18px;background:var(--surface);box-shadow:var(--shadow)}.eyebrow{margin:0 0 6px;color:var(--accent-strong);font-size:.72rem;font-weight:850;letter-spacing:.11em}.action-card h2,.section h2,.recommendation-card h2,.compact-panel h2{margin:0;font-size:1.18rem;letter-spacing:-.015em}.supporting{margin:7px 0 0;color:var(--muted)}.command-row{display:flex;align-items:center;gap:10px;max-width:100%}.command-row code{display:block;max-width:440px;padding:12px 14px;border:1px solid var(--border);border-radius:10px;background:var(--surface-2);color:var(--text);font:650 .88rem ui-monospace,SFMono-Regular,Consolas,monospace;overflow-wrap:anywhere}.section{padding-top:34px}.section-heading{display:flex;align-items:end;justify-content:space-between;gap:24px;margin-bottom:14px}.section-note{margin:0;color:var(--subtle);font-size:.86rem}.harness-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,300px),1fr));gap:12px}.harness-card{min-width:0;padding:18px;border:1px solid var(--border);border-radius:16px;background:var(--surface)}.harness-top{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.harness-card h3{margin:0;font-size:1.06rem}.health{display:inline-flex;align-items:center;gap:7px;flex:0 0 auto;color:var(--accent-strong);font-size:.76rem;font-weight:800}.health::before{content:"";width:8px;height:8px;border-radius:50%;background:var(--accent)}.health.limited{color:var(--warning)}.health.limited::before{background:var(--warning)}.health.attention{color:var(--danger)}.health.attention::before{background:var(--danger)}.harness-meta{margin:5px 0 0;color:var(--muted);font-size:.86rem}.provider-line{margin:13px 0 0;font-size:.9rem}.provider-line strong{font-weight:800}.allowance{margin-top:16px;padding-top:14px;border-top:1px solid var(--border)}.quota{margin-top:12px}.quota:first-child{margin-top:0}.quota-row{display:flex;justify-content:space-between;gap:16px;margin-bottom:6px;font-size:.88rem}.quota-row strong{font-variant-numeric:tabular-nums}.track{height:7px;border-radius:999px;background:var(--surface-2);overflow:hidden}.fill{height:100%;border-radius:inherit;background:var(--accent)}.quota-meta{margin:5px 0 0;color:var(--subtle);font-size:.76rem}.no-allowance{margin:14px 0 0;color:var(--subtle);font-size:.82rem}.recommendation-card,.compact-panel,.details-panel{margin-top:14px;border:1px solid var(--border);border-radius:16px;background:var(--surface)}.recommendation-card{padding:20px}.recommendation-action{margin:9px 0 0;font-weight:760}.compact-panel{display:flex;align-items:center;justify-content:space-between;gap:20px;padding:16px 18px}.provider-list,.secondary-list{margin:0;padding:0;list-style:none}.provider-list{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px}.provider-list li{padding:7px 9px;border:1px solid var(--border);border-radius:9px;background:var(--surface-2);font-size:.82rem}.details-panel{padding:0 16px}.details-panel summary{min-height:48px;display:flex;align-items:center;cursor:pointer;color:var(--muted);font-weight:750}.secondary-list{padding:0 0 14px}.secondary-list li{padding:7px 0;border-top:1px solid var(--border);color:var(--muted);font-size:.86rem}.error{color:var(--danger);font-weight:700}footer{padding:28px 0 42px;color:var(--subtle);font-size:.82rem}footer strong{color:var(--muted)}[hidden]{display:none!important}@media(prefers-color-scheme:dark){:root{--bg:#0b1118;--surface:#111923;--surface-2:#17212d;--text:#f3f6fa;--muted:#b2bdc9;--subtle:#8996a4;--border:#273443;--accent:#2dd4bf;--accent-strong:#99f6e4;--accent-soft:#123d39;--warning:#fbbf24;--warning-soft:#422f12;--danger:#ff8a80;--danger-soft:#44201f;--shadow:0 16px 38px rgba(0,0,0,.22);--focus:#60a5fa}.primary-button{color:#062a27}.mark{color:#062a27}.action-card{border-color:#28514d}}@media(max-width:760px){.topbar,main,footer{width:min(100% - 24px,1040px)}.hero{padding:38px 0 22px}.action-card{grid-template-columns:1fr;gap:16px;padding:19px}.command-row{align-items:stretch;flex-direction:column}.command-row code{max-width:none}.command-row .primary-button{width:100%}.section{padding-top:28px}.section-heading{align-items:flex-start;flex-direction:column;gap:3px}.compact-panel{align-items:flex-start;flex-direction:column}.provider-list{justify-content:flex-start}.topbar{height:62px}}@media(max-width:390px){.hero h1{font-size:2rem}.harness-card{padding:15px}.harness-top{align-items:flex-start;flex-direction:column;gap:6px}}@media(prefers-reduced-motion:reduce){*{scroll-behavior:auto!important;transition:none!important;animation:none!important}}`;
20718
+ DASHBOARD_JS = `const byId=(id)=>document.getElementById(id);const setText=(id,value)=>{const node=byId(id);if(node)node.textContent=value};function formatReset(value){return value?'Resets '+new Date(value).toLocaleString():'Reset time unavailable'}function renderHarness(item){const card=document.createElement('article');card.className='harness-card';const top=document.createElement('div');top.className='harness-top';const title=document.createElement('h3');title.textContent=item.name;const health=document.createElement('span');health.className='health '+item.health;health.textContent=item.statusLabel;top.append(title,health);card.append(top);const meta=document.createElement('p');meta.className='harness-meta';meta.textContent=item.version?'Version '+item.version:'Version unavailable';card.append(meta);if(item.providers.length){const provider=document.createElement('p');provider.className='provider-line';const strong=document.createElement('strong');strong.textContent=item.providers.join(', ');provider.append(strong,document.createTextNode(' active automatically'));card.append(provider)}if(item.allowance.length){const allowance=document.createElement('div');allowance.className='allowance';for(const quota of item.allowance){const box=document.createElement('div');box.className='quota';const row=document.createElement('div');row.className='quota-row';const label=document.createElement('span');label.textContent=quota.label;const value=document.createElement('strong');value.textContent=quota.remainingPercent===null?'Unknown':quota.remainingPercent+'% left';row.append(label,value);const track=document.createElement('div');track.className='track';track.setAttribute('role','progressbar');track.setAttribute('aria-label',item.name+' '+quota.label);track.setAttribute('aria-valuemin','0');track.setAttribute('aria-valuemax','100');if(quota.remainingPercent!==null){track.setAttribute('aria-valuenow',String(quota.remainingPercent));track.setAttribute('aria-valuetext',quota.remainingPercent+'% remaining')}const fill=document.createElement('div');fill.className='fill';fill.style.width=(quota.remainingPercent===null?0:Math.max(0,Math.min(100,quota.remainingPercent)))+'%';track.append(fill);const detail=document.createElement('p');detail.className='quota-meta';detail.textContent=formatReset(quota.resetsAt)+(quota.confidence==='authoritative'?' \xB7 verified allowance':' \xB7 '+quota.confidence);box.append(row,track,detail);allowance.append(box)}card.append(allowance)}else{const empty=document.createElement('p');empty.className='no-allowance';empty.textContent='Allowance data is not available for this harness.';card.append(empty)}return card}function render(model){document.body.dataset.state=model.state;const status=byId('status');status.textContent=model.statusLabel;status.className='status-chip '+model.state;setText('headline',model.headline);setText('summary',model.summary);setText('updated','Updated '+new Date(model.generatedAt).toLocaleString());setText('next-title',model.nextStep.title);setText('description',model.nextStep.description);const commandRow=byId('command-row');if(model.nextStep.command){setText('command',model.nextStep.command);commandRow.hidden=false}else{setText('command','');commandRow.hidden=true}const harnesses=byId('harnesses');harnesses.replaceChildren();if(model.harnesses.length===0){const empty=document.createElement('p');empty.className='supporting';empty.textContent='No active optimized harness is available yet.';harnesses.append(empty)}for(const item of model.harnesses)harnesses.append(renderHarness(item));const recommendationPanel=byId('recommendation-panel');if(model.recommendation){setText('recommendation',model.recommendation.action);setText('reason',model.recommendation.reason||'This recommendation is based on the currently observable local signals.');recommendationPanel.hidden=false}else{recommendationPanel.hidden=true}const providersPanel=byId('providers-panel');const providers=byId('providers');providers.replaceChildren();if(model.providers.length){for(const item of model.providers){const node=document.createElement('li');node.textContent=item.name+' \xB7 '+item.harnesses.join(', ');providers.append(node)}providersPanel.hidden=false}else{providersPanel.hidden=true}const otherPanel=byId('other-panel');const other=byId('other-harnesses');other.replaceChildren();if(model.otherHarnesses.length){setText('other-summary','Other detected tools ('+model.otherHarnesses.length+')');for(const item of model.otherHarnesses){const node=document.createElement('li');node.textContent=item.name+(item.version?' \xB7 '+item.version:'')+' \xB7 detected, not active in the optimized setup';other.append(node)}otherPanel.hidden=false}else{otherPanel.hidden=true}setText('error','')}async function load(){const refresh=byId('refresh');refresh.disabled=true;refresh.textContent='Refreshing\u2026';try{const response=await fetch('/api/status',{cache:'no-store'});if(!response.ok)throw new Error('Dashboard data is unavailable');render(await response.json())}catch(error){setText('error',error instanceof Error?error.message:String(error))}finally{refresh.disabled=false;refresh.textContent='Refresh'}}byId('refresh').addEventListener('click',load);byId('copy').addEventListener('click',async()=>{const command=byId('command').textContent||'';try{await navigator.clipboard.writeText(command);setText('updated','Command copied')}catch{setText('updated','Copy unavailable \u2014 select the command manually')}});load();setInterval(()=>{if(!document.hidden)load()},30000);`;
20574
20719
  }
20575
20720
  });
20576
20721
 
@@ -20761,7 +20906,7 @@ async function runUi(options, baseOptions) {
20761
20906
  return EXIT_CODES["unsupported-environment"];
20762
20907
  }
20763
20908
  if (options.json) {
20764
- const exitCode = initial.state === "attention" ? EXIT_CODES["problems-found"] : EXIT_CODES.ok;
20909
+ const exitCode = initial.state === "action-needed" ? EXIT_CODES["problems-found"] : EXIT_CODES.ok;
20765
20910
  process5.stdout.write(serializeEnvelope(toEnvelope(commandResult({ command: "ui", exitCode, data: initial }), TOOL_VERSION)));
20766
20911
  return exitCode;
20767
20912
  }