samagotchi 0.133.0 → 0.135.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 (127) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +116 -1
  3. data/bin/chi +2 -3
  4. data/docs/architecture.md +6 -3
  5. data/docs/cli.md +50 -34
  6. data/docs/configuration.md +9 -6
  7. data/docs/guardrails.md +146 -13
  8. data/docs/internals/background-tasks.md +1 -0
  9. data/docs/internals/engine.md +6 -3
  10. data/docs/internals/participants.md +7 -6
  11. data/docs/internals/tool-guardrails.md +2 -0
  12. data/docs/internals/web-frontend.md +262 -0
  13. data/docs/plugins.md +2 -1
  14. data/docs/sessions.md +5 -2
  15. data/docs/testing.md +34 -4
  16. data/lib/samagotchi/bridge.rb +11 -6
  17. data/lib/samagotchi/bridge_client.rb +8 -5
  18. data/lib/samagotchi/bundles/system/manifest.yml +1 -1
  19. data/lib/samagotchi/chi_home.rb +12 -2
  20. data/lib/samagotchi/config.rb +0 -2
  21. data/lib/samagotchi/desktop/macos.rb +19 -4
  22. data/lib/samagotchi/engine.rb +82 -12
  23. data/lib/samagotchi/guardrail_wiring.rb +8 -6
  24. data/lib/samagotchi/guardrails/approval.rb +41 -5
  25. data/lib/samagotchi/guardrails/implicit_writers.rb +158 -0
  26. data/lib/samagotchi/guardrails/pair_boundary.rb +11 -5
  27. data/lib/samagotchi/guardrails/pair_command.rb +828 -86
  28. data/lib/samagotchi/guardrails/parent_approvals.rb +13 -16
  29. data/lib/samagotchi/guardrails/read_only_shell.rb +58 -4
  30. data/lib/samagotchi/guardrails/shared_git.rb +1 -1
  31. data/lib/samagotchi/guardrails/shell_git_dirs.rb +7 -2
  32. data/lib/samagotchi/guardrails/shell_lex.rb +45 -0
  33. data/lib/samagotchi/guardrails/shell_paths.rb +3 -2
  34. data/lib/samagotchi/guardrails/targets.rb +8 -3
  35. data/lib/samagotchi/guardrails_command.rb +13 -10
  36. data/lib/samagotchi/home_command.rb +22 -6
  37. data/lib/samagotchi/home_doctor.rb +36 -3
  38. data/lib/samagotchi/home_notice.rb +8 -1
  39. data/lib/samagotchi/hooks/loader.rb +5 -0
  40. data/lib/samagotchi/llm/chat_loop.rb +4 -3
  41. data/lib/samagotchi/log_line.rb +12 -0
  42. data/lib/samagotchi/message_parts.rb +1 -1
  43. data/lib/samagotchi/project_env.rb +3 -11
  44. data/lib/samagotchi/revise_anchor.rb +33 -0
  45. data/lib/samagotchi/self_report.rb +3 -1
  46. data/lib/samagotchi/session_inbox.rb +20 -12
  47. data/lib/samagotchi/session_manager.rb +13 -11
  48. data/lib/samagotchi/system_one/approval_question.rb +21 -16
  49. data/lib/samagotchi/system_one/self_protect.rb +70 -16
  50. data/lib/samagotchi/testing/waiting.rb +13 -0
  51. data/lib/samagotchi/toolkit_binding.rb +16 -0
  52. data/lib/samagotchi/tools/delegate_relay.rb +6 -5
  53. data/lib/samagotchi/tools/delegate_wait.rb +5 -5
  54. data/lib/samagotchi/tools/execute.rb +6 -6
  55. data/lib/samagotchi/tools/output_guardrails.rb +9 -2
  56. data/lib/samagotchi/tools/read.rb +5 -5
  57. data/lib/samagotchi/turn_anchors.rb +49 -0
  58. data/lib/samagotchi/update_command.rb +7 -3
  59. data/lib/samagotchi/update_hint.rb +6 -1
  60. data/lib/samagotchi/verify_anchor.rb +5 -5
  61. data/lib/samagotchi/version.rb +1 -1
  62. data/lib/samagotchi/web/app.rb +2 -14
  63. data/lib/samagotchi/web/message_display.rb +17 -1
  64. data/lib/samagotchi/web/participant_access.rb +2 -2
  65. data/lib/samagotchi/web/participant_view.rb +8 -0
  66. data/lib/samagotchi/web/public/activity.js +1 -1
  67. data/lib/samagotchi/web/public/annotations.js +1 -1
  68. data/lib/samagotchi/web/public/answer_fold.js +262 -0
  69. data/lib/samagotchi/web/public/answer_refs.js +2 -0
  70. data/lib/samagotchi/web/public/app.js +462 -338
  71. data/lib/samagotchi/web/public/bubbles.js +3 -3
  72. data/lib/samagotchi/web/public/cards_place.js +9 -4
  73. data/lib/samagotchi/web/public/chip_popover.js +73 -11
  74. data/lib/samagotchi/web/public/claim_link.js +4 -2
  75. data/lib/samagotchi/web/public/composer.css +11 -1
  76. data/lib/samagotchi/web/public/context_chips.js +9 -6
  77. data/lib/samagotchi/web/public/data.js +4 -2
  78. data/lib/samagotchi/web/public/dock_reserve.js +13 -15
  79. data/lib/samagotchi/web/public/feature_gates.js +33 -0
  80. data/lib/samagotchi/web/public/history_reveal.js +27 -0
  81. data/lib/samagotchi/web/public/index.html +82 -37
  82. data/lib/samagotchi/web/public/latest.js +46 -0
  83. data/lib/samagotchi/web/public/lists_view.js +15 -13
  84. data/lib/samagotchi/web/public/live_timing.js +2 -0
  85. data/lib/samagotchi/web/public/llm_context_chip.js +5 -13
  86. data/lib/samagotchi/web/public/markdown_place.js +1 -1
  87. data/lib/samagotchi/web/public/method_api.js +14 -0
  88. data/lib/samagotchi/web/public/notifications.js +4 -11
  89. data/lib/samagotchi/web/public/participant.js +11 -6
  90. data/lib/samagotchi/web/public/participant_names.js +1 -1
  91. data/lib/samagotchi/web/public/participants_panel.js +4 -2
  92. data/lib/samagotchi/web/public/project_picker.js +18 -22
  93. data/lib/samagotchi/web/public/question_cards.js +2 -2
  94. data/lib/samagotchi/web/public/refs.js +6 -7
  95. data/lib/samagotchi/web/public/restore.js +2 -0
  96. data/lib/samagotchi/web/public/review_start.js +1 -1
  97. data/lib/samagotchi/web/public/revise_stack.js +372 -0
  98. data/lib/samagotchi/web/public/scope.js +12 -20
  99. data/lib/samagotchi/web/public/send_turn.js +29 -16
  100. data/lib/samagotchi/web/public/session_actions.js +15 -14
  101. data/lib/samagotchi/web/public/session_fields.js +152 -0
  102. data/lib/samagotchi/web/public/session_payload.js +35 -0
  103. data/lib/samagotchi/web/public/session_state.js +2 -0
  104. data/lib/samagotchi/web/public/session_store.js +191 -0
  105. data/lib/samagotchi/web/public/stage_model.js +4 -4
  106. data/lib/samagotchi/web/public/stage_view.js +11 -16
  107. data/lib/samagotchi/web/public/start_page.js +4 -4
  108. data/lib/samagotchi/web/public/start_settings.js +29 -18
  109. data/lib/samagotchi/web/public/start_toolkit.js +5 -4
  110. data/lib/samagotchi/web/public/stream_handlers.js +88 -90
  111. data/lib/samagotchi/web/public/task_stop.js +1 -1
  112. data/lib/samagotchi/web/public/timing.js +7 -3
  113. data/lib/samagotchi/web/public/{turn_view.js → turn_block.js} +46 -101
  114. data/lib/samagotchi/web/public/turn_events.js +2 -2
  115. data/lib/samagotchi/web/public/turn_html.js +17 -9
  116. data/lib/samagotchi/web/public/turn_model.js +6 -6
  117. data/lib/samagotchi/web/public/turn_range.js +32 -0
  118. data/lib/samagotchi/web/public/verdict_card.js +5 -13
  119. data/lib/samagotchi/web/public/verdict_fresh.js +2 -0
  120. data/lib/samagotchi/web/public/verify_target.js +7 -10
  121. data/lib/samagotchi/web/public/working_set_view.js +3 -1
  122. data/lib/samagotchi/web/server.rb +4 -4
  123. data/lib/samagotchi/web/session_control.rb +2 -2
  124. data/lib/samagotchi/worker.rb +9 -9
  125. data/lib/samagotchi/worker_inbound.rb +6 -5
  126. metadata +16 -3
  127. data/lib/samagotchi/web/public/hold.js +0 -78
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8b85b6006a6570eb4145c39cf37ad004a56332b33240353c78d15529d532cd71
4
- data.tar.gz: 6c194c4f62179e781a121e1e35eb9f8407795cb6e2b519ffa3ff917d0b6096eb
3
+ metadata.gz: 93a0efdc96f935536f82621c8c70c078cf4d89a9a88ce2a6881b77a9e545de30
4
+ data.tar.gz: c8fd5b64ba27f5ad4d83369f58990cc53d449f6eb498050f32e2199216fcb9b6
5
5
  SHA512:
