samagotchi 0.139.1 → 0.141.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +56 -1
- data/README.md +2 -1
- data/docs/architecture.md +8 -6
- data/docs/cli.md +3 -1
- data/docs/configuration.md +33 -1
- data/docs/context.md +249 -46
- data/docs/guardrails.md +11 -0
- data/docs/internals/engine.md +7 -1
- data/docs/internals/prompt-caching.md +10 -1
- data/docs/internals/remote-sessions.md +4 -1
- data/docs/plugins.md +75 -18
- data/docs/sessions.md +3 -2
- data/lib/samagotchi/bridge/turn_accumulator.rb +4 -1
- data/lib/samagotchi/bundles/claude-peer/manifest.yml +2 -2
- data/lib/samagotchi/bundles/claude-peer/scripts/chi-peer-SKILL.md +14 -0
- data/lib/samagotchi/bundles/codex-peer/manifest.yml +2 -2
- data/lib/samagotchi/bundles/codex-peer/scripts/chi-peer-SKILL.md +15 -1
- data/lib/samagotchi/bundles/dev/manifest.yml +2 -2
- data/lib/samagotchi/bundles/github-pr/manifest.yml +4 -4
- data/lib/samagotchi/bundles/github-pr/plugin.rb +72 -176
- data/lib/samagotchi/bundles/system/manifest.yml +1 -1
- data/lib/samagotchi/config.rb +8 -0
- data/lib/samagotchi/context_candidate_choice.rb +154 -0
- data/lib/samagotchi/context_candidates.rb +259 -0
- data/lib/samagotchi/context_candidates_log.rb +90 -0
- data/lib/samagotchi/context_command.rb +65 -17
- data/lib/samagotchi/context_judge.rb +194 -0
- data/lib/samagotchi/context_move.rb +31 -0
- data/lib/samagotchi/context_report_command.rb +161 -0
- data/lib/samagotchi/context_sources.rb +311 -29
- data/lib/samagotchi/engine.rb +189 -32
- data/lib/samagotchi/owner_prompt.rb +39 -0
- data/lib/samagotchi/plugin/api.rb +1 -0
- data/lib/samagotchi/plugin/attached_context.rb +105 -13
- data/lib/samagotchi/plugin/context.rb +12 -1
- data/lib/samagotchi/plugin/peer.rb +53 -0
- data/lib/samagotchi/plugin/sessions.rb +9 -2
- data/lib/samagotchi/prompt_warmup.rb +9 -1
- data/lib/samagotchi/send_command.rb +3 -1
- data/lib/samagotchi/session.rb +4 -0
- data/lib/samagotchi/session_access/contract.rb +4 -0
- data/lib/samagotchi/session_access/local.rb +34 -3
- data/lib/samagotchi/session_access/remote.rb +33 -8
- data/lib/samagotchi/session_access.rb +31 -6
- data/lib/samagotchi/session_commands.rb +28 -5
- data/lib/samagotchi/session_continue.rb +9 -2
- data/lib/samagotchi/side_judgments.rb +84 -0
- data/lib/samagotchi/terminal_ui.rb +15 -0
- data/lib/samagotchi/testing/boundary.rb +5 -1
- data/lib/samagotchi/testing/host.rb +4 -1
- data/lib/samagotchi/toolkit_report_command.rb +2 -1
- data/lib/samagotchi/toolkit_suggest.rb +3 -18
- data/lib/samagotchi/version.rb +1 -1
- data/lib/samagotchi/web/app.rb +24 -11
- data/lib/samagotchi/web/auto_update.rb +8 -1
- data/lib/samagotchi/web/public/app.js +8 -2
- data/lib/samagotchi/web/public/chains.js +10 -2
- data/lib/samagotchi/web/public/update_notice.js +21 -8
- data/lib/samagotchi/web/session_access_routes.rb +8 -3
- data/lib/samagotchi/web/session_create.rb +1 -0
- data/lib/samagotchi/web/session_hub.rb +5 -2
- data/lib/samagotchi/web/update_check.rb +14 -8
- data/lib/samagotchi/worker.rb +5 -0
- metadata +9 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4d6c521351f86a38243b9757eff32df1745e88d2be1158684ba029e85f16b9e1
|
|
4
|
+
data.tar.gz: 99c0f5f7b2356a58a36f4d38330a17d95decdc64446e26ee55f38d3b5794b3ba
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7b735c84997b1a4c035c6d3c0f7baf6035f4f29bd400e6bce116ecaf5fe06c0d2b304fe19a8447a523833bf71cfe9829193d6c8fcb136f42e7a5f900e4f7a30f
|
|
7
|
+
data.tar.gz: 0705cdf1abb1716a40f38c396b020442b44c2d985911f4d945362f0d2a83bde088c0699f660c8dce791edd666b83529e7d991e642703ceb023558caaa128c394
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,59 @@ 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.141.0] - 2026-10-31
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Movable context: a continue (`chi send --new --continues`, the web's Continue →) and a bundle's fork take the
|
|
15
|
+
session's attached context with them, with a note in the new session naming what moved and what stayed. A command
|
|
16
|
+
source moves, a pushed one stays; `chi context add --movable / --no-movable` (and `ctx.context.attach(movable:)`)
|
|
17
|
+
say it outright, and `chi context ls` marks one that stays. A push into a continued session is refused with the
|
|
18
|
+
next link's id. See docs/context.md (Movable context).
|
|
19
|
+
- A paired Claude Code or Codex session follows a continue: the new session asks it once to pair again with the new
|
|
20
|
+
id (a `moved` message to the inbox the old session had), and a reply pushed to the old id is refused with the new
|
|
21
|
+
one, so the peer pairs again then (claude-peer 0.4.6, codex-peer 0.3.5: install the chi-peer skill again with
|
|
22
|
+
`/claude install-skill` or `/codex install-skill`). Bundles get `ctx.continues` and `ctx.context.left_behind`. See
|
|
23
|
+
docs/context.md (Peers and a continue).
|
|
24
|
+
|
|
25
|
+
Update with `chi update` (claude-peer 0.4.6, codex-peer 0.3.5).
|
|
26
|
+
|
|
27
|
+
## [0.140.0] - 2026-10-31
|
|
28
|
+
|
|
29
|
+
### Added
|
|
30
|
+
|
|
31
|
+
- Candidates for attached context: a bundle proposes a source (`ctx.context.propose`, `candidates`, `withdraw`),
|
|
32
|
+
and chi attaches it when the session's owner mentions it; `chi context ls` and `/context` list them with their
|
|
33
|
+
state (proposed, attached, declined). See docs/context.md (Candidates).
|
|
34
|
+
- The candidate judge, audit only and opt-in (`context.candidates.mode: audit`; off by default): System 1 is asked
|
|
35
|
+
whether the session's work is about each proposed candidate, and the answers go to `context_candidates.jsonl`;
|
|
36
|
+
nothing is attached. `chi context report [--days N]` counts them against what you attached or declined. Jev
|
|
37
|
+
through OpenRouter works as the System 1 host. See docs/context.md (The judge).
|
|
38
|
+
- The candidate judge's on mode (`context.candidates.mode: on`): a candidate judged at `threshold` (0.8) or above
|
|
39
|
+
is attached quietly (its note comes before your next turn, never mid-turn; removing it declines it), one from
|
|
40
|
+
`offer_threshold` (0.6) gets a card once (Attach / Not here), lower ones stay proposed. `/context attach NAME` and
|
|
41
|
+
`/context decline NAME` choose a candidate yourself; `chi context report` counts the judge's attaches you removed
|
|
42
|
+
later. See docs/context.md (On mode).
|
|
43
|
+
|
|
44
|
+
### Changed
|
|
45
|
+
|
|
46
|
+
- github-pr no longer attaches the branch's PR by itself: mention it (#N, the branch, the URL), or set
|
|
47
|
+
`auto_attach: attach` for the old behaviour. It proposes the PR as a candidate when the worker starts (a delegate
|
|
48
|
+
child too), and a prompt of yours that names it attaches it before that turn runs, its note in that turn.
|
|
49
|
+
`auto_attach: offer` (the card with Attach and Not here, `/pr-attach`, `/pr-decline`) is gone and reads as
|
|
50
|
+
`propose`, as does an unknown value. (github-pr 0.6.0)
|
|
51
|
+
|
|
52
|
+
### Fixed
|
|
53
|
+
|
|
54
|
+
- chi web's update check no longer holds up the page, the API or the automatic install while it fetches from
|
|
55
|
+
RubyGems (~10 s): reading and saving the auto-update record take their own lock.
|
|
56
|
+
- Stopping chi web while the automatic update's preflight runs waits for it (up to 25 s) instead of abandoning it,
|
|
57
|
+
and a preflight that ends after the stop no longer restarts chi web.
|
|
58
|
+
- An automatic install with `update.restart: idle` no longer offers the "installed" toast's Restart buttons (a
|
|
59
|
+
failed run, `restart: never` or a manual install still do).
|
|
60
|
+
|
|
61
|
+
Update with `chi update` (the dev profile 0.7.4).
|
|
62
|
+
|
|
10
63
|
## [0.139.1] - 2026-10-31
|
|
11
64
|
|
|
12
65
|
### Fixed
|
|
@@ -5326,7 +5379,9 @@ and long-lived sessions.
|
|
|
5326
5379
|
- A macOS desktop helper (`chi desktop install`): a "Send to chi" Service and a
|
|
5327
5380
|
hotkey panel that send selected text or the clipboard to your sessions.
|
|
5328
5381
|
|
|
5329
|
-
[Unreleased]: https://github.com/dm1try/samagotchi/compare/v0.
|
|
5382
|
+
[Unreleased]: https://github.com/dm1try/samagotchi/compare/v0.141.0...HEAD
|
|
5383
|
+
[0.141.0]: https://github.com/dm1try/samagotchi/compare/v0.140.0...v0.141.0
|
|
5384
|
+
[0.140.0]: https://github.com/dm1try/samagotchi/compare/v0.139.1...v0.140.0
|
|
5330
5385
|
[0.139.1]: https://github.com/dm1try/samagotchi/compare/v0.139.0...v0.139.1
|
|
5331
5386
|
[0.139.0]: https://github.com/dm1try/samagotchi/compare/v0.138.0...v0.139.0
|
|
5332
5387
|
[0.138.0]: https://github.com/dm1try/samagotchi/compare/v0.137.0...v0.138.0
|
data/README.md
CHANGED
|
@@ -176,7 +176,8 @@ stopped on, which the agent answers with `chi answer`. See
|
|
|
176
176
|
`chi context` attaches outside text that keeps changing to a session: a
|
|
177
177
|
command chi runs every few minutes, text you push, or a URL. With the
|
|
178
178
|
`github-pr` bundle (in `dev`; needs `gh`) a session on a branch with an open
|
|
179
|
-
pull request gets it
|
|
179
|
+
pull request gets it proposed, and attached once you mention it (#N, the branch
|
|
180
|
+
or its URL). The agent gets a short note when it
|
|
180
181
|
changes (a summary of what changed, never the comments' words) and reads the
|
|
181
182
|
text with `context_read` when your request is about it; a review requesting
|
|
182
183
|
changes, red checks or a merge can start a turn in a live, idle session that
|
data/docs/architecture.md
CHANGED
|
@@ -606,8 +606,9 @@ reload in a toast, since an open tab keeps its old JS across a `chi web` upgrade
|
|
|
606
606
|
`installed`, the newest chi on this machine (`InstalledVersions`: the highest `samagotchi-<v>.gemspec`
|
|
607
607
|
in RubyGems' specification dirs, or a checkout's `version.rb` on disk; looked at again on each full
|
|
608
608
|
probe, every 10 s). A `chi` frame and the `GET /api/events` snapshot carry the full state
|
|
609
|
-
`{version, installed, available, update_blocked, auto}` (`auto`: `update.auto`, `off` or `install`, which the page's
|
|
610
|
-
"available" wording follows
|
|
609
|
+
`{version, installed, available, update_blocked, auto, restart}` (`auto`: `update.auto`, `off` or `install`, which the page's
|
|
610
|
+
"available" wording follows; `restart`: `update.restart`, with which the page offers no Restart toast for the
|
|
611
|
+
version an automatic install's frames name unless it is `never` or the run failed: that run restarts by itself); `/api/info` and the session-command wake response carry the same fields. `SessionHub#update_available` publishes the checker result under the hub's
|
|
611
612
|
Monitor, but fetching never holds it.
|
|
612
613
|
|
|
613
614
|
`Web::UpdateCheck` runs its own thread beside the hub. When `update.notify: on` (the default) or
|
|
@@ -663,7 +664,8 @@ the worker's own atomic refusal still applies), the left ones retried each step
|
|
|
663
664
|
turn running, `Server.restart_preflight` (the restart's command with `--version`, 20 s, killed on a timeout; it must
|
|
664
665
|
print a chi at least the release) and, if it passes, the record's `phase: web` is written **before**
|
|
665
666
|
`UpdateOps#restart_web`. A failed preflight, or a refused restart, publishes `restart_failed` and ends the run
|
|
666
|
-
(`failed`).
|
|
667
|
+
(`failed`). `AutoUpdate#stop` waits `STOP_WAIT` (25 s, longer than the preflight's timeout) for its thread, and a
|
|
668
|
+
preflight that ends after a stop leads to nothing (no `web`, no exec): the next start takes the run up again. The restarted chi web's AutoUpdate (first step after 5 s) finds `phase: web`, checks it runs the
|
|
667
669
|
release, counts the workers once more and publishes `updated`, then `done`. Results reach the phone as `chi_notice`
|
|
668
670
|
hub events (`SessionHub#publish_notice`), see [internals/web-push.md](internals/web-push.md).
|
|
669
671
|
|
|
@@ -717,8 +719,8 @@ model: [internals/remote-sessions.md](internals/remote-sessions.md).
|
|
|
717
719
|
| `POST /api/sessions/:id/wait/prepare` | owner | `question_id` (absent: the pending one; `null`: none), `turn`, `created`, `busy` (+ `queue`) | 200 `{session_id, cursor, baseline: {messages, question_id, last_turn}, own_turn, known_turn, running, live, settled, last_turn_id}` (`WaitStart`) | 409 `busy`, `waiting` (`SendCommand::Busy`'s words, and its fields: `question`, `parent_strategy`) |
|
|
718
720
|
| `POST /api/sessions/:id/wait` | owner | `cursor`, `baseline`, `turn`, `queued`, `ended_before`, `owner_grace`, `timeout` (capped at 30 s) | 200: `ReplyWait::Result`'s fields (`status`: `done`, `waiting_for_answer`, `no_reply`, `error`, `stopped`, `worker_gone`, or `timeout`: ask again; `text`, `file`, `question` as `PendingQuestion#to_file`, `outcome`, `limit`, `error_kind`, `retryable`, `cancel_reason`, `stopped_by`, `kept_steps`, `turn_id`, `origin`; never the session) and `parent_strategy` `{name, allowed, origin}` (`ParentReport.strategy_for`, this server's config.yml) | 400 `invalid_wait`; 503 `server_stopping` |
|
|
719
721
|
| `POST /api/sessions/:id/notes` | owner | `text`, `source` (default `cli`, never `broadcast`) | 200 `{status: queued \| waits, session_id, queued}` (`NoteDelivery`) | 409 `owned_by_tui` (`status: refused`); 400 `note_rejected`, `missing_fields`, `invalid_source` |
|
|
720
|
-
| `POST /api/sessions/:id/context` (more bodies) | owner | `{name, push: true, why, hint}` or `{name, cmd, every, why, hint}` beside the page's `{url, why, hint}`; `added_by` `cli`/`agent` (else `web`) | 201 `{status: attached, name}` | 400 `invalid_source`; 409 `exists` |
|
|
721
|
-
| `POST /api/sessions/:id/context/:name/push` | owner | `text`, `summary`, `wake`, `hint` (a source's JSON output, checked the same way) | 200 `{status: pushed, name, before, revision, changed}` | 404 `not_found`; 409 `not_push`; 400 `invalid_text` |
|
|
722
|
+
| `POST /api/sessions/:id/context` (more bodies) | owner | `{name, push: true, why, hint}` or `{name, cmd, every, why, hint}` beside the page's `{url, why, hint}`; `added_by` `cli`/`agent` (else `web`); `movable` (any body) | 201 `{status: attached, name, movable}` | 400 `invalid_source`; 409 `exists` |
|
|
723
|
+
| `POST /api/sessions/:id/context/:name/push` | owner | `text`, `summary`, `wake`, `hint` (a source's JSON output, checked the same way) | 200 `{status: pushed, name, before, revision, changed}` | 404 `not_found`; 409 `not_push`; 410 `context_continued` (`next_id`); 400 `invalid_text` |
|
|
722
724
|
| `DELETE /api/sessions/:id/context/:name?own=1` | owner | | 200 `{status: detached}`: the session's own only | 409 `project_source` (chi context rm's words); 404 |
|
|
723
725
|
| `POST /api/sessions/:id/stop` | owner | `wait?` (seconds, capped at `SessionManager::STOP_WAIT`, 10: `chi --remote NAME sessions stop` sends it) | 200 `{status: stopped, session_id, released}`: `released`, whether the worker let go within the wait (without one `STOP_WAIT_SECONDS`, 2 s: the page's Stop) | 409 `owned_by_tui` |
|
|
724
726
|
| `DELETE /api/sessions/:id?force=` | owner | `force=true` stops a live worker first (the page sends it) | as before | 409 `worker_running` without it |
|
|
@@ -881,7 +883,7 @@ A map of the parts the overview above doesn't name (paths under `lib/samagotchi/
|
|
|
881
883
|
| 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. |
|
|
882
884
|
| 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). |
|
|
883
885
|
| Idle work | `idle_scheduler.rb` (`IdleScheduler`), `idle_recap.rb` (`IdleRecap`), `idle_reminders.rb` | One poller for an idle session's recap and reminders. |
|
|
884
|
-
| Attached context | `context_sources.rb` (`ContextSources`), `context_poller.rb`, `context_absorber.rb`, `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)). |
|
|
886
|
+
| 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)). |
|
|
885
887
|
| 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)). |
|
|
886
888
|
| 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)). |
|
|
887
889
|
| 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)). |
|
data/docs/cli.md
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
22
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))
|
|
23
23
|
- `chi broadcast [-m TEXT] [--all] [--dry-run]`, `chi broadcast log [--last N] [--format json]`, `chi broadcast deliver BROADCAST_ID (ID|PREFIX)...` — share one piece of information (TEXT or stdin) with every session it may concern, as a context note from `broadcast` (see [Broadcast](broadcast.md))
|
|
24
24
|
- `chi context <add|push|ls|show|refresh|rm|mute|unmute> …` — attach live external text to sessions (a command chi runs every so often, or text pushed in); the model gets a short note when it changes and reads it with `context_read`; `chi context add <URL>` attaches a GitHub PR with the github-pr bundle (see [Attached context](context.md))
|
|
25
|
+
- `chi context report [--days N]` — the candidate judge's counts from `context_candidates.jsonl`: candidates proposed, mentioned, attached or declined by you; the judge's asks; what it would attach per threshold, and how that agrees with what you did (this machine only; see [The log and the report](context.md#the-log-and-the-report))
|
|
25
26
|
- `chi send [-m TEXT] [--image PATH]... [--cut | --queue] (ID|PREFIX)...` — send a message to sessions as if typed there: a turn starts (or a running one takes it at its next step; `--cut` asks it to cut long thinking for it; `--queue` runs it as a turn of its own after the running one, and `--queue --wait` waits for that turn's own answer); piped stdin goes above `-m` as quoted context, and `--image` attaches images (see [Sessions: Sending a message](sessions.md#sending-a-message)); `--new` starts a session with it instead (`--new --continues ID|last:ID` the next link of that session's chain, see [Session chains](sessions.md#session-chains)), and `--wait` prints the answer (`--wait ID` with no message waits for the next reply without sending — to an idle session whose last turn already ended, that ended turn's reply or end comes back; `--wait --turn T ID` with no message waits for exactly turn T, whether running, queued or last ended; `--format json` includes its `turn_id` when known, for waiting again after exit 3 or 4; exit 3 a question waits, its options on stderr; exit 4 `--timeout` passed with the turn still running; see [Starting a session](sessions.md#starting-a-session))
|
|
26
27
|
- `chi answer ID --question QID (--option N|LABEL)... [--text T] [--timeout S] [--format json]` (or `--dismiss`) — answer the question a session waits on (the one `chi send --wait` exited 3 with), then wait and print what comes next as `chi send --wait` does: the reply (0), the next question (3), still running after `--timeout` (4). `--option` is 1-based or the label, repeated on a multi-select question; `--text` is free text, or a Deny's reason; `--dismiss` leaves it unanswered and the model finishes its reply. A question no longer open (the web answered first) isn't answered again: it waits for that turn's reply. An option the question doesn't offer exits 2; a worker that is gone exits 1 (`send the task again: chi send --wait -m "…" ID`). What a parent may pick follows `guardrails.parent_answers`, or the session's own `parent_answers` when stricter (`soft`, the default: a deny, a plain answer, Continue and "Allow once"; `standard`: no allow; `hard`: no Continue either), never a wider scope or an allow on chi's own config; a refused pick exits 1 with what to answer instead (a convention, not a security boundary; see [Guardrails](guardrails.md#answers-from-a-parent-agent))
|
|
27
28
|
- `chi remote add NAME URL [--token-file F | --token-stdin]`, `chi remote ls`, `chi remote rm NAME` — the other machines whose chi web the session commands reach with `--remote NAME` (see [Remote sessions](#remote-sessions))
|
|
@@ -901,7 +902,8 @@ REPL alike:
|
|
|
901
902
|
`cutting in…`, then `steered`. A phone shows the short form (`↳ after this
|
|
902
903
|
thinking · 0:42`) with `cut in` and `queue` chips.
|
|
903
904
|
- Commands answer, wait or are refused, by what they do:
|
|
904
|
-
- At once, beside the turn: `/stats`, `/recap` (and `/recap on|off|default`), `/help`, `/context
|
|
905
|
+
- At once, beside the turn: `/stats`, `/recap` (and `/recap on|off|default`), `/help`, `/context` (and
|
|
906
|
+
`/context attach|decline NAME`: a candidate's note still waits for the next turn), a
|
|
905
907
|
plugin's anytime command (`/btw`), and the commands that only show
|
|
906
908
|
something: `/models` (with a filter too), and `/model`, `/llm-context`,
|
|
907
909
|
`/thinking`, `/reasoning-history` and `/guardrails` alone.
|
data/docs/configuration.md
CHANGED
|
@@ -1758,6 +1758,33 @@ its own). The first target is a long session such as a day-long coordinator, whe
|
|
|
1758
1758
|
turn that runs a layer or whose session set its strategy) and the web's chip. A woken worker's status line counts
|
|
1759
1759
|
its saved context against the session's budget.
|
|
1760
1760
|
|
|
1761
|
+
## The candidate judge
|
|
1762
|
+
|
|
1763
|
+
`context.candidates.mode: audit` asks System 1 whether a session's work is about each candidate a bundle proposed
|
|
1764
|
+
(see [The judge](context.md#the-judge)); `on` also acts on the answer: attaches at `threshold`, a card from
|
|
1765
|
+
`offer_threshold` ([On mode](context.md#on-mode)). It uses `guardrails.system_one.host` and `.model`, but its own mode: System
|
|
1766
|
+
1's `mode` (approvals) can stay `off`. Jev, the hosted judgment model, is served through OpenRouter
|
|
1767
|
+
(`/api/v1/systemone`), so OpenRouter can be the System 1 host:
|
|
1768
|
+
|
|
1769
|
+
```yaml
|
|
1770
|
+
hosts:
|
|
1771
|
+
openrouter:
|
|
1772
|
+
url: https://openrouter.ai/api/v1
|
|
1773
|
+
api: openai
|
|
1774
|
+
api_key_env: OPENROUTER_API_KEY
|
|
1775
|
+
guardrails:
|
|
1776
|
+
system_one:
|
|
1777
|
+
host: openrouter
|
|
1778
|
+
model: typesafe/jev-1.14
|
|
1779
|
+
context:
|
|
1780
|
+
candidates:
|
|
1781
|
+
mode: audit
|
|
1782
|
+
```
|
|
1783
|
+
|
|
1784
|
+
A remote host is asked beside the turn. A System 1 host that is the model's own local server is asked after the
|
|
1785
|
+
turn's last request, and the turn-end warm-up follows them, re-warming the prefix they evicted (see
|
|
1786
|
+
[prompt caching](internals/prompt-caching.md)).
|
|
1787
|
+
|
|
1761
1788
|
## Opening files from chi web
|
|
1762
1789
|
|
|
1763
1790
|
In `chi web`, a file tool's row (read, edit, write) and the lines of its diff are refs to that file. They look like
|
|
@@ -2082,7 +2109,8 @@ Both are read when chi web starts (restart it to apply a change). What it does,
|
|
|
2082
2109
|
the command to run). `chi update` also merges the shipped bundles that live sessions read, hence "no turn anywhere".
|
|
2083
2110
|
2. **Installs** exactly the release the notice named, as the **Update** button does (the system bundle and shipped
|
|
2084
2111
|
bundles are merged three ways; files you edited are kept and counted in the push). The page's sticky toast says
|
|
2085
|
-
"Automatic chi update in progress" and its sheet shows the rows
|
|
2112
|
+
"Automatic chi update in progress" and its sheet shows the rows; with `update.restart: idle` no "installed"
|
|
2113
|
+
toast with **Restart** buttons follows (the run restarts by itself). A failed install is tried **once per version**:
|
|
2086
2114
|
it pushes the failed row's reason and stays quiet until a newer release (or you, with the button) tries again.
|
|
2087
2115
|
3. **Restarts** (`update.restart: idle`). Stale workers first, only those whose session is idle and untouched for
|
|
2088
2116
|
10 minutes (so nobody who is about to type loses their worker), and each worker still refuses by itself when
|
|
@@ -2190,6 +2218,10 @@ column says so, a `--kebab-name` flag. The maps (`hosts:`, `models:`,
|
|
|
2190
2218
|
| `context.every_seconds` | `300` | | How often an attached context source's command runs when it has no `--every` (seconds, at least 30). See [Attached context](context.md). |
|
|
2191
2219
|
| `context.wake` | `true` | yes | A source whose update says `wake: true` may start a turn in a live, idle session (one per source per 10 minutes, a peer source up to `context.peer_turns` in a row, within `session.max_wakes`); so may a session's pushed source's first push. `false`: updates wait as notes for the next turn. See [Waking](context.md#waking). |
|
|
2192
2220
|
| `context.peer_turns` | `3` | yes | Wake turns in a row a peer agent's answers may start (a peer bundle's outbox source, such as `codex-outbox`), with no message typed in the web or a TUI in between (`chi send` doesn't count); within `session.max_wakes`. Then answers wait as notes, and the UIs hear it once. An answer whose summary ends its verdicts with `VERDICT OK` wakes once to close the round, counted toward `session.max_wakes` only. `0`: a peer source wakes like any other. See [Waking](context.md#waking). |
|
|
2221
|
+
| `context.candidates.mode` | `off` | | The candidate judge: `off` (the default: no conversation text goes to a System 1 host), `audit` (asks System 1 whether the session's work is about each proposed candidate and logs it in `context_candidates.jsonl`; attaches nothing), `on` (the same asks, acted on: attached at `threshold`, a card from `offer_threshold`; see [On mode](context.md#on-mode)). Its host and model are `guardrails.system_one.host` / `.model`. config.yml only. See [The judge](context.md#the-judge). |
|
|
2222
|
+
| `context.candidates.threshold` | `0.8` | | The probability at which the judge attaches a candidate in on mode (a judged line's `would: attach`). config.yml only. |
|
|
2223
|
+
| `context.candidates.offer_threshold` | `0.6` | | The probability from which on mode shows the candidate's card, once (`would: offer`, below `threshold`). config.yml only. |
|
|
2224
|
+
| `context.candidates.reask_after_turns` | `3` | | Owner prompts after a judged ask before the judge's one re-ask of that candidate. config.yml only. |
|
|
2193
2225
|
| `toolkit.default` | `full` | | The toolkit a new session is stored on: the tools its prompts declare (`full`, `lean`, `child`, one of `toolkit.kits` or a bundle's). `chi --toolkit` picks one per session. See "Toolkits". |
|
|
2194
2226
|
| `toolkit.child` | `full` | | A delegate child's toolkit, unless its `delegate` call names one (`toolkit:`). See "Toolkits". |
|
|
2195
2227
|
| `toolkit.suggest.mode` | `off` | | `audit` asks System 1 for a toolkit suggestion without changing the session; `on` waits for it (up to `guardrails.system_one.timeout_ms`) on an eligible turn and starts the session on a confidently suggested kit (Toolkits, On mode). The System 1 host, model and timeout come from `guardrails.system_one.*`. config.yml only. |
|
data/docs/context.md
CHANGED
|
@@ -89,8 +89,8 @@ web) without touching the other sessions.
|
|
|
89
89
|
## The commands
|
|
90
90
|
|
|
91
91
|
```
|
|
92
|
-
chi context add NAME (--cmd CMD | --push) [--every SECONDS] [--why TEXT] [--hint TEXT] TARGET
|
|
93
|
-
chi context add URL [--why TEXT] [--hint TEXT] TARGET a URL an installed bundle's provider knows
|
|
92
|
+
chi context add NAME (--cmd CMD | --push) [--every SECONDS] [--why TEXT] [--hint TEXT] [--[no-]movable] TARGET
|
|
93
|
+
chi context add URL [--why TEXT] [--hint TEXT] [--[no-]movable] TARGET a URL an installed bundle's provider knows
|
|
94
94
|
chi context push NAME [-m TEXT] [TARGET] new text for a --push source (stdin without -m)
|
|
95
95
|
chi context ls [TARGET] [--format json]
|
|
96
96
|
chi context show NAME [--json] [TARGET]
|
|
@@ -105,7 +105,9 @@ and `-`, up to 40 characters, starting with a letter or digit
|
|
|
105
105
|
(`subscriptions` is taken).
|
|
106
106
|
|
|
107
107
|
In a session, `/context` lists what is attached (as `context_read` does
|
|
108
|
-
with no name).
|
|
108
|
+
with no name), then the session's [candidates](#candidates). `chi context ls`
|
|
109
|
+
lists them too (`--format json`: rows with `"candidate": true` and their
|
|
110
|
+
`status`), from another machine's chi web as well.
|
|
109
111
|
|
|
110
112
|
## Recipes
|
|
111
113
|
|
|
@@ -311,6 +313,219 @@ lower.) Every other source keeps the line above. `context.peer_turns: 0` turns
|
|
|
311
313
|
the loop off: a peer source then wakes like any other. `context_read` names a
|
|
312
314
|
peer source in its header (`Peer: your peer agent Codex's answers …`).
|
|
313
315
|
|
|
316
|
+
## Movable context
|
|
317
|
+
|
|
318
|
+
A session's own sources go with it to the next session of its work: the next
|
|
319
|
+
link of a [chain](sessions.md#session-chains) (`chi send --new --continues`,
|
|
320
|
+
the web's Continue →) and a bundle's fork
|
|
321
|
+
([`ctx.sessions.fork`](plugins.md#other-sessions-ctxsessions)). A topic switch goes
|
|
322
|
+
to a fresh session with its own context, never through a continue.
|
|
323
|
+
|
|
324
|
+
Each source says whether it moves:
|
|
325
|
+
|
|
326
|
+
- **A command source moves** (`--cmd`, a URL's source): chi runs its command
|
|
327
|
+
itself, in the new session too.
|
|
328
|
+
- **A pushed source stays** (`--push`): its writer (`pbpaste | chi context
|
|
329
|
+
push notes <id>`, a peer agent) holds the old session's id.
|
|
330
|
+
- `chi context add … --movable` / `--no-movable` (either kind) says it
|
|
331
|
+
outright: `--movable` on a pushed source means its writer finds the new id
|
|
332
|
+
itself. A bundle passes `movable:` to `ctx.context.attach`.
|
|
333
|
+
|
|
334
|
+
What moves is copied before the new session's worker starts: the source, its
|
|
335
|
+
last text (so its first note quotes it without waiting for a fetch, and its
|
|
336
|
+
interval holds), and the session's choices: every removed (declined) and
|
|
337
|
+
muted marker. Candidates don't move. The new link gets the usual *Attached*
|
|
338
|
+
note for each source; a fork starts where its seed's notes left off, so a
|
|
339
|
+
source that changed since gets an *Updated* note. A second chi note, after
|
|
340
|
+
the chain's, names what moved and what stayed:
|
|
341
|
+
|
|
342
|
+
> Context moved with this session: pr-412, ci. Left with 3f2a9c1e: notes (pushed).
|
|
343
|
+
|
|
344
|
+
`chi send --new --continues` and the web's Continue toast say the same in a
|
|
345
|
+
few words, and `chi context ls` marks a session's source that stays
|
|
346
|
+
(`· stays`; `--format json` has the derived `movable`). Project sources are
|
|
347
|
+
shared already, and a review fork (`chi review --from`) and a delegate take none.
|
|
348
|
+
|
|
349
|
+
A push into a continued session is refused, nothing written, with the next
|
|
350
|
+
link's id (`chi context push` exits 1; chi web answers 410
|
|
351
|
+
`context_continued`):
|
|
352
|
+
|
|
353
|
+
```
|
|
354
|
+
chi context push: 3f2a9c1e was continued as 7b1d…: notes stays with the session it was attached to; attach it to 7b1d… (or pair again with 7b1d…) and push there
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
An archived session that nobody continued takes pushes as before.
|
|
358
|
+
|
|
359
|
+
### Peers and a continue
|
|
360
|
+
|
|
361
|
+
A peer's pairing ([claude-peer, codex-peer](plugins.md#the-claude-peer-bundle):
|
|
362
|
+
`<peer>-inbox` and `<peer>-outbox`, both pushed) stays with the old session,
|
|
363
|
+
and the peer pairs again with the new one. The continue keeps what stayed in
|
|
364
|
+
the new session (`left.json` beside its sources: each name, its last pushed
|
|
365
|
+
hint, the old id; `ctx.context.left_behind`), and the new session's worker
|
|
366
|
+
posts the peer one `moved` message to the inbox left behind, once:
|
|
367
|
+
`chi <old> · moved · continued as <new id>`. The peer's chi-peer skill pairs
|
|
368
|
+
again with the new id, the same way it paired before. Without an inbox (an
|
|
369
|
+
outbox-only pairing through a remote), or when the message didn't arrive, the
|
|
370
|
+
peer's next push to the old id is refused with the new id, and the skill pairs
|
|
371
|
+
again and pushes there. The second note says which, not whether it worked:
|
|
372
|
+
|
|
373
|
+
> Left with 3f2a9c1e: claude-inbox, claude-outbox (Claude's pairing: chi asks Claude to pair again with this session).
|
|
374
|
+
|
|
375
|
+
or, for an outbox alone, `codex-outbox (Codex pairs again when it next
|
|
376
|
+
answers)`. A fork takes no pairing and posts nothing.
|
|
377
|
+
|
|
378
|
+
## Candidates
|
|
379
|
+
|
|
380
|
+
A bundle can **propose** a source instead of attaching it
|
|
381
|
+
([`ctx.context.propose`](plugins.md#attached-context-ctxcontext)): a
|
|
382
|
+
candidate, with a title and the words that name it (its *mentions*). Nothing
|
|
383
|
+
reaches the agent until you name it in one of your own prompts; then chi
|
|
384
|
+
attaches it before that turn runs, gives it one first fetch (up to 10
|
|
385
|
+
seconds), and the turn starts with its attached note, whose why names what
|
|
386
|
+
you wrote ("Why: you mentioned #412"). A source whose first text takes longer
|
|
387
|
+
gets its note with a later turn.
|
|
388
|
+
|
|
389
|
+
How a mention counts:
|
|
390
|
+
|
|
391
|
+
- whole words, any case;
|
|
392
|
+
- `#N` only for N of 10 or more, or right after "PR" or "pull" ("PR #4");
|
|
393
|
+
- a branch name only when it is at least 6 characters and holds a `/`, `-`
|
|
394
|
+
or `_` (`feat/login`, not `web`);
|
|
395
|
+
- a URL exactly as proposed (`…/pull/42/files` is another URL);
|
|
396
|
+
- nothing inside a fenced code block: a pasted log's `#412` isn't you asking.
|
|
397
|
+
|
|
398
|
+
Only the session's owner counts: a participant's message, a steer, a note or
|
|
399
|
+
a reminder never attaches anything, and a review session gets no candidates.
|
|
400
|
+
A bundle usually proposes from an init task that finishes while your first
|
|
401
|
+
turn runs; when it does, the prompts you already wrote count too, and a hit
|
|
402
|
+
is attached at once (its note comes with your next turn).
|
|
403
|
+
|
|
404
|
+
A candidate's state is never stored: it is *attached* while a source of its
|
|
405
|
+
name (or its URL) is, *declined* once you removed that source from the
|
|
406
|
+
session or answered its card "Not here" (it isn't proposed, judged or
|
|
407
|
+
attached again), else *proposed*. `chi context ls` and `/context` list them
|
|
408
|
+
under the sources:
|
|
409
|
+
|
|
410
|
+
```
|
|
411
|
+
$ chi context ls
|
|
412
|
+
no attached context
|
|
413
|
+
candidates (attached when the session's owner mentions one):
|
|
414
|
+
pr-412 proposed #412 Fix the login redirect
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
You can also choose yourself: `/context attach NAME` attaches a proposed
|
|
418
|
+
candidate (its why: "you attached it"), `/context decline NAME` declines it.
|
|
419
|
+
Both are the session owner's (a participant can't send a `/` line, and a
|
|
420
|
+
review session refuses them); an unknown name, or one attached or declined
|
|
421
|
+
already, is an error that says so. They are what the judge's card's buttons
|
|
422
|
+
run (see [On mode](#on-mode)).
|
|
423
|
+
|
|
424
|
+
Forks and continues take no candidates: the bundle proposes again in the
|
|
425
|
+
new session (see [Movable context](#movable-context) for the sources).
|
|
426
|
+
|
|
427
|
+
### The judge
|
|
428
|
+
|
|
429
|
+
A mention is the only thing that attaches a candidate by itself. With
|
|
430
|
+
`context.candidates.mode: audit` chi also asks [System 1](guardrails.md#system-1-experimental)
|
|
431
|
+
about each proposed candidate — "Is this session's work about the
|
|
432
|
+
candidate?" — and logs the answer, so you can see how it would do before
|
|
433
|
+
anything depends on it; `audit` attaches nothing. With `on` the answer acts
|
|
434
|
+
([On mode](#on-mode)). The default is `off`: no conversation text goes to a System 1 host unless you
|
|
435
|
+
turn this on, whatever `guardrails.system_one` says. The host and model are
|
|
436
|
+
`guardrails.system_one.host` / `.model` (Jev through OpenRouter: see
|
|
437
|
+
[The candidate judge](configuration.md#the-candidate-judge)).
|
|
438
|
+
|
|
439
|
+
```yaml
|
|
440
|
+
context:
|
|
441
|
+
candidates:
|
|
442
|
+
mode: audit # off (default) | audit | on
|
|
443
|
+
threshold: 0.8 # on: attach at or above this
|
|
444
|
+
offer_threshold: 0.6 # on: a card from this, below threshold
|
|
445
|
+
reask_after_turns: 3 # owner prompts before the one re-ask
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
What it asks, and when:
|
|
449
|
+
|
|
450
|
+
- **One ask per candidate**, at the start of each of your own turns (never a
|
|
451
|
+
participant's, never in a review session or on a Continue), after the
|
|
452
|
+
toolkit suggestion. A candidate proposed while your turn runs (github-pr's
|
|
453
|
+
usual case) is asked about right then, on your prompts so far.
|
|
454
|
+
- **What it sees:** the candidate's title (and description, when the bundle
|
|
455
|
+
gave one) and your own prompts: the first one with a task in it and the
|
|
456
|
+
latest, each cut at 1500 characters. Never the branch, the checkout or the
|
|
457
|
+
source's "why". For a delegate child, also the titles of what its parent
|
|
458
|
+
session has attached, and the question says the first message is the
|
|
459
|
+
parent's request.
|
|
460
|
+
- **Has a task been stated yet?** The same ask has a second question; below
|
|
461
|
+
0.5 the candidate stays unjudged and is asked again at your next prompt
|
|
462
|
+
(a first "hi" doesn't count against it).
|
|
463
|
+
- **After a judged ask:** one re-ask once `reask_after_turns` more prompts of
|
|
464
|
+
yours came, with the conversation grown; then it is done.
|
|
465
|
+
- **Where it runs:** on a remote System 1 host (Jev) beside your turn; on the
|
|
466
|
+
model's own local server (System 1 on the same Splash) after your turn
|
|
467
|
+
ends, so it never competes with the turn's prefill; the turn-end warm-up
|
|
468
|
+
waits for those asks and restores the cached prompt they pushed out. One
|
|
469
|
+
session's asks run one batch at a time.
|
|
470
|
+
|
|
471
|
+
### On mode
|
|
472
|
+
|
|
473
|
+
With `context.candidates.mode: on` the judge's answer acts:
|
|
474
|
+
|
|
475
|
+
- **p ≥ `threshold` (0.8): attached quietly.** The source goes into the
|
|
476
|
+
session's own folder, its why "it looks related to your task" (the agent
|
|
477
|
+
never sees a probability), and it shows as a chip like any attached source.
|
|
478
|
+
Its note reaches the agent only at the next between-turn delivery: an
|
|
479
|
+
answer that comes while your turn runs waits for that turn to end, so the
|
|
480
|
+
running turn's history, cached prompt and reasoning stay as they were.
|
|
481
|
+
Removing it — the chip's ×, or `chi context rm NAME` — declines it: it is
|
|
482
|
+
never proposed or judged again in that session.
|
|
483
|
+
- **`offer_threshold` (0.6) ≤ p < `threshold`: one card**, from `context`,
|
|
484
|
+
with the candidate's title and two buttons: **Attach** (`/context attach
|
|
485
|
+
NAME`) and **Not here** (`/context decline NAME`). The card shows once per
|
|
486
|
+
candidate, also across a worker restart (a `carded` line in the log
|
|
487
|
+
remembers it), and never inside a running turn: an answer that comes
|
|
488
|
+
mid-turn shows its card when the turn ends. In the terminal the card lists
|
|
489
|
+
the two commands to type. Answering it replaces the card with what
|
|
490
|
+
happened; a later re-ask at or above the threshold attaches it and closes
|
|
491
|
+
the card.
|
|
492
|
+
- **Below `offer_threshold`: nothing.** The candidate stays proposed (a
|
|
493
|
+
mention still attaches it).
|
|
494
|
+
|
|
495
|
+
### The log and the report
|
|
496
|
+
|
|
497
|
+
Everything about candidates goes to `context_candidates.jsonl` in the state
|
|
498
|
+
folder (0600, local; written in every mode, `off` too, since nothing in it
|
|
499
|
+
leaves the machine): `proposed`, `mentioned`, `judged` (the probability `p`,
|
|
500
|
+
the task-stated probability `task_p`, `stated`, `would`: attach / offer /
|
|
501
|
+
none at the thresholds then, with your prompts cut to 200 characters),
|
|
502
|
+
`judge_attached` (on mode's attach, with `p`), `carded` (on mode's card, with
|
|
503
|
+
`p`), `attached` / `declined` with `by: "command"` (`/context attach|decline`,
|
|
504
|
+
the card's buttons), `attached` / `declined` / `detached` with `by: "user"`
|
|
505
|
+
(what you did otherwise, seen at your next turn's start; removing a source
|
|
506
|
+
declines it) and `withdrawn`.
|
|
507
|
+
|
|
508
|
+
`chi context report [--days N]` counts it, with no prompts in the output
|
|
509
|
+
(this machine only):
|
|
510
|
+
|
|
511
|
+
```
|
|
512
|
+
$ chi context report
|
|
513
|
+
chi context report: the last 14 days, 12 sessions (mode audit)
|
|
514
|
+
candidates: proposed 14 · mentioned 3 · attached by you 1 · declined 2 · detached 0 · withdrawn 0
|
|
515
|
+
on mode: judge attached 0 · you removed 0 of them later · carded 0 · /context attach 0 · /context decline 0 (the card's buttons)
|
|
516
|
+
judge: 19 asks · judged 15 · no task yet 4 · 11 candidates judged
|
|
517
|
+
would attach (each candidate's latest judged ask):
|
|
518
|
+
≥ 0.5 5
|
|
519
|
+
≥ 0.6 4 offer_threshold
|
|
520
|
+
≥ 0.7 3
|
|
521
|
+
≥ 0.8 3 threshold
|
|
522
|
+
≥ 0.9 1
|
|
523
|
+
against your own choice (6 judged candidates you attached, mentioned or declined), at 0.8: agree 5 · would attach what you declined 0 · would miss what you attached 1
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
The on mode line's "you removed N of them later" is the judge's false
|
|
527
|
+
positives: sources it attached that you then took off.
|
|
528
|
+
|
|
314
529
|
## GitHub PRs: the github-pr bundle
|
|
315
530
|
|
|
316
531
|
```sh
|
|
@@ -320,13 +535,19 @@ chi bundle install github-pr # or the dev profile: chi bundle install dev
|
|
|
320
535
|
It needs [`gh`](https://cli.github.com), logged in (`gh auth login`).
|
|
321
536
|
|
|
322
537
|
- When a session's worker starts on a branch with an open pull request, the
|
|
323
|
-
bundle
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
538
|
+
bundle proposes it as a [candidate](#candidates) `pr-<number>`, titled
|
|
539
|
+
"#42 <the PR's title>": nothing reaches the agent until you mention it
|
|
540
|
+
in a prompt (`#42`, the branch's name, or the PR's URL). Then it is
|
|
541
|
+
attached in that same turn ("Why: you mentioned #42"). Not in a `chi
|
|
542
|
+
scratch` session or a review session, and quietly nothing without `gh`, a
|
|
543
|
+
login, a repository or an open PR. A delegate child gets the proposal too
|
|
544
|
+
(its task may name the PR). At a turn's start more than 5 minutes after
|
|
545
|
+
its last look, the bundle looks again, beside the turn (a branch switched
|
|
546
|
+
mid-session). Once you remove an attached PR (`chi context rm`, the chip's
|
|
547
|
+
detach) it stays removed: it isn't proposed or attached again; `chi context
|
|
548
|
+
add <PR URL>` brings it back.
|
|
328
549
|
- `chi context add <PR URL>` attaches any PR.
|
|
329
|
-
- `auto_attach` (below) can make it
|
|
550
|
+
- `auto_attach` (below) can make it attach the PR at once, or do nothing.
|
|
330
551
|
- The text: title, state, branch, description, reviews, comments (oldest
|
|
331
552
|
first) and checks, every 5 minutes.
|
|
332
553
|
- The summary says what changed in **counts, authors and states only**
|
|
@@ -336,50 +557,28 @@ It needs [`gh`](https://cli.github.com), logged in (`gh auth login`).
|
|
|
336
557
|
- It wakes for a review requesting changes, checks turning red, and the PR
|
|
337
558
|
merged or closed. Comments alone never wake.
|
|
338
559
|
|
|
339
|
-
###
|
|
560
|
+
### Propose, attach or off
|
|
340
561
|
|
|
341
562
|
```yaml
|
|
342
563
|
bundles:
|
|
343
564
|
github-pr:
|
|
344
|
-
auto_attach:
|
|
565
|
+
auto_attach: propose # propose (the default) | attach | off
|
|
345
566
|
```
|
|
346
567
|
|
|
347
|
-
- `
|
|
348
|
-
above.
|
|
349
|
-
- `
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
`→ /pr-decline 42`, to type. Attach attaches it as auto-attach would
|
|
354
|
-
(even after Not here: a click is your choice); Not here marks it removed
|
|
355
|
-
from the session, so `attach` mode won't attach it there either. Either
|
|
356
|
-
turns the card into a one-line notice. Not here on a PR that is attached
|
|
357
|
-
already changes nothing and says so: `chi context rm pr-42` removes it. A worker restart (idle exit,
|
|
358
|
-
resume) doesn't ask again; once the card has scrolled out of the last 20,
|
|
359
|
-
`/pr-attach 42` or `chi context add <PR URL>` still attaches it. `/pr-attach` and
|
|
360
|
-
`/pr-decline` act only on a PR offered in that session.
|
|
361
|
-
- `off`: nothing is attached or offered. `chi context add <PR URL>` and line
|
|
362
|
-
links work as before.
|
|
568
|
+
- `propose`: the branch's open PR is a candidate, attached when you mention
|
|
569
|
+
it, as above.
|
|
570
|
+
- `attach`: it is attached when the worker starts, mention or not (the
|
|
571
|
+
default before candidates; not in a delegate child).
|
|
572
|
+
- `off`: nothing is proposed or attached. `chi context add <PR URL>` and
|
|
573
|
+
line links work as before.
|
|
363
574
|
|
|
364
575
|
`true` and `false` (YAML reads a bare `on`/`off` as those) mean `attach` and
|
|
365
|
-
`off
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
attached gets no line links (unless your message names its URL).
|
|
372
|
-
|
|
373
|
-
In `offer` mode the bundle keeps a local log,
|
|
374
|
-
`$XDG_STATE_HOME/samagotchi/plugins/github-pr/offers.ndjson`, to find out
|
|
375
|
-
later when an offer is wanted: one JSON line per event, `offered` (session,
|
|
376
|
-
project root, working directory, branch, PR URL, main checkout or worktree,
|
|
377
|
-
model), `attached` and `declined` (with the seconds since the offer), and
|
|
378
|
-
`first_prompt` (the first 160 characters of every session's first message,
|
|
379
|
-
offered or not; a fork's first after the conversation it started from, once;
|
|
380
|
-
not scratch sessions or delegate children). Over 1 MiB it is
|
|
381
|
-
renamed to `offers.ndjson.1` (one old file is kept). Only you can read it
|
|
382
|
-
(0600), and nothing leaves your machine.
|
|
576
|
+
`off`. `offer`, which once posted a card with Attach and Not here, now reads
|
|
577
|
+
as `propose`, and so does an unknown value, each with a warning in the log.
|
|
578
|
+
The setting is read when the bundle looks.
|
|
579
|
+
|
|
580
|
+
A proposed PR that isn't attached gets no line links (unless your message
|
|
581
|
+
names its URL).
|
|
383
582
|
|
|
384
583
|
### Line links
|
|
385
584
|
|
|
@@ -468,8 +667,12 @@ sessions/<id>/<name>.json, …snapshot.json a session's own
|
|
|
468
667
|
sessions/<id>/subscriptions.json what the session has seen and read (its worker writes it)
|
|
469
668
|
sessions/<id>/muted/<name> a project source this session mutes
|
|
470
669
|
sessions/<id>/declined/<name> a source you removed (its hint inside): auto-attach skips it
|
|
471
|
-
sessions/<id>/
|
|
670
|
+
sessions/<id>/candidates/<name>.json a source a plugin proposed here ({url or cmd, title, describe, mentions, proposed_by, at}; no status)
|
|
472
671
|
```
|
|
473
672
|
|
|
673
|
+
The candidates' log, `context_candidates.jsonl`, sits one level up, beside
|
|
674
|
+
the sessions folder (`$XDG_STATE_HOME/samagotchi/`; see
|
|
675
|
+
[The log and the report](#the-log-and-the-report)).
|
|
676
|
+
|
|
474
677
|
Deleting a session deletes its folder. A source and its snapshot go with
|
|
475
678
|
`chi context rm`; its `.lock` stays (a fetch may still hold it).
|
data/docs/guardrails.md
CHANGED
|
@@ -1087,6 +1087,17 @@ contention guard. The session's own checks come first; the kits and the
|
|
|
1087
1087
|
suggestion log are read only for a session that can be asked, the log only
|
|
1088
1088
|
after an earlier `undecided`.
|
|
1089
1089
|
|
|
1090
|
+
The candidate judge is a third use (`context.candidates.mode`, off by
|
|
1091
|
+
default; [context.md, The judge](context.md#the-judge)): two `noul`
|
|
1092
|
+
questions per proposed candidate, "Is this session's work about the
|
|
1093
|
+
candidate?" and "Has the user stated a task yet?", on the same host and
|
|
1094
|
+
model, gated by its own mode alone. It logs to `context_candidates.jsonl`
|
|
1095
|
+
with the `context` tag; in on mode `ContextCandidateChoice` acts on the
|
|
1096
|
+
answer (attach, card, or nothing). Unlike the toolkit's audit it doesn't skip a shared
|
|
1097
|
+
local host: it asks after the turn ends there. Both side judgments run
|
|
1098
|
+
through `SideJudgments` (one ask in flight per kind, a failure is one warn,
|
|
1099
|
+
shutdown waits up to a second).
|
|
1100
|
+
|
|
1090
1101
|
### What the audit writes
|
|
1091
1102
|
|
|
1092
1103
|
With a client, `GuardrailWiring#request_approval` asks System 1 one `noul`
|
data/docs/internals/engine.md
CHANGED
|
@@ -38,7 +38,7 @@ Engine#run_turn(session, prompt, on_event:, max_iterations:, cancel_controller:,
|
|
|
38
38
|
│ # resumed: true (only on a step-limit Continue: resumed: given),
|
|
39
39
|
│ # images (only when there are any), cut_after (the model's cut wait, s)}
|
|
40
40
|
│ # start_toolkit_suggestion: ToolkitSuggest's ask on its own thread from a copied snapshot (audit and on
|
|
41
|
-
│ # mode: one eligibility
|
|
41
|
+
│ # mode: one eligibility; SideJudgments' :toolkit kind: one in flight, warn-not-raise). Audit never blocks the turn or changes the session; on mode
|
|
42
42
|
│ # returns a ToolkitSuggest::Pending the turn joins below. See configuration.md (Toolkits) and
|
|
43
43
|
│ # guardrails.md (System 1).
|
|
44
44
|
│ # refresh_profile! (may ask the server's /props once)
|
|
@@ -50,6 +50,12 @@ Engine#run_turn(session, prompt, on_event:, max_iterations:, cancel_controller:,
|
|
|
50
50
|
│ # start, or a Stop (which wins over an answer already in, and cuts the ask's request through
|
|
51
51
|
│ # Pending#cancel_controller; a Stop after a timeout doesn't), and on a candidate picked ≥ threshold
|
|
52
52
|
│ # ToolkitBinding#suggest sets the session's toolkit, origin suggested, saved, with the notice;
|
|
53
|
+
│ # then start_context_judge (owner turns only: ContextCandidatesLog#look, and unless
|
|
54
|
+
│ # context.candidates.mode is off, ContextJudge's asks on SideJudgments' :context kind, each answer to
|
|
55
|
+
│ # ContextCandidateChoice#after_judged (on mode: attach to the session's folder, or a card held while a
|
|
56
|
+
│ # turn runs and shown from run_turn's ensure, show_context_cards_after_turn); on a shared
|
|
57
|
+
│ # local System 1 host they wait for the turn's end: started before warm_up_next_turn, whose warm-up
|
|
58
|
+
│ # waits for them, or from run_turn's ensure; docs/context.md, The judge);
|
|
53
59
|
│ # then the session's toolkit (apply_toolkit!: Registry#toolkit, ToolIndex#refresh! for find_tools'
|
|
54
60
|
│ # chi line, a prompt rebuild when it changed). A Stop during the probes or the waits returns false
|
|
55
61
|
│ # (the ask's line says canceled; an ensure marks one the turn never settled failed).
|