@macintacos/caret 1.1.0 → 1.2.0

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 (100) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +11 -4
  3. package/bin/caret-launcher +78 -25
  4. package/commands/doctor.md +2 -1
  5. package/dist/cli.js +2253 -904
  6. package/opencode/caret.core.ts +458 -0
  7. package/opencode/caret.plugin.ts +83 -456
  8. package/opencode/caret.plugin.v2.ts +243 -0
  9. package/opencode/caret.tui.ts +75 -0
  10. package/opencode/commands/doctor.md +2 -1
  11. package/opencode/index.ts +6 -5
  12. package/opencode/permission.ts +102 -0
  13. package/package.json +2 -1
  14. package/ui/dist/assets/{angular-html-BECXXPyr.js → angular-html-BVXNFElL.js} +1 -1
  15. package/ui/dist/assets/{angular-ts-CJKAKY9F.js → angular-ts-BBdNNVOV.js} +1 -1
  16. package/ui/dist/assets/{apl-CCcfDDqZ.js → apl-DN-9LSnm.js} +1 -1
  17. package/ui/dist/assets/{astro-DKCnAnVR.js → astro-DuMkehjz.js} +1 -1
  18. package/ui/dist/assets/{blade-DQ_JdT2N.js → blade-B_5LVqnt.js} +1 -1
  19. package/ui/dist/assets/{c-D3TwszVj.js → c-5LpWn0DJ.js} +1 -1
  20. package/ui/dist/assets/{chapel-C-2sPcCX.js → chapel-qw3-lXMw.js} +1 -1
  21. package/ui/dist/assets/{cobol-BPmo_4f_.js → cobol-BAnr3Azd.js} +1 -1
  22. package/ui/dist/assets/{coffee-DMTsNDVt.js → coffee-CGRFpAgb.js} +1 -1
  23. package/ui/dist/assets/{cpp-BJr6_Y8R.js → cpp-olfuBwwP.js} +1 -1
  24. package/ui/dist/assets/{crystal-pIWESUkD.js → crystal-qe9b46tp.js} +1 -1
  25. package/ui/dist/assets/{css-DRd9Q4Li.js → css-DkXCh44l.js} +1 -1
  26. package/ui/dist/assets/{dist-aKlRxpD_.js → dist-B1RcczPQ.js} +1 -1
  27. package/ui/dist/assets/{dist-BGfsV7n2.js → dist-BnIbJslb.js} +1 -1
  28. package/ui/dist/assets/{dist-BJ7SLVNC.js → dist-BnbtGh0F.js} +1 -1
  29. package/ui/dist/assets/{dist-BFQBMwmz.js → dist-CFbPxPI-.js} +1 -1
  30. package/ui/dist/assets/{dist-DoJTqy3z.js → dist-CHZr2-kE.js} +1 -1
  31. package/ui/dist/assets/{dist-BNr0c85A.js → dist-CMOjVm1q.js} +1 -1
  32. package/ui/dist/assets/{dist-C6t67BjE.js → dist-CfHYS987.js} +1 -1
  33. package/ui/dist/assets/{dist-CU5aMlNo.js → dist-D8lZm-8I.js} +1 -1
  34. package/ui/dist/assets/{dist-CD25BkNS.js → dist-KWgwFCxG.js} +1 -1
  35. package/ui/dist/assets/{dist-RKKeH1zs.js → dist-iPRbc51X.js} +1 -1
  36. package/ui/dist/assets/{edge-DeNk4F2G.js → edge-hytDa3H3.js} +1 -1
  37. package/ui/dist/assets/{elixir-DHc-DOO8.js → elixir-DnjerbFh.js} +1 -1
  38. package/ui/dist/assets/{elm-CJRqEcvz.js → elm-Cy60APyX.js} +1 -1
  39. package/ui/dist/assets/{erb-BEWGTHDA.js → erb-Rclm0zaT.js} +1 -1
  40. package/ui/dist/assets/{git-rebase-DzlcWhg9.js → git-rebase-Be7W4GuM.js} +1 -1
  41. package/ui/dist/assets/{glimmer-js-B-aWCRIZ.js → glimmer-js-DAN9CyDo.js} +1 -1
  42. package/ui/dist/assets/{glimmer-ts-DcjmPyQn.js → glimmer-ts-Bd4Ltw2M.js} +1 -1
  43. package/ui/dist/assets/{glsl-C9FOT-Uv.js → glsl-DIrrPSk8.js} +1 -1
  44. package/ui/dist/assets/{graphql-BgKSoRp0.js → graphql-CBXqF557.js} +1 -1
  45. package/ui/dist/assets/{hack-BOedpUUE.js → hack-D_K_3nhB.js} +1 -1
  46. package/ui/dist/assets/{haml-Cpngw1vd.js → haml-g7mpgDGW.js} +1 -1
  47. package/ui/dist/assets/{handlebars-CpW1IyBg.js → handlebars-DRWwCyqd.js} +1 -1
  48. package/ui/dist/assets/{html-CV142D8s.js → html-Byvm88Y2.js} +1 -1
  49. package/ui/dist/assets/{html-derivative-Df7h1Nuw.js → html-derivative-DpLoxBsM.js} +1 -1
  50. package/ui/dist/assets/{http-Cneddv9N.js → http-DGq_mf9b.js} +1 -1
  51. package/ui/dist/assets/{hurl-D6TS55N6.js → hurl-qkfW8ihO.js} +1 -1
  52. package/ui/dist/assets/{index-Ci9yCNtV.js → index-BwtwrzNC.js} +4 -4
  53. package/ui/dist/assets/{java-BicD3zQH.js → java-BHSPy0gM.js} +1 -1
  54. package/ui/dist/assets/{javascript-l6vKHWBV.js → javascript-BGu3ZEma.js} +1 -1
  55. package/ui/dist/assets/{jinja-BJF2iot2.js → jinja-BkUiOuUL.js} +1 -1
  56. package/ui/dist/assets/{jison-DiXPFJAT.js → jison-DQ_FQMYl.js} +1 -1
  57. package/ui/dist/assets/{json-BDRuI4UV.js → json-BHyU93c5.js} +1 -1
  58. package/ui/dist/assets/{jsx-BvfdkIOy.js → jsx-DhxI-Xjj.js} +1 -1
  59. package/ui/dist/assets/{julia-bXAhreI5.js → julia-BpY5TdkA.js} +1 -1
  60. package/ui/dist/assets/{just-BOxCfXDg.js → just-Dy9X30SL.js} +1 -1
  61. package/ui/dist/assets/{latex-B9OiTBLF.js → latex-DnqjVTTq.js} +1 -1
  62. package/ui/dist/assets/{liquid-DuLKDeWE.js → liquid-DSLF1wIz.js} +1 -1
  63. package/ui/dist/assets/{lua-Dbh9FQm_.js → lua-CWQ1tn9q.js} +1 -1
  64. package/ui/dist/assets/{marko--tjEBgDM.js → marko-CVOaD8Lr.js} +1 -1
  65. package/ui/dist/assets/{mdc-ByNJpl3m.js → mdc-CorrsEtK.js} +1 -1
  66. package/ui/dist/assets/{nginx-D4wsmFK9.js → nginx--n2A1zuK.js} +1 -1
  67. package/ui/dist/assets/{nim-Cy8RxisP.js → nim-eb5p3yB7.js} +1 -1
  68. package/ui/dist/assets/{org-CAm7o61d.js → org-Cnlel0O3.js} +1 -1
  69. package/ui/dist/assets/{perl-BAvaFGKe.js → perl-DDWGMuBV.js} +1 -1
  70. package/ui/dist/assets/{php-DpAf3w7u.js → php-Bz2SRtKk.js} +1 -1
  71. package/ui/dist/assets/{pug-Dm7otyJU.js → pug-cGPMemK2.js} +1 -1
  72. package/ui/dist/assets/{qml-D4rWQQKC.js → qml-B4Hbmvdi.js} +1 -1
  73. package/ui/dist/assets/{r-DMKUX8qf.js → r-BuuNGonz.js} +1 -1
  74. package/ui/dist/assets/{razor-BIUJkuf_.js → razor-CHpWr94T.js} +1 -1
  75. package/ui/dist/assets/{regexp-D8W_pVHj.js → regexp-9s1znDWq.js} +1 -1
  76. package/ui/dist/assets/{rst-aFr0DP5H.js → rst-BBsXWDuP.js} +1 -1
  77. package/ui/dist/assets/{ruby-BzH6kUKr.js → ruby-pQqViN30.js} +1 -1
  78. package/ui/dist/assets/{sas-CDk9DyCV.js → sas-C4SSIJLx.js} +1 -1
  79. package/ui/dist/assets/{scss-DABbvU5W.js → scss-D8e130Cq.js} +1 -1
  80. package/ui/dist/assets/{shellscript-B0ObP3K-.js → shellscript-CHUzbqv1.js} +1 -1
  81. package/ui/dist/assets/{shellsession-2sv3Jq0j.js → shellsession-BulTL_bH.js} +1 -1
  82. package/ui/dist/assets/{soy-irSRV4oq.js → soy-zGj4V7Ec.js} +1 -1
  83. package/ui/dist/assets/{sql-DJCHoKvP.js → sql-CnJYFgwb.js} +1 -1
  84. package/ui/dist/assets/{stata-a8YnzbIc.js → stata-BXDojqs4.js} +1 -1
  85. package/ui/dist/assets/{surrealql-DdXPOg8s.js → surrealql-3hRFCpnH.js} +1 -1
  86. package/ui/dist/assets/{svelte-ClAKUEZR.js → svelte-C8TzlKVd.js} +1 -1
  87. package/ui/dist/assets/{templ-NUCvvUBA.js → templ-D5KJNb8h.js} +1 -1
  88. package/ui/dist/assets/{tex-DwZeSAfC.js → tex-szX76TU8.js} +1 -1
  89. package/ui/dist/assets/{ts-tags-CFJEHYY_.js → ts-tags-H1v1spsZ.js} +1 -1
  90. package/ui/dist/assets/{tsx-B934yX2T.js → tsx-CoyAoKjY.js} +1 -1
  91. package/ui/dist/assets/{twig-NFkkOj3w.js → twig-pqXRFgM9.js} +1 -1
  92. package/ui/dist/assets/{typescript-7bmMC_xU.js → typescript-CNl_4SRH.js} +1 -1
  93. package/ui/dist/assets/{typst-BQEjp9tn.js → typst-Dr_K1Jqf.js} +1 -1
  94. package/ui/dist/assets/{vue-JqD9ieOF.js → vue-Wl1CPRGX.js} +1 -1
  95. package/ui/dist/assets/{vue-html-CT4XQRX1.js → vue-html-F5NdFsoh.js} +1 -1
  96. package/ui/dist/assets/{vue-vine-DIR27Dmn.js → vue-vine-YWSKUX3v.js} +1 -1
  97. package/ui/dist/assets/{xml-DhsMbw-1.js → xml-crSJzq2-.js} +1 -1
  98. package/ui/dist/assets/{xsl-BvqsVUg9.js → xsl-D-YjJFxJ.js} +1 -1
  99. package/ui/dist/assets/{yaml-C8eWjK_Q.js → yaml-BZWjhwN4.js} +1 -1
  100. package/ui/dist/index.html +1 -1
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "caret",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Review, annotate, and approve Claude Code plans in a local web UI.",
5
5
  "author": { "name": "macintacos" },
