heyspex 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/README.md +10 -0
  2. package/bin/hs-vault-binding.mjs +157 -0
  3. package/bin/hs.mjs +81 -77
  4. package/bin/spexcode.mjs +91 -0
  5. package/dev-factory/engine/worktree.mjs +36 -7
  6. package/dev-factory/lib/epic-detect.mjs +2 -2
  7. package/dev-factory/lib/fleet-readiness.mjs +3 -5
  8. package/dev-factory/lib/fleet-state.mjs +2 -2
  9. package/dev-factory/lib/sufficiency-score.mjs +3 -5
  10. package/dist/cli/hs-check.mjs +76 -46
  11. package/dist/cli/hs-claim.mjs +63 -33
  12. package/dist/cli/hs-connect.mjs +520 -214
  13. package/dist/cli/hs-defer.mjs +161 -19
  14. package/dist/cli/hs-dev.mjs +11 -5
  15. package/dist/cli/hs-env.mjs +187 -161
  16. package/dist/cli/hs-index-rebuild.mjs +123 -78
  17. package/dist/cli/hs-index-reconcile.mjs +203 -107
  18. package/dist/cli/hs-init.mjs +426 -179
  19. package/dist/cli/hs-install.mjs +759 -437
  20. package/dist/cli/hs-join.mjs +590 -383
  21. package/dist/cli/hs-vault-pull.mjs +359 -254
  22. package/dist/cli/hs-vault-push.mjs +151 -113
  23. package/dist/cli/hs-vault.mjs +271 -104
  24. package/dist/cli/hs-workspace.mjs +90 -57
  25. package/dist/cli-templates/customer-vault/specs/protocols/session-close-protocol.md +178 -91
  26. package/docs/copilot-plugin-install.md +189 -177
  27. package/docs/driving-heyspex-from-copilot.md +174 -165
  28. package/docs/mcp-client-config.md +93 -25
  29. package/package.json +255 -250
  30. package/plugins/heyspex/.mcp.json +3 -4
  31. package/plugins/heyspex/README.md +323 -312
  32. package/plugins/heyspex/bin/launch-mcp.mjs +21 -7
  33. package/plugins/heyspex/mcp.json +12 -13
  34. package/scripts/check-mcp-freshness.mjs +6 -4
  35. package/scripts/claude-hooks/_intent-classifier-router.mjs +518 -456
  36. package/scripts/claude-hooks/intent-classifier-trigger.mjs +305 -279
  37. package/scripts/claude-hooks/research-method-guard.mjs +2 -2
  38. package/scripts/claude-hooks/wip-checkpoint.mjs +33 -9
  39. package/scripts/claude-statusline/fonts/HeySpexIcons.ttf +0 -0
  40. package/scripts/claude-statusline/statusline-command.mjs +1058 -0
  41. package/scripts/dev-server-status.mjs +3 -2
  42. package/scripts/dev-server-stop.mjs +3 -2
  43. package/scripts/hs-capture-cli.mjs +2 -2
  44. package/scripts/hs-settings.mjs +2 -2
  45. package/scripts/hs-view.mjs +3 -2
  46. package/scripts/install-copilot-hooks.mjs +64 -34
  47. package/scripts/lib/copilot-cli.mjs +108 -0
  48. package/scripts/lib/customer-kit.mjs +223 -30
  49. package/scripts/lib/dev-mode.mjs +28 -2
  50. package/scripts/lib/shared-path-helpers.mjs +32 -0
  51. package/scripts/lib/standalone-doctor.mjs +131 -32
  52. package/scripts/wip-ledger-health.mjs +3 -2
  53. package/spexharness/src/gates/vault-mirror-catchup.mjs +113 -24
  54. package/spexharness/src/gates/vault-mirror-catchup.runner.mjs +52 -0
  55. package/spexharness/src/intent-directive.mjs +839 -626
  56. package/spexharness/src/rule-table.mjs +1 -1
  57. package/vendor/heyspex-mcp/cli-verbs.mjs +16 -2
  58. package/vendor/heyspex-mcp/cli.mjs +20 -4
  59. package/vendor/heyspex-mcp/console-fetch.mjs +15 -3
  60. package/vendor/heyspex-mcp/dev-tools.mjs +11 -4
  61. package/vendor/heyspex-mcp/events-tools.mjs +1 -1
  62. package/vendor/heyspex-mcp/factory-run-status.mjs +42 -0
  63. package/vendor/heyspex-mcp/mcp-config.mjs +4 -2
  64. package/vendor/heyspex-mcp/spec-edit-tools.mjs +26 -1
  65. package/vendor/heyspex-mcp/test-helpers.mjs +5 -2
  66. package/vendor/heyspex-mcp/tool-catalog.mjs +12 -0
  67. package/vendor/heyspex-mcp/tool-dispatch.mjs +59 -23
  68. package/vendor/heyspex-mcp/usable-dir-env.mjs +82 -0
  69. package/vendor/heyspex-mcp/vault-binding.mjs +839 -0
  70. package/vendor/heyspex-mcp/vault-resolve.mjs +353 -245