6
- metadata.gz: 777ad65e1223ba4f99058f5ecdd3d89621af1b1f2f61ff02b21a0760607a92d18d179f9da49dae7c257a07ac107fdcfadd2c0bcf14c8555a25a1570f07c8729e
7
- data.tar.gz: e5115ba552ca82ac8a1f6d79f917d50d970bcd7202866a3ac30a15a89541ea94b61ef0a2ff61f0594f996c2a874aa01e7fe1cb3c4cf1551357f017417416c217
6
+ metadata.gz: 478a7f90b5f012fa5c26cc571743191dc78550b9227880d01957e922606f495f35a6d4f4e6dba65fe2edacc0274fb57a48b67377efd704ea7f4034e0a03c1bb0
7
+ data.tar.gz: 66e0a258aa80f18ddbee8d40430c77f19b74dc0b335a889379e795f3e38e21282ec283018b63563318e3b9fb03ee170143ae1e68ca1131fce923422d3ddeb248
data/CHANGELOG.md CHANGED
@@ -7,6 +7,119 @@ 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.135.0] - 2026-10-30
11
+
12
+ ### Added
13
+
14
+ - Web: Revise on a finished answer: your next message rewrites it, and once that turn completes the earlier version
15
+ folds in place to one stub row ("v1 · its first line · N lines — superseded by v2", a click unfolds it); the newest
16
+ answer's "v2 · 1 earlier ▾" chip lists the versions by their prompts. Stacks show on every owner's page, live and
17
+ after a reload.
18
+
19
+ ### Changed
20
+
21
+ - Guardrails: a file or string check (`test -f x`, `[ -d dir ]`, `[ "$a" = b ]`) counts as read-only, so
22
+ `test -f x && cat x` no longer asks where `cat x` alone wouldn't.
23
+
24
+ ### Removed
25
+
26
+ - Web: the turn view (`web.view: turn`, `chi web --web-view`, `SAMAGOTCHI_WEB_VIEW`, `?view=`): the stage is the only
27
+ view; finished turns still show as blocks of steps in the history. A config.yml that still sets `web.view` warns
28
+ about an unknown key; a chi web started with `--web-view` doesn't come back from an Update restart (start it again
29
+ without the flag).
30
+
31
+ ### Fixed
32
+
33
+ - Web: opening another session clears the previous one's init row, markdown tip and card actions at once; they no
34
+ longer stayed when the open failed.
35
+ - Web: a canceled turn's timing shows in the info bar right away, not at the next unrelated redraw.
36
+ - Web: the info bar follows a terminal taking the open session (its Continue and Stop, the title's ✎) at once, not at
37
+ the hub's next event.
38
+ - Web: Verify fresh on a verdict's card says it's unavailable as soon as the open session's worker goes, not at the
39
+ hub's next event.
40
+ - Web: a turn's end no longer shows the session idle while the next queued turn already runs (its late re-read wrote
41
+ the stored "idle" over "running").
42
+ - Web: a sign-in that lapsed behind an auth proxy is reported (the sign-in prompt) by the notification bell and the
43
+ push devices list too.
44
+ - Pair turns: a program is judged by its name in any case, as macOS's disk runs it: `GIT config …`, `CHI share`,
45
+ `NOHUP`, `PRINTENV` or `Bash -c` are refused like their lower-case names (System 1's memories exemption reads
46
+ `MAKE` or `RUBY x.rb` the same way). More spellings that hid a command are caught: fish's `--command S` and
47
+ `-C`/`--init-command S`, `PROMPT_COMMAND` and a `$(…)` kept in a value bash expands later (`PS4='$(…)' bash -x`),
48
+ the program behind `xcrun`, `arch`, `script`, `builtin`, `uv run`, `pnpm exec`, `bunx` and a wrapper's value option
49
+ (`env -u X`, `sudo -u root`), the command lines `env -S`, `ssh -o ProxyCommand=`, `hyperfine` and `parallel` run,
50
+ `php -B/-R/-E`, `perl -de`, `jruby`/`raku`/`julia -e`. git or chi behind a program chi doesn't know
51
+ (`some-runner git config …`, `chronic chi share x`) and a `$(…)` kept in a value now ask you (refused when what it
52
+ runs reads as git config or chi). `git add maintenance start` no longer asks you; `git lfs update` does.
53
+
54
+ Update with `chi update`, then restart `chi web` (without `--web-view`) and the session workers (`chi sessions
55
+ restart`). `chi home doctor` says what else to do.
56
+
57
+ ## [0.134.0] - 2026-10-30
58
+
59
+ ### Added
60
+
61
+ - Web: a long answer (over ~25 lines or ~2,000 characters) gets a fold row above it: one click folds it to its first
62
+ line and its length, another opens it. Your folds are kept per browser across reloads; a jump into a folded answer
63
+ (a claim link, the working set, "View check") opens it.
64
+
65
+ ### Fixed
66
+
67
+ - Web: the start page's ⚙ and 🧰 buttons say whether their panel is open (`aria-expanded`) to screen readers.
68
+ - Web: an open sheet or popover is placed again when the window resizes (a rotation, a phone's keyboard): its header
69
+ no longer ends up above the screen, and a sheet turns back into a popover on a wide window.
70
+ - Web: on a phone the ⚙ panel's sheet may take 85 % of the screen, so with "Apply and budget" open its closing note is
71
+ no longer cut off at the bottom edge.
72
+ - Web: the ⚙ and 🧰 panels keep the keyboard focus while open (Tab wraps inside, `aria-modal`), their override chips
73
+ say whether the panel is open (`aria-expanded`), and Esc or × gives focus back to the chip that opened it.
74
+ - Web: "default" on the ⚙ panel's Context row now clears a set apply rule and budget too: the chip read "ctx apply
75
+ payoff · budget 64000" while the row showed default, and the new session got them.
76
+ - Web: on a touch screen a tapped row or link in the ⚙ and 🧰 panels (and the ⚙ and 🧰 buttons) no longer keeps its
77
+ hover tint.
78
+ - Web: a sheet's and a popover's × is a 36 px tap target on a touch screen (it was 22x16 px).
79
+ - Web: the Stop sheet's "+N more" no longer sits 74 px to the right (it shared a class with the ⚙ panel's row).
80
+ - Pair turns: a read-only mention of mise's config (`find . -name mise.toml && make`) no longer asks the owner; a
81
+ delete, move or write of it still does, and `.tool-versions` (mise reads it too) is covered the same way.
82
+ - `chi home doctor` checks the desktop helper only when the helper's chi reads this chi's config dir: a run with
83
+ `XDG_CONFIG_HOME` elsewhere no longer reports the installed helper against a home it never boots.
84
+ - The new-version hint ("… the desktop helper can be updated: chi update") follows the same rule: a run with
85
+ `XDG_CONFIG_HOME` elsewhere no longer hints about the installed helper.
86
+ - `chi home set` under `bundle exec` refuses to record its own Ruby, whose gem path is the bundle's, instead of making
87
+ it the home every launch boots (`--ruby` another Ruby still works).
88
+ - `chi update` under `bundle exec`, run on another Ruby than the chi home's, hands over to the home's chi outside the
89
+ bundle instead of loading the bundle into it (which failed noisily).
90
+ - `chi self`'s home row says when this chi runs on the home's Ruby and gems but isn't the home's newest chi (`this chi
91
+ is X`), as the terminal line and `chi home doctor` do.
92
+ - `chi home doctor` reports a worker that couldn't boot the chi home's chi (the debug log's newest `boot_failed` line
93
+ since the home was set, unless a worker started after it), with what to run.
94
+ - Toolkit suggestions (`toolkit.suggest.mode: on`): a suggestion that times out or gets no answer from System 1 now
95
+ says so in a notice (the session runs its default kit) and a timeout logs a warning, instead of falling back silently.
96
+ - Pair turns: a participant can no longer write git's config at all, so no setting makes git run a command later in
97
+ your name (a hook, a filter or driver, a helper, an include): `git config` only reads, parsed strictly (an unknown or
98
+ abbreviated option counts as a write), and `git -c`, `--config-env`, a clone's `-c`/`--config`, `--template` and
99
+ `GIT_TEMPLATE_DIR` are denied, as are a submodule's hooks (`.git/modules/*/hooks`) and the hook installers
100
+ (`pre-commit install`, `husky`, `lefthook install`). A command git runs from its text (`rebase --exec`,
101
+ `submodule foreach`) is checked like any command. Reading git's config (`git config --get`, `-l`) is no longer
102
+ refused.
103
+ - Pair turns: a command that writes outside the project with no word naming where now asks you like any other
104
+ outside write: global installs (`npm -g`, `pip install`, `gem install`, `brew`, `cargo`/`go install`, `pipx`,
105
+ `uv tool`), user config (`npm config set` writes `~/.npmrc`, `gh config set`), `defaults write`, `launchctl`; and
106
+ so does a shell or interpreter reading its script from stdin (`… | sh`, `| bash -x`, `curl … | bash`,
107
+ `sh < run.sh`). Global installs are recognised in any spelling (`npm i --location global`, `python3.12 -m pip`,
108
+ `npm_config_global=true`, `npm link`), with more tools (`deno`, `dotnet tool`, `corepack`, `bundle config set`).
109
+ - System 1 no longer auto-allows a command that names the memories folder and then climbs out of it by a script's
110
+ own calls (`python3 -c '…os.chdir(os.pardir)…'`, `ruby -e '…File.dirname(Dir.pwd)…'`) or runs a script it can't
111
+ see (a file, stdin, `| sh -x`, `python3.12 x.py`, `make`, `awk -f`): it could write `config.yml`. You decide
112
+ those; plain memory edits stay eligible.
113
+ - Guardrails: a `task_create` whose `env:` points git at another config (`GIT_CONFIG_GLOBAL`, `GIT_CONFIG_SYSTEM`,
114
+ `GIT_CONFIG_KEY_n`/`VALUE_n`) is no longer read-only, and a pair turn's command that sets one is denied like
115
+ `git -c`.
116
+ - Pair turns: more spellings that hid a git config write or a command are caught: a git global option that takes a
117
+ value (`--attr-source`, `--shallow-file`, one git adds later), `git-config` and the other dashed builtins, a script
118
+ after a shell's options (`sh -c -- S`, `bash -c -x S`) or in an option cluster (`ruby -we`, `perl -le`, `node -pe`,
119
+ `python3 -Ic`), and a command handed through an environment variable (`GIT_EDITOR`, `GIT_SSH_COMMAND`,
120
+ `GIT_EXTERNAL_DIFF`, `GIT_PAGER`, `EDITOR`, …). `git maintenance register/start`, `git lfs install` and
121
+ `scalar register` now ask you.
122
+
10
123
  ## [0.133.0] - 2026-10-30
