@telora/daemon 0.22.4 → 0.22.42

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 (159) hide show
  1. package/build-info.json +5 -3
  2. package/dist/backends/index.d.ts.map +1 -1
  3. package/dist/backends/index.js +2 -0
  4. package/dist/backends/index.js.map +1 -1
  5. package/dist/ci/ci-sensor-loop.d.ts +36 -2
  6. package/dist/ci/ci-sensor-loop.d.ts.map +1 -1
  7. package/dist/ci/ci-sensor-loop.js +48 -9
  8. package/dist/ci/ci-sensor-loop.js.map +1 -1
  9. package/dist/ci/ci-status.d.ts.map +1 -1
  10. package/dist/ci/ci-status.js +1 -0
  11. package/dist/ci/ci-status.js.map +1 -1
  12. package/dist/completion/detector.d.ts +9 -0
  13. package/dist/completion/detector.d.ts.map +1 -1
  14. package/dist/completion/detector.js +18 -0
  15. package/dist/completion/detector.js.map +1 -1
  16. package/dist/completion/event-phases.d.ts +24 -8
  17. package/dist/completion/event-phases.d.ts.map +1 -1
  18. package/dist/completion/event-phases.js +81 -45
  19. package/dist/completion/event-phases.js.map +1 -1
  20. package/dist/completion/event.d.ts +9 -0
  21. package/dist/completion/event.d.ts.map +1 -1
  22. package/dist/completion/event.js +4 -0
  23. package/dist/completion/event.js.map +1 -1
  24. package/dist/completion/exit-classification.d.ts +2 -2
  25. package/dist/completion/exit-classification.d.ts.map +1 -1
  26. package/dist/completion/exit-classification.js +2 -0
  27. package/dist/completion/exit-classification.js.map +1 -1
  28. package/dist/completion/index.js +1 -1
  29. package/dist/completion/liveness-firing.d.ts +27 -0
  30. package/dist/completion/liveness-firing.d.ts.map +1 -0
  31. package/dist/completion/liveness-firing.js +79 -0
  32. package/dist/completion/liveness-firing.js.map +1 -0
  33. package/dist/completion/stdin-turn-tracker.d.ts +19 -0
  34. package/dist/completion/stdin-turn-tracker.d.ts.map +1 -0
  35. package/dist/completion/stdin-turn-tracker.js +57 -0
  36. package/dist/completion/stdin-turn-tracker.js.map +1 -0
  37. package/dist/completion/supervision-firing-record.d.ts +190 -0
  38. package/dist/completion/supervision-firing-record.d.ts.map +1 -0
  39. package/dist/completion/supervision-firing-record.js +232 -0
  40. package/dist/completion/supervision-firing-record.js.map +1 -0
  41. package/dist/completion/team-lifecycle.d.ts.map +1 -1
  42. package/dist/completion/team-lifecycle.js +3 -0
  43. package/dist/completion/team-lifecycle.js.map +1 -1
  44. package/dist/completion/team-phase.d.ts.map +1 -1
  45. package/dist/completion/team-phase.js +2 -1
  46. package/dist/completion/team-phase.js.map +1 -1
  47. package/dist/directive/directive-dispatch.d.ts +7 -1
  48. package/dist/directive/directive-dispatch.d.ts.map +1 -1
  49. package/dist/directive/directive-dispatch.js +75 -12
  50. package/dist/directive/directive-dispatch.js.map +1 -1
  51. package/dist/directive/directive-executor.d.ts +1 -1
  52. package/dist/directive/directive-executor.d.ts.map +1 -1
  53. package/dist/directive/directive-executor.js +10 -6
  54. package/dist/directive/directive-executor.js.map +1 -1
  55. package/dist/directive/directive-queue.d.ts +35 -9
  56. package/dist/directive/directive-queue.d.ts.map +1 -1
  57. package/dist/directive/directive-queue.js +15 -8
  58. package/dist/directive/directive-queue.js.map +1 -1
  59. package/dist/directive/directive-verify-hold-gate.d.ts +20 -0
  60. package/dist/directive/directive-verify-hold-gate.d.ts.map +1 -0
  61. package/dist/directive/directive-verify-hold-gate.js +47 -0
  62. package/dist/directive/directive-verify-hold-gate.js.map +1 -0
  63. package/dist/drift/staleness-sensor.d.ts +62 -67
  64. package/dist/drift/staleness-sensor.d.ts.map +1 -1
  65. package/dist/drift/staleness-sensor.js +233 -68
  66. package/dist/drift/staleness-sensor.js.map +1 -1
  67. package/dist/drift/staleness.d.ts +8 -0
  68. package/dist/drift/staleness.d.ts.map +1 -1
  69. package/dist/drift/staleness.js +7 -1
  70. package/dist/drift/staleness.js.map +1 -1
  71. package/dist/focus/focus-engine.js +1 -1
  72. package/dist/focus/focus-engine.js.map +1 -1
  73. package/dist/focus/focus-executor.d.ts.map +1 -1
  74. package/dist/focus/focus-executor.js +12 -6
  75. package/dist/focus/focus-executor.js.map +1 -1
  76. package/dist/focus/focus-team-state.d.ts.map +1 -1
  77. package/dist/focus/focus-team-state.js +1 -0
  78. package/dist/focus/focus-team-state.js.map +1 -1
  79. package/dist/focus/focus-worktree-state.d.ts.map +1 -1
  80. package/dist/focus/focus-worktree-state.js +4 -2
  81. package/dist/focus/focus-worktree-state.js.map +1 -1
  82. package/dist/focus/listener-spawn.d.ts +59 -6
  83. package/dist/focus/listener-spawn.d.ts.map +1 -1
  84. package/dist/focus/listener-spawn.js +164 -39
  85. package/dist/focus/listener-spawn.js.map +1 -1
  86. package/dist/focus/listener.d.ts.map +1 -1
  87. package/dist/focus/listener.js +20 -11
  88. package/dist/focus/listener.js.map +1 -1
  89. package/dist/focus/team-actionable-work.d.ts +90 -0
  90. package/dist/focus/team-actionable-work.d.ts.map +1 -0
  91. package/dist/focus/team-actionable-work.js +113 -0
  92. package/dist/focus/team-actionable-work.js.map +1 -0
  93. package/dist/merge/focus-merge.d.ts.map +1 -1
  94. package/dist/merge/focus-merge.js +2 -1
  95. package/dist/merge/focus-merge.js.map +1 -1
  96. package/dist/nexus/return.d.ts +60 -1
  97. package/dist/nexus/return.d.ts.map +1 -1
  98. package/dist/nexus/return.js +78 -2
  99. package/dist/nexus/return.js.map +1 -1
  100. package/dist/queries/schemas.d.ts +61 -0
  101. package/dist/queries/schemas.d.ts.map +1 -1
  102. package/dist/queries/schemas.js +12 -2
  103. package/dist/queries/schemas.js.map +1 -1
  104. package/dist/shell/heartbeat-metadata.d.ts +91 -0
  105. package/dist/shell/heartbeat-metadata.d.ts.map +1 -0
  106. package/dist/shell/heartbeat-metadata.js +169 -0
  107. package/dist/shell/heartbeat-metadata.js.map +1 -0
  108. package/dist/shell/heartbeat.d.ts +7 -22
  109. package/dist/shell/heartbeat.d.ts.map +1 -1
  110. package/dist/shell/heartbeat.js +120 -89
  111. package/dist/shell/heartbeat.js.map +1 -1
  112. package/dist/shell/model-resolution.d.ts +54 -0
  113. package/dist/shell/model-resolution.d.ts.map +1 -1
  114. package/dist/shell/model-resolution.js +50 -0
  115. package/dist/shell/model-resolution.js.map +1 -1
  116. package/dist/shell/unified-shell.d.ts.map +1 -1
  117. package/dist/shell/unified-shell.js +21 -12
  118. package/dist/shell/unified-shell.js.map +1 -1
  119. package/dist/spawn/helpers.d.ts.map +1 -1
  120. package/dist/spawn/helpers.js +6 -1
  121. package/dist/spawn/helpers.js.map +1 -1
  122. package/dist/spawn/model-routing.d.ts +14 -19
  123. package/dist/spawn/model-routing.d.ts.map +1 -1
  124. package/dist/spawn/model-routing.js +57 -39
  125. package/dist/spawn/model-routing.js.map +1 -1
  126. package/dist/spawn/process-spawn.d.ts +32 -1
  127. package/dist/spawn/process-spawn.d.ts.map +1 -1
  128. package/dist/spawn/process-spawn.js +43 -5
  129. package/dist/spawn/process-spawn.js.map +1 -1
  130. package/dist/spawn/spawn-cooldown.d.ts.map +1 -1
  131. package/dist/spawn/spawn-cooldown.js +2 -1
  132. package/dist/spawn/spawn-cooldown.js.map +1 -1
  133. package/dist/spawn/worktree-session.d.ts +53 -5
  134. package/dist/spawn/worktree-session.d.ts.map +1 -1
  135. package/dist/spawn/worktree-session.js +61 -29
  136. package/dist/spawn/worktree-session.js.map +1 -1
  137. package/dist/testing/fixtures/index.js +1 -1
  138. package/dist/types/focus.d.ts +12 -2
  139. package/dist/types/focus.d.ts.map +1 -1
  140. package/dist/types/index.js +1 -1
  141. package/dist/types/session.d.ts +1 -1
  142. package/dist/types/session.d.ts.map +1 -1
  143. package/dist/update/auto-update-idle.d.ts +22 -0
  144. package/dist/update/auto-update-idle.d.ts.map +1 -1
  145. package/dist/update/auto-update-idle.js +8 -1
  146. package/dist/update/auto-update-idle.js.map +1 -1
  147. package/dist/update/auto-update.d.ts +0 -6
  148. package/dist/update/auto-update.d.ts.map +1 -1
  149. package/dist/update/auto-update.js +20 -6
  150. package/dist/update/auto-update.js.map +1 -1
  151. package/dist/update/version-check.d.ts +73 -0
  152. package/dist/update/version-check.d.ts.map +1 -1
  153. package/dist/update/version-check.js +107 -11
  154. package/dist/update/version-check.js.map +1 -1
  155. package/dist/worktree/verify-interlock.d.ts +34 -0
  156. package/dist/worktree/verify-interlock.d.ts.map +1 -1
  157. package/dist/worktree/verify-interlock.js +27 -1
  158. package/dist/worktree/verify-interlock.js.map +1 -1
  159. package/package.json +3 -3
