samagotchi 0.130.1 → 0.132.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 (68) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +76 -1
  3. data/bin/chi +3 -1
  4. data/docs/architecture.md +32 -1
  5. data/docs/cli.md +32 -9
  6. data/docs/configuration.md +67 -8
  7. data/docs/desktop.md +15 -6
  8. data/docs/guardrails.md +3 -3
  9. data/docs/internals/anthropic.md +3 -2
  10. data/docs/internals/engine.md +4 -4
  11. data/docs/internals/participants.md +23 -6
  12. data/docs/internals/prompt-caching.md +29 -6
  13. data/docs/memory.md +16 -2
  14. data/docs/plugins.md +68 -1
  15. data/lib/samagotchi/bootstrap_command.rb +35 -6
  16. data/lib/samagotchi/bundles/model-notes/manifest.yml +4 -1
  17. data/lib/samagotchi/bundles/model-notes/model_notes_tone.md +3 -0
  18. data/lib/samagotchi/bundles/model-notes/notes/README.md +14 -0
  19. data/lib/samagotchi/bundles/system/manifest.yml +1 -1
  20. data/lib/samagotchi/cache_confirm.rb +47 -9
  21. data/lib/samagotchi/chi_home.rb +311 -0
  22. data/lib/samagotchi/desktop/macos.rb +75 -19
  23. data/lib/samagotchi/engine.rb +66 -6
  24. data/lib/samagotchi/engine_snapshots.rb +5 -0
  25. data/lib/samagotchi/gem_update.rb +19 -10
  26. data/lib/samagotchi/guardrail_wiring.rb +3 -1
  27. data/lib/samagotchi/guardrails/protected_paths.rb +6 -3
  28. data/lib/samagotchi/guardrails/verdict.rb +1 -1
  29. data/lib/samagotchi/home_command.rb +149 -0
  30. data/lib/samagotchi/installed_versions.rb +5 -3
  31. data/lib/samagotchi/level_setting_command.rb +3 -2
  32. data/lib/samagotchi/llm_context_command.rb +53 -7
  33. data/lib/samagotchi/llm_context_override.rb +3 -2
  34. data/lib/samagotchi/plugin/api.rb +45 -1
  35. data/lib/samagotchi/plugin/context.rb +34 -1
  36. data/lib/samagotchi/plugin/loader.rb +5 -2
  37. data/lib/samagotchi/plugin/prompt_sections.rb +124 -0
  38. data/lib/samagotchi/run_options.rb +1 -0
  39. data/lib/samagotchi/session_access/contract.rb +1 -1
  40. data/lib/samagotchi/session_commands.rb +68 -21
  41. data/lib/samagotchi/session_manager.rb +36 -1
  42. data/lib/samagotchi/session_model_settings.rb +5 -2
  43. data/lib/samagotchi/system_prompt.rb +34 -3
  44. data/lib/samagotchi/terminal_ui/attach_launcher.rb +3 -2
  45. data/lib/samagotchi/terminal_ui/formatting.rb +3 -0
  46. data/lib/samagotchi/testing/bundle.rb +22 -3
  47. data/lib/samagotchi/testing/host.rb +22 -1
  48. data/lib/samagotchi/testing/recorder.rb +6 -1
  49. data/lib/samagotchi/testing/recording_api.rb +1 -1
  50. data/lib/samagotchi/toolkit_command.rb +2 -2
  51. data/lib/samagotchi/update_command.rb +65 -7
  52. data/lib/samagotchi/version.rb +1 -1
  53. data/lib/samagotchi/web/app.rb +11 -1
  54. data/lib/samagotchi/web/participant_view.rb +22 -6
  55. data/lib/samagotchi/web/public/annotate_bar.js +6 -1
  56. data/lib/samagotchi/web/public/app.js +14 -5
  57. data/lib/samagotchi/web/public/index.html +6 -2
  58. data/lib/samagotchi/web/public/llm_context_chip.js +4 -3
  59. data/lib/samagotchi/web/public/model_pick.js +26 -0
  60. data/lib/samagotchi/web/public/model_picker.js +3 -1
  61. data/lib/samagotchi/web/public/participant.js +24 -6
  62. data/lib/samagotchi/web/public/start_page.js +14 -2
  63. data/lib/samagotchi/web/public/verdict_card.js +48 -4
  64. data/lib/samagotchi/web/public/verdict_fresh.js +8 -4
  65. data/lib/samagotchi/web/public/verify_target.js +73 -0
  66. data/lib/samagotchi/web/server.rb +27 -8
  67. data/lib/samagotchi/web/update_check.rb +3 -2
  68. metadata +6 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dcca1391e17e266cf83e1c56dec7ab52d21a1928a4c5190d2bf594884cca936f
4
- data.tar.gz: fc59a582d279b19352c3bda61bb5d2fc3796ae0e079e52b3dcb26dc85988ea33
3
+ metadata.gz: ebe264e1dbd5adc620889aa40d66fd458519c64f038a3a3e5de06ee6a6da46e7
4
+ data.tar.gz: 3c72148287422c9821c25bc3979c71890fb4abad81af3829650aef3c13549a3f
5
5
  SHA512:
6
- metadata.gz: b5cc1d80ca1b0d64f809360e111bdae2778772c5ca3c8cae7d6f339f650a55fb65b796ccc5ca3038b25c637223568a7facbc90a351ac5df77bee25c24fac3e59
7
- data.tar.gz: 4e149d518537a529c69494f14b0d07435c6e3327d27ae34a42c0e30504c74fee543282c4023fbd44587a301f189c24bd7d3aebdff40235784bd45f95cfd63217
6
+ metadata.gz: f8ffaf8ca17c125a38af6a30432d8b14a66ea97df8201686acedca8dde11869845b0e2a6abe0f9ece18db4e5848f9340b2ef73910371977fafe9889d430eebad
7
+ data.tar.gz: e556232bbad1093cff1779510162a179b1284cc90bd8cc54d8082e2a4dab5e96f98bb6ebae5ef99ab82610a1bd33880c830cfae8b1076d1e6ca841c406ae45b3
data/CHANGELOG.md CHANGED
@@ -7,6 +7,79 @@ and commands may change between minor versions. How releases are made:
7
7
  [docs/releasing.md](docs/releasing.md).
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.132.0] - 2026-10-29
11
+
12
+ ### Added
13
+
14
+ - `chi home`, `chi home set [--ruby PATH]`, `chi home doctor`: the chi home, the one Ruby and gem path every chi
15
+ launch boots (`~/.config/samagotchi/home.json`). The first `chi bootstrap` or `chi update` records it once (the
16
+ desktop helper's Ruby when it has samagotchi, else chi's own); see docs/configuration.md (The chi home). A
17
+ write or edit of home.json asks, as config.yml does (rule `chi-home`, the user's alone).
18
+ - Bundles: model-notes 0.2.0 ships `model_notes_tone` (`models: *`): every model answers first, in plain words, without
19
+ preambles or closing offers. Off with `chi --mute model_notes_tone`; your own note of that name wins.
20
+ - Plugins: `chi.prompt_section(name) { |ctx| … }` adds a bundle's text to the system prompt's stable part (after the
21
+ toolkit's prompt, before the memory indexes), and `chi.prompt_changed!` builds the prompt again at the next turn.
22
+ A section that fails keeps its last good text; `/stats` names the sections (`prompt sections:`).
23
+ - Plugins: a command can ask before a change that restarts the prompt cache, as `/thinking` does:
24
+ `ctx.cache_confirm(line, changed:)` gives a confirm for a person at a web tab or a TUI once the session has a
25
+ model reply, and the command returns `[text, confirm]` (the TUI prefills the `--yes` line, the web shows Apply).
26
+ - Plugins: `ctx.model_names` lists the names chi looks the session's model up under (alias, target, ref, bare id),
27
+ so a bundle can match a per-model map the way config.yml's `models:` settings are matched.
28
+
29
+ ### Changed
30
+
31
+ - With a chi home, every session worker (whoever starts or wakes it), chi web's restart and Update, `chi update`
32
+ and `chi bootstrap`'s commonmarker install run on it: the home's Ruby with its gem path set inside Ruby, never in
33
+ an env, so session tools keep the spawner's GEM_HOME/GEM_PATH. `chi update` from another Ruby runs the home's
34
+ (`updating the chi home (<ruby>)`) and installs into its gems; a worker whose home can't load chi logs one
35
+ `boot_failed` line instead of a silent spawn timeout. Without a home every launch is as before.
36
+ - Desktop helper: `chi desktop install` and `upgrade` make it boot the chi home when there is one, and its launch
37
+ file no longer carries `RUBYLIB`, nor `GEM_HOME`/`GEM_PATH` when it boots the home (they reached every command its
38
+ sessions ran). `chi update` drops `RUBYLIB` from an existing one, and `GEM_HOME`/`GEM_PATH` once it boots the home.
39
+ - `/model` asks before switching to another model once the session has a model reply, from a web tab or a TUI (the
40
+ new model has no cache of the conversation): the reply names the size it rereads and the line that applies it,
41
+ flags and all (`/model qwen --default --yes`); `--yes` (or `-y`) applies at once, and a typo is an error before any
42
+ question. `chi send`, delegates and `chi --model` on an attached or resumed session apply at once.
43
+ - `/llm-context` asks the same way before the two changes that break the prompt cache now: `forget` turned on or off,
44
+ and a layer with applied stubs turned off (`/llm-context reset --yes` applies too). Turning `stale` on, the apply
45
+ rule and the budget don't ask; the web's `llm ctx` chip and `chi --llm-context` on an attached or resumed session
46
+ apply at once.
47
+
48
+ Update with `chi update`, then restart `chi web` and the session workers (`chi sessions restart`): a new TUI's
49
+ `--model X` on a worker from before this release switches it to the model "X --yes".
50
+
51
+ ## [0.131.0] - 2026-10-29
52
+
53
+ ### Changed
54
+
55
+ - Web: the start page's composer row stays one row at any width: a long model name ellipsizes instead of pushing
56
+ Start to a second row.
57
+ - Web: the start page's model button shows a short name (`openrouter · deepseek-v4.1-flash`: no org prefix, the tag
58
+ kept, the host only when it isn't the default); its tooltip and label keep the full name.
59
+ - Cache: confirmations for prompt-cache changes estimate the reread size when known and warn that Anthropic drops
60
+ preserved thinking after a full-prefix change.
61
+
62
+ ### Fixed
63
+
64
+ - Web: a Verify verdict card sits right after the answer it quotes, on your page and a participant's, instead of
65
+ under the turn's prompt, screens above the claim in a long turn. A quote the page can't find yet puts the card at
66
+ the turn's end.
67
+ - Web: Verify on a claim in a model's reply on a participant's page records its verdict and shows the card again;
68
+ the claim was sent without its turn, so the check ran as a plain comment.
69
+ - Web: after a fresh verdict lands on an unclear card, its button reads **Verify fresh again**: each press starts
70
+ another paid check (a participant's counts against their cap).
71
+ - Web: Verify is offered only on a finished turn's final answer, on your page and a participant's: the one place a
72
+ verdict card can come from. Selecting an earlier reply, a step, a message, a line added mid-turn or a turn still
73
+ running no longer offers a Verify that silently ran as a plain comment; the bar keeps its other actions there.
74
+ - Web: on a participant's page, a turn a delegate's report or a context note woke opens as "An automatic turn"
75
+ (still without the report or note). Its answer read as one more reply of the turn before: Verify was offered on
76
+ it and refused, and hidden on that turn's real final answer.
77
+ - Web: Verify on a claim that names a file in the session's folder or your home folder (or holds a key) records its
78
+ verdict: the pages quote such a path relative, or with `~`, and the check compared it against the answer's full
79
+ path, so it ran as a plain comment with no card.
80
+
81
+ Update with `chi update`, then restart `chi web` and the session workers (`chi sessions restart`).
82
+
10
83
  ## [0.130.1] - 2026-10-29
11
84
 
12
85
  ### Fixed
@@ -4964,7 +5037,9 @@ and long-lived sessions.
4964
5037
  - A macOS desktop helper (`chi desktop install`): a "Send to chi" Service and a
4965
5038
  hotkey panel that send selected text or the clipboard to your sessions.
4966
5039
 
4967
- [Unreleased]: https://github.com/dm1try/samagotchi/compare/v0.130.1...HEAD
5040
+ [Unreleased]: https://github.com/dm1try/samagotchi/compare/v0.132.0...HEAD
5041
+ [0.132.0]: https://github.com/dm1try/samagotchi/compare/v0.131.0...v0.132.0
5042
+ [0.131.0]: https://github.com/dm1try/samagotchi/compare/v0.130.1...v0.131.0
4968
5043
  [0.130.1]: https://github.com/dm1try/samagotchi/compare/v0.130.0...v0.130.1
4969
5044
  [0.130.0]: https://github.com/dm1try/samagotchi/compare/v0.129.0...v0.130.0
4970
5045
  [0.129.0]: https://github.com/dm1try/samagotchi/compare/v0.128.0...v0.129.0
data/bin/chi CHANGED
@@ -82,7 +82,9 @@ SUBCOMMANDS = {
82
82
  # audit suggestions for which toolkit fits a session's first prompt
83
83
  "toolkit" => ["samagotchi/toolkit_report_command", "ToolkitReportCommand"],
84
84
  # other machines' chi web, for chi --remote NAME (add, ls, rm)
85
- "remote" => ["samagotchi/remote_command", "RemoteCommand"]
85
+ "remote" => ["samagotchi/remote_command", "RemoteCommand"],
86
+ # the chi home: the Ruby every chi launch boots (set, doctor)
87
+ "home" => ["samagotchi/home_command", "HomeCommand"]
86
88
  }.freeze
87
89
  # chi --remote NAME <command> (or CHI_REMOTE=NAME): the session commands
88
90
  # against another machine's chi web; what runs here only is refused (exit 2).
data/docs/architecture.md CHANGED
@@ -133,6 +133,36 @@ terminal renders the events it gets over the Bridge.
133
133
  - In REPL mode `TerminalUI` builds the `Engine` in process (`-p` and `--non-interactive` too);
134
134
  otherwise the session's `Worker` (`lib/samagotchi/worker.rb`, spawned by `SessionManager`) builds it.
135
135
 
136
+ ## How chi launches itself
137
+
138
+ chi starts chi in several places, and each must land on the same install whoever starts it (a terminal on another
139
+ Ruby, chi web, the macOS helper under launchd). The **chi home** (`ChiHome`, `chi_home.rb`; recorded in
140
+ `$XDG_CONFIG_HOME/samagotchi/home.json` by `chi home set`, or once by `chi bootstrap` / `chi update`:
141
+ [configuration.md](configuration.md#the-chi-home)) names that install: a Ruby and its gem path.
142
+
143
+ **One mechanism.** `ChiHome::Record#boot_argv(run:)` is `[home ruby, "-e", "Gem.paths = {'GEM_HOME' => …,
144
+ 'GEM_PATH' => …}; <run>"]`: the gem path goes into the boot string, never into an environment, so the tools a worker
145
+ runs keep the spawner's GEM_HOME/GEM_PATH (or none), and a stray one in the spawner's env can't move chi off the
146
+ home. `ChiHome::CHI_BOOT` (`gem 'samagotchi', '>= 0.a'; load Gem.bin_path('samagotchi', 'chi')`) plus `"--"` and
147
+ the arguments runs the home's newest `chi`. Each site asks `ChiHome.current` at launch time; it is nil (and the site
148
+ keeps its own argv, as before the home) without home.json, for one that isn't its shape (warned once), when the
149
+ home's Ruby is gone, when no `samagotchi-*.gemspec` is under its gem path, and from a source checkout.
150
+
151
+ | Site | With a home | Without |
152
+ |---|---|---|
153
+ | `SessionManager.worker_command`: every worker (attach, `chi send`, chi web, delegate and Verify-fresh children, `resume_session`, `:restart`) | the home's ruby, `Gem.paths`, `>= 0.a` with the fallback pin (`ChiHome.fallback_version`: the spawner's version when the home has it, else the home's newest; a home older than the spawner is warned once); a chi that still can't load writes one `boot_failed` line to `SAMAGOTCHI_LOG_FILE` and exits 1 | `RbConfig.ruby -e` with `>= 0.a` (a checkout: `-I lib`) |
154
+ | `Web::Server.reexec_command` (chi web's restart) | `CHI_BOOT -- web …`; the `:no_wrapper` refusal never applies; a home whose newest chi is older than this one is passed over (logged `restart_home_older`) | `[RbConfig.ruby, wrapper, …]` (`$PROGRAM_NAME` in a checkout) |
155
+ | `Web::App#update_argv` (the **Update** button's child) | `CHI_BOOT -- update --to V --no-desktop --json` | `[RbConfig.ruby, wrapper, update, …]` |
156
+ | `UpdateCommand` | on another Ruby than the home (`Record#running_here?`): exec `CHI_BOOT -- update …` once (`SAMAGOTCHI_UPDATE_IN_HOME=1`: an older home chi ignores it); the install (`GemUpdate`) runs `ChiHome.gem_bin` with `ChiHome.install_env` (the home's GEM_HOME/GEM_PATH for that child, `mise`'s dir on PATH); the hand-over execs `CHI_BOOT -- update --no-gem --gem-from …` | this Ruby's `gem`, the wrapper |
157
+ | `BootstrapCommand` (commonmarker) | `ChiHome.gem_bin` + `install_env`; installed? = in the home's specifications | this Ruby's `gem` |
158
+ | `Desktop::MacOS#launch_config` | argv `CHI_BOOT + ["--"]`; `launch_ok?` / `launch_problem` check only absolute argv entries | `[ruby, wrapper or bin/chi]` |
159
+ | `InstalledVersions`, `Web::UpdateCheck` | the home's specification dirs and gem dir | the running process's |
160
+
161
+ Unchanged: `ContextProviders`' `{ruby}` (`RbConfig.ruby`: the home's ruby inside a home worker), `chi bundle
162
+ try/test/check` (`-I LIB_DIR`), hooks (in-process). The worker's boot string, `run_session_loop(id, state_dir:)` and
163
+ `SAMAGOTCHI_BOOT_FALLBACK` stay the cross-version contract (`spec/worker_contract_spec.rb`): the home only adds the
164
+ prelude in front. An older chi that wakes a session doesn't read home.json and starts its worker as before.
165
+
136
166
  ## Session retention & ordering
137
167
 
138
168
  - **Files:** `~/.local/state/samagotchi/sessions/<uuid>.json` + `<uuid>/input|output|owner.lock|bridge.json` (XDG-aware), and the `<uuid>/stopped` and `<uuid>/archived` marker files.
@@ -227,7 +257,8 @@ The system prompt (`SystemPrompt#build`, assembled in `#system_prompt_with_index
227
257
  base prompt, then the toolkit's "Not loaded in this session" line (only when the toolkit
228
258
  leaves tools out), rg guidance, the identity, the model notes, the preloaded memories,
229
259
  AGENTS.md (root → cwd), the appended files (`--append-system-prompt`), the toolkit's
230
- kit prompt (a kit's `prompt:` text, only when it has one), the memory
260
+ kit prompt (a kit's `prompt:` text, only when it has one), the plugins' prompt
261
+ sections (`chi.prompt_section`, only when a plugin gives text), the memory
231
262
  indexes, and last **the model** (`Model: this session runs on <ref> (host …; model key …)` and a line telling
232
263
  the model to answer "which model are you" from it, not from training), the working
233
264
  directory and the session id and log (Gemma's native tool declarations still follow).
data/docs/cli.md CHANGED
@@ -35,6 +35,7 @@
35
35
  - `chi models [--format text|json] [--timeout S] [TEXT]` — list the models every configured host offers, as the names `--model` takes (see [Listing the models](#listing-the-models))
36
36
  - `chi self` — print version, source dir (checkout or installed gem), config/memory/session paths, model/host and bundles. Run by a session's `execute`, the `model` row (and host, loop, profile, thinking, served model) is **that session's** model, labelled `(this session <id8>; default …)`; elsewhere it is the default, `(default)`. `model key` is the memory overlay key (`<name>.<key>.md`), and `model notes` the model notes a prompt of that model loads (`model_notes_deepseek (system, 612 chars)`, `none`; inside a session its `--mute` list is left out). `chi self --model` prints only the model a new session starts on, an alias resolved to its target (the desktop helper's hint)
37
37
  - `chi update [--dry-run] [--to VERSION] [--json] [--no-gem] [--no-bundles] [--no-desktop]` — update an installed chi: the gem, the system bundle, the shipped bundles you installed and the desktop helper, in one table (see [Updating](#updating))
38
+ - `chi home`, `chi home set [--ruby PATH]`, `chi home doctor` — the chi home: the one Ruby (and its gem path) every chi launch boots, whoever launches it. `chi home` shows it (its Ruby, the newest chi in it, gem home and path, `mise`, when and by which chi it was set, and the chi you ran when that is another one; exit 1 with the problem when it can't boot chi), `set` records this chi's Ruby and gem path (or `--ruby PATH`'s own; it must have samagotchi), `doctor` checks it (for now: its Ruby is there and has samagotchi; exit 1 says what to do). This machine only (see [The chi home](configuration.md#the-chi-home))
38
39
  - `chi bundle install|upgrade|uninstall|status|diff|list|build|trash|new|test|check` — manage memory bundles (see [Bundle hooks](hooks.md#bundle-hooks-unified-workflow-bundle)); `list` shows the installed ones and the ones shipped with chi, which `install <name>` installs; `core` and `dev` are profiles that install a set of them (see [Bundle profiles](memory.md#bundle-profiles-core-and-dev), [Guardrails](guardrails.md), [Plugins](plugins.md#the-btw-bundle), [the mcp bundle](plugins.md#the-mcp-bundle) [the loop-guard bundle](plugins.md#the-loop-guard-bundle), [the check-in bundle](plugins.md#the-check-in-bundle) and [the skills bundle](plugins.md#the-skills-bundle)). `trash` lists and empties the bundle trash (moved files from uninstalls/upgrades). A usage error (an unknown subcommand or flag, a missing argument, a bad `build --scope`) exits 2, as for the other subcommands. Plain `chi` and `chi web` exit 1 on an unknown flag, a flag missing its value or a stray argument. `new`, `test` and `check` are for writing one: see [Writing a bundle](#writing-a-bundle-new-test-check)
39
40
 
40
41
  - `chi guardrails replay [--dry-run] [--threshold T] [--model M]` — seed System 1's record from the approvals this machine's sessions already answered: each ask is judged by the configured model and written to `guardrails/judgments.jsonl` with the answer the user gave, then a per-rule table prints (asks, allowed, denied, would-be auto-allows, false allows, asks with no judgment). A parent agent's answer is not the user's: only its deny is replayed, and only where the parent could have allowed. `--dry-run` judges without writing, `--threshold` overrides `guardrails.system_one.threshold` for the table, `--model` the configured model for this run. Exit 2 when `guardrails.system_one.mode` is off or no `host` is set; a usage error exits 2 (see [System 1](guardrails.md#system-1-experimental))
@@ -257,11 +258,22 @@ done
257
258
  [configuration](configuration.md#all-settings)). If the gem can't be updated
258
259
  in place, the notice gives the blocker and its command instead.
259
260
 
261
+ - **The chi home.** With a [chi home](configuration.md#the-chi-home), a `chi
262
+ update` started on another Ruby first says `updating the chi home (<ruby>)`
263
+ and runs the home's chi update instead (the version check, `--to` and the
264
+ rows are the home's); chi web's **Update** runs the home's too. Without
265
+ one, the first `chi update` (not `--dry-run`, not under Bundler, and only
266
+ once its own checks passed) records one: of the desktop helper's Ruby and
267
+ the Ruby it runs on, the one with the newer chi, and says `chi home set to
268
+ <ruby> (chi home set to change)`.
260
269
  - **The gem.** It asks rubygems.org for the newest samagotchi (5 s timeout)
261
270
  and, when that's newer, runs `gem install samagotchi` with the gem command
262
- of the Ruby chi runs on (the real one, not a mise/rbenv/asdf shim; a chi
263
- installed under another Ruby is a separate install it doesn't touch). Then it
264
- hands over to the new chi, which does the rest and prints the table. Old
271
+ of the chi home's Ruby, into the home's gems (`GEM_HOME`/`GEM_PATH` set to
272
+ the home's for that one command, and `mise`'s folder on its PATH when the
273
+ home names one, for mise's reshim plugin); without a home, the Ruby chi runs
274
+ on (the real one, not a mise/rbenv/asdf shim; a chi installed under another
275
+ Ruby is a separate install it doesn't touch). Then it hands over to the new
276
+ chi, which does the rest and prints the table. Old
265
277
  versions stay installed: running workers and an old `chi web` still load
266
278
  files from them, so a `gem cleanup` while they run breaks them (a
267
279
  `LoadError`, missing web assets); restart them first. A chi web, an
@@ -293,7 +305,9 @@ done
293
305
  sources changed; otherwise only its launch file is refreshed (a newer chi or
294
306
  other terminal settings). It keeps the Ruby, chi and PATH the helper runs (a
295
307
  PATH is filled in only when the file has none): `chi desktop install --force`
296
- and `chi desktop upgrade` bake this shell's. A helper whose Ruby or chi is gone
308
+ and `chi desktop upgrade` bake this shell's (the chi home's boot, when there
309
+ is one). A refresh drops `RUBYLIB` from the launch file, and `GEM_HOME`/`GEM_PATH`
310
+ once it boots the chi home. A helper whose Ruby or chi is gone
297
311
  is reported as failed, naming `chi desktop install --force`. See
298
312
  [Desktop helper](desktop.md).
299
313
  - **Running processes** are reported, never stopped. A live worker keeps its
@@ -689,11 +703,14 @@ saved with the session and applies from the next turn's start; the reply says
689
703
  what it costs: `forget` on or off re-reads the whole prompt once, `stale` turned
690
704
  on stages the reads already superseded as one batch under the apply rule, and a
691
705
  layer turned off sends its stubs whole again (turning it back on brings them
692
- back). `/llm-context` alone answers mid-turn too; a change sent while a turn runs
706
+ back). Once the session has a model reply, the two that break the cache now
707
+ (`forget` on or off, a layer with applied stubs turned off) ask first and name
708
+ the `--yes` line that applies them; `/llm-context reset --yes` works too.
709
+ `/llm-context` alone answers mid-turn too; a change sent while a turn runs
693
710
  waits for the turn's end (see *Typing during a turn*). `/stats` shows
694
711
  the same values on its `llm context:` line. The web's info bar shows them as the
695
712
  `llm ctx` chip (`llm ctx stale,forget · session`), whose popover sets them
696
- through `/llm-context`. See "LLM context: a session's own strategy" in
713
+ through `/llm-context … --yes` (its form says what a change costs). See "LLM context: a session's own strategy" in
697
714
  [configuration.md](configuration.md).
698
715
 
699
716
  `/working-set` lists the session's working set as the model has it (see [The
@@ -801,9 +818,9 @@ mid-turn too, and the lists, cards, top bar and tab show it in place of the firs
801
818
  message; a continue's next link keeps it. In the web, `✎` next to the session's
802
819
  title (its strip card, or the top bar) does it. See [Session titles](sessions.md#session-titles).
803
820
 
804
- A `/thinking`, `/reasoning-history` or `/toolkit` change that restarts the prompt cache
821
+ A `/model`, `/llm-context`, `/thinking`, `/reasoning-history` or `/toolkit` change that restarts the prompt cache
805
822
  asks first: the reply says what it costs, changes nothing, and names the line
806
- that applies it (`/thinking low --yes`). `--yes` (or `-y`) applies it at once.
823
+ that applies it (`/thinking low --yes`, `/model qwen --default --yes`). `--yes` (or `-y`) applies it at once.
807
824
  The terminal puts that line in the next input (Enter applies it); the web's
808
825
  reply has an Apply button. `chi send ID "/thinking low"`,
809
826
  `chi -p "/thinking low" --non-interactive` and lines piped into the REPL apply
@@ -1214,7 +1231,9 @@ pills there (a review turn refuses `/` lines).
1214
1231
 
1215
1232
  After the presets, both pages have a built-in **Verify**: the quote, then
1216
1233
  an ask to check the claim against the code and end on a line `Verdict:
1217
- confirmed|refuted|unclear — <reason>`. A session whose worker predates Verify (started by an older chi) refuses it (409
1234
+ confirmed|refuted|unclear — <reason>`. Verify is offered only on text in a finished turn's final answer, the
1235
+ claim a verdict card can come from; elsewhere (an earlier reply, a step, a message, a line added mid-turn, a turn
1236
+ still running) the bar keeps its other actions. A session whose worker predates Verify (started by an older chi) refuses it (409
1218
1237
  `verify_unavailable`); a participant's page disables Verify and Verify fresh with a hint to restart the session. On your page a selection in a turn
1219
1238
  also offers **Copy link**: a link to that turn and quote for a participant's
1220
1239
  browser (the one their review link was opened in), which opens their page
@@ -1594,6 +1613,10 @@ In interactive assist mode, you can switch the request model without restarting:
1594
1613
  - `/model <name> --alias <alias>`: create alias for current effective model (alias value may be bare or `host:model`).
1595
1614
  - `/model`: show the effective model (and default when diverged: `runtime model: <effective> (default: <default>, profile=<name>, <source>)`, e.g. `profile=qwen36, server (chat_template)`). When the session's prompt carries model notes the line ends with `; notes: model_notes_deepseek (system, 612 chars)`; a switch's `runtime model set to …` names the new model's ([Memory](memory.md#model-notes)).
1596
1615
  - `/model clear` (or `default`/`none`/`off`): clear the session override, reverting to the configured default.
1616
+ - Once the session has a model reply, a switch to another model asks first from a web tab or a TUI (the new model
1617
+ has no cache of the conversation): the reply names the line with `--yes` that applies it, flags and all
1618
+ (`/model qwen --alias q --yes`); `--yes` (or `-y`) applies at once. A typo (an unknown host, a bad alias) is an
1619
+ error before any question. See "Changes that restart the prompt cache" in [configuration.md](configuration.md).
1597
1620
  - `/guardrails`: the guardrail rules (by source), what failed to load, your stored approvals, and System 1's
1598
1621
  recent auto-allows; `/guardrails revoke N` removes approval N and `/guardrails wrong [N]` flags an auto-allow
1599
1622
  this session should have been asked about (see [Guardrails](guardrails.md)).
@@ -833,12 +833,19 @@ models:
833
833
 
834
834
  ## Changes that restart the prompt cache
835
835
 
836
- `/thinking`, `/reasoning-history` and `/toolkit` ask before a change that makes the server read the conversation again:
837
- Gemma's thinking switch, a remote chat host's thinking fields ("Thinking"), a change to or from `all` once an earlier
838
- reply has thinking ("Reasoning history"), and any change to the declared tools, which start every request
839
- ("Toolkits"). They ask only when what the next turn runs under really changes and the session has a model reply.
840
-
841
- - The reply says what it costs and changes nothing yet: `Nothing changed yet: send /thinking low --yes to apply.`
836
+ `/model`, `/llm-context`, `/thinking`, `/reasoning-history` and `/toolkit` ask before a change that makes the server
837
+ read the conversation again: a switch to another model (a plain name, `--default`, `--alias N`, `clear`; the new model
838
+ has no cache of the conversation), `forget` turned on or off and a layer with applied stubs turned off ("LLM context:
839
+ a session's own strategy"), Gemma's thinking switch, a remote chat host's thinking fields ("Thinking"), a change to or
840
+ from `all` once an earlier reply has thinking ("Reasoning history"), and any change to the declared tools, which start
841
+ every request ("Toolkits"). They ask only when what the next turn runs under really changes (`/model` naming the model
842
+ it already runs, by its resolved ref, doesn't ask) and the session has a model reply. A `/model` name is checked
843
+ first: an unknown host or a bad alias is an error at once, not a question.
844
+
845
+ - The reply says what it costs and changes nothing yet. When known, it estimates the reread size: the whole
846
+ conversation for full-prefix changes, or from the first changed reply for reasoning history. On `api: anthropic`,
847
+ a full-prefix change also says preserved thinking in replies is dropped from then on.
848
+ - `Nothing changed yet: send /thinking low --yes to apply.` names the line that applies it.
842
849
  - `--yes` (or `-y`, anywhere after the command) applies it at once.
843
850
  - The terminal (the REPL and an attached TUI) puts the `--yes` line in the next input: Enter applies it.
844
851
  - The web's reply bubble has an **Apply (restarts the cache)** button. The session bar's chips are already an explicit
@@ -846,8 +853,9 @@ reply has thinking ("Reasoning history"), and any change to the declared tools,
846
853
  the button is gone after a reload.
847
854
  - Only a person at a web tab or a chi TUI is asked. `chi send ID "/thinking low"`,
848
855
  `chi -p "/thinking low" --non-interactive`, lines piped into the REPL, a delegate, a plugin and a card's action
849
- apply directly, since nobody would see the question; so do the start flags (`chi --thinking` on a resumed or
850
- attached session sends `/thinking LEVEL --yes`). A plain `chi -p` opens the REPL, which asks.
856
+ apply directly, since nobody would see the question; so do the start flags (`chi --thinking`, `--model` and
857
+ `--llm-context` on a resumed or attached session send `/thinking LEVEL --yes`, `/model NAME --yes` and
858
+ `/llm-context … --yes`). A plain `chi -p` opens the REPL, which asks.
851
859
 
852
860
  ## Llama HTTP Timeouts
853
861
 
@@ -1344,6 +1352,51 @@ The helper reads these from its launch file: after editing them run
1344
1352
  (`$TMUX_TMPDIR/tmux-<uid>`, else `/tmp/tmux-<uid>`) are resolved then and
1345
1353
  frozen in it. See [Desktop helper](desktop.md#agents-in-kitty-and-tmux).
1346
1354
 
1355
+ ## The chi home
1356
+
1357
+ With several Rubies on one machine (mise, rbenv, chruby; a project that pins its own), whichever Ruby started chi
1358
+ used to decide which chi ran: a terminal in a project on Ruby 3.4 woke its session's worker on that Ruby's chi (an
1359
+ older one, or none), chi web's restart could fall off onto another install, and the macOS helper ran the Ruby of the
1360
+ shell it was installed from. The **chi home** is the one Ruby, and its gem path, every chi launch boots, whoever
1361
+ launches it. It is recorded in `~/.config/samagotchi/home.json` (`$XDG_CONFIG_HOME` is honoured):
1362
+
1363
+ ```json
1364
+ {
1365
+ "ruby": "/Users/me/.local/share/mise/installs/ruby/4.0.7/bin/ruby",
1366
+ "gem_home": "/Users/me/.local/share/mise/installs/ruby/4.0.7/lib/ruby/gems/4.0.0",
1367
+ "gem_path": "/Users/me/.gem/ruby/4.0.0:/Users/me/.local/share/mise/installs/ruby/4.0.7/lib/ruby/gems/4.0.0",
1368
+ "mise": "/opt/homebrew/bin/mise",
1369
+ "set_at": "2026-10-29T21:00:00Z",
1370
+ "set_by_version": "0.132.0"
1371
+ }
1372
+ ```
1373
+
1374
+ - **Setting it.** `chi home set` records the Ruby your `chi` runs on and its gem path (a chruby shell's
1375
+ `GEM_HOME`/`GEM_PATH` are part of it: that is where its chi lives); `chi home set --ruby PATH` records another
1376
+ Ruby with its own gem dirs. Either needs samagotchi installed there (`gem install samagotchi` with that Ruby
1377
+ first). Without a home.json, the first `chi bootstrap` or `chi update` records one, once (from an installed chi,
1378
+ never under `bundle exec`): of the desktop helper's Ruby (when its newest chi is at least the one running) and the
1379
+ Ruby chi runs on, the one with the newer chi. Nothing else ever overwrites it.
1380
+ `chi home` shows it; `chi home doctor` checks it (see [CLI](cli.md#commands)).
1381
+ - **What follows it.** Every session worker (whoever starts or wakes it: a terminal, `chi send`, chi web, a
1382
+ delegating session, a restart), chi web's restart and its **Update** button, `chi update` (from another Ruby it
1383
+ runs the home's `chi update`, and installs into the home's gems with the home's `gem`), `chi bootstrap`'s
1384
+ commonmarker install, chi web's "installed; restart" notice and the macOS helper after its next `chi desktop
1385
+ install` or `upgrade`. The boot sets the home's gem path inside Ruby (`Gem.paths`), never in an environment
1386
+ variable: the commands a session runs (`execute`, tasks, `!cmd`, MCP servers) keep the GEM_HOME/GEM_PATH of whoever
1387
+ started the worker, or none. How: [How chi launches itself](architecture.md#how-chi-launches-itself).
1388
+ - **No home, or one that can't boot chi** (its Ruby gone after a Ruby upgrade, samagotchi uninstalled there, a
1389
+ home.json that isn't JSON): each launch uses the Ruby that starts it, as without a home, and the log says why once
1390
+ per process (`home_unusable`, `home_invalid`). After a Ruby upgrade: `gem install samagotchi` with the new Ruby,
1391
+ then `chi home set` from it. A source checkout (`bin/chi`, `bundle exec`) never uses the home: a worktree's
1392
+ `bin/chi` starts its own code.
1393
+ - **A home with an older chi than the one launching**: workers still boot the home (the log says so once,
1394
+ `home_older_than_spawner`), but chi web's restart runs the newest chi it knows outside the home instead
1395
+ (`restart_home_older`): its flags may be ones the older chi doesn't know.
1396
+ - **A home that still fails at boot** (a broken install): the worker writes one `boot_failed` line to the debug log
1397
+ (`log.file`) and exits, rather than leave the spawner waiting.
1398
+ - Each machine has its own home (a remote's is that machine's).
1399
+
1347
1400
  ## Project specific description
1348
1401
 
1349
1402
  If an AGENTS.md file is present in the project root, samagotchi injects its
@@ -1638,6 +1691,12 @@ its own). The first target is a long session such as a day-long coordinator, whe
1638
1691
  and their results stay in the history.
1639
1692
  - **Switching a layer off:** its stubs go out whole again from the next request (a cache break from the first). The
1640
1693
  session keeps the originals and the edits, so turning the layer back on brings the same stubs back.
1694
+ - **Asks first:** once the session has a model reply, `/llm-context` from a web tab or a TUI asks before the two that
1695
+ break the cache now: `forget` on or off, and a layer with applied stubs turned off (the reply names the
1696
+ `/llm-context … --yes` line; "Changes that restart the prompt cache"). Turning `stale` on, the apply rule and the
1697
+ budget don't ask: they only decide when a batch goes in, and each batch's break comes as designed (`next_request`
1698
+ with staged edits pending moves a break the old rule makes by the end of the next turn anyway). The chip's Set and
1699
+ `--llm-context` on an attached or resumed session send `--yes`.
1641
1700
  - **Where to see it:** `/llm-context` (each value and where it came from: `the session`, `models: <key>`,
1642
1701
  `hosts entry '<name>'`, `llm_context.*`), `/stats` (`llm context:`), the turn log (an `llm_context` record per
1643
1702
  turn that runs a layer or whose session set its strategy) and the web's chip. A woken worker's status line counts
data/docs/desktop.md CHANGED
@@ -257,7 +257,9 @@ don't break it. From a checkout it runs **that** checkout's `bin/chi`; installin
257
257
  warning, because the helper stops working once that worktree is removed. After switching between a checkout and a
258
258
  gem install, run `chi desktop upgrade` from the one you now use.
259
259
 
260
- The helper runs the Ruby and chi of **the shell you installed from**, and only `chi desktop install --force` and
260
+ With a [chi home](configuration.md#the-chi-home), `chi desktop install` and `upgrade` make the helper boot the home
261
+ (its Ruby, the newest chi in its gems) whatever shell you run them from. Without one, the helper runs the Ruby and
262
+ chi of **the shell you installed from**, and only `chi desktop install --force` and
261
263
  `chi desktop upgrade` change that: they pick the Ruby and chi of the shell you run them in. `chi update` never
262
264
  repoints it, so running it from a project with another Ruby (or an older chi) leaves the helper where it was. If
263
265
  the Ruby or chi the helper runs is gone (a Ruby upgrade, a removed worktree), `chi update` fails the helper's row
@@ -286,12 +288,19 @@ says the same.
286
288
  Apps started by macOS get a bare environment: no shell rc files, so no rbenv/chruby/mise/asdf and none of your
287
289
  exports. So `install` writes `~/Library/Application Support/Chi Helper/launch.json` with:
288
290
 
289
- - the absolute path of the Ruby running chi and of chi itself (the gem's wrapper, or a checkout's `bin/chi`), as of
290
- the last `chi desktop install` or `upgrade` (`chi update` keeps them);
291
+ - what to run, as of the last `chi desktop install` or `upgrade` (`chi update` keeps it): with a
292
+ [chi home](configuration.md#the-chi-home), the home's boot, `["<home ruby>", "-e", "Gem.paths = {…}; gem
293
+ 'samagotchi', '>= 0.a'; load Gem.bin_path('samagotchi', 'chi')", "--"]` (the helper appends its own arguments
294
+ after `--`); without one, the absolute path of the Ruby running chi and of chi itself (the gem's wrapper, or a
295
+ checkout's `bin/chi`). The helper and `chi update` check only the absolute paths in it;
291
296
  - `LANG=en_US.UTF-8`;
292
- - only these variables, and only when they are set: `XDG_CONFIG_HOME`, `XDG_STATE_HOME`, `GEM_HOME`, `GEM_PATH`,
293
- `RUBYLIB` (a relative `XDG_*` dir made absolute from the install's current folder: the helper starts in `/`).
294
- No tokens and no `SAMAGOTCHI_*` settings go in;
297
+ - only these variables, and only when they are set: `XDG_CONFIG_HOME`, `XDG_STATE_HOME` (a relative one made
298
+ absolute from the install's current folder: the helper starts in `/`). No tokens and no `SAMAGOTCHI_*` settings
299
+ go in, and never `RUBYLIB`. `GEM_HOME` and `GEM_PATH` go in only without a chi home (a `[ruby, chi]` launch,
300
+ whose chi may be found only through them, as under chruby): the home's boot sets its gem path itself, and they
301
+ would reach every command the helper's sessions run (a project's `bundle exec` on the wrong gems). A launch file
302
+ from an older chi loses `RUBYLIB` at the next `chi update`, and `GEM_HOME`/`GEM_PATH` once it boots the chi home
303
+ (`chi desktop upgrade` moves it to the home);
295
304
  - `PATH`: the shell's PATH when the file is written, with only absolute folders, in order, each once. The helper's
296
305
  chi, the sessions it starts and their `execute` commands can find the tools your terminal finds (mise, Homebrew,
297
306
  `codex`, `node`);
data/docs/guardrails.md CHANGED
@@ -4,7 +4,7 @@ Every tool call the model makes passes one check before it runs, in both
4
4
  loops (native and chat hosts). The verdict is **allow**, **ask** or
5
5
  **deny**; the strictest vote wins, and a deny can't be undone by a later
6
6
  voter. Of two asks the first one names the rule, except a rule only the
7
- user may allow (`chi-config`, `chi-hooks`, `shell-touches-chi`,
7
+ user may allow (`chi-config`, `chi-home`, `chi-hooks`, `shell-touches-chi`,
8
8
  `chi-context-cmd`, `chi-broadcast`): it takes over, and only the scopes both asks offer
9
9
  are offered.
10
10
 
@@ -215,7 +215,7 @@ rules off: `guardrails: {disable: [write-outside-repo, git-outside-repo]}`.
215
215
 
216
216
  Whatever the setting, a parent can't allow a call on chi's own files: a
217
217
  `write`, `edit` or `execute` on the config dir (config.yml, installed bundles'
218
- rules), the hooks dir or the approval store, by its rule (`chi-config`,
218
+ rules), the hooks dir or the approval store, by its rule (`chi-config`, `chi-home`,
219
219
  `chi-hooks`, `shell-touches-chi`), its paths or its command. "Allow once" on a
220
220
  config.yml rewrite would allow everything from then on, so those questions are
221
221
  the user's alone (`user_only`): `chi answer` and the worker refuse the allow
@@ -280,7 +280,7 @@ Built in, for `write`, `edit` and `memory_write` (symlinks resolved; see
280
280
  - deny: the approval store's dir, installed bundles (`memories/.bundles/`),
281
281
  and [attached context](context.md) sources (`<state dir>/context/`: a
282
282
  source's command runs later, outside the gate; `chi context` changes them);
283
- - ask (once or for the session): `config.yml` and the plain hooks dir.
283
+ - ask (once or for the session): `config.yml`, `home.json` (the [chi home](configuration.md#the-chi-home): the Ruby every chi launch boots) and the plain hooks dir.
284
284
 
285
285
  `execute` can still reach them; the guardrails bundle asks about shell
286
286
  commands that name them.
@@ -133,8 +133,9 @@ append-only within a process, so what changes the prefix is:
133
133
  1. **A system-prompt rebuild** (`SystemPrompt#build` is cached per process and key; `SystemPrompt#reset!` drops it):
134
134
  a new process (`--resume`, a respawn after `session.idle_exit_minutes`, a crash) after a memory index line, an
135
135
  AGENTS.md, an appended file, a model note or a bundle memory changed; `/model` (the tail's `Model:` line, its
136
- overlays and notes); `/thinking` (another key); a toolkit or profile change; a plugin's `tools_changed!`; the
137
- session's first participant joining or last leaving (the tail's participants line, participants.md).
136
+ overlays and notes); `/thinking` (another key); a toolkit or profile change; a plugin's `tools_changed!` or
137
+ `prompt_changed!` (its prompt section's text, plugins.md); the session's first participant joining or last
138
+ leaving (the tail's participants line, participants.md).
138
139
  2. **A tool set change**: the same triggers, plus MCP lines that differ on a respawn.
139
140
  3. **History edits by design**: the `llm_context` `stale`/`forget` stubs, and the image cut moving a batch.
140
141
 
@@ -832,10 +832,10 @@ answer is stripped from prefill + response, so the reasoning never lands in it).
832
832
  persistent.
833
833
  5. **A stable system prompt for the cache.** `SystemPrompt#build` caches the prompt per Engine, keyed by
834
834
  `[chat, thinking, layers]` (chat/native, the thinking level, the turn's LLM context layers), and is reset
835
- only on a model switch, a tools change, a profile change or a toolkit change (`Engine#apply_toolkit!`). The
836
- stable part (base prompt, the toolkit's not-loaded line, rg guidance, identity, model notes, preloaded memories,
837
- AGENTS.md, appended files, the toolkit's kit prompt, memory indexes) comes before the volatile tail (model,
838
- working directory, session).
835
+ only on a model switch, a tools change, a plugin's `prompt_changed!` (`Engine#prompt_changed!`), a profile
836
+ change or a toolkit change (`Engine#apply_toolkit!`). The stable part (base prompt, the toolkit's not-loaded line,
837
+ rg guidance, identity, model notes, preloaded memories, AGENTS.md, appended files, the toolkit's kit prompt, the
838
+ plugins' prompt sections, memory indexes) comes before the volatile tail (model, working directory, session).
839
839
  prompt-caching.md covers this in detail.
840
840
 
841
841
  ## Key files
@@ -375,7 +375,10 @@ fields: a field added to an event later reaches nobody until it is named there.
375
375
  so the owner's `!` line and its output, a delegate's report (a wake turn's too), and the notes chi adds (a declined
376
376
  Continue) never show. A turn no person sent (its record's `automatic`, `SessionMetrics`: a task's or a plugin's,
377
377
  read from analytics.json and the live worker's records; the running turn's by its start; a delegate child's first
378
- turn, its parent's task) shows as an automatic turn without its prompt, as the stream does. A raw loop's saved
378
+ turn, its parent's task) shows as an automatic turn without its prompt, as the stream does; so does a wake turn's
379
+ start (`.wake_start`: the delegate report or the context note a wake turn opens with is dropped, its `turn_id` and
380
+ `at` kept), so its answer is never read as one more reply of the turn before (Verify, verdict cards and claim
381
+ links group by `[data-turn-id]`). A raw loop's saved
379
382
  reply is cut before the display reads it (`.visible_raw`): what came before a bare `</think>` and everything from
380
383
  an unclosed thought or tool call on, which the display would only untag. Each
381
384
  prompt carries its author and an image count; replies their text and their step's tool rows. Notes, steers and
@@ -428,6 +431,13 @@ fields: a field added to an event later reaches nobody until it is named there.
428
431
  After the presets comes the built-in **Verify** (`verify_preset.js`, on the owner's page too): the quote, then
429
432
  "Verify this claim against the code. If this session's context doesn't settle it, say so. End with a line
430
433
  `Verdict: confirmed|refuted|unclear — <one-line reason>`." It fills the box like any preset and never sends.
434
+ It is offered only where the Engine will take the claim (`verify_target.js`, the bar's `offeredPreset`): a
435
+ selection in the final answer of an ended turn, the last answer bubble (the owner's `.bubble.output` that isn't a
436
+ delegate report's reply; a participant's last `.p-msg.reply > .p-bubble`) between the turn's opening
437
+ (`[data-turn-id]`) and the next one (or, on the owner's page, a context note: a wake turn opens with one; a
438
+ participant's page gets a wake turn's opening as an automatic turn).
439
+ Anywhere else (an earlier reply, a step, a prompt, a line merged mid-turn, the Plan, the running turn) the button
440
+ is hidden and the bar keeps its other actions.
431
441
  - **Deep links to a claim** (`claim_link.js`). The owner selects text in a turn's answer, step or own message and
432
442
  Annotate's **Copy link** copies `<base>/#s=<id>&t=<turn8>&q=<quote>&p=<prefix>`: `base` the participants list's
433
443
  `link_base` (`ParticipantsAdmin#participant_base`: `web.public_url`'s origin, else the LAN address, else the Host),
@@ -454,13 +464,18 @@ fields: a field added to an event later reaches nobody until it is named there.
454
464
  with the submitted turn, without changing its prompt text. A Verify turn that fails fast and is rolled back hands
455
465
  the claim back with its prompt (`prompt_restored`'s `verify`), so the owner's resend from the composer is a Verify
456
466
  turn again. Before the Engine stamps the anchor or records a verdict, it checks that the source turn exists and
457
- its assistant reply contains the quote. Matching is case-sensitive, collapses whitespace, and strips common
467
+ its final assistant reply (`AnswerTail`: the turn's last assistant message with text) contains the quote. Matching is case-sensitive, collapses whitespace, and strips common
458
468
  Markdown presentation (links, headings, list/blockquote prefixes, emphasis and code delimiters) from both sides;
459
- this matches the rendered text the page selects without treating different casing as the same claim. A fresh child
469
+ this matches the rendered text the page selects without treating different casing as the same claim. The quote may
470
+ also be in the answer as the pages show it (`Engine#verify_quote_in?`, `ParticipantView::Redact.text`: the session's
471
+ folder relative, home `~`, secret shapes `[redacted]`): a participant's page has only that text, and the owner's
472
+ page quotes it the same way (`claimOpts()`, `normalizeClaim`; `spec/fixtures/redact_cases.json` keeps the two
473
+ sides alike), so a claim naming a path is taken on both. A fresh child
460
474
  checks the same anchor against its parent's history. A completed Verify reply whose final non-empty line has
461
475
  a valid `Verdict: confirmed|refuted|unclear — <reason>` appends a verdict to the session. Both pages place its card
462
- after the source turn, name its author, show the reason and quote, and link to the checking turn; a live completion
463
- adds the card without a reload. The participant view receives only the card fields through its allowlist, with the
476
+ in the source turn, right after the bubble that holds the quote (the answer's, matched as a claim link reads the
477
+ page; a quote not found yet goes at the turn's end), name its author, show the reason and quote, and link to the
478
+ checking turn; a live completion adds the card without a reload. The participant view receives only the card fields through its allowlist, with the
464
479
  quote and reason redacted by the view's normal rules, never the full reply.
465
480
  - **Verify fresh** (`VerifyFresh`, `verdict_fresh.js`). An `unclear` card has a **Verify fresh** button (the owner's
466
481
  page always; a participant's while `can_comment`, i.e. while their grant could run a turn now; never in the owner's
@@ -520,7 +535,9 @@ fields: a field added to an event later reaches nobody until it is named there.
520
535
  `:verdict_recorded`; chi web shows the ones still waiting (`VerifyFresh.verdicts_of`: the summary, the review
521
536
  data). The card shows "Verifying fresh…" while the child runs (the summary's `verify_fresh` `{of, child_id}`,
522
537
  the review data's `fresh_running`, ids only) and the fresh verdict as a `fresh: ✅ confirmed — …` line on the same
523
- card. The participant view passes `fresh` and `of`, never the child's id (a participant can't open it). No push
538
+ card. The original stays unclear, so the button stays, as **Verify fresh again**: each press is another paid
539
+ child (a participant's against their cap). The participant view passes `fresh` and `of`, never the child's id (a
540
+ participant can't open it). No push
524
541
  for a fresh verdict yet (`Attention` pushes a verdict at a turn's end).
525
542
  - **The comment box** is the owner's composer (`composer_mount.js`, styled by the shared `composer.css`), mounted by
526
543
  `participant.js` with a subset on. It has: the height that grows with the text, the grip (drag to resize,