11
124
 
12
125
  ### Added
@@ -5077,7 +5190,9 @@ and long-lived sessions.
5077
5190
  - A macOS desktop helper (`chi desktop install`): a "Send to chi" Service and a
5078
5191
  hotkey panel that send selected text or the clipboard to your sessions.
5079
5192
 
5080
- [Unreleased]: https://github.com/dm1try/samagotchi/compare/v0.133.0...HEAD
5193
+ [Unreleased]: https://github.com/dm1try/samagotchi/compare/v0.135.0...HEAD
5194
+ [0.135.0]: https://github.com/dm1try/samagotchi/compare/v0.134.0...v0.135.0
5195
+ [0.134.0]: https://github.com/dm1try/samagotchi/compare/v0.133.0...v0.134.0
5081
5196
  [0.133.0]: https://github.com/dm1try/samagotchi/compare/v0.132.0...v0.133.0
5082
5197
  [0.132.0]: https://github.com/dm1try/samagotchi/compare/v0.131.0...v0.132.0
5083
5198
  [0.131.0]: https://github.com/dm1try/samagotchi/compare/v0.130.1...v0.131.0
data/bin/chi CHANGED
@@ -234,7 +234,7 @@ if options[:dir]
234
234
  exit 2
235
235
  end
236
236
 