@@ -1,7 +1,67 @@
1
1
  export interface VersionCheckResult {
2
2
  latestVersion: string;
3
3
  updateAvailable: boolean;
4
+ /**
5
+ * The registry URL this check actually consulted, resolved via
6
+ * {@link resolveRegistryUrl}. Carried on the result so a caller can name the
7
+ * registry alongside the version it read -- a host's reading then always
8
+ * identifies the registry it consulted, not just the answer. Optional so
9
+ * injected test fakes need not supply it; the real {@link checkForUpdates}
10
+ * always populates it.
11
+ */
12
+ registryUrl?: string;
4
13
  }
14
+ /**
15
+ * Read a single npm config value via `npm config get <key>`.
16
+ *
17
+ * Returns a trimmed http(s) URL, or null when npm is unavailable, the key is
18
+ * unset (npm prints an empty line or the literal "undefined"/"null"), or the
19
+ * value is not an http(s) URL. Fails soft so a host without `npm` on PATH still
20
+ * resolves through the fallback chain rather than throwing.
21
+ */
22
+ export declare function readNpmConfigValue(key: string): string | null;
23
+ /** Injected dependencies for {@link resolveRegistryUrl} (pure + unit-testable). */
24
+ export interface RegistryResolutionDeps {
25
+ env: NodeJS.ProcessEnv;
26
+ npmConfigGet: (key: string) => string | null;
27
+ }
28
+ /**
29
+ * Resolve the registry URL the update check should target, so the CHECK asks npm
30
+ * the same question the INSTALL resolves. `self-update.ts` runs
31
+ * `npm install -g @telora/daemon@latest`, which resolves the @telora scope from
32
+ * npm config (~/.npmrc -> Gitea on the daemon hosts); a check that targeted a
33
+ * different registry would be blind to a Gitea-only publish -- the exact failure
34
+ * this focus exists to close.
35
+ *
36
+ * Resolution order:
37
+ * 1. TELORA_REGISTRY_URL when EXPLICITLY set in the environment -> override.
38
+ * Read straight from `env` (NOT through loadEnvConfig, whose typed default
39
+ * would make an unset var indistinguishable from an explicit npmjs choice).
40
+ * 2. `npm config get @telora:registry` -> the scope registry the installer uses.
41
+ * 3. `npm config get registry` -> npm's configured default registry.
42
+ * 4. the public npmjs registry -> last-resort fallback (npm absent / unset).
43
+ *
44
+ * Pure over injected deps; {@link getRegistryUrl} binds the real env + npm reader.
45
+ */
46
+ export declare function resolveRegistryUrl(deps: RegistryResolutionDeps): string;
47
+ /**
48
+ * The registry `npm install -g @telora/daemon@latest` ACTUALLY resolves: npm
49
+ * config (@telora scope, then default), ignoring the TELORA_REGISTRY_URL CHECK
50
+ * override -- the installer reads ~/.npmrc, never that env var. This is the
51
+ * registry a version reading must be ATTRIBUTABLE to for its agreement to count:
52
+ * an operator who points the check elsewhere (override) has not changed where
53
+ * an install lands, so a reading from the override registry cannot certify the
54
+ * installed version is current.
55
+ */
56
+ export declare function resolveInstallRegistryUrl(npmConfigGet?: (key: string) => string | null): string;
57
+ /**
58
+ * True when a reading taken from `readingRegistry` can be ATTRIBUTED to the
59
+ * registry npm resolves for an install (`installRegistry`) -- only then does the
60
+ * agreement/lag it reports count. A null/absent reading registry (legacy cache,
61
+ * unstamped) is unattributable, and so is a reading from a different registry
62
+ * than the installer resolves. Trailing-slash / case insensitive.
63
+ */
64
+ export declare function isReadingAttributable(readingRegistry: string | null | undefined, installRegistry: string): boolean;
5
65
  /**
6
66
  * Parse a semver string's numeric major.minor.patch core, ignoring any
7
67
  * pre-release / build suffix (e.g. "1.2.3-beta.1" -> [1, 2, 3]).
@@ -14,6 +74,19 @@ export declare function parseVersionCore(version: string): [number, number, numb
14
74
  * either version cannot be parsed, so a malformed tag never silently no-ops.
15
75
  */
