token-harness 0.1.16 → 0.1.17

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "token-harness",
3
- "version": "0.1.16",
3
+ "version": "0.1.17",
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:aeb90d5b-b157-a969-ef00-e4d3853a0ef7",
4
+ "serialNumber": "urn:uuid:acbec121-baa9-de33-8ab5-e5e88efbd50e",
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.16",
11
+ "version": "0.1.17",
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": "aeb90d5bb157a969ef00e4d3853a0ef75dbb909cbf43d2085d1bc50aeb184a82"
23
+ "content": "acbec121baa9de338ab5e5e88efbd50e5c4b3f0a1f2c6f7171f80dd05b12f312"
24
24
  }
25
25
  ]
26
26
  },
package/token-harness.mjs CHANGED
@@ -6535,12 +6535,33 @@ var init_install = __esm({
6535
6535
  version3 === null ? packageName : `${packageName}==${version3}`
6536
6536
  ],
6537
6537
  verified: true
6538
+ },
6539
+ uv: {
6540
+ executable: "uv",
6541
+ // Headroom uses uv's isolated tool installer. Token Harness invokes an existing uv only;
6542
+ // it never bootstraps uv, Python, or administrator prerequisites.
6543
+ args: (packageName, version3) => [
6544
+ "tool",
6545
+ "install",
6546
+ "--force",
6547
+ version3 === null ? packageName : `${packageName}==${version3}`
6548
+ ],
6549
+ verified: true
6538
6550
  }
6539
6551
  };
6540
6552
  UNINSTALL_COMMANDS = {
6553
+ npm: {
6554
+ executable: "npm",
6555
+ args: (packageName) => ["uninstall", "--global", packageName]
6556
+ },
6541
6557
  pipx: {
6542
6558
  executable: "pipx",
6543
6559
  args: (packageName) => ["uninstall", packageName]
6560
+ },
6561
+ uv: {
6562
+ executable: "uv",
6563
+ // Extras are install-time selectors; uv tool uninstall expects the distribution name.
6564
+ args: (packageName) => ["tool", "uninstall", packageName.replace(/\[.*\]$/, "")]
6544
6565
  }
6545
6566
  };