237
- # `chi web`: its flags (--port, --open, --web-view…) went through the parser above.
237
+ # `chi web`: its flags (--port, --open…) went through the parser above.
238
238
  options[:web] = true if web
239
239
 
240
240
  # The first interactive start of a new installed chi says what `chi update` would update.
@@ -253,9 +253,8 @@ if options[:web]
253
253
  port = options[:web_port] || Samagotchi::Config.get("web.port")
254
254
  markdown = options[:web_markdown]
255
255
  markdown = Samagotchi::Config.get("web.markdown") if markdown.nil?
256
- view = Samagotchi::Config.get("web.view")
257
256
  exit Samagotchi::Web::Server.launch(port: port, scope: options[:scope] || "project", open_browser: options[:web_open],
258
- markdown: markdown, view: view, new_token: options[:new_token], tunnel: options[:tunnel],
257
+ markdown: markdown, new_token: options[:new_token], tunnel: options[:tunnel],
259
258
  working_set: Samagotchi::Config.get("web.working_set"),
260
259
  annotate_presets: Samagotchi::Config.get("web.annotate_presets"),
261
260
  editor: Samagotchi::Config.get("web.editor"),
data/docs/architecture.md CHANGED
@@ -236,6 +236,9 @@ agent logic and can be used without any terminal rendering; the UI is a thin lay
236
236
  run's own prompts until their turns end; `#run` distinguishes an empty answer from a
237
237
  prompt this terminal removed before it ran (both exit 1), as well as chi's other outcomes.
238
238
  Without a capable terminal it falls back to `PlainSurface` (append-only).
239
+ - The browser's page (`lib/samagotchi/web/public/`: `app.js` for the owner, `participant.js` for a participant) is a
240
+ client of chi web: where its state lives, which redraw follows which write, its render idioms, stale-answer guards,
241
+ storage keys and streams are in [internals/web-frontend.md](internals/web-frontend.md).
239
242
 
240
243
  #### Using the core
241
244
 
@@ -532,16 +535,16 @@ The page's frequent reads of `GET /api/sessions/:id` stay light too:
532
535
  (`turn_model.js` `questionRefs`) before the card draws, so the stage's asking slot (`stage_slots.js`
533
536
  `drawAsking(text, refs)`) pairs them on its raw draw and again after its markdown swap; the card pairs its