16
76
  export declare function isNewerVersion(candidate: string, current: string): boolean;
77
+ /** Component-wise magnitude of how far one version is behind another (clamped at 0). */
78
+ export interface VersionDistance {
79
+ major: number;
80
+ minor: number;
81
+ patch: number;
82
+ }
83
+ /**
84
+ * Component-wise (newest - running) semver distance, clamped at 0 per component.
85
+ * Returns a zero distance when either version's core cannot be parsed. Pure --
86
+ * the single home for the running-vs-latest lag math shared by the heartbeat
87
+ * (lag field) and the propagation-staleness sensor (threshold decision).
88
+ */
89
+ export declare function versionDistance(running: string, newest: string): VersionDistance;
17
90
  /**
18
91
  * Check the npm registry for the latest published version of @telora/daemon.
19
92
  *
@@ -1 +1 @@
1
- {"version":3,"file":"version-check.d.ts","sourceRoot":"","sources":["../../src/update/version-check.ts"],"names":[],"mappings":"AAsBA,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,OAAO,CAAC;CAC1B;AAkBD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAWjF;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAS1E;AAED;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CAAC,cAAc,EAAE,MAAM,EAAE,WAAW,SAAmB,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAoDhI"}
1
+ {"version":3,"file":"version-check.d.ts","sourceRoot":"","sources":["../../src/update/version-check.ts"],"names":[],"mappings":"AAsBA,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,OAAO,CAAC;IACzB;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAMD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAa7D;AAED,mFAAmF;AACnF,MAAM,WAAW,sBAAsB;IACrC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,YAAY,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;CAC9C;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,sBAAsB,GAAG,MAAM,CAUvE;AAED;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CACvC,YAAY,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,IAAyB,GAChE,MAAM,CAER;AAMD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO,CAGlH;AASD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAWjF;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAS1E;AAED,wFAAwF;AACxF,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,eAAe,CAShF;AAED;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CAAC,cAAc,EAAE,MAAM,EAAE,WAAW,SAAmB,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CA6DhI"}
@@ -10,24 +10,97 @@
10
10
  * a registry outage never prevents startup or normal operation -- but logs a
11
11
  * warn line so a broken update path produces a signal instead of silent rot.
12
12
  */