6546
6567
  QUERY_COMMANDS = {
@@ -6633,17 +6654,35 @@ var init_install = __esm({
6633
6654
  },
6634
6655
  npm: {
6635
6656
  executable: "npm",
6636
- args: (packageName) => ["ls", "-g", packageName, "--depth=0"],
6657
+ // Listing the global root as JSON proves both presence and absence without depending on
6658
+ // localized human output or npm's exit behavior for a package-name filter.
6659
+ args: () => ["ls", "--global", "--depth=0", "--json"],
6637
6660
  parse: (stdout, packageName) => {
6638
- const pattern = new RegExp(`(?:^|[^@\\w.-])${packageName}@(\\d[^\\s]*)`);
6639
- const match = pattern.exec(stdout);
6640
- const candidate = match?.[1] ?? null;
6641
- if (candidate === null || parseSemanticVersion(candidate) === null) {
6661
+ let parsed;
6662
+ try {
6663
+ parsed = JSON.parse(stdout);
6664
+ } catch {
6665
+ return { status: "unknown", version: null };
6666
+ }
6667
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
6668
+ return { status: "unknown", version: null };
6669
+ }
6670
+ const dependencies = parsed["dependencies"];
6671
+ if (dependencies === void 0)
6672
+ return { status: "absent", version: null };
6673
+ if (typeof dependencies !== "object" || dependencies === null || Array.isArray(dependencies)) {
6674
+ return { status: "unknown", version: null };
6675
+ }
6676
+ const dependency = dependencies[packageName];
6677
+ if (dependency === void 0)
6678
+ return { status: "absent", version: null };
6679
+ const candidate = typeof dependency === "string" ? dependency : typeof dependency === "object" && dependency !== null && !Array.isArray(dependency) ? dependency["version"] : null;
6680
+ if (typeof candidate !== "string" || parseSemanticVersion(candidate) === null) {
6642
6681
  return { status: "unknown", version: null };
6643
6682
  }
6644
6683
  return { status: "captured", version: candidate };
6645
6684
  },
6646
- verified: false
6685
+ verified: true
6647
6686
  },
6648
6687
  pnpm: {
6649
6688
  executable: "pnpm",
@@ -6698,16 +6737,20 @@ var init_install = __esm({
6698
6737
  executable: "uv",
6699
6738
  args: () => ["tool", "list"],
6700
6739
  parse: (stdout, packageName) => {
6701
- const pattern = new RegExp(`^${packageName}\\s+v?(\\S+)`, "m");
6702
- const match = pattern.exec(stdout);
6703
- if (match === null)
6704
- return { status: "absent", version: null };
6705
- const candidate = match[1] ?? "";
6706
- if (parseSemanticVersion(candidate) === null)
6707
- return { status: "unknown", version: null };
6708
- return { status: "captured", version: candidate };
6740
+ const distribution = packageName.replace(/\[.*\]$/, "");
6741
+ for (const line of stdout.split(/\r?\n/)) {
6742
+ const fields = line.trim().split(/\s+/);
6743
+ if (fields[0] !== distribution)
6744
+ continue;
6745
+ const candidate = (fields[1] ?? "").replace(/^v/i, "");
6746
+ if (parseSemanticVersion(candidate) === null) {
6747
+ return { status: "unknown", version: null };
6748
+ }
6749
+ return { status: "captured", version: candidate };
6750
+ }
6751
+ return { status: "absent", version: null };
6709
6752
  },
6710
- verified: false
6753
+ verified: true
6711
6754
  },
6712
6755
  pipx: {
6713
6756
  executable: "pipx",
@@ -8892,7 +8935,7 @@ var init_snapshots = __esm({
8892
8935
  * calling a constructor directly.
8893
8936
  */
8894
8937
  static create(input) {
8895
- if (input.fs.isInside(input.backupRoot, input.projectRoot)) {
8938
+ if (input.projectRoot !== null && input.fs.isInside(input.backupRoot, input.projectRoot)) {
8896
8939
  return {
8897
8940
  ok: false,
8898
8941
  diagnostics: [
@@ -9387,7 +9430,7 @@ var TOOL_VERSION;
9387
9430
  var init_version2 = __esm({
9388
9431
  "apps/cli/dist/src/version.js"() {
9389
9432
  "use strict";
9390
- TOOL_VERSION = "0.1.16";
9433
+ TOOL_VERSION = "0.1.17";
9391
9434
  }
9392
9435
  });
9393
9436
 
@@ -11189,6 +11232,10 @@ var init_environment = __esm({
11189
11232
  "HOMEPATH",
11190
11233
  "LOCALAPPDATA",
11191
11234
  "NUMBER_OF_PROCESSORS",
11235
+ // npm global installs must stay in the same prefix the parent process is using. This value is
11236
+ // a filesystem location, not a credential; dropping it can update a different global npm tree
11237
+ // while PATH continues to resolve the old executable.
11238
+ "NPM_CONFIG_PREFIX",
11192
11239
  "PATH",
11193
11240
  "PATHEXT",
11194
11241
  "PROCESSOR_ARCHITECTURE",
@@ -11214,6 +11261,10 @@ var init_environment = __esm({
11214
11261
  "LC_ALL",
11215
11262
  "LC_CTYPE",
11216
11263
  "LOGNAME",
11264
+ // npm documents config environment variables with the lowercase npm_config_ prefix on POSIX.
11265
+ // Keep both common spellings because POSIX environment names are case-sensitive.
11266
+ "NPM_CONFIG_PREFIX",
11267
+ "npm_config_prefix",
11217
11268
  "PATH",
11218
11269
  "SHELL",
11219
11270
  "TMPDIR",
@@ -16778,6 +16829,25 @@ function skillArtifacts(context, harness, capabilities = null) {
16778
16829
  digest
16779
16830
  }));
16780
16831
  }
16832
+ function skillInstallContainmentBoundary(context, harness, capabilities, protectedPaths) {
16833
+ const install = SKILLS_INSTALL[harness];
16834
+ if (install === void 0)
16835
+ return [...protectedPaths];
16836
+ const prefix = `${install.directory}/skills/`;
16837
+ const relativeArtifacts = capabilities === null ? [] : publishedSkillArtifactDigests(capabilities, harness).map(([path]) => path);
16838
+ const fallbackArtifacts = Object.keys(SKILL_ARTIFACT_DIGESTS).map((path) => `${install.directory}/skills/${path}`);
16839
+ const contract = relativeArtifacts.length > 0 ? relativeArtifacts : capabilities !== null && requiresRuntimeSkillDigests(capabilities) ? [] : fallbackArtifacts;
16840
+ const skillRoots = /* @__PURE__ */ new Set();
16841
+ for (const relative of contract) {
16842
+ if (!relative.startsWith(prefix))
16843
+ continue;
16844
+ const first = relative.slice(prefix.length).split("/")[0];
16845
+ if (first) {
16846
+ skillRoots.add(context.fs.join(context.projectRoot, install.directory, "skills", first));
16847
+ }
16848
+ }
16849
+ return [...skillRoots, ...protectedPaths];
16850
+ }
16781
16851
  async function harnessTrimSkillsConfigured(context, harness, capabilities) {
16782
16852
  const artifacts = skillArtifacts(context, harness, capabilities);
16783
16853
  if (artifacts.length === 0)
@@ -16866,6 +16936,11 @@ async function plan(context, request) {
16866
16936
  const expectedArtifacts = skillArtifacts(context, harness, currentCapabilities);
16867
16937
  if (expectedArtifacts.length === 0)
16868
16938
  continue;
16939
+ const protectedPaths = [
16940
+ context.fs.join(context.projectRoot, install.directory, install.hook),
16941
+ context.fs.join(context.projectRoot, install.instructions)
16942
+ ];
16943
+ const containmentBoundary = skillInstallContainmentBoundary(context, harness, currentCapabilities, protectedPaths);
16869
16944
  actions.push({
16870
16945
  kind: "delegated-provider-install",
16871
16946
  id: `harnesstrim-${harness}-skills-${digestText(context.projectRoot).slice(7, 15)}`,
@@ -16886,13 +16961,10 @@ async function plan(context, request) {
16886
16961
  explanation: `Install HarnessTrim ${harness} skills without a hook or reduce-pipe instruction`,
16887
16962
  executable: "harnesstrim",
16888
16963
  args: ["install", harness, context.projectRoot, "--apply", ...install.args],
16889
- containmentBoundary: review.containmentBoundary.map((path) => context.fs.join(context.projectRoot, path)),
16964
+ containmentBoundary,
16890
16965
  expectedArtifacts,
16891
16966
  // The two files each installer reports skipping. Named here because they must not appear.
16892
- protectedPaths: [
16893
- context.fs.join(context.projectRoot, install.directory, install.hook),
16894
- context.fs.join(context.projectRoot, install.instructions)
16895
- ],
16967
+ protectedPaths,
16896
16968
  rollbackStrategy: "restore-snapshot",
16897
16969
  snapshotSizeCapBytes: 1048576,
16898
16970
  upstreamUninstallAvailable: review.upstreamUninstallAvailable
@@ -16917,7 +16989,7 @@ var init_harnesstrim = __esm({
16917
16989
  CODEX2 = harnessId("codex");
16918
16990
  PI2 = harnessId("pi");
16919
16991
  SKILLS_UPSTREAM = "0.0.7";
16920
- RUNTIME_SKILL_DIGESTS_MINIMUM = "0.3.0";
16992
+ RUNTIME_SKILL_DIGESTS_MINIMUM = "0.2.0";
16921
16993
  SKILL_ARTIFACT_DIGESTS = {
16922
16994
  "compact-handoff/SKILL.md": "sha256:0efbf35581c559359e755b204778b64a289dab4d20dadc1cba3d5b5c995b5f01",
16923
16995
  "debug-log-slim/SKILL.md": "sha256:17f5ccc34d29d7aba083444e0e4d87fd3d49916ebcb4e6544caf8c89f13f0045",
@@ -18224,6 +18296,29 @@ function prerequisiteDiagnostic(harness, detail2) {
18224
18296
  remediation: `Install or update GitNexus to ${GITNEXUS_REVIEWED_MCP_VERSION} or newer with the MCP command, then refresh Token Harness`
18225
18297
  });
18226
18298
  }
18299
+ function gitnexusInstallAction() {
18300
+ return {
18301
+ kind: "package-manager-install",
18302
+ id: `gitnexus:install:${GITNEXUS_REVIEWED_MCP_VERSION}`,
18303
+ riskClass: "delegated",
18304
+ requiresNetwork: true,
18305
+ requiresElevation: false,
18306
+ affectedPaths: [],
18307
+ affectedProcesses: ["npm"],
18308
+ preconditions: [
18309
+ "npm remains runnable",
18310
+ `the reviewed GitNexus ${GITNEXUS_REVIEWED_MCP_VERSION} package remains installable`
18311
+ ],
18312
+ postconditions: [
18313
+ `GitNexus ${GITNEXUS_REVIEWED_MCP_VERSION} is installed and exposes the mcp command`
18314
+ ],
18315
+ rollbackData: "package-inventory",
18316
+ explanation: `Install the reviewed GitNexus ${GITNEXUS_REVIEWED_MCP_VERSION} CLI through npm`,
18317
+ packageManager: "npm",
18318
+ packageName: "gitnexus",
18319
+ version: GITNEXUS_REVIEWED_MCP_VERSION
18320
+ };
18321
+ }
18227
18322
  async function planGitNexusManagedMcpActivation(context, harness) {
18228
18323
  if (harness !== "claude") {
18229
18324
  return {
@@ -18242,13 +18337,39 @@ async function planGitNexusManagedMcpActivation(context, harness) {
18242
18337
  };
18243
18338
  }
18244
18339
  const observation = await observeGitNexusManagedRuntime(context);
18340
+ const installActions = [];
18245
18341
  if (!observation.ready) {
18246
- return {
18247
- harness,
18248
- target: null,
18249
- actions: [],
18250
- diagnostics: [prerequisiteDiagnostic(harness, observation.detail)]
18251
- };
18342
+ if (!observation.absent) {
18343
+ return {
18344
+ harness,
18345
+ target: null,
18346
+ actions: [],
18347
+ diagnostics: [prerequisiteDiagnostic(harness, observation.detail)]
18348
+ };
18349
+ }
18350
+ const npm = await context.runner.run({
18351
+ executable: "npm",
18352
+ args: ["--version"],
18353
+ cwd: context.projectRoot,
18354
+ timeoutMs: 2e4
18355
+ });
18356
+ if (npm.failure !== null || npm.exitCode !== 0) {
18357
+ return {
18358
+ harness,
18359
+ target: null,
18360
+ actions: [],
18361
+ diagnostics: [
18362
+ diagnostic({
18363
+ severity: "warning",
18364
+ code: "gitnexus-npm-unavailable",
18365
+ subject: harness,
18366
+ message: "GitNexus is absent and npm is not available in this terminal",
18367
+ remediation: "Make npm available on PATH, then refresh Token Harness. Token Harness will not bootstrap Node.js or administrator prerequisites."
18368
+ })
18369
+ ]
18370
+ };
18371
+ }
18372
+ installActions.push(gitnexusInstallAction());
18252
18373
  }
18253
18374
  const target = claudeTarget(context);
18254
18375
  if (!context.fs.isInside(target, context.paths.home)) {
@@ -18366,7 +18487,7 @@ async function planGitNexusManagedMcpActivation(context, harness) {
18366
18487
  ],
18367
18488
  createIfMissing: true
18368
18489
  };
18369
- return { harness, target, actions: [action], diagnostics: [] };
18490
+ return { harness, target, actions: [...installActions, action], diagnostics: [] };
18370
18491
  }
18371
18492
  function planGitNexusManagedMcpRemoval(context, ownership) {
18372
18493
  const harness = "claude";
@@ -19179,7 +19300,22 @@ async function mcptoonDetection(context) {
19179
19300
  configuredHarnesses.push(harness);
19180
19301
  }
19181
19302
  }
19182
- const warnings = !observation.absent && !observation.ready ? [warning("mcptoon-provider-capability-unavailable", "mcptoon", observation.detail)] : [];
19303
+ const pipx = observation.absent ? await context.runner.run({
19304
+ executable: "pipx",
19305
+ args: ["--version"],
19306
+ cwd: context.projectRoot,
19307
+ timeoutMs: 2e4
19308
+ }) : null;
19309
+ const canInstall = observation.absent && pipx !== null && pipx.failure === null && pipx.exitCode === 0;
19310
+ const warnings = observation.absent && !canInstall ? [
19311
+ diagnostic({
19312
+ severity: "warning",
19313
+ code: "mcptoon-pipx-unavailable",
19314
+ subject: "mcptoon",
19315
+ message: "mcptoon is not installed and pipx is not available in this terminal",
19316
+ remediation: "Install pipx or make it available on PATH, then refresh. Token Harness will use it to install the reviewed mcptoon build."
19317
+ })
19318
+ ] : !observation.absent && !observation.ready ? [warning("mcptoon-provider-capability-unavailable", "mcptoon", observation.detail)] : [];
19183
19319
  return {
19184
19320
  providerId: MCPTOON,
19185
19321
  state: observation.absent ? "absent" : configuredHarnesses.length > 0 ? "configured" : "installed",
@@ -19191,7 +19327,7 @@ async function mcptoonDetection(context) {
19191
19327
  unmanagedHarnessesConfigured: [],
19192
19328
  supportsUnmanagedHarnesses: false,
19193
19329
  managedByTokenHarness: false,
19194
- assignableHarnesses: observation.ready ? [CLAUDE5, CODEX3] : [],
19330
+ assignableHarnesses: observation.ready || canInstall ? [CLAUDE5, CODEX3] : [],
19195
19331
  evidence: [],
19196
19332
  warnings
19197
19333
  };
@@ -19200,7 +19336,22 @@ async function gitnexusDetection(context) {
19200
19336
  const observation = await observeGitNexusManagedRuntime(context);
19201
19337
  const verification = observation.ready ? await verifyGitNexusManagedMcpActivation(context, CLAUDE5) : null;
19202
19338
  const configuredHarnesses = verification?.state === "verified" ? [CLAUDE5] : [];
19203
- const warnings = !observation.absent && !observation.ready ? [warning("gitnexus-provider-capability-unavailable", "gitnexus", observation.detail)] : [];
19339
+ const npm = observation.absent ? await context.runner.run({
19340
+ executable: "npm",
19341
+ args: ["--version"],
19342
+ cwd: context.projectRoot,
19343
+ timeoutMs: 2e4
19344
+ }) : null;
19345
+ const canInstall = observation.absent && npm !== null && npm.failure === null && npm.exitCode === 0;
19346
+ const warnings = observation.absent && !canInstall ? [
19347
+ diagnostic({
19348
+ severity: "warning",
19349
+ code: "gitnexus-npm-unavailable",
19350
+ subject: "gitnexus",
19351
+ message: "GitNexus is not installed and npm is not available in this terminal",
19352
+ remediation: "Make npm available on PATH, then refresh. Token Harness can install the reviewed GitNexus build after explicit approval."
19353
+ })
19354
+ ] : !observation.absent && !observation.ready ? [warning("gitnexus-provider-capability-unavailable", "gitnexus", observation.detail)] : [];
19204
19355
  return {
19205
19356
  providerId: GITNEXUS,
19206
19357
  state: observation.absent ? "absent" : configuredHarnesses.length > 0 ? "configured" : "installed",
@@ -19212,7 +19363,7 @@ async function gitnexusDetection(context) {
19212
19363
  unmanagedHarnessesConfigured: [],
19213
19364
  supportsUnmanagedHarnesses: false,
19214
19365
  managedByTokenHarness: false,
19215
- assignableHarnesses: observation.ready ? [CLAUDE5] : [],
19366
+ assignableHarnesses: observation.ready || canInstall ? [CLAUDE5] : [],
19216
19367
  evidence: [],
19217
19368
  warnings
19218
19369
  };
@@ -19544,6 +19695,30 @@ async function headroomManagedMcpRuntime(context) {
19544
19695
  detail: `Headroom ${observation.version} exposes the local MCP server required by the managed integration`
19545
19696
  };
19546
19697
  }
19698
+ function headroomInstallAction() {
19699
+ return {
19700
+ kind: "package-manager-install",
19701
+ id: `headroom:install:${HEADROOM_REVIEWED_MCP_VERSION}`,
19702
+ riskClass: "delegated",
19703
+ requiresNetwork: true,
19704
+ requiresElevation: false,
19705
+ affectedPaths: [],
19706
+ affectedProcesses: ["uv"],
19707
+ preconditions: [
19708
+ "uv remains runnable",
19709
+ `the reviewed Headroom ${HEADROOM_REVIEWED_MCP_VERSION} MCP package remains installable`
19710
+ ],
19711
+ postconditions: [
19712
+ `Headroom ${HEADROOM_REVIEWED_MCP_VERSION} is installed with the MCP extra`,
19713
+ "headroom mcp serve --help succeeds"
19714
+ ],
19715
+ rollbackData: "package-inventory",
19716
+ explanation: `Install reviewed Headroom ${HEADROOM_REVIEWED_MCP_VERSION} with its MCP extra through uv`,
19717
+ packageManager: "uv",
19718
+ packageName: "headroom-ai[mcp]",
19719
+ version: HEADROOM_REVIEWED_MCP_VERSION
19720
+ };
19721
+ }
19547
19722
  function prerequisite(harness, detail2) {
19548
19723
  return {
19549
19724
  harness,
@@ -19841,9 +20016,24 @@ async function planHeadroomManagedMcpActivation(context, harness) {
19841
20016
  };
19842
20017
  }
19843
20018
  const cli = await headroomManagedMcpRuntime(context);
19844
- if (!cli.ok)
19845
- return prerequisite(harness, cli.detail);
19846
- return harness === "claude" ? planClaude(context, harness) : planCodex(context, harness);
20019
+ const installActions = [];
20020
+ if (!cli.ok) {
20021
+ const observation = await observeHeadroomCandidate(context);
20022
+ if (observation.state !== "absent")
20023
+ return prerequisite(harness, cli.detail);
20024
+ const uv = await context.runner.run({
20025
+ executable: "uv",
20026
+ args: ["--version"],
20027
+ cwd: context.projectRoot,
20028
+ timeoutMs: 2e4
20029
+ });
20030
+ if (uv.failure !== null || uv.exitCode !== 0) {
20031
+ return prerequisite(harness, "Headroom is absent and uv is not available in this terminal. Install uv or make it available on PATH; Token Harness will not bootstrap Python or uv itself.");
20032
+ }
20033
+ installActions.push(headroomInstallAction());
20034
+ }
20035
+ const activation = harness === "claude" ? await planClaude(context, harness) : await planCodex(context, harness);
20036
+ return { ...activation, actions: [...installActions, ...activation.actions] };
19847
20037
  }
19848
20038
  function headroomOwnedArtifact(context, harness) {
19849
20039
  if (harness === "claude") {
@@ -19972,10 +20162,17 @@ async function detect8(context) {
19972
20162
  configuredHarnesses.push(harness);
19973
20163
  }
19974
20164
  }
20165
+ const uv = observation.state === "absent" ? await context.runner.run({
20166
+ executable: "uv",
20167
+ args: ["--version"],
20168
+ cwd: context.projectRoot,
20169
+ timeoutMs: 2e4
20170
+ }) : null;
20171
+ const canInstall = observation.state === "absent" && uv !== null && uv.failure === null && uv.exitCode === 0;
19975
20172
  const warnings = [];
19976
- if (observation.state === "absent")
20173
+ if (observation.state === "absent" && !canInstall)
19977
20174
  warnings.push(manualInstallWarning());
19978
- else if (!runtime.ok) {
20175
+ else if (!runtime.ok && observation.state !== "absent") {
19979
20176
  warnings.push(diagnostic({
19980
20177
  severity: "warning",
19981
20178
  code: "headroom-provider-capability-unavailable",
@@ -19998,7 +20195,7 @@ async function detect8(context) {
19998
20195
  unmanagedHarnessesConfigured: [],
19999
20196
  supportsUnmanagedHarnesses: false,
20000
20197
  managedByTokenHarness: false,
20001
- assignableHarnesses: runtime.ok ? [CLAUDE7, CODEX4] : [],
20198
+ assignableHarnesses: runtime.ok || canInstall ? [CLAUDE7, CODEX4] : [],
20002
20199
  evidence: [],
20003
20200
  warnings
20004
20201
  };
@@ -21449,6 +21646,33 @@ var init_candidate_campaign_surface = __esm({
21449
21646
  }
21450
21647
  });
21451
21648
 
21649
+ // apps/cli/dist/src/commands/snapshot-safety.js
21650
+ async function repositoryRootForBackupSafety(context) {
21651
+ const adapters = context.adapters;
21652
+ if (adapters === null)
21653
+ return context.projectRoot;
21654
+ const fs = adapters.fs;
21655
+ let current = context.projectRoot;
21656
+ while (true) {
21657
+ for (const marker of [".git", ".hg", ".svn"]) {
21658
+ if (await fs.stat(fs.join(current, marker)) !== null)
21659
+ return current;
21660
+ }
21661
+ if (context.home !== null && fs.isInside(current, context.home) && fs.isInside(context.home, current)) {
21662
+ return null;
21663
+ }
21664
+ const parent = fs.dirname(current);
21665
+ if (parent === current)
21666
+ return null;
21667
+ current = parent;
21668
+ }
21669
+ }
21670
+ var init_snapshot_safety = __esm({
21671
+ "apps/cli/dist/src/commands/snapshot-safety.js"() {
21672
+ "use strict";
21673
+ }
21674
+ });
21675
+
21452
21676
  // apps/cli/dist/src/commands/gitnexus-candidate-lifecycle.js
21453
21677
  function emptyReport(outcome2, requestedStateVerified = false) {
21454
21678
  return {
@@ -21510,7 +21734,7 @@ function selectorProblem(context, command) {
21510
21734
  }
21511
21735
  return null;
21512
21736
  }
21513
- function stores(context, id) {
21737
+ async function stores(context, id) {
21514
21738
  if (context.adapters === null || context.stateRoot === null)
21515
21739
  return null;
21516
21740
  const fs = context.adapters.fs;
@@ -21518,7 +21742,7 @@ function stores(context, id) {
21518
21742
  fs,
21519
21743
  backupRoot: fs.join(context.stateRoot, "backups"),
21520
21744
  transactionId: id,
21521
- projectRoot: context.projectRoot,
21745
+ projectRoot: await repositoryRootForBackupSafety(context),
21522
21746
  now: context.now
21523
21747
  });
21524
21748
  if (!creation.ok)
@@ -21711,7 +21935,7 @@ async function runGitNexusCandidateApply(context) {
21711
21935
  return finish("apply", EXIT_CODES["confirmation-required"], emptyReport("confirmation-required"), diagnostics);
21712
21936
  }
21713
21937
  const id = transactionId("gitnexus-activate-claude", context);
21714
- const built = stores(context, id);
21938
+ const built = await stores(context, id);
21715
21939
  if (built === null || !("snapshots" in built)) {
21716
21940
  diagnostics.push(...built?.failure ?? []);
21717
21941
  return finish("apply", EXIT_CODES["unsupported-environment"], emptyReport("rejected"), diagnostics);
@@ -21817,7 +22041,7 @@ async function runGitNexusCandidateUninstall(context) {
21817
22041
  return finish("uninstall", EXIT_CODES["confirmation-required"], emptyReport("confirmation-required"), diagnostics);
21818
22042
  }
21819
22043
  const id = transactionId("gitnexus-deactivate-claude", context);
21820
- const built = stores(context, id);
22044
+ const built = await stores(context, id);
21821
22045
  if (built === null || !("snapshots" in built)) {
21822
22046
  diagnostics.push(...built?.failure ?? []);
21823
22047
  return finish("uninstall", EXIT_CODES["unsupported-environment"], emptyReport("rejected"), diagnostics);
@@ -21857,6 +22081,7 @@ var init_gitnexus_candidate_lifecycle = __esm({
21857
22081
  init_src3();
21858
22082
  init_src();
21859
22083
  init_candidate_campaign_surface();
22084
+ init_snapshot_safety();
21860
22085
  ACTIVATION_ACTION_ID = "gitnexus:claude:mcp-server";
21861
22086
  REMOVAL_ACTION_ID = "gitnexus:claude:mcp-server:remove";
21862
22087
  REVIEWED_VALUE_DIGEST = jsonValueDigest(GITNEXUS_MCP_SERVER);
@@ -21934,7 +22159,7 @@ function selectorProblem2(context, command) {
21934
22159
  }
21935
22160
  return null;
21936
22161
  }
21937
- function stores2(context, transactionId2) {
22162
+ async function stores2(context, transactionId2) {
21938
22163
  if (context.adapters === null || context.stateRoot === null)
21939
22164
  return null;
21940
22165
  const fs = context.adapters.fs;
@@ -21942,7 +22167,7 @@ function stores2(context, transactionId2) {
21942
22167
  fs,
21943
22168
  backupRoot: fs.join(context.stateRoot, "backups"),
21944
22169
  transactionId: transactionId2,
21945
- projectRoot: context.projectRoot,
22170
+ projectRoot: await repositoryRootForBackupSafety(context),
21946
22171
  now: context.now
21947
22172
  });
21948
22173
  if (!creation.ok)
@@ -22033,7 +22258,7 @@ async function runCandidateApply(context) {
22033
22258
  return finish2("apply", EXIT_CODES["confirmation-required"], emptyReport2("confirmation-required"), diagnostics);
22034
22259
  }
22035
22260
  const transactionId2 = candidateTransactionId(`mcptoon-activate-${harness}`, context);
22036
- const built = stores2(context, transactionId2);
22261
+ const built = await stores2(context, transactionId2);
22037
22262
  if (built === null || !("snapshots" in built)) {
22038
22263
  diagnostics.push(...built?.failure ?? []);
22039
22264
  return finish2("apply", EXIT_CODES["unsupported-environment"], emptyReport2("rejected"), diagnostics);
@@ -22178,7 +22403,7 @@ async function runCandidateUninstall(context) {
22178
22403
  return finish2("uninstall", EXIT_CODES["confirmation-required"], emptyReport2("confirmation-required"), diagnostics);
22179
22404
  }
22180
22405
  const transactionId2 = candidateTransactionId(`mcptoon-deactivate-${harness}`, context);
22181
- const built = stores2(context, transactionId2);
22406
+ const built = await stores2(context, transactionId2);
22182
22407
  if (built === null || !("snapshots" in built)) {
22183
22408
  diagnostics.push(...built?.failure ?? []);
22184
22409
  return finish2("uninstall", EXIT_CODES["unsupported-environment"], emptyReport2("rejected"), diagnostics);
@@ -22223,6 +22448,7 @@ var init_mcptoon_candidate_lifecycle = __esm({
22223
22448
  init_src3();
22224
22449
  init_src();
22225
22450
  init_candidate_campaign_surface();
22451
+ init_snapshot_safety();
22226
22452
  }
22227
22453
  });
22228
22454
 
@@ -24539,6 +24765,73 @@ var init_plan2 = __esm({
24539
24765
  });
24540
24766
 
24541
24767
  // apps/cli/dist/src/commands/apply.js
24768
+ async function verifyManagedIntegrationPostconditions(context, integrations) {
24769
+ if (integrations.length === 0)
24770
+ return [];
24771
+ if (context.adapters === null) {
24772
+ return [
24773
+ diagnostic({
24774
+ severity: "error",
24775
+ code: "managed-setup-postcondition-unavailable",
24776
+ message: "The managed integration could not be re-observed because platform adapters are unavailable",
24777
+ remediation: "Refresh the current setup before retrying"
24778
+ })
24779
+ ];
24780
+ }
24781
+ const detectionContext = {
24782
+ fs: context.adapters.fs,
24783
+ runner: context.adapters.runner,
24784
+ facts: context.platform,
24785
+ paths: context.adapters.paths,
24786
+ projectRoot: context.projectRoot
24787
+ };
24788
+ const harnessConfigs = (await Promise.all(listHarnessAdapters().map(async (adapter) => (await adapter.inspect(detectionContext)).summaries))).flat();
24789
+ const providerContext4 = {
24790
+ ...detectionContext,
24791
+ harnessConfigs,
24792
+ now: context.now,
24793
+ localDatabase: context.adapters.localDatabase,
24794
+ projectIdFor: context.adapters.projectIdFor
24795
+ };
24796
+ const adapters = new Map(listProviderAdapters().map((adapter) => [adapter.manifest.id, adapter]));
24797
+ const diagnostics = [];
24798
+ for (const integration of integrations) {
24799
+ const adapter = adapters.get(integration.providerId);
24800
+ if (adapter === void 0) {
24801
+ diagnostics.push(diagnostic({
24802
+ severity: "error",
24803
+ code: "managed-setup-postcondition-unavailable",
24804
+ subject: integration.providerId,
24805
+ message: `The provider adapter disappeared before ${integration.harnessId} setup could be verified`,
24806
+ remediation: "Refresh Token Harness and review a new setup preview"
24807
+ }));
24808
+ continue;
24809
+ }
24810
+ try {
24811
+ const detection = await adapter.detect(providerContext4);
24812
+ if (!detection.configuredHarnesses.some((harness) => harness === integration.harnessId)) {
24813
+ const runtimeProblem = detection.warnings.find((entry) => entry.severity === "error" || entry.severity === "warning");
24814
+ diagnostics.push(diagnostic({
24815
+ severity: "error",
24816
+ code: "managed-setup-postcondition-unmet",
24817
+ subject: integration.providerId,
24818
+ message: `${adapter.manifest.displayName} setup did not become active for ${integration.harnessId} after the approved actions` + (runtimeProblem === void 0 ? "" : `: ${runtimeProblem.message}`),
24819
+ path: detection.executable,
24820
+ remediation: runtimeProblem?.remediation ?? "Check that the newly installed provider executable is on PATH, then review a fresh setup preview"
24821
+ }));
24822
+ }
24823
+ } catch (error) {
24824
+ diagnostics.push(diagnostic({
24825
+ severity: "error",
24826
+ code: "managed-setup-postcondition-unavailable",
24827
+ subject: integration.providerId,
24828
+ message: `The provider could not be re-observed after setup: ${error instanceof Error ? error.message : String(error)}`,
24829
+ remediation: "Refresh and inspect the provider runtime before retrying"
24830
+ }));
24831
+ }
24832
+ }
24833
+ return diagnostics;
24834
+ }
24542
24835
  function transactionIdFor(planId, at) {
24543
24836
  const digest = digestText(`${planId} ${at}`);
24544
24837
  return digest.slice(digest.indexOf(":") + 1, digest.indexOf(":") + 13);
@@ -24758,7 +25051,7 @@ async function runApply(context) {
24758
25051
  fs,
24759
25052
  backupRoot: fs.join(context.stateRoot, "backups"),
24760
25053
  transactionId: transactionId2,
24761
- projectRoot: context.projectRoot,
25054
+ projectRoot: await repositoryRootForBackupSafety(context),
24762
25055
  now: context.now
24763
25056
  });
24764
25057
  if (!creation.ok) {
@@ -24788,7 +25081,8 @@ async function runApply(context) {
24788
25081
  journal,
24789
25082
  // RFC 0004 §Process policy: an installer reaches the machine through the runner or not at all.
24790
25083
  runner: context.adapters.runner,
24791
- now: context.now
25084
+ now: context.now,
25085
+ verifyPostconditions: async () => verifyManagedIntegrationPostconditions(context, computed.managedIntegrations)
24792
25086
  });
24793
25087
  diagnostics.push(...transaction.diagnostics);
24794
25088
  const report = {
@@ -24823,8 +25117,10 @@ var init_apply = __esm({
24823
25117
  "apps/cli/dist/src/commands/apply.js"() {
24824
25118
  "use strict";
24825
25119
  init_src();
25120
+ init_src3();
24826
25121
  init_candidate_lifecycle();
24827
25122
  init_plan2();
25123
+ init_snapshot_safety();
24828
25124
  PLANS_DIRECTORY = "plans";
24829
25125
  }
24830
25126
  });
@@ -27573,7 +27869,7 @@ function finish4(exitCode, command, data, diagnostics) {
27573
27869
  diagnostics
27574
27870
  });
27575
27871
  }
27576
- function stores3(context, transactionId2) {
27872
+ async function stores3(context, transactionId2) {
27577
27873
  if (context.adapters === null || context.stateRoot === null)
27578
27874
  return null;
27579
27875
  const fs = context.adapters.fs;
@@ -27581,7 +27877,7 @@ function stores3(context, transactionId2) {
27581
27877
  fs,
27582
27878
  backupRoot: fs.join(context.stateRoot, "backups"),
27583
27879
  transactionId: transactionId2,
27584
- projectRoot: context.projectRoot,
27880
+ projectRoot: await repositoryRootForBackupSafety(context),
27585
27881
  now: context.now
27586
27882
  });
27587
27883
  if (!creation.ok)
@@ -27656,7 +27952,7 @@ async function runRollback(context) {
27656
27952
  }));
27657
27953
  return finish4(EXIT_CODES["confirmation-required"], "rollback", empty("confirmation-required"), diagnostics);
27658
27954
  }
27659
- const built = stores3(context, target.transactionId);
27955
+ const built = await stores3(context, target.transactionId);
27660
27956
  if (built === null || built.store === void 0) {
27661
27957
  diagnostics.push(...built?.failure ?? []);
27662
27958
  return finish4(EXIT_CODES["unsupported-environment"], "rollback", empty("rejected"), diagnostics);
@@ -27784,7 +28080,7 @@ async function runUninstall(context) {
27784
28080
  }
27785
28081
  const fs = context.adapters.fs;
27786
28082
  const transactionId2 = `uninstall-${context.now().replace(/[^0-9]/g, "").slice(0, 14)}`;
27787
- const built = stores3(context, transactionId2);
28083
+ const built = await stores3(context, transactionId2);
27788
28084
  if (built === null || built.store === void 0) {
27789
28085
  diagnostics.push(...built?.failure ?? []);
27790
28086
  return finish4(EXIT_CODES["unsupported-environment"], "uninstall", empty("rejected"), diagnostics);
@@ -27820,6 +28116,7 @@ var init_rollback = __esm({
27820
28116
  init_src();
27821
28117
  init_candidate_lifecycle();
27822
28118
  init_plan2();
28119
+ init_snapshot_safety();
27823
28120
  }
27824
28121
  });
27825
28122
 
@@ -28430,6 +28727,8 @@ async function runPackageChannelUpdate(context, options = {}) {
28430
28727
  updateTargets.set(action.id, {
28431
28728
  providerId: adapter.manifest.id,
28432
28729
  target: query.version,
28730
+ channel: channel.id,
28731
+ packageName,
28433
28732
  adapter
28434
28733
  });
28435
28734
  }
@@ -28491,7 +28790,7 @@ async function runPackageChannelUpdate(context, options = {}) {
28491
28790
  fs,
28492
28791
  backupRoot: fs.join(context.stateRoot, "backups"),
28493
28792
  transactionId: transactionId2,
28494
- projectRoot: context.projectRoot,
28793
+ projectRoot: await repositoryRootForBackupSafety(context),
28495
28794
  now: context.now
28496
28795
  });
28497
28796
  if (!creation.ok) {
@@ -28526,13 +28825,27 @@ async function runPackageChannelUpdate(context, options = {}) {
28526
28825
  const expected = parseSemanticVersion(target.target);
28527
28826
  const exactTarget = observed !== null && expected !== null && compareVersions(observed, expected) === 0;
28528
28827
  if (!exactTarget) {
28828
+ const inventory = await queryPackageInventory({
28829
+ channel: target.channel,
28830
+ packageName: target.packageName,
28831
+ runner: adapters.runner,
28832
+ cwd: context.projectRoot
28833
+ });
28834
+ const inventoryDetail = inventory.status === "captured" && inventory.version !== null ? ` The ${target.channel} global inventory reports ${inventory.version}.` : ` The ${target.channel} inventory could not confirm the installed target (status: ${inventory.status}).`;
28835
+ const prefix = target.channel === "npm" ? await adapters.runner.run({
28836
+ executable: "npm",
28837
+ args: ["config", "get", "prefix"],
28838
+ cwd: context.projectRoot,
28839
+ timeoutMs: 2e4
28840
+ }) : null;
28841
+ const prefixDetail = prefix !== null && prefix.failure === null && prefix.exitCode === 0 ? ` npm prefix: ${prefix.stdout.trim() || "(empty)"}.` : "";
28529
28842
  postconditions.push(diagnostic({
28530
28843
  severity: "error",
28531
28844
  code: "provider-update-version-not-observed",
28532
28845
  subject: target.adapter.manifest.id,
28533
- message: `${target.providerId} update did not become active: requested ${target.target}, but the executable currently resolved on PATH reports ${detection.version ?? "no readable version"}`,
28846
+ message: `${target.providerId} update did not become active: requested ${target.target}, but the executable currently resolved on PATH reports ${detection.version ?? "no readable version"}.` + inventoryDetail + prefixDetail,
28534
28847
  path: detection.executable,
28535
- remediation: "Review duplicate PATH installations. Token Harness will not report this update as successful while the old executable is still the one being resolved."
28848
+ remediation: "Review duplicate PATH installations and the package-manager global prefix. Token Harness will not report this update as successful while the requested runtime is not the one being resolved."
28536
28849
  }));
28537
28850
  continue;
28538
28851
  }
@@ -28604,6 +28917,7 @@ var init_update_base = __esm({
28604
28917
  "use strict";
28605
28918
  init_src();
28606
28919
  init_src3();
28920
+ init_snapshot_safety();
28607
28921
  }
28608
28922
  });
28609
28923
 
@@ -28864,7 +29178,7 @@ async function runUpdate(context) {
28864
29178
  fs,
28865
29179
  backupRoot: fs.join(context.stateRoot, "backups"),
28866
29180
  transactionId: transactionId2,
28867
- projectRoot: context.projectRoot,
29181
+ projectRoot: await repositoryRootForBackupSafety(context),
28868
29182
  now: context.now
28869
29183
  });
28870
29184
  if (!snapshotCreation.ok) {
@@ -29147,6 +29461,7 @@ var init_update = __esm({
29147
29461
  "use strict";
29148
29462
  init_src();
29149
29463
  init_src2();
29464
+ init_snapshot_safety();
29150
29465
  init_update_base();
29151
29466
  init_rtk_release_update();
29152
29467
  }
@@ -32299,11 +32614,20 @@ function guideSetupTarget(report, harness, provider) {
32299
32614
  };
32300
32615
  }
32301
32616
  if (detection.state === "absent" || detection.state === "available") {
32617
+ if (detection.assignableHarnesses.includes(harnessDetection.harnessId)) {
32618
+ return {
32619
+ providerId: provider,
32620
+ provider: label,
32621
+ state: "actionable",
32622
+ reason: `${label} is not installed yet, but Token Harness has a reviewed automatic install + ${name(harness)} setup path. The exact package and configuration changes are shown before approval.`
32623
+ };
32624
+ }
32625
+ const prerequisite2 = detection.warnings.find((entry) => entry.severity === "warning" || entry.severity === "error");
32302
32626
  return {
32303
32627
  providerId: provider,
32304
32628
  provider: label,
32305
32629
  state: "unavailable",
32306
- reason: `${label} is not installed in a state Token Harness can configure automatically.`
32630
+ reason: prerequisite2 === void 0 ? `${label} is not installed and no automatic installer prerequisite is available in this terminal.` : `${prerequisite2.message}${prerequisite2.remediation === null ? "" : ` ${prerequisite2.remediation}`}`
32307
32631
  };
32308
32632
  }
32309
32633
  if (detection.state === "broken") {
@@ -32315,11 +32639,12 @@ function guideSetupTarget(report, harness, provider) {
32315
32639
  };
32316
32640
  }
32317
32641
  if (!detection.assignableHarnesses.includes(harnessDetection.harnessId)) {
32642
+ const capability = detection.warnings.find((entry) => entry.severity === "warning" || entry.severity === "error");
32318
32643
  return {
32319
32644
  providerId: provider,
32320
32645
  provider: label,
32321
32646
  state: "not-applicable",
32322
- reason: `The installed ${label} build does not expose an automatic ${name(harness)} setup surface.`
32647
+ reason: capability === void 0 ? `The installed ${label} build does not expose an automatic ${name(harness)} setup surface.` : `${capability.message}${capability.remediation === null ? "" : ` ${capability.remediation}`}`
32323
32648
  };
32324
32649
  }
32325
32650
  return {
@@ -32364,7 +32689,7 @@ function stackFingerprint(report) {
32364
32689
  function createGuideCall(base) {
32365
32690
  return async (args) => {
32366
32691
  const savings = args[0] === "savings";
32367
- const updateCheck = args[0] === "update";
32692
+ const updateCheck = args[0] === "update" && !args.includes("--yes");
32368
32693
  const translated = savings ? ["metrics", ...args.slice(1)] : [...args];
32369
32694
  let stdout = "";
32370
32695
  await run({
@@ -32575,7 +32900,7 @@ function describeChange(action, harness) {
32575
32900
  files: action.affectedPaths.length
32576
32901
  };
32577
32902
  }
32578
- var GuideError, NAMES, name, GUIDE_MANAGED_PROVIDERS, RECOMMENDED_SETUP_PROVIDERS, TASKS, PERIODS, STACK_COMPONENTS, ISSUE_COPY, EFFORT_LABELS, SAFETY_RULES, TASK_RULES, READ_STAGES, GuideService;
32903
+ var GuideError, NAMES, name, sameGuideVersion, GUIDE_MANAGED_PROVIDERS, RECOMMENDED_SETUP_PROVIDERS, TASKS, PERIODS, STACK_COMPONENTS, ISSUE_COPY, EFFORT_LABELS, SAFETY_RULES, TASK_RULES, READ_STAGES, GuideService;
32579
32904
  var init_guided = __esm({
32580
32905
  "apps/cli/dist/src/guided.js"() {
32581
32906
  "use strict";
@@ -32603,6 +32928,7 @@ var init_guided = __esm({
32603
32928
  headroom: "Headroom"
32604
32929
  };
32605
32930
  name = (id) => NAMES[id] ?? id;
32931
+ sameGuideVersion = (left, right) => left !== null && right !== null && left.replace(/^v/i, "").trim() === right.replace(/^v/i, "").trim();
32606
32932
  GUIDE_MANAGED_PROVIDERS = [
32607
32933
  "rtk",
32608
32934
  "harnesstrim",
@@ -32654,6 +32980,12 @@ var init_guided = __esm({
32654
32980
  "codex-native-policy-shadowed": "A project or profile overrides this Codex setting. That setting belongs to you and will not be replaced.",
32655
32981
  "no-providers-registered": "No optimization provider was selected for this operation.",
32656
32982
  "already-in-desired-state": "The supported integration is already configured. Nothing needs to be changed.",
32983
+ "delegated-install-snapshot-too-large": "The optimizer setup found too much unrelated data inside its rollback boundary. Nothing was changed. Update Token Harness or use a narrower project directory before retrying.",
32984
+ "delegated-install-failed": "The optimizer installer itself did not complete successfully. Nothing was kept from the failed transaction.",
32985
+ "delegated-install-artifact-mismatch": "The optimizer installer completed but did not produce the artifact contract it advertised. The transaction was rolled back.",
32986
+ "delegated-install-protected-path-changed": "The optimizer installer touched a file this setup promised to leave alone. The transaction was rolled back.",
32987
+ "delegated-install-undeclared-write": "The optimizer installer changed a path outside the approved write set. The transaction was rolled back.",
32988
+ "action-precondition-drift": "A file changed after the preview was created. Review a fresh preview before applying anything.",
32657
32989
  "managed-mutation-unsupported": "Automatic setup is unavailable because the installed provider does not expose the required managed surface. Existing integrations are left untouched.",
32658
32990
  "plan-ownership-drift": "The integration changed after the preview. Review a fresh plan; nothing was forced.",
32659
32991
  "plan-version-drift": "An installed version changed after the preview. Review a fresh plan.",
@@ -33210,49 +33542,137 @@ var init_guided = __esm({
33210
33542
  throw new GuideError(409, "This preview expired or was already used. Review a fresh preview.");
33211
33543
  this.approval = null;
33212
33544
  if (approval.operation === "update") {
33213
- this.record("Installing only the provider updates you approved.", "working");
33214
- let result6;
33545
+ const approvedUpdates = approval.updateTargets ?? [];
33546
+ if (approvedUpdates.length === 0)
33547
+ throw new GuideError(409, "This update preview contains no concrete provider version. Review it again.");
33548
+ this.record("Re-checking the exact provider versions you approved before installing them.", "working");
33549
+ let fresh;
33215
33550
  try {
33216
- result6 = await this.call(["update", "--yes"]);
33551
+ fresh = await this.call(["update"]);
33217
33552
  } catch {
33218
33553
  this.invalidateObservedState();
33219
- const message = "The update stopped before its final result could be read. No automatic retry was made. Refresh and inspect the installed optimizer versions before retrying.";
33554
+ const message = "The update channels could not be re-checked immediately before installation. Nothing was changed. Review a fresh update preview.";
33220
33555
  this.record(message, "attention");
33221
33556
  return {
33222
33557
  ok: false,
33223
- title: "Update result needs checking",
33558
+ title: "Update preview changed",
33224
33559
  messages: [message],
33225
33560
  appliedPlans: 0
33226
33561
  };
33227
33562
  }
33228
- if (result6.exitCode !== 0 || result6.data === null) {
33229
- const message = explainGuideIssue(result6.diagnostics, "The optimizer update was not applied. The installed version, update channel or runtime capability state changed after the preview, so nothing was forced.");
33563
+ if (fresh.exitCode !== 0 || fresh.data === null) {
33564
+ const message = explainGuideIssue(fresh.diagnostics, "The update channels changed or could not be re-checked after approval. Nothing was changed; review a fresh update preview.");
33565
+ this.invalidateObservedState();
33566
+ this.record(message, "attention");
33567
+ return {
33568
+ ok: false,
33569
+ title: "Update preview changed",
33570
+ messages: [message],
33571
+ appliedPlans: 0
33572
+ };
33573
+ }
33574
+ const approvedByProvider = new Map(approvedUpdates.map((target) => [String(target.provider), target.version]));
33575
+ const freshUpgradable = fresh.data.providers.filter((row2) => row2.verdict === "upgradable");
33576
+ const unexpected = freshUpgradable.find((row2) => {
33577
+ const approved = approvedByProvider.get(String(row2.providerId)) ?? null;
33578
+ return approved === null || !sameGuideVersion(row2.available, approved);
33579
+ });
33580
+ const unresolved = approvedUpdates.find((target) => {
33581
+ const row2 = fresh.data?.providers.find((candidate) => candidate.providerId === target.provider);
33582
+ return !(row2 !== void 0 && (row2.verdict === "upgradable" && sameGuideVersion(row2.available, target.version) || row2.verdict === "current" && sameGuideVersion(row2.installed, target.version)));
33583
+ });
33584
+ if (unexpected !== void 0 || unresolved !== void 0) {
33585
+ const changed = unexpected !== void 0 ? `${name(unexpected.providerId)} now offers ${unexpected.available ?? "a different version"}.` : `${name(unresolved.provider)} no longer reports the approved target ${unresolved.version}.`;
33586
+ const message = changed + " Nothing was installed because the live update state no longer matches the preview. Review a fresh update preview.";
33230
33587
  this.invalidateObservedState();
33231
33588
  this.record(message, "attention");
33232
33589
  return {
33233
33590
  ok: false,
33234
- title: "Optimizer update was not applied",
33591
+ title: "Update preview changed",
33235
33592
  messages: [message],
33236
33593
  appliedPlans: 0
33237
33594
  };
33238
33595
  }
33239
- const applied = result6.data.execution?.results.filter((row2) => row2.status === "applied") ?? [];
33596
+ const pending = approvedUpdates.filter((target) => {
33597
+ const row2 = fresh.data?.providers.find((candidate) => candidate.providerId === target.provider);
33598
+ return row2?.verdict === "upgradable";
33599
+ });
33600
+ let appliedCount = 0;
33601
+ if (pending.length > 0) {
33602
+ this.record("Installing the provider versions from the approved preview.", "working");
33603
+ let result6;
33604
+ try {
33605
+ result6 = await this.call(["update", "--yes"]);
33606
+ } catch {
33607
+ this.invalidateObservedState();
33608
+ const message = "The update stopped before its final result could be read. No automatic retry was made. Refresh and inspect the installed optimizer versions before retrying.";
33609
+ this.record(message, "attention");
33610
+ return {
33611
+ ok: false,
33612
+ title: "Update result needs checking",
33613
+ messages: [message],
33614
+ appliedPlans: 0
33615
+ };
33616
+ }
33617
+ if (result6.exitCode !== 0 || result6.data === null) {
33618
+ const message = explainGuideIssue(result6.diagnostics, "The optimizer update was not applied. The installed version, update channel or runtime capability state changed after the preview, so nothing was forced.");
33619
+ this.invalidateObservedState();
33620
+ this.record(message, "attention");
33621
+ return {
33622
+ ok: false,
33623
+ title: "Optimizer update was not applied",
33624
+ messages: [message],
33625
+ appliedPlans: 0
33626
+ };
33627
+ }
33628
+ appliedCount = result6.data.execution?.results.filter((row2) => row2.status === "applied").length ?? 0;
33629
+ }
33630
+ let inventory;
33631
+ try {
33632
+ inventory = await this.call(["doctor"]);
33633
+ } catch {
33634
+ this.invalidateObservedState();
33635
+ const message = "The installer returned, but Token Harness could not re-read the active optimizer runtimes. The update is not being reported as successful. Refresh and inspect the installed versions.";
33636
+ this.record(message, "attention");
33637
+ return {
33638
+ ok: false,
33639
+ title: "Update result needs checking",
33640
+ messages: [message],
33641
+ appliedPlans: appliedCount
33642
+ };
33643
+ }
33644
+ const missing = approvedUpdates.filter((target) => {
33645
+ const detection = inventory.data?.providers.find((candidate) => candidate.providerId === target.provider);
33646
+ return !sameGuideVersion(detection?.version ?? null, target.version);
33647
+ });
33648
+ if (inventory.data === null || missing.length > 0) {
33649
+ const message = missing.length > 0 ? "The approved update target was not observed on the active PATH after installation: " + missing.map((target) => `${name(target.provider)} ${target.version}`).join(", ") + ". This is not being reported as a successful update." : "The active optimizer versions could not be verified after installation. This is not being reported as a successful update.";
33650
+ this.invalidateObservedState();
33651
+ this.record(message, "attention");
33652
+ return {
33653
+ ok: false,
33654
+ title: "Update was not verified",
33655
+ messages: [
33656
+ message,
33657
+ "Refresh after correcting PATH or the package installation; no automatic retry was made."
33658
+ ],
33659
+ appliedPlans: appliedCount
33660
+ };
33661
+ }
33240
33662
  this.lastApplied = null;
33241
33663
  this.invalidateObservedState();
33242
- const messages2 = applied.length > 0 ? [
33243
- "The optimizer update completed successfully and the active runtime was verified.",
33244
- "Token Harness re-ran the update transaction safety checks before changing software.",
33245
- "Choose Refresh to read the installed versions again. Reopen a coding agent if the updated optimizer requires it."
33246
- ] : [
33247
- "No optimizer needed an update by the time the approved action ran.",
33248
- "Nothing was forced. Choose Refresh to read the current versions."
33664
+ const versions = approvedUpdates.map((target) => `${name(target.provider)} ${target.version}`).join(", ");
33665
+ const messages2 = [
33666
+ appliedCount > 0 ? `Installed and verified the approved optimizer version${approvedUpdates.length === 1 ? "" : "s"}: ${versions}.` : `The approved optimizer version${approvedUpdates.length === 1 ? " was" : "s were"} already active when the final check ran: ${versions}.`,
33667
+ "The active runtime was re-read after the operation; success is shown only because it matches the approved target.",
33668
+ "Reopen a coding agent if the updated optimizer requires it."
33249
33669
  ];
33250
- this.record(applied.length > 0 ? "Optimizer update installed and verified." : "Optimizer update no longer needed.", "success");
33670
+ this.record(appliedCount > 0 ? "Optimizer update installed and verified." : "Approved optimizer version already active and verified.", "success");
33251
33671
  return {
33252
33672
  ok: true,
33253
- title: applied.length > 0 ? "Optimizer updated" : "Already up to date",
33673
+ title: appliedCount > 0 ? "Optimizer updated" : "Approved version already active",
33254
33674
  messages: messages2,
33255
- appliedPlans: applied.length
33675
+ appliedPlans: appliedCount
33256
33676
  };
33257
33677
  }
33258
33678
  if (approval.operation === "candidate-apply" || approval.operation === "candidate-uninstall") {
@@ -33451,6 +33871,7 @@ var init_guided = __esm({
33451
33871
  }
33452
33872
  this.updates = { fingerprint, report: updateResult.data };
33453
33873
  const available = updateResult.data.providers.filter((row2) => row2.verdict === "upgradable");
33874
+ const updateTargets = available.flatMap((row2) => row2.available === null ? [] : [{ provider: row2.providerId, version: row2.available }]);
33454
33875
  const blocked = updateResult.data.providers.filter((row2) => row2.verdict === "blocked-unreviewed");
33455
33876
  const messages = [];
33456
33877
  if (available.length > 0) {
@@ -33462,7 +33883,9 @@ var init_guided = __esm({
33462
33883
  if (available.length === 0 && blocked.length === 0)
33463
33884
  messages.push("Your managed optimizers are up to date on their configured channels.");
33464
33885
  let ticket = null;
33465
- if (available.length > 0) {
33886
+ if (available.length > 0 && updateTargets.length !== available.length) {
33887
+ messages.push("An update channel reported an upgradable optimizer without a concrete target version. No install approval was created.");
33888
+ } else if (updateTargets.length > 0) {
33466
33889
  ticket = this.random();
33467
33890
  const expires = this.now() + 10 * 6e4;
33468
33891
  this.approval = {
@@ -33473,7 +33896,8 @@ var init_guided = __esm({
33473
33896
  provider: null,
33474
33897
  description: "Optimizer updates",
33475
33898
  operation: "update",
33476
- network: updateResult.data.network.length > 0
33899
+ network: updateResult.data.network.length > 0,
33900
+ updateTargets
33477
33901
  };
33478
33902
  messages.push("Review the versions above, then choose Install updates. Token Harness will re-check the update channels and transaction safety rules before changing software.");
33479
33903
  } else {
@@ -33482,10 +33906,10 @@ var init_guided = __esm({
33482
33906
  const stack = this.stackSnapshot();
33483
33907
  if (this.cached !== null)
33484
33908
  this.cached.value = { ...this.cached.value, stack };
33485
- this.record(available.length > 0 ? "Optimizer update available. Waiting for your approval." : "Provider update check completed. No update is pending.", "success");
33909
+ this.record(ticket !== null ? "Optimizer update available. Waiting for your approval." : available.length > 0 ? "Provider update check could not produce an exact install target." : "Provider update check completed. No update is pending.", "success");
33486
33910
  return {
33487
33911
  ok: true,
33488
- title: available.length > 0 ? "Updates available" : "Optimizers up to date",
33912
+ title: ticket !== null ? "Updates available" : available.length > 0 ? "Update check needs attention" : "Optimizers up to date",
33489
33913
  messages,
33490
33914
  appliedPlans: 0,
33491
33915
  stack,
@@ -35942,16 +36366,21 @@ var init_guided_product_client = __esm({
35942
36366
  function componentState(id, component) {
35943
36367
  if (!component || component.detectedState === 'absent') return { label: 'Not installed', cls: '' };
35944
36368
  if (component.health === 'attention') return { label: 'Needs attention', cls: 'warn' };
35945
- if (component.configured)
36369
+ const targets = activeAgents().map(agent => setupTarget(agent.id, id)).filter(Boolean);
36370
+ const connectedHere = targets.some(target => target.state === 'connected');
36371
+ const actionableHere = targets.some(target => target.state === 'actionable');
36372
+ if (component.installed && actionableHere && connectedHere)
36373
+ return { label: 'Partially connected · setup available', cls: 'warn' };
36374
+ if (component.installed && actionableHere)
36375
+ return { label: 'Installed · setup available', cls: 'warn' };
36376
+ if (connectedHere)
35946
36377
  return {
35947
36378
  label: component.verification === 'verified' ? 'Connected · verified' : 'Connected',
35948
36379
  cls: 'good',
35949
36380
  };
35950
- const targets = activeAgents().map(agent => setupTarget(agent.id, id)).filter(Boolean);
35951
- if (component.installed && targets.some(target => target.state === 'actionable'))
35952
- return { label: 'Installed · setup available', cls: 'warn' };
35953
36381
  if (component.installed && targets.some(target => target.state === 'unavailable'))
35954
36382
  return { label: 'Installed · no automatic setup', cls: '' };
36383
+ if (component.configured) return { label: 'Connected elsewhere', cls: '' };
35955
36384
  if (component.installed) return { label: 'Installed', cls: '' };
35956
36385
  return { label: 'Not installed', cls: '' };
35957
36386
  }
@@ -35978,15 +36407,25 @@ var init_guided_product_client = __esm({
35978
36407
  const actionableFor = providerTargets
35979
36408
  .filter(item => item.target.state === 'actionable')
35980
36409
  .map(item => item.agent.name);
35981
- const unavailableFor = providerTargets.filter(item => item.target.state === 'unavailable');
35982
- const configuredFor = component?.configuredHarnesses?.length
35983
- ? component.configuredHarnesses.map(agentName).join(', ')
35984
- : actionableFor.length
35985
- ? 'Setup available for ' + actionableFor.join(', ')
35986
- : unavailableFor.length
35987
- ? 'No compatible automatic setup surface detected'
35988
- : 'Not applicable to the detected coding agents';
35989
- facts.append(node('span', 'Connection'), node('strong', configuredFor));
36410
+ const unavailableFor = providerTargets
36411
+ .filter(item => item.target.state === 'unavailable')
36412
+ .map(item => item.agent.name);
36413
+ const notApplicableFor = providerTargets
36414
+ .filter(item => item.target.state === 'not-applicable')
36415
+ .map(item => item.agent.name);
36416
+ const connectedFor = component?.configuredHarnesses?.length
36417
+ ? component.configuredHarnesses.map(agentName)
36418
+ : [];
36419
+ if (connectedFor.length)
36420
+ facts.append(node('span', 'Connected to'), node('strong', connectedFor.join(', ')));
36421
+ if (actionableFor.length)
36422
+ facts.append(node('span', 'Setup available'), node('strong', actionableFor.join(', ')));
36423
+ if (unavailableFor.length)
36424
+ facts.append(node('span', 'Automatic setup unavailable'), node('strong', unavailableFor.join(', ')));
36425
+ if (notApplicableFor.length)
36426
+ facts.append(node('span', 'Not applicable'), node('strong', notApplicableFor.join(', ')));
36427
+ if (!connectedFor.length && !actionableFor.length && !unavailableFor.length && !notApplicableFor.length)
36428
+ facts.append(node('span', 'Connection'), node('strong', 'No detected coding agent target'));
35990
36429
  if (component?.update === 'available')
35991
36430
  facts.append(
35992
36431
  node('span', 'Update'),
@@ -36005,7 +36444,8 @@ var init_guided_product_client = __esm({
36005
36444
  card.append(
36006
36445
  messageBox(
36007
36446
  'Why there is no Connect button',
36008
- unavailableFor[0].target.reason,
36447
+ providerTargets.find(item => item.target.state === 'unavailable')?.target.reason ||
36448
+ 'The installed provider does not expose an automatic setup surface for this coding agent.',
36009
36449
  ),
36010
36450
  );
36011
36451