@@ -234,6 +234,11 @@ function readLocalDevModeRecord({ homeDir = heyspexHome(), readFile = defaultRea
234
234
  return { record: null, parseError: `unparseable dev-mode.json: ${String(err?.message ?? err)}` };
235
235
  }
236
236
  }
237
+ function overrideCloudCheck(source, cloudKnown, staleAgainstCloud) {
238
+ if (source !== "local-override") return "not-applicable";
239
+ if (!cloudKnown) return "unverified";
240
+ return staleAgainstCloud ? "stale" : "in-sync";
241
+ }
237
242
  function resolveDevMode({
238
243
  env = process.env,
239
244
  homeDir = heyspexHome(),
@@ -273,6 +278,7 @@ function resolveDevMode({
273
278
  const semantics = deriveSemantics(mode, reliance);
274
279
  const consoleUrl = source === "local-override" && local.record?.console_url ? local.record.console_url.replace(/\/+$/, "") : semantics.consoleUrl;
275
280
  const staleAgainstCloud = source === "local-override" && cloudValue !== null && (cloudValue.mode !== mode || mode === "dev" && cloudValue.reliance !== semantics.reliance);
281
+ const cloudCheck = overrideCloudCheck(source, cloudKnown, staleAgainstCloud);
276
282
  return {
277
283
  mode,
278
284
  reliance: semantics.reliance,
@@ -290,7 +296,8 @@ function resolveDevMode({
290
296
  present: local.record !== null,
291
297
  record: local.record,
292
298
  parseError: local.parseError,
293
- staleAgainstCloud
299
+ staleAgainstCloud,
300
+ cloudCheck
294
301
  },
295
302
  cloudSetting: { known: cloudKnown, value: cloudValue }
296
303
  };
@@ -3615,7 +3622,7 @@ var init_satellite = __esm({
3615
3622
  });
3616
3623
 
3617
3624
  // spex-console/src/lib/vault-resolve/index.ts
3618
- import { existsSync as existsSync2, readFileSync as readFileSync7 } from "node:fs";
3625
+ import { existsSync as existsSync2, readFileSync as readFileSync7, realpathSync, statSync } from "node:fs";
3619
3626
  import { tmpdir } from "node:os";
3620
3627
  import path2 from "node:path";
3621
3628
  async function defaultRegistryLookup() {
@@ -3669,8 +3676,44 @@ function readMarkerSatellite(dir) {
3669
3676
  function isVaultRootDir(dir) {
3670
3677
  const norm = (p) => path2.resolve(p).replace(/[\\/]+/g, "/").replace(/\/+$/, "").toLowerCase();
3671
3678
  if (norm(dir) === norm(tmpdir())) return false;
3679
+ if (!existsSync2(path2.join(dir, "specs")) && readRepoBinding(dir)) return false;
3672
3680
  return existsSync2(path2.join(dir, "heyspex.yaml")) || existsSync2(path2.join(dir, "specs"));
3673
3681
  }
3682
+ function parseRepoBinding(content) {
3683
+ const src = String(content ?? "");
3684
+ if (/^(vault_id|vault_root):/m.test(src)) return null;
3685
+ const kind = src.match(/^kind:\s*(.+?)\s*$/m)?.[1]?.replace(/^["']|["']$/g, "").trim();
3686
+ if (kind && kind !== "repo-binding") return null;
3687
+ const lines = src.split(/\r?\n/);
3688
+ const start = lines.findIndex((l) => /^vault:(\s|$)/.test(l));
3689
+ if (start === -1) return null;
3690
+ const unq = (v) => v.trim().replace(/\s+#.*$/, "").replace(/^"(.*)"$/, "$1").replace(/^'(.*)'$/, "$1").trim();
3691
+ const scalar = lines[start].slice("vault:".length).trim();
3692
+ if (scalar && !scalar.startsWith("#")) {
3693
+ const id = unq(scalar);
3694
+ return id ? { id, name: null, remote: null } : null;
3695
+ }
3696
+ const out = {
3697
+ id: null,
3698
+ name: null,
3699
+ remote: null
3700
+ };
3701
+ for (let i = start + 1; i < lines.length; i += 1) {
3702
+ const l = lines[i];
3703
+ if (!l.trim() || /^\s*#/.test(l)) continue;
3704
+ if (!/^\s+/.test(l)) break;
3705
+ const m = l.match(/^\s+([a-z_]+):\s*(.*)$/);
3706
+ if (m && (m[1] === "id" || m[1] === "name" || m[1] === "remote")) out[m[1]] = unq(m[2]) || null;
3707
+ }
3708
+ return out.id ? { id: out.id, name: out.name, remote: out.remote } : null;
3709
+ }
3710
+ function readRepoBinding(dir) {
3711
+ try {
3712
+ return parseRepoBinding(readFileSync7(path2.join(dir, "heyspex.yaml"), "utf8"));
3713
+ } catch {
3714
+ return null;
3715
+ }
3716
+ }
3674
3717
  function findCwdVaultOrAttachment(startDir, stopAt) {
3675
3718
  const deps = {
3676
3719
  fileExists: (p) => existsSync2(p),
@@ -3697,6 +3740,8 @@ function findCwdVaultOrAttachment(startDir, stopAt) {
3697
3740
  const pinned = readPinnedVaultRoot(dir, deps).find((pin) => !isAtOrUnder(pin.value, dir));
3698
3741
  if (pinned) return { repoRootAbs: path2.resolve(pinned.value), satellite: true };
3699
3742
  if (isVaultRootDir(dir)) return { repoRootAbs: dir, satellite: false };
3743
+ const binding = readRepoBinding(dir);
3744
+ if (binding) return { repoRootAbs: dir, satellite: false, binding };
3700
3745
  if (boundary && dir === boundary) return null;
3701
3746
  const parent = path2.dirname(dir);
3702
3747
  if (parent === dir) return null;
@@ -3704,6 +3749,22 @@ function findCwdVaultOrAttachment(startDir, stopAt) {
3704
3749
  }
3705
3750
  return null;
3706
3751
  }
3752
+ function isExistingDir(p) {
3753
+ try {
3754
+ return statSync(p).isDirectory();
3755
+ } catch {
3756
+ return false;
3757
+ }
3758
+ }
3759
+ function envNotVaultError(name, raw, abs, from) {
3760
+ const shown = abs.replace(/\\/g, "/");
3761
+ return new VaultResolutionFailure(
3762
+ "VAULT_NOT_FOUND",
3763
+ `${name}=${raw} does not name a vault checkout (${shown}). Unset ${name} so the vault bound to this repo is used (\`hs vault resolve\` shows it), or point it at a vault checkout.`,
3764
+ `unset ${name}`,
3765
+ from
3766
+ );
3767
+ }
3707
3768
  async function resolveActiveVaultRoot(options2 = {}) {
3708
3769
  const registryLookup = options2.registryLookup ?? defaultRegistryLookup;
3709
3770
  const accountPointerLookup = options2.accountPointerLookup ?? defaultAccountPointerLookup;
@@ -3735,8 +3796,70 @@ async function resolveActiveVaultRoot(options2 = {}) {
3735
3796
  detail: `explicit vaultId "${options2.vaultId}" has no registry.json row and no Neon row`
3736
3797
  });
3737
3798
  }
3738
- const cwdBase = path2.resolve(options2.cwd ?? process.cwd());
3799
+ const fromDir = path2.resolve(options2.cwd ?? process.cwd());
3800
+ const envRoot = process.env.HEYSPEX_VAULT_ROOT;
3801
+ if (envRoot) {
3802
+ const root = path2.resolve(envRoot.trim());
3803
+ const envIsVault = isExistingDir(root) && isVaultRootDir(root);
3804
+ if (!envIsVault && !await registryLookupByRoot(root)) {
3805
+ onTier({
3806
+ tier: "env-vault-root",
3807
+ outcome: "empty",
3808
+ detail: `${envRoot} is not a vault checkout`
3809
+ });
3810
+ throw envNotVaultError("HEYSPEX_VAULT_ROOT", envRoot, root, fromDir);
3811
+ }
3812
+ onTier({ tier: "env-vault-root", outcome: "resolved", detail: envRoot });
3813
+ return finalizePathTier(root, "env-vault-root");
3814
+ }
3815
+ onTier({ tier: "env-vault-root", outcome: "skipped", detail: "HEYSPEX_VAULT_ROOT unset" });
3816
+ const envDir = process.env.HEYSPEX_VAULT_DIR;
3817
+ if (envDir) {
3818
+ const specsDirFromEnv = path2.resolve(envDir.trim());
3819
+ const envDirIsSpecs = isExistingDir(specsDirFromEnv) && path2.basename(specsDirFromEnv).toLowerCase() === "specs";
3820
+ const envDirRegistered = Boolean(await registryLookupByRoot(path2.dirname(specsDirFromEnv)));
3821
+ if (!envDirIsSpecs && !envDirRegistered) {
3822
+ onTier({
3823
+ tier: "env-vault-dir",
3824
+ outcome: "empty",
3825
+ detail: `${envDir} is not a specs/ folder`
3826
+ });
3827
+ throw envNotVaultError("HEYSPEX_VAULT_DIR", envDir, specsDirFromEnv, fromDir);
3828
+ }
3829
+ onTier({ tier: "env-vault-dir", outcome: "resolved", detail: envDir });
3830
+ return finalizePathTier(path2.dirname(specsDirFromEnv), "env-vault-dir");
3831
+ }
3832
+ onTier({ tier: "env-vault-dir", outcome: "skipped", detail: "HEYSPEX_VAULT_DIR unset" });
3833
+ let cwdBase = path2.resolve(options2.cwd ?? process.cwd());
3834
+ try {
3835
+ cwdBase = realpathSync(cwdBase);
3836
+ } catch {
3837
+ }
3739
3838
  const cwdMatch = findCwdVaultOrAttachment(cwdBase, options2.cwdWalkRoot);
3839
+ if (cwdMatch?.binding) {
3840
+ const record = await registryLookup(cwdMatch.binding.id);
3841
+ const root = record ? record.repoRootAbs : null;
3842
+ if (root) {
3843
+ onTier({
3844
+ tier: "repo-binding",
3845
+ outcome: "resolved",
3846
+ detail: `${cwdMatch.repoRootAbs} -> ${cwdMatch.binding.id}`
3847
+ });
3848
+ return finalize(cwdMatch.binding.id, root, "repo-binding");
3849
+ }
3850
+ onTier({
3851
+ tier: "repo-binding",
3852
+ outcome: "no-registry-row",
3853
+ detail: `${cwdMatch.repoRootAbs}/heyspex.yaml binds ${cwdMatch.binding.id}, which has no registry row (or folder) on this machine`
3854
+ });
3855
+ const bindingDir = cwdMatch.repoRootAbs.replace(/\\/g, "/");
3856
+ throw new VaultResolutionFailure(
3857
+ "VAULT_BINDING_BROKEN",
3858
+ `${bindingDir}/heyspex.yaml binds this repo to vault ${cwdMatch.binding.name ?? cwdMatch.binding.id} (${cwdMatch.binding.id}), but this machine has no registered checkout of it. Clone it (or \`hs pull\` in an existing checkout), \`hs vault register <path>\`, then \`hs vault bind --vault ${cwdMatch.binding.id}\` in ${bindingDir}.`,
3859
+ `hs vault bind --vault ${cwdMatch.binding.id}`,
3860
+ cwdBase
3861
+ );
3862
+ }
3740
3863
  if (cwdMatch?.satellite) {
3741
3864
  onTier({ tier: "satellite-pin", outcome: "resolved", detail: cwdMatch.repoRootAbs });
3742
3865
  if (cwdMatch.markerVaultId) {
@@ -3744,7 +3867,7 @@ async function resolveActiveVaultRoot(options2 = {}) {
3744
3867
  }
3745
3868
  return finalizePathTier(cwdMatch.repoRootAbs, "satellite-pin");
3746
3869
  }
3747
- if (cwdMatch) {
3870
+ if (cwdMatch && !cwdMatch.binding) {
3748
3871
  const root = path2.resolve(cwdMatch.repoRootAbs);
3749
3872
  const record = await registryLookupByRoot(root);
3750
3873
  const markerVaultId = readMarkerVaultId(root);
@@ -3768,19 +3891,18 @@ async function resolveActiveVaultRoot(options2 = {}) {
3768
3891
  outcome: "empty",
3769
3892
  detail: `no satellite pin, heyspex.yaml or specs/ at or above ${cwdBase}`
3770
3893
  });
3771
- const envRoot = process.env.HEYSPEX_VAULT_ROOT;
3772
- if (envRoot) {
3773
- onTier({ tier: "env-vault-root", outcome: "resolved", detail: envRoot });
3774
- return finalizePathTier(path2.resolve(envRoot), "env-vault-root");
3775
- }
3776
- onTier({ tier: "env-vault-root", outcome: "skipped", detail: "HEYSPEX_VAULT_ROOT unset" });
3777
- const envDir = process.env.HEYSPEX_VAULT_DIR;
3778
- if (envDir) {
3779
- const specsDirFromEnv = path2.resolve(envDir);
3780
- onTier({ tier: "env-vault-dir", outcome: "resolved", detail: envDir });
3781
- return finalizePathTier(path2.dirname(specsDirFromEnv), "env-vault-dir");
3894
+ if (!options2.allowAccountPointer) {
3895
+ onTier({
3896
+ tier: "account-pointer",
3897
+ outcome: "skipped",
3898
+ detail: "account pointer retired for local resolution (HS-TYJA)"
3899
+ });
3900
+ const unbound = new NoActiveVaultError(
3901
+ `No HeySpex vault is bound to ${cwdBase.replace(/\\/g, "/")}, and it is not inside a vault checkout. There is no default "active" vault. Bind this repo: \`hs vault bind --vault <name|id>\` (register a vault checkout first with \`hs vault register <path>\` if \`hs vault list\` shows none).`
3902
+ );
3903
+ unbound.from = cwdBase.replace(/\\/g, "/");
3904
+ throw unbound;
3782
3905
  }
3783
- onTier({ tier: "env-vault-dir", outcome: "skipped", detail: "HEYSPEX_VAULT_DIR unset" });
3784
3906
  const pointerVaultId = await accountPointerLookup(options2.accountId);
3785
3907
  if (pointerVaultId) {
3786
3908
  const record = await registryLookup(pointerVaultId);
@@ -3802,7 +3924,7 @@ async function resolveActiveVaultRoot(options2 = {}) {
3802
3924
  }
3803
3925
  throw new NoActiveVaultError();
3804
3926
  }
3805
- var UNREGISTERED_VAULT_ID, NoActiveVaultError;
3927
+ var UNREGISTERED_VAULT_ID, NoActiveVaultError, VaultResolutionFailure;
3806
3928
  var init_vault_resolve = __esm({
3807
3929
  "spex-console/src/lib/vault-resolve/index.ts"() {
3808
3930
  "use strict";
@@ -3814,6 +3936,22 @@ var init_vault_resolve = __esm({
3814
3936
  this.name = "NoActiveVaultError";
3815
3937
  Object.setPrototypeOf(this, _NoActiveVaultError.prototype);
3816
3938
  }
3939
+ /** Stable machine code ([[HS-TYJA]]), shared with `vault-binding.mjs`. */
3940
+ code = "VAULT_UNBOUND";
3941
+ /** The exact repair command. */
3942
+ fix = "hs vault bind --vault <name|id>";
3943
+ /** The folder resolution walked from (forward slashes), when known. */
3944
+ from = null;
3945
+ };
3946
+ VaultResolutionFailure = class _VaultResolutionFailure extends NoActiveVaultError {
3947
+ constructor(code, message, fix, from) {
3948
+ super(message);
3949
+ this.name = "VaultResolutionError";
3950
+ this.code = code;
3951
+ this.fix = fix;
3952
+ this.from = from ? from.replace(/\\/g, "/") : null;
3953
+ Object.setPrototypeOf(this, _VaultResolutionFailure.prototype);
3954
+ }
3817
3955
  };
3818
3956
  }
3819
3957
  });
@@ -4484,7 +4622,11 @@ async function ensureActiveVaultResolved(options2 = {}) {
4484
4622
  registryLookup: buildRegistryLookup(options2),
4485
4623
  accountPointerLookup: buildAccountPointerLookup(accountId, options2),
4486
4624
  registryLookupByRoot: buildRegistryLookupByRoot(options2.registryOpts),
4487
- onTier: recordVaultResolveTier
4625
+ onTier: recordVaultResolveTier,
4626
+ // Cloud console server: no repo on disk to walk, so the account pointer
4627
+ // is still its last resort until every request names its vault
4628
+ // (follow-up to [[HS-TYJA]]; local resolvers never read it).
4629
+ allowAccountPointer: true
4488
4630
  });
4489
4631
  } catch (err) {
4490
4632
  markVaultResolveFailed(err);
@@ -9523,7 +9665,7 @@ var init_search_body_hit = __esm({
9523
9665
 
9524
9666
  // spex-console/src/lib/vault.ts
9525
9667
  import { spawn } from "node:child_process";
9526
- import { readdirSync, readFileSync as readFileSync9, statSync } from "node:fs";
9668
+ import { readdirSync, readFileSync as readFileSync9, statSync as statSync2 } from "node:fs";
9527
9669
  import { promises as fs6 } from "node:fs";
9528
9670
  import path11 from "node:path";
9529
9671
  import yaml3 from "js-yaml";
@@ -56,6 +56,11 @@ function assertNotRealHomeUnderTest(filePath) {
56
56
  // spex-console/src/lib/dev-mode.ts
57
57
  var CLOUD_CONSOLE_URL = "https://app.heyspex.com";
58
58
  var LOCAL_CONSOLE_URL = "http://localhost:3000";
59
+ function overrideCloudCheck(source, cloudKnown, staleAgainstCloud) {
60
+ if (source !== "local-override") return "not-applicable";
61
+ if (!cloudKnown) return "unverified";
62
+ return staleAgainstCloud ? "stale" : "in-sync";
63
+ }
59
64
  function normalizeMode(raw) {
60
65
  const v = String(raw ?? "").trim().toLowerCase();
61
66
  if (v === "prod" || v === "production") return { mode: "prod", reliance: "cloud" };
@@ -163,6 +168,7 @@ function resolveDevMode({
163
168
  const semantics = deriveSemantics(mode, reliance);
164
169
  const consoleUrl = source === "local-override" && local.record?.console_url ? local.record.console_url.replace(/\/+$/, "") : semantics.consoleUrl;
165
170
  const staleAgainstCloud = source === "local-override" && cloudValue !== null && (cloudValue.mode !== mode || mode === "dev" && cloudValue.reliance !== semantics.reliance);
171
+ const cloudCheck = overrideCloudCheck(source, cloudKnown, staleAgainstCloud);
166
172
  return {
167
173
  mode,
168
174
  reliance: semantics.reliance,
@@ -180,7 +186,8 @@ function resolveDevMode({
180
186
  present: local.record !== null,
181
187
  record: local.record,
182
188
  parseError: local.parseError,
183
- staleAgainstCloud
189
+ staleAgainstCloud,
190
+ cloudCheck
184
191
  },
185
192
  cloudSetting: { known: cloudKnown, value: cloudValue }
186
193
  };
@@ -275,7 +282,7 @@ async function discardResponseBody(res) {
275
282
  }
276
283
  }
277
284
  async function fetchCloudDevMode({
278
- consoleUrl,
285
+ consoleUrl = CLOUD_CONSOLE_URL,
279
286
  fetchImpl = fetch,
280
287
  homeDir = heyspexHome(),
281
288
  readFile = defaultReadFile,
@@ -493,7 +500,7 @@ function printStatus(resolved, cloudError) {
493
500
  if (resolved.localOverride.present) {
494
501
  const rec = resolved.localOverride.record;
495
502
  out.push(
496
- ` local override: active (written ${rec?.updated_at ?? "?"} by ${rec?.source ?? "?"})` + (resolved.localOverride.staleAgainstCloud ? " \u2014 DISAGREES with the cloud setting (stale override?)" : "")
503
+ ` local override: active (written ${rec?.updated_at ?? "?"} by ${rec?.source ?? "?"})` + (resolved.localOverride.cloudCheck === "stale" ? " \u2014 DISAGREES with the cloud setting (stale override?)" : resolved.localOverride.cloudCheck === "unverified" ? " \u2014 UNVERIFIED: the cloud setting could not be read, so staleness is unknown" : "")
497
504
  );
498
505
  } else if (resolved.localOverride.parseError) {
499
506
  out.push(` local override: UNREADABLE, ignored \u2014 ${resolved.localOverride.parseError}`);
@@ -523,8 +530,7 @@ async function main() {
523
530
  const positional = argv.filter((a) => !a.startsWith("--"));
524
531
  const token = positional[0]?.toLowerCase();
525
532
  if (token === void 0 || token === "status") {
526
- const pre = resolveDevMode();
527
- const cloud = await fetchCloudDevMode({ consoleUrl: pre.consoleUrl });
533
+ const cloud = await fetchCloudDevMode({ consoleUrl: CLOUD_CONSOLE_URL });
528
534
  const resolved = resolveDevMode({ cloudSetting: cloud.known ? cloud.value : void 0 });
529
535
  if (json) {
530
536
  process3.stdout.write(