13
- import { loadEnvConfig } from '@telora/daemon-core';
13
+ import { execFileSync } from 'node:child_process';
14
14
  import { createLogger } from '../shell/log.js';
15
15
  const log = createLogger({ module: 'auto-update' });
16
16
  const CHECK_TIMEOUT_MS = 5000;
17
+ const SCOPE_REGISTRY_KEY = '@telora:registry';
18
+ const DEFAULT_REGISTRY_KEY = 'registry';
19
+ const NPMJS_FALLBACK = 'https://registry.npmjs.org/';
17
20
  /**
18
- * Resolve the registry URL the update check should target.
21
+ * Read a single npm config value via `npm config get <key>`.
19
22
  *
20
- * Defaults to the public npmjs registry the package is installed from. Does NOT
21
- * derive from package.json publishConfig.registry -- that field points at the
22
- * internal Gitea LAN host for PUBLISHING and is unreachable from installed
23
- * daemons in the field. TELORA_REGISTRY_URL stays as the explicit LAN/dev
24
- * override (declared + defaulted in the typed env-config).
23
+ * Returns a trimmed http(s) URL, or null when npm is unavailable, the key is
24
+ * unset (npm prints an empty line or the literal "undefined"/"null"), or the
25
+ * value is not an http(s) URL. Fails soft so a host without `npm` on PATH still
26
+ * resolves through the fallback chain rather than throwing.
25
27
  */