534
537
  question text and its kept reply (`question_cards.js`); the step's closed `.gen-text` takes them
535
- (`turn_view.js`; on a reload its `data-answer-at`, the message's `display_refs`) and `linkTextRefs` pairs it at
538
+ (`turn_block.js`; on a reload its `data-answer-at`, the message's `display_refs`) and `linkTextRefs` pairs it at
536
539
  the turn's end and after a reload. A closed step's text is markdown too with `web.markdown` on: a reload's
537
- from its message's `html` (`turn_view.js` `textTemplate`), a live turn's from `POST /api/render` on its step's
540
+ from its message's `html` (`turn_block.js` `textTemplate`), a live turn's from `POST /api/render` on its step's
538
541
  first open after the turn's end (`markdown_place.js` `renderStepTexts`, which pairs its refs again after the
539
542
  swap); the text as written stays on it as `data-copy-source` (`stepText`, a reloaded card's kept reply). A file ref outside the
540
543
  session's folder is dropped, as a reload drops it: the folder `/tail` names, else (an older worker) the hub's
541
544
  session list entry's, else (refs to check, no hub entry) the session file's; with no folder known at all, every
542
545
  file ref is dropped rather than shown unchecked.
543
546
  A plugin tool's row refs (`refs`, `RowRefs`) ride its tool events and, on a reload, its part (saved as
544
- `tool_refs`); `turn_view.js` binds them to the row's title (`refs.js bindRowRefs`: the first on the title,
547
+ `tool_refs`); `turn_block.js` binds them to the row's title (`refs.js bindRowRefs`: the first on the title,
545
548
  the others in its menu).
