samagotchi 0.153.0 → 0.154.1

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 (226) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +42 -1
  3. data/README.md +2 -3
  4. data/bin/chi +23 -24
  5. data/docs/architecture.md +30 -33
  6. data/docs/broadcast.md +5 -5
  7. data/docs/bundles.md +9 -12
  8. data/docs/cli.md +82 -96
  9. data/docs/configuration.md +27 -26
  10. data/docs/context.md +3 -3
  11. data/docs/desktop.md +1 -1
  12. data/docs/guardrails.md +8 -10
  13. data/docs/hooks.md +9 -9
  14. data/docs/internals/attached-context.md +2 -2
  15. data/docs/internals/background-tasks.md +3 -4
  16. data/docs/internals/block-renderers.md +4 -0
  17. data/docs/internals/bridge.md +21 -8
  18. data/docs/internals/context-telemetry.md +1 -1
  19. data/docs/internals/engine.md +33 -7
  20. data/docs/internals/objectives.md +6 -5
  21. data/docs/internals/participants.md +7 -7
  22. data/docs/internals/prompt-caching.md +4 -2
  23. data/docs/internals/remote-sessions.md +7 -7
  24. data/docs/internals/web-frontend.md +2 -2
  25. data/docs/internals/web-push.md +1 -1
  26. data/docs/memory.md +2 -2
  27. data/docs/plugins.md +23 -28
  28. data/docs/sessions.md +24 -24
  29. data/docs/sub-agent.md +2 -2
  30. data/docs/system-one.md +1 -1
  31. data/docs/testing.md +31 -6
  32. data/lib/samagotchi/answer_text.rb +33 -0
  33. data/lib/samagotchi/bridge/card_places.rb +56 -7
  34. data/lib/samagotchi/bridge/card_store.rb +24 -9
  35. data/lib/samagotchi/bridge.rb +52 -32
  36. data/lib/samagotchi/bridge_client.rb +19 -14
  37. data/lib/samagotchi/broadcast/recipients.rb +2 -2
  38. data/lib/samagotchi/broadcast/triage.rb +1 -1
  39. data/lib/samagotchi/broadcast_command.rb +5 -5
  40. data/lib/samagotchi/bundle_command/try/command.rb +1 -1
  41. data/lib/samagotchi/bundle_command/try/run.rb +1 -1
  42. data/lib/samagotchi/bundle_command/try/trace.rb +1 -1
  43. data/lib/samagotchi/bundle_command.rb +2 -2
  44. data/lib/samagotchi/bundles/btw/manifest.yml +2 -2
  45. data/lib/samagotchi/bundles/btw/plugin.rb +1 -1
  46. data/lib/samagotchi/bundles/coordinator/manifest.yml +2 -2
  47. data/lib/samagotchi/bundles/coordinator/plugin.rb +3 -2
  48. data/lib/samagotchi/bundles/decision-card/manifest.yml +4 -4
  49. data/lib/samagotchi/bundles/decision-card/plugin.rb +1 -9
  50. data/lib/samagotchi/bundles/dev/manifest.yml +2 -2
  51. data/lib/samagotchi/bundles/github-pr/manifest.yml +2 -2
  52. data/lib/samagotchi/bundles/github-pr/plugin.rb +3 -3
  53. data/lib/samagotchi/bundles/skills/manifest.yml +2 -2
  54. data/lib/samagotchi/bundles/skills/plugin.rb +3 -2
  55. data/lib/samagotchi/bundles/system/config_modification_protocol.md +3 -4
  56. data/lib/samagotchi/bundles/system/manifest.yml +3 -3
  57. data/lib/samagotchi/bundles/system/self_map.md +1 -1
  58. data/lib/samagotchi/child_move.rb +3 -3
  59. data/lib/samagotchi/commands/registry.rb +6 -6
  60. data/lib/samagotchi/composer_route.rb +4 -5
  61. data/lib/samagotchi/config.rb +14 -12
  62. data/lib/samagotchi/context_candidate_choice.rb +1 -1
  63. data/lib/samagotchi/context_candidates.rb +4 -3
  64. data/lib/samagotchi/continue_offer.rb +1 -1
  65. data/lib/samagotchi/debug_log.rb +1 -1
  66. data/lib/samagotchi/degrade.rb +75 -0
  67. data/lib/samagotchi/desktop/macos/ChiRunner.swift +3 -3
  68. data/lib/samagotchi/engine/cards.rb +87 -0
  69. data/lib/samagotchi/engine/context_judge.rb +138 -0
  70. data/lib/samagotchi/engine/events.rb +131 -0
  71. data/lib/samagotchi/engine/guardrails.rb +87 -0
  72. data/lib/samagotchi/engine/hooks.rb +119 -0
  73. data/lib/samagotchi/engine/messages.rb +124 -0
  74. data/lib/samagotchi/engine/model_settings.rb +127 -0
  75. data/lib/samagotchi/engine/models.rb +261 -0
  76. data/lib/samagotchi/engine/objectives.rb +116 -0
  77. data/lib/samagotchi/engine/participants.rb +86 -0
  78. data/lib/samagotchi/engine/plugins.rb +208 -0
  79. data/lib/samagotchi/engine/questions.rb +98 -0
  80. data/lib/samagotchi/engine/recap.rb +130 -0
  81. data/lib/samagotchi/engine/session.rb +131 -0
  82. data/lib/samagotchi/engine/side_requests.rb +135 -0
  83. data/lib/samagotchi/engine/steering.rb +134 -0
  84. data/lib/samagotchi/engine/toolkit.rb +269 -0
  85. data/lib/samagotchi/engine/turn_end.rb +180 -0
  86. data/lib/samagotchi/engine/turn_helpers.rb +160 -0
  87. data/lib/samagotchi/engine/verify.rb +153 -0
  88. data/lib/samagotchi/engine.rb +62 -2646
  89. data/lib/samagotchi/engine_snapshots.rb +9 -8
  90. data/lib/samagotchi/grants.rb +575 -0
  91. data/lib/samagotchi/guardrail_wiring.rb +2 -2
  92. data/lib/samagotchi/guardrails/context.rb +2 -3
  93. data/lib/samagotchi/guardrails/parent_approvals.rb +2 -2
  94. data/lib/samagotchi/guardrails/parent_policy.rb +2 -2
  95. data/lib/samagotchi/hook_routes.rb +3 -3
  96. data/lib/samagotchi/idle_recap.rb +7 -6
  97. data/lib/samagotchi/idle_reminders.rb +3 -4
  98. data/lib/samagotchi/iteration_limit.rb +2 -2
  99. data/lib/samagotchi/kernel_loop.rb +13 -13
  100. data/lib/samagotchi/launch_mode.rb +13 -32
  101. data/lib/samagotchi/level_setting_command.rb +3 -2
  102. data/lib/samagotchi/llm/chat_loop.rb +3 -1
  103. data/lib/samagotchi/llm_context_command.rb +3 -2
  104. data/lib/samagotchi/log.rb +7 -7
  105. data/lib/samagotchi/log_line.rb +1 -1
  106. data/lib/samagotchi/log_path.rb +1 -1
  107. data/lib/samagotchi/note_command.rb +1 -1
  108. data/lib/samagotchi/note_delivery.rb +18 -8
  109. data/lib/samagotchi/objectives.rb +24 -3
  110. data/lib/samagotchi/objectives_check.rb +8 -27
  111. data/lib/samagotchi/objectives_command.rb +4 -69
  112. data/lib/samagotchi/objectives_edit.rb +87 -0
  113. data/lib/samagotchi/output_formatter.rb +7 -1
  114. data/lib/samagotchi/owner_lock.rb +7 -1
  115. data/lib/samagotchi/parent_answers_command.rb +5 -4
  116. data/lib/samagotchi/participant_exposure.rb +42 -0
  117. data/lib/samagotchi/participant_mode.rb +1 -1
  118. data/lib/samagotchi/participant_name.rb +1 -1
  119. data/lib/samagotchi/participants.rb +17 -17
  120. data/lib/samagotchi/participants_watch.rb +1 -1
  121. data/lib/samagotchi/plugin/api.rb +3 -2
  122. data/lib/samagotchi/plugin/context.rb +21 -7
  123. data/lib/samagotchi/plugin/peer.rb +2 -1
  124. data/lib/samagotchi/plugin/sessions.rb +6 -4
  125. data/lib/samagotchi/plugin_tasks.rb +1 -2
  126. data/lib/samagotchi/private_files.rb +29 -0
  127. data/lib/samagotchi/project_env.rb +2 -2
  128. data/lib/samagotchi/question_desk.rb +8 -7
  129. data/lib/samagotchi/recap_command.rb +2 -1
  130. data/lib/samagotchi/recap_setup.rb +1 -1
  131. data/lib/samagotchi/recap_store.rb +1 -1
  132. data/lib/samagotchi/redact.rb +86 -0
  133. data/lib/samagotchi/reminder_queue.rb +2 -2
  134. data/lib/samagotchi/remote_attach_command.rb +1 -1
  135. data/lib/samagotchi/reply_wait/poll.rb +2 -2
  136. data/lib/samagotchi/review_start.rb +1 -1
  137. data/lib/samagotchi/run_options.rb +6 -6
  138. data/lib/samagotchi/self_report.rb +42 -39
  139. data/lib/samagotchi/send_command/busy.rb +1 -1
  140. data/lib/samagotchi/send_command.rb +4 -1
  141. data/lib/samagotchi/session.rb +11 -2
  142. data/lib/samagotchi/session_access/contract.rb +3 -3
  143. data/lib/samagotchi/session_access/local.rb +9 -9
  144. data/lib/samagotchi/session_access/remote.rb +17 -7
  145. data/lib/samagotchi/session_access.rb +4 -4
  146. data/lib/samagotchi/session_archive_command.rb +2 -2
  147. data/lib/samagotchi/session_chain.rb +8 -6
  148. data/lib/samagotchi/session_commands.rb +45 -48
  149. data/lib/samagotchi/session_continue.rb +1 -1
  150. data/lib/samagotchi/session_delete_command.rb +4 -4
  151. data/lib/samagotchi/session_manager.rb +67 -49
  152. data/lib/samagotchi/session_metrics.rb +2 -2
  153. data/lib/samagotchi/session_model_settings.rb +3 -2
  154. data/lib/samagotchi/session_participants.rb +1 -1
  155. data/lib/samagotchi/session_retention.rb +27 -7
  156. data/lib/samagotchi/sessions_command.rb +4 -4
  157. data/lib/samagotchi/share_command.rb +10 -10
  158. data/lib/samagotchi/steer.rb +13 -2
  159. data/lib/samagotchi/stream_event.rb +22 -0
  160. data/lib/samagotchi/system_prompt.rb +154 -145
  161. data/lib/samagotchi/task_watch.rb +1 -1
  162. data/lib/samagotchi/terminal_ui/attach_launcher.rb +72 -10
  163. data/lib/samagotchi/terminal_ui/attached_loop/composer.rb +12 -9
  164. data/lib/samagotchi/terminal_ui/attached_loop/exit_commands.rb +16 -0
  165. data/lib/samagotchi/terminal_ui/attached_loop/questions.rb +2 -3
  166. data/lib/samagotchi/terminal_ui/attached_loop.rb +17 -8
  167. data/lib/samagotchi/terminal_ui/attached_view.rb +1 -11
  168. data/lib/samagotchi/terminal_ui/event_renderer.rb +3 -5
  169. data/lib/samagotchi/terminal_ui/formatting.rb +7 -7
  170. data/lib/samagotchi/terminal_ui/input_support.rb +17 -22
  171. data/lib/samagotchi/terminal_ui/join_replay.rb +16 -12
  172. data/lib/samagotchi/terminal_ui/line_reader.rb +2 -2
  173. data/lib/samagotchi/terminal_ui/live_region.rb +2 -2
  174. data/lib/samagotchi/terminal_ui/log_tail.rb +135 -0
  175. data/lib/samagotchi/terminal_ui/one_shot_sink.rb +2 -2
  176. data/lib/samagotchi/terminal_ui/plain_surface.rb +1 -1
  177. data/lib/samagotchi/terminal_ui/question_prompt.rb +4 -5
  178. data/lib/samagotchi/terminal_ui/reline_seam.rb +2 -12
  179. data/lib/samagotchi/terminal_ui/status_row.rb +6 -14
  180. data/lib/samagotchi/terminal_ui.rb +142 -1387
  181. data/lib/samagotchi/title_command.rb +2 -2
  182. data/lib/samagotchi/tool_runner.rb +15 -16
  183. data/lib/samagotchi/toolkit_command.rb +2 -1
  184. data/lib/samagotchi/tools/delegate.rb +3 -1
  185. data/lib/samagotchi/tools/delegate_cursor.rb +3 -3
  186. data/lib/samagotchi/tools/delegate_wait.rb +1 -1
  187. data/lib/samagotchi/tools/objectives_tool.rb +2 -2
  188. data/lib/samagotchi/tools/send_note.rb +2 -1
  189. data/lib/samagotchi/turn_endings.rb +2 -2
  190. data/lib/samagotchi/turn_flow.rb +11 -7
  191. data/lib/samagotchi/update_hint.rb +2 -2
  192. data/lib/samagotchi/version.rb +1 -1
  193. data/lib/samagotchi/web/app.rb +42 -51
  194. data/lib/samagotchi/web/message_display.rb +7 -0
  195. data/lib/samagotchi/web/participant_access.rb +2 -2
  196. data/lib/samagotchi/web/participant_review.rb +5 -5
  197. data/lib/samagotchi/web/participant_stream_filter.rb +8 -8
  198. data/lib/samagotchi/web/participant_view.rb +2 -82
  199. data/lib/samagotchi/web/participants_admin.rb +1 -1
  200. data/lib/samagotchi/web/public/block_host.js +35 -8
  201. data/lib/samagotchi/web/public/block_renderers.css +9 -5
  202. data/lib/samagotchi/web/public/card_stamps.js +27 -0
  203. data/lib/samagotchi/web/public/cards_place.js +5 -3
  204. data/lib/samagotchi/web/public/chains.js +2 -2
  205. data/lib/samagotchi/web/public/claim_link.js +4 -4
  206. data/lib/samagotchi/web/public/composer_mode.js +1 -1
  207. data/lib/samagotchi/web/public/format.js +4 -3
  208. data/lib/samagotchi/web/public/turn_html.js +8 -4
  209. data/lib/samagotchi/web/push/store.rb +1 -1
  210. data/lib/samagotchi/web/session_access_routes.rb +13 -4
  211. data/lib/samagotchi/web/session_control.rb +12 -8
  212. data/lib/samagotchi/web/session_create.rb +1 -1
  213. data/lib/samagotchi/web/session_hub.rb +2 -2
  214. data/lib/samagotchi/web/session_show.rb +6 -2
  215. data/lib/samagotchi/web/session_summary.rb +1 -1
  216. data/lib/samagotchi/worker.rb +103 -9
  217. data/lib/samagotchi/worker_link.rb +3 -3
  218. data/lib/samagotchi/working_set_command.rb +3 -2
  219. data/lib/samagotchi.rb +0 -1
  220. metadata +31 -7
  221. data/lib/samagotchi/pending_input_queue.rb +0 -55
  222. data/lib/samagotchi/terminal_ui/between_turns.rb +0 -138
  223. data/lib/samagotchi/terminal_ui/repl_input.rb +0 -152
  224. data/lib/samagotchi/web/grants.rb +0 -575
  225. data/lib/samagotchi/web/participant_exposure.rb +0 -44
  226. data/lib/samagotchi/web/private_files.rb +0 -31
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e9dd8da2f6f95806fccc0df5dad4844525947650b92589461adcb70b8bcdf2d7
4
- data.tar.gz: a1457568c9d119b661d025be9e39989a33593666d668b328c3cd8528e451aa55
3
+ metadata.gz: 9533994f61b5607aef4d2dc6318cd6e885a0331c163643bd06d3c16f5e6f03c0
4
+ data.tar.gz: b768811c50bb587fcf4d16696ab69b857c75168067fd521270d871954169874e
5
5
  SHA512:
6
- metadata.gz: 6ed8fbbd7439b3ff95cb6eb251edf5635812cff0579928469a575bbb4bdc190e14ff6959a2f49eb627f127f711c1782c62c99379a2130433e057d0a55dd2e359
7
- data.tar.gz: 82b22635aad92e8edb672e61ac0eed1c461c1c81330bfde64ac09cd8c969183e37f9420495cbb6b0fbe0624f9a552a17af9cb70a2707b0f483084d25fb10d936
6
+ metadata.gz: 2064776b06d42184107924bc44391f46681d755437e2c98a2e7c24205e900aba33bd8d3d792c7cea4dd6bdbf2813870395112db7315dbec33f92e198267c4ddc
7
+ data.tar.gz: a826305fa133e9ca4d1bd62e112ca7464fcf932f91292dc4112286e7f8f501c167fc18ccfeeb12dd24bec649e24636c810a715417cac45f454a19b4ba56f2b05
data/CHANGELOG.md CHANGED
@@ -8,6 +8,45 @@ and commands may change between minor versions. How releases are made:
8
8
 
9
9
  ## [Unreleased]
10
10
 
11
+ ## [0.154.1] - 2026-11-07
12
+
13
+ ### Fixed
14
+
15
+ - chi web refuses a scratch session's page and stream (409 `scratch`, in the words every other client gets) when a tab is opened at its id by hand, and a scratch worker counts only its terminal's stream: such a tab no longer keeps the worker up after its terminal is killed.
16
+ - A card in chi web comes back where it was after a reload: the page finds the turn it came after (or `/continue no`'s reason line) by its id instead of counting the turns drawn after it, so the page and the worker can no longer disagree on the count.
17
+ - A Qwen model's turn that was asked to finish an open tool call no longer splits in two after a reload of chi web: the request to finish it is part of the turn, drawn as nothing, as it was live.
18
+ - chi web starting just as `chi scratch` did no longer deletes the new scratch session before its worker takes it (the worker crashed with "Session not found" and the terminal said the Bridge did not start in time): the retention sweep, `chi sessions prune` and `clean` leave an unowned scratch session alone for 30 s after its last save.
19
+ - A terminal joining a session (`chi --attach`, `--resume`) shows the last turn's own prompt instead of a Qwen model's request to finish an open tool call, with the input merged into that turn on its `input>` lines; the idle recap no longer counts either as a turn of its own.
20
+ - A turn no longer fails when a plugin changes its tools or prompt section (or a profile change drops the system prompt) at the moment the system prompt is built.
21
+
22
+ Update with `chi update` (btw 0.1.5, coordinator 0.8.1, github-pr 0.6.4, skills 0.1.10: comments only; the desktop helper rebuilds once).
23
+
24
+ ## [0.154.0] - 2026-11-07
25
+
26
+ ### Changed
27
+
28
+ - `chi scratch` in a terminal runs attached, on a session worker of its own that saves nothing (no memory writes, no delegates, approvals for this session only). Ctrl-D, `/detach`, `/exit` or a second Ctrl-C ends it: the worker stops and the session is deleted ("Scratch session deleted."); a worker whose terminal is gone (a killed terminal) deletes it too. `chi send`, chi web and `chi --attach`/`--resume` refuse a scratch session, in one wording. `chi scratch -p TEXT --non-interactive` still runs its turn in this process.
29
+ - `chi -v` runs attached: the terminal shows the session's debug records (raw LLM responses, tool calls and results) above the prompt, and a worker this chi starts logs at debug. A worker that was already running keeps the level it started with, and one line says so. With `--non-interactive`, `-v` still mirrors the records to stderr.
30
+ - A session a `chi -p … --non-interactive` run has open is refused as "in use by a one-turn chi --non-interactive run or an older chi's terminal" (`chi send`, `chi note`, `chi sessions delete`/`archive`, chi web, the delegate tools), not as "open in a chi REPL".
31
+ - `chi bundle upgrade --agent` merges the conflicts in the attached terminal.
32
+ - chi now writes a warning to the debug log when part of its work falls back after an error (a system prompt section left out, a Bridge route or a chi web answer given empty, a session command's lookup) instead of dropping it silently: once per process for each kind, later ones at `debug`.
33
+
34
+ ### Removed
35
+
36
+ - The in-process REPL: an interactive `chi` (plain, `-p`, `--resume`, `--attach`) always runs attached to its session's worker; `--non-interactive` runs its one turn in this process as before.
37
+ - The `--shared` and `--no-shared` flags (they are an unknown option now) and the `session.shared` setting (config.yml warns "removed: chi always runs attached"; `SAMAGOTCHI_SESSION_SHARED` is ignored).
38
+ - The `:repl` interface: a hook event's `interface` and a plugin's `ctx.frontend` are never `:repl` (a bundle that checks for it never matches).
39
+
40
+ ### Fixed
41
+
42
+ - `chi scratch`: a terminal whose stream drops and reconnects no longer has its turn cancelled and its session deleted by the worker; the worker waits about 25 s with no stream before it takes the terminal as gone.
43
+ - chi web: a diagram drawn by a block renderer is usable without a mouse: a screen reader hears that its source is behind the "Show the source" button, and a button that shows on keyboard focus zooms it to full size and back.
44
+ - The objectives tool refuses a proposal its card's Apply would refuse (an add or reword whose text is only a status like `[done]` or only `(done when: …)`, or `done` for a dropped objective), so the model hears why instead of leaving a card that can't apply.
45
+ - A thought the model never closed no longer reaches the continue note's "Its last answer" or decision-card's `/short`: both read the answer as you saw it, with the one rule a Check this record uses (a bundle gets it as `ctx.last_answer`). decision-card 0.2.1.
46
+ - chi web: a reply that is only a thought the model never closed is no longer shown as an answer or taken as the session's last answer.
47
+
48
+ Update with `chi update` (decision-card 0.2.1, the dev profile 0.7.7).
49
+
11
50
  ## [0.153.0] - 2026-11-06
12
51
 
13
52
  ### Added
@@ -5733,7 +5772,9 @@ and long-lived sessions.
5733
5772
  - A macOS desktop helper (`chi desktop install`): a "Send to chi" Service and a
5734
5773
  hotkey panel that send selected text or the clipboard to your sessions.
5735
5774
 
5736
- [Unreleased]: https://github.com/dm1try/samagotchi/compare/v0.153.0...HEAD
5775
+ [Unreleased]: https://github.com/dm1try/samagotchi/compare/v0.154.1...HEAD
5776
+ [0.154.1]: https://github.com/dm1try/samagotchi/compare/v0.154.0...v0.154.1
5777
+ [0.154.0]: https://github.com/dm1try/samagotchi/compare/v0.153.0...v0.154.0
5737
5778
  [0.153.0]: https://github.com/dm1try/samagotchi/compare/v0.152.0...v0.153.0
5738
5779
  [0.152.0]: https://github.com/dm1try/samagotchi/compare/v0.151.0...v0.152.0
5739
5780
  [0.151.0]: https://github.com/dm1try/samagotchi/compare/v0.150.0...v0.151.0
data/README.md CHANGED
@@ -119,7 +119,6 @@ hosts:
119
119
 
120
120
  ```sh
121
121
  chi # interactive session the web UI can join too
122
- chi --no-shared # the plain in-process REPL
123
122
  chi -p "explain lib/" --non-interactive # one turn, print the answer, exit
124
123
  chi --resume <session-id> # continue a saved session
125
124
  chi web --open # web UI: this project's sessions (--scope=all: every one)
@@ -200,7 +199,7 @@ Rules come from `config.yml` (`guardrails:`), installed bundles and hooks;
200
199
  the `guardrails` bundle (in `core`, which `chi bootstrap` installs; else
201
200
  `chi bundle install guardrails`) adds a default set (asks before `git push`,
202
201
  history rewrites, wide `rm -rf`, `curl | sh`, writes outside the repo; denies
203
- writes to `.git/hooks`). You answer in the REPL, the attached TUI or the web:
202
+ writes to `.git/hooks`). You answer in the attached TUI or the web:
204
203
  once, for the session, for the repo, or for the whole rule in the repo.
205
204
  `/guardrails` lists the rules and your approvals. See [Guardrails](docs/guardrails.md).
206
205
 
@@ -209,7 +208,7 @@ once, for the session, for the repo, or for the whole rule in the repo.
209
208
  - [CHANGELOG](CHANGELOG.md): what changed in each release
210
209
  - [Releasing](docs/releasing.md): versions, the changelog, how a release is published
211
210
 
212
- - [CLI and REPL](docs/cli.md): flags, sharing a session, web UI, `/model`, status line
211
+ - [CLI and terminal](docs/cli.md): flags, sharing a session, web UI, `/model`, status line
213
212
  - [Configuration](docs/configuration.md): `config.yml`, hosts, model server APIs, timeouts, retries, logs
214
213
  - [Memory](docs/memory.md): scopes, model-specific overlays and model notes
215
214
  - [Sessions](docs/sessions.md): storage, retention, `chi sessions`
data/bin/chi CHANGED
@@ -139,7 +139,8 @@ if ARGV[0] == "web" && ARGV[1] == "push"
139
139
  end
140
140
 
141
141
  # `chi scratch`: the run options below, for a session that leaves nothing
142
- # behind (TerminalUI scratch:). The word goes before OptionParser sees it.
142
+ # behind (AttachLauncher scratch:; TerminalUI's with --non-interactive). The
143
+ # word goes before OptionParser sees it.
143
144
  scratch = ARGV[0] == "scratch"
144
145
  ARGV.shift if scratch
145
146
 
@@ -192,7 +193,7 @@ end
192
193
 
193
194
  # A scratch session is new, runs here and goes when it ends.
194
195
  if scratch
195
- flag = { resume: "--resume", attach: "--attach", shared: "--shared" }.find { |key, _flag| options[key] }&.last
196
+ flag = { resume: "--resume", attach: "--attach" }.find { |key, _flag| options[key] }&.last
196
197
  if flag
197
198
  warn "Error: chi scratch starts a new session in this terminal and keeps nothing; it can't take #{flag}"
198
199
  exit 1
@@ -203,15 +204,19 @@ end
203
204
  # session's own level); a session-starting run's is that session's own
204
205
  # (TerminalUI, AttachLauncher), not a process setting.
205
206
  cli_overrides["thinking.level"] = options[:thinking] if web && options[:thinking]
207
+ # -v: debug records, in this process and in a worker it spawns (Config.cli_env).
208
+ cli_overrides["log.level"] = "debug" if options[:verbose]
206
209
 
207
210
  # Apply CLI precedence: CLI > ENV > file. Workers this chi spawns get
208
211
  # these through their env (Config.cli_env).
209
212
  Samagotchi::Config.reload!(cli_overrides: cli_overrides) unless cli_overrides.empty?
210
213
 
211
214
  # The debug log (Samagotchi::LogPath, level log.level) for every command.
212
- # -v (the plain REPL only): debug records, each mirrored to stderr.
215
+ # -v: debug records; a --non-interactive one-shot mirrors each to stderr,
216
+ # the attached TUI shows its session's above the live region (LogTail).
213
217
  require "samagotchi/log"
214
- Samagotchi::Log.configure(level: options[:verbose] ? :debug : nil, mirror: options[:verbose])
218
+ Samagotchi::Log.configure(level: options[:verbose] ? :debug : nil,
219
+ mirror: options[:verbose] && options[:non_interactive])
215
220
 
216
221
  # chi --remote NAME --attach ID (--resume ID, --dir DIR, -p TEXT): the
217
222
  # attached TUI on that machine's session. Nothing below runs: it checks
@@ -274,8 +279,9 @@ rescue Samagotchi::Session::AmbiguousId => e
274
279
  exit 1
275
280
  end
276
281
 
277
- # A `chi scratch` session a killed REPL left behind would turn into a kept
278
- # one if opened again; the next sweep deletes it.
282
+ # A `chi scratch` session is its terminal's (a live one), or one a killed
283
+ # terminal left behind, which would turn into a kept one if opened again;
284
+ # the next sweep deletes it.
279
285
  %i[resume attach].each do |key|
280
286
  next unless options[key]
281
287
 
@@ -286,8 +292,7 @@ end
286
292
  end
287
293
  next unless leftover
288
294
 
289
- require "samagotchi/launch_mode"
290
- warn "Error: #{Samagotchi::LaunchMode::SCRATCH_LEFTOVER}"
295
+ warn "Error: #{Samagotchi::Session::SCRATCH_REFUSED}"
291
296
  exit 1
292
297
  end
293
298
 
@@ -395,12 +400,7 @@ end
395
400
 
396
401
  chi_update_hint.call
397
402
  require "samagotchi/launch_mode"
398
- launch, launch_note = if scratch
399
- [:repl, nil]
400
- else
401
- Samagotchi::LaunchMode.resolve(options, shared_config: Samagotchi::Config.get("session.shared"))
402
- end
403
- warn launch_note if launch_note
403
+ launch = Samagotchi::LaunchMode.resolve(options)
404
404
 
405
405
  if launch == :attached
406
406
  error = Samagotchi::LaunchMode.attached_conflict(options)
@@ -411,7 +411,7 @@ if launch == :attached
411
411
 
412
412
  require "samagotchi/terminal_ui/attach_launcher"
413
413
  begin
414
- ended = Samagotchi::TerminalUI::AttachLauncher.run(attach: options[:attach], shared: !options[:attach], resume: options[:resume],
414
+ ended = Samagotchi::TerminalUI::AttachLauncher.run(attach: options[:attach], resume: options[:resume],
415
415
  prompt: options[:prompt], model: options[:model],
416
416
  no_interrupt: !!options[:no_interrupt],
417
417
  default_input: !options[:no_default_input],
@@ -423,7 +423,8 @@ if launch == :attached
423
423
  toolkit: options[:toolkit_value],
424
424
  toolkit_flags: options[:toolkit_flags] || [],
425
425
  settings: options[:settings],
426
- parent_answers: options[:parent_answers])
426
+ parent_answers: options[:parent_answers],
427
+ scratch: scratch, verbose: options[:verbose])
427
428
  rescue Samagotchi::TerminalUI::AttachLauncher::Error, Samagotchi::Toolkit::Refused => e
428
429
  warn "Error: #{e.message}"
429
430
  exit 1
@@ -435,13 +436,13 @@ if launch == :attached
435
436
  exit Samagotchi::TerminalUI::AttachLauncher.exit_status(ended)
436
437
  end
437
438
 
439
+ # --non-interactive: the -p prompt's one turn in this process (TerminalUI,
440
+ # the one-shot host); bare, a no-op that creates no session.
438
441
  require "samagotchi/cli/exit"
439
442
  begin
440
443
  ended = Samagotchi::TerminalUI.new(
441
444
  prompt: options[:prompt],
442
445
  session_id: options[:resume],
443
- no_interrupt: options[:no_interrupt] || options[:non_interactive],
444
- no_default_input: options[:no_default_input],
445
446
  memories: options[:memories] || [],
446
447
  muted_memories: options[:muted] || [],
447
448
  llm_context: options[:llm_context] || {},
@@ -451,13 +452,11 @@ begin
451
452
  toolkit_flags: options[:toolkit_flags] || [],
452
453
  settings: options[:settings],
453
454
  parent_answers: options[:parent_answers],
454
- non_interactive: options[:non_interactive],
455
455
  model_name: options[:model],
456
456
  scratch: scratch
457
457
  ).run
458
- # `chi -p X </dev/null`: the turn failed (nothing was sent again); -p
459
- # --non-interactive: the turn ended with no answer or at the iteration
460
- # limit, or Ctrl-C cancelled it.
458
+ # The turn failed, ended with no answer or at the iteration limit, or
459
+ # Ctrl-C cancelled it.
461
460
  exit 1 if %i[turn_failed empty_answer iteration_limit].include?(ended)
462
461
  exit Samagotchi::CLI::Exit::INTERRUPTED if ended == :interrupted
463
462
  rescue Samagotchi::TerminalUI::SessionBusy, Samagotchi::TerminalUI::SessionNotFound, Samagotchi::ModelProfile::MissingModel,
@@ -465,11 +464,11 @@ rescue Samagotchi::TerminalUI::SessionBusy, Samagotchi::TerminalUI::SessionNotFo
465
464
  warn "Error: #{e.message}"
466
465
  exit 1
467
466
  rescue Samagotchi::LLM::ProviderError => e
468
- # -p --non-interactive: the turn failed; its prompt is in the session.
467
+ # The turn failed; its prompt is in the session.
469
468
  warn "Error: #{e.summary}"
470
469
  exit 1
471
470
  rescue Samagotchi::ImageStore::Error => e
472
- # -p --non-interactive: an @path image that can't be used.
471
+ # An @path image that can't be used.
473
472
  warn "Error: #{e.message}"
474
473
  exit 1
475
474
  end
data/docs/architecture.md CHANGED
@@ -10,9 +10,9 @@ A compact visual overview of the current architecture, then the core API in pros
10
10
  │ │
11
11
  ┌────────────────────┴────────────────────┐ ┌───────────────┴────────────────┐
12
12
  │ TerminalUI │ │ Web::App (Rack) │ ← browser UI
13
- │ attached (default): AttachLauncher + │ │ session hub · /api/events │
13
+ │ interactive: AttachLauncher + │ │ session hub · /api/events │
14
14
  │ AttachedLoop, no Engine │ │ /api/* · reads session files │
15
- │ REPL (--no-shared …): its own Engine │ └───────────────┬────────────────┘
15
+ │ --non-interactive: its own Engine │ └───────────────┬────────────────┘
16
16
  └────────────────────┬────────────────────┘ │ App#relay, bridge_get,
17
17
  │ BridgeClient (SSE + HTTP) │ /stream proxy
18
18
  └────────────────────┬────────────────────┘
@@ -60,7 +60,7 @@ A compact visual overview of the current architecture, then the core API in pros
60
60
 
61
61
  ```
62
62
  TerminalUI ── delegates ──▶ Engine
63
- (REPL / render / commands) (pure logic, no terminal)
63
+ (one-shot host) (pure logic, no terminal)
64
64
  ▲ │
65
65
  └────────── on_event: ◀────────────┘
66
66
  (turn_started, turn_completed,
@@ -69,13 +69,14 @@ TerminalUI ── delegates ──▶ Engine
69
69
 
70
70
  - **`Engine`** (`lib/samagotchi/engine.rb`) owns *all* agent logic and knows nothing
71
71
  about the terminal ([internals/engine.md](internals/engine.md)).
72
- - **`TerminalUI`** (`lib/samagotchi/terminal_ui.rb`) owns the REPL and rendering; it
73
- delegates all core work to an `Engine`.
72
+ - **`TerminalUI`** (`lib/samagotchi/terminal_ui.rb`) is the one-shot host: `chi -p TEXT
73
+ --non-interactive` (with `--resume ID` or `chi scratch` too) runs that one turn in this
74
+ process, its answer alone on stdout, and delegates all core work to its `Engine`. Every
75
+ interactive terminal is the attached one (`TerminalUI::AttachLauncher`, `AttachedLoop`).
74
76
  - The `on_event:` seam on `run_turn` exposes raw `KernelLoop` events plus the
75
77
  higher-level turn events, so any new UI can render without terminal coupling.
76
78
  - **`ComposerRoute`** (`lib/samagotchi/composer_route.rb`) decides where a line typed at
77
- either terminal's prompt goes (the REPL's `steer_line` / `run_input_line`, the attached
78
- `AttachedLoop::Composer#submit`): `/cut TEXT` / `/queue TEXT`, a terminal's own word, a session
79
+ the attached terminal's prompt goes (`AttachedLoop::Composer#submit`): `/cut TEXT` / `/queue TEXT`, a terminal's own word, a session
79
80
  command, a typo, a prompt. Each UI keeps what it does with the route. The web's
80
81
  `composer.js#routeComposerLine` decides the same; `spec/fixtures/composer_routes.json`
81
82
  holds the cases both answer (see [testing.md](testing.md)).
@@ -90,7 +91,7 @@ bin/chi ─▶ TerminalUI ─▶ Engine#run_turn ─▶ KernelLoop / ChatLoop
90
91
  (turn started / completed / canceled)
91
92
  ```
92
93
 
93
- That is the REPL; attached (the default) the session's `Worker` calls `Engine#run_turn` and the
94
+ That is a `--non-interactive` one-shot; interactive, the session's `Worker` calls `Engine#run_turn` and the
94
95
  terminal renders the events it gets over the Bridge.
95
96
 
96
97
  ## Layers at a glance
@@ -98,7 +99,7 @@ terminal renders the events it gets over the Bridge.
98
99
  | Layer | Class(es) | Responsibility |
99
100
  |-------|-----------|----------------|
100
101
  | Core | `Samagotchi::Engine` | System prompt, memory injection, tool declarations, session lifecycle, model↔tool loop (`run_turn`). No terminal coupling. |
101
- | UI | `Samagotchi::TerminalUI` | REPL (Reline), rendering, REPL commands. Delegates all core work to an `Engine`. |
102
+ | UI | `Samagotchi::TerminalUI`, `TerminalUI::AttachLauncher` / `AttachedLoop` | `TerminalUI`: the `--non-interactive` one-shot host, its own `Engine`. The attached TUI (every interactive `chi`): a client of the session worker's Bridge, no `Engine`. |
102
103
  | Model loops | `KernelLoop` (via `LLM::NativeBackend`), `LLM::ChatLoop` | The model↔tool loop: raw prompt, or a chat API (OpenAI chat, Anthropic Messages), chosen per host (see below). |
103
104
  | Adapters | `Samagotchi::Client`, `LLM::OpenAIChat`, `LLM::AnthropicMessages`, `LLM::HTTP` | Raw-prompt servers, the OpenAI chat API, Anthropic's Messages API, and the HTTP they share. |
104
105
  | Tools | `lib/samagotchi/tools/*` | Execute, read, edit, write, memory, task_*, web_fetch, delegate/delegate_result, ask_user_question, reminders, send_note, list_sessions, context_read, objectives, forget_outputs, find_tools/call_tool (the tool index), plus runtime/output-guardrails. |
@@ -109,29 +110,27 @@ terminal renders the events it gets over the Bridge.
109
110
 
110
111
  ## Entry points
111
112
 
112
- - `LaunchMode.resolve` picks the terminal's mode. By default (`session.shared: true`)
113
- plain `bin/chi`, `-p` and `--resume ID` run attached, like `--shared`; `--no-shared`,
114
- `session.shared: false`, `--non-interactive` and `--verbose` run the REPL. `--memory`
113
+ - `LaunchMode.resolve` picks the terminal's mode: `:attached` (plain `bin/chi`, `-p`,
114
+ `--resume ID`, `--attach ID`, `-v`) or `:one_shot` (`--non-interactive`). `--memory`
115
115
  and `--mute` are session fields (`preloaded_memory_names`, `muted_memory_names`) the
116
116
  worker reads when it builds its `Engine`; `MutedMemories` filters the prompt's index and
117
117
  the kernel's `memory_read`.
118
- - The REPL → builds `TerminalUI`. `TerminalUI#run` is the single dispatch
119
- for the REPL, `-p`/`--prompt`, `--non-interactive`, and `--resume`.
120
- - Attached (`bin/chi`, `--attach ID`, `--shared [--resume ID]`) → `TerminalUI::AttachLauncher`: no `Engine`
118
+ - One-shot → builds `TerminalUI`: the `-p` prompt's one turn (a new session, `--resume ID`'s or
119
+ `chi scratch`'s) under an `OwnerLock` of kind `"tui"`; bare `--non-interactive` is a no-op.
120
+ - Attached (`bin/chi`, `-p`, `--attach ID`, `--resume ID`) → `TerminalUI::AttachLauncher`: no `Engine`
121
121
  and no `OwnerLock`; finds or starts the session's worker and runs `TerminalUI::AttachedLoop`
122
122
  as a client of its Bridge (`BridgeClient#follow`, `post_turn`, `post_command`, `cancel`, `answer`,
123
123
  `dismiss_question`; opening the SSE connection answers `BridgeClient::StreamOpen::Opened`, `Refused` or `Unreachable`). The worker runs in the session's `working_directory`, so `!cmd` and
124
124
  the tools don't depend on where the terminal attached from.
125
125
  - `bin/chi web` → builds `Web::Server` (Rack+WEBrick on `127.0.0.1:4567`, `--port`/`SAMAGOTCHI_WEB_PORT`, `--open`;
126
126
  `web.host: lan` adds a LAN address, `--new-token` replaces its access token).
127
- - `bin/chi sessions {list,stop,restart,archive,unarchive,delete,prune,clean,stats}` (`SessionsCommand`; not the REPL's `SessionCommands`) → retention & ordering (`SessionRetention`, `updated_at desc`, dry-run, test-only); `stop` is `SessionManager.stop_session(wait:)`, which waits for the worker to release `owner.lock`; `delete` (`SessionDeleteCommand`) is `SessionManager.delete_session(stop:)`, which the TUI's `/exit --delete` and the web's `DELETE /api/sessions/:id` use too.
127
+ - `bin/chi sessions {list,stop,restart,archive,unarchive,delete,prune,clean,stats}` (`SessionsCommand`; not the session's `SessionCommands`) → retention & ordering (`SessionRetention`, `updated_at desc`, dry-run, test-only); `stop` is `SessionManager.stop_session(wait:)`, which waits for the worker to release `owner.lock`; `delete` (`SessionDeleteCommand`) is `SessionManager.delete_session(stop:)`, which the TUI's `/exit --delete` and the web's `DELETE /api/sessions/:id` use too.
128
128
  - Session commands (`chi send`, `answer`, `note`, a session's `context`, `sessions list/stop/restart/archive/unarchive/delete`) →
129
129
  `SessionAccess` (`session_access.rb`): what they ask of a session goes through one backend object,
130
130
  `SessionAccess::Local` (`session_access/local.rb`) on this machine's files and workers; a `--wait`'s pre-send state
131
131
  (cursor, baseline, own turn) is `prepare_wait`'s `WaitStart`. `SessionAccess::Contract` lists which commands and flags
132
132
  run against a remote and which on this machine only.
133
- - In REPL mode `TerminalUI` builds the `Engine` in process (`-p` and `--non-interactive` too);
134
- otherwise the session's `Worker` (`lib/samagotchi/worker.rb`, spawned by `SessionManager`) builds it.
133
+ - A one-shot's `TerminalUI` builds the `Engine` in process; otherwise the session's `Worker` (`lib/samagotchi/worker.rb`, spawned by `SessionManager`) builds it.
135
134
 
136
135
  ## How chi launches itself
137
136
 
@@ -193,7 +192,7 @@ log's last 4 MB). Rows: [configuration.md](configuration.md#checking-it-chi-home
193
192
  ## Session retention & ordering
194
193
 
195
194
  - **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.
196
- - **Single owner:** the process running a session's Engine (worker or in-process TUI) holds a flock on `owner.lock` (`OwnerLock`); a second owner backs off, and the web answers 409 for a TUI-owned session.
195
+ - **Single owner:** the process running a session's Engine (its worker, or a `--non-interactive` one-shot) holds a flock on `owner.lock` (`OwnerLock`); a second owner backs off, and the web answers 409 for a session a one-shot owns.
197
196
  - **Status:** `status` is turn state (`idle`/`running`); liveness is the lock. A stop is the `<uuid>/stopped` marker (`Session.mark_stopped`; a resume removes it), which `Session.load` and `.summary_from_file` read as status `stopped`, so no other process rewrites a worker's session file.
198
197
  - **Retention:** 14 days / 500 cap (env `SAMAGOTCHI_SESSION_RETENTION_DAYS`/`MAX_COUNT`, optional `KEEP_STATUS`), live-owner guard, only when `*.json` present; lazy sweep at most once per `session.sweep_interval_hours` (default 24) from the session hub's full-probe tick (and on `GET /api/sessions`, which the page no longer calls), manual via `bin/chi sessions prune --dry-run`.
199
198
  - **Ordering:** `Session.list(sort:,order:,limit:,offset:)` and `GET /api/sessions?sort=&order=&limit=&offset=` default `updated_at desc`; Web UI sort/filter/pagination.
@@ -207,22 +206,20 @@ agent logic and can be used without any terminal rendering; the UI is a thin lay
207
206
  | Layer | Class | Responsibility |
208
207
  |-------|-------|----------------|
209
208
  | Core | `Samagotchi::Engine` | System prompt, memory injection, tool declarations, session lifecycle, the model↔tool loop (`run_turn`). No terminal coupling. |
210
- | UI | `Samagotchi::TerminalUI` | Interactive REPL (Reline), rendering (ANSI, spinner, status line), REPL commands. Delegates all core work to an `Engine`. |
209
+ | UI | `Samagotchi::TerminalUI`, `TerminalUI::AttachLauncher` / `AttachedLoop` | The attached TUI: rendering (ANSI, spinner, status line) and the terminal's own commands over the worker's Bridge. `TerminalUI`: the `--non-interactive` one-shot host, which delegates all core work to its `Engine`. |
211
210
  | Model loops and adapters | `KernelLoop`, `LLM::ChatLoop`, `Samagotchi::Client`, `LLM::OpenAIChat`, `LLM::AnthropicMessages`, `LLM::HTTP` | The model↔tool loops and the HTTP adapters they talk through (see "Model loops and adapters"). |
212
211
  | Bridge (SSE/HTTP) ([internals/bridge.md](internals/bridge.md)) | `Samagotchi::Bridge`, `SessionManager` | The **single live client transport**: an SSE read stream + HTTP POST turn/cancel/answer surface that attaches to a worker's existing `Engine` via `Engine#subscribe`. Every session worker starts it (bound `127.0.0.1`, localhost-only), and it answers only a request that names its secret (`X-Chi-Bridge`, from the worker's 0600 `bridge.json`). |
213
212
  | Web (Rack) | `Samagotchi::Web::App`, `SessionManager` | Single-port `127.0.0.1:4567` control plane via `rack`+`webrick` (serve `index.html` + `/api/*`). With `web.host: lan` (or one of this machine's IPv4 addresses) the server also listens on that address, where every request needs the access token, this machine's on loopback too (`App#token_gate`: the `chi_token` cookie, on loopback a value derived from the token (`Token.loopback_cookie`), or `Authorization: Bearer`; chi web prints a `Local:` link with a one-time code; [CLI](cli.md#chi-web-on-your-phone)). Experimental: behind an auth proxy (`web.public_url`, `Web::ProxyGate`) every request needs the token, this machine's too, and one that came through the proxy also the configured identity header for the owner ([configuration.md](configuration.md#behind-an-auth-proxy)). A request goes through, in order: the Host check (`local_host_header?`: loopback names, the LAN address, the public host), the cross-site check (`cross_site?`: Origin this server's or the public origin, no `Sec-Fetch-Site` cross-site/same-site on a POST or `/api`), the frame check (`framed?`: a frame/embed/object load from another origin, 403 `framed`; every HTML answer carries `X-Frame-Options: DENY` and `frame-ancestors 'none'; frame-src 'none'`, so a page's own frames can't navigate either), the token gate (`token_gate` → `principal_for`, `proxied_principal` for a proxied request; the `?token=` / `POST /api/token` trade sets the cookie, `__Host-chi_token` through the proxy; with `web.public_url` a direct request takes Bearer only, and with it or LAN mode chi's token-less `/api/info` probe gets `probe_info`), then the route's permission (`Principal#permits?`). It talks to each worker's Bridge (`App#relay`, `bridge_get`; `/stream` proxies it) and reads the session files; no `Engine` of its own. Markdown (`web.markdown`) is rendered here only (`Web::MarkdownRenderer`): the answers it serves, card bodies, and `POST /api/render` for a text the page already shows. `App` keeps the gate, `ROUTES` and the helpers the handlers share; its handlers live in mixins it includes, each a `Web::` module with private methods: `SessionAccessRoutes` (`web/session_access_routes.rb`), `ParticipantAccess` (`web/participant_access.rb`), `ParticipantsAdmin` (`web/participants_admin.rb`), `ParticipantReview` (`web/participant_review.rb`), `MessageDisplay` (`web/message_display.rb`), `SessionShow` (`web/session_show.rb`), `SessionCreate` (`web/session_create.rb`), `SessionControl` (`web/session_control.rb`), `PushRoutes` (`web/push_routes.rb`) and `ProxyGate` (`web/proxy_gate.rb`). Exact paths in `GATE_FREE_PATHS` are served before the token gate (the fragment trade's script, and the Home Screen app's manifest, service worker and icons). `bin/chi web` entrypoint. |
214
213
  | Sessions | `Samagotchi::Session`, `SessionManager` | File-based `~/.local/state/samagotchi/sessions/<uuid>.json` + sidecar `input/`/`output/`; retention (14d/500) + ordering (`updated_at desc`). |
215
214
 
216
- - `bin/chi` in REPL mode (see `LaunchMode` above) builds `TerminalUI`. `TerminalUI#run` is the single
217
- dispatch for the REPL, `-p`/`--prompt`, `--non-interactive`, and `--resume`: it
218
- builds the working session once, runs a single prompt turn when `-p` is given,
219
- then either exits (`--non-interactive`) or drops into the REPL carrying the
220
- post-turn conversation.
215
+ - `bin/chi` in one-shot mode (`--non-interactive`, see `LaunchMode` above) builds `TerminalUI`.
216
+ `TerminalUI#run` builds the session (new, `--resume`'s or `chi scratch`'s), runs the `-p`
217
+ turn with the answer alone on stdout and the session lines on stderr, and exits.
221
218
  - A session's `Worker` (spawned by `SessionManager`) builds its `Engine` (no terminal rendering).
222
- - `bin/chi` in attached mode (the default, `--attach`, `--shared`) builds no `Engine`: `TerminalUI::AttachLauncher` finds
219
+ - `bin/chi` in attached mode (every interactive run) builds no `Engine`: `TerminalUI::AttachLauncher` finds
223
220
  or starts the worker, and `TerminalUI::AttachedLoop` is a client of its Bridge
224
221
  (`BridgeClient#follow` for events, `post_turn`/`cancel`/`answer` for input). It
225
- renders through the same `EventRenderer` as the REPL, on an `AttachedView` that
222
+ renders through `EventRenderer`, on an `AttachedView` that
226
223
  draws on a `Screen`: a live region at the bottom of the terminal (activity row,
227
224
  prompt, status/notes/hints) under normal scrollback. From a turn's 3rd tool call the
228
225
  activity slot gets a second, dim row: the turn's tool tally (`TurnTally`, seeded from the
@@ -449,7 +446,7 @@ calling the `SessionAccess::Local` operation of the same name, so a remote backe
449
446
  token-gated like the rest (LAN mode: `Authorization: Bearer`), and one that takes an id is a `:session` route (an id
450
447
  that isn't one, or no such session: 404 `not_found`). Every `ROUTES` row also names who may use it, checked against
451
448
  the request's `Web::Principal` (`App#principal_for`): `owner`, or `participant` for a route a participant may use too.
452
- A participant (a `Web::Grants` token for one session) may use the page (`GET /`), `GET /api/info`, their session's
449
+ A participant (a `Grants` token for one session) may use the page (`GET /`), `GET /api/info`, their session's
453
450
  show, review and filtered stream, and their turns and waits, each answered as theirs; every other route is `owner` (Permission below, and the participants routes in
454
451
  [internals/participants.md](internals/participants.md)); `spec/web/principal_spec.rb` fails on a row without one. How a request flows end to end, which checks run where and the trust
455
452
  model: [internals/remote-sessions.md](internals/remote-sessions.md).
@@ -472,7 +469,7 @@ model: [internals/remote-sessions.md](internals/remote-sessions.md).
472
469
  | `GET /api/sessions/:id?brief=1` | participant (theirs: title, status, participants) | | 200 `{brief, session: {id, status (the file's), title, display_title, project_root, working_directory, model_name, model_typed, parent_answers, owner}, pending_question}` (the file's; no messages): `Remote#show` | 404 |
473
470
  | `POST /api/sessions/:id/turn` (its 202) | owner | | the ack with `via`: `bridge` or `file` (the input file: a remote `chi send --wait` follows that turn) | |
474
471
  | `GET /api/sessions/:id/context?full=1`, `…/context/:name?full=1` | owner | | each row with `source` (`Source#to_h`, its command too; the page's rows never carry one), `snapshot` (`Snapshot#to_h`, no text) and `shadowed`, shadowed project sources included | |
475
- | `POST /api/sessions/:id/wake` | owner | `wait` (seconds, default and most 10: `WAKE_MAX_WAIT`) | 200 `{session_id, woke, worker: {epoch, started_at, version, features}, model_name, default_model, parent_strategy, installed}`: the live worker as is (`woke: false`), else resumed and its Bridge waited for (`Local#wake`); `default_model` and `installed` are this machine's | 409 `owned_by_tui`, `scratch` (`LaunchMode::SCRATCH_LEFTOVER`); 504 `worker_timeout` (`LaunchMode::BRIDGE_LATE`); 400 `invalid_wait`; 404 |
472
+ | `POST /api/sessions/:id/wake` | owner | `wait` (seconds, default and most 10: `WAKE_MAX_WAIT`) | 200 `{session_id, woke, worker: {epoch, started_at, version, features}, model_name, default_model, parent_strategy, installed}`: the live worker as is (`woke: false`), else resumed and its Bridge waited for (`Local#wake`); `default_model` and `installed` are this machine's | 409 `owned_by_tui`, `scratch` (`Session::SCRATCH_REFUSED`); 504 `worker_timeout` (`LaunchMode::BRIDGE_LATE`); 400 `invalid_wait`; 404 |
476
473
  | `GET /api/sessions/:id/worker` | owner | | 200 `{session_id, live, stopped, owner: worker \| tui \| null, worker: {epoch, started_at, version, features} \| null, default_model, parent_strategy}` (`Local#worker`; never starts one; `default_model` is this machine's) | 404 |
477
474
  | `POST /api/sessions/:id/exit` | owner | `client_id` (passed on only when it is an attached TUI's, `tui:…`; any other is dropped), `delete` | 200 the worker's `{status: exiting, session_id, discard}` (`BridgeClient#request_exit`; never wakes one) | 409 `held` with the worker's `{status, reason, tasks, hint}`; 503 `not_live`; 501 `not_supported`; 504 `worker_timeout` |
478
475
  | `POST /api/sessions/:id/recap` | owner | | 200 the worker's `{enabled, saved, request, min_user_turns, session_off}` (`BridgeClient#request_recap`) | 503, 501, 504 as every relay |
@@ -593,7 +590,7 @@ credit held by in-flight requests, retried after 20 s), `OutOfCredits` (any othe
593
590
  402), `ServerError`, `AuthError`, `BadRequest` (`context_overflow?`) or `ProtocolError`. Engine keeps the turn's
594
591
  conversation (the prompt plus completed tool iterations) and emits
595
592
  `:turn_failed` with `error_kind:`, `retryable:`, `host:` and a one-line
596
- `summary:`, which the REPL, the attached TUI and the web show.
593
+ `summary:`, which the attached TUI, a one-shot's stderr and the web show.
597
594
 
598
595
  **Usage and models.** A turn's token counts are `SessionMetrics`', read from the
599
596
  stream events (server counts, else a chars/4 estimate). Model lists are `LLM::ModelInfo`
@@ -628,15 +625,15 @@ A map of the parts the overview above doesn't name (paths under `lib/samagotchi/
628
625
  | Worker link | `worker_link.rb` (`WorkerLink`: `Live`, `Starting`, `Leaving`, `Skew`, `Stale`, `None`), `worker_sidecar.rb` (`WorkerSidecar`) | Whether a session's worker can be reached and the client for it: every Bridge client asks `WorkerLink.resolve` / `.client` / `.await` (*Worker link* above); `WorkerSidecar` is the `bridge.json` it reads. |
629
626
  | Session access | `session_access.rb` (`SessionAccess`: `NewSession`, `SetupWords`, `WaitStart`, `SessionView`, `Created`, `ContextEntry`, `ContextPush`, the errors `RemoteFailed`, `RemoteTooOld`, `Refused`, `BadRequest`), `session_access/local.rb` (`SessionAccess::Local`), `session_access/remote.rb` (`SessionAccess::Remote`), `session_access/http_transport.rb`, `session_access/web_bridge_client.rb` (`SessionAccess::WebBridgeClient`, a remote attach's worker through chi web), `session_access/dispatch.rb` (`SessionAccess::Dispatch`), `session_access/contract.rb` (`SessionAccess::Contract`), `remotes.rb` (`Remotes`), `remote_command.rb` (`chi remote`), `web/session_access_routes.rb` (`Web::SessionAccessRoutes`) | The seam between the session commands and where the sessions live: `Local` is this machine's (the `SessionManager`, `ReplyWait`, `NoteDelivery`, `ContextSources` and Bridge calls the commands made); `Remote` is another machine's, the same methods as requests to its chi web's routes of the same name (Bearer token, `HTTPTransport`), results as Local's value objects and refusals as the classes Local's callees raise, built from the fields chi web sends; waits and prefixes run on the server, a wait asked again per 30 s slice. `Dispatch` is bin/chi's front for `--remote NAME` / `CHI_REMOTE` (taken off before the subcommand lookup): it refuses what the contract table lists `local_only` (exit 2, one message) and runs the command with a `Remote` on the `Remotes` entry (`$XDG_CONFIG_HOME/samagotchi/remotes.yml`, 0600). chi web's routes answer from `Local` (*chi web's routes for the session commands* above). Checks that read this machine's config or files (vision, parent answers, the cwd's project, `SAMAGOTCHI_PARENT_SESSION`) stay in the commands and are skipped under a `Remote`, where chi web's create, turn and wait routes run the vision, parent-answers and busy checks with the server's config and the worker checks a parent's answer. See [internals/remote-sessions.md](internals/remote-sessions.md). |
630
627
  | Idle work | `idle_scheduler.rb` (`IdleScheduler`), `idle_recap.rb` (`IdleRecap`), `idle_reminders.rb` | One poller for an idle session's recap and reminders. |
631
- | Attached context | `context_sources.rb` (`ContextSources`), `context_poller.rb`, `context_absorber.rb`, `context_candidates.rb` (`ContextCandidates`: proposed sources, attached on the owner's mention at a turn's start, before the worker's absorb, or in the REPL's turn; `owner_prompt.rb` decides whose words count), `peer_sources.rb` (`PeerSources`: the sources peer bundles declare) | External sources a session keeps fresh, and the peer loop's wakes ([context.md](context.md)). |
628
+ | Attached context | `context_sources.rb` (`ContextSources`), `context_poller.rb`, `context_absorber.rb`, `context_candidates.rb` (`ContextCandidates`: proposed sources, attached on the owner's mention at a turn's start, before the worker's absorb, or in a one-shot's turn; `owner_prompt.rb` decides whose words count), `peer_sources.rb` (`PeerSources`: the sources peer bundles declare) | External sources a session keeps fresh, and the peer loop's wakes ([context.md](context.md)). |
632
629
  | LLM context strategies | `llm_context_strategy.rb`, `llm_context_view.rb`, `llm_context_stale.rb`, `llm_context_forget.rb` | What a request sends of the history (none, stale, forget) ([internals/llm-context-forget.md](internals/llm-context-forget.md)). |
633
630
  | Session chains | `session_continue.rb` (`SessionContinue`), `session_chain.rb` (`SessionChain`) | A session that continues an earlier one. `SessionChain.opener_for` gives the text web `continue →` prefills in the new link: the previous link's own first typed message when that link continues one itself, else nil (the 201's `opener`; not saved) ([sessions.md](sessions.md)). |
634
631
  | Review sessions | `review_start.rb` (`ReviewStart`), `session_review.rb` (`SessionReview`, the session's `review` field), `review_command.rb` (`ReviewCommand`, `chi review`), `review_apply.rb` (`ReviewApply`) | A session made to be shared: idle, its subjects project files checked by `Guardrails::ReviewPaths`, a fork of a working session from its recap (`--from`); Apply quotes a participant's review turn into the owner's composer ([sessions.md](sessions.md#review-sessions), [internals/participants.md](internals/participants.md)). |
635
632
  | chi web's routes | `web/app.rb` (`Web::App`: the gate, `ROUTES`, the shared helpers), `web/message_display.rb` (`Web::MessageDisplay`: saved messages and cards as display items, `POST /api/render`), `web/session_show.rb` (`Web::SessionShow`: `GET /api/sessions/:id` with its `cards`, `tail` and `timing` re-reads, `GET …/output`, the timing payload), `web/session_create.rb` (`Web::SessionCreate`: `POST /api/sessions`, a continue, a review fork), `web/session_control.rb` (`Web::SessionControl`: answer, command, turn and images, cancel, stop, restart, archive, delete), `web/push_routes.rb` (`Web::PushRoutes`: `/api/push`, its subscriptions, prefs, test and presence), `web/block_renderer_routes.rb` (`Web::BlockRendererRoutes`: `GET /api/block_renderers` and one renderer's file, [internals/block-renderers.md](internals/block-renderers.md)) | The handlers `App`'s `ROUTES` name, in the file that holds their kind; each mixin is included in `App` and reads its helpers and ivars, so `app.send(:handle_show, …)` and the specs that stub `App` methods work as before. |
636
- | Web Push | `web/push.rb` (`Web::Push`: `Runtime`, `preflight!`, the `web.push.*` settings), `web/push/crypto.rb` (`Push::Crypto`: RFC 8291 aes128gcm, RFC 8292 VAPID), `web/push/store.rb` (`Push::Store`, `Store::Sub`: `web-push/vapid.pem`, `subscriptions.json`), `web/push/client.rb` (`Push::Client`, `Client::Result`), `web/push/attention.rb` (`Push::Attention`: notify.js's rules in Ruby, shared cases in `spec/fixtures/attention_cases.json`), `web/push/presence.rb` (`Push::Presence`: the pages' "in front" reports), `web/push/notifier.rb` (`Push::Notifier`, a hub subscriber with a sender thread), `web/push_routes.rb` (`Web::PushRoutes`), `web/private_files.rb` (`Web::PrivateFiles`, shared with the grants), `public/sw.js`, `public/push.js`, `public/manifest.webmanifest` | chi web pushes what the tab notifies for (approvals, questions, step-limit questions, cards, failed turns; done turns to a device that asks) to the owner's Home Screen app over an https public URL: the Notifier turns the hub's new attentions into show pushes after a hold, unless a chi web page is in front, at most 30 an hour, with one retry and a restart catch-up (`sent.json`) (each carries the keys still open, and the badge; no close push: every push shows a notification); the bell (`notifications.js`) subscribes the device, and the service worker and the page close the answered ones. See [internals/web-push.md](internals/web-push.md). |
633
+ | Web Push | `web/push.rb` (`Web::Push`: `Runtime`, `preflight!`, the `web.push.*` settings), `web/push/crypto.rb` (`Push::Crypto`: RFC 8291 aes128gcm, RFC 8292 VAPID), `web/push/store.rb` (`Push::Store`, `Store::Sub`: `web-push/vapid.pem`, `subscriptions.json`), `web/push/client.rb` (`Push::Client`, `Client::Result`), `web/push/attention.rb` (`Push::Attention`: notify.js's rules in Ruby, shared cases in `spec/fixtures/attention_cases.json`), `web/push/presence.rb` (`Push::Presence`: the pages' "in front" reports), `web/push/notifier.rb` (`Push::Notifier`, a hub subscriber with a sender thread), `web/push_routes.rb` (`Web::PushRoutes`), `private_files.rb` (`PrivateFiles`, shared with the grants), `public/sw.js`, `public/push.js`, `public/manifest.webmanifest` | chi web pushes what the tab notifies for (approvals, questions, step-limit questions, cards, failed turns; done turns to a device that asks) to the owner's Home Screen app over an https public URL: the Notifier turns the hub's new attentions into show pushes after a hold, unless a chi web page is in front, at most 30 an hour, with one retry and a restart catch-up (`sent.json`) (each carries the keys still open, and the badge; no close push: every push shows a notification); the bell (`notifications.js`) subscribes the device, and the service worker and the page close the answered ones. See [internals/web-push.md](internals/web-push.md). |
637
634
  | chi web's updates | `web/update_check.rb` (`Web::UpdateCheck`), `web/update_ops.rb` (`Web::UpdateOps`), `web/auto_update.rb` (`Web::AutoUpdate`) | The RubyGems checker and its `update_check.json`; the install, worker-restart and chi-web-restart operations (one at a time) the owner's routes and AutoUpdate share; `update.auto: install`'s thread (install when no turn runs, then idle workers and chi web). See [configuration](configuration.md#unattended-updates-updateauto). |
638
635
  | Behind an auth proxy | `web/public_url.rb` (`Web::PublicUrl`: `web.public_url`, `web.proxy.identity_header`, `web.proxy.owner`), `web/proxy_gate.rb` (`Web::ProxyGate`, mixed into App; `RawHeaderNames`, prepended to WEBrick's request by `Web::Server`), `web/link_codes.rb` (`Web::LinkCodes`: the links' one-time codes), `proxy_trace.rb` (`ProxyTrace`), `web/public/token_fragment.js`, `web/public/auth_lost.js`, `web/tunnel.rb` + `web/tunnel/tailscale.rb` (`Web::Tunnel`, `Web::Tunnel::Tailscale`: `chi web --tunnel tailscale`, Tailscale Serve set for one run and the PublicUrl it makes) | Experimental: chi web behind an auth proxy. Every request needs the token; a proxied one's owner also needs the identity header (one clean value under one name); the `__Host-` cookie, an absolute `Location` from the public URL, https links with a one-time code in the fragment; the page's lost-sign-in banner. Bridges refuse proxy traces ([configuration.md](configuration.md#behind-an-auth-proxy)). |
639
- | Participants | `participants.rb` (`Participants`, the `participants.json` sidecar), `share_command.rb` (`ShareCommand`, `chi share`), `session_participants.rb`, `participants_watch.rb`, `web/grants.rb` (`Web::Grants`), `web/principal.rb` (`Web::Principal`), `web/participant_access.rb` (`Web::ParticipantAccess`: the participant's gate and routes), `web/participants_admin.rb` (`Web::ParticipantsAdmin`: the owner's invite, list, revoke, cap and Apply routes), `web/participant_review.rb` + `web/participant_view.rb` (`Web::ParticipantReview`, `Web::ParticipantView`), `web/participant_stream_filter.rb`, `guardrails/review_boundary.rb` + `guardrails/review_paths.rb` | The people or agents an owner invites to review one session through chi web: their grants and gate, what they read, their read-only review turns ([internals/participants.md](internals/participants.md), [guardrails.md](guardrails.md)). |
636
+ | Participants | `participants.rb` (`Participants`, the `participants.json` sidecar), `share_command.rb` (`ShareCommand`, `chi share`), `session_participants.rb`, `participants_watch.rb`, `grants.rb` (`Grants`), `participant_exposure.rb` (`ParticipantExposure`), `web/principal.rb` (`Web::Principal`), `web/participant_access.rb` (`Web::ParticipantAccess`: the participant's gate and routes), `web/participants_admin.rb` (`Web::ParticipantsAdmin`: the owner's invite, list, revoke, cap and Apply routes), `web/participant_review.rb` + `web/participant_view.rb` (`Web::ParticipantReview`, `Web::ParticipantView`), `redact.rb` (`Redact`, `Redact::Viewer`: the redaction every string a participant gets passes, also the Engine's Verify quote check), `web/participant_stream_filter.rb`, `guardrails/review_boundary.rb` + `guardrails/review_paths.rb` | The people or agents an owner invites to review one session through chi web: their grants and gate, what they read, their read-only review turns ([internals/participants.md](internals/participants.md), [guardrails.md](guardrails.md)). |
640
637
  | Analytics | `analytics_file.rb` (`AnalyticsFile`), `session_metrics/totals.rb` (`SessionMetrics::Totals`), `session_metrics/model_segment.rb` (`SessionMetrics::ModelSegment`) | A session's `analytics.json` (`SessionMetrics#persist`); the sums over its turn records (`Totals`: tokens, cost, speeds, kept as running counters) and their split per model after a `/model` switch (`ModelSegment`: a run of turns on one model, the `model_segments` rows); `session_metrics/cost.rb` (`SessionMetrics::Cost`): the spend `ctx.cost` reads; `session_metrics/usage.rb` (`SessionMetrics::Usage`): the work `ctx.usage` reads. `session_metrics/side_totals.rb` (`SessionMetrics::SideTotals`) and `side_usage.rb` (`SideUsage`): the side requests' sums, apart from the turns'. |
641
638
  | Images / vision | `image_store.rb` (`ImageStore`), `vision_support.rb`, `vision_context.rb` | Stored prompt images and whether a model takes them. |
642
639
  | Toolkits | `toolkit.rb` (`Toolkit`), `toolkit_binding.rb` (`ToolkitBinding`, the Engine's seam), `toolkit_command.rb` (`/toolkit`), `tools/registry.rb` (`Registry#toolkit`, `#left_out_names`), `web/public/toolkit_chip.js` | Which registered tools a session's prompts declare: saved in the session, resolved at a turn's start (`Engine#apply_toolkit!`), named in the prompt's not-loaded line, a kit's prompt text after the appended files; `chi.toolkit` and `ctx.use_toolkit` for plugins ([configuration.md](configuration.md#toolkits)). |
data/docs/broadcast.md CHANGED
@@ -24,7 +24,7 @@ selection: see [Desktop helper](desktop.md#everyone-it-concerns).
24
24
 
25
25
  The recipients are your own sessions, in every project:
26
26
 
27
- - a worker or a chi REPL runs them now, or their last turn ended within
27
+ - a worker or a one-turn `chi --non-interactive` run runs them now, or their last turn ended within
28
28
  `broadcast.active_hours` (default 8). A session with no turn yet counts
29
29
  by its last save;
30
30
  - not a delegate child: its parent relays what concerns it (the
@@ -32,8 +32,8 @@ The recipients are your own sessions, in every project:
32
32
  - not a `chi scratch` session, not an archived one, and not a test run
33
33
  (unless `chi broadcast` itself runs as one, `SAMAGOTCHI_ENV=test`).
34
34
 
35
- A session open in a plain chi REPL (`--no-shared`) can't take notes: it is
36
- listed as skipped, "open in a chi REPL".
35
+ A session a one-turn `chi -p … --non-interactive` run has can't take notes: it
36
+ is listed as skipped, "in use by a one-turn chi --non-interactive run or an older chi's terminal".
37
37
 
38
38
  ## Tags: which sessions it concerns
39
39
 
@@ -101,7 +101,7 @@ broadcast b-7f3a1c9e "payments API returns 500 since 14:00 (PAY-123)"
101
101
  5e1f0a77 delivered model: yes (p 0.91)
102
102
  77aa0b3c delivered unchecked: triage deadline
103
103
  c0ffee12 skipped model: no
104
- d00dad00 skipped open in a chi REPL
104
+ d00dad00 skipped in use by a one-turn chi --non-interactive run or an older chi's terminal
105
105
  delivered 4 · skipped 2 · 1 unchecked: triage deadline
106
106
  ```
107
107
 
@@ -193,7 +193,7 @@ any shell command that runs it, once at a time, and only you may allow it
193
193
 
194
194
  | Setting | Default | What it does |
195
195
  |---|---|---|
196
- | `broadcast.active_hours` | `8` | A session with no worker or REPL counts when its last turn ended within this many hours. |
196
+ | `broadcast.active_hours` | `8` | A session with no worker or one-turn run counts when its last turn ended within this many hours. |
197
197
  | `broadcast.ticket_pattern` | `\b[A-Z][A-Z0-9]+-\d+\b` | A Ruby regex for ticket ids; an invalid one warns and the default is used. |
198
198
  | `broadcast.triage_model` | recap's, else `default.model` | The triage model, a model ref (`box:qwen3.5-9b`). |
199
199
  | `broadcast.triage_host_ref` | none | A `hosts:` name for it. |
data/docs/bundles.md CHANGED
@@ -18,11 +18,8 @@ only against this API (`lib/samagotchi/bundles/btw/plugin.rb`).
18
18
  - The card's **Keep as session** runs `/btw keep <id>`. It forks the
19
19
  conversation, the question and the answer into an idle child session, and
20
20
  shows a card `kept as <id>`.
21
- - The last 10 answers can be kept, while the session's worker (or REPL)
22
- runs. After that, or after a restart, `keep` says expired.
23
- - In the REPL, a question asked during a turn is about the conversation
24
- before that turn, and the card says so. In a worker it includes the turn
25
- so far.
21
+ - The last 10 answers can be kept, while the session's worker runs. After that, or after a restart, `keep` says expired.
22
+ - A question asked during a turn includes the turn so far.
26
23
  - Settings: `bundles: btw: {max_tokens: 1024, timeout: 120}`.
27
24
  - It ships no memory, so it adds no line to the prompt's memory index. Its
28
25
  0.1.0 shipped `btw.md` as one, and `chi bundle upgrade btw` leaves that file
@@ -803,7 +800,7 @@ file; skills themselves work without it ([docs/memory.md](memory.md#skills)).
803
800
 
804
801
  | | |
805
802
  |---|---|
806
- | `/skill save [name] [--system]` | sends this session a request to save what was just done as `skill_<name>` (chi picks a name when none is given), project scope unless `--system`. The request holds the skill's shape, so the result is the same with a model that never read the memory guide. It runs as a turn; sent while a turn runs, it joins that turn at its next step (the request says to finish the task first). An existing skill is updated. In a `--no-shared` REPL, which takes no messages, the command shows the request to send yourself |
803
+ | `/skill save [name] [--system]` | sends this session a request to save what was just done as `skill_<name>` (chi picks a name when none is given), project scope unless `--system`. The request holds the skill's shape, so the result is the same with a model that never read the memory guide. It runs as a turn; sent while a turn runs, it joins that turn at its next step (the request says to finish the task first). An existing skill is updated. When the session can't take a message (a `--non-interactive` one-shot's), the command shows the request to send yourself |
807
804
  | `/skill list` | the `skill_*` memories of both scopes, with the date and description from the index |
808
805
  | `/skill show <name>` | one skill as saved (project first, as `memory_read` looks) |
809
806
  | `/skill diff <name> [N]` | the skill now against its N-th newest older version (default 1: before the last change), unified |
@@ -869,7 +866,7 @@ and a summary of what changed in counts, authors and states only; it wakes
869
866
  the session for a review requesting changes, checks turning red, or the PR
870
867
  merged or closed. In the web, a `path:line` in a worker's answer links to
871
868
  that line of the session's PR ([Line links](context.md#line-links); `line_links:
872
- always` for the REPL and `chi -p` too), and its ref menu offers the file
869
+ always` for a `chi -p … --non-interactive` one-shot too), and its ref menu offers the file
873
870
  here and a "PR diff" action (`event[:refs]`). `auto_attach: attach` attaches
874
871
  it at once (the old default), `off` does nothing ([Propose, attach or
875
872
  off](context.md#propose-attach-or-off)).
@@ -884,9 +881,9 @@ chi bundle install coordinator # in the dev profile
884
881
  chi as a coordinator of parallel work, the way you would run several agents
885
882
  yourself: split the work, one git worktree and child session per task, keep
886
883
  talking while they run, check each report, and merge only when you allow it. It
887
- works in a session with a worker (plain `chi`, the web). A `--no-shared` REPL
888
- or `-p` gets no delegate reports, so the children's replies wouldn't come back
889
- by themselves there.
884
+ works in a session with a worker (plain `chi`, `chi -p`, the web). A
885
+ `--non-interactive` one-shot gets no delegate reports, so the children's
886
+ replies wouldn't come back by themselves there.
890
887
 
891
888
  - **The skill.** `skill_coordinator` (system scope; its index line says what
892
889
  it is for, from the manifest's `description:`) holds the steps. The model
@@ -915,8 +912,8 @@ by themselves there.
915
912
  reads the open handoff, checks it against git and the session list (git
916
913
  wins; mismatches are reported) and goes on from the first open step.
917
914
  - **`/coordinate <goal>`** sends this session a turn asking the model to
918
- follow the skill for the goal (in a `--no-shared` REPL it shows the text to
919
- send yourself). Asking "do this in parallel" works too: the index line leads
915
+ follow the skill for the goal (when the session can't take a message, as
916
+ in a `--non-interactive` one-shot, it shows the text to send yourself). Asking "do this in parallel" works too: the index line leads
920
917
  the model to the skill. **`/coordinate resume`** asks it to resume this
921
918
  project's open handoff; with several open it shows a card with a Resume
922
919
  action each (`/coordinate resume <name>` picks one), with none it says so.