28
+ export function readNpmConfigValue(key) {
29
+ try {
30
+ const out = execFileSync('npm', ['config', 'get', key], {
31
+ encoding: 'utf-8',
32
+ timeout: 5000,
33
+ stdio: ['ignore', 'pipe', 'ignore'],
34
+ }).trim();
35
+ if (!out || out === 'undefined' || out === 'null')
36
+ return null;
37
+ if (!/^https?:\/\//i.test(out))
38
+ return null;
39
+ return out;
40
+ }
41
+ catch {
42
+ return null;
43
+ }
44
+ }
45
+ /**
46
+ * Resolve the registry URL the update check should target, so the CHECK asks npm
47
+ * the same question the INSTALL resolves. `self-update.ts` runs
48
+ * `npm install -g @telora/daemon@latest`, which resolves the @telora scope from
49
+ * npm config (~/.npmrc -> Gitea on the daemon hosts); a check that targeted a
50
+ * different registry would be blind to a Gitea-only publish -- the exact failure
51
+ * this focus exists to close.
52
+ *
53
+ * Resolution order:
54
+ * 1. TELORA_REGISTRY_URL when EXPLICITLY set in the environment -> override.
55
+ * Read straight from `env` (NOT through loadEnvConfig, whose typed default
56
+ * would make an unset var indistinguishable from an explicit npmjs choice).
57
+ * 2. `npm config get @telora:registry` -> the scope registry the installer uses.
58
+ * 3. `npm config get registry` -> npm's configured default registry.
59
+ * 4. the public npmjs registry -> last-resort fallback (npm absent / unset).
60
+ *
61
+ * Pure over injected deps; {@link getRegistryUrl} binds the real env + npm reader.
62
+ */
63
+ export function resolveRegistryUrl(deps) {
64
+ const override = deps.env.TELORA_REGISTRY_URL;
65
+ if (typeof override === 'string' && override.trim().length > 0) {
66
+ return override.trim();
67
+ }
68
+ return (deps.npmConfigGet(SCOPE_REGISTRY_KEY) ??
69
+ deps.npmConfigGet(DEFAULT_REGISTRY_KEY) ??
70
+ NPMJS_FALLBACK);
71
+ }
72
+ /**
73
+ * The registry `npm install -g @telora/daemon@latest` ACTUALLY resolves: npm
74
+ * config (@telora scope, then default), ignoring the TELORA_REGISTRY_URL CHECK
75
+ * override -- the installer reads ~/.npmrc, never that env var. This is the
76
+ * registry a version reading must be ATTRIBUTABLE to for its agreement to count:
77
+ * an operator who points the check elsewhere (override) has not changed where
78
+ * an install lands, so a reading from the override registry cannot certify the
79
+ * installed version is current.
80
+ */
81
+ export function resolveInstallRegistryUrl(npmConfigGet = readNpmConfigValue) {
82
+ return resolveRegistryUrl({ env: {}, npmConfigGet });
83
+ }
84
+ function normalizeRegistry(url) {
85
+ return url.trim().replace(/\/+$/, '').toLowerCase();
86
+ }
87
+ /**
88
+ * True when a reading taken from `readingRegistry` can be ATTRIBUTED to the
89
+ * registry npm resolves for an install (`installRegistry`) -- only then does the
90
+ * agreement/lag it reports count. A null/absent reading registry (legacy cache,
91
+ * unstamped) is unattributable, and so is a reading from a different registry
92
+ * than the installer resolves. Trailing-slash / case insensitive.
93
+ */
94
+ export function isReadingAttributable(readingRegistry, installRegistry) {
95
+ if (!readingRegistry)
96
+ return false;
97
+ return normalizeRegistry(readingRegistry) === normalizeRegistry(installRegistry);
98
+ }
26
99
  function getRegistryUrl() {
27
- // Pass process.env explicitly so the value reflects the LIVE environment on
28
- // every call (the update check can run long after startup, and tests mutate
29
- // the env between calls) rather than the memoized startup snapshot.
30
- return loadEnvConfig(process.env).TELORA_REGISTRY_URL;
100
+ // Read the LIVE environment + npm config on every call (the update check can
101
+ // run long after startup, and tests mutate the env between calls) rather than
102
+ // a memoized startup snapshot.
103
+ return resolveRegistryUrl({ env: process.env, npmConfigGet: readNpmConfigValue });
31
104
  }
32
105
  /**
33
106
  * Parse a semver string's numeric major.minor.patch core, ignoring any
@@ -66,6 +139,23 @@ export function isNewerVersion(candidate, current) {
66
139
  }
67
140
  return false;
68
141
  }
142
+ /**
143
+ * Component-wise (newest - running) semver distance, clamped at 0 per component.
144
+ * Returns a zero distance when either version's core cannot be parsed. Pure --
145
+ * the single home for the running-vs-latest lag math shared by the heartbeat
146
+ * (lag field) and the propagation-staleness sensor (threshold decision).
147
+ */
148
+ export function versionDistance(running, newest) {
149
+ const r = parseVersionCore(running);
150
+ const n = parseVersionCore(newest);
151
+ if (!r || !n)
152
+ return { major: 0, minor: 0, patch: 0 };
153
+ return {
154
+ major: Math.max(0, n[0] - r[0]),
155
+ minor: Math.max(0, n[1] - r[1]),
156
+ patch: Math.max(0, n[2] - r[2]),
157
+ };
158
+ }
69
159
  /**
70
160
  * Check the npm registry for the latest published version of @telora/daemon.
71
161
  *
@@ -99,9 +189,15 @@ export async function checkForUpdates(currentVersion, packageName = '@telora/dae
99
189
  log.warn(`[auto-update] Version check inconclusive: no dist-tags.latest for ${packageName} at registry ${registryUrl}`);
100
190
  return null;
101
191
  }
192
+ // Name the registry this check consulted alongside its result, so a host's
193
+ // reading always identifies WHICH registry answered -- the mars incident
194
+ // (hourly "up to date (v0.22.4)" while Gitea served 0.22.13) would have been
195
+ // visible the moment the check named its npmjs.org registry.
196
+ log.info(`[auto-update] Version check: ${packageName} latest v${latestVersion} via registry ${registryUrl} (running v${currentVersion})`);
102
197
  return {
103
198
  latestVersion,
104
199
  updateAvailable: isNewerVersion(latestVersion, currentVersion),
200
+ registryUrl,
105
201
  };
106
202
  }
107
203
  finally {
@@ -1 +1 @@
1
- {"version":3,"file":"version-check.js","sourceRoot":"","sources":["../../src/update/version-check.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"version-check.js","sourceRoot":"","sources":["../../src/update/version-check.ts"],"names":[],"mappings":"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"}
@@ -18,4 +18,38 @@ export declare function acquireVerifyHold(worktreePath: string): () => void;
18
18
  export declare function isWorktreeUnderVerify(worktreePath: string): boolean;
19
19
  /** Test seam: clear all holds between cases. */
20
20
  export declare function __resetVerifyHolds(): void;
21
+ /** Injectable probe seam for {@link runWorktreeMutationUnderInterlock}. */
22
+ export interface WorktreeMutationInterlockDeps {
23
+ /** Verify-hold probe; defaults to the real {@link isWorktreeUnderVerify}. */
24
+ isWorktreeUnderVerify?: (worktreePath: string) => boolean;
25
+ }
26
+ /**
27
+ * Result of a guarded worktree mutation: either the mutation was deferred
28
+ * (a verify was running in the worktree) or it ran and produced `result`.
29
+ */
30
+ export type WorktreeMutationResult<T> = {
31
+ deferred: true;
32
+ } | {
33
+ deferred: false;
34
+ result: T;
35
+ };
36
+ /**
37
+ * The ONE boundary every daemon path that REWRITES an existing worktree passes
38
+ * through -- the write-side peer of `guardedCommit`'s interlock check.
39
+ *
40
+ * While a verify command is running in `worktreePath`, a rewrite (a rebase, a
41
+ * git-hook reinstall) would mutate a tree the verify is mid-way through and
42
+ * commit paths are already refusing to touch -- the same mid-verify window that
43
+ * tears a write. So this defers: it runs `mutate` ONLY when the worktree is not
44
+ * held, and otherwise returns `{ deferred: true }` having run nothing. A deferral
45
+ * is a benign wait, not a failure -- the caller retries on a later poll.
46
+ *
47
+ * Routing every worktree-rewrite through this single function (rather than an
48
+ * inline `isWorktreeUnderVerify` check re-implemented per call site) means a
49
+ * worktree-write path added later cannot silently bypass the interlock: it either
50
+ * calls this boundary or it does not rewrite the worktree at all. The probe is
51
+ * injectable so the boundary is unit-testable without a real worktree or a live
52
+ * verify.
53
+ */
54
+ export declare function runWorktreeMutationUnderInterlock<T>(worktreePath: string, mutate: () => T, deps?: WorktreeMutationInterlockDeps): WorktreeMutationResult<T>;
21
55
  //# sourceMappingURL=verify-interlock.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"verify-interlock.d.ts","sourceRoot":"","sources":["../../src/worktree/verify-interlock.ts"],"names":[],"mappings":"AA2DA;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,IAAI,CAgBlE;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAEnE;AAED,gDAAgD;AAChD,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC"}
1
+ {"version":3,"file":"verify-interlock.d.ts","sourceRoot":"","sources":["../../src/worktree/verify-interlock.ts"],"names":[],"mappings":"AA4DA;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,IAAI,CAgBlE;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAEnE;AAED,gDAAgD;AAChD,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AAED,2EAA2E;AAC3E,MAAM,WAAW,6BAA6B;IAC5C,6EAA6E;IAC7E,qBAAqB,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC;CAC3D;AAED;;;GAGG;AACH,MAAM,MAAM,sBAAsB,CAAC,CAAC,IAChC;IAAE,QAAQ,EAAE,IAAI,CAAA;CAAE,GAClB;IAAE,QAAQ,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,CAAC,CAAA;CAAE,CAAC;AAEnC;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iCAAiC,CAAC,CAAC,EACjD,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,CAAC,EACf,IAAI,GAAE,6BAAkC,GACvC,sBAAsB,CAAC,CAAC,CAAC,CAM3B"}
@@ -1,5 +1,6 @@
1
1
  // PINNED-BY-BEGIN (generated by gen:pinned-by -- do not hand-edit; checked by lint:pinned-by)
2
- // Pinned by: none -- no test imports this module directly (baselined; see lint:pinned-by)
2
+ // Pinned by: packages/daemon/src/directive/directive-verify-hold-gate.test.ts,
3
+ // packages/daemon/src/focus/pending-spawn-verify-hold.test.ts
3
4
  // PINNED-BY-END
4
5
  /**
5
6
  * Per-worktree verify interlock.
@@ -94,4 +95,29 @@ export function isWorktreeUnderVerify(worktreePath) {
94
95
  export function __resetVerifyHolds() {
95
96
  holds.clear();
96
97
  }
98
+ /**
99
+ * The ONE boundary every daemon path that REWRITES an existing worktree passes
100
+ * through -- the write-side peer of `guardedCommit`'s interlock check.
101
+ *
102
+ * While a verify command is running in `worktreePath`, a rewrite (a rebase, a
103
+ * git-hook reinstall) would mutate a tree the verify is mid-way through and
104
+ * commit paths are already refusing to touch -- the same mid-verify window that
105
+ * tears a write. So this defers: it runs `mutate` ONLY when the worktree is not
106
+ * held, and otherwise returns `{ deferred: true }` having run nothing. A deferral
107
+ * is a benign wait, not a failure -- the caller retries on a later poll.
108
+ *
109
+ * Routing every worktree-rewrite through this single function (rather than an
110
+ * inline `isWorktreeUnderVerify` check re-implemented per call site) means a
111
+ * worktree-write path added later cannot silently bypass the interlock: it either
112
+ * calls this boundary or it does not rewrite the worktree at all. The probe is
113
+ * injectable so the boundary is unit-testable without a real worktree or a live
114
+ * verify.
115
+ */
116
+ export function runWorktreeMutationUnderInterlock(worktreePath, mutate, deps = {}) {
117
+ const underVerify = deps.isWorktreeUnderVerify ?? isWorktreeUnderVerify;
118
+ if (underVerify(worktreePath)) {
119
+ return { deferred: true };
120
+ }
121
+ return { deferred: false, result: mutate() };
122
+ }
97
123
  //# sourceMappingURL=verify-interlock.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"verify-interlock.js","sourceRoot":"","sources":["../../src/worktree/verify-interlock.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,0FAA0F;AAC1F,gBAAgB;AAEhB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,MAAM,GAAG,GAAG,YAAY,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;AAEjD;;;;;GAKG;AACH,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;AAExC,gFAAgF;AAChF,SAAS,MAAM,CAAC,YAAoB;IAClC,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,YAAY,CAAC,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC,YAAY,CAAC,CAAC;IAC/B,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAAC,YAAoB;IACpD,MAAM,GAAG,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;IACjC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1C,GAAG,CAAC,KAAK,CAAC,uCAAuC,GAAG,WAAW,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAClF,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,OAAO,GAAG,EAAE;QACV,IAAI,QAAQ;YAAE,OAAO;QACrB,QAAQ,GAAG,IAAI,CAAC;QAChB,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QACvC,IAAI,IAAI,IAAI,CAAC,EAAE,CAAC;YACd,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACvB,CAAC;QACD,GAAG,CAAC,KAAK,CAAC,uCAAuC,GAAG,WAAW,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;IAC1F,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,YAAoB;IACxD,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;AACpD,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,kBAAkB;IAChC,KAAK,CAAC,KAAK,EAAE,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"verify-interlock.js","sourceRoot":"","sources":["../../src/worktree/verify-interlock.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,+EAA+E;AAC/E,gEAAgE;AAChE,gBAAgB;AAEhB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,MAAM,GAAG,GAAG,YAAY,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;AAEjD;;;;;GAKG;AACH,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;AAExC,gFAAgF;AAChF,SAAS,MAAM,CAAC,YAAoB;IAClC,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,YAAY,CAAC,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC,YAAY,CAAC,CAAC;IAC/B,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAAC,YAAoB;IACpD,MAAM,GAAG,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;IACjC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1C,GAAG,CAAC,KAAK,CAAC,uCAAuC,GAAG,WAAW,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAClF,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,OAAO,GAAG,EAAE;QACV,IAAI,QAAQ;YAAE,OAAO;QACrB,QAAQ,GAAG,IAAI,CAAC;QAChB,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QACvC,IAAI,IAAI,IAAI,CAAC,EAAE,CAAC;YACd,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACvB,CAAC;QACD,GAAG,CAAC,KAAK,CAAC,uCAAuC,GAAG,WAAW,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;IAC1F,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,YAAoB;IACxD,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;AACpD,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,kBAAkB;IAChC,KAAK,CAAC,KAAK,EAAE,CAAC;AAChB,CAAC;AAgBD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,iCAAiC,CAC/C,YAAoB,EACpB,MAAe,EACf,OAAsC,EAAE;IAExC,MAAM,WAAW,GAAG,IAAI,CAAC,qBAAqB,IAAI,qBAAqB,CAAC;IACxE,IAAI,WAAW,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9B,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC5B,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;AAC/C,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@telora/daemon",
3
- "version": "0.22.4",
3
+ "version": "0.22.42",
4
4
  "description": "Agent orchestration daemon for Telora - spawns and manages Claude Code instances",
5
5
  "type": "module",
6
6
  "bin": {
@@ -37,8 +37,8 @@
37
37
  },
38
38
  "//testRunner": "Uses Node.js built-in test runner (node:test) via tsx for TypeScript support. The root package uses Vitest; this is a deliberate choice for the daemon package to avoid framework dependencies. Test files live beside the modules they exercise (owner-directory layout); the runner discovers them recursively.",
39
39
  "dependencies": {
40
- "@telora/daemon-core": "^0.2.87",
41
- "@telora/mcp-products": "^0.22.133",
40
+ "@telora/daemon-core": "^0.2.89",
41
+ "@telora/mcp-products": "^0.22.135",
42
42
  "commander": "^14.0.3",
43
43
  "yaml": "^2.4.0",
44
44
  "zod": "^4.3.6"