546
549
  - `?timing=1`: the whole timing (`analytics.json` merged with the worker's `/state`) and
547
550
  `turn_count`, when the page's merge came up short.
data/docs/cli.md CHANGED
@@ -17,7 +17,6 @@
17
17
  - `chi web --tunnel tailscale` — the Web UI over https on your tailnet, for your phone anywhere: Tailscale Serve (never Funnel) on this machine's `<machine>.<tailnet>.ts.net` name for this run, the owner your Tailscale login, turned off on exit (see [Tailscale Serve](configuration.md#tailscale-serve-your-tailnet)); `--tunnel` without `web` exits 2
18
18
  - `chi web push ls [--format json]`, `chi web push rm ID`, `chi web push test [ID]` — the phones chi web pushes to (see [Phone notifications](configuration.md#phone-notifications-web-push)): list them (short id, label, origin, added, last delivery, done turns, last error; `stale` for one made on another public URL than chi web's now: never sent to), remove one, or send a test notification to ID or to every device not stale. chi web need not run; nothing printed holds a device's push address or keys. A usage error exits 2; a store others can read, a corrupt one, an unknown device or a failed test push exit 1. This machine only: `chi --remote X web push` exits 2
19
19
  - `chi web --web-markdown` — opt in to sanitized Markdown rendering for completed assistant messages, the stage's asking text and a resolved question card's reply
20
- - `chi web --web-view turn` — draw turns with the turn view (each turn as one block of steps, the running one at the bottom of the history) instead of the default stage view (the running turn pinned above the composer); `?view=stage|turn` on the page URL overrides it (see [Web views](#web-views))
21
20
  - `chi web --no-web-working-set` — turns the stage view's working set off (on by default; `--web-working-set` turns a config's `web.working_set: false` back on): what each turn brought into the model's context, in the stage and under each finished turn; `?working_set=1|0` on the page URL overrides it (see [The working set](#the-working-set))
22
21
  - `chi sessions list|stop|restart|archive|unarchive|delete|prune|clean|stats` — manage persisted sessions; `list` shows this git project's, `list --scope=all` every one, a delegated session with `↳ <parent>`, `list --archived` the archived ones too (see [Sessions](sessions.md)). `stats ID` prints a session's cost, tokens and progress, and its own settings (`--set`; a `settings:` line), from a live worker's `GET stats`, else its saved `analytics.json` (`--format json` one object, with `settings`), without running a model turn. A usage error (an unknown subcommand or flag, a flag missing its value, `stop`, `restart` or `delete` with no ids, a bad `list --format` or `--scope`, a `--days`, `--keep` or `--limit` that isn't a whole number) exits 2; an unknown or refused session exits 1
23
22
  - `chi note [--source NAME] [-m TEXT] (ID|PREFIX)... | --all` — add a context note (TEXT or stdin) to sessions: background the model sees on its next turn; it starts no turn (see [Sessions: Context notes](sessions.md#context-notes))
@@ -1026,29 +1025,42 @@ touch screen), and so does each code block of a rendered answer. An answer
1026
1025
  copies its Markdown source, not the rendered text; a code block copies just
1027
1026
  its code; a prompt copies the text as you typed it.
1028
1027
 
1029
- ### Web views
1030
-
1031
- `web.view` picks how the page draws a turn: `stage` (the default: the
1032
- running turn pinned above the composer, below) or `turn` (each turn as one
1033
- block of steps in the history, the running one at the bottom, below).
1034
-
1035
- ```sh
1036
- chi web --web-view turn # stage is the default
1037
- ```
1038
-
1039
- The setting also supports `SAMAGOTCHI_WEB_VIEW=turn` or the global config:
1040
-
1041
- ```yaml
1042
- web:
1043
- view: turn
1044
- ```
1045
-
1046
- `?view=stage` or `?view=turn` on the page URL picks the view for that page
1047
- load, whatever the config says; the parameter is dropped when you switch
1048
- between the project and all-sessions views. The terminal UIs are not
1049
- affected.
1050
-
1051
- **The stage view** pins the running turn above the composer, in its own
1028
+ A long answer (over 25 lines or 2,000 characters of its text) can be folded
1029
+ by hand: a slim "▾ N lines" row sits just above it once its turn has ended.
1030
+ Click it and the answer folds to one row, "▸ its first line · N lines" (the
1031
+ first line of what a hook presented in its place, else its first heading,
1032
+ else its first line); click again to unfold. A delegate report's reply
1033
+ folds the same way. Folding is this browser's choice, kept per session in
1034
+ localStorage (`chi_answer_fold:<session id>`, the last 200 folded answers;
1035
+ the keys of sessions gone from the list are dropped when the list loads);
1036
+ other viewers and the participant page are not affected. A jump into a
1037
+ folded answer (a claim link, say) unfolds it for that page load.
1038
+
1039
+ **Revise** rewrites an answer and stacks the versions. A finished turn's
1040
+ final answer has a Revise button on its bottom edge (on hover; always shown
1041
+ on a touch screen), unless it's a Verify turn's answer, a canceled or failed
1042
+ turn's partial answer, or an earlier version in a stack. Revise arms the
1043
+ composer with a chip, "Revising: ‹its first line› ✕"; your next message (say
1044
+ "cut it shorter") is sent as a Revise of that answer. ✕, emptying the box or
1045
+ opening another session lets go of it. When the Revise turn completes with an
1046
+ answer, the earlier version folds where it was into one stub row,
1047
+ "▸ v1 · “its first line” · 84 lines — superseded by v2": its prompt, its
1048
+ steps and its answer, all behind it (a warn card, a verdict card and the
1049
+ recap stay on view). Click the stub to unfold that version in place (kept per
1050
+ browser, with the folded answers); a time divider between two folded stubs
1051
+ moves into the later stub. The newest version has a chip, "v3 · 2 earlier ▾",
1052
+ listing every version by its prompt; pick one to jump to its stub. Revise
1053
+ again on the newest version adds to the stack. Stacks are session data (the
1054
+ stamp is on the Revise prompt, see [sessions.md](sessions.md), Revise
1055
+ stacks): every owner's page shows them, live and after a reload; the
1056
+ participant page doesn't draw them yet. A session whose worker predates
1057
+ Revise (started by an older chi) disables the button and shows the chip as
1058
+ "Revise: restart this session to use Revise"; a message sent then is a plain
1059
+ one. A Revise turn that fails comes back into the composer with its chip.
1060
+
1061
+ ### How the page draws a turn
1062
+
1063
+ **The stage** pins the running turn above the composer, in its own
1052
1064
  card, so it stays on screen without scrolling: a status row (what it is
1053
1065
  doing, the step, the elapsed time), your prompt on one line, the newest
1054
1066
  narration sentence (else the newest thinking one, in italics; click it for
@@ -1067,8 +1079,8 @@ stage's bottom edge takes you to it. Once answered, the model's
1067
1079
  question or its own approval keeps that reply (a delegate's relayed
1068
1080
  approval, a hook's question and the step limit don't): two muted lines
1069
1081
  under its `question → answer` line, the whole text when you open the card,
1070
- in both views and after a reload. The chip at the stage's bottom edge, `N steps · M tool
1071
- calls` with one tick per call, opens the turn view's block right above it (newest step first
1082
+ live and after a reload. The chip at the stage's bottom edge, `N steps · M tool
1083
+ calls` with one tick per call, opens the turn block right above it (newest step first
1072
1084
  while it runs; a tick opens its step). Below the chip, past a dashed rule, wait the
1073
1085
  messages queued for after the turn and the commands queued for its end; they go into
1074
1086
  the history after the turn's answer. `▾` folds the stage to its status
@@ -1083,10 +1095,11 @@ message moves it at once. The history is never scrolled while a turn runs, and o
1083
1095
  follows the hand-off if you were at its end. The `/` command list opens
1084
1096
  over the stage's lower edge.
1085
1097
 
1086
- **The turn view** shows a turn as *one block* where the work
1087
- happens. The running
1088
- generation is the live part at the bottom (its thinking, its narration, its
1089
- tool rows), the earlier ones stack above it collapsed to one line each
1098
+ **The turn block** shows a turn's work as *one block*: in the stage's cloud
1099
+ while the turn runs (newest step first), in the history after the hand-off
1100
+ and on a reload. The running
1101
+ generation is the live part on top (its thinking, its narration, its
1102
+ tool rows), the earlier ones below it collapsed to one line each
1090
1103
  (their narration's first line, else their first call's title such as
1091
1104
  `edit lib/a.rb`, and a call count), expandable for inspection. A tool row
1092
1105
  says what the call did: a file's path relative to the session's folder, a
@@ -1105,8 +1118,8 @@ first line, so a mid-turn note reads without a click), and each run of steps
1105
1118
  that only called tools or thought sits behind one `· N steps` line that
1106
1119
  shows them; old turns open the same way after a reload. A turn whose steps
1107
1120
  said nothing collapses the block to its summary (`3 steps
1108
- · 8 tool calls · execute ×7 · read ×1`). Either way the answer expands from
1109
- the box into a normal bubble under it (Markdown, annotate). A plain answer
1121
+ · 8 tool calls · execute ×7 · read ×1`). Either way the answer is a normal
1122
+ bubble under the block (Markdown, annotate). A plain answer
1110
1123
  without tools ends exactly as it does today. Rows the code collapses stay
1111
1124
  as you toggled them. A reloaded session shows the same block
1112
1125
  from the saved messages (each step's thinking, narration, tool parameters
@@ -1119,7 +1132,10 @@ steps saved before that have none, so they show no thinking. An `edit` or
1119
1132
  made (up to 120 lines or 8 KB), live and after a reload (see
1120
1133
  [Guardrails](guardrails.md#ask) for the diff an approval shows first).
1121
1134
 
1122
- **When things happened**, in both views and on a participant's review page: where 10 minutes or
1135
+ `web.view`, `chi web --web-view`, `SAMAGOTCHI_WEB_VIEW` and `?view=` were removed with the turn view (the
1136
+ stage is the only view; a config.yml that still sets `web.view:` warns about an unknown key).
1137
+
1138
+ **When things happened**, on the owner's page and on a participant's review page: where 10 minutes or
1123
1139
  more of quiet passed between the end of one activity and the start of the next (a turn, a context
1124
1140
  note, a reminder), the history has one dim centred line, `── 14:32 · 47 min later ──`; the date is
1125
1141
  added when the day changed or the turn wasn't today (`── Sat 24 Oct 09:10 · 13 h later ──`).
@@ -1136,7 +1152,7 @@ it read, edited or wrote, the memories it read or wrote and the URLs it
1136
1152
  fetched. It is on by default; `web.working_set: false` (or `chi web
1137
1153
  --no-web-working-set`, `SAMAGOTCHI_WEB_WORKING_SET=false`; `?working_set=0` on
1138
1154
  the page URL for one page load, `?working_set=1` back on) turns it off, and the
1139
- session bar shows the `mem N` chip again. The turn view ignores it.
1155
+ session bar shows the `mem N` chip again.
1140
1156
 
1141
1157
  - **The rail**, on the right of the stage's live slots: the running turn's set
1142
1158
  in four lines, folded as it grows (files under one folder become
@@ -1375,7 +1375,8 @@ launches it. It is recorded in `~/.config/samagotchi/home.json` (`$XDG_CONFIG_HO
1375
1375
  - **Setting it.** `chi home set` records the Ruby your `chi` runs on and its gem path (a chruby shell's
1376
1376
  `GEM_HOME`/`GEM_PATH` are part of it: that is where its chi lives); `chi home set --ruby PATH` records another
1377
1377
  Ruby with its own gem dirs. Either needs samagotchi installed there (`gem install samagotchi` with that Ruby
1378
- first). Without a home.json, the first `chi bootstrap` or `chi update` records one, once (from an installed chi,
1378
+ first). Under `bundle exec`, `chi home set` refuses to record its own Ruby (the bundle's gem path is no home);
1379
+ `--ruby` another Ruby still works. Without a home.json, the first `chi bootstrap` or `chi update` records one, once (from an installed chi,
1379
1380
  never under `bundle exec`): of the desktop helper's Ruby (when its newest chi is at least the one running) and the
1380
1381
  Ruby chi runs on, the one with the newer chi. Nothing else ever overwrites it.
1381
1382
  `chi home` shows it; `chi home doctor` checks it (see [CLI](cli.md#commands)).
@@ -1396,7 +1397,7 @@ launches it. It is recorded in `~/.config/samagotchi/home.json` (`$XDG_CONFIG_HO
1396
1397
  `home_older_than_spawner`), but chi web's restart runs the newest chi it knows outside the home instead
1397
1398
  (`restart_home_older`): its flags may be ones the older chi doesn't know.
1398
1399
  - **A home that still fails at boot** (a broken install): the worker writes one `boot_failed` line to the debug log
1399
- (`log.file`) and exits, rather than leave the spawner waiting.
1400
+ (`log.file`) and exits, rather than leave the spawner waiting; `chi home doctor` reports the newest one.
1400
1401
  - Each machine has its own home (a remote's is that machine's).
1401
1402
 
1402
1403
  ### Checking it: chi home doctor
@@ -1408,7 +1409,8 @@ fails (a launch can't boot what it should), 0 otherwise. Run it in a project fol
1408
1409
  |---|---|---|
1409
1410
  | the home | `fail`: its Ruby is gone (a Ruby upgrade) or has no samagotchi | `gem install samagotchi` with the new Ruby, then `chi home set` from it |
1410
1411
  | this chi | `warn`: the chi you ran is another Ruby's, or another version, than the home's (`ok` for a source checkout, which starts its own code) | `chi home set` to make this one the home, or run the home's |
1411
- | the desktop helper | `fail`: its launch file's Ruby or chi is gone; `warn`: it runs `[ruby, chi]` (installed before the home), boots the home as it was before a `chi home set`, or sets `GEM_HOME`/`GEM_PATH` | `chi desktop install --force` / `chi desktop upgrade` |
1412
+ | the last worker boot | `fail`: the newest worker boot in the debug log since the home was set is a `boot_failed` line (the home's Ruby couldn't load chi), not a worker's `start`; nothing without a log file | `gem install samagotchi` with the home's Ruby (or `chi home set` another), then `chi sessions restart ID` |
1413
+ | the desktop helper (when installed, and its chi reads this chi's config dir: none with `XDG_CONFIG_HOME` elsewhere) | `fail`: its launch file's Ruby or chi is gone; `warn`: it runs `[ruby, chi]` (installed before the home), boots the home as it was before a `chi home set`, or sets `GEM_HOME`/`GEM_PATH` | `chi desktop install --force` / `chi desktop upgrade` |
1412
1414
  | sessions | `warn`: sessions last saved by a newer chi than the home's (their workers run without what it added) | `chi update` |
1413
1415
  | the tools' `chi` | `warn`: `$XDG_STATE_HOME/samagotchi/bin/chi` boots another chi than the home | the next worker start rewrites it (`chi sessions restart ID` for a running session) |
1414
1416
  | this project's Gemfile.lock | `warn`: the nearest Gemfile.lock up to the git root bundles samagotchi (`bundle exec chi` isn't supported) | `bundle remove samagotchi` there; run chi itself |
@@ -1530,7 +1532,9 @@ toolkit:
1530
1532
  suggested`, and the turn's first request declares it; the notice reads
1531
1533
  `toolkit: web (suggested, p=0.71) · /toolkit to change`. Anything else (the default, a low-confidence or unknown
1532
1534
  pick, `undecided`, no answer, a failing System 1, which warns once as `[samagotchi:toolkit]`) keeps the default
1533
- kit. A Stop during the wait (or before it, even with the answer in) ends the turn before its first request, and
1535
+ kit. No answer in time or none at all says so in a warn notice, `toolkit: full (no suggestion: System 1 took over
1536
+ 5000 ms) · /toolkit to change` (or `System 1 gave no answer`), and a timeout logs a `toolkit_suggest_timeout`
1537
+ warning: a slow System 1 host wants a larger `guardrails.system_one.timeout_ms`. A Stop during the wait (or before it, even with the answer in) ends the turn before its first request, and
1534
1538
  nothing switches. After an `undecided`, a later prompt within the defer limits may switch the session; that notice
1535
1539
  says `from this turn`, and that request re-reads the whole prompt (system prompt, tools and conversation, which
1536
1540
  the defer limits keep small) without `/toolkit`'s cache confirmation. `/toolkit` or `ctx.use_toolkit` marks the
@@ -2180,8 +2184,7 @@ column says so, a `--kebab-name` flag. The maps (`hosts:`, `models:`,
2180
2184
  | `web.port` | `4567` | `--port` | `chi web`'s port. See [CLI](cli.md). |
2181
2185
  | `web.host` | `127.0.0.1` | yes | `127.0.0.1`, `::1` or `localhost`; `lan` (this machine's private IPv4 address) or one of its IPv4 addresses also opens `chi web` to the network, with an access token, asked of this machine's 127.0.0.1 too (its `Local:` link carries a one-time code; `chi web --new-token` replaces the token). Anything else binds `127.0.0.1` with a warning. See [CLI: chi web on your phone](cli.md#chi-web-on-your-phone). |
2182
2186
  | `web.markdown` | `false` | yes | Render answers as Markdown in `chi web`. |
2183
- | `web.view` | `stage` | yes | How `chi web` draws a turn: `stage` (the running turn pinned above the composer) or `turn` (one block per turn in the history). See [CLI](cli.md#web-views). |
2184
- | `web.working_set` | `true` | yes | The stage view's working set: the files, memories and URLs a turn brought into the model's context, in a rail in the stage, a footprint line under each finished turn and a `set N` chip in place of the mem chip; `false` brings the mem chip back. `?working_set=1` or `?working_set=0` on the page URL overrides it for that page load; the turn view ignores it. See [CLI: the working set](cli.md#the-working-set). |
2187
+ | `web.working_set` | `true` | yes | The stage view's working set: the files, memories and URLs a turn brought into the model's context, in a rail in the stage, a footprint line under each finished turn and a `set N` chip in place of the mem chip; `false` brings the mem chip back. `?working_set=1` or `?working_set=0` on the page URL overrides it for that page load. See [CLI: the working set](cli.md#the-working-set). |
2185
2188
  | `web.annotate_presets` | `Agreed\|Could you please elaborate?` | yes | Quick replies next to Annotate in `chi web`, `\|`-separated (a YAML list works too); `""` in the file or on the CLI leaves only Annotate (an empty env value means the default). See [CLI](cli.md#web-annotate-presets). |
2186
2189
  | `web.editor` | `vscode` | yes | What a file ref in `chi web` (a file tool row's title, a diff line) opens, for a viewer on this machine: a preset (`vscode`, `vscode-insiders`, `cursor`, `zed`) or a URL template with `{path}` and an optional `{line}`; `none` turns refs off. See [Opening files from chi web](#opening-files-from-chi-web). |
2187
2190
  | `web.start_dir` | the folder `chi web` runs in | | The folder `chi web` starts in (`chi web --start-dir DIR` for one run): its page (the printed link, a bare `/`, the LAN link and QR code, the Home Screen app) opens on that folder's project, outside a repo on every session, and a new session from the all view starts there; the header's project picker switches projects. `~` and a relative path (resolved from your home folder) work; one that isn't a folder stops `chi web` from starting. `chi web` never changes its own folder. See [CLI](cli.md). |