6
6
  "homepage": "https://github.com/macintacos/caret",
package/README.md CHANGED
@@ -60,6 +60,9 @@ bunx --no-cache @macintacos/caret@latest install --refresh # update
60
60
  bunx --no-cache @macintacos/caret@latest install --uninstall # remove
61
61
  ```
62
62
 
63
+ `--refresh` restarts the caret service on the newest caret installed, never older than the
64
+ one you ran; caret keeps a copy of it under `~/.local/state/caret/roots/`.
65
+
63
66
  `caret`'s UI is designed to check for updates, at most once a day. When a newer `caret` is
64
67
  out, the review UI says so once: a toast on load that opens **What's new** (the skipped
65
68
  release notes or trunk commits), a mark on the settings button, and a
@@ -73,10 +76,12 @@ Turn the check off from that same pane, or by hand in
73
76
  check = false
74
77
  ```
75
78
 
76
- See [the OpenCode adapter](doc/ARCHITECTURE.md#the-opencode-adapter) for the by-hand
77
- equivalents, for pinning a version in OpenCode's `plugin` array, and for what each agent's
78
- install touches; [the Claude Code adapter](doc/ARCHITECTURE.md#the-claude-code-adapter)
79
- covers the hooks `caret` registers there.
79
+ `caret` supports OpenCode v1 1.3.4 or later. See
80
+ [the OpenCode adapter](doc/ARCHITECTURE.md#the-opencode-adapter) for the by-hand
81
+ equivalents, for pinning a version in OpenCode's plugin array (`plugin` on v1, `plugins`
82
+ on v2), and for what each agent's install touches;
83
+ [the Claude Code adapter](doc/ARCHITECTURE.md#the-claude-code-adapter) covers the hooks
84
+ `caret` registers there.
80
85
 
81
86
  ## Using `caret`
82
87
 
@@ -104,6 +109,8 @@ your browser instead of the terminal prompt. There you:
104
109
  port, the review timeout, the log level — it reads an optional `config.toml` and `CARET_*`
105
110
  environment variables. Every key, every variable, and their defaults are in
106
111
  [`doc/CONFIGURING.md`](doc/CONFIGURING.md).
112
+ To open the review UI from another device, such as a phone or a laptop, see
113
+ [Reaching caret from another device](doc/RUNNING.md#reaching-caret-from-another-device).
107
114
 
108
115
  ## Documentation
109
116
 
@@ -19,6 +19,9 @@
19
19
  # service the launchd label WITHOUT `.plist` on macOS; the full unit name
20
20
  # WITH `.service` on Linux. Only macOS appends a suffix below.
21
21
  #
22
+ # $XDG_STATE_HOME/caret/roots/<version>/ holds caret install's own copies, scanned
23
+ # beside the agents' caches.
24
+ #
22
25
  # Each record must end with a newline: `read -r` reports EOF on a file without
23
26
  # one, and the read is what decides the record exists.
24
27
 
@@ -27,7 +30,11 @@ set -euo pipefail
27
30
  state="${XDG_STATE_HOME:-$HOME/.local/state}/caret"
28
31
  records="$state/launcher"
29
32
  claude_roots="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/plugins/cache/caret/caret"
30
- opencode_roots="${XDG_CACHE_HOME:-$HOME/.cache}/opencode/packages/@macintacos"
33
+ opencode_cache="${XDG_CACHE_HOME:-$HOME/.cache}/opencode"
34
+ opencode_v1_roots="$opencode_cache/packages/@macintacos"
35
+ opencode_v2_roots="$opencode_cache/npm/@macintacos"
36
+ # Keep in sync with ownedRootsDir() (src/config/paths.ts).
37
+ owned_roots="$state/roots"
31
38
 
32
39
  # The units name no log destination, so nothing opens this before caret does:
33
40
  # openDaemonStderr's 0700/0600 guarantee (src/daemon/lifecycle.ts) happens here for a
@@ -60,50 +67,96 @@ read_record() {
60
67
  [ -f "$1" ] && read -r value <"$1" && [ -n "$value" ] && printf '%s' "$value"
61
68
  }
62
69
 
63
- # Highest of the `<version><TAB><path>` lines on stdin. A numeric field sort
64
- # rather than `sort -V`, which BSD sort does not carry everywhere. Ceiling: on an
65
- # equal numeric prefix the whole-line tiebreak puts a prerelease ABOVE the stable
66
- # release, so 0.15.0-rc.1 would beat 0.15.0. caret publishes no prereleases.
70
+ # Highest of the `<version><TAB><rest>` lines on stdin, printing <rest>. A numeric
71
+ # field sort rather than `sort -V`, which BSD sort does not carry everywhere. On an
72
+ # equal numeric prefix sort compares the whole line, and two things ride on that:
73
+ # candidates() puts its rank right after the version, so an agent's root (1) beats an
74
+ # owned copy (0) — keep the sort unstable (no -s); and a prerelease sorts ABOVE its
75
+ # release (0.15.0-rc.1 beats 0.15.0), a ceiling since caret publishes no prereleases.
76
+ # Keep in sync with pickLauncherRoot (src/commands/install/launcher.ts).
67
77
  highest() { sort -t. -k1,1n -k2,2n -k3,3n | tail -1 | cut -f2-; }
68
78
 
69
- # A candidate is a caret when it ships an executable bin/caret — the one file
70
- # every install method carries, tested the way it is used, since a non-executable
71
- # one would exec-fail at 126 and the supervisor would respawn into it forever.
79
+ # bin/caret-native embeds its UI at compile time; the bundle serves ui/dist, so a
80
+ # half-installed one would answer every UI request with ENOENT. A non-executable
81
+ # bin/caret would exec-fail at 126 and the supervisor would respawn into it forever.
82
+ # Keep in sync with isRunnableRoot (src/daemon/lifecycle.ts).
83
+ root_runnable() {
84
+ [ -x "$1/bin/caret" ] || return 1
85
+ [ -x "$1/bin/caret-native" ] || [ -f "$1/ui/dist/index.html" ]
86
+ }
87
+
72
88
  # Version comes from package.json, never the directory name: OpenCode names its
73
89
  # dir after the verbatim `plugin` specifier. The key is anchored so a minified
74
90
  # manifest yields nothing rather than a later key's value — a miss falls into the
75
91
  # branch that names the directory, a wrong version picks the wrong caret.
76
92
  candidate_version() {
77
- [ -x "$1/bin/caret" ] || return 1
93
+ root_runnable "$1" || return 1
78
94
  sed -n 's/^[[:space:]]*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$1/package.json" 2>/dev/null | head -1
79
95
  }
80
96
 
81
- # Every dir either cache offers, runnable caret or not — the difference between
82
- # a broken install (terminal) and an empty cache (eviction). The OpenCode entry
83
- # is a two-line npm project, not a caret root; the root is one level down.
97
+ # OpenCode v2's live install under spec dir $1: the numerically largest all-digit
98
+ # child. Older generations persist beside it and are never loaded. Keep in sync with
99
+ # liveGenerationDir (src/adapters/opencode/paths.ts).
100
+ live_generation() {
101
+ local dir name newest=""
102
+ for dir in "$1"/*; do
103
+ name="${dir##*/}"
104
+ case "$name" in '' | *[!0-9]*) continue ;; esac
105
+ if [ -z "$newest" ] || [ "$name" -gt "$newest" ]; then newest="$name"; fi
106
+ done
107
+ if [ -n "$newest" ]; then printf '%s' "$1/$newest"; fi
108
+ }
109
+
110
+ # Every dir either agent's cache or caret's own copies offer, runnable caret or
111
+ # not — the difference between a broken install (terminal) and an empty cache
112
+ # (eviction). OpenCode's cache dir is named exactly `caret` or `caret@<spec>`: v1's
113
+ # holds a two-line npm project with the root one level down; v2's holds numbered
114
+ # generations, of which only the live one is offered. `*` skips dot-prefixed dirs,
115
+ # so a half-copied owned root is never a candidate. Keep in sync with
116
+ # launcherCandidateDirs (src/commands/install/launcher.ts) and opencodeRootPaths
117
+ # (src/adapters/opencode/paths.ts); both suites pin it through
118
+ # test/core/commands/install/fixtures/launcher-caches.txt.
84
119
  candidate_dirs() {
85
- local dir
86
- for dir in "$claude_roots"/* "$opencode_roots"/caret*/node_modules/@macintacos/caret; do
120
+ local dir spec live
121
+ for dir in "$claude_roots"/* \
122
+ "$opencode_v1_roots"/caret/node_modules/@macintacos/caret \
123
+ "$opencode_v1_roots"/caret@*/node_modules/@macintacos/caret; do
124
+ if [ -d "$dir" ]; then printf '%s\n' "$dir"; fi
125
+ done
126
+ for spec in "$opencode_v2_roots"/caret "$opencode_v2_roots"/caret@*; do
127
+ if [ ! -d "$spec" ]; then continue; fi
128
+ live="$(live_generation "$spec")"
129
+ dir="$live/node_modules/@macintacos/caret"
130
+ if [ -n "$live" ] && [ -d "$dir" ]; then printf '%s\n' "$dir"; fi
131
+ done
132
+ for dir in "$owned_roots"/*; do
87
133
  if [ -d "$dir" ]; then printf '%s\n' "$dir"; fi
88
134
  done
89
135
  }
90
136
 
137
+ # `<version><TAB><rank><TAB><dir>`: rank 0 for caret's own copy, 1 for an agent's.
91
138
  candidates() {
92
- local dir version
139
+ local dir version rank
93
140
  candidate_dirs | while read -r dir; do
94
141
  version="$(candidate_version "$dir" || true)"
95
- if [ -n "$version" ]; then printf '%s\t%s\n' "$version" "$dir"; fi
142
+ rank=1
143
+ case "$dir" in "$owned_roots"/*) rank=0 ;; esac
144
+ if [ -n "$version" ]; then printf '%s\t%s\t%s\n' "$version" "$rank" "$dir"; fi
96
145
  done
97
146
  }
98
147
 
99
148
  resolve_root() {
100
149
  local pin
101
150
  pin="$(read_record "$records/pinned-root" || true)"
102
- if [ -n "$pin" ] && [ -x "$pin/bin/caret" ]; then
151
+ if [ -n "$pin" ] && root_runnable "$pin"; then
103
152
  printf '%s' "$pin"
104
153
  return 0
105
154
  fi
106
- candidates | highest
155
+ # The rank sorts an agent's root above an owned copy of the same version: a hook
156
+ # reuses a supervised daemon only when its build matches. highest() leaves
157
+ # candidates()' rank in front of the dir. Keep in sync with pickLauncherRoot
158
+ # (src/commands/install/launcher.ts).
159
+ candidates | highest | cut -f2-
107
160
  }
108
161
 
109
162
  # The newest mise-managed bun, for a machine whose mise shims are not on the
@@ -153,8 +206,8 @@ stop_agent() {
153
206
  # tears its service down and deletes itself. Returns non-zero without touching
154
207
  # anything when there is no `service` record — nothing here installed a
155
208
  # supervisor, so this launcher cannot know what still names it, and deleting
156
- # itself would leave whatever does respawning on ENOENT. Deleting only bin/ and
157
- # the records leaves review state for a reinstall.
209
+ # itself would leave whatever does respawning on ENOENT. Deleting bin/, the
210
+ # records and caret's own roots leaves review state for a reinstall.
158
211
  evict() {
159
212
  local service unit
160
213
  service="$(read_record "$records/service" || true)"
@@ -166,17 +219,17 @@ evict() {
166
219
  systemctl --user disable --now "$service" || true
167
220
  unit="${XDG_CONFIG_HOME:-$HOME/.config}/systemd/user/$service"
168
221
  fi
169
- printf 'caret-launcher: no caret installed anywhere; removing %s and %s.\n' \
170
- "$unit" "$state/bin" >&2
222
+ printf 'caret-launcher: no caret installed anywhere; removing %s and %s/{bin,launcher,roots}.\n' \
223
+ "$unit" "$state" >&2
171
224
  rm -f "$unit"
172
- rm -rf "${state:?}/bin" "${state:?}/launcher"
225
+ rm -rf "${state:?}/bin" "${state:?}/launcher" "${state:?}/roots"
173
226
  exit 0
174
227
  }
175
228
 
176
229
  # Only under a supervisor: a hand-run launcher keeps its diagnostics on the terminal.
177
230
  if [ "${CARET_SUPERVISED:-}" = 1 ]; then open_daemon_log; fi
178
231
 
179
- # Only a total miss re-probes. A populated version dir with no runnable bin/caret
232
+ # Only a total miss re-probes. A populated version dir with no runnable caret
180
233
  # is far more likely a bad install than an extraction caught mid-flight, and that
181
234
  # path is recoverable with `caret install`; an empty cache is the one whose branch
182
235
  # deletes things, so it is the one worth waiting on.
@@ -190,7 +243,7 @@ done
190
243
  if [ -z "$root" ]; then
191
244
  found="$(candidate_dirs)"
192
245
  if [ -z "$found" ]; then evict || true; fi
193
- printf 'caret-launcher: no runnable bin/caret under any of:\n%s\n' \
246
+ printf 'caret-launcher: no runnable caret (an executable bin/caret and a UI build) under any of:\n%s\n' \
194
247
  "${found:-(no install directories at all)}" >&2
195
248
  printf 'caret-launcher: run: caret install — to restore the service.\n' >&2
196
249
  stop_agent
@@ -39,7 +39,8 @@ one. What each id means:
39
39
 
40
40
  | id | what failed | relay |
41
41
  | --- | --- | --- |
42
- | `daemon-reachable` | a caret service is recorded but the daemon did not answer, or the effective port answers as something other than caret | the check's remedy verbatim, then offer to read any log it names |
42
+ | `daemon-reachable` | a caret service is recorded but its supervisor is not keeping it alive (not loaded, turned off, or parked) or the daemon did not answer; or the effective port answers as something other than caret | the check's remedy verbatim, then offer to read any log it names |
43
+ | `daemon-version` | the running daemon is older than npm's latest | the check's remedy verbatim |
43
44
  | `daemon-lock` | the lock names a dead pid, or a port caret is not configured to bind | the check's remedy verbatim |
44
45
  | `agent-install` | the agent the check names does not have caret enabled | `caret install` |
45
46
  | `log-errors` | a live log wrote an NDJSON error record in the last 24h; the detail names which log and when it last erred